From a641ae497d209c56aacc2e6ab19fdedf653a544a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Galder=20Zamarren=CC=83o?= Date: Mon, 19 Oct 2020 10:02:52 +0200 Subject: [PATCH 001/681] Output call tree analysis as CSV for use in graph database * Methods and virtual methods are represented with graph nodes. * Direct, virtual and overriden-by relationships have been mapped. * Bytecode indexes are part of the relationships. * A method can interact with others multiple times, with each bytecode index indicating the origin of the call with the origin method. --- docs/reference-manual/native-image/Reports.md | 13 + .../pointsto/reports/CallTreePrinter.java | 278 ++++++++++++++++++ 2 files changed, 291 insertions(+) diff --git a/docs/reference-manual/native-image/Reports.md b/docs/reference-manual/native-image/Reports.md index ee2e5e8dca11..d0aee5feae2b 100644 --- a/docs/reference-manual/native-image/Reports.md +++ b/docs/reference-manual/native-image/Reports.md @@ -151,3 +151,16 @@ The call tree report name has the structure `call_tree__. The object tree report name has the structure: `object_tree__.txt`. The image name is the name of the generated image, which can be set with the `-H:Name=` option. The `` is in the `yyyyMMdd_HHmmss` format. + +#### CSV files + +The reports include a number of CSV files containing raw data for methods and their relationships. +The aim of these files is to make it enable this raw data to be easily imported into graph databases. +Graph databases can provide the following functionality: + +* Sophisticated graphical visualization of the call tree graph that provide a different perspective compared to text-based formats. +* Ability to execute complex queries that can for example show a subset of the tree that causes certain code path to be included in the call tree analysis. +This querying functionality is crucial in making big analysis call trees manageable. + +The process to import the files into graph databases is specific to each database. +Please follow the instructions provided by the graph database providers to find out how to import them. diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/CallTreePrinter.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/CallTreePrinter.java index 1ee89f84013f..a4b3a12e2648 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/CallTreePrinter.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/CallTreePrinter.java @@ -35,24 +35,36 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Deque; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.flow.InvokeTypeFlow; import com.oracle.graal.pointsto.meta.AnalysisMethod; import jdk.vm.ci.code.BytecodePosition; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; public final class CallTreePrinter { + public static final Pattern CAMEL_CASE_PATTERN = Pattern.compile( + "\\b[a-zA-Z]|[A-Z]|\\."); + public static void print(BigBang bb, String reportsPath, String reportName) { CallTreePrinter printer = new CallTreePrinter(bb); printer.buildCallTree(); @@ -65,6 +77,8 @@ public static void print(BigBang bb, String reportsPath, String reportName) { writer -> printer.printClasses(writer, false)); ReportUtils.report("list of used packages", reportsPath, "used_packages_" + reportName, "txt", writer -> printer.printClasses(writer, true)); + + printCsvFiles(printer.methodToNode, reportsPath, reportName); } interface Node { @@ -299,4 +313,268 @@ private static String packagePrefix(String name) { } return name.substring(0, lastDot); } + + private static void printCsvFiles(Map methodToNode, String reportsPath, String reportName) { + // Set virtual node at next available method id + final AtomicInteger virtualNodeId = new AtomicInteger(MethodNode.methodId); + + Set entryPointIds = new HashSet<>(); + Set nonVirtualNodes = new HashSet<>(); + Map, Integer> virtualNodes = new HashMap<>(); + + Map> directEdges = new HashMap<>(); + Map> virtualEdges = new HashMap<>(); + Map> overridenByEdges = new HashMap<>(); + + final Iterator iterator = methodToNode.values().stream().filter(n -> n.isEntryPoint).iterator(); + while (iterator.hasNext()) { + final MethodNode node = iterator.next(); + entryPointIds.add(node.id); + walkNodes(node, directEdges, virtualEdges, overridenByEdges, virtualNodes, nonVirtualNodes, virtualNodeId); + } + + ReportUtils.report("call tree for vm entry point", reportsPath, "csv_call_tree_vm_" + reportName, "csv", + CallTreePrinter::printVMEntryPoint); + + ReportUtils.report("call tree for methods", reportsPath, "csv_call_tree_methods_" + reportName, "csv", + writer -> printMethodNodes(methodToNode.values(), writer)); + + ReportUtils.report("call tree for virtual methods", reportsPath, "csv_call_tree_virtual_methods_" + reportName, "csv", + writer -> printVirtualNodes(virtualNodes, writer)); + + ReportUtils.report("call tree for entry points", reportsPath, "csv_call_tree_entry_points_" + reportName, "csv", + writer -> printEntryPointIds(entryPointIds, writer)); + + ReportUtils.report("call tree for direct edges", reportsPath, "csv_call_tree_direct_edges_" + reportName, "csv", + writer -> printBciEdges(directEdges, writer)); + + ReportUtils.report("call tree for overriden by edges", reportsPath, "csv_call_tree_override_by_edges_" + reportName, "csv", + writer -> printNonBciEdges(overridenByEdges, writer)); + + ReportUtils.report("call tree for virtual edges", reportsPath, "csv_call_tree_virtual_edges_" + reportName, "csv", + writer -> printBciEdges(virtualEdges, writer)); + } + + private static void printVMEntryPoint(PrintWriter writer) { + writer.println(convertToCSV("Id", "Name")); + writer.println(convertToCSV("0", "VM")); + } + + private static void printMethodNodes(Collection methods, PrintWriter writer) { + writer.println(convertToCSV("Id", "Name", "Type", "Parameters", "Return", "Display")); + methods.stream() + .map(CallTreePrinter::methodNodeInfo) + .map(CallTreePrinter::convertToCSV) + .forEach(writer::println); + } + + private static List methodNodeInfo(MethodNode method) { + return resolvedJavaMethodInfo(method.id, method.method); + } + + private static void walkNodes(MethodNode methodNode, Map> directEdges, Map> virtualEdges, Map> overridenByEdges, + Map, Integer> virtualNodes, Set nonVirtualNodes, AtomicInteger virtualNodeId) { + for (InvokeNode invoke : methodNode.invokes) { + if (invoke.isDirectInvoke) { + if (invoke.callees.size() > 0) { + Node calleeNode = invoke.callees.get(0); + addDirectEdge(methodNode.id, invoke, calleeNode, directEdges, nonVirtualNodes); + if (calleeNode instanceof MethodNode) { + walkNodes((MethodNode) calleeNode, directEdges, virtualEdges, overridenByEdges, virtualNodes, nonVirtualNodes, virtualNodeId); + } + } + } else { + final int nodeId = addVirtualNode(invoke, virtualNodes, virtualNodeId); + addVirtualMethodEdge(methodNode.id, invoke, nodeId, virtualEdges); + for (Node calleeNode : invoke.callees) { + addOverridenByEdge(nodeId, calleeNode, overridenByEdges, nonVirtualNodes); + if (calleeNode instanceof MethodNode) { + walkNodes((MethodNode) calleeNode, directEdges, virtualEdges, overridenByEdges, virtualNodes, nonVirtualNodes, virtualNodeId); + } + } + } + } + } + + private static void addDirectEdge(int nodeId, InvokeNode invoke, Node calleeNode, Map> edges, Set nodes) { + Set nodeEdges = edges.computeIfAbsent(nodeId, k -> new HashSet<>()); + MethodNode methodNode = calleeNode instanceof MethodNode + ? (MethodNode) calleeNode + : ((MethodNodeReference) calleeNode).methodNode; + nodes.add(methodNode); + nodeEdges.add(new BciEndEdge(methodNode.id, bytecodeIndexes(invoke))); + } + + private static List bytecodeIndexes(InvokeNode node) { + return Stream.of(node.sourceReferences) + .map(source -> source.bci) + .collect(Collectors.toList()); + } + + private static int addVirtualNode(InvokeNode node, Map, Integer> virtualNodes, AtomicInteger virtualNodeId) { + final List virtualMethodInfo = virtualMethodInfo(node.targetMethod); + return virtualNodes.computeIfAbsent(virtualMethodInfo, k -> virtualNodeId.getAndIncrement()); + } + + private static void addVirtualMethodEdge(int startId, InvokeNode invoke, int endId, Map> edges) { + Set nodeEdges = edges.computeIfAbsent(startId, k -> new HashSet<>()); + nodeEdges.add(new BciEndEdge(endId, bytecodeIndexes(invoke))); + } + + private static void printVirtualNodes(Map, Integer> virtualNodes, PrintWriter writer) { + writer.println(convertToCSV("Id", "Name", "Type", "Parameters", "Return", "Display")); + virtualNodes.entrySet().stream() + .map(CallTreePrinter::virtualMethodAndIdInfo) + .map(CallTreePrinter::convertToCSV) + .forEach(writer::println); + } + + private static List virtualMethodAndIdInfo(Map.Entry, Integer> entry) { + final List methodInfo = entry.getKey(); + final List result = new ArrayList<>(methodInfo.size() + 1); + result.add(String.valueOf(entry.getValue())); + for (int i = 1; i < methodInfo.size(); i++) { + result.add(i, methodInfo.get(i)); + } + return result; + } + + private static void printEntryPointIds(Set entryPoints, PrintWriter writer) { + writer.println(convertToCSV("Id")); + entryPoints.forEach(writer::println); + } + + private static void addOverridenByEdge(int nodeId, Node calleeNode, Map> edges, Set nodes) { + Set nodeEdges = edges.computeIfAbsent(nodeId, k -> new HashSet<>()); + MethodNode methodNode = calleeNode instanceof MethodNode + ? (MethodNode) calleeNode + : ((MethodNodeReference) calleeNode).methodNode; + nodes.add(methodNode); + nodeEdges.add(methodNode.id); + } + + private static void printBciEdges(Map> edges, PrintWriter writer) { + final Set idEdges = edges.entrySet().stream() + .flatMap(entry -> entry.getValue().stream().map(endId -> new BciEdge(entry.getKey(), endId))) + .collect(Collectors.toSet()); + + writer.println(convertToCSV("StartId", "EndId", "BytecodeIndexes")); + idEdges.stream() + .map(edge -> convertToCSV(String.valueOf(edge.startId), String.valueOf(edge.endEdge.id), showBytecodeIndexes(edge.endEdge.bytecodeIndexes))) + .forEach(writer::println); + } + + private static String showBytecodeIndexes(List bytecodeIndexes) { + return bytecodeIndexes.stream() + .map(String::valueOf) + .collect(Collectors.joining("->")); + } + + private static void printNonBciEdges(Map> edges, PrintWriter writer) { + final Set idEdges = edges.entrySet().stream() + .flatMap(entry -> entry.getValue().stream().map(endId -> new NonBciEdge(entry.getKey(), endId))) + .collect(Collectors.toSet()); + + writer.println(convertToCSV("StartId", "EndId")); + idEdges.stream() + .map(edge -> convertToCSV(String.valueOf(edge.startId), String.valueOf(edge.endId))) + .forEach(writer::println); + } + + private static List virtualMethodInfo(AnalysisMethod method) { + return resolvedJavaMethodInfo(null, method); + } + + private static List resolvedJavaMethodInfo(Integer id, ResolvedJavaMethod method) { + // TODO method parameter types are opaque, but could in the future be split out and link + // together + // e.g. each method could BELONG to a type, and a method could have PARAMETER relationships + // with N types + // see https://neo4j.com/developer/guide-import-csv/#_converting_data_values_with_load_csv + // for examples + final String parameters = method.getSignature().getParameterCount(false) > 0 + ? method.format("%P").replace(",", "") + : "empty"; + + return Arrays.asList( + id == null ? null : Integer.toString(id), + method.getName(), + method.getDeclaringClass().toJavaName(true), + parameters, + method.getSignature().getReturnType(null).toJavaName(true), + display(method)); + } + + private static String display(ResolvedJavaMethod method) { + final ResolvedJavaType type = method.getDeclaringClass(); + final String typeName = type.toJavaName(true); + if (type.getJavaKind() == JavaKind.Object) { + List matchResults = new ArrayList<>(); + Matcher matcher = CAMEL_CASE_PATTERN.matcher(typeName); + while (matcher.find()) { + matchResults.add(matcher.toMatchResult().group()); + } + + return String.join("", matchResults) + "." + method.getName(); + } + + return typeName + "." + method.getName(); + } + + private static String convertToCSV(String... data) { + return String.join(",", data); + } + + private static String convertToCSV(List data) { + return String.join(",", data); + } + + private static final class NonBciEdge { + + final int startId; + final int endId; + + private NonBciEdge(int startId, int endId) { + this.startId = startId; + this.endId = endId; + } + } + + private static final class BciEdge { + final int startId; + final BciEndEdge endEdge; + + private BciEdge(int startId, BciEndEdge endEdge) { + this.startId = startId; + this.endEdge = endEdge; + } + } + + private static final class BciEndEdge { + final int id; + final List bytecodeIndexes; + + private BciEndEdge(int id, List bytecodeIndexes) { + this.id = id; + this.bytecodeIndexes = bytecodeIndexes; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + BciEndEdge endEdge = (BciEndEdge) o; + return id == endEdge.id && + bytecodeIndexes.equals(endEdge.bytecodeIndexes); + } + + @Override + public int hashCode() { + return Objects.hash(id, bytecodeIndexes); + } + } } From 46c20551d46966ea4fab7d7bf64fb0f1ae8c4969 Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Thu, 26 Aug 2021 18:34:33 +0200 Subject: [PATCH 002/681] Add x82 configuration --- bench-common.libsonnet | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bench-common.libsonnet b/bench-common.libsonnet index f6760bd80fe2..92adc49ec58d 100644 --- a/bench-common.libsonnet +++ b/bench-common.libsonnet @@ -49,6 +49,13 @@ default_numa_node:: 0, num_threads:: 72 }, + x82:: common.linux + common.amd64 + self._bench_machine + { + machine_name:: "x82", + capabilities+: ["no_frequency_scaling", "tmpfs25g"], + numa_nodes:: [0, 1], + default_numa_node:: 0, + num_threads:: 96 + }, xgene3:: common.linux + common.aarch64 + self._bench_machine + { machine_name:: "xgene3", capabilities+: [], From d62e5c10e4c54ce4d07580f8692276fed19f6589 Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Thu, 26 Aug 2021 18:56:40 +0200 Subject: [PATCH 003/681] Rework math stub gate definition --- compiler/ci_includes/gate.jsonnet | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/ci_includes/gate.jsonnet b/compiler/ci_includes/gate.jsonnet index e9ada1369f48..7731c1689ccb 100644 --- a/compiler/ci_includes/gate.jsonnet +++ b/compiler/ci_includes/gate.jsonnet @@ -1,10 +1,11 @@ { - local common = (import '../../common.jsonnet'), + local common = import '../../common.jsonnet', + local utils = import '../../common-utils.libsonnet', local config = import '../../repo-configuration.libsonnet', local linux_amd64 = common["linux-amd64"], - local gateMathStubsListener = common.daily + linux_amd64 + common.oraclejdk8 + { - name: 'daily-hotspot-mathstubs-listener', + local gate_math_stubs_listener = { + name: 'daily-hotspot-mathstubs-listener-' + utils.prefixed_jdk(self.jdk_version), environment+: { "HOTSPOT_PORT_SYNC_CHECK" : "true" }, @@ -14,12 +15,10 @@ run+: [ ["mx", "build"] ], - notify_emails: [ - "yudi.zheng@oracle.com" - ], + notify_groups:: ["compiler_stubs"], }, builds: [ - gateMathStubsListener, + common.daily + linux_amd64 + common.oraclejdk8 + gate_math_stubs_listener, ] } From 7acefc4a5a8ccaf3dbd2e9c0c0bc8cfaf85f23dd Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Mon, 30 Aug 2021 11:47:44 +0200 Subject: [PATCH 004/681] Migrate javadoc publisher builder to jsonnet --- ci.hocon | 3 -- ci.jsonnet | 11 +++++- ci_includes/publish-javadoc.hocon | 44 ------------------------ ci_includes/publish-javadoc.jsonnet | 52 +++++++++++++++++++++++++++++ compiler/ci_includes/gate.jsonnet | 3 +- 5 files changed, 64 insertions(+), 49 deletions(-) delete mode 100644 ci_includes/publish-javadoc.hocon create mode 100644 ci_includes/publish-javadoc.jsonnet diff --git a/ci.hocon b/ci.hocon index 667507ef4749..ccd3bbeb9ed8 100644 --- a/ci.hocon +++ b/ci.hocon @@ -54,9 +54,6 @@ include "compiler/ci_includes/bench-aarch64-c2.hocon" # ------------------ SVM ---------------------- include "substratevm/ci_includes/gate.hocon" -# Publish Javadoc -include "ci_includes/publish-javadoc.hocon" - # ------------------- VM ---------------------- include "vm/ci_common/common.hocon" include "vm/ci_common/common-bench.hocon" diff --git a/ci.jsonnet b/ci.jsonnet index 3e95ac872dc0..c551f8554803 100644 --- a/ci.jsonnet +++ b/ci.jsonnet @@ -10,6 +10,9 @@ local espresso = import 'espresso/ci.jsonnet'; # Sulong local sulong = import 'sulong/ci.jsonnet'; +# JavaDoc +local javadoc = import "ci_includes/publish-javadoc.jsonnet"; + # Add a guard to `build` that prevents it from running in the gate # for a PR that only touches *.md flles. local add_markdown_guard(build) = build + { @@ -23,5 +26,11 @@ local add_markdown_guard(build) = build + { _checkCommon: (import 'common.jsonnet'), ci_resources:: (import 'ci-resources.libsonnet'), specVersion: "2", - builds: [add_markdown_guard(b) for b in (compiler.builds + wasm.builds + espresso.builds + sulong.builds)] + builds: [add_markdown_guard(b) for b in ( + compiler.builds + + wasm.builds + + espresso.builds + + sulong.builds + + javadoc.builds + )] } diff --git a/ci_includes/publish-javadoc.hocon b/ci_includes/publish-javadoc.hocon deleted file mode 100644 index 8b9ae71c1e87..000000000000 --- a/ci_includes/publish-javadoc.hocon +++ /dev/null @@ -1,44 +0,0 @@ -# Publish Javadoc of graal components post-merge - -builds += [ - ${linux-amd64} ${oraclejdk8} { - timelimit : "30:00", - run : [ - [cd, "./sdk"], - ["mx", "build"], - ["mx", "javadoc"], - ["zip", "-r", "javadoc.zip", "javadoc"], - [cd, "../truffle"], - ["mx", "build"], - ["mx", "javadoc"], - ["zip", "-r", "javadoc.zip", "javadoc"], - [cd, "../tools"], - ["mx", "build"], - ["mx", "javadoc"], - ["zip", "-r", "javadoc.zip", "javadoc"], - [cd, "../compiler"], - ["mx", "build"], - ["mx", "javadoc", "--projects", "org.graalvm.graphio"], - ["cd", "src/org.graalvm.graphio/"], - ["zip", "-r", "../../graphio-javadoc.zip", "javadoc"], - [cd, "../../.."], - [set-export, GRAAL_REPO, [pwd]], - [cd, ".."] - ["git", "clone", [mx, urlrewrite, "https://github.com/graalvm/graalvm-website.git"]], - [cd, "graalvm-website"] - ["rm", "-rf", "sdk/javadoc", "truffle/javadoc", "tools/javadoc", "graphio/javadoc"], - ["git", "status" ], - ["unzip", "-o", "-d", "sdk", "$GRAAL_REPO/sdk/javadoc.zip"], - ["unzip", "-o", "-d", "truffle", "$GRAAL_REPO/truffle/javadoc.zip"], - ["unzip", "-o", "-d", "tools", "$GRAAL_REPO/tools/javadoc.zip"], - ["unzip", "-o", "-d", "graphio", "$GRAAL_REPO/compiler/graphio-javadoc.zip"], - ["git", "add", "sdk/javadoc", "truffle/javadoc", "tools/javadoc", "graphio/javadoc"], - ["git", "config", "user.name", "Javadoc Publisher"], - ["git", "config", "user.email", "graal-dev@openjdk.java.net"], - ["git", "diff", "--staged", "--quiet", "||", "git", "commit", "-m", [ "echo", "Javadoc as of", [ "date", "+%Y/%m/%d" ] ] ], - ["git", "push", "origin", "HEAD"], - ], - targets : [post-merge], - name: "graal-publish-javadoc" - } -] diff --git a/ci_includes/publish-javadoc.jsonnet b/ci_includes/publish-javadoc.jsonnet new file mode 100644 index 000000000000..cdb68e132b8e --- /dev/null +++ b/ci_includes/publish-javadoc.jsonnet @@ -0,0 +1,52 @@ +{ + local common = import '../common.jsonnet', + local utils = import '../common-utils.libsonnet', + local linux_amd64 = common["linux-amd64"], + + local javadoc_publisher = { + name: 'graal-publish-javadoc-' + utils.prefixed_jdk(self.jdk_version), + run+: [ + ["cd", "./sdk"], + ["mx", "build"], + ["mx", "javadoc"], + ["zip", "-r", "javadoc.zip", "javadoc"], + ["cd", "../truffle"], + ["mx", "build"], + ["mx", "javadoc"], + ["zip", "-r", "javadoc.zip", "javadoc"], + ["cd", "../tools"], + ["mx", "build"], + ["mx", "javadoc"], + ["zip", "-r", "javadoc.zip", "javadoc"], + ["cd", "../compiler"], + ["mx", "build"], + ["mx", "javadoc", "--projects", "org.graalvm.graphio"], + ["cd", "src/org.graalvm.graphio/"], + ["zip", "-r", "../../graphio-javadoc.zip", "javadoc"], + ["cd", "../../.."], + ["set-export", "GRAAL_REPO", ["pwd"]], + ["cd", ".."], + ["git", "clone", ["mx", "urlrewrite", "https://github.com/graalvm/graalvm-website.git"]], + ["cd", "graalvm-website"], + ["rm", "-rf", "sdk/javadoc", "truffle/javadoc", "tools/javadoc", "graphio/javadoc"], + ["git", "status" ], + ["unzip", "-o", "-d", "sdk", "$GRAAL_REPO/sdk/javadoc.zip"], + ["unzip", "-o", "-d", "truffle", "$GRAAL_REPO/truffle/javadoc.zip"], + ["unzip", "-o", "-d", "tools", "$GRAAL_REPO/tools/javadoc.zip"], + ["unzip", "-o", "-d", "graphio", "$GRAAL_REPO/compiler/graphio-javadoc.zip"], + ["git", "add", "sdk/javadoc", "truffle/javadoc", "tools/javadoc", "graphio/javadoc"], + ["git", "config", "user.name", "Javadoc Publisher"], + ["git", "config", "user.email", "graal-dev@openjdk.java.net"], + ["git", "diff", "--staged", "--quiet", "||", "git", "commit", "-m", ["echo", "Javadoc as of", ["date", "+%Y/%m/%d"]]], + ["git", "push", "origin", "HEAD"] + ], + notify_groups:: ["javadoc"], + timelimit : "30:00" + }, + + local all_builds = [ + common.post_merge + linux_amd64 + common.oraclejdk8 + javadoc_publisher, + ], + // adds a "defined_in" field to all builds mentioning the location of this current file + builds:: [{ defined_in: std.thisFile } + b for b in all_builds] +} diff --git a/compiler/ci_includes/gate.jsonnet b/compiler/ci_includes/gate.jsonnet index 7731c1689ccb..2cf427ef325e 100644 --- a/compiler/ci_includes/gate.jsonnet +++ b/compiler/ci_includes/gate.jsonnet @@ -15,7 +15,8 @@ run+: [ ["mx", "build"] ], - notify_groups:: ["compiler_stubs"], + timelimit : "10:00", + notify_groups:: ["compiler_stubs"], }, builds: [ From 3c7c54f3e1379ad29638a5bec8d58fe847019d6e Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 1 Sep 2021 15:44:54 +0200 Subject: [PATCH 005/681] svm: always use SubstrateArraycopyWithExceptionNode and remove SubstrateArraycopyNode --- .../graal/jdk/SubstrateArraycopyNode.java | 54 ------------------- .../graal/jdk/SubstrateArraycopySnippets.java | 14 ----- .../SubstrateArraycopyWithExceptionNode.java | 16 ------ 3 files changed, 84 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyNode.java diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyNode.java deleted file mode 100644 index 89920d15f7f4..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyNode.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2015, 2017, 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.core.graal.jdk; - -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; -import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; - -import jdk.vm.ci.meta.JavaKind; - -/** - * Substrate specific intrinisfication for {@link System#arraycopy}. - * - * Lowering is implemented in the platform/VM specific - * {@link org.graalvm.compiler.nodes.spi.LoweringProvider LoweringProvider}. Most of them eventually - * go through {@link SubstrateArraycopySnippets}. - * - * @see SubstrateArraycopyWithExceptionNode Variant with exception edge. - */ -@NodeInfo -public final class SubstrateArraycopyNode extends BasicArrayCopyNode { - public static final NodeClass TYPE = NodeClass.create(SubstrateArraycopyNode.class); - - protected SubstrateArraycopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, JavaKind elementKind, int bci) { - super(TYPE, src, srcPos, dest, destPos, length, elementKind, bci); - if (this.elementKind == null) { - this.elementKind = ArrayCopy.selectComponentKind(this); - } - } -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java index e9a02b74211f..68813625a6c2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java @@ -30,7 +30,6 @@ import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.ForeignCallWithExceptionNode; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -61,7 +60,6 @@ public static void registerForeignCalls(Providers providers, SubstrateForeignCal protected SubstrateArraycopySnippets(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, Map, NodeLoweringProvider> lowerings) { super(options, factories, providers, snippetReflection); - lowerings.put(SubstrateArraycopyNode.class, new SubstrateArraycopyLowering()); lowerings.put(SubstrateArraycopyWithExceptionNode.class, new SubstrateArraycopyWithExceptionLowering()); } @@ -112,18 +110,6 @@ private static void boundsCheck(Object fromArray, int fromIndex, Object toArray, } } - static final class SubstrateArraycopyLowering implements NodeLoweringProvider { - @Override - public void lower(SubstrateArraycopyNode node, LoweringTool tool) { - StructuredGraph graph = node.graph(); - ForeignCallNode call = graph.add(new ForeignCallNode(ARRAYCOPY, node.getSource(), node.getSourcePosition(), node.getDestination(), - node.getDestinationPosition(), node.getLength())); - call.setStateAfter(node.stateAfter()); - call.setBci(node.getBci()); - graph.replaceFixedWithFixed(node, call); - } - } - static final class SubstrateArraycopyWithExceptionLowering implements NodeLoweringProvider { @Override public void lower(SubstrateArraycopyWithExceptionNode node, LoweringTool tool) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java index 14d919c33af5..13fd59e4606f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java @@ -33,14 +33,11 @@ import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.AbstractBeginNode; -import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.WithExceptionNode; import org.graalvm.compiler.nodes.memory.MemoryKill; -import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; import org.graalvm.word.LocationIdentity; @@ -52,8 +49,6 @@ * Lowering is implemented in the platform/VM specific * {@link org.graalvm.compiler.nodes.spi.LoweringProvider LoweringProvider}. Most of them eventually * go through {@link SubstrateArraycopySnippets}. - * - * @see SubstrateArraycopyNode Variant without exception edge. */ @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, cyclesRationale = "may be replaced with non-throwing counterpart", size = SIZE_64) public class SubstrateArraycopyWithExceptionNode extends WithExceptionNode implements ArrayCopy { @@ -139,15 +134,4 @@ public int getBci() { public JavaKind getElementKind() { return elementKind; } - - @Override - public FixedNode replaceWithNonThrowing() { - SubstrateArraycopyNode plainArrayCopy = this.asNode().graph() - .add(new SubstrateArraycopyNode(getSource(), getSourcePosition(), getDestination(), getDestinationPosition(), getLength(), getElementKind(), getBci())); - plainArrayCopy.setStateAfter(stateAfter); - AbstractBeginNode oldException = this.exceptionEdge; - graph().replaceSplitWithFixed(this, plainArrayCopy, this.next()); - GraphUtil.killCFG(oldException); - return plainArrayCopy; - } } From 61475aa5453554145cdc28ac6e5409e2b3085c22 Mon Sep 17 00:00:00 2001 From: Roland Schatz Date: Tue, 7 Sep 2021 17:07:13 +0200 Subject: [PATCH 006/681] Unit test for PEA of Array.newInstance. --- .../core/test/ea/PartialEscapeAnalysisTest.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java index 019ebb93623f..95643b44be61 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.test.ea; import java.lang.ref.SoftReference; +import java.lang.reflect.Array; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.test.TypeSystemTest; @@ -129,6 +130,18 @@ public static Object test3Snippet(int a) { } } + @Test + public void testDynArray() { + testPartialEscapeAnalysis("testDynArraySnippet", 0, 0); + } + + public static Object testDynArraySnippet(int a) { + Object[] args = (Object[]) Array.newInstance(Object.class, 2); + args[0] = a; + args[1] = 42; + return (int) args[0] + (int) args[1]; + } + @Test public void testArrayCopy() { testPartialEscapeAnalysis("testArrayCopySnippet", 0, 0); From 20416ad2b842fbedadbab44cf6f6854743813c6a Mon Sep 17 00:00:00 2001 From: Roland Schatz Date: Tue, 7 Sep 2021 17:13:06 +0200 Subject: [PATCH 007/681] Constant folding of RawLoadNode on immutable location identities. --- .../graalvm/compiler/nodes/extended/RawLoadNode.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java index 3faf761c980f..21f5e1403c05 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java @@ -178,14 +178,14 @@ public Node canonical(CanonicalizerTool tool) { if (offset().isConstant() && targetObject.isConstant() && !targetObject.isNullConstant()) { ConstantNode objectConstant = (ConstantNode) targetObject; ResolvedJavaType type = StampTool.typeOrNull(objectConstant); - if (type != null && type.isArray()) { - JavaConstant arrayConstant = objectConstant.asJavaConstant(); - if (arrayConstant != null) { + if (type != null) { + JavaConstant javaConstant = objectConstant.asJavaConstant(); + if (javaConstant != null) { int stableDimension = objectConstant.getStableDimension(); - if (stableDimension > 0) { + if (locationIdentity.isImmutable() || (type.isArray() && stableDimension > 0)) { NodeView view = NodeView.from(tool); long constantOffset = offset().asJavaConstant().asLong(); - Constant constant = stamp(view).readConstant(tool.getConstantReflection().getMemoryAccessProvider(), arrayConstant, constantOffset); + Constant constant = stamp(view).readConstant(tool.getConstantReflection().getMemoryAccessProvider(), javaConstant, constantOffset); boolean isDefaultStable = objectConstant.isDefaultStable(); if (constant != null && (isDefaultStable || !constant.isDefaultForKind())) { /* @@ -199,7 +199,7 @@ public Node canonical(CanonicalizerTool tool) { * accesses for building the AST during PE, and should not enforce * ordering on language side accesses. */ - return ConstantNode.forConstant(stamp(view), constant, stableDimension - 1, isDefaultStable, tool.getMetaAccess()); + return ConstantNode.forConstant(stamp(view), constant, Math.max(stableDimension - 1, 0), isDefaultStable, tool.getMetaAccess()); } } } From db11f7b6ae4f09656b1b390183cf26dea83fefa2 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 8 Sep 2021 08:15:45 +0200 Subject: [PATCH 008/681] svm: add simplification to update SubstrateArraycopyWithExceptionNode#elementKind --- .../jdk/SubstrateArraycopyWithExceptionNode.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java index 13fd59e4606f..4fc947a627cc 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java @@ -38,6 +38,8 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.WithExceptionNode; import org.graalvm.compiler.nodes.memory.MemoryKill; +import org.graalvm.compiler.nodes.spi.Simplifiable; +import org.graalvm.compiler.nodes.spi.SimplifierTool; import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; import org.graalvm.word.LocationIdentity; @@ -51,7 +53,7 @@ * go through {@link SubstrateArraycopySnippets}. */ @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, cyclesRationale = "may be replaced with non-throwing counterpart", size = SIZE_64) -public class SubstrateArraycopyWithExceptionNode extends WithExceptionNode implements ArrayCopy { +public class SubstrateArraycopyWithExceptionNode extends WithExceptionNode implements ArrayCopy, Simplifiable { public static final NodeClass TYPE = NodeClass.create(SubstrateArraycopyWithExceptionNode.class); @@ -134,4 +136,14 @@ public int getBci() { public JavaKind getElementKind() { return elementKind; } + + @Override + public void simplify(SimplifierTool tool) { + if (this.elementKind == null) { + this.elementKind = ArrayCopy.selectComponentKind(this); + if (this.elementKind != null) { + tool.addToWorkList(usages()); + } + } + } } From 0ebabb230c13f397f4cf12653481276e07ffba09 Mon Sep 17 00:00:00 2001 From: "cengfeng.lzy" Date: Wed, 8 Sep 2021 16:22:50 +0800 Subject: [PATCH 009/681] Refator NoClassInitializationPlguin to common place Standalone pointsto needs to use NoClassInitializationPlguin as its ClassInitializationPlugin, so it is refactored to the pointsto project for better reusibility. --- .../graal/pointsto}/phases/NoClassInitializationPlugin.java | 2 +- .../classinitialization/EarlyClassInitializerAnalysis.java | 2 +- .../hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java | 2 +- .../hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java | 1 + .../hosted/substitute/UnsafeAutomaticSubstitutionProcessor.java | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) rename substratevm/src/{com.oracle.svm.hosted/src/com/oracle/svm/hosted => com.oracle.graal.pointsto/src/com/oracle/graal/pointsto}/phases/NoClassInitializationPlugin.java (98%) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/NoClassInitializationPlugin.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java similarity index 98% rename from substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/NoClassInitializationPlugin.java rename to substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java index c55749bf73c2..d7ebceed74da 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/NoClassInitializationPlugin.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/NoClassInitializationPlugin.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.hosted.phases; +package com.oracle.graal.pointsto.phases; import java.util.function.Supplier; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/EarlyClassInitializerAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/EarlyClassInitializerAnalysis.java index 1aa15f0fc94b..85aca69ae2a8 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/EarlyClassInitializerAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/EarlyClassInitializerAnalysis.java @@ -54,6 +54,7 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; +import com.oracle.graal.pointsto.phases.NoClassInitializationPlugin; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.classinitialization.EnsureClassInitializedNode; import com.oracle.svm.core.graal.thread.VMThreadLocalAccess; @@ -61,7 +62,6 @@ import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.phases.EarlyConstantFoldLoadFieldPlugin; -import com.oracle.svm.hosted.phases.NoClassInitializationPlugin; import com.oracle.svm.hosted.snippets.ReflectionPlugins; import com.oracle.svm.hosted.snippets.SubstrateGraphBuilderPlugins; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java index 7afc2101255b..fe47e4c1bc1d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java @@ -36,8 +36,8 @@ import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor; +import com.oracle.graal.pointsto.phases.NoClassInitializationPlugin; import com.oracle.svm.hosted.c.GraalAccess; -import com.oracle.svm.hosted.phases.NoClassInitializationPlugin; import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.phases.util.Providers; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java index d591f8808cf2..d796dce91fbd 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java @@ -37,6 +37,7 @@ import java.util.Set; import java.util.stream.StreamSupport; +import com.oracle.graal.pointsto.phases.NoClassInitializationPlugin; import org.graalvm.collections.Pair; import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/UnsafeAutomaticSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/UnsafeAutomaticSubstitutionProcessor.java index 54372b325283..7dd4c5130974 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/UnsafeAutomaticSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/UnsafeAutomaticSubstitutionProcessor.java @@ -74,6 +74,7 @@ import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor; import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.phases.NoClassInitializationPlugin; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.annotate.AutomaticFeature; @@ -87,7 +88,6 @@ import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.classinitialization.ClassInitializerGraphBuilderPhase; -import com.oracle.svm.hosted.phases.NoClassInitializationPlugin; import com.oracle.svm.hosted.snippets.ReflectionPlugins; import jdk.vm.ci.meta.JavaKind; From 4d897ead28d0e22ee128ee54a166ee7f8d40665f Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 14 Sep 2021 22:22:39 +0300 Subject: [PATCH 010/681] Resubmit a PR to include WASM and NI changelogs --- substratevm/CHANGELOG.md | 5 +++++ wasm/CHANGELOG.md | 5 +++++ wasm/README.md | 37 ++++++++++++++++++------------------- 3 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 substratevm/CHANGELOG.md create mode 100644 wasm/CHANGELOG.md diff --git a/substratevm/CHANGELOG.md b/substratevm/CHANGELOG.md new file mode 100644 index 000000000000..ef9f442ed7fd --- /dev/null +++ b/substratevm/CHANGELOG.md @@ -0,0 +1,5 @@ +# Native Image Changelog + +This changelog summarizes major changes to Native Image, developed under the codename **Substrate VM**. + +## Version 21.3.0
 diff --git a/wasm/CHANGELOG.md b/wasm/CHANGELOG.md new file mode 100644 index 000000000000..e6e83856aa7e --- /dev/null +++ b/wasm/CHANGELOG.md @@ -0,0 +1,5 @@ +# Wasm (GraalWasm (GraalVM Implementation of WebAssembly) Changelog + +This changelog summarizes major changes to the WebAssembly engine implemented in GraalVM (GraalWasm). + +## Version 21.3.0 diff --git a/wasm/README.md b/wasm/README.md index 5250a7550a22..a62feb7ff021 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -1,7 +1,7 @@ # GraalWasm -GraalWasm is a WebAssembly engine implemented in the GraalVM. +GraalWasm is a WebAssembly engine implemented in GraalVM. It can interpret and compile WebAssembly programs in the binary format, or be embedded into other programs. @@ -15,7 +15,7 @@ Feedback, bug reports, and open-source contributions are welcome! ### Prerequisites - Python 3 (required by `mx`) -- git (to download, update, and locate repositories) +- GIT (to download, update, and locate repositories) - A [JVMCI-enabled JDK 8](https://github.com/graalvm/graal-jvmci-8/releases) or a newer JDK version (JDK 9+) - GCC for translating C files @@ -24,32 +24,32 @@ Feedback, bug reports, and open-source contributions are welcome! To build GraalWasm, you need to follow the standard workflow for Graal projects. We summarize the basic steps below: -1. Create a new folder where your repositories `mx` and `graal` should be located +1. Create a new folder where your repositories `mx` and `graal` should be located: ```bash $ mkdir graalvm $ cd graalvm ``` -2. Clone `mx` and add it to the PATH +2. Clone `mx` and add it to the `PATH`: ```bash $ git clone https://github.com/graalvm/mx.git $ export PATH=$PWD/mx:$PATH ``` -3. Clone the `graal` repository and enter the wasm directory. +3. Clone the `graal` repository and enter the wasm directory: ```bash $ git clone https://github.com/oracle/graal.git $ cd graal/wasm ``` -4. Set JAVA_HOME +4. Set `JAVA_HOME`: ```bash $ export JAVA_HOME=[path to JDK] ``` -5. Build the project +5. Build the project: ```bash $ mx --dy /truffle,/compiler build ``` @@ -65,7 +65,7 @@ which contains the GraalWasm implementation. The `build` command will also create the `wasm-tests.jar`, which contains the main test cases. To run these tests, the WebAssembly binary toolkit is needed. 1. Download the binary of the [WebAssembly binary toolkit(wabt)](https://github.com/WebAssembly/wabt) and extract it. -2. Set `WABT_DIR` +2. Set `WABT_DIR`: ```bash $ export WABT_DIR=[path to wabt]/bin @@ -98,7 +98,7 @@ This command results in the following output: Running: BranchBlockSuite (4/16 tests - you have enabled filters) -------------------------------------------------------------------------------- Using runtime: org.graalvm.compiler.truffle.runtime.hotspot.java.HotSpotTruffleRuntime@7b1d7fff -😍😍😍😍 +😍😍😍😍 Finished running: BranchBlockSuite 🍀 4/4 Wasm tests passed. ``` @@ -114,7 +114,7 @@ To compile these programs, you will need to install additional dependencies on y To build these additional tests and benchmarks, you need to: 1. Install the [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html). We currently test against Emscripten **1.39.13**. - + ```bash $ cd [preferred emsdk install location] @@ -134,21 +134,21 @@ $ ./emsdk activate [version number] $ source ./emsdk_env.sh ``` -2. Set `EMCC_DIR` and `GCC_DIR` +2. Set `EMCC_DIR` and `GCC_DIR`: ```bash $ export EMCC_DIR=[path to emsdk]/upstream/emscripten $ export GCC_DIR=[path to gcc (usually /usr/bin)] ``` -3. Run `emscripten-init` +3. Run `emscripten-init`: ```bash $ cd grallvm/graal/wasm $ mx emscripten-init ~/.emscripten [path to emsdk] --local ``` -4. Build with additional dependencies +4. Build with additional dependencies: ```bash $ mx --dy /truffle,/compiler build --all @@ -177,7 +177,7 @@ This will result in the following output: Running: CSuite (1 tests) -------------------------------------------------------------------------------- Using runtime: org.graalvm.compiler.truffle.runtime.hotspot.java.HotSpotTruffleRuntime@368239c8 -😍 +😍 Finished running: CSuite 🍀 1/1 Wasm tests passed. ``` @@ -194,9 +194,9 @@ The GraalWasm project includes a custom JMH-based benchmark suite, which is capable of running WebAssembly benchmark programs. The benchmark programs consist of several special functions, most notably `benchmarkRun`, which runs the body of the benchmark. -The benchmarks are kept in the `src/com.oracle.truffle.wasm.benchcases` Mx project. +The benchmarks are kept in the `src/com.oracle.truffle.wasm.benchcases` MX project. -For the benchmarks to run `NODE_DIR` has to be set. You can use the node version that is part of emscripten, for example: +For the benchmarks to run `NODE_DIR` has to be set. You can use the node version that is part of Emscripten, for example: ```bash $ export NODE_DIR=[path to emsdk]/node/14.15.5_64bit/bin @@ -256,7 +256,7 @@ If downloading GraalWasm as a separate GraalVM component, you can download it as follows (replace JDK and GraalVM versions with appropriate values): ```bash -$ graalvm-ce-java8-19.3.0/bin/gu install --force -L wasm-installable-java8-linux-.jar +$ graalvm-ce-java8-21.2.0/bin/gu install --force -L wasm-installable-java8-linux-.jar ``` This will install a launcher, which runs WebAssembly modules. @@ -314,5 +314,4 @@ mainFunction.execute(); ``` For more polyglot-related examples, consult the documentation at the -[GraalVM website](https://www.graalvm.org/docs/reference-manual/polyglot/). - +[GraalVM website](https://www.graalvm.org/reference-manual/polyglot-programming/). From 91a831db836df217c22a18b9bb224e025e184f90 Mon Sep 17 00:00:00 2001 From: Andrew Craik Date: Thu, 26 Aug 2021 11:13:32 +1000 Subject: [PATCH 011/681] Support masked vector shuffles on AMD64 This change adds support for generating vector shuffle operations which use a zeroing mask on AVX-512 enabled hardware. --- .../compiler/asm/amd64/AMD64Assembler.java | 14 +++++++ .../lir/amd64/vector/AMD64VectorShuffle.java | 40 +++++++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java index e0eb84891213..8c8cbf71a3c9 100644 --- a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java +++ b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java @@ -1396,6 +1396,20 @@ public void emit(AMD64Assembler asm, AVXSize size, Register dst, AMD64Address sr asm.emitOperandHelper(dst, src, 1, getDisp8Scale(useEvex, size)); asm.emitByte(imm8); } + + public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src, int imm8, Register mask, int z, int b) { + asm.evexPrefix(dst, mask, Register.None, src, size, pp, mmmmm, wEvex, z, b); + asm.emitByte(op); + asm.emitModRM(dst, src); + asm.emitByte(imm8); + } + + public void emit(AMD64Assembler asm, AVXSize size, Register dst, AMD64Address src, int imm8, Register mask, int z, int b) { + asm.evexPrefix(dst, mask, Register.None, src, size, pp, mmmmm, wEvex, z, b); + asm.emitByte(op); + asm.emitOperandHelper(dst, src, 1, getDisp8Scale(true, size)); + asm.emitByte(imm8); + } } /** diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java index 4c33ab5d2303..d723c5623982 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java @@ -65,6 +65,7 @@ import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp; +import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.asm.amd64.AVXKind; import org.graalvm.compiler.debug.GraalError; @@ -176,13 +177,17 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { public static class ShuffleWordOp extends AMD64LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ShuffleWordOp.class); - private final VexRMIOp op; + protected final VexRMIOp op; @Def({REG}) protected AllocatableValue result; @Use({REG, STACK}) protected AllocatableValue source; - private final int selector; + protected final int selector; public ShuffleWordOp(VexRMIOp op, AllocatableValue result, AllocatableValue source, int selector) { - super(TYPE); + this(TYPE, op, result, source, selector); + } + + protected ShuffleWordOp(LIRInstructionClass c, VexRMIOp op, AllocatableValue result, AllocatableValue source, int selector) { + super(c); this.op = op; this.result = result; this.source = source; @@ -200,6 +205,35 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { } } + public static class ShuffleWordOpWithMask extends ShuffleWordOp implements AVX512Support { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ShuffleWordOpWithMask.class); + + // both used and killed, must be a fixed register + @Use({REG}) protected AllocatableValue mask; + + public ShuffleWordOpWithMask(VexRMIOp op, AllocatableValue result, AllocatableValue source, int selector, AllocatableValue mask) { + super(TYPE, op, result, source, selector); + this.mask = mask; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + AMD64Kind kind = (AMD64Kind) source.getPlatformKind(); + if (isRegister(source)) { + op.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(source), selector, asRegister(mask), AMD64BaseAssembler.EVEXPrefixConfig.Z1, + AMD64BaseAssembler.EVEXPrefixConfig.B0); + } else { + op.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), (AMD64Address) crb.asAddress(source), selector, asRegister(mask), AMD64BaseAssembler.EVEXPrefixConfig.Z1, + AMD64BaseAssembler.EVEXPrefixConfig.B0); + } + } + + @Override + public AllocatableValue getOpmask() { + return mask; + } + } + public static class ShuffleFloatOp extends AMD64LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ShuffleFloatOp.class); @Def({REG}) protected AllocatableValue result; From ec7cbf48f3958fecec31055daa362fc8f5d1b883 Mon Sep 17 00:00:00 2001 From: Andrew Craik Date: Tue, 31 Aug 2021 16:05:49 +1000 Subject: [PATCH 012/681] Add support for VPERMT2B VPERMT2B is a useful instruction for permuting elements of a 512 byte ZMM register since it allows lane crossing in the permute. This change adds support for encoding this instruction and adds instruction objects to represent it during code generation. --- .../compiler/asm/amd64/AMD64Assembler.java | 15 ++++++ .../lir/amd64/vector/AMD64VectorShuffle.java | 50 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java index 8c8cbf71a3c9..5816bd5d692f 100644 --- a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java +++ b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java @@ -1612,6 +1612,7 @@ public static class VexRVMOp extends VexOp { public static final VexRVMOp VPBLENDMQ = new VexRVMOp("VPBLENDMQ", P_66, M_0F38, W1, 0x64, VEXOpAssertion.AVX512F_VL, EVEXTuple.FVM, W1); public static final VexRVMOp VBLENDMPS = new VexRVMOp("VBLENDMPS", P_66, M_0F38, W0, 0x65, VEXOpAssertion.AVX512F_VL, EVEXTuple.FVM, W0); public static final VexRVMOp VBLENDMPD = new VexRVMOp("VBLENDMPD", P_66, M_0F38, W1, 0x65, VEXOpAssertion.AVX512F_VL, EVEXTuple.FVM, W1); + public static final VexRVMOp VPERMT2B = new VexRVMOp("VPERMT2B", P_66, M_0F38, W0, 0x7D, VEXOpAssertion.AVX512F_VL, EVEXTuple.FVM, W0); // @formatter:on protected VexRVMOp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) { @@ -1650,6 +1651,20 @@ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, asm.emitOperandHelper(dst, src2, 0, getDisp8Scale(useEvex, size)); } + public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, Register src2, Register mask, int z, int b) { + assert assertion.check((AMD64) asm.target.arch, size, dst, src1, src2); + asm.vexPrefix(dst, src1, src2, mask, size, pp, mmmmm, w, wEvex, false, assertion.l128feature, assertion.l256feature, z, b); + asm.emitByte(op); + asm.emitModRM(dst, src2); + } + + public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, AMD64Address src2, Register mask, int z, int b) { + assert assertion.check((AMD64) asm.target.arch, size, dst, src1, null); + boolean useEvex = asm.vexPrefix(dst, src1, src2, mask, size, pp, mmmmm, w, wEvex, false, assertion.l128feature, assertion.l256feature, z, b); + asm.emitByte(op); + asm.emitOperandHelper(dst, src2, 0, getDisp8Scale(useEvex, size)); + } + public boolean isPacked() { return pp == P_ || pp == P_66; } diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java index d723c5623982..99c69d7312b9 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java @@ -42,6 +42,7 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp.VPEXTRQ; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp.VPEXTRW; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVD; +import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVDQU64; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp.VMOVQ; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp.VINSERTF128; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp.VINSERTF32X4; @@ -55,12 +56,14 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp.VINSERTI64X4; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp.VSHUFPD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMIOp.VSHUFPS; +import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VPERMT2B; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VPSHUFB; import static org.graalvm.compiler.asm.amd64.AVXKind.AVXSize.XMM; import static org.graalvm.compiler.asm.amd64.AVXKind.AVXSize.ZMM; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; +import jdk.vm.ci.code.Register; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMRIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMIOp; @@ -68,6 +71,7 @@ import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.asm.amd64.AVXKind; +import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; @@ -76,6 +80,7 @@ import jdk.vm.ci.amd64.AMD64.CPUFeature; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.meta.AllocatableValue; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; public class AMD64VectorShuffle { @@ -151,6 +156,51 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { } } + public static final class ConstPermuteBytesUsingTableOp extends AMD64LIRInstruction implements AVX512Support { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ConstPermuteBytesUsingTableOp.class); + @Def({REG}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue source; + @Use({REG}) protected AllocatableValue mask; + @Temp({REG}) protected AllocatableValue selector; + + byte[] selectorData; + + public ConstPermuteBytesUsingTableOp(LIRGeneratorTool tool, AllocatableValue result, AllocatableValue source, byte[] selectorData) { + this(tool, result, source, selectorData, null); + } + + public ConstPermuteBytesUsingTableOp(LIRGeneratorTool tool, AllocatableValue result, AllocatableValue source, byte[] selectorData, AllocatableValue mask) { + super(TYPE); + this.result = result; + this.source = source; + this.selectorData = selectorData; + this.selector = tool.newVariable(LIRKind.value(source.getPlatformKind())); + this.mask = mask; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + AMD64Kind kind = (AMD64Kind) source.getPlatformKind(); + int alignment = crb.dataBuilder.ensureValidDataAlignment(selectorData.length); + AMD64Address address = (AMD64Address) crb.recordDataReferenceInCode(selectorData, alignment); + VMOVDQU64.emit(masm, AVXKind.getRegisterSize(kind), asRegister(selector), address); + if (isRegister(source)) { + VPERMT2B.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(selector), asRegister(source), mask != null ? asRegister(mask) : Register.None, + AMD64BaseAssembler.EVEXPrefixConfig.Z1, + AMD64BaseAssembler.EVEXPrefixConfig.B0); + } else { + VPERMT2B.emit(masm, AVXKind.getRegisterSize(kind), asRegister(result), asRegister(selector), (AMD64Address) crb.asAddress(source), mask != null ? asRegister(mask) : Register.None, + AMD64BaseAssembler.EVEXPrefixConfig.Z1, + AMD64BaseAssembler.EVEXPrefixConfig.B0); + } + } + + @Override + public AllocatableValue getOpmask() { + return mask; + } + } + public static final class ConstShuffleBytesOp extends AMD64LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ConstShuffleBytesOp.class); @Def({REG}) protected AllocatableValue result; From 1af214b4cffe77c014dcd88ea08789dfa4247ad9 Mon Sep 17 00:00:00 2001 From: Andrew Craik Date: Mon, 13 Sep 2021 16:43:20 +1000 Subject: [PATCH 013/681] Clean-up and review fixes --- .../graalvm/compiler/asm/amd64/AMD64Assembler.java | 4 ++++ .../compiler/core/amd64/AMD64LIRGenerator.java | 12 ++++++++++++ .../lir/amd64/vector/AMD64VectorShuffle.java | 1 - 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java index 5816bd5d692f..51428351a555 100644 --- a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java +++ b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java @@ -1398,6 +1398,7 @@ public void emit(AMD64Assembler asm, AVXSize size, Register dst, AMD64Address sr } public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src, int imm8, Register mask, int z, int b) { + assert assertion.check((AMD64) asm.target.arch, size, dst, null, src); asm.evexPrefix(dst, mask, Register.None, src, size, pp, mmmmm, wEvex, z, b); asm.emitByte(op); asm.emitModRM(dst, src); @@ -1405,6 +1406,7 @@ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src, i } public void emit(AMD64Assembler asm, AVXSize size, Register dst, AMD64Address src, int imm8, Register mask, int z, int b) { + assert assertion.check((AMD64) asm.target.arch, size, dst, null, null); asm.evexPrefix(dst, mask, Register.None, src, size, pp, mmmmm, wEvex, z, b); asm.emitByte(op); asm.emitOperandHelper(dst, src, 1, getDisp8Scale(true, size)); @@ -1691,6 +1693,7 @@ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, asm.emitModRM(dst, src2); } + @Override public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, Register src2, Register mask, int z, int b) { assert assertion.check((AMD64) asm.target.arch, LZ, dst, src1, src2, null); assert size == AVXSize.DWORD || size == AVXSize.QWORD; @@ -1708,6 +1711,7 @@ public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, asm.emitOperandHelper(dst, src2, 0); } + @Override public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, AMD64Address src2, Register mask, int z, int b) { assert assertion.check((AMD64) asm.target.arch, LZ, dst, src1, null, null); assert size == AVXSize.DWORD || size == AVXSize.QWORD; diff --git a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java index 69fd3b4c9c02..c43fc61c27e5 100644 --- a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java @@ -764,4 +764,16 @@ public void emitZeroMemory(Value address, Value length, boolean isAligned) { emitMove(lengthReg, length); append(new AMD64ZeroMemoryOp(asAddressValue(address), lengthReg)); } + + public boolean supportsCPUFeature(AMD64.CPUFeature feature) { + return ((AMD64) target().arch).getFeatures().contains(feature); + } + + public boolean supportsCPUFeature(String feature) { + try { + return ((AMD64) target().arch).getFeatures().contains(AMD64.CPUFeature.valueOf(feature)); + } catch (IllegalArgumentException e) { + return false; + } + } } diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java index 99c69d7312b9..59560c77ab49 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java @@ -258,7 +258,6 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { public static class ShuffleWordOpWithMask extends ShuffleWordOp implements AVX512Support { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ShuffleWordOpWithMask.class); - // both used and killed, must be a fixed register @Use({REG}) protected AllocatableValue mask; public ShuffleWordOpWithMask(VexRMIOp op, AllocatableValue result, AllocatableValue source, int selector, AllocatableValue mask) { From ffb293005c3c9520eef4d12f0a999f042e6ce4d3 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Wed, 7 Jul 2021 10:44:58 +0300 Subject: [PATCH 014/681] Don't build LibGraal component by default LibGraal fails to build with upstream OpenJDK 11 due to it's dependency on HotSpotJVMCIRuntime.getCurrentJavaThread() which has not been backported to upstream OpenJDK 11. Preventing it from being build by default enables us to build components of GraalVM that do not depend on it, e.g., 'Native Image'. --- substratevm/mx.substratevm/suite.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 37b2410d8f34..480f790e97b4 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -942,6 +942,7 @@ "annotationProcessors": [ "compiler:GRAAL_PROCESSOR", ], + "defaultBuild": False, }, "com.oracle.svm.configure": { @@ -1264,6 +1265,7 @@ "distDependencies": [ "SVM", ], + "defaultBuild": False, }, # From 796e2edb0ba85e4cb9a25f3b0c345147e1efdc41 Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Tue, 14 Sep 2021 15:53:46 +0200 Subject: [PATCH 015/681] refactorings --- .../compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java | 3 +++ .../src/org/graalvm/compiler/nodes/loop/LoopEx.java | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java index 077c2dbb5639..ead822210245 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java @@ -269,6 +269,9 @@ private static boolean isCountedLoopExit(IfNode ifNode, LazyValue laz if (loopEx.detectCounted()) { return ifNode == loopEx.counted().getLimitTest(); } + if (loopEx.canBecomeLimitTestAfterFloatingReads(ifNode)) { + return true; + } } return false; } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java index b65a33963d51..9a48948cc5c8 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java @@ -566,4 +566,8 @@ public boolean canStripMine() { } return true; } + + public boolean canBecomeLimitTestAfterFloatingReads(@SuppressWarnings("unused") IfNode ifNode) { + return false; + } } From 417159ff1f6e530ed240595a103fd9508dc6af95 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Fri, 17 Sep 2021 10:23:27 +0300 Subject: [PATCH 016/681] Dynamic Proxy configuration does not support the definition of unordered interfaces --- docs/reference-manual/native-image/DynamicProxy.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/reference-manual/native-image/DynamicProxy.md b/docs/reference-manual/native-image/DynamicProxy.md index c56dadc05175..d70cbaf4b534 100644 --- a/docs/reference-manual/native-image/DynamicProxy.md +++ b/docs/reference-manual/native-image/DynamicProxy.md @@ -90,9 +90,9 @@ For the exceptional cases where the analysis cannot discover the interface array ## Manual Configuration -Dynamic proxy classes can be generated at native image build time by specifying the list of interfaces that they implement. Native Image provides two options for this purpose: `-H:DynamicProxyConfigurationFiles=` and `-H:DynamicProxyConfigurationResources=`. +Dynamic proxy classes can be generated at native image build time by specifying the list of interfaces that they implement. +Native Image provides two options for that: `-H:DynamicProxyConfigurationFiles=` and `-H:DynamicProxyConfigurationResources=`. These options accept JSON files whose structure is an array of arrays of fully qualified interface names. For example: -These options accept JSON files whose structure is an array of arrays of fully qualified interface names. For example: ```json [ ["java.lang.AutoCloseable", "java.util.Comparator"], @@ -101,6 +101,8 @@ These options accept JSON files whose structure is an array of arrays of fully q ] ``` +Note that the order of the specified proxy interfaces is significant: two requests for a `Proxy` class with the same combination of interfaces but in a different order will result in two distinct behaviours (for more detailed information, refer to [`Proxy Class `javadoc](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/reflect/Proxy.html). + The `java.lang.reflect.Proxy` API also allows creation of a dynamic proxy that does not implement any user provided interfaces. Therefore the following is a valid configuration: ```json [ From 5d9846ef69f02e03f380c27bed76468df7dfbf76 Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Fri, 17 Sep 2021 10:09:07 +0200 Subject: [PATCH 017/681] make sure we always display error logging even when the thread cannot enter the Truffle context --- .../jdwp/impl/DebuggerConnection.java | 12 +- .../truffle/espresso/jdwp/impl/JDWP.java | 106 +++++++++++++----- 2 files changed, 85 insertions(+), 33 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java index 500ed5c06c73..68f1a7f4294f 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java @@ -587,8 +587,16 @@ private void processPacket(Packet packet) { } handleReply(packet, result); } catch (Throwable t) { - JDWP.LOGGER.warning(() -> "[Internal error]: " + t.getClass()); - JDWP.LOGGER.throwing(DebuggerConnection.class.getName(), "processPacket", t); + if (entered) { + // we can only use the Truffle logger if we were able to enter the context + JDWP.LOGGER.warning(() -> "[Internal error]"); + JDWP.LOGGER.throwing(DebuggerConnection.class.getName(), "processPacket", t); + } else { + // Checkstyle: stop allow error output + System.out.println("[internal error]: " + t.getMessage()); + t.printStackTrace(); + // Checkstyle: resume allow error output + } PacketStream reply = new PacketStream().replyPacket().id(packet.id); reply.errorCode(ErrorCodes.INTERNAL); handleReply(packet, new CommandResult(reply)); diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java index c5cc5a4eb9ee..8200ed62b886 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java @@ -1105,10 +1105,27 @@ public Object call() { new Thread(new Runnable() { @Override public void run() { - ThreadJob.JobResult result = job.getResult(); - writeMethodResult(reply, context, result); + boolean entered = controller.enterTruffleContext(); CommandResult commandResult = new CommandResult(reply); - connection.handleReply(packet, commandResult); + try { + ThreadJob.JobResult result = job.getResult(); + writeMethodResult(reply, context, result); + } catch (Throwable t) { + reply.errorCode(ErrorCodes.INTERNAL); + // Checkstyle: stop allow error output + if (entered) { + LOGGER.warning(() -> "Internal Espresso error: " + t); + } else { + System.err.println("Internal Espresso error: " + t.getMessage()); + } + t.printStackTrace(); + // Checkstyle: resume allow error output + } finally { + connection.handleReply(packet, commandResult); + if (entered) { + controller.leaveTruffleContext(); + } + } } }).start(); } catch (Throwable t) { @@ -1269,10 +1286,27 @@ public Object call() throws Exception { new Thread(new Runnable() { @Override public void run() { - ThreadJob.JobResult result = job.getResult(); - writeMethodResult(reply, context, result); + boolean entered = controller.enterTruffleContext(); CommandResult commandResult = new CommandResult(reply); - connection.handleReply(packet, commandResult); + try { + ThreadJob.JobResult result = job.getResult(); + writeMethodResult(reply, context, result); + } catch (Throwable t) { + reply.errorCode(ErrorCodes.INTERNAL); + // Checkstyle: stop allow error output + if (entered) { + LOGGER.warning(() -> "Internal Espresso error: " + t); + } else { + System.err.println("Internal Espresso error: " + t.getMessage()); + } + t.printStackTrace(); + // Checkstyle: resume allow error output + } finally { + connection.handleReply(packet, commandResult); + if (entered) { + controller.leaveTruffleContext(); + } + } } }).start(); } catch (Throwable t) { @@ -1749,10 +1783,27 @@ public Object call() throws Exception { new Thread(new Runnable() { @Override public void run() { - ThreadJob.JobResult result = job.getResult(); - writeMethodResult(reply, context, result); + boolean entered = controller.enterTruffleContext(); CommandResult commandResult = new CommandResult(reply); - connection.handleReply(packet, commandResult); + try { + ThreadJob.JobResult result = job.getResult(); + writeMethodResult(reply, context, result); + } catch (Throwable t) { + reply.errorCode(ErrorCodes.INTERNAL); + // Checkstyle: stop allow error output + if (entered) { + LOGGER.warning(() -> "Internal Espresso error: " + t); + } else { + System.err.println("Internal Espresso error: " + t.getMessage()); + } + t.printStackTrace(); + // Checkstyle: resume allow error output + } finally { + connection.handleReply(packet, commandResult); + if (entered) { + controller.leaveTruffleContext(); + } + } } }).start(); } catch (Throwable t) { @@ -2974,31 +3025,24 @@ public static void writeValue(byte tag, Object value, PacketStream reply, boolea } private static void writeMethodResult(PacketStream reply, JDWPContext context, ThreadJob.JobResult result) { - try { - if (result.getException() != null) { - LOGGER.fine(() -> "method threw exception"); - reply.writeByte(TagConstants.OBJECT); - reply.writeLong(0); - reply.writeByte(TagConstants.OBJECT); - Object guestException = context.getGuestException(result.getException()); - reply.writeLong(context.getIds().getIdAsLong(guestException)); - } else { - Object value = context.toGuest(result.getResult()); - if (value != null) { - byte tag = context.getTag(value); - writeValue(tag, value, reply, true, context); - } else { // return value is null - reply.writeByte(TagConstants.OBJECT); - reply.writeLong(0); - } - // no exception, so zero object ID + if (result.getException() != null) { + reply.writeByte(TagConstants.OBJECT); + reply.writeLong(0); + reply.writeByte(TagConstants.OBJECT); + Object guestException = context.getGuestException(result.getException()); + reply.writeLong(context.getIds().getIdAsLong(guestException)); + } else { + Object value = context.toGuest(result.getResult()); + if (value != null) { + byte tag = context.getTag(value); + writeValue(tag, value, reply, true, context); + } else { // return value is null reply.writeByte(TagConstants.OBJECT); reply.writeLong(0); } - } catch (Throwable t) { - LOGGER.warning(() -> "Internal Espresso error: " + t); - LOGGER.throwing(JDWP.class.getName(), "writeMethodResult", t); - reply.errorCode(ErrorCodes.INTERNAL); + // no exception, so zero object ID + reply.writeByte(TagConstants.OBJECT); + reply.writeLong(0); } } From 7ca690a88bccee742be1fb64719599403a9e231e Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Fri, 17 Sep 2021 11:30:19 +0200 Subject: [PATCH 018/681] fix java 9 or later substitution for JDK ProxyGenerator class --- .../Target_java_lang_reflect_ProxyGenerator.java | 2 +- .../espresso/substitutions/VersionFilter.java | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_reflect_ProxyGenerator.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_reflect_ProxyGenerator.java index 5e2aaa7bc249..0f0b5f7db69e 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_reflect_ProxyGenerator.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_reflect_ProxyGenerator.java @@ -33,7 +33,7 @@ @EspressoSubstitutions public final class Target_java_lang_reflect_ProxyGenerator { - @Substitution(versionFilter = VersionFilter.Java8OrEarlier.class) + @Substitution(versionFilter = VersionFilter.Java9OrLater.class) abstract static class GenerateProxyClass extends SubstitutionNode { abstract @JavaType(byte[].class) StaticObject execute( diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java index f75994215630..1cbcba54b238 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java @@ -53,6 +53,18 @@ public boolean isValidFor(JavaVersion version) { } } + final class Java9OrLater implements VersionFilter { + public static final Java9OrLater INSTANCE = new Java9OrLater(); + + private Java9OrLater() { + } + + @Override + public boolean isValidFor(JavaVersion version) { + return version.java9OrLater(); + } + } + final class Java11OrEarlier implements VersionFilter { public static final Java11OrEarlier INSTANCE = new Java11OrEarlier(); From 211ea12a3f141589a06807f6c7c7b9a3759bd4a6 Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Fri, 17 Sep 2021 12:11:32 +0200 Subject: [PATCH 019/681] delay entering truffle context for logging --- .../src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java index 8200ed62b886..818fc245701c 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java @@ -1105,12 +1105,13 @@ public Object call() { new Thread(new Runnable() { @Override public void run() { - boolean entered = controller.enterTruffleContext(); + boolean entered = false; CommandResult commandResult = new CommandResult(reply); try { ThreadJob.JobResult result = job.getResult(); writeMethodResult(reply, context, result); } catch (Throwable t) { + entered = controller.enterTruffleContext(); reply.errorCode(ErrorCodes.INTERNAL); // Checkstyle: stop allow error output if (entered) { @@ -1286,12 +1287,13 @@ public Object call() throws Exception { new Thread(new Runnable() { @Override public void run() { - boolean entered = controller.enterTruffleContext(); + boolean entered = false; CommandResult commandResult = new CommandResult(reply); try { ThreadJob.JobResult result = job.getResult(); writeMethodResult(reply, context, result); } catch (Throwable t) { + entered = controller.enterTruffleContext(); reply.errorCode(ErrorCodes.INTERNAL); // Checkstyle: stop allow error output if (entered) { @@ -1783,12 +1785,13 @@ public Object call() throws Exception { new Thread(new Runnable() { @Override public void run() { - boolean entered = controller.enterTruffleContext(); + boolean entered = false; CommandResult commandResult = new CommandResult(reply); try { ThreadJob.JobResult result = job.getResult(); writeMethodResult(reply, context, result); } catch (Throwable t) { + entered = controller.enterTruffleContext(); reply.errorCode(ErrorCodes.INTERNAL); // Checkstyle: stop allow error output if (entered) { From d9d7eb09fe7546c7b254102a6d5c39f15d2c202d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Fri, 17 Sep 2021 12:13:26 +0200 Subject: [PATCH 020/681] Use labsjdk-ce-11 in SVM gates --- substratevm/ci_includes/gate.hocon | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/substratevm/ci_includes/gate.hocon b/substratevm/ci_includes/gate.hocon index fe41f3535dbf..4f2577c9ba32 100644 --- a/substratevm/ci_includes/gate.hocon +++ b/substratevm/ci_includes/gate.hocon @@ -25,8 +25,8 @@ builds += [ ${oraclejdk8} ${svm-common-darwin-gate} ${gate-svm-js} { name: "gate-svm-darwin-js" } - ${labsjdk-ee-11} ${svm-common-linux-gate} ${linux-deploy} { - name: "gate-svm-build-ee-11" + ${labsjdk-ce-11} ${svm-common-linux-gate} ${linux-deploy} { + name: "gate-svm-build-ce-11" downloads: { "MUSL_LIBS": { "name": "musl-libs", @@ -43,7 +43,7 @@ builds += [ ${svm-cmd-gate} ["build,helloworld,test,maven,nativeimagehelp,muslcbuild"] ] } - ${labsjdk-ee-11} ${svm-common-linux-gate} ${linux-deploy} { + ${labsjdk-ce-11} ${svm-common-linux-gate} ${linux-deploy} { name: "gate-svm-modules-basic" run: [ ${svm-cmd-gate} ["build,hellomodule,test"] From 261096af485656b177825e60d59fa60f746bb8a7 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Fri, 17 Sep 2021 15:14:37 +0300 Subject: [PATCH 021/681] Add native-image heap size limit in GraalVM documentation --- docs/reference-manual/native-image/MemoryManagement.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/reference-manual/native-image/MemoryManagement.md b/docs/reference-manual/native-image/MemoryManagement.md index 6e3fb95e37f8..3df61764ff52 100644 --- a/docs/reference-manual/native-image/MemoryManagement.md +++ b/docs/reference-manual/native-image/MemoryManagement.md @@ -48,7 +48,7 @@ Note: The maximum heap size is only the upper limit for the Java heap and not ne The *Serial GC* is optimized for low footprint and small Java heap sizes. If no other GC is specified, the Serial GC will be used implicitly as the default on both GraalVM Community and Enterprise Edition. -Since GraalVM 20.3, it is also possible to explicitly enable the Serial GC by passing the option `--gc=serial` to the native image builder. +It is also possible to explicitly enable the Serial GC by passing the option `--gc=serial` to the native image builder. ```shell # Build a native image that uses the serial GC with default settings @@ -75,6 +75,8 @@ Note that this is just the maximum value. Depending on the application, the amount of actually used Java heap memory can be much lower. To override this default behavior, either specify a value for `-XX:MaximumHeapSizePercent` or explicitly set the maximum [Java heap size](#java-heap-size). +Be mindful that the GC needs some extra memory when performing a garbage collection (2x is the worst case, usually it significantly less). Therefore, the resident set size, RSS, can increase temporarily during a garbage collection which can be an issue in any environment with memory constraints (having little memory available, such as a container). + ### Performance Tuning For tuning the GC performance and the memory footprint, the following options can be used: From 73054492c3e6c792274ce332be0b7663ef6aaa89 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Fri, 17 Sep 2021 15:15:51 +0300 Subject: [PATCH 022/681] Minor correction --- docs/reference-manual/native-image/MemoryManagement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-manual/native-image/MemoryManagement.md b/docs/reference-manual/native-image/MemoryManagement.md index 3df61764ff52..7d95c6a9df5d 100644 --- a/docs/reference-manual/native-image/MemoryManagement.md +++ b/docs/reference-manual/native-image/MemoryManagement.md @@ -75,7 +75,7 @@ Note that this is just the maximum value. Depending on the application, the amount of actually used Java heap memory can be much lower. To override this default behavior, either specify a value for `-XX:MaximumHeapSizePercent` or explicitly set the maximum [Java heap size](#java-heap-size). -Be mindful that the GC needs some extra memory when performing a garbage collection (2x is the worst case, usually it significantly less). Therefore, the resident set size, RSS, can increase temporarily during a garbage collection which can be an issue in any environment with memory constraints (having little memory available, such as a container). +Be mindful that the GC needs some extra memory when performing a garbage collection (2x is the worst case, usually it significantly less). Therefore, the resident set size, RSS, can increase temporarily during a garbage collection which can be an issue in any environment with memory constraints (such as a container). ### Performance Tuning From 3be82c34b62c2a08fbb13664399e0b8871c67e16 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Fri, 17 Sep 2021 15:50:33 +0300 Subject: [PATCH 023/681] Follow Ch. Haeubl comment --- docs/reference-manual/native-image/MemoryManagement.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference-manual/native-image/MemoryManagement.md b/docs/reference-manual/native-image/MemoryManagement.md index 7d95c6a9df5d..f39af9332cd5 100644 --- a/docs/reference-manual/native-image/MemoryManagement.md +++ b/docs/reference-manual/native-image/MemoryManagement.md @@ -75,7 +75,8 @@ Note that this is just the maximum value. Depending on the application, the amount of actually used Java heap memory can be much lower. To override this default behavior, either specify a value for `-XX:MaximumHeapSizePercent` or explicitly set the maximum [Java heap size](#java-heap-size). -Be mindful that the GC needs some extra memory when performing a garbage collection (2x is the worst case, usually it significantly less). Therefore, the resident set size, RSS, can increase temporarily during a garbage collection which can be an issue in any environment with memory constraints (such as a container). +Be mindful that the GC needs some extra memory when performing a garbage collection (2x of the maximum heap size is the worst case, usually, it is significantly less). +Therefore, the resident set size, RSS, can increase temporarily during a garbage collection which can be an issue in any environment with memory constraints (such as a container). ### Performance Tuning From b06c8c4b720eb30cd1353cbedd13d256fa9c7463 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Mon, 13 Sep 2021 16:19:25 -0400 Subject: [PATCH 024/681] TRegex: Add ASCII encoding to reduce range of Unicode char sets to ASCII if match string is ASCII-only. --- regex/CHANGELOG.md | 4 + .../oracle/truffle/regex/RegexOptions.java | 3 + .../tregex/nodes/TRegexExecutorNode.java | 2 +- .../parser/flavors/RubyFlavorProcessor.java | 8 ++ .../regex/tregex/string/Encodings.java | 63 +++++++++- .../regex/tregex/string/StringASCII.java | 112 ++++++++++++++++++ .../tregex/string/StringBufferASCII.java | 85 +++++++++++++ 7 files changed, 274 insertions(+), 3 deletions(-) create mode 100644 regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/StringASCII.java create mode 100644 regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/StringBufferASCII.java diff --git a/regex/CHANGELOG.md b/regex/CHANGELOG.md index 51d1dc05d849..52fef7b9502f 100644 --- a/regex/CHANGELOG.md +++ b/regex/CHANGELOG.md @@ -2,6 +2,10 @@ This changelog summarizes major changes between TRegex versions relevant to language implementors integrating TRegex into their language. This document will focus on API changes relevant to integrators of TRegex. +## Version 22.0.0 + +* Added new `ASCII` encoding that callers can use when compiling a regex to limit the range of code point matches to [0xx, 0x7f]. + ## Version 21.3.0 * Support for case-insensitive matching in Ruby regular expressions. diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexOptions.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexOptions.java index 87ce806df420..d573684d77e7 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexOptions.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexOptions.java @@ -397,6 +397,9 @@ private int parseEncoding(int i) throws RegexSyntaxException { throw optionsSyntaxErrorUnexpectedValue(iVal, Encodings.ALL_NAMES); } switch (src.charAt(iVal)) { + case 'A': + encoding = Encodings.ASCII; + return expectValue(iVal, Encodings.ASCII.getName(), Encodings.ALL_NAMES); case 'B': encoding = Encodings.LATIN_1; return expectValue(iVal, "BYTES", Encodings.ALL_NAMES); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java index 36fbe87585c0..4452e0fd89c8 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java @@ -182,7 +182,7 @@ public int inputReadAndDecode(TRegexExecutorLocals locals, int index) { return codepoint | (c & (0xff >>> nBytes)) << (6 * (nBytes - 1)); } } else { - assert getEncoding() == Encodings.UTF_16_RAW || getEncoding() == Encodings.UTF_32 || getEncoding() == Encodings.LATIN_1; + assert getEncoding() == Encodings.UTF_16_RAW || getEncoding() == Encodings.UTF_32 || getEncoding() == Encodings.LATIN_1 || getEncoding() == Encodings.ASCII; locals.setNextIndex(inputIncRaw(index)); return inputReadRaw(locals); } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/flavors/RubyFlavorProcessor.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/flavors/RubyFlavorProcessor.java index e75d986e8c0c..74c7823fedf4 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/flavors/RubyFlavorProcessor.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/flavors/RubyFlavorProcessor.java @@ -1088,10 +1088,18 @@ private void escape() { } private CodePointSet getUnicodeCharClass(char className) { + if (inSource.getEncoding() == Encodings.ASCII) { + return ASCII_CHAR_CLASSES.get(className); + } + return trimToEncoding(UNICODE_CHAR_CLASSES.get(className)); } private CodePointSet getUnicodePosixCharClass(String className) { + if (inSource.getEncoding() == Encodings.ASCII) { + return ASCII_POSIX_CHAR_CLASSES.get(className); + } + return trimToEncoding(UNICODE_POSIX_CHAR_CLASSES.get(className)); } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/Encodings.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/Encodings.java index 68a716a77458..8b8f2caf4a88 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/Encodings.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/Encodings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -62,8 +62,9 @@ public final class Encodings { public static final Encoding UTF_32 = new Encoding.UTF32(); public static final Encoding UTF_16_RAW = new Encoding.UTF16Raw(); public static final Encoding LATIN_1 = new Encoding.Latin1(); + public static final Encoding ASCII = new Encoding.Ascii(); - public static final String[] ALL_NAMES = {UTF_8.getName(), UTF_16.getName(), UTF_16_RAW.getName(), UTF_32.getName(), LATIN_1.getName(), "BYTES"}; + public static final String[] ALL_NAMES = {UTF_8.getName(), UTF_16.getName(), UTF_16_RAW.getName(), UTF_32.getName(), ASCII.getName(), LATIN_1.getName(), "BYTES"}; public static Encoding getEncoding(String name) { switch (name) { @@ -518,5 +519,63 @@ public Matchers toMatchers(Builder matchersBuilder) { return new Matchers.SimpleMatchers(matchersBuilder.materialize(0), matchersBuilder.getNoMatchSuccessor()); } } + + public static final class Ascii extends Encoding { + + @Override + public String getName() { + return "ASCII"; + } + + @Override + public int getMaxValue() { + return 0x7f; + } + + @Override + public CodePointSet getFullSet() { + return Constants.ASCII_RANGE; + } + + @Override + public int getEncodedSize(int codepoint) { + return 1; + } + + @Override + public boolean isFixedCodePointWidth(CodePointSet set) { + return true; + } + + @Override + public boolean isUnicode() { + return false; + } + + @Override + public AbstractStringBuffer createStringBuffer(int capacity) { + return new StringBufferASCII(capacity); + } + + @Override + public LoopOptimizationNode extractLoopOptNode(CodePointSet cps) { + return new LoopOptIndexOfAnyByteNode(cps.inverseToByteArray(this)); + } + + @Override + public int getNumberOfDecodingSteps() { + return 1; + } + + @Override + public void createMatcher(Builder matchersBuilder, int i, CodePointSet cps, CompilationBuffer compilationBuffer) { + matchersBuilder.getBuffer(0).set(i, CharMatchers.createMatcher(cps, compilationBuffer)); + } + + @Override + public Matchers toMatchers(Builder matchersBuilder) { + return new Matchers.SimpleMatchers(matchersBuilder.materialize(0), matchersBuilder.getNoMatchSuccessor()); + } + } } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/StringASCII.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/StringASCII.java new file mode 100644 index 000000000000..a1deb4121034 --- /dev/null +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/StringASCII.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.regex.tregex.string; + +import java.util.Arrays; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; + +public final class StringASCII implements AbstractString { + + @CompilationFinal(dimensions = 1) private final byte[] str; + + public StringASCII(byte[] str) { + this.str = str; + } + + @Override + public int encodedLength() { + return str.length; + } + + @Override + public Object content() { + return str; + } + + @Override + public String toString() { + return defaultToString(); + } + + @Override + public StringASCII substring(int start, int end) { + return new StringASCII(Arrays.copyOfRange(str, start, end)); + } + + @Override + public boolean regionMatches(int offset, AbstractString other, int ooffset, int encodedLength) { + byte[] o = ((StringASCII) other).str; + if (offset + encodedLength > str.length || ooffset + encodedLength > o.length) { + return false; + } + for (int i = 0; i < encodedLength; i++) { + if (str[offset + i] != o[ooffset + i]) { + return false; + } + } + return true; + } + + @Override + public AbstractStringIterator iterator() { + return new StringASCIIIterator(str); + } + + private static final class StringASCIIIterator extends AbstractStringIterator { + + private final byte[] str; + + private StringASCIIIterator(byte[] str) { + this.str = str; + } + + @Override + public boolean hasNext() { + return i < str.length; + } + + @Override + public int nextInt() { + return Byte.toUnsignedInt(str[i++]); + } + } +} diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/StringBufferASCII.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/StringBufferASCII.java new file mode 100644 index 000000000000..950806d27bcf --- /dev/null +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/string/StringBufferASCII.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.regex.tregex.string; + +import com.oracle.truffle.regex.tregex.buffer.ByteArrayBuffer; +import com.oracle.truffle.regex.tregex.string.Encodings.Encoding; + +public final class StringBufferASCII extends ByteArrayBuffer implements AbstractStringBuffer { + + public StringBufferASCII() { + this(16); + } + + public StringBufferASCII(int capacity) { + super(capacity); + } + + @Override + public Encoding getEncoding() { + return Encodings.ASCII; + } + + @Override + public void append(int codepoint) { + assert codepoint <= Encodings.ASCII.getMaxValue(); + add((byte) codepoint); + } + + @Override + public void appendOR(int c1, int c2) { + assert c1 <= Encodings.ASCII.getMaxValue(); + assert c2 <= Encodings.ASCII.getMaxValue(); + add((byte) (c1 | c2)); + } + + @Override + public void appendXOR(int c1, int c2) { + assert c1 <= Encodings.ASCII.getMaxValue(); + assert c2 <= Encodings.ASCII.getMaxValue(); + add((byte) (c1 ^ c2)); + } + + @Override + public StringASCII materialize() { + return new StringASCII(toArray()); + } +} From 24f580349a6ef52b02fc148ec9406929cb954fb6 Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Fri, 17 Sep 2021 21:15:32 +0000 Subject: [PATCH 025/681] Update truffleruby import. --- vm/mx.vm/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index d674654e2173..21bd52395c5f 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -57,7 +57,7 @@ }, { "name": "truffleruby", - "version": "7dcb07a57591f45c032f463bf4ceec7a49495348", + "version": "bbd2a3362f8e84b9bcda5eda6cd3ad36f15d1966", "dynamic": True, "urls": [ {"url": "https://github.com/oracle/truffleruby.git", "kind": "git"}, From 838ffba4435b58dfe5811eb4356d6a8a54e4d27e Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Sun, 19 Sep 2021 21:21:23 +0200 Subject: [PATCH 026/681] Prepare next dev cycle --- compiler/mx.compiler/suite.py | 2 +- espresso/mx.espresso/suite.py | 2 +- regex/mx.regex/suite.py | 2 +- sdk/mx.sdk/suite.py | 2 +- substratevm/mx.substratevm/suite.py | 2 +- tools/mx.tools/suite.py | 2 +- truffle/external_repos/simplelanguage/pom.xml | 2 +- truffle/external_repos/simplelanguage/sl | 2 +- truffle/external_repos/simpletool/pom.xml | 2 +- truffle/mx.truffle/suite.py | 2 +- vm/mx.vm/suite.py | 2 +- wasm/mx.wasm/suite.py | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index a71c392fd794..c4d7d5abd557 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -4,7 +4,7 @@ "sourceinprojectwhitelist" : [], "groupId" : "org.graalvm.compiler", - "version" : "21.3.0", + "version" : "22.0.0", "release" : False, "url" : "http://www.graalvm.org/", "developer" : { diff --git a/espresso/mx.espresso/suite.py b/espresso/mx.espresso/suite.py index f45444818a1c..030b5f9e1f77 100644 --- a/espresso/mx.espresso/suite.py +++ b/espresso/mx.espresso/suite.py @@ -23,7 +23,7 @@ suite = { "mxversion": "5.280.5", "name": "espresso", - "version" : "21.3.0", + "version" : "22.0.0", "release" : False, "groupId" : "org.graalvm.espresso", "url" : "https://www.graalvm.org/reference-manual/java-on-truffle/", diff --git a/regex/mx.regex/suite.py b/regex/mx.regex/suite.py index 35df7f695662..7b1cfb295a93 100644 --- a/regex/mx.regex/suite.py +++ b/regex/mx.regex/suite.py @@ -43,7 +43,7 @@ "name" : "regex", - "version" : "21.3.0", + "version" : "22.0.0", "release" : False, "groupId" : "org.graalvm.regex", "url" : "http://www.graalvm.org/", diff --git a/sdk/mx.sdk/suite.py b/sdk/mx.sdk/suite.py index e437c7f85251..15bee000c6b5 100644 --- a/sdk/mx.sdk/suite.py +++ b/sdk/mx.sdk/suite.py @@ -41,7 +41,7 @@ suite = { "mxversion" : "5.309.1", "name" : "sdk", - "version" : "21.3.0", + "version" : "22.0.0", "release" : False, "sourceinprojectwhitelist" : [], "url" : "https://github.com/oracle/graal", diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 31e8543fad08..0c863b180c16 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -2,7 +2,7 @@ suite = { "mxversion": "5.308.1", "name": "substratevm", - "version" : "21.3.0", + "version" : "22.0.0", "release" : False, "url" : "https://github.com/oracle/graal/tree/master/substratevm", diff --git a/tools/mx.tools/suite.py b/tools/mx.tools/suite.py index 090f4b1839b9..c1194e2f16f7 100644 --- a/tools/mx.tools/suite.py +++ b/tools/mx.tools/suite.py @@ -26,7 +26,7 @@ "defaultLicense" : "GPLv2-CPE", "groupId" : "org.graalvm.tools", - "version" : "21.3.0", + "version" : "22.0.0", "release" : False, "url" : "http://openjdk.java.net/projects/graal", "developer" : { diff --git a/truffle/external_repos/simplelanguage/pom.xml b/truffle/external_repos/simplelanguage/pom.xml index fcb929984906..dd31d304f740 100644 --- a/truffle/external_repos/simplelanguage/pom.xml +++ b/truffle/external_repos/simplelanguage/pom.xml @@ -48,7 +48,7 @@ UTF-8 jdt_apt - 21.3.0-dev + 22.0.0-dev pom diff --git a/truffle/external_repos/simplelanguage/sl b/truffle/external_repos/simplelanguage/sl index 9a87b90ff32a..5cc73def802d 100755 --- a/truffle/external_repos/simplelanguage/sl +++ b/truffle/external_repos/simplelanguage/sl @@ -41,7 +41,7 @@ # # If you update this number make sure the graalvm.version value in ./pom.xml matches -VERSION="21.3.0-dev" +VERSION="22.0.0-dev" MAIN_CLASS="com.oracle.truffle.sl.launcher.SLMain" SCRIPT_HOME="$(cd "$(dirname "$0")" && pwd -P)" diff --git a/truffle/external_repos/simpletool/pom.xml b/truffle/external_repos/simpletool/pom.xml index 41e9c1cc8690..f34f4be02559 100644 --- a/truffle/external_repos/simpletool/pom.xml +++ b/truffle/external_repos/simpletool/pom.xml @@ -49,7 +49,7 @@ UTF-8 1.8 1.8 - 21.3.0-dev + 22.0.0-dev diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index c926eb0743a0..c7fc6b56b372 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -41,7 +41,7 @@ suite = { "mxversion" : "5.300.4", "name" : "truffle", - "version" : "21.3.0", + "version" : "22.0.0", "release" : False, "groupId" : "org.graalvm.truffle", "sourceinprojectwhitelist" : [], diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 5a0ed0bd459e..3eb70f303099 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -1,6 +1,6 @@ suite = { "name": "vm", - "version" : "21.3.0", + "version" : "22.0.0", "mxversion" : "5.309.2", "release" : False, "groupId" : "org.graalvm", diff --git a/wasm/mx.wasm/suite.py b/wasm/mx.wasm/suite.py index 4bdff093cf08..d7e6ce21cdf2 100644 --- a/wasm/mx.wasm/suite.py +++ b/wasm/mx.wasm/suite.py @@ -42,7 +42,7 @@ "mxversion" : "5.301.0", "name" : "wasm", "groupId" : "org.graalvm.wasm", - "version" : "21.3.0", + "version" : "22.0.0", "versionConflictResolution" : "latest", "url" : "http://graalvm.org/", "developer" : { From bfdae8274fd2730a075d038aad35ce61189011c6 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 23 Aug 2021 08:55:13 +0200 Subject: [PATCH 027/681] compiler: use WorkSnippetID instead snippet info --- .../arraycopy/ArrayCopySnippets.java | 72 ++++++++++++------- .../ArrayCopyWithDelayedLoweringNode.java | 9 ++- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index dea3f0910c52..fe39750896af 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -119,9 +119,6 @@ protected boolean useOriginalArraycopy() { * array copy might be {@linkplain Templates#lower(ArrayCopyNode, boolean, LoweringTool) * expanded}. * - * @param workSnippet is always {@link #exactArraycopyWithSlowPathWork} which calls - * {@link #doExactArraycopyWithSlowPathWork} - * * @see Templates#lower(ArrayCopyNode, boolean, LoweringTool) * @see #exactArraycopyWithSlowPathWork * @see #doExactArraycopyWithSlowPathWork @@ -129,8 +126,8 @@ protected boolean useOriginalArraycopy() { @SuppressWarnings("unused") @Snippet public void arraycopyExactSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, - @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, - @ConstantParameter SnippetCounter elementKindCounter, @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) { + @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, @ConstantParameter SnippetCounter elementKindCounter, + @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck); @@ -140,23 +137,19 @@ public void arraycopyExactSnippet(Object src, int srcPos, Object dest, int destP elementKindCounter.inc(); elementKindCopiedCounter.add(length); - ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind); + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.exactArraycopyWithSlowPathWork, elementKind); } /** * Snippet that performs a stub call for an {@linkplain ArrayCopy#isExact() exact} array copy. * - * @param workSnippet is always {@link #exactArraycopyWithSlowPathWork} which calls - * {@link #doExactArraycopyWithSlowPathWork} - * * @see #exactArraycopyWithSlowPathWork * @see #doExactArraycopyWithSlowPathWork */ - @SuppressWarnings("unused") @Snippet public void arraycopyExactStubCallSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, - @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, - @ConstantParameter SnippetCounter elementKindCounter, @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) { + @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, @ConstantParameter SnippetCounter elementKindCounter, + @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck); @@ -173,38 +166,33 @@ public void arraycopyExactStubCallSnippet(Object src, int srcPos, Object dest, i * Performs an array copy with a type check for every store. At least one of the involved * objects is known to be an object array. Lowering is delayed using an * {@link ArrayCopyWithDelayedLoweringNode}. - * - * @param workSnippet is always {@link #checkcastArraycopyWithSlowPathWork} which calls - * {@link #doCheckcastArraycopyWithSlowPathWork} */ @Snippet public void arraycopyCheckcastSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @ConstantParameter Counters counters, - @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind) { + @ConstantParameter JavaKind elementKind) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck); checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); incrementLengthCounter(length, counters); - ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind); + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.checkcastArraycopyWithSlowPathWork, elementKind); } /** * Performs an array copy using a generic stub. Used when we do not know anything about the * object types. Lowering is delayed using an {@link ArrayCopyWithDelayedLoweringNode}. - * - * @param workSnippet is always {@link #genericArraycopyWithSlowPathWork} */ @Snippet public void arraycopyGenericSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @ConstantParameter Counters counters, - @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind) { + @ConstantParameter JavaKind elementKind) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck); checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); incrementLengthCounter(length, counters); - ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind); + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.genericArraycopyWithSlowPathWork, elementKind); } /** @@ -391,6 +379,27 @@ void createArraycopyCounter(JavaKind kind, Group counters, Group copiedCounters) } } + /** + * Identifies snippets used for {@linkplain ArrayCopyWithDelayedLoweringNode delayed lowering} + * of {@link ArrayCopyNode}. + * + * @see Templates#getSnippet(WorkSnippetID) + */ + public enum WorkSnippetID { + /** + * @see ArrayCopySnippets#exactArraycopyWithSlowPathWork + */ + exactArraycopyWithSlowPathWork, + /** + * @see ArrayCopySnippets#checkcastArraycopyWithSlowPathWork + */ + checkcastArraycopyWithSlowPathWork, + /** + * @see ArrayCopySnippets#genericArraycopyWithSlowPathWork + */ + genericArraycopyWithSlowPathWork; + } + public static class Templates extends SnippetTemplate.AbstractTemplates { private final SnippetInfo arraycopyGenericSnippet; private final SnippetInfo arraycopyExactSnippet; @@ -421,6 +430,18 @@ public Templates(ArrayCopySnippets receiver, OptionValues options, Iterable TYPE = NodeClass.create(ArrayCopyWithDelayedLoweringNode.class); - private final SnippetTemplate.SnippetInfo snippet; + private final ArrayCopySnippets.WorkSnippetID snippet; - public ArrayCopyWithDelayedLoweringNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, SnippetTemplate.SnippetInfo snippet, JavaKind elementKind) { + public ArrayCopyWithDelayedLoweringNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ArrayCopySnippets.WorkSnippetID snippet, JavaKind elementKind) { super(TYPE, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI); assert StampTool.isPointerNonNull(src) && StampTool.isPointerNonNull(dest) : "must have been null checked"; this.snippet = snippet; } @NodeIntrinsic - public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter SnippetTemplate.SnippetInfo snippet, + public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter ArrayCopySnippets.WorkSnippetID snippet, @ConstantNodeParameter JavaKind elementKind); - public SnippetTemplate.SnippetInfo getSnippet() { + public ArrayCopySnippets.WorkSnippetID getSnippet() { return snippet; } From ce178618d054c165ddcb1487e12682100df0249b Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 1 Sep 2021 12:25:49 +0200 Subject: [PATCH 028/681] compiler: ArrayCopyWithDelayedLoweringNode should store its lowering stage --- .../compiler/nodes/StructuredGraph.java | 4 +++ .../arraycopy/ArrayCopySnippets.java | 31 ++++++------------- .../ArrayCopyWithDelayedLoweringNode.java | 21 +++++++------ 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 100cae11097a..981440d03157 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -133,6 +133,10 @@ public boolean areDeoptsFixed() { public boolean requiresValueProxies() { return this != AFTER_FSA; } + + public boolean reachedStage(GuardsStage stage) { + return this.ordinal() >= stage.ordinal(); + } } /** diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index fe39750896af..ebe27004f309 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -48,6 +48,7 @@ import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; @@ -137,7 +138,8 @@ public void arraycopyExactSnippet(Object src, int srcPos, Object dest, int destP elementKindCounter.inc(); elementKindCopiedCounter.add(length); - ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.exactArraycopyWithSlowPathWork, elementKind); + // Don't lower until floating guards are fixed. + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.exactArraycopyWithSlowPathWork, GuardsStage.FIXED_DEOPTS, elementKind); } /** @@ -176,7 +178,8 @@ public void arraycopyCheckcastSnippet(Object src, int srcPos, Object dest, int d checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); incrementLengthCounter(length, counters); - ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.checkcastArraycopyWithSlowPathWork, elementKind); + // Don't lower until frame states are assigned to deoptimization points. + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.checkcastArraycopyWithSlowPathWork, GuardsStage.AFTER_FSA, elementKind); } /** @@ -192,7 +195,8 @@ public void arraycopyGenericSnippet(Object src, int srcPos, Object dest, int des checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); incrementLengthCounter(length, counters); - ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.genericArraycopyWithSlowPathWork, elementKind); + // Don't lower until frame states are assigned to deoptimization points. + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.genericArraycopyWithSlowPathWork, GuardsStage.AFTER_FSA, elementKind); } /** @@ -551,26 +555,11 @@ public void lower(ArrayCopyNode arraycopy, boolean mayExpandThisArraycopy, Lower } public void lower(ArrayCopyWithDelayedLoweringNode arraycopy, LoweringTool tool) { - lower(arraycopy, false, tool); - } - - public void lower(ArrayCopyWithDelayedLoweringNode arraycopy, boolean mayExpandArraycopyLoops, LoweringTool tool) { - StructuredGraph graph = arraycopy.graph(); - - SnippetInfo snippetInfo = getSnippet(arraycopy.getSnippet()); - if (snippetInfo == exactArraycopyWithSlowPathWork && mayExpandArraycopyLoops) { - if (!graph.getGuardsStage().areDeoptsFixed()) { - // Don't lower until floating guards are fixed. - return; - } - } else { - if (!graph.getGuardsStage().areFrameStatesAtDeopts()) { - // Don't lower until frame states are assigned to deoptimization points. - return; - } + if (!arraycopy.reachedLoweringStage()) { + return; } - Arguments args = new Arguments(snippetInfo, graph.getGuardsStage(), tool.getLoweringStage()); + Arguments args = new Arguments(getSnippet(arraycopy.getSnippet()), arraycopy.graph().getGuardsStage(), tool.getLoweringStage()); args.add("src", arraycopy.getSource()); args.add("srcPos", arraycopy.getSourcePosition()); args.add("dest", arraycopy.getDestination()); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java index 62fd8e99c7a3..e16a19f5d65c 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; @@ -41,15 +42,8 @@ * is delayed to avoid unfavorable interaction with other phases (floating guards, frame state * assignment, etc.). * - * Depending on the {@link #snippet}, lowering is delayed until either - * {@linkplain org.graalvm.compiler.nodes.StructuredGraph.GuardsStage#areDeoptsFixed() floating - * guards are fixed} or - * {@linkplain org.graalvm.compiler.nodes.StructuredGraph.GuardsStage#areFrameStatesAtDeopts() frame - * states are assigned to deoptimization points}. See - * {@link ArrayCopySnippets.Templates#lower(ArrayCopyWithDelayedLoweringNode, boolean, org.graalvm.compiler.nodes.spi.LoweringTool)} - * for more details. - * * @see ArrayCopyNode + * @see ArrayCopySnippets */ @NodeInfo(allowedUsageTypes = InputType.Memory) public final class ArrayCopyWithDelayedLoweringNode extends BasicArrayCopyNode { @@ -57,16 +51,19 @@ public final class ArrayCopyWithDelayedLoweringNode extends BasicArrayCopyNode { public static final NodeClass TYPE = NodeClass.create(ArrayCopyWithDelayedLoweringNode.class); private final ArrayCopySnippets.WorkSnippetID snippet; + private final StructuredGraph.GuardsStage delayUntil; - public ArrayCopyWithDelayedLoweringNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ArrayCopySnippets.WorkSnippetID snippet, JavaKind elementKind) { + public ArrayCopyWithDelayedLoweringNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ArrayCopySnippets.WorkSnippetID snippet, + StructuredGraph.GuardsStage delayUntil, JavaKind elementKind) { super(TYPE, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI); assert StampTool.isPointerNonNull(src) && StampTool.isPointerNonNull(dest) : "must have been null checked"; this.snippet = snippet; + this.delayUntil = delayUntil; } @NodeIntrinsic public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter ArrayCopySnippets.WorkSnippetID snippet, - @ConstantNodeParameter JavaKind elementKind); + @ConstantNodeParameter StructuredGraph.GuardsStage delayUntil, @ConstantNodeParameter JavaKind elementKind); public ArrayCopySnippets.WorkSnippetID getSnippet() { return snippet; @@ -75,4 +72,8 @@ public ArrayCopySnippets.WorkSnippetID getSnippet() { public void setBci(int bci) { this.bci = bci; } + + public boolean reachedLoweringStage() { + return graph().getGuardsStage().reachedStage(delayUntil); + } } From 3853dc6c367d4972571fc9d34fad394d2a351f9a Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 1 Sep 2021 13:27:26 +0200 Subject: [PATCH 029/681] compiler: rename arraycopyExactSnippet to delayedExactArraycopyWithSlowPathWork --- .../arraycopy/ArrayCopySnippets.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index ebe27004f309..8501039b1b29 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -118,7 +118,8 @@ protected boolean useOriginalArraycopy() { /** * Snippet that performs an {@linkplain ArrayCopy#isExact() exact} array copy. Used when the * array copy might be {@linkplain Templates#lower(ArrayCopyNode, boolean, LoweringTool) - * expanded}. + * expanded}. Lowering is delayed using an {@link ArrayCopyWithDelayedLoweringNode} which will + * dispatch to {@link #exactArraycopyWithSlowPathWork}. * * @see Templates#lower(ArrayCopyNode, boolean, LoweringTool) * @see #exactArraycopyWithSlowPathWork @@ -126,7 +127,7 @@ protected boolean useOriginalArraycopy() { */ @SuppressWarnings("unused") @Snippet - public void arraycopyExactSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, + public void delayedExactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, @ConstantParameter SnippetCounter elementKindCounter, @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); @@ -144,9 +145,6 @@ public void arraycopyExactSnippet(Object src, int srcPos, Object dest, int destP /** * Snippet that performs a stub call for an {@linkplain ArrayCopy#isExact() exact} array copy. - * - * @see #exactArraycopyWithSlowPathWork - * @see #doExactArraycopyWithSlowPathWork */ @Snippet public void arraycopyExactStubCallSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @@ -214,7 +212,8 @@ public static void arraycopyNativeSnippet(Object src, int srcPos, Object dest, i } /** - * @see #doExactArraycopyWithSlowPathWork + * Inlines a loop that performs an {@linkplain ArrayCopy#isExact() exact} element-by-element + * array copy. The explict loop allows subsequent phases to optimize the code. */ @SuppressWarnings("unused") @Snippet(allowPartialIntrinsicArgumentMismatch = true) @@ -224,8 +223,7 @@ public void exactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, } /** - * Inlines a loop that performs an {@linkplain ArrayCopy#isExact() exact} element-by-element - * array copy. The explict loop allows subsequent phases to optimize the code. + * @see #exactArraycopyWithSlowPathWork */ protected abstract void doExactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters, MetaAccessProvider metaAccess); @@ -406,7 +404,7 @@ public enum WorkSnippetID { public static class Templates extends SnippetTemplate.AbstractTemplates { private final SnippetInfo arraycopyGenericSnippet; - private final SnippetInfo arraycopyExactSnippet; + private final SnippetInfo delayedExactArraycopyWithSlowPathWork; private final SnippetInfo arraycopyExactStubCallSnippet; private final SnippetInfo arraycopyCheckcastSnippet; private final SnippetInfo arraycopyNativeSnippet; @@ -425,7 +423,7 @@ public Templates(ArrayCopySnippets receiver, OptionValues options, Iterable Date: Wed, 1 Sep 2021 13:27:44 +0200 Subject: [PATCH 030/681] compiler: rename arraycopyCheckcastSnippet to delayedCheckcastArraycopySnippet --- .../arraycopy/HotSpotArraycopySnippets.java | 2 +- .../arraycopy/ArrayCopySnippets.java | 45 ++++++++++--------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java index 0bc3530f26d4..89a6ae8ce7c2 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java @@ -116,7 +116,7 @@ protected void doExactArraycopyWithSlowPathWork(Object src, int srcPos, Object d @Override @SuppressWarnings("unused") - protected void doCheckcastArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters) { + protected void doCheckcastArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters) { if (probability(FREQUENT_PROBABILITY, length > 0)) { Object nonNullSrc = PiNode.asNonNullObject(src); Object nonNullDest = PiNode.asNonNullObject(dest); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index 8501039b1b29..6f687f492402 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -165,11 +165,14 @@ public void arraycopyExactStubCallSnippet(Object src, int srcPos, Object dest, i /** * Performs an array copy with a type check for every store. At least one of the involved * objects is known to be an object array. Lowering is delayed using an - * {@link ArrayCopyWithDelayedLoweringNode}. + * {@link ArrayCopyWithDelayedLoweringNode} which will dispatch to + * {@link #checkcastArraycopySnippet}. + * + * @see #checkcastArraycopySnippet */ @Snippet - public void arraycopyCheckcastSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @ConstantParameter Counters counters, - @ConstantParameter JavaKind elementKind) { + public void delayedCheckcastArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, + @ConstantParameter Counters counters, @ConstantParameter JavaKind elementKind) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck); @@ -177,7 +180,7 @@ public void arraycopyCheckcastSnippet(Object src, int srcPos, Object dest, int d incrementLengthCounter(length, counters); // Don't lower until frame states are assigned to deoptimization points. - ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.checkcastArraycopyWithSlowPathWork, GuardsStage.AFTER_FSA, elementKind); + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.checkcastArraycopySnippet, GuardsStage.AFTER_FSA, elementKind); } /** @@ -229,21 +232,19 @@ protected abstract void doExactArraycopyWithSlowPathWork(Object src, int srcPos, MetaAccessProvider metaAccess); /** - * @see #doCheckcastArraycopyWithSlowPathWork + * Performs an array copy via fast checkcast stub. */ @Snippet(allowPartialIntrinsicArgumentMismatch = true) - public void checkcastArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, + public void checkcastArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity arrayLocation, @ConstantParameter Counters counters) { - doCheckcastArraycopyWithSlowPathWork(src, srcPos, dest, destPos, length, elementKind, arrayLocation, counters); + doCheckcastArraycopySnippet(src, srcPos, dest, destPos, length, elementKind, arrayLocation, counters); } /** - * Performs an array copy via {@link CheckcastArrayCopyCallNode}. - * - * @see CheckcastArrayCopyCallNode + * @see #checkcastArraycopySnippet */ - protected abstract void doCheckcastArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters); + protected abstract void doCheckcastArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters); /** * Performs an array copy via {@link GenericArrayCopyCallNode}. @@ -393,9 +394,9 @@ public enum WorkSnippetID { */ exactArraycopyWithSlowPathWork, /** - * @see ArrayCopySnippets#checkcastArraycopyWithSlowPathWork + * @see ArrayCopySnippets#checkcastArraycopySnippet */ - checkcastArraycopyWithSlowPathWork, + checkcastArraycopySnippet, /** * @see ArrayCopySnippets#genericArraycopyWithSlowPathWork */ @@ -406,9 +407,9 @@ public static class Templates extends SnippetTemplate.AbstractTemplates { private final SnippetInfo arraycopyGenericSnippet; private final SnippetInfo delayedExactArraycopyWithSlowPathWork; private final SnippetInfo arraycopyExactStubCallSnippet; - private final SnippetInfo arraycopyCheckcastSnippet; + private final SnippetInfo delayedCheckcastArraycopySnippet; private final SnippetInfo arraycopyNativeSnippet; - private final SnippetInfo checkcastArraycopyWithSlowPathWork; + private final SnippetInfo checkcastArraycopySnippet; private final SnippetInfo genericArraycopyWithSlowPathWork; private final SnippetInfo exactArraycopyWithSlowPathWork; @@ -425,9 +426,9 @@ public Templates(ArrayCopySnippets receiver, OptionValues options, Iterable Date: Wed, 1 Sep 2021 13:27:49 +0200 Subject: [PATCH 031/681] compiler: rename arraycopyGenericSnippet to delayedGenericArraycopySnippet --- .../arraycopy/HotSpotArraycopySnippets.java | 19 ++++++ .../arraycopy/ArrayCopySnippets.java | 61 +++++++++---------- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java index 89a6ae8ce7c2..dc239cdf7a08 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java @@ -33,6 +33,7 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.PiNode; @@ -44,6 +45,7 @@ import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode; import org.graalvm.compiler.replacements.arraycopy.ArrayCopySnippets; import org.graalvm.compiler.replacements.arraycopy.CheckcastArrayCopyCallNode; +import org.graalvm.compiler.replacements.arraycopy.GenericArrayCopyCallNode; import org.graalvm.compiler.word.Word; import org.graalvm.word.LocationIdentity; import org.graalvm.word.Pointer; @@ -146,4 +148,21 @@ protected void doCheckcastArraycopySnippet(Object src, int srcPos, Object dest, } } } + + @Override + protected void doGenericArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters) { + // The length > 0 check should not be placed here because generic array copy stub should + // enforce type check. This is fine performance-wise because this snippet is rarely used. + counters.genericArraycopyDifferentTypeCounter.inc(); + counters.genericArraycopyDifferentTypeCopiedCounter.add(length); + int copiedElements = GenericArrayCopyCallNode.genericArraycopy(src, srcPos, dest, destPos, length); + if (probability(SLOW_PATH_PROBABILITY, copiedElements != 0)) { + /* + * the stub doesn't throw the ArrayStoreException, but returns the number of copied + * elements (xor'd with -1). + */ + copiedElements ^= -1; + System.arraycopy(src, srcPos + copiedElements, dest, destPos + copiedElements, length - copiedElements); + } + } } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index 6f687f492402..6a6231d84daf 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -27,7 +27,6 @@ import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.DEOPT_PROBABILITY; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import java.util.EnumMap; @@ -185,11 +184,14 @@ public void delayedCheckcastArraycopySnippet(Object src, int srcPos, Object dest /** * Performs an array copy using a generic stub. Used when we do not know anything about the - * object types. Lowering is delayed using an {@link ArrayCopyWithDelayedLoweringNode}. + * object types. Lowering is delayed using an {@link ArrayCopyWithDelayedLoweringNode} which + * will dispatch to {@link #genericArraycopySnippet}. + * + * @see #genericArraycopySnippet */ @Snippet - public void arraycopyGenericSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @ConstantParameter Counters counters, - @ConstantParameter JavaKind elementKind) { + public void delayedGenericArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, + @ConstantParameter Counters counters, @ConstantParameter JavaKind elementKind) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck); @@ -197,7 +199,7 @@ public void arraycopyGenericSnippet(Object src, int srcPos, Object dest, int des incrementLengthCounter(length, counters); // Don't lower until frame states are assigned to deoptimization points. - ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.genericArraycopyWithSlowPathWork, GuardsStage.AFTER_FSA, elementKind); + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.genericArraycopySnippet, GuardsStage.AFTER_FSA, elementKind); } /** @@ -247,31 +249,24 @@ public void checkcastArraycopySnippet(Object src, int srcPos, Object dest, int d protected abstract void doCheckcastArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters); /** - * Performs an array copy via {@link GenericArrayCopyCallNode}. + * Performs a generic array copy with all required type and store checks. * - * @see GenericArrayCopyCallNode - * @see #arraycopyGenericSnippet + * @see #delayedGenericArraycopySnippet + * @see #doGenericArraycopySnippet */ @SuppressWarnings("unused") @Snippet(allowPartialIntrinsicArgumentMismatch = true) - public void genericArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, + public void genericArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity arrayLocation, @ConstantParameter Counters counters) { - // The length > 0 check should not be placed here because generic array copy stub should - // enforce type check. This is fine performance-wise because this snippet is rarely used. - counters.genericArraycopyDifferentTypeCounter.inc(); - counters.genericArraycopyDifferentTypeCopiedCounter.add(length); - int copiedElements = GenericArrayCopyCallNode.genericArraycopy(src, srcPos, dest, destPos, length); - if (probability(SLOW_PATH_PROBABILITY, copiedElements != 0)) { - /* - * the stub doesn't throw the ArrayStoreException, but returns the number of copied - * elements (xor'd with -1). - */ - copiedElements ^= -1; - System.arraycopy(src, srcPos + copiedElements, dest, destPos + copiedElements, length - copiedElements); - } + doGenericArraycopySnippet(src, srcPos, dest, destPos, length, elementKind, arrayLocation, counters); } + /** + * @see #genericArraycopySnippet + */ + protected abstract void doGenericArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters); + private static void incrementLengthCounter(int length, Counters counters) { if (!IS_BUILDING_NATIVE_IMAGE) { counters.lengthHistogram.inc(length); @@ -398,19 +393,19 @@ public enum WorkSnippetID { */ checkcastArraycopySnippet, /** - * @see ArrayCopySnippets#genericArraycopyWithSlowPathWork + * @see ArrayCopySnippets#genericArraycopySnippet */ - genericArraycopyWithSlowPathWork; + genericArraycopySnippet; } public static class Templates extends SnippetTemplate.AbstractTemplates { - private final SnippetInfo arraycopyGenericSnippet; + private final SnippetInfo delayedGenericArraycopySnippet; private final SnippetInfo delayedExactArraycopyWithSlowPathWork; private final SnippetInfo arraycopyExactStubCallSnippet; private final SnippetInfo delayedCheckcastArraycopySnippet; private final SnippetInfo arraycopyNativeSnippet; private final SnippetInfo checkcastArraycopySnippet; - private final SnippetInfo genericArraycopyWithSlowPathWork; + private final SnippetInfo genericArraycopySnippet; private final SnippetInfo exactArraycopyWithSlowPathWork; private final boolean useOriginalArraycopy; @@ -423,13 +418,13 @@ public Templates(ArrayCopySnippets receiver, OptionValues options, Iterable Date: Wed, 1 Sep 2021 13:43:26 +0200 Subject: [PATCH 032/681] compiler: rename ArrayCopySnippets#arraycopyNativeSnippet to #arraycopyNativeExceptionSnippet --- .../replacements/arraycopy/ArrayCopySnippets.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index 6a6231d84daf..a86a985288ab 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -48,6 +48,7 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; +import org.graalvm.compiler.nodes.UnreachableNode; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; @@ -207,13 +208,15 @@ public void delayedGenericArraycopySnippet(Object src, int srcPos, Object dest, * only used in cases where we already know that the operation will fail. */ @Snippet - public static void arraycopyNativeSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { + public static void arraycopyNativeExceptionSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { // all checks are done in the native method, so no need to emit additional checks here incrementLengthCounter(length, counters); counters.systemArraycopyCounter.inc(); counters.systemArraycopyCopiedCounter.add(length); System.arraycopy(src, srcPos, dest, destPos, length); + // the call will never return + UnreachableNode.unreachable(); } /** @@ -403,7 +406,7 @@ public static class Templates extends SnippetTemplate.AbstractTemplates { private final SnippetInfo delayedExactArraycopyWithSlowPathWork; private final SnippetInfo arraycopyExactStubCallSnippet; private final SnippetInfo delayedCheckcastArraycopySnippet; - private final SnippetInfo arraycopyNativeSnippet; + private final SnippetInfo arraycopyNativeExceptionSnippet; private final SnippetInfo checkcastArraycopySnippet; private final SnippetInfo genericArraycopySnippet; private final SnippetInfo exactArraycopyWithSlowPathWork; @@ -422,7 +425,7 @@ public Templates(ArrayCopySnippets receiver, OptionValues options, Iterable Date: Mon, 30 Aug 2021 11:58:23 +0200 Subject: [PATCH 033/681] compiler: move GenericArrayCopyCallNode and CheckcastArrayCopyCallNode into hotspot specific project --- .../compiler/hotspot/HotSpotBackend.java | 2 +- .../meta/HotSpotHostForeignCallsProvider.java | 26 +++++++++++++++-- .../arraycopy/CheckcastArrayCopyCallNode.java | 12 +++++--- .../arraycopy/GenericArrayCopyCallNode.java | 8 ++++-- .../arraycopy/HotSpotArraycopySnippets.java | 3 -- .../arraycopy/ArrayCopyCallNode.java | 8 ++---- .../arraycopy/ArrayCopyLookup.java | 28 ------------------- .../meta/SubstrateForeignCallsProvider.java | 9 ------ 8 files changed, 40 insertions(+), 56 deletions(-) rename compiler/src/{org.graalvm.compiler.replacements/src/org/graalvm/compiler => org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot}/replacements/arraycopy/CheckcastArrayCopyCallNode.java (93%) rename compiler/src/{org.graalvm.compiler.replacements/src/org/graalvm/compiler => org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot}/replacements/arraycopy/GenericArrayCopyCallNode.java (92%) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java index 47aeb87f705c..ad8074b5c8d0 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java @@ -30,9 +30,9 @@ import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition.SAFEPOINT; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.NO_LOCATIONS; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.UNSAFE_ARRAYCOPY; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_TOP_LOCATION; -import static org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls.UNSAFE_ARRAYCOPY; import static org.graalvm.word.LocationIdentity.any; import java.util.EnumSet; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 2f5397769357..1f3d18cd84ce 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -114,6 +114,7 @@ import org.graalvm.compiler.hotspot.CompilerRuntimeHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; +import org.graalvm.compiler.hotspot.replacements.arraycopy.CheckcastArrayCopyCallNode; import org.graalvm.compiler.hotspot.stubs.ArrayStoreExceptionStub; import org.graalvm.compiler.hotspot.stubs.ClassCastExceptionStub; import org.graalvm.compiler.hotspot.stubs.CreateExceptionStub; @@ -130,8 +131,8 @@ import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.ArrayIndexOf; +import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.word.Word; @@ -157,6 +158,23 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall public static final HotSpotForeignCallDescriptor INVOKE_STATIC_METHOD_ONE_ARG = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS, "JVMCIRuntime::invoke_static_method_one_arg", long.class, Word.class, Word.class, long.class); + /** + * Signature of an unsafe {@link System#arraycopy} stub. + * + * The signature is equivalent to {@link sun.misc.Unsafe#copyMemory(long, long, long)}. For the + * semantics refer to {@link sun.misc.Unsafe#copyMemory(Object, long, Object, long, long)}. + * + * @see sun.misc.Unsafe#copyMemory + */ + public static final ForeignCallSignature UNSAFE_ARRAYCOPY = new ForeignCallSignature("unsafe_arraycopy", void.class, Word.class, Word.class, Word.class); + /** + * Signature of a generic {@link System#arraycopy} stub. + * + * Instead of throwing an {@link ArrayStoreException}, the stub is expected to return the number + * of copied elements xor'd with {@code -1}. A return value of {@code 0} indicates that the + * operation was successful. + */ + public static final ForeignCallSignature GENERIC_ARRAYCOPY = new ForeignCallSignature("generic_arraycopy", int.class, Word.class, int.class, Word.class, int.class, int.class); public static class TestForeignCalls { public static final HotSpotForeignCallDescriptor BOOLEAN_RETURNS_BOOLEAN = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS, "boolean returns boolean", @@ -217,7 +235,11 @@ protected static void link(Stub stub) { stub.getLinkage().setCompiledStub(stub); } - @Override + /** + * Looks up the call descriptor for a fast checkcast {@link System#arraycopy} stub. + * + * @see CheckcastArrayCopyCallNode + */ public ForeignCallDescriptor lookupCheckcastArraycopyDescriptor(boolean uninit) { return checkcastArraycopyDescriptors[uninit ? 1 : 0]; } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/CheckcastArrayCopyCallNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java similarity index 93% rename from compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/CheckcastArrayCopyCallNode.java rename to compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java index 6c996eb0229e..ab358f9024b9 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/CheckcastArrayCopyCallNode.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java @@ -23,7 +23,7 @@ * questions. */ //JaCoCo Exclude -package org.graalvm.compiler.replacements.arraycopy; +package org.graalvm.compiler.hotspot.replacements.arraycopy; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; @@ -32,6 +32,7 @@ import org.graalvm.compiler.core.common.type.PrimitiveStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; @@ -49,6 +50,8 @@ import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode; +import org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; import org.graalvm.word.LocationIdentity; @@ -60,7 +63,8 @@ * Implements {@link System#arraycopy} via a {@linkplain ForeignCallNode stub call} that performs a * fast {@code CHECKCAST} check. * - * The target of the call is queried via {@link ArrayCopyLookup#lookupCheckcastArraycopyDescriptor}. + * The target of the call is queried via + * {@link HotSpotHostForeignCallsProvider#lookupCheckcastArraycopyDescriptor}. * * Instead of throwing an {@link ArrayStoreException}, the stub is expected to return the number of * copied elements xor'd with {@code -1}. Users of this node are responsible for converting that @@ -76,7 +80,7 @@ public final class CheckcastArrayCopyCallNode extends AbstractMemoryCheckpoint i public static final NodeClass TYPE = NodeClass.create(CheckcastArrayCopyCallNode.class); - private final ArrayCopyForeignCalls foreignCalls; + private final HotSpotHostForeignCallsProvider foreignCalls; private final JavaKind wordKind; @Input ValueNode src; @@ -94,7 +98,7 @@ protected CheckcastArrayCopyCallNode(@InjectedNodeParameter ArrayCopyForeignCall ValueNode destPos, ValueNode length, ValueNode superCheckOffset, ValueNode destElemKlass, boolean uninit) { super(TYPE, StampFactory.forKind(JavaKind.Int)); - this.foreignCalls = foreignCalls; + this.foreignCalls = (HotSpotHostForeignCallsProvider) foreignCalls; this.wordKind = wordTypes.getWordKind(); this.src = src; this.srcPos = srcPos; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/GenericArrayCopyCallNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java similarity index 92% rename from compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/GenericArrayCopyCallNode.java rename to compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java index 2cc41f6a59d3..57b179381d89 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/GenericArrayCopyCallNode.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java @@ -23,15 +23,16 @@ * questions. */ //JaCoCo Exclude -package org.graalvm.compiler.replacements.arraycopy; +package org.graalvm.compiler.hotspot.replacements.arraycopy; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.GENERIC_ARRAYCOPY; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; -import static org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls.GENERIC_ARRAYCOPY; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.GetObjectAddressNode; @@ -42,13 +43,14 @@ import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; /** * Implements {@link System#arraycopy} via a {@link ForeignCallNode call} to a - * {@linkplain ArrayCopyLookup#GENERIC_ARRAYCOPY generic stub}. + * {@linkplain HotSpotHostForeignCallsProvider#GENERIC_ARRAYCOPY generic stub}. * * Instead of throwing an {@link ArrayStoreException}, the stub is expected to return the number of * copied elements xor'd with {@code -1}. Users of this node are responsible for converting that diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java index dc239cdf7a08..c9a3233e99b5 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java @@ -33,7 +33,6 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; -import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.PiNode; @@ -44,8 +43,6 @@ import org.graalvm.compiler.replacements.ReplacementsUtil; import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode; import org.graalvm.compiler.replacements.arraycopy.ArrayCopySnippets; -import org.graalvm.compiler.replacements.arraycopy.CheckcastArrayCopyCallNode; -import org.graalvm.compiler.replacements.arraycopy.GenericArrayCopyCallNode; import org.graalvm.compiler.word.Word; import org.graalvm.word.LocationIdentity; import org.graalvm.word.Pointer; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java index efe3aa2b058a..5621210e8ff3 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java @@ -36,8 +36,6 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; @@ -56,6 +54,8 @@ import org.graalvm.compiler.nodes.memory.MemoryKill; import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.spi.Canonicalizable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.word.WordTypes; @@ -72,10 +72,6 @@ * based on the element type and memory properties. * * The target of the call is queried via {@link ArrayCopyLookup#lookupArraycopyDescriptor}. - * - * @see GenericArrayCopyCallNode A generic {@link System#arraycopy} stub call node. - * @see CheckcastArrayCopyCallNode A {@link System#arraycopy} stub call node that performs a fast - * check cast. */ @NodeInfo(allowedUsageTypes = {Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, SingleMemoryKill, MemoryAccess, Canonicalizable { diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyLookup.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyLookup.java index abad4aa1ccd7..a70088d8c239 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyLookup.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyLookup.java @@ -25,40 +25,12 @@ package org.graalvm.compiler.replacements.arraycopy; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.core.common.spi.ForeignCallSignature; -import org.graalvm.compiler.word.Word; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; public interface ArrayCopyLookup { - /** - * Signature of an unsafe {@link System#arraycopy} stub. - * - * The signature is equivalent to {@link sun.misc.Unsafe#copyMemory(long, long, long)}. For the - * semantics refer to {@link sun.misc.Unsafe#copyMemory(Object, long, Object, long, long)}. - * - * @see sun.misc.Unsafe#copyMemory - */ - ForeignCallSignature UNSAFE_ARRAYCOPY = new ForeignCallSignature("unsafe_arraycopy", void.class, Word.class, Word.class, Word.class); - - /** - * Signature of a generic {@link System#arraycopy} stub. - * - * Instead of throwing an {@link ArrayStoreException}, the stub is expected to return the number - * of copied elements xor'd with {@code -1}. A return value of {@code 0} indicates that the - * operation was successful. - */ - ForeignCallSignature GENERIC_ARRAYCOPY = new ForeignCallSignature("generic_arraycopy", int.class, Word.class, int.class, Word.class, int.class, int.class); - - /** - * Looks up the call descriptor for a fast checkcast {@link System#arraycopy} stub. - * - * @see CheckcastArrayCopyCallNode - */ - ForeignCallDescriptor lookupCheckcastArraycopyDescriptor(boolean uninit); - /** * Looks up the call descriptor for a specialized {@link System#arraycopy} stub. * diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateForeignCallsProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateForeignCallsProvider.java index e0aba1ccdc70..ba47837024ea 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateForeignCallsProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateForeignCallsProvider.java @@ -98,15 +98,6 @@ public void registerArrayCopyForeignCallsDelegate(ArrayCopyLookup arraycopyForei this.arrayCopyLookup = arraycopyForeignCalls; } - @Override - public ForeignCallDescriptor lookupCheckcastArraycopyDescriptor(boolean uninit) { - if (arrayCopyLookup != null) { - return arrayCopyLookup.lookupCheckcastArraycopyDescriptor(uninit); - } else { - throw VMError.unsupportedFeature("Fast checkcast ArrayCopy not supported yet."); - } - } - @Override public ForeignCallDescriptor lookupArraycopyDescriptor(JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, LocationIdentity killedLocation) { if (arrayCopyLookup != null) { From 4dbd8bde23d10a5be02dbe49416b73adcec172db Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 30 Aug 2021 10:58:41 +0200 Subject: [PATCH 034/681] compiler: document lowering strategies of ArrayCopySnippets --- .../arraycopy/ArrayCopySnippets.java | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index a86a985288ab..fc37e92ed2b4 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -77,6 +77,37 @@ /** * Snippets for lowering {@link System#arraycopy}. + * + *
    + *
  • {@link #arraycopyNativeExceptionSnippet}: this snippet is used when the array copy is know to + * fail, either because at least on of the objects is not an array, or one is an object array and + * the other one a primitive array.
  • + *
  • {@link #arraycopyExactStubCallSnippet}: this snippet is used for array copies that do not + * require a store check. This is the case if the array copy is either + * {@linkplain ArrayCopy#isExact() exact}, i.e., we can prove that the source array type is + * assignable to the destination array types, or if one of the objects is a primitive array (and the + * other is unknown). In the latter case, it is sufficient to dynamically check that the array types + * are the same. No store check is needed.
  • + *
  • {@link #exactArraycopyWithSlowPathWork}: if we can do an + * {@linkplain #arraycopyExactStubCallSnippet array copy without store check}, it might be better to + * inline the copy loop to allow further compiler phases to optimize the code, instead of doing a + * stub call. This is only done if {@code mayExpandThisArraycopy} is {@code true}. Lowering is + * delayed until {@linkplain GuardsStage#FIXED_DEOPTS deopts are fixed} using + * {@link #delayedExactArraycopyWithSlowPathWork}.
  • + *
  • {@link #checkcastArraycopySnippet}: this snippet is used if at least one of the objects is an + * object array, but the compatibility of source and destination cannot be proven statically. We + * need to perform a store check on every element. Lowering is delayed {@link GuardsStage#AFTER_FSA + * after framestate assignment} via {@link #delayedCheckcastArraycopySnippet})
  • + *
  • {@link #genericArraycopySnippet}: this snippet is used if we have no information about the + * types of the objects. The snippet needs to perform all required type and store checks. Lowering + * is delayed {@link GuardsStage#AFTER_FSA after framestate assignment} via + * {@link #delayedGenericArraycopySnippet}.
  • + *
+ * + * See {@link Templates#lower(ArrayCopyNode, boolean, LoweringTool)} for the implementation details + * of the lowering strategies. + * + * @see Templates#lower(ArrayCopyNode, boolean, LoweringTool) */ public abstract class ArrayCopySnippets implements Snippets { @@ -453,10 +484,13 @@ public void lower(ArrayCopyNode arraycopy, LoweringTool tool) { } /** - * Lowers an {@link ArrayCopyNode}. + * Lowers an {@link ArrayCopyNode}. See the documentation of {@link ArrayCopySnippets} for + * an overview of the lowering strategies. * * @param mayExpandThisArraycopy {@code true} if the array copy might be expanded to a copy * loop. + * + * @see ArrayCopySnippets */ public void lower(ArrayCopyNode arraycopy, boolean mayExpandThisArraycopy, LoweringTool tool) { JavaKind elementKind = ArrayCopy.selectComponentKind(arraycopy); From 4804a0ba89ee791aa0ceae805fb268dfa1080b2f Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 1 Sep 2021 09:28:25 +0200 Subject: [PATCH 035/681] compiler: make INJECTED_META_ACCESS accessible in subclasses --- .../replacements/arraycopy/HotSpotArraycopySnippets.java | 8 +++----- .../replacements/arraycopy/ArrayCopySnippets.java | 7 +++---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java index c9a3233e99b5..c9a40828622f 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java @@ -49,7 +49,6 @@ import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; public class HotSpotArraycopySnippets extends ArrayCopySnippets { @@ -91,10 +90,9 @@ protected int heapWordSize() { } @Override - protected void doExactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters, - MetaAccessProvider metaAccess) { - int scale = ReplacementsUtil.arrayIndexScale(metaAccess, elementKind); - int arrayBaseOffset = ReplacementsUtil.getArrayBaseOffset(metaAccess, elementKind); + protected void doExactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters) { + int scale = ReplacementsUtil.arrayIndexScale(INJECTED_META_ACCESS, elementKind); + int arrayBaseOffset = ReplacementsUtil.getArrayBaseOffset(INJECTED_META_ACCESS, elementKind); long sourceOffset = arrayBaseOffset + (long) srcPos * scale; long destOffset = arrayBaseOffset + (long) destPos * scale; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index fc37e92ed2b4..00f7218afade 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -123,7 +123,7 @@ private enum ArrayCopyTypeCheck { } /** Marker value for the {@link InjectedParameter} injected parameter. */ - static final MetaAccessProvider INJECTED_META_ACCESS = null; + protected static final MetaAccessProvider INJECTED_META_ACCESS = null; /** * Checks whether the hubs for the given objects are equal. The objects must be non-null. @@ -258,14 +258,13 @@ public static void arraycopyNativeExceptionSnippet(Object src, int srcPos, Objec @Snippet(allowPartialIntrinsicArgumentMismatch = true) public void exactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity arrayLocation, @ConstantParameter Counters counters) { - doExactArraycopyWithSlowPathWork(src, srcPos, dest, destPos, length, elementKind, arrayLocation, counters, INJECTED_META_ACCESS); + doExactArraycopyWithSlowPathWork(src, srcPos, dest, destPos, length, elementKind, arrayLocation, counters); } /** * @see #exactArraycopyWithSlowPathWork */ - protected abstract void doExactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters, - MetaAccessProvider metaAccess); + protected abstract void doExactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters); /** * Performs an array copy via fast checkcast stub. From ef0c03ac149f12567159102c9f7ca3ecad8321cf Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 1 Sep 2021 14:41:22 +0200 Subject: [PATCH 036/681] compiler: fix ArrayCopyIntrinsificationTest Javadoc --- .../compiler/hotspot/test/ArrayCopyIntrinsificationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java index 117014cbff43..f13944ee997a 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java @@ -163,7 +163,7 @@ public void testObject() { } /** - * Tests {@link ArrayCopySnippets#arraycopyGenericSnippet} with checkcast. + * Tests {@link ArrayCopySnippets#genericArraycopySnippet} with checkcast. */ @Test public void testArrayStoreException() { From 841650f73e892f7a84f5121fb4b0431fe51a631c Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 2 Sep 2021 16:20:52 +0200 Subject: [PATCH 037/681] compiler: fix Javadoc typos in ArrayCopySnippets --- .../hotspot/meta/HotSpotHostForeignCallsProvider.java | 1 + .../replacements/arraycopy/ArrayCopySnippets.java | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 1f3d18cd84ce..ac90f8639539 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -167,6 +167,7 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall * @see sun.misc.Unsafe#copyMemory */ public static final ForeignCallSignature UNSAFE_ARRAYCOPY = new ForeignCallSignature("unsafe_arraycopy", void.class, Word.class, Word.class, Word.class); + /** * Signature of a generic {@link System#arraycopy} stub. * diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index 00f7218afade..2d0561ecd308 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -80,12 +80,12 @@ * *
    *
  • {@link #arraycopyNativeExceptionSnippet}: this snippet is used when the array copy is know to - * fail, either because at least on of the objects is not an array, or one is an object array and - * the other one a primitive array.
  • + * throw an exception, either because at least one of the objects is not an array, or one is an + * object array and the other one a primitive array. *
  • {@link #arraycopyExactStubCallSnippet}: this snippet is used for array copies that do not * require a store check. This is the case if the array copy is either * {@linkplain ArrayCopy#isExact() exact}, i.e., we can prove that the source array type is - * assignable to the destination array types, or if one of the objects is a primitive array (and the + * assignable to the destination array type, or if one of the objects is a primitive array (and the * other is unknown). In the latter case, it is sufficient to dynamically check that the array types * are the same. No store check is needed.
  • *
  • {@link #exactArraycopyWithSlowPathWork}: if we can do an @@ -236,7 +236,7 @@ public void delayedGenericArraycopySnippet(Object src, int srcPos, Object dest, /** * Performs an array copy using the original {@link System#arraycopy} call. Currently, this is - * only used in cases where we already know that the operation will fail. + * only used in cases where we already know that the operation will throw an exception. */ @Snippet public static void arraycopyNativeExceptionSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { From 5bd9d0d9066ef0ab1eedfb501f53d0db49dc6f15 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 2 Sep 2021 16:24:49 +0200 Subject: [PATCH 038/681] compiler: rename ArrayCopySnippets#delayedExactArraycopyWithSlowPathWork to delayedExactArraycopyWithExpandedLoopSnippet --- .../arraycopy/HotSpotArraycopySnippets.java | 2 +- .../arraycopy/ArrayCopySnippets.java | 45 ++++++++++--------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java index c9a40828622f..c854699812d0 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java @@ -90,7 +90,7 @@ protected int heapWordSize() { } @Override - protected void doExactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters) { + protected void doExactArraycopyWithExpandedLoopSnippet(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters) { int scale = ReplacementsUtil.arrayIndexScale(INJECTED_META_ACCESS, elementKind); int arrayBaseOffset = ReplacementsUtil.getArrayBaseOffset(INJECTED_META_ACCESS, elementKind); long sourceOffset = arrayBaseOffset + (long) srcPos * scale; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index 2d0561ecd308..a238beec2dcf 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -88,12 +88,12 @@ * assignable to the destination array type, or if one of the objects is a primitive array (and the * other is unknown). In the latter case, it is sufficient to dynamically check that the array types * are the same. No store check is needed.
  • - *
  • {@link #exactArraycopyWithSlowPathWork}: if we can do an + *
  • {@link #exactArraycopyWithExpandedLoopSnippet}: if we can do an * {@linkplain #arraycopyExactStubCallSnippet array copy without store check}, it might be better to * inline the copy loop to allow further compiler phases to optimize the code, instead of doing a * stub call. This is only done if {@code mayExpandThisArraycopy} is {@code true}. Lowering is * delayed until {@linkplain GuardsStage#FIXED_DEOPTS deopts are fixed} using - * {@link #delayedExactArraycopyWithSlowPathWork}.
  • + * {@link #delayedExactArraycopyWithExpandedLoopSnippet}. *
  • {@link #checkcastArraycopySnippet}: this snippet is used if at least one of the objects is an * object array, but the compatibility of source and destination cannot be proven statically. We * need to perform a store check on every element. Lowering is delayed {@link GuardsStage#AFTER_FSA @@ -150,15 +150,15 @@ protected boolean useOriginalArraycopy() { * Snippet that performs an {@linkplain ArrayCopy#isExact() exact} array copy. Used when the * array copy might be {@linkplain Templates#lower(ArrayCopyNode, boolean, LoweringTool) * expanded}. Lowering is delayed using an {@link ArrayCopyWithDelayedLoweringNode} which will - * dispatch to {@link #exactArraycopyWithSlowPathWork}. + * dispatch to {@link #exactArraycopyWithExpandedLoopSnippet}. * * @see Templates#lower(ArrayCopyNode, boolean, LoweringTool) - * @see #exactArraycopyWithSlowPathWork - * @see #doExactArraycopyWithSlowPathWork + * @see #exactArraycopyWithExpandedLoopSnippet + * @see #doExactArraycopyWithExpandedLoopSnippet */ @SuppressWarnings("unused") @Snippet - public void delayedExactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, + public void delayedExactArraycopyWithExpandedLoopSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, @ConstantParameter SnippetCounter elementKindCounter, @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); @@ -171,7 +171,7 @@ public void delayedExactArraycopyWithSlowPathWork(Object src, int srcPos, Object elementKindCopiedCounter.add(length); // Don't lower until floating guards are fixed. - ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.exactArraycopyWithSlowPathWork, GuardsStage.FIXED_DEOPTS, elementKind); + ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, WorkSnippetID.exactArraycopyWithExpandedLoopSnippet, GuardsStage.FIXED_DEOPTS, elementKind); } /** @@ -256,15 +256,16 @@ public static void arraycopyNativeExceptionSnippet(Object src, int srcPos, Objec */ @SuppressWarnings("unused") @Snippet(allowPartialIntrinsicArgumentMismatch = true) - public void exactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity arrayLocation, - @ConstantParameter Counters counters) { - doExactArraycopyWithSlowPathWork(src, srcPos, dest, destPos, length, elementKind, arrayLocation, counters); + public void exactArraycopyWithExpandedLoopSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, + @ConstantParameter LocationIdentity arrayLocation, @ConstantParameter Counters counters) { + doExactArraycopyWithExpandedLoopSnippet(src, srcPos, dest, destPos, length, elementKind, arrayLocation, counters); } /** - * @see #exactArraycopyWithSlowPathWork + * @see #exactArraycopyWithExpandedLoopSnippet */ - protected abstract void doExactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters); + protected abstract void doExactArraycopyWithExpandedLoopSnippet(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, + Counters counters); /** * Performs an array copy via fast checkcast stub. @@ -418,9 +419,9 @@ void createArraycopyCounter(JavaKind kind, Group counters, Group copiedCounters) */ public enum WorkSnippetID { /** - * @see ArrayCopySnippets#exactArraycopyWithSlowPathWork + * @see ArrayCopySnippets#exactArraycopyWithExpandedLoopSnippet */ - exactArraycopyWithSlowPathWork, + exactArraycopyWithExpandedLoopSnippet, /** * @see ArrayCopySnippets#checkcastArraycopySnippet */ @@ -433,13 +434,13 @@ public enum WorkSnippetID { public static class Templates extends SnippetTemplate.AbstractTemplates { private final SnippetInfo delayedGenericArraycopySnippet; - private final SnippetInfo delayedExactArraycopyWithSlowPathWork; + private final SnippetInfo delayedExactArraycopyWithExpandedLoopSnippet; private final SnippetInfo arraycopyExactStubCallSnippet; private final SnippetInfo delayedCheckcastArraycopySnippet; private final SnippetInfo arraycopyNativeExceptionSnippet; private final SnippetInfo checkcastArraycopySnippet; private final SnippetInfo genericArraycopySnippet; - private final SnippetInfo exactArraycopyWithSlowPathWork; + private final SnippetInfo exactArraycopyWithExpandedLoopSnippet; private final boolean useOriginalArraycopy; private ResolvedJavaMethod originalArraycopy; @@ -452,19 +453,19 @@ public Templates(ArrayCopySnippets receiver, OptionValues options, Iterable Date: Fri, 3 Sep 2021 12:18:48 +0200 Subject: [PATCH 039/681] compiler: remove obsolete comment from HotSpotArraycopySnippets#doGenericArraycopySnippet --- .../replacements/arraycopy/HotSpotArraycopySnippets.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java index c854699812d0..573ebaa88924 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/HotSpotArraycopySnippets.java @@ -146,8 +146,6 @@ protected void doCheckcastArraycopySnippet(Object src, int srcPos, Object dest, @Override protected void doGenericArraycopySnippet(Object src, int srcPos, Object dest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation, Counters counters) { - // The length > 0 check should not be placed here because generic array copy stub should - // enforce type check. This is fine performance-wise because this snippet is rarely used. counters.genericArraycopyDifferentTypeCounter.inc(); counters.genericArraycopyDifferentTypeCopiedCounter.add(length); int copiedElements = GenericArrayCopyCallNode.genericArraycopy(src, srcPos, dest, destPos, length); From d153cede3b4969de9a690c263fa0c14180d3533f Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 7 Sep 2021 10:25:40 +0200 Subject: [PATCH 040/681] compiler: rename ArrayCopyWithDelayedLoweringNode#reachedRequiredLoweringStage --- .../compiler/replacements/arraycopy/ArrayCopySnippets.java | 2 +- .../arraycopy/ArrayCopyWithDelayedLoweringNode.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index a238beec2dcf..e5c31ad0b7d5 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -586,7 +586,7 @@ public void lower(ArrayCopyNode arraycopy, boolean mayExpandThisArraycopy, Lower } public void lower(ArrayCopyWithDelayedLoweringNode arraycopy, LoweringTool tool) { - if (!arraycopy.reachedLoweringStage()) { + if (!arraycopy.reachedRequiredLoweringStage()) { return; } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java index e16a19f5d65c..299bbb1fbfd5 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java @@ -73,7 +73,7 @@ public void setBci(int bci) { this.bci = bci; } - public boolean reachedLoweringStage() { + public boolean reachedRequiredLoweringStage() { return graph().getGuardsStage().reachedStage(delayUntil); } } From f8904bf8692dd249a53ac96aabd138017d186bca Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 7 Sep 2021 10:26:51 +0200 Subject: [PATCH 041/681] compiler: reformat HotSpotHostForeignCallsProvider --- .../compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index ac90f8639539..721104ea0a12 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -158,6 +158,7 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall public static final HotSpotForeignCallDescriptor INVOKE_STATIC_METHOD_ONE_ARG = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS, "JVMCIRuntime::invoke_static_method_one_arg", long.class, Word.class, Word.class, long.class); + /** * Signature of an unsafe {@link System#arraycopy} stub. * From 914af4ca23e6d540d879ad3face4482f1603c930 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 7 Sep 2021 10:47:40 +0200 Subject: [PATCH 042/681] compiler: rename StructuredGraph#reachedGuardStage --- .../src/org/graalvm/compiler/nodes/StructuredGraph.java | 2 +- .../arraycopy/ArrayCopyWithDelayedLoweringNode.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 981440d03157..27e3a26e1b5f 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -134,7 +134,7 @@ public boolean requiresValueProxies() { return this != AFTER_FSA; } - public boolean reachedStage(GuardsStage stage) { + public boolean reachedGuardsStage(GuardsStage stage) { return this.ordinal() >= stage.ordinal(); } } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java index 299bbb1fbfd5..ad387562b569 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java @@ -74,6 +74,6 @@ public void setBci(int bci) { } public boolean reachedRequiredLoweringStage() { - return graph().getGuardsStage().reachedStage(delayUntil); + return graph().getGuardsStage().reachedGuardsStage(delayUntil); } } From 6f4612494641fc38b9a61f0c626052ec02827d70 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 20 Sep 2021 09:29:26 +0200 Subject: [PATCH 043/681] compiler: fix typo in ArrayCopySnippets Javadoc --- .../compiler/replacements/arraycopy/ArrayCopySnippets.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index e5c31ad0b7d5..3aa0459427d2 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -79,8 +79,8 @@ * Snippets for lowering {@link System#arraycopy}. * *
      - *
    • {@link #arraycopyNativeExceptionSnippet}: this snippet is used when the array copy is know to - * throw an exception, either because at least one of the objects is not an array, or one is an + *
    • {@link #arraycopyNativeExceptionSnippet}: this snippet is used when the array copy is known + * to throw an exception, either because at least one of the objects is not an array, or one is an * object array and the other one a primitive array.
    • *
    • {@link #arraycopyExactStubCallSnippet}: this snippet is used for array copies that do not * require a store check. This is the case if the array copy is either From c97ad05262851506b5337acf8b862de0b16eacfa Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Jul 2021 13:43:19 +0200 Subject: [PATCH 044/681] compiler: print killedLocationIdentities in dumps --- .../graalvm/compiler/printer/BinaryGraphPrinter.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java index 343a6463af3c..200566ee9404 100644 --- a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java +++ b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java @@ -64,6 +64,8 @@ import org.graalvm.compiler.nodes.VirtualState; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.graalvm.compiler.nodes.memory.MultiMemoryKill; +import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.nodes.util.JavaConstantFormattable; import org.graalvm.graphio.GraphBlocks; import org.graalvm.graphio.GraphElements; @@ -271,6 +273,14 @@ public void nodeProperties(GraphInfo info, Node node, Map props) } props.put("category", "floating"); } + + if (node instanceof SingleMemoryKill) { + props.put("killedLocationIdentity", ((SingleMemoryKill) node).getKilledLocationIdentity()); + } + if (node instanceof MultiMemoryKill) { + props.put("killedLocationIdentities", ((MultiMemoryKill) node).getKilledLocationIdentities()); + } + if (getSnippetReflectionProvider() != null) { for (Map.Entry prop : props.entrySet()) { if (prop.getValue() instanceof JavaConstantFormattable) { From fc69cefdfad42fe08b9a8d895cf7ed68302b8c30 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Jul 2021 11:22:25 +0200 Subject: [PATCH 045/681] compiler: remove unused method MacroStateSplitNode#replaceSnippetInvokes --- .../replacements/nodes/MacroStateSplitNode.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java index c6596ba6c23c..3245de4faee6 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java @@ -74,18 +74,4 @@ public boolean hasSideEffect() { public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } - - protected void replaceSnippetInvokes(StructuredGraph snippetGraph) { - for (MethodCallTargetNode call : snippetGraph.getNodes(MethodCallTargetNode.TYPE)) { - Invoke invoke = call.invoke(); - if (!call.targetMethod().equals(getTargetMethod())) { - throw new GraalError("unexpected invoke %s in snippet", getClass().getSimpleName()); - } - assert invoke.stateAfter().bci == BytecodeFrame.AFTER_BCI; - // Here we need to fix the bci of the invoke - InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), bci(), invoke.getKilledLocationIdentity())); - newInvoke.setStateAfter(invoke.stateAfter()); - snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke); - } - } } From 4c23ecd11157b7e70754b1c830588ea67534d432 Mon Sep 17 00:00:00 2001 From: Michael Simacek Date: Mon, 26 Jul 2021 19:40:23 +0200 Subject: [PATCH 046/681] Avoid building multiple images for python benchmarks --- vm/mx.vm/ce-python | 3 +-- vm/mx.vm/mx_vm.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/vm/mx.vm/ce-python b/vm/mx.vm/ce-python index a1b48d31433c..c7ea6e78e539 100644 --- a/vm/mx.vm/ce-python +++ b/vm/mx.vm/ce-python @@ -1,4 +1,3 @@ # Do not modify this env file without updating the Graal.Python benchmark builders DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-js,graalpython -FORCE_BASH_LAUNCHERS=polyglot,polybench -SKIP_LIBRARIES=polyglot +NATIVE_IMAGES=graalpython,lib:jvmcicompiler diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index 46b09a207f27..a1f7a979916f 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -131,7 +131,7 @@ ce_components = ['bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'poly', 'polynative', 'pro', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] ce_complete_components = ['bpolyglot', 'cmp', 'cov', 'dap', 'ejvm', 'gu', 'gvm', 'gwa', 'ins', 'insight', 'insightheap', 'java', 'js', 'lg', 'libpoly', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nil', 'njs', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rby', 'rbyl', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] ce_ruby_components = ['cmp', 'cov', 'dap', 'gvm', 'ins', 'insight', 'insightheap', 'lg', 'llp', 'llrc', 'llrn', 'lsp', 'nfi', 'pro', 'rby', 'rbyl', 'rgx', 'sdk', 'svm', 'svmnfi', 'tfl', 'tflm', 'vvm'] -ce_python_components = ['bpolybench', 'bpolyglot', 'cmp', 'cov', 'dap', 'dis', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llmulrl', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nic', 'nil', 'nju', 'pbm', 'pmh', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] +ce_python_components = ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgu', 'bjs', 'blli', 'bllimul', 'bnative-image', 'bnative-image-configure', 'bpolybench', 'bpolyglot', 'cmp', 'cov', 'dap', 'dis', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llmulrl', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nic', 'nil', 'nju', 'pbm', 'pmh', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svml', 'svmnfi', 'tfl', 'tflm', 'vvm'] ce_fastr_components = ce_components + ['R', 'llp', 'bRMain'] ce_no_native_components = ['bgu', 'bjs', 'blli', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgraalvm-native-binutil', 'bnative-image', 'bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lsp', 'nfi', 'ni', 'nil', 'polynative', 'pro', 'rgx', 'sdk', 'llrc', 'llrn', 'llrl', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'libpoly', 'poly', 'vvm'] From 5d50cfcd1b4f3033c3fd0ee89a9ea2836b717a89 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Jul 2021 11:38:35 +0200 Subject: [PATCH 047/681] compiler: merge MacroStateSplitNode into MacroNode Every MacroNode is a StateSplit because every Invoke is a StateSplit. --- .../replacements/CallSiteTargetNode.java | 4 +- .../nodes/BasicObjectCloneNode.java | 2 +- .../replacements/nodes/MacroInvokable.java | 3 +- .../replacements/nodes/MacroNode.java | 28 ++++++- .../nodes/MacroStateSplitNode.java | 77 ------------------- .../MacroStateSplitWithExceptionNode.java | 4 +- .../replacements/nodes/MethodHandleNode.java | 2 +- .../nodes/ProfileBooleanNode.java | 2 +- .../nodes/PureFunctionMacroNode.java | 2 +- .../nodes/ReflectionGetCallerClassNode.java | 2 +- .../nodes/VirtualizableInvokeMacroNode.java | 2 +- 11 files changed, 36 insertions(+), 92 deletions(-) delete mode 100644 compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CallSiteTargetNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CallSiteTargetNode.java index 51eab2f950e9..774c74f2ea86 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CallSiteTargetNode.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CallSiteTargetNode.java @@ -34,7 +34,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.replacements.nodes.MacroStateSplitNode; +import org.graalvm.compiler.replacements.nodes.MacroNode; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.Assumptions; @@ -42,7 +42,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; @NodeInfo -public final class CallSiteTargetNode extends MacroStateSplitNode implements Canonicalizable, Lowerable { +public final class CallSiteTargetNode extends MacroNode implements Canonicalizable, Lowerable { public static final NodeClass TYPE = NodeClass.create(CallSiteTargetNode.class); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java index fcbc4dc80e08..7cb6319c1ec9 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java @@ -32,7 +32,7 @@ import org.graalvm.compiler.nodes.ValueNode; @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, cyclesRationale = "see rationale in MacroNode", size = SIZE_8) -public abstract class BasicObjectCloneNode extends MacroStateSplitNode implements ObjectClone { +public abstract class BasicObjectCloneNode extends MacroNode implements ObjectClone { public static final NodeClass TYPE = NodeClass.create(BasicObjectCloneNode.class); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java index 093b1b7cabb6..c0c09e76c9ec 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java @@ -57,8 +57,7 @@ * used as a replacement.
    • *
    • If a {@link MethodSubstitution} for the target method is found, this substitution is used as * a replacement.
    • - *
    • Otherwise, the macro node is replaced with an {@link InvokeNode}. Note that this is only - * possible if the macro node is a {@link MacroStateSplitNode}.
    • + *
    • Otherwise, the macro node is replaced with an {@link InvokeNode}.
    • *
    */ public interface MacroInvokable extends Invokable, Lowerable { diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java index c5dfbe023d47..01443e1c876c 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.FixedNode; @@ -40,9 +41,11 @@ import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeNode; +import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; @@ -57,10 +60,11 @@ size = SIZE_UNKNOWN, sizeRationale = "If this node is not optimized away it will be lowered to a call, which we cannot estimate") //@formatter:on -public abstract class MacroNode extends FixedWithNextNode implements MacroInvokable { +public abstract class MacroNode extends FixedWithNextNode implements MacroInvokable, StateSplit, SingleMemoryKill { public static final NodeClass TYPE = NodeClass.create(MacroNode.class); @Input protected NodeInputList arguments; + @OptionalInput(InputType.State) protected FrameState stateAfter; protected final int bci; protected final ResolvedJavaMethod callerMethod; @@ -154,8 +158,26 @@ public InvokeKind getInvokeKind() { return invokeKind; } - protected FrameState stateAfter() { - return null; + @Override + public FrameState stateAfter() { + return stateAfter; + } + + @Override + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + @Override + public boolean hasSideEffect() { + return true; + } + + @Override + public LocationIdentity getKilledLocationIdentity() { + return LocationIdentity.any(); } @Override diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java deleted file mode 100644 index 3245de4faee6..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2013, 2020, 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 org.graalvm.compiler.replacements.nodes; - -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.Invoke; -import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.nodes.StateSplit; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.java.MethodCallTargetNode; -import org.graalvm.compiler.nodes.memory.MemoryKill; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.word.LocationIdentity; - -import jdk.vm.ci.code.BytecodeFrame; - -/** - * This is an extension of {@link MacroNode} that is a {@link StateSplit} and a {@link MemoryKill}. - */ -@NodeInfo -public abstract class MacroStateSplitNode extends MacroNode implements StateSplit, SingleMemoryKill { - - public static final NodeClass TYPE = NodeClass.create(MacroStateSplitNode.class); - @OptionalInput(InputType.State) protected FrameState stateAfter; - - protected MacroStateSplitNode(NodeClass c, MacroParams p) { - super(c, p); - } - - @Override - public FrameState stateAfter() { - return stateAfter; - } - - @Override - public void setStateAfter(FrameState x) { - assert x == null || x.isAlive() : "frame state must be in a graph"; - updateUsages(stateAfter, x); - stateAfter = x; - } - - @Override - public boolean hasSideEffect() { - return true; - } - - @Override - public LocationIdentity getKilledLocationIdentity() { - return LocationIdentity.any(); - } -} diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitWithExceptionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitWithExceptionNode.java index 29cf0e41362e..d9a88896bc1a 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitWithExceptionNode.java @@ -52,12 +52,12 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; /** - * This duplicates a {@link MacroStateSplitNode} using {@link WithExceptionNode} as a base class. + * This duplicates a {@link MacroNode} using {@link WithExceptionNode} as a base class. * * See the documentation of {@link MacroInvokable} for more information. * * @see MacroInvokable - * @see MacroStateSplitNode + * @see MacroNode */ //@formatter:off @NodeInfo(cycles = CYCLES_UNKNOWN, diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java index c925cb20beec..abd90e9ac8e9 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java @@ -76,7 +76,7 @@ * Node for invocation methods defined on the class {@link MethodHandle}. */ @NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "see MacroNode", size = SIZE_UNKNOWN, sizeRationale = "see MacroNode") -public final class MethodHandleNode extends MacroStateSplitNode implements Simplifiable { +public final class MethodHandleNode extends MacroNode implements Simplifiable { public static final NodeClass TYPE = NodeClass.create(MethodHandleNode.class); protected final IntrinsicMethod intrinsicMethod; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ProfileBooleanNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ProfileBooleanNode.java index 478bcdf8e05e..07edfde9db91 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ProfileBooleanNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ProfileBooleanNode.java @@ -46,7 +46,7 @@ import jdk.vm.ci.meta.JavaConstant; @NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) -public class ProfileBooleanNode extends MacroStateSplitNode implements Simplifiable { +public class ProfileBooleanNode extends MacroNode implements Simplifiable { public static final NodeClass TYPE = NodeClass.create(ProfileBooleanNode.class); private final ConstantReflectionProvider constantProvider; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/PureFunctionMacroNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/PureFunctionMacroNode.java index feaaf177c047..3e0ca1fdcd5b 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/PureFunctionMacroNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/PureFunctionMacroNode.java @@ -40,7 +40,7 @@ * {@link System#identityHashCode(Object)}. */ @NodeInfo -public abstract class PureFunctionMacroNode extends MacroStateSplitNode implements Canonicalizable { +public abstract class PureFunctionMacroNode extends MacroNode implements Canonicalizable { public static final NodeClass TYPE = NodeClass.create(PureFunctionMacroNode.class); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReflectionGetCallerClassNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReflectionGetCallerClassNode.java index 11d72e287572..7af8659f1f48 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReflectionGetCallerClassNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReflectionGetCallerClassNode.java @@ -42,7 +42,7 @@ import jdk.vm.ci.meta.ResolvedJavaType; @NodeInfo -public abstract class ReflectionGetCallerClassNode extends MacroStateSplitNode implements Canonicalizable, Lowerable { +public abstract class ReflectionGetCallerClassNode extends MacroNode implements Canonicalizable, Lowerable { public static final NodeClass TYPE = NodeClass.create(ReflectionGetCallerClassNode.class); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/VirtualizableInvokeMacroNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/VirtualizableInvokeMacroNode.java index f2d10adbea9c..78c14a10e152 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/VirtualizableInvokeMacroNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/VirtualizableInvokeMacroNode.java @@ -36,7 +36,7 @@ * analysis. */ @NodeInfo -public class VirtualizableInvokeMacroNode extends MacroStateSplitNode implements Virtualizable { +public class VirtualizableInvokeMacroNode extends MacroNode implements Virtualizable { public static final NodeClass TYPE = NodeClass.create(VirtualizableInvokeMacroNode.class); From 35d7f750d7cbd50cfcc4fc9b25ffd8dd9b2b122f Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Jul 2021 11:40:42 +0200 Subject: [PATCH 048/681] compiler: rename MacroStateSplitWithExceptionNode to MacroWithExceptionNode --- .../graalvm/compiler/replacements/SnippetTemplate.java | 8 ++++---- .../nodes/FallbackInvokeWithExceptionNode.java | 8 ++++---- ...WithExceptionNode.java => MacroWithExceptionNode.java} | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) rename compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/{MacroStateSplitWithExceptionNode.java => MacroWithExceptionNode.java} (94%) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index 7dd3066e6bcb..28e80a58854d 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -172,7 +172,7 @@ import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; import org.graalvm.compiler.replacements.nodes.FallbackInvokeWithExceptionNode; import org.graalvm.compiler.replacements.nodes.LoadSnippetVarargParameterNode; -import org.graalvm.compiler.replacements.nodes.MacroStateSplitWithExceptionNode; +import org.graalvm.compiler.replacements.nodes.MacroWithExceptionNode; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; import org.graalvm.util.CollectionsUtil; import org.graalvm.word.LocationIdentity; @@ -1708,10 +1708,10 @@ public UnmodifiableEconomicMap instantiate(MetaAccessProvider metaAc } if (fallbackInvoke != null) { - GraalError.guarantee(replacee instanceof MacroStateSplitWithExceptionNode, "%s can only be used in snippets replacing %s", FallbackInvokeWithExceptionNode.class.getSimpleName(), - MacroStateSplitWithExceptionNode.class.getSimpleName()); + GraalError.guarantee(replacee instanceof MacroWithExceptionNode, "%s can only be used in snippets replacing %s", FallbackInvokeWithExceptionNode.class.getSimpleName(), + MacroWithExceptionNode.class.getSimpleName()); WithExceptionNode fallbackInvokeNode = (WithExceptionNode) duplicates.get(fallbackInvoke); - MacroStateSplitWithExceptionNode macroNode = (MacroStateSplitWithExceptionNode) replacee; + MacroWithExceptionNode macroNode = (MacroWithExceptionNode) replacee; // create fallback invoke InvokeWithExceptionNode invoke = macroNode.createInvoke(returnValue); // replace placeholder diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/FallbackInvokeWithExceptionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/FallbackInvokeWithExceptionNode.java index cba202eb723b..690d1a107db8 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/FallbackInvokeWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/FallbackInvokeWithExceptionNode.java @@ -39,12 +39,12 @@ import org.graalvm.word.LocationIdentity; /** - * Placeholder for a fallback call from a {@link MacroStateSplitWithExceptionNode}. + * Placeholder for a fallback call from a {@link MacroWithExceptionNode}. * * The {@link #fallbackFunctionCall()} intrinsic can be used in snippets that lower a - * {@link MacroStateSplitWithExceptionNode}. The {@link FallbackInvokeWithExceptionNode} will be - * replaced with the {@linkplain MacroStateSplitWithExceptionNode#createInvoke original call} of the - * macro node. This can be useful for handling exceptional and/or slow path cases. + * {@link MacroWithExceptionNode}. The {@link FallbackInvokeWithExceptionNode} will be replaced with + * the {@linkplain MacroWithExceptionNode#createInvoke original call} of the macro node. This can be + * useful for handling exceptional and/or slow path cases. * * Currently, only one {@link FallbackInvokeWithExceptionNode} is allowed per snippet. */ diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitWithExceptionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java similarity index 94% rename from compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitWithExceptionNode.java rename to compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java index d9a88896bc1a..26aba2ee9c62 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java @@ -65,9 +65,9 @@ size = SIZE_UNKNOWN, sizeRationale = "If this node is not optimized away it will be lowered to a call, which we cannot estimate") //@formatter:on -public abstract class MacroStateSplitWithExceptionNode extends WithExceptionNode implements MacroInvokable, StateSplit, SingleMemoryKill { +public abstract class MacroWithExceptionNode extends WithExceptionNode implements MacroInvokable, StateSplit, SingleMemoryKill { - public static final NodeClass TYPE = NodeClass.create(MacroStateSplitWithExceptionNode.class); + public static final NodeClass TYPE = NodeClass.create(MacroWithExceptionNode.class); @Input protected NodeInputList arguments; @OptionalInput(InputType.State) protected FrameState stateAfter; @@ -77,7 +77,7 @@ public abstract class MacroStateSplitWithExceptionNode extends WithExceptionNode protected final InvokeKind invokeKind; protected final StampPair returnStamp; - protected MacroStateSplitWithExceptionNode(NodeClass c, MacroParams p) { + protected MacroWithExceptionNode(NodeClass c, MacroParams p) { super(c, p.returnStamp != null ? p.returnStamp.getTrustedStamp() : null); this.arguments = new NodeInputList<>(this, p.arguments); this.bci = p.bci; From 34eb27d057b3b31c4b8a29f6ca66325f53e67b25 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Jul 2021 11:42:58 +0200 Subject: [PATCH 049/681] compiler: every MacroInvokable is a SingleMemoryKill and a StateSplit --- .../graalvm/compiler/replacements/nodes/MacroInvokable.java | 4 +++- .../org/graalvm/compiler/replacements/nodes/MacroNode.java | 4 +--- .../compiler/replacements/nodes/MacroWithExceptionNode.java | 4 +--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java index c0c09e76c9ec..8a84ca1a5086 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java @@ -34,8 +34,10 @@ import org.graalvm.compiler.nodes.Invokable; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeNode; +import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; @@ -60,7 +62,7 @@ *
  • Otherwise, the macro node is replaced with an {@link InvokeNode}.
  • *
*/ -public interface MacroInvokable extends Invokable, Lowerable { +public interface MacroInvokable extends Invokable, Lowerable, StateSplit, SingleMemoryKill { CallTargetNode.InvokeKind getInvokeKind(); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java index 01443e1c876c..2577ba0c5d8a 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java @@ -41,11 +41,9 @@ import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; @@ -60,7 +58,7 @@ size = SIZE_UNKNOWN, sizeRationale = "If this node is not optimized away it will be lowered to a call, which we cannot estimate") //@formatter:on -public abstract class MacroNode extends FixedWithNextNode implements MacroInvokable, StateSplit, SingleMemoryKill { +public abstract class MacroNode extends FixedWithNextNode implements MacroInvokable { public static final NodeClass TYPE = NodeClass.create(MacroNode.class); @Input protected NodeInputList arguments; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java index 26aba2ee9c62..a8e331ed20d9 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java @@ -40,11 +40,9 @@ import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; -import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.WithExceptionNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.replacements.nodes.MacroNode.MacroParams; import org.graalvm.word.LocationIdentity; @@ -65,7 +63,7 @@ size = SIZE_UNKNOWN, sizeRationale = "If this node is not optimized away it will be lowered to a call, which we cannot estimate") //@formatter:on -public abstract class MacroWithExceptionNode extends WithExceptionNode implements MacroInvokable, StateSplit, SingleMemoryKill { +public abstract class MacroWithExceptionNode extends WithExceptionNode implements MacroInvokable { public static final NodeClass TYPE = NodeClass.create(MacroWithExceptionNode.class); @Input protected NodeInputList arguments; From 7881c90935c9865c04f848d9f069d074bc76818e Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Jul 2021 11:47:56 +0200 Subject: [PATCH 050/681] compiler: remove unused method MacroWithExceptionNode#getLocationIdentity --- .../compiler/replacements/nodes/MacroWithExceptionNode.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java index a8e331ed20d9..dc11570b441d 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java @@ -132,10 +132,6 @@ public Invoke replaceWithInvoke() { } } - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } - protected InvokeWithExceptionNode createInvoke() { return createInvoke(this); } From dd7cb84e496914212dccd25eed1359c424136286 Mon Sep 17 00:00:00 2001 From: Marouane el hallaoui Date: Tue, 31 Aug 2021 17:30:00 +0100 Subject: [PATCH 051/681] update to jvmci-21.3-b03 --- common.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/common.json b/common.json index eed1172ae295..c599e129d6de 100644 --- a/common.json +++ b/common.json @@ -2,20 +2,20 @@ "README": "This file contains definitions that are useful for the hocon and jsonnet CI files of multiple repositories.", "jdks": { - "openjdk8": {"name": "openjdk", "version": "8u302+06-jvmci-21.3-b02", "platformspecific": true }, - "oraclejdk8": {"name": "oraclejdk", "version": "8u311+06-jvmci-21.3-b02", "platformspecific": true }, - "oraclejdk8Debug": {"name": "oraclejdk", "version": "8u311+06-jvmci-21.3-b02-fastdebug", "platformspecific": true }, + "openjdk8": {"name": "openjdk", "version": "8u302+06-jvmci-21.3-b03", "platformspecific": true }, + "oraclejdk8": {"name": "oraclejdk", "version": "8u311+09-jvmci-21.3-b03", "platformspecific": true }, + "oraclejdk8Debug": {"name": "oraclejdk", "version": "8u311+09-jvmci-21.3-b03-fastdebug", "platformspecific": true }, "openjdk11": {"name": "openjdk", "version": "11.0.11+9", "platformspecific": true }, "oraclejdk11": {"name": "oraclejdk", "version": "11.0.11+9", "platformspecific": true }, - "labsjdk-ce-11": {"name": "labsjdk", "version": "ce-11.0.12+5-jvmci-21.3-b02", "platformspecific": true }, - "labsjdk-ee-11": {"name": "labsjdk", "version": "ee-11.0.13+6-jvmci-21.3-b02", "platformspecific": true }, + "labsjdk-ce-11": {"name": "labsjdk", "version": "ce-11.0.12+5-jvmci-21.3-b03", "platformspecific": true }, + "labsjdk-ee-11": {"name": "labsjdk", "version": "ee-11.0.13+9-jvmci-21.3-b03", "platformspecific": true }, "oraclejdk17": {"name": "oraclejdk", "version": "17.0.1+2", "platformspecific": true }, - "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17+35-jvmci-21.3-b02", "platformspecific": true }, - "labsjdk-ce-17Debug": {"name": "labsjdk", "version": "ce-17+35-jvmci-21.3-b02-debug", "platformspecific": true }, - "labsjdk-ee-17": {"name": "labsjdk", "version": "ee-17.0.1+7-jvmci-21.3-b02", "platformspecific": true }, - "labsjdk-ee-17Debug": {"name": "labsjdk", "version": "ee-17.0.1+7-jvmci-21.3-b02-debug", "platformspecific": true } + "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17+35-jvmci-21.3-b03", "platformspecific": true }, + "labsjdk-ce-17Debug": {"name": "labsjdk", "version": "ce-17+35-jvmci-21.3-b03-debug", "platformspecific": true }, + "labsjdk-ee-17": {"name": "labsjdk", "version": "ee-17.0.1+9-jvmci-21.3-b03", "platformspecific": true }, + "labsjdk-ee-17Debug": {"name": "labsjdk", "version": "ee-17.0.1+9-jvmci-21.3-b03-debug", "platformspecific": true } }, "COMMENT" : "The devkits versions reflect those used to build the JVMCI JDKs (e.g., see devkit_platform_revisions in /make/conf/jib-profiles.js)", From fce66273894a724b565521ae27a88b87e90988e1 Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Fri, 20 Aug 2021 12:32:11 +0200 Subject: [PATCH 052/681] type checking: common hub access and slot check on svm --- .../graalvm/compiler/core/phases/MidTier.java | 5 + .../micro/benchmarks/TypecheckBenchmark.java | 309 ++++++++++++++++++ .../meta/SubstrateBasicLoweringProvider.java | 2 +- .../graal/snippets/SubstrateIntrinsics.java | 4 + .../svm/core/graal/snippets/TypeSnippets.java | 55 ++-- .../svm/core/graal/word/DynamicHubAccess.java | 36 ++ .../core/graal/word/SubstrateOperation.java | 42 +++ .../word/SubstrateWordOperationPlugins.java | 91 ++++++ .../svm/hosted/NativeImageGenerator.java | 3 +- 9 files changed, 523 insertions(+), 24 deletions(-) create mode 100644 compiler/src/org.graalvm.micro.benchmarks/src/micro/benchmarks/TypecheckBenchmark.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/DynamicHubAccess.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateOperation.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java index 5ad2da686d68..7227895cbae1 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java @@ -36,6 +36,7 @@ import static org.graalvm.compiler.core.common.SpectrePHTMitigations.NonDeoptGuardTargets; import static org.graalvm.compiler.core.common.SpectrePHTMitigations.Options.SpectrePHTBarriers; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.loop.phases.LoopPartialUnrollPhase; import org.graalvm.compiler.loop.phases.LoopPredicationPhase; import org.graalvm.compiler.loop.phases.LoopSafepointEliminationPhase; @@ -102,6 +103,10 @@ public MidTier(OptionValues options) { appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER)); + if (GraalOptions.ConditionalElimination.getValue(options)) { + appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); + } + appendPhase(new OptimizeDivPhase()); appendPhase(new FrameStateAssignmentPhase()); diff --git a/compiler/src/org.graalvm.micro.benchmarks/src/micro/benchmarks/TypecheckBenchmark.java b/compiler/src/org.graalvm.micro.benchmarks/src/micro/benchmarks/TypecheckBenchmark.java new file mode 100644 index 000000000000..e4f749be75e7 --- /dev/null +++ b/compiler/src/org.graalvm.micro.benchmarks/src/micro/benchmarks/TypecheckBenchmark.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2017, 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 micro.benchmarks; + +import java.lang.reflect.Array; +import java.util.Random; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +public class TypecheckBenchmark extends BenchmarkBase { + + static class A { + + } + + static class B { + + } + + static class C { + + } + + static class AA { + + } + + static class AA1 extends AA { + + } + + static class AA2 extends AA1 { + + } + + static class BB { + + } + + static class BB1 extends BB { + + } + + static class BB2 extends BB1 { + + } + + static class CC { + + } + + static class CC1 extends CC { + + } + + static class CC2 extends CC1 { + + } + + @State(Scope.Benchmark) + public static class ThreadState { + + private static final int N = 100000; + + final Random r = new Random(17); + + final C c = new C(); + final B b = new B(); + final A a = new A(); + final CC2 cc2 = new CC2(); + final CC1 cc1 = new CC1(); + final CC cc = new CC(); + final BB2 bb2 = new BB2(); + final BB1 bb1 = new BB1(); + final BB bb = new BB(); + final AA2 aa2 = new AA2(); + final AA1 aa1 = new AA1(); + final AA aa = new AA(); + Random r1 = new Random(31); + + int magic = 14; + + Object[] aas = createAAs(); + Class[] classes = createClasses(N); + Object[] object = createObjects(N); + + private Object[] createAAs() { + Object[] source = new Object[N]; + for (int i = 0; i < N; i++) { + if (i == magic) { + source[i] = new CC(); + } + int rand = r.nextInt(3); + if (rand <= 1) { + source[i] = new AA2(); + } else { + source[i] = new AA1(); + } + } + return source; + } + + private Class[] createClasses(int n2) { + Class[] ccs = new Class[n2]; + for (int i = 0; i < N; i++) { + ccs[i] = nextClass(); + } + return ccs; + } + + private Object[] createObjects(int n2) { + Object[] o = new Object[n2]; + for (int i = 0; i < N; i++) { + o[i] = nextElement(); + } + return o; + } + + private Object nextElement() { + int rand = r.nextInt(12); + + if (rand == 10) { + return aa2; + } else if (rand == 11) { + return bb2; + } else if (rand == 12) { + return cc2; + } else if (rand == 9) { + return c; + } else if (rand == 8) { + return b; + } else if (rand == 7) { + return a; + } else if (rand == 6) { + return cc1; + } else if (rand == 5) { + return cc; + } else if (rand == 4) { + return bb1; + } else if (rand == 3) { + return bb; + } else if (rand == 2) { + return aa1; + } + return aa; + } + + private Class nextClass() { + int rand = r1.nextInt(10); + + if (rand == 9) { + return C.class; + } else if (rand == 8) { + return B.class; + } else if (rand == 7) { + return A.class; + } else if (rand == 6) { + return CC1.class; + } else if (rand == 5) { + return CC.class; + } else if (rand == 4) { + return BB1.class; + } else if (rand == 3) { + return BB.class; + } else if (rand == 2) { + return AA1.class; + } + return AA.class; + } + } + + @Benchmark + public void benchArrayStore(ThreadState state) { + Object[] target = (Object[]) Array.newInstance(state.aas[0].getClass().getSuperclass(), state.aas.length); + for (int i = 0; i < state.aas.length; i++) { + if (i == state.magic) { + continue; + } + target[i] = state.aas[i]; + } + } + + @Benchmark + public int repetitiveTypeCheckExact(ThreadState state) { + int res = 0; + for (int i = 0; i < state.object.length; i++) { + Object o = state.object[i]; + if (o instanceof A) { + res++; + } else if (o instanceof B) { + res += 2; + } else if (o instanceof C) { + res += 4; + } + } + return res; + } + + @Benchmark + public int repetitiveTypeCheckSubclasses(ThreadState state) { + int res = 0; + for (int i = 0; i < state.object.length; i++) { + Object o = state.object[i]; + if (o == null) { + return 0; + } + if (o instanceof AA1) { + res += 7; + } else if (o instanceof BB1) { + res += 5; + } else if (o instanceof CC1) { + res += 3; + } else if (o instanceof AA) { + res++; + } else if (o instanceof BB) { + res += 2; + } else if (o instanceof CC) { + res += 4; + } + } + return res; + } + + @Benchmark + public int repetitiveClassIsAssignable(ThreadState state) { + int res = 0; + for (int i = 0; i < state.object.length; i++) { + Object o = state.object[i]; + if (o == null) { + return 0; + } + if (AA1.class.isAssignableFrom(o.getClass())) { + res += 7; + } else if (BB1.class.isAssignableFrom(o.getClass())) { + res += 3; + } else if (CC1.class.isAssignableFrom(o.getClass())) { + res += 5; + } else if (AA.class.isAssignableFrom(o.getClass())) { + res++; + } else if (BB.class.isAssignableFrom(o.getClass())) { + res += 2; + } else if (CC.class.isAssignableFrom(o.getClass())) { + res += 4; + } + } + return res; + } + + @Benchmark + public int repetitiveInstanceOfDynamic(ThreadState state) { + int res = 0; + for (int i = 0; i < state.object.length / 8; i += 8) { + Object o1 = state.object[i]; + Object o2 = state.object[i + 1]; + Object o3 = state.object[i + 2]; + Object o4 = state.object[i + 3]; + Object o5 = state.object[i + 4]; + Object o6 = state.object[i + 5]; + Object o7 = state.object[i + 6]; + Object o8 = state.object[i + 7]; + Class c = state.classes[i]; + + if (c.isInstance(o1)) { + res++; + } else if (c.isInstance(o2)) { + res++; + } else if (c.isInstance(o3)) { + res++; + } else if (c.isInstance(o4)) { + res++; + } else if (c.isInstance(o5)) { + res++; + } else if (c.isInstance(o6)) { + res++; + } else if (c.isInstance(o7)) { + res++; + } else if (c.isInstance(o8)) { + res++; + } + } + + return res; + } + +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java index 037bec25405d..64769d770b2d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java @@ -175,7 +175,7 @@ protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, Lower return graph.unique(new LoadHubNode(tool.getStampProvider(), object)); } - assert !object.isConstant() || object.asJavaConstant().isNull(); + assert !object.isConstant() || object.asJavaConstant().isNull() : "Object should either not be a constant or the null constant" + object; ObjectLayout objectLayout = getObjectLayout(); Stamp headerBitsStamp = StampFactory.forUnsignedInteger(8 * objectLayout.getReferenceSize()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateIntrinsics.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateIntrinsics.java index bd151312aaa8..fb5aad712efb 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateIntrinsics.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateIntrinsics.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.extended.LoadHubOrNullNode; import org.graalvm.word.Pointer; import com.oracle.svm.core.hub.DynamicHub; @@ -44,6 +45,9 @@ protected interface Any { @NodeIntrinsic(LoadHubNode.class) public static native DynamicHub loadHub(Object object); + @NodeIntrinsic(LoadHubOrNullNode.class) + public static native DynamicHub loadHubOrNull(Object object); + @NodeIntrinsic(value = ForeignCallNode.class) public static native void runtimeCall(@ConstantNodeParameter ForeignCallDescriptor descriptor); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/TypeSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/TypeSnippets.java index 7f6b3c5c7305..fc62f5662a3a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/TypeSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/TypeSnippets.java @@ -25,6 +25,7 @@ package com.oracle.svm.core.graal.snippets; import static com.oracle.svm.core.graal.snippets.SubstrateIntrinsics.loadHub; +import static com.oracle.svm.core.graal.snippets.SubstrateIntrinsics.loadHubOrNull; import java.util.Map; @@ -38,6 +39,7 @@ import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.calc.FloatingNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode; import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; @@ -47,11 +49,11 @@ import org.graalvm.compiler.replacements.InstanceOfSnippetsTemplates; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.Snippets; -import org.graalvm.compiler.word.ObjectAccess; import com.oracle.svm.core.annotate.DuplicatedInNativeCode; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.graal.meta.RuntimeConfiguration; +import com.oracle.svm.core.graal.word.DynamicHubAccess; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.meta.SharedType; @@ -66,16 +68,16 @@ protected static SubstrateIntrinsics.Any typeEqualitySnippet( SubstrateIntrinsics.Any falseValue, @Snippet.ConstantParameter boolean allowsNull, DynamicHub exactType) { - - if (object == null) { - return allowsNull ? trueValue : falseValue; + if (allowsNull) { + if (object == null) { + return trueValue; + } } - Object objectNonNull = PiNode.piCastNonNull(object, SnippetAnchorNode.anchor()); - - if (loadHub(objectNonNull) == exactType) { - return trueValue; + Object hubOrNull = loadHubOrNull(object); + if (hubOrNull != exactType) { + return falseValue; } - return falseValue; + return trueValue; } @Snippet @@ -87,12 +89,16 @@ protected static SubstrateIntrinsics.Any instanceOfSnippet( short start, short range, short slot, @Snippet.ConstantParameter int typeIDSlotOffset) { if (object == null) { - return allowsNull ? trueValue : falseValue; + if (allowsNull) { + return trueValue; + } + return falseValue; } - Object objectNonNull = PiNode.piCastNonNull(object, SnippetAnchorNode.anchor()); - DynamicHub objectHub = loadHub(objectNonNull); - - return slotTypeCheck(start, range, slot, typeIDSlotOffset, objectHub, trueValue, falseValue); + GuardingNode guard = SnippetAnchorNode.anchor(); + Object nonNullObject = PiNode.piCastNonNull(object, guard); + DynamicHub hubNoneNull = loadHub(nonNullObject); + // no need to guard, guarded via hub + return slotTypeCheck(start, range, slot, typeIDSlotOffset, hubNoneNull, trueValue, falseValue, null); } @Snippet @@ -104,12 +110,16 @@ protected static SubstrateIntrinsics.Any instanceOfDynamicSnippet( @Snippet.ConstantParameter boolean allowsNull, @Snippet.ConstantParameter int typeIDSlotOffset) { if (object == null) { - return allowsNull ? trueValue : falseValue; + if (allowsNull) { + return trueValue; + } + return falseValue; } - Object objectNonNull = PiNode.piCastNonNull(object, SnippetAnchorNode.anchor()); - DynamicHub objectHub = loadHub(objectNonNull); - - return slotTypeCheck(type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), typeIDSlotOffset, objectHub, trueValue, falseValue); + GuardingNode guard = SnippetAnchorNode.anchor(); + Object nonNullObject = PiNode.piCastNonNull(object, guard); + DynamicHub hubNoneNull = loadHub(nonNullObject); + // no need to guard, guarded via hub + return slotTypeCheck(type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), typeIDSlotOffset, hubNoneNull, trueValue, falseValue, null); } @Snippet @@ -119,7 +129,8 @@ protected static SubstrateIntrinsics.Any classIsAssignableFromSnippet( SubstrateIntrinsics.Any trueValue, SubstrateIntrinsics.Any falseValue, @Snippet.ConstantParameter int typeIDSlotOffset) { - return slotTypeCheck(type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), typeIDSlotOffset, checkedHub, trueValue, falseValue); + // no guard needed, b guaranteed to be non null + return slotTypeCheck(type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), typeIDSlotOffset, checkedHub, trueValue, falseValue, null); } @DuplicatedInNativeCode @@ -128,12 +139,12 @@ private static SubstrateIntrinsics.Any slotTypeCheck( int typeIDSlotOffset, DynamicHub checkedHub, SubstrateIntrinsics.Any trueValue, - SubstrateIntrinsics.Any falseValue) { + SubstrateIntrinsics.Any falseValue, GuardingNode guard) { int typeCheckStart = Short.toUnsignedInt(start); int typeCheckRange = Short.toUnsignedInt(range); int typeCheckSlot = Short.toUnsignedInt(slot) * 2; - int checkedTypeID = Short.toUnsignedInt(ObjectAccess.readShort(checkedHub, typeIDSlotOffset + typeCheckSlot, NamedLocationIdentity.FINAL_LOCATION)); + int checkedTypeID = Short.toUnsignedInt(DynamicHubAccess.readShort(checkedHub, typeIDSlotOffset + typeCheckSlot, NamedLocationIdentity.FINAL_LOCATION, guard)); if (UnsignedMath.belowThan(checkedTypeID - typeCheckStart, typeCheckRange)) { return trueValue; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/DynamicHubAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/DynamicHubAccess.java new file mode 100644 index 000000000000..e926f9110bb1 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/DynamicHubAccess.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012, 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.core.graal.word; + +import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.word.LocationIdentity; + +import com.oracle.svm.core.graal.word.SubstrateOperation.SubstrateOpcode; + +public final class DynamicHubAccess { + + @SubstrateOperation(opcode = SubstrateOpcode.READ_FROM_HUB) + public static native short readShort(Object object, int offset, LocationIdentity identity, GuardingNode guard); +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateOperation.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateOperation.java new file mode 100644 index 000000000000..1227bb12af05 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateOperation.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 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.core.graal.word; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface SubstrateOperation { + + enum SubstrateOpcode { + READ_FROM_HUB + } + + SubstrateOpcode opcode(); + +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java new file mode 100644 index 000000000000..62c782a0fda7 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012, 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.core.graal.word; + +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.memory.FixedAccessNode; +import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; +import org.graalvm.compiler.nodes.memory.ReadNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.word.WordOperationPlugin; +import org.graalvm.compiler.word.WordTypes; +import org.graalvm.util.GuardedAnnotationAccess; +import org.graalvm.word.LocationIdentity; + +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class SubstrateWordOperationPlugins extends WordOperationPlugin { + + public SubstrateWordOperationPlugins(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) { + super(snippetReflection, wordTypes); + } + + @Override + public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + if (!wordTypes.isWordOperation(method)) { + if (!method.getDeclaringClass().equals(b.getMetaAccess().lookupJavaType(DynamicHubAccess.class))) { + return false; + } + } + + SubstrateOperation operation = GuardedAnnotationAccess.getAnnotation(method, SubstrateOperation.class); + if (operation == null) { + processWordOperation(b, args, wordTypes.getWordOperation(method, b.getMethod().getDeclaringClass())); + return true; + } + processSubstrateOperation(b, method, args, operation); + return true; + } + + protected void processSubstrateOperation(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, SubstrateOperation operation) { + switch (operation.opcode()) { + case READ_FROM_HUB: + JavaKind returnKind = method.getSignature().getReturnKind(); + assert args.length == 4 : "arg length=" + args.length + " operation=" + operation; + JavaKind readKind = wordTypes.asKind(method.getSignature().getReturnType(method.getDeclaringClass())); + AddressNode address = makeAddress(b, args[0], args[1]); + LocationIdentity location; + assert args[2].isConstant() : args[2]; + location = snippetReflection.asObject(LocationIdentity.class, args[2].asJavaConstant()); + assert location != null : snippetReflection.asObject(Object.class, args[2].asJavaConstant()); + FixedAccessNode read = b.add(new ReadNode(address, location, StampFactory.forKind(readKind), BarrierType.NONE)); + if (!(args[3] instanceof ConstantNode)) { + // guard can be the null constant + read.setGuard((GuardingNode) args[3]); + } + b.push(returnKind, read); + break; + default: + throw GraalError.shouldNotReachHere("Unkown operation " + operation); + } + } +} 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 e6df8a8d4b78..5773e53793b5 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 @@ -192,6 +192,7 @@ import com.oracle.svm.core.graal.snippets.ExceptionSnippets; import com.oracle.svm.core.graal.snippets.NodeLoweringProvider; import com.oracle.svm.core.graal.snippets.TypeSnippets; +import com.oracle.svm.core.graal.word.SubstrateWordOperationPlugins; import com.oracle.svm.core.graal.word.SubstrateWordTypes; import com.oracle.svm.core.heap.Heap; import com.oracle.svm.core.heap.RestrictHeapAccessCallees; @@ -1109,7 +1110,7 @@ public static void registerGraphBuilderPlugins(FeatureHandler featureHandler, Ru TargetDescription target) { GraphBuilderConfiguration.Plugins plugins = new GraphBuilderConfiguration.Plugins(new SubstitutionInvocationPlugins(annotationSubstitutionProcessor)); - WordOperationPlugin wordOperationPlugin = new WordOperationPlugin(providers.getSnippetReflection(), providers.getWordTypes()); + WordOperationPlugin wordOperationPlugin = new SubstrateWordOperationPlugins(providers.getSnippetReflection(), providers.getWordTypes()); SubstrateReplacements replacements = (SubstrateReplacements) providers.getReplacements(); plugins.appendInlineInvokePlugin(replacements); From 9737841a11961a21c67c934ccd8a8077cb34199d Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Fri, 27 Aug 2021 18:00:08 +0200 Subject: [PATCH 053/681] consider load hub or null on constants if canon did not catch it --- .../replacements/DefaultJavaLoweringProvider.java | 8 ++++++++ .../src/micro/benchmarks/TypecheckBenchmark.java | 2 +- .../core/graal/meta/SubstrateBasicLoweringProvider.java | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java index 9d69d73b4fb1..039abf9ef396 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java @@ -620,6 +620,14 @@ protected void lowerLoadHubOrNullNode(LoadHubOrNullNode loadHubOrNullNode, Lower if (graph.getGuardsStage().allowsFloatingGuards()) { return; } + ValueNode object = loadHubOrNullNode.getValue(); + if (object.isConstant() && !object.asJavaConstant().isNull()) { + ValueNode synonym = LoadHubNode.findSynonym(object, loadHubOrNullNode.stamp(NodeView.DEFAULT), tool.getMetaAccess(), tool.getConstantReflection()); + if (synonym != null) { + loadHubOrNullNode.replaceAtUsagesAndDelete(graph.maybeAddOrUnique(synonym)); + return; + } + } final FixedWithNextNode predecessor = tool.lastFixedNode(); final ValueNode value = loadHubOrNullNode.getValue(); AbstractPointerStamp stamp = (AbstractPointerStamp) value.stamp(NodeView.DEFAULT); diff --git a/compiler/src/org.graalvm.micro.benchmarks/src/micro/benchmarks/TypecheckBenchmark.java b/compiler/src/org.graalvm.micro.benchmarks/src/micro/benchmarks/TypecheckBenchmark.java index e4f749be75e7..2a548c8f152e 100644 --- a/compiler/src/org.graalvm.micro.benchmarks/src/micro/benchmarks/TypecheckBenchmark.java +++ b/compiler/src/org.graalvm.micro.benchmarks/src/micro/benchmarks/TypecheckBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java index 64769d770b2d..6869ecabd713 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java @@ -69,8 +69,8 @@ import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.config.ObjectLayout; import com.oracle.svm.core.graal.nodes.FloatingWordCastNode; -import com.oracle.svm.core.graal.nodes.SubstrateCompressionNode; import com.oracle.svm.core.graal.nodes.LoweredDeadEndNode; +import com.oracle.svm.core.graal.nodes.SubstrateCompressionNode; import com.oracle.svm.core.graal.nodes.SubstrateFieldLocationIdentity; import com.oracle.svm.core.graal.nodes.SubstrateNarrowOopStamp; import com.oracle.svm.core.graal.snippets.NodeLoweringProvider; From 095271d347ab4685ccdb2ae31cc9c8ea79ee5d39 Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Wed, 1 Sep 2021 13:36:23 +0200 Subject: [PATCH 054/681] schedule phase: respect target arch that do not support implicit null checks --- .../core/aarch64/AArch64SuitesCreator.java | 10 +-- .../compiler/core/test/GraalCompilerTest.java | 7 +- .../compiler/core/test/GraphScheduleTest.java | 3 +- .../core/test/GuardPrioritiesTest.java | 2 +- .../compiler/core/test/LongNodeChainTest.java | 2 +- .../core/test/MemoryScheduleTest.java | 2 +- .../core/test/ReentrantBlockIteratorTest.java | 2 +- .../compiler/core/test/SchedulingTest.java | 2 +- .../compiler/core/test/SchedulingTest2.java | 4 +- .../compiler/core/test/TypeSystemTest.java | 3 +- .../core/test/ea/EscapeAnalysisTest.java | 2 +- .../hotspot/SymbolicSnippetEncoder.java | 3 +- .../phases/aot/ReplaceConstantNodesPhase.java | 9 +-- .../graal/SchedulePhaseBenchmark.java | 18 ++--- .../graal/util/ScheduleState.java | 9 +-- .../compiler/nodes/cfg/ControlFlowGraph.java | 4 ++ .../compiler/nodes/spi/LoweringProvider.java | 5 ++ .../common/ConditionalEliminationPhase.java | 2 +- .../compiler/phases/common/FixReadsPhase.java | 9 ++- .../phases/common/GuardLoweringPhase.java | 2 +- .../compiler/phases/common/LoweringPhase.java | 2 +- .../common/ProfileCompiledMethodsPhase.java | 4 +- .../graalvm/compiler/phases/BasePhase.java | 2 +- .../phases/contract/NodeCostUtil.java | 3 +- .../phases/schedule/SchedulePhase.java | 65 +++++++++++++------ .../compiler/phases/util/GraphOrder.java | 3 +- .../printer/GraalDebugHandlersFactory.java | 3 +- .../compiler/printer/GraphPrinter.java | 3 +- .../DefaultJavaLoweringProvider.java | 5 ++ .../truffle/compiler/ExpansionStatistics.java | 3 +- .../virtual/phases/ea/EffectsPhase.java | 2 +- .../graal/meta/SubstrateLoweringProvider.java | 4 ++ 32 files changed, 113 insertions(+), 86 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java index f484cd6351d5..18aa11bb7e2a 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java @@ -30,23 +30,23 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.java.DefaultSuitesCreator; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.LowTierContext; import org.graalvm.compiler.phases.tiers.Suites; public class AArch64SuitesCreator extends DefaultSuitesCreator { - private final List> insertReadReplacementBeforePositions; + private final List>> insertReadReplacementBeforePositions; - public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins, List> insertReadReplacementBeforePositions) { + public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins, List>> insertReadReplacementBeforePositions) { super(compilerConfiguration, plugins); this.insertReadReplacementBeforePositions = insertReadReplacementBeforePositions; } - public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, List> insertReadReplacementBeforePositions) { + public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, List>> insertReadReplacementBeforePositions) { super(compilerConfiguration); this.insertReadReplacementBeforePositions = insertReadReplacementBeforePositions; } @@ -55,7 +55,7 @@ public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, List> findPhase = null; - for (Class phase : insertReadReplacementBeforePositions) { + for (Class> phase : insertReadReplacementBeforePositions) { findPhase = suites.getLowTier().findPhase(phase); if (findPhase != null) { // Put AArch64ReadReplacementPhase right before the requested phase diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java index b5ec3198abd5..22e42e8edfc1 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java @@ -496,8 +496,8 @@ protected void assertConstantReturn(StructuredGraph graph, int value) { } protected static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) { - SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST); - schedule.apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph, SchedulingStrategy.EARLIEST); + ScheduleResult scheduleResult = graph.getLastSchedule(); NodeMap canonicalId = graph.createNodeMap(); @@ -575,8 +575,7 @@ private static int filteredUsageCount(Node node) { * @return a scheduled textual dump of {@code graph} . */ protected static String getScheduledGraphString(StructuredGraph graph) { - SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); - schedule.apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph, SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); ScheduleResult scheduleResult = graph.getLastSchedule(); StringBuilder result = new StringBuilder(); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java index 6d4eaa4d8171..dcae927ece3d 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java @@ -43,8 +43,7 @@ protected void assertOrderedAfterSchedule(StructuredGraph graph, Node a, Node b) } protected void assertOrderedAfterSchedule(StructuredGraph graph, SchedulePhase.SchedulingStrategy strategy, Node a, Node b) { - SchedulePhase ibp = new SchedulePhase(strategy); - ibp.apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph, strategy); assertOrderedAfterLastSchedule(graph, a, b); } diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java index 1f50d8435ed8..0ad459b9021f 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java @@ -111,7 +111,7 @@ public void unknownTest() { assumeTrue("GuardPriorities must be turned one", GraalOptions.GuardPriorities.getValue(getInitialOptions())); StructuredGraph graph = prepareGraph("unknownCondition"); - new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER).apply(graph); + new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER).apply(graph, getDefaultHighTierContext()); for (GuardNode g1 : graph.getNodes(GuardNode.TYPE)) { for (GuardNode g2 : graph.getNodes(GuardNode.TYPE)) { if (g1.getSpeculation().equals(SpeculationLog.NO_SPECULATION) ^ g2.getSpeculation().equals(SpeculationLog.NO_SPECULATION)) { diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java index 021cdd58f715..96ac33582e24 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java @@ -80,7 +80,7 @@ private void longAddChain(boolean reverse) { graph.start().setNext(returnNode); for (SchedulingStrategy s : Strategies) { - new SchedulePhase(s).apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph, s); } this.createCanonicalizerPhase().apply(graph, context); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java index 55b8feda603b..92e7914468db 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java @@ -718,7 +718,7 @@ private ScheduleResult getFinalSchedule(final String snippet, final TestMode mod new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); SchedulePhase schedule = new SchedulePhase(schedulingStrategy); - schedule.apply(graph); + schedule.apply(graph, getDefaultLowTierContext()); return graph.getLastSchedule(); } catch (Throwable e) { throw debug.handle(e); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java index d0216e1a7e90..4443313e5e84 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java @@ -244,7 +244,7 @@ protected List processLoop(Loop loop, VoidState initialState) ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, false); ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); // schedule for IGV - new SchedulePhase(graph.getOptions()).apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph); return blocks; } diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest.java index d43d6a3c2148..de17b0293ee8 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest.java @@ -64,7 +64,7 @@ public void testValueProxyInputs() { } graph.clearAllStateAfter(); SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST); - schedulePhase.apply(graph); + schedulePhase.apply(graph, getDefaultHighTierContext()); ScheduleResult schedule = graph.getLastSchedule(); NodeMap nodeToBlock = schedule.getCFG().getNodeToBlock(); assertTrue(graph.getNodes().filter(LoopExitNode.class).count() == 1); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java index 380b3e3390e5..cf343b349622 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java @@ -72,7 +72,7 @@ public void testValueProxyInputs() { beginNode.setNext(returnNode); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); - schedulePhase.apply(graph); + schedulePhase.apply(graph, getDefaultHighTierContext()); ScheduleResult schedule = graph.getLastSchedule(); BlockMap> blockToNodesMap = schedule.getBlockToNodesMap(); NodeMap nodeToBlock = schedule.getNodeToBlockMap(); @@ -106,7 +106,7 @@ public void testValueProxyInputs() { FrameStateAssignmentPhase phase = new FrameStateAssignmentPhase(); phase.apply(graph); - schedulePhase.apply(graph); + schedulePhase.apply(graph, midContext); schedule = graph.getLastSchedule(); blockToNodesMap = schedule.getBlockToNodesMap(); nodeToBlock = schedule.getNodeToBlockMap(); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java index 05c2f94a1d89..44aa8ad47b67 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java @@ -209,8 +209,7 @@ protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { public static void outputGraph(StructuredGraph graph, String message) { TTY.println("========================= " + message); - SchedulePhase schedulePhase = new SchedulePhase(graph.getOptions()); - schedulePhase.apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph); ScheduleResult schedule = graph.getLastSchedule(); for (Block block : schedule.getCFG().getBlocks()) { TTY.print("Block " + block + " "); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java index 5706749921e5..6e9d60e35cd7 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java @@ -471,7 +471,7 @@ public static Object testPeeledLoopSnippet() { public void testPeeledLoop() { prepareGraph("testPeeledLoopSnippet", false); new LoopPeelingPhase(new DefaultLoopPolicies()).apply(graph, getDefaultHighTierContext()); - new SchedulePhase(graph.getOptions()).apply(graph); + new SchedulePhase(graph.getOptions()).apply(graph, getDefaultHighTierContext()); } public static void testDeoptMonitorSnippetInner(Object o2, Object t, int i) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index 23cee691847c..b15c52dc2678 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -928,8 +928,7 @@ private static String compareGraphStrings(StructuredGraph expectedGraph, String } private static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) { - SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST); - schedule.apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph, SchedulePhase.SchedulingStrategy.EARLIEST); StructuredGraph.ScheduleResult scheduleResult = graph.getLastSchedule(); NodeMap canonicalId = graph.createNodeMap(); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java index 9872c70c1705..a41598fae333 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java @@ -523,7 +523,7 @@ private static void handleLoadMethodCounters(StructuredGraph graph, FrameStateMa * @param context */ private static void replaceLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, CoreProviders context) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false); + new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, context, false); for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) { if (anyUsagesNeedReplacement(node)) { @@ -538,9 +538,10 @@ private static void replaceLoadMethodCounters(StructuredGraph graph, FrameStateM * @param graph * @param stateMapper * @param classInfo + * @param context */ - private void replaceKlassesAndObjects(StructuredGraph graph, FrameStateMapperClosure stateMapper, ClassInfo classInfo) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false); + private void replaceKlassesAndObjects(StructuredGraph graph, FrameStateMapperClosure stateMapper, ClassInfo classInfo, CoreProviders context) { + new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, context, false); for (ConstantNode node : getConstantNodes(graph)) { Constant constant = node.asConstant(); @@ -580,7 +581,7 @@ protected void run(StructuredGraph graph, CoreProviders context) { // Replace object and klass constants (including the ones added in the previous pass) // with resolution nodes. - replaceKlassesAndObjects(graph, stateMapper, new ClassInfo(context.getMetaAccess())); + replaceKlassesAndObjects(graph, stateMapper, new ClassInfo(context.getMetaAccess()), context); } else { replaceKlassesWithoutResolution(graph, new ClassInfo(context.getMetaAccess())); } diff --git a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java index f9d1e8bfb278..940c0f836b55 100644 --- a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java +++ b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java @@ -39,7 +39,7 @@ public static class StringEquals extends ScheduleState { @Benchmark public void stringEquals(StringEquals s) { - s.schedule.apply(s.graph); + SchedulePhase.runWithoutContextOptimizations(s.graph); } @Benchmark @@ -95,7 +95,7 @@ public IntersectionState_LATEST_OPTIMAL() { @Benchmark public void intersection_LATEST_OPTIMAL(IntersectionState_LATEST_OPTIMAL s) { - s.schedule.apply(s.graph); + SchedulePhase.runWithoutContextOptimizations(s.graph, s.getSelectedStrategy()); } @MethodSpec(declaringClass = SchedulePhaseBenchmark.class, name = "intersectionSnippet") @@ -107,7 +107,7 @@ public IntersectionState_LATEST_OUT_OF_LOOPS_OPTIMAL() { @Benchmark public void intersection_LATEST_OUT_OF_LOOPS_OPTIMAL(IntersectionState_LATEST_OUT_OF_LOOPS_OPTIMAL s) { - s.schedule.apply(s.graph); + SchedulePhase.runWithoutContextOptimizations(s.graph, s.getSelectedStrategy()); } @MethodSpec(declaringClass = SchedulePhaseBenchmark.class, name = "intersectionSnippet") @@ -119,7 +119,7 @@ public IntersectionState_EARLIEST_OPTIMAL() { @Benchmark public void intersection_EARLIEST_OPTIMAL(IntersectionState_EARLIEST_OPTIMAL s) { - s.schedule.apply(s.graph); + SchedulePhase.runWithoutContextOptimizations(s.graph, s.getSelectedStrategy()); } @MethodSpec(declaringClass = SchedulePhaseBenchmark.class, name = "intersectionSnippet") @@ -131,7 +131,7 @@ public IntersectionState_EARLIEST_WITH_GUARD_ORDER_OPTIMAL() { @Benchmark public void intersection_EARLIEST_WITH_GUARD_ORDER_OPTIMAL(IntersectionState_EARLIEST_WITH_GUARD_ORDER_OPTIMAL s) { - s.schedule.apply(s.graph); + SchedulePhase.runWithoutContextOptimizations(s.graph, s.getSelectedStrategy()); } // Checkstyle: resume method name check @@ -145,7 +145,7 @@ public ScheduleEarliestIterative_LATEST_OPTIMAL() { @Benchmark public void scheduleEarliestIterative_LATEST_OPTIMAL(ScheduleEarliestIterative_LATEST_OPTIMAL s) { - s.schedule.apply(s.graph); + SchedulePhase.runWithoutContextOptimizations(s.graph, s.getSelectedStrategy()); } @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative") @@ -157,7 +157,7 @@ public ScheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL() { @Benchmark public void scheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL(ScheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL s) { - s.schedule.apply(s.graph); + SchedulePhase.runWithoutContextOptimizations(s.graph, s.getSelectedStrategy()); } @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative") @@ -169,7 +169,7 @@ public ScheduleEarliestIterative_EARLIEST_OPTIMAL() { @Benchmark public void scheduleEarliestIterative_EARLIEST_OPTIMAL(ScheduleEarliestIterative_EARLIEST_OPTIMAL s) { - s.schedule.apply(s.graph); + SchedulePhase.runWithoutContextOptimizations(s.graph, s.getSelectedStrategy()); } @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative") @@ -181,7 +181,7 @@ public ScheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL() { @Benchmark public void scheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL(ScheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL s) { - s.schedule.apply(s.graph); + SchedulePhase.runWithoutContextOptimizations(s.graph, s.getSelectedStrategy()); } // Checkstyle: resume method name check } diff --git a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java index 434d5a30f717..9c621cddb796 100644 --- a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java +++ b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java @@ -27,14 +27,11 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.HighTierContext; public class ScheduleState extends GraphState { - public SchedulePhase schedule; - private final SchedulingStrategy selectedStrategy; public ScheduleState(SchedulingStrategy selectedStrategy) { @@ -45,10 +42,8 @@ public ScheduleState() { this(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); } - @Override - public void beforeInvocation() { - schedule = new SchedulePhase(selectedStrategy); - super.beforeInvocation(); + public SchedulingStrategy getSelectedStrategy() { + return selectedStrategy; } @Override diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java index ba9ba7b1b89e..25d1e232b507 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java @@ -77,6 +77,10 @@ public interface RecursiveVisitor { void exit(Block b, V value); } + public static ControlFlowGraph computeForSchedule(StructuredGraph graph) { + return compute(graph, true, true, true, false); + } + public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) { ControlFlowGraph cfg = new ControlFlowGraph(graph); cfg.identifyBlocks(); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java index 0d6f17e84f10..dc151a686aea 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java @@ -70,4 +70,9 @@ public interface LoweringProvider { */ boolean supportsRounding(); + /** + * Indicates whether this target platform supports the usage of implicit (trapping) null checks. + */ + boolean supportsImplicitNullChecks(); + } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java index 75691ae9c145..12d16801dd20 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java @@ -190,7 +190,7 @@ protected void run(StructuredGraph graph, CoreProviders context) { cfg.visitDominatorTree(new MoveGuardsUpwards(), graph.isBeforeStage(StageFlag.VALUE_PROXY_REMOVAL)); } try (DebugContext.Scope scheduleScope = graph.getDebug().scope(SchedulePhase.class)) { - SchedulePhase.run(graph, SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER, cfg); + SchedulePhase.run(graph, SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER, cfg, context, false); } catch (Throwable t) { throw graph.getDebug().handle(t); } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java index 7180e65fc88e..da3e25601d27 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java @@ -77,7 +77,6 @@ import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener; import org.graalvm.compiler.phases.graph.ScheduledNodeIterator; import org.graalvm.compiler.phases.schedule.SchedulePhase; @@ -104,7 +103,7 @@ public class FixReadsPhase extends BasePhase { private static final CounterKey counterBetterMergedStamps = DebugContext.counter("FixReads_BetterMergedStamp"); protected boolean replaceInputsWithConstants; - protected Phase schedulePhase; + protected BasePhase schedulePhase; protected CanonicalizerPhase canonicalizerPhase; @Override @@ -595,7 +594,7 @@ public void exit(Block b, Integer state) { } - public FixReadsPhase(boolean replaceInputsWithConstants, Phase schedulePhase, CanonicalizerPhase canonicalizerPhase) { + public FixReadsPhase(boolean replaceInputsWithConstants, BasePhase schedulePhase, CanonicalizerPhase canonicalizerPhase) { this.replaceInputsWithConstants = replaceInputsWithConstants; this.schedulePhase = schedulePhase; this.canonicalizerPhase = canonicalizerPhase; @@ -605,7 +604,7 @@ public FixReadsPhase(boolean replaceInputsWithConstants, Phase schedulePhase, Ca @SuppressWarnings("try") protected void run(StructuredGraph graph, CoreProviders context) { assert graph.verify(); - schedulePhase.apply(graph); + schedulePhase.apply(graph, context); ScheduleResult schedule = graph.getLastSchedule(); FixReadsClosure fixReadsClosure = new FixReadsClosure(); EconomicSetNodeEventListener ec = new EconomicSetNodeEventListener(); @@ -642,7 +641,7 @@ protected CharSequence getName() { protected void run(StructuredGraph graph, LowTierContext context) { if (GraalOptions.RawConditionalElimination.getValue(graph.getOptions())) { SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST, true); - schedulePhase.apply(graph); + schedulePhase.apply(graph, context); ScheduleResult schedule = graph.getLastSchedule(); schedule.getCFG().visitDominatorTree(new RawConditionalEliminationVisitor(graph, schedule, context.getMetaAccess(), replaceInputsWithConstants), false); } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java index 94be0fd4a1cc..6b89d95fff98 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java @@ -110,7 +110,7 @@ private void lowerToIf(GuardNode guard) { protected void run(StructuredGraph graph, CoreProviders context) { if (graph.getGuardsStage().allowsFloatingGuards()) { SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); - schedulePhase.apply(graph); + schedulePhase.apply(graph, context); ScheduleResult schedule = graph.getLastSchedule(); for (Block block : schedule.getCFG().getBlocks()) { diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java index c0e5d0db99eb..c71b8c737046 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java @@ -370,7 +370,7 @@ public boolean checkContract() { @Override public void run(StructuredGraph graph) { - schedulePhase.apply(graph, false); + schedulePhase.apply(graph, context, false); schedule = graph.getLastSchedule(); schedule.getCFG().computePostdominators(); Block startBlock = schedule.getCFG().getStartBlock(); diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java index b682e26d4ed2..95450a4bb237 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java @@ -103,10 +103,8 @@ private static String getProperty(String name, String def) { @Override protected void run(StructuredGraph graph) { - SchedulePhase schedule = new SchedulePhase(graph.getOptions()); - schedule.apply(graph, false); - ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); + SchedulePhase.runWithoutContextOptimizations(graph, SchedulePhase.getDefaultStrategy(graph.getOptions()), cfg, true); for (Loop loop : cfg.getLoops()) { double loopProbability = cfg.blockFor(loop.getHeader().getBeginNode()).getRelativeFrequency(); if (loopProbability > (1D / Integer.MAX_VALUE)) { diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java index e5035282a2a7..8f605e75d2a3 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java @@ -184,7 +184,7 @@ protected boolean shouldDumpAfterAtBasicLevel() { } @SuppressWarnings("try") - protected final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { + public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { if (ExcludePhaseFilter.exclude(graph.getOptions(), this, graph.asJavaMethod())) { return; } diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java index f1a1a86b0deb..dd5f43e06124 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java @@ -71,8 +71,7 @@ public static double computeGraphCycles(StructuredGraph graph, boolean fullSched Function> blockToNodes; ControlFlowGraph cfg; if (fullSchedule) { - SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS, true); - schedule.apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph, SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS, true); cfg = graph.getLastSchedule().getCFG(); blockToNodes = b -> graph.getLastSchedule().getBlockToNodesMap().get(b); } else { diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java index ce14a1970e53..4b3667f07091 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java @@ -85,12 +85,13 @@ import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.MultiMemoryKill; import org.graalvm.compiler.nodes.memory.SingleMemoryKill; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.ValueProxy; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.Phase; +import org.graalvm.compiler.phases.BasePhase; import org.graalvm.word.LocationIdentity; -public final class SchedulePhase extends Phase { +public final class SchedulePhase extends BasePhase { public enum SchedulingStrategy { EARLIEST_WITH_GUARD_ORDER, @@ -125,7 +126,7 @@ public SchedulePhase(OptionValues options) { } public SchedulePhase(boolean immutableGraph, OptionValues options) { - this(OptScheduleOutOfLoops.getValue(options) ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST, immutableGraph); + this(getDefaultStrategy(options), immutableGraph); } public SchedulePhase(SchedulingStrategy strategy) { @@ -137,6 +138,10 @@ public SchedulePhase(SchedulingStrategy strategy, boolean immutableGraph) { this.immutableGraph = immutableGraph; } + public static SchedulingStrategy getDefaultStrategy(OptionValues options) { + return OptScheduleOutOfLoops.getValue(options) ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST; + } + private NodeEventScope verifyImmutableGraph(StructuredGraph graph) { if (immutableGraph && Assertions.assertionsEnabled()) { return graph.trackNodeEvents(new NodeEventListener() { @@ -152,16 +157,33 @@ public void changed(NodeEvent e, Node node) { @Override @SuppressWarnings("try") - protected void run(StructuredGraph graph) { + protected void run(StructuredGraph graph, CoreProviders context) { try (NodeEventScope scope = verifyImmutableGraph(graph)) { - Instance inst = new Instance(); + Instance inst = new Instance(context.getLowerer().supportsImplicitNullChecks()); inst.run(graph, selectedStrategy, immutableGraph); } } - public static void run(StructuredGraph graph, SchedulingStrategy strategy, ControlFlowGraph cfg) { - Instance inst = new Instance(cfg); - inst.run(graph, strategy, false); + public static void runWithoutContextOptimizations(StructuredGraph graph) { + runWithoutContextOptimizations(graph, getDefaultStrategy(graph.getOptions())); + } + + public static void runWithoutContextOptimizations(StructuredGraph graph, SchedulingStrategy strategy) { + runWithoutContextOptimizations(graph, strategy, ControlFlowGraph.computeForSchedule(graph), false); + } + + public static void runWithoutContextOptimizations(StructuredGraph graph, SchedulingStrategy strategy, boolean immutable) { + runWithoutContextOptimizations(graph, strategy, ControlFlowGraph.computeForSchedule(graph), immutable); + } + + public static void runWithoutContextOptimizations(StructuredGraph graph, SchedulingStrategy strategy, ControlFlowGraph cfg, boolean immutable) { + Instance inst = new Instance(cfg, false); + inst.run(graph, strategy, immutable); + } + + public static void run(StructuredGraph graph, SchedulingStrategy strategy, ControlFlowGraph cfg, CoreProviders context, boolean immutable) { + Instance inst = new Instance(cfg, context.getLowerer().supportsImplicitNullChecks()); + inst.run(graph, strategy, immutable); } public static class Instance { @@ -173,19 +195,19 @@ public static class Instance { protected ControlFlowGraph cfg; protected BlockMap> blockToNodesMap; protected NodeMap nodeToBlockMap; + protected boolean supportsImplicitNullChecks; - public Instance() { - this(null); + public Instance(boolean supportsImplicitNullChecks) { + this(null, supportsImplicitNullChecks); } - public Instance(ControlFlowGraph cfg) { + public Instance(ControlFlowGraph cfg, boolean supportsImplicitNullChecks) { this.cfg = cfg; + this.supportsImplicitNullChecks = supportsImplicitNullChecks; } @SuppressWarnings("try") public void run(StructuredGraph graph, SchedulingStrategy selectedStrategy, boolean immutableGraph) { - // assert GraphOrder.assertNonCyclicGraph(graph); - if (this.cfg == null) { this.cfg = ControlFlowGraph.compute(graph, true, true, true, false); } @@ -206,7 +228,7 @@ public void run(StructuredGraph graph, SchedulingStrategy selectedStrategy, bool } BlockMap> watchListMap = calcLatestBlocks(selectedStrategy, currentNodeMap, earliestBlockToNodesMap, visited, latestBlockToNodesMap, immutableGraph); - sortNodesLatestWithinBlock(cfg, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited); + sortNodesLatestWithinBlock(cfg, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited, supportsImplicitNullChecks); assert verifySchedule(cfg, latestBlockToNodesMap, currentNodeMap); assert (!Assertions.detailedAssertionsEnabled(graph.getOptions())) || @@ -409,14 +431,14 @@ private static void fillKillSet(LocationSet killed, List subList) { } private static void sortNodesLatestWithinBlock(ControlFlowGraph cfg, BlockMap> earliestBlockToNodesMap, BlockMap> latestBlockToNodesMap, NodeMap currentNodeMap, - BlockMap> watchListMap, NodeBitMap visited) { + BlockMap> watchListMap, NodeBitMap visited, boolean supportsImplicitNullChecks) { for (Block b : cfg.getBlocks()) { - sortNodesLatestWithinBlock(b, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited); + sortNodesLatestWithinBlock(b, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited, supportsImplicitNullChecks); } } private static void sortNodesLatestWithinBlock(Block b, BlockMap> earliestBlockToNodesMap, BlockMap> latestBlockToNodesMap, NodeMap nodeMap, - BlockMap> watchListMap, NodeBitMap unprocessed) { + BlockMap> watchListMap, NodeBitMap unprocessed, boolean supportsImplicitNullChecks) { List earliestSorting = earliestBlockToNodesMap.get(b); ArrayList result = new ArrayList<>(earliestSorting.size()); ArrayList watchList = null; @@ -452,7 +474,7 @@ private static void sortNodesLatestWithinBlock(Block b, BlockMap> ear sortIntoList(n, b, result, nodeMap, unprocessed, null); } else if (nodeMap.get(n) == b && n instanceof FloatingReadNode) { FloatingReadNode floatingReadNode = (FloatingReadNode) n; - if (isImplicitNullOpportunity(floatingReadNode, b)) { + if (isImplicitNullOpportunity(floatingReadNode, b, supportsImplicitNullChecks)) { // Schedule at the beginning of the block. sortIntoList(floatingReadNode, b, result, nodeMap, unprocessed, null); } else { @@ -596,7 +618,7 @@ protected void calcLatestBlock(Block earliestBlock, SchedulingStrategy strategy, } } - if (latestBlock != earliestBlock && strategy.considerImplicitNullChecks() && isImplicitNullOpportunity(currentNode, earliestBlock) && + if (latestBlock != earliestBlock && strategy.considerImplicitNullChecks() && isImplicitNullOpportunity(currentNode, earliestBlock, supportsImplicitNullChecks) && earliestBlock.getRelativeFrequency() < latestBlock.getRelativeFrequency() * IMPLICIT_NULL_CHECK_OPPORTUNITY_PROBABILITY_FACTOR) { latestBlock = earliestBlock; } @@ -604,7 +626,10 @@ protected void calcLatestBlock(Block earliestBlock, SchedulingStrategy strategy, selectLatestBlock(currentNode, earliestBlock, latestBlock, currentNodeMap, watchListMap, constrainingLocation, latestBlockToNodesMap); } - protected static boolean isImplicitNullOpportunity(Node currentNode, Block block) { + protected static boolean isImplicitNullOpportunity(Node currentNode, Block block, boolean supportsImplicitNullChecks) { + if (!supportsImplicitNullChecks) { + return false; + } if (currentNode instanceof FloatingReadNode) { FloatingReadNode floatingReadNode = (FloatingReadNode) currentNode; Node pred = block.getBeginNode().predecessor(); diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java index 2eebfa16ecac..d9ca05e27db8 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java @@ -159,9 +159,8 @@ private static void visitForward(ArrayList nodes, NodeBitMap visited, Node public static boolean assertSchedulableGraph(final StructuredGraph graph) { assert graph.getGuardsStage() != GuardsStage.AFTER_FSA : "Cannot use the BlockIteratorClosure after FrameState Assignment, HIR Loop Data Structures are no longer valid."; try (DebugContext.Scope s = graph.getDebug().scope("AssertSchedulableGraph")) { - final SchedulePhase schedulePhase = new SchedulePhase(getSchedulingPolicy(graph), true); + SchedulePhase.runWithoutContextOptimizations(graph, getSchedulingPolicy(graph), true); final EconomicMap loopEntryStates = EconomicMap.create(Equivalence.IDENTITY); - schedulePhase.apply(graph, false); final ScheduleResult schedule = graph.getLastSchedule(); BlockIteratorClosure closure = new BlockIteratorClosure() { diff --git a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java index 1a1978fa47e2..018d1f2695c4 100644 --- a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java +++ b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java @@ -101,8 +101,7 @@ static ScheduleResult tryGetSchedule(DebugContext debug, StructuredGraph graph) // Also provide a schedule when an error occurs if (DebugOptions.PrintGraphWithSchedule.getValue(graph.getOptions()) || debug.contextLookup(Throwable.class) != null) { try (DebugCloseable noIntercept = debug.disableIntercept()) { - SchedulePhase schedule = new SchedulePhase(graph.getOptions()); - schedule.apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph); scheduleResult = graph.getLastSchedule(); } catch (Throwable t) { } diff --git a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java index e4ae066bc3ed..16b790efd6ec 100644 --- a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java +++ b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java @@ -249,8 +249,7 @@ static StructuredGraph.ScheduleResult getScheduleOrNull(Graph graph) { if (scheduleResult == null) { DebugContext debug = graph.getDebug(); try (Scope scope = debug.disable()) { - SchedulePhase schedule = new SchedulePhase(graph.getOptions()); - schedule.apply(sgraph); + SchedulePhase.runWithoutContextOptimizations(sgraph); scheduleResult = sgraph.getLastSchedule(); } catch (Throwable t) { } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java index 039abf9ef396..301056e12482 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java @@ -208,6 +208,11 @@ public void initialize(OptionValues options, Iterable fact providers.getReplacements().registerSnippetTemplateCache(new SnippetCounterNode.SnippetCounterSnippets.Templates(options, factories, providers, snippetReflection, target)); } + @Override + public boolean supportsImplicitNullChecks() { + return target.implicitNullCheckLimit > 0; + } + public final TargetDescription getTarget() { return target; } diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/ExpansionStatistics.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/ExpansionStatistics.java index f7896f79c9ec..0b082d3f76e8 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/ExpansionStatistics.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/ExpansionStatistics.java @@ -294,8 +294,7 @@ private static int orderBySumDesc(Entry e0, Entry e1) { private static TreeNode buildMethodTree(StructuredGraph graph) { TreeNode root = new TreeNode(null, null, ExpansionStatistics::buildMethodTreeLabel); - SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS, true); - schedule.apply(graph); + SchedulePhase.runWithoutContextOptimizations(graph, SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS, true); ControlFlowGraph cfg = graph.getLastSchedule().getCFG(); for (Node node : graph.getNodes()) { NodeSourcePosition nodeSourcePosition = node.getNodeSourcePosition(); diff --git a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java index 66f4511bb201..e0f37ee06461 100644 --- a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java +++ b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java @@ -95,7 +95,7 @@ public boolean runAnalysis(StructuredGraph graph, CoreProvidersT context) { schedule = null; cfg = ControlFlowGraph.compute(graph, true, true, false, false); } else { - new SchedulePhase(strategy).apply(graph, false); + new SchedulePhase(strategy).apply(graph, context, false); schedule = graph.getLastSchedule(); cfg = schedule.getCFG(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateLoweringProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateLoweringProvider.java index bc7e984939fe..4f75702cb5ac 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateLoweringProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateLoweringProvider.java @@ -61,4 +61,8 @@ static LoweringProvider create(MetaAccessProvider metaAccess, ForeignCallsProvid } + @Override + default boolean supportsImplicitNullChecks() { + return false; + } } From 5d4e39ce7da51854489c944a2454a3d81c18f99d Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Mon, 6 Sep 2021 10:21:32 +0200 Subject: [PATCH 055/681] address review comments --- .../DefaultJavaLoweringProvider.java | 4 ++++ .../meta/SubstrateBasicLoweringProvider.java | 3 ++- .../svm/core/graal/snippets/TypeSnippets.java | 19 ++++++++----------- .../word/SubstrateWordOperationPlugins.java | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java index 301056e12482..1c69da41509f 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java @@ -627,6 +627,10 @@ protected void lowerLoadHubOrNullNode(LoadHubOrNullNode loadHubOrNullNode, Lower } ValueNode object = loadHubOrNullNode.getValue(); if (object.isConstant() && !object.asJavaConstant().isNull()) { + /* + * Special case: insufficient canonicalization was run since the last lowering, if we + * are loading the hub from a constant we want to still fold it. + */ ValueNode synonym = LoadHubNode.findSynonym(object, loadHubOrNullNode.stamp(NodeView.DEFAULT), tool.getMetaAccess(), tool.getConstantReflection()); if (synonym != null) { loadHubOrNullNode.replaceAtUsagesAndDelete(graph.maybeAddOrUnique(synonym)); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java index 6869ecabd713..a57361ac5bf7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; import org.graalvm.compiler.nodes.ConstantNode; @@ -175,7 +176,7 @@ protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, Lower return graph.unique(new LoadHubNode(tool.getStampProvider(), object)); } - assert !object.isConstant() || object.asJavaConstant().isNull() : "Object should either not be a constant or the null constant" + object; + GraalError.guarantee(!object.isConstant() || object.asJavaConstant().isNull(), "Object should either not be a constant or the null constant %s", object); ObjectLayout objectLayout = getObjectLayout(); Stamp headerBitsStamp = StampFactory.forUnsignedInteger(8 * objectLayout.getReferenceSize()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/TypeSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/TypeSnippets.java index fc62f5662a3a..ec5bf7fd65c3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/TypeSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/TypeSnippets.java @@ -96,9 +96,8 @@ protected static SubstrateIntrinsics.Any instanceOfSnippet( } GuardingNode guard = SnippetAnchorNode.anchor(); Object nonNullObject = PiNode.piCastNonNull(object, guard); - DynamicHub hubNoneNull = loadHub(nonNullObject); - // no need to guard, guarded via hub - return slotTypeCheck(start, range, slot, typeIDSlotOffset, hubNoneNull, trueValue, falseValue, null); + DynamicHub nonNullHub = loadHub(nonNullObject); + return slotTypeCheck(start, range, slot, typeIDSlotOffset, nonNullHub, trueValue, falseValue); } @Snippet @@ -117,9 +116,8 @@ protected static SubstrateIntrinsics.Any instanceOfDynamicSnippet( } GuardingNode guard = SnippetAnchorNode.anchor(); Object nonNullObject = PiNode.piCastNonNull(object, guard); - DynamicHub hubNoneNull = loadHub(nonNullObject); - // no need to guard, guarded via hub - return slotTypeCheck(type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), typeIDSlotOffset, hubNoneNull, trueValue, falseValue, null); + DynamicHub nonNullHub = loadHub(nonNullObject); + return slotTypeCheck(type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), typeIDSlotOffset, nonNullHub, trueValue, falseValue); } @Snippet @@ -129,8 +127,7 @@ protected static SubstrateIntrinsics.Any classIsAssignableFromSnippet( SubstrateIntrinsics.Any trueValue, SubstrateIntrinsics.Any falseValue, @Snippet.ConstantParameter int typeIDSlotOffset) { - // no guard needed, b guaranteed to be non null - return slotTypeCheck(type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), typeIDSlotOffset, checkedHub, trueValue, falseValue, null); + return slotTypeCheck(type.getTypeCheckStart(), type.getTypeCheckRange(), type.getTypeCheckSlot(), typeIDSlotOffset, checkedHub, trueValue, falseValue); } @DuplicatedInNativeCode @@ -139,13 +136,13 @@ private static SubstrateIntrinsics.Any slotTypeCheck( int typeIDSlotOffset, DynamicHub checkedHub, SubstrateIntrinsics.Any trueValue, - SubstrateIntrinsics.Any falseValue, GuardingNode guard) { + SubstrateIntrinsics.Any falseValue) { int typeCheckStart = Short.toUnsignedInt(start); int typeCheckRange = Short.toUnsignedInt(range); int typeCheckSlot = Short.toUnsignedInt(slot) * 2; - + // No need to guard reading from hub as `checkedHub` is guaranteed to be non-null. + final GuardingNode guard = null; int checkedTypeID = Short.toUnsignedInt(DynamicHubAccess.readShort(checkedHub, typeIDSlotOffset + typeCheckSlot, NamedLocationIdentity.FINAL_LOCATION, guard)); - if (UnsignedMath.belowThan(checkedTypeID - typeCheckStart, typeCheckRange)) { return trueValue; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java index 62c782a0fda7..248e60b1e005 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java @@ -70,7 +70,7 @@ protected void processSubstrateOperation(GraphBuilderContext b, ResolvedJavaMeth switch (operation.opcode()) { case READ_FROM_HUB: JavaKind returnKind = method.getSignature().getReturnKind(); - assert args.length == 4 : "arg length=" + args.length + " operation=" + operation; + GraalError.guarantee(args.length == 4, "arg length=%d operation=%s", args.length, operation); JavaKind readKind = wordTypes.asKind(method.getSignature().getReturnType(method.getDeclaringClass())); AddressNode address = makeAddress(b, args[0], args[1]); LocationIdentity location; From dcb74580d6f4c0b5685c08dd0e7c17327bbb4698 Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Mon, 20 Sep 2021 16:10:13 +0200 Subject: [PATCH 056/681] Bump ci-overlay version --- graal-common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graal-common.json b/graal-common.json index 13410b510ccd..e6854c6c3b14 100644 --- a/graal-common.json +++ b/graal-common.json @@ -1,7 +1,7 @@ { "README": "This file contains definitions that are useful for the hocon and jsonnet CI files of the graal and graal-enterprise repositories.", "ci": { - "overlay": "b6feed939cb56920c218bad4cd64e2f475eaacf1" + "overlay": "32cfe3bc1cae2b79569d17017dc83ba8d494a4c9" }, "mx_version" : "HEAD" } From 02e6ef6726fdefbecaffda62886dc8941fec58de Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Mon, 20 Sep 2021 16:12:42 +0200 Subject: [PATCH 057/681] Prevent timeouts in dacapo weekly forks --- compiler/ci_common/benchmark-suites.libsonnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ci_common/benchmark-suites.libsonnet b/compiler/ci_common/benchmark-suites.libsonnet index 27cde8cf4168..187f49a3a176 100644 --- a/compiler/ci_common/benchmark-suites.libsonnet +++ b/compiler/ci_common/benchmark-suites.libsonnet @@ -42,7 +42,7 @@ ], timelimit: "45:00", forks_batches:: 1, - forks_timelimit:: "02:45:00", + forks_timelimit:: "04:00:00", min_jdk_version:: 8, max_jdk_version:: null }, From b4030240301c95f3c3d357c7f8b5ba666a61cac0 Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Mon, 20 Sep 2021 18:23:57 +0200 Subject: [PATCH 058/681] Add renaissance 0.12.0 and 0.13.0 --- .../mx.java-benchmarks/mx_java_benchmarks.py | 15 +++++++++++++-- java-benchmarks/mx.java-benchmarks/suite.py | 10 ++++++++++ .../mx.substratevm/mx_substratevm_benchmark.py | 2 +- substratevm/mx.substratevm/suite.py | 10 ++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py index bd89ba573067..dd5c0d0ab500 100644 --- a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py +++ b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py @@ -1839,16 +1839,27 @@ def renaissanceIterations(self): benchmarks = _renaissanceConfig.copy() if self.version() == "0.9.0": del benchmarks["scala-doku"] # was introduced in 0.10.0 + if mx.get_jdk().javaCompliance >= '17' and self.version() in ["0.9.0", "0.10.0", "0.11.0", "0.12.0"]: + # JDK17 support for Spark benchmarks was added in 0.13.0 + # See: https://github.com/renaissance-benchmarks/renaissance/issues/295 + del benchmarks["als"] + del benchmarks["chi-square"] + del benchmarks["dec-tree"] + del benchmarks["gauss-mix"] + del benchmarks["log-regression"] + del benchmarks["movie-lens"] + del benchmarks["naive-bayes"] + del benchmarks["page-rank"] return benchmarks def version(self): return super(RenaissanceBenchmarkSuite, self).version() def defaultSuiteVersion(self): - return "0.11.0" + return self.availableSuiteVersions()[-1] def availableSuiteVersions(self): - return ["0.9.0", "0.10.0", "0.11.0"] + return ["0.9.0", "0.10.0", "0.11.0", "0.12.0", "0.13.0"] def renaissancePath(self): lib = mx.library(self.renaissanceLibraryName()) diff --git a/java-benchmarks/mx.java-benchmarks/suite.py b/java-benchmarks/mx.java-benchmarks/suite.py index 5a6d8bfad05b..3cd82714bd1e 100644 --- a/java-benchmarks/mx.java-benchmarks/suite.py +++ b/java-benchmarks/mx.java-benchmarks/suite.py @@ -77,6 +77,16 @@ "sha1" : "613f7615179ea364116cdd68aa41ad44a9cc49e4", }, + "RENAISSANCE_0.12.0" : { + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/renaissance/renaissance-gpl-0.12.0.jar"], + "sha1" : "5bf404f875622a714f9b5c772b52ad857b97658d", + }, + + "RENAISSANCE_0.13.0" : { + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/renaissance/renaissance-gpl-0.13.0.jar"], + "sha1" : "65eaca6ec6ba4c7293b82644bbdefd5cb2178825", + }, + "UBENCH_AGENT_DIST" : { "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/java-ubench-agent-2e5becaf97afcf64fd8aef3ac84fc05a3157bff5.zip"], "sha1" : "19087a34b80be8845e9a3e7f927ceb592de83762", diff --git a/substratevm/mx.substratevm/mx_substratevm_benchmark.py b/substratevm/mx.substratevm/mx_substratevm_benchmark.py index 0db79674e2a4..ab64cb709e27 100644 --- a/substratevm/mx.substratevm/mx_substratevm_benchmark.py +++ b/substratevm/mx.substratevm/mx_substratevm_benchmark.py @@ -166,7 +166,7 @@ def harness_path(self): # Before supporting new Renaissance versions, we must cross-compile Renaissance harness project # with scala 11 for benchmarks compiled with this version of Scala. def availableSuiteVersions(self): - return ["0.9.0", "0.10.0", "0.11.0"] + return ["0.9.0", "0.10.0", "0.11.0", "0.12.0", "0.13.0"] def renaissance_unpacked(self): return extract_archive(self.renaissancePath(), 'renaissance.extracted') diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 31e8543fad08..0de5c71a4e7d 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -53,6 +53,16 @@ "sha1" : "8d402c1e7c972badfcffdd6c64ed4e791b0dea02", "packedResource": True, }, + "RENAISSANCE_HARNESS_v0.12" : { + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/renaissance/renaissance-harness_v0.12.0.tar.gz"], + "sha1" : "c061f62ce6f2758ec30b92e69f20f14b93e34b35", + "packedResource": True, + }, + "RENAISSANCE_HARNESS_v0.13" : { + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/renaissance/renaissance-harness_v0.13.0.tar.gz"], + "sha1" : "ca32c080016c5659bbf3eddc184e14b742769372", + "packedResource": True, + }, "DACAPO_SVM" : { "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/dacapo-9.12-native-image.jar"], "sha1" : "5d534f0b7aa9124d9797a180688468d2f126039a", From 736f76a1f168c750fbe722fac1180dfc0a44c8b5 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Thu, 26 Aug 2021 16:34:12 +0200 Subject: [PATCH 059/681] Conditionalize loading of JNI library 'harfbuzz' It only was a separate library for a while in OpenJDK [11.0.10, 11.0.12], OracleJDK [11.0.10, 11.0.11] and OpenJDK 16. The patch got reverted later on. Only add the extra library when it's actually needed. --- .../hosted/jdk/JNIRegistrationAWTSupport.java | 17 ++++++++++++++++- .../svm/hosted/jdk/JNIRegistrationAwt.java | 16 +++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAWTSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAWTSupport.java index 1fbae0accd3e..dcf75b097238 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAWTSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAWTSupport.java @@ -25,6 +25,10 @@ package com.oracle.svm.hosted.jdk; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; + +import java.util.Optional; + +import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.hosted.Feature; @@ -32,9 +36,15 @@ import com.oracle.svm.core.annotate.AutomaticFeature; import com.oracle.svm.hosted.FeatureImpl.BeforeImageWriteAccessImpl; +import jdk.vm.ci.services.Services; + @Platforms(Platform.WINDOWS.class) @AutomaticFeature public class JNIRegistrationAWTSupport implements Feature { + + private static final int JDK_UPDATE = GraalServices.getJavaUpdateVersion(); + private static final boolean IS_OPENJDK = Optional.ofNullable(Services.getSavedProperties().get("java.vm.name")).orElse("").startsWith("OpenJDK"); + @Override public void beforeImageWrite(BeforeImageWriteAccess access) { JNIRegistrationSupport jniRegistrationSupport = JNIRegistrationSupport.singleton(); @@ -79,7 +89,12 @@ public void beforeImageWrite(BeforeImageWriteAccess access) { jniRegistrationSupport.addJavaShimExports( "JNU_ThrowClassNotFoundException"); } - if (jniRegistrationSupport.isRegisteredLibrary("fontmanager") && JavaVersionUtil.JAVA_SPEC >= 11) { + // harfbuzz became a separate library in OpenJDK 16/11.0.10 (JDK-8249821) and then went back + // to be included in fontmanager library in OpenJDK 17/11.0.13 (or 11.0.12 for OracleJDK). + // See JDK-8255790. + int jdk11HbUpdateBound = IS_OPENJDK ? 12 : 11; + if (jniRegistrationSupport.isRegisteredLibrary("fontmanager") && + ((JavaVersionUtil.JAVA_SPEC == 11 && JDK_UPDATE >= 10 && JDK_UPDATE <= jdk11HbUpdateBound) || JavaVersionUtil.JAVA_SPEC == 16)) { /* * Dependency on `harfbuzz` may not be expressed in Java, so we register it manually * here just in case. diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAwt.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAwt.java index d3f4f829fb93..3586b1225d3a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAwt.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAwt.java @@ -33,7 +33,11 @@ import com.oracle.svm.core.jni.JNIRuntimeAccess; import com.oracle.svm.hosted.FeatureImpl; import com.oracle.svm.hosted.c.NativeLibraries; + +import jdk.vm.ci.services.Services; + import org.graalvm.compiler.serviceprovider.JavaVersionUtil; +import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -42,12 +46,16 @@ import org.graalvm.nativeimage.impl.InternalPlatform; import java.awt.GraphicsEnvironment; +import java.util.Optional; @Platforms({InternalPlatform.PLATFORM_JNI.class}) @AutomaticFeature @SuppressWarnings({"unused"}) public class JNIRegistrationAwt extends JNIRegistrationUtil implements Feature { + private static final int JDK_UPDATE = GraalServices.getJavaUpdateVersion(); + private static final boolean IS_OPENJDK = Optional.ofNullable(Services.getSavedProperties().get("java.vm.name")).orElse("").startsWith("OpenJDK"); + @Override public void beforeAnalysis(BeforeAnalysisAccess access) { if (JavaVersionUtil.JAVA_SPEC >= 11 && Platform.includedIn(Platform.LINUX.class)) { @@ -161,7 +169,13 @@ private static void registerFreeType(DuringAnalysisAccess access) { NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("fontmanager"); nativeLibraries.addStaticJniLibrary("fontmanager", isHeadless() ? "awt_headless" : "awt_xawt"); - nativeLibraries.addStaticJniLibrary("harfbuzz"); + // harfbuzz became a separate library in OpenJDK 16/11.0.10 (JDK-8249821) and then went back + // to be included in fontmanager library in OpenJDK 17/11.0.13 (or 11.0.12 for OracleJDK). + // See JDK-8255790. + int jdk11HbUpdateBound = IS_OPENJDK ? 12 : 11; + if (JavaVersionUtil.JAVA_SPEC == 16 || (JavaVersionUtil.JAVA_SPEC == 11 && JDK_UPDATE >= 10 && JDK_UPDATE <= jdk11HbUpdateBound)) { + nativeLibraries.addStaticJniLibrary("harfbuzz"); + } nativeLibraries.addDynamicNonJniLibrary("freetype"); From e3df2fbb0b009823037a61fc2ac95142e9322335 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Fri, 17 Sep 2021 15:38:54 -0700 Subject: [PATCH 060/681] Remove analysis Arrays.copyOf optimization. --- .../pointsto/flow/MethodTypeFlowBuilder.java | 103 ------------------ .../nodes/AnalysisArraysCopyOfNode.java | 79 -------------- .../plugins/PointstoGraphBuilderPlugins.java | 28 ----- 3 files changed, 210 deletions(-) delete mode 100644 substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/nodes/AnalysisArraysCopyOfNode.java diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java index 2157a3fb4b28..e7172a1cf51f 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java @@ -121,7 +121,6 @@ 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.nodes.AnalysisArraysCopyOfNode; import com.oracle.graal.pointsto.nodes.UnsafePartitionLoadNode; import com.oracle.graal.pointsto.nodes.UnsafePartitionStoreNode; import com.oracle.graal.pointsto.phases.InlineBeforeAnalysis; @@ -129,7 +128,6 @@ import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaKind; public class MethodTypeFlowBuilder { @@ -1171,10 +1169,6 @@ protected void node(FixedNode n) { state.add(node, wordToObjectBuilder); } - } else if (n instanceof AnalysisArraysCopyOfNode) { - AnalysisArraysCopyOfNode node = (AnalysisArraysCopyOfNode) n; - processArraysCopyOf(node, node.getOriginal(), node.getNewArrayType(), state); - } else if (n instanceof InvokeNode || n instanceof InvokeWithExceptionNode) { Invoke invoke = (Invoke) n; if (invoke.callTarget() instanceof MethodCallTargetNode) { @@ -1496,101 +1490,4 @@ protected NewInstanceTypeFlow createNewArrayTypeFlow(NewArrayNode node, Analysis protected void checkUnsafeOffset(@SuppressWarnings("unused") ValueNode base, @SuppressWarnings("unused") ValueNode offset) { } - protected void processArraysCopyOf(ValueNode node, ValueNode original, ValueNode newArrayType, TypeFlowsOfNodes state) { - TypeFlowBuilder originalArrayBuilder = state.lookup(original); - - Object key = uniqueKey(node); - BytecodeLocation newArrayLabel = bb.analysisPolicy().createAllocationSite(bb, key, methodFlow.getMethod()); - - /* - * Arrays.copyOf is essentially a dynamic new instance plus a System.arrayCopy. - */ - - /* - * First we determine the type of the new array and create a dynamic new instance flow to - * allocate it. - */ - TypeFlowBuilder newArrayTypeBuilder; - if (newArrayType == null) { - /* - * The type of the new array and that of the original are the same. The dynamic new - * instance flow will create a new heap object for each incoming type and for each - * different heap context. - */ - newArrayTypeBuilder = originalArrayBuilder; - } else { - /* - * The type of the new array and that of the original are different. The elements are - * copied from the original array but the type of the resulting objects are given by the - * new type. Both the original 'values' and the 'new type' are needed for a proper - * intercept when the analysis is context sensitive. - */ - newArrayTypeBuilder = getDynamicTypeFlow(node, newArrayType, true, state); - } - - TypeFlowBuilder newArrayBuilder = TypeFlowBuilder.create(bb, node, DynamicNewInstanceTypeFlow.class, () -> { - DynamicNewInstanceTypeFlow newArrayFlow = new DynamicNewInstanceTypeFlow(newArrayTypeBuilder.get(), bb.getObjectArrayType(), node, newArrayLabel); - methodFlow.addMiscEntry(newArrayFlow); - return newArrayFlow; - }); - - if (newArrayType != null && (newArrayType instanceof GetClassNode || newArrayType.isConstant())) { - newArrayBuilder.addObserverDependency(newArrayTypeBuilder); - } - - state.add(node, newArrayBuilder); - - /* - * Then we use an array copy type flow to propagate the elements type state from the - * original array into the copy. - */ - TypeFlowBuilder arrayCopyBuilder = TypeFlowBuilder.create(bb, node, ArrayCopyTypeFlow.class, () -> { - ArrayCopyTypeFlow arrayCopyFlow = new ArrayCopyTypeFlow(node, null, originalArrayBuilder.get(), newArrayBuilder.get()); - methodFlow.addMiscEntry(arrayCopyFlow); - return arrayCopyFlow; - }); - - arrayCopyBuilder.addObserverDependency(originalArrayBuilder); - arrayCopyBuilder.addObserverDependency(newArrayBuilder); - - /* Array copies must not be removed. */ - typeFlowGraphBuilder.registerSinkBuilder(arrayCopyBuilder); - } - - /** - * Get the type flow of a dynamic type. If the type results from a GetClassNode or a - * JavaConstant this method will return accurate type information. Otherwise it will return all - * instantiated types or, if it is an array, all instantiated array types. - */ - protected TypeFlowBuilder getDynamicTypeFlow(ValueNode node, ValueNode typeSource, boolean isArrayType, TypeFlowsOfNodes state) { - TypeFlowBuilder dynamicTypeBuilder; - if (typeSource instanceof GetClassNode) { - GetClassNode getClassNode = (GetClassNode) typeSource; - dynamicTypeBuilder = state.lookup(getClassNode.getObject()); - - } else if (typeSource.isConstant()) { - assert state.lookup(typeSource).getFlowClass() == SourceTypeFlow.class; - - Constant constant = typeSource.asJavaConstant(); - AnalysisType exactType = (AnalysisType) bb.getProviders().getConstantReflection().asJavaType(constant); - exactType.registerAsAllocated(node); - - dynamicTypeBuilder = TypeFlowBuilder.create(bb, node, SourceTypeFlow.class, () -> { - SourceTypeFlow dynamicTypeFlow = new SourceTypeFlow(node, TypeState.forExactType(bb, exactType, false)); - methodFlow.addMiscEntry(dynamicTypeFlow); - return dynamicTypeFlow; - }); - } else { - /* - * Without precise type information either the type flow corresponding to all - * instantiated object types or all instantiated array types will be returned. - */ - AnalysisType arrayType = isArrayType ? bb.getObjectArrayType() : bb.getObjectType(); - dynamicTypeBuilder = TypeFlowBuilder.create(bb, node, AllInstantiatedTypeFlow.class, () -> { - return arrayType.getTypeFlow(bb, false); - }); - } - - return dynamicTypeBuilder; - } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/nodes/AnalysisArraysCopyOfNode.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/nodes/AnalysisArraysCopyOfNode.java deleted file mode 100644 index 73a9e41d9e52..000000000000 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/nodes/AnalysisArraysCopyOfNode.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 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.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; - -import jdk.vm.ci.meta.ConstantReflectionProvider; -import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; - -@NodeInfo(size = SIZE_IGNORED, cycles = CYCLES_IGNORED) -public class AnalysisArraysCopyOfNode extends FixedWithNextNode implements ArrayLengthProvider { - public static final NodeClass TYPE = NodeClass.create(AnalysisArraysCopyOfNode.class); - - @Input ValueNode original; - @Input ValueNode newLength; - @OptionalInput ValueNode newArrayType; - - public AnalysisArraysCopyOfNode(@InjectedNodeParameter Stamp stamp, ValueNode original, ValueNode newLength) { - this(stamp, original, newLength, null); - } - - public AnalysisArraysCopyOfNode(@InjectedNodeParameter Stamp stamp, ValueNode original, ValueNode newLength, ValueNode newArrayType) { - super(TYPE, computeStamp(stamp)); - this.original = original; - this.newLength = newLength; - this.newArrayType = newArrayType; - } - - public ValueNode getOriginal() { - return original; - } - - public ValueNode getNewArrayType() { - return newArrayType; - } - - @Override - public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider constantReflection) { - return newLength; - } - - private static Stamp computeStamp(Stamp result) { - if (result instanceof ObjectStamp) { - return result.join(StampFactory.objectNonNull()); - } - return result; - } - -} diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/plugins/PointstoGraphBuilderPlugins.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/plugins/PointstoGraphBuilderPlugins.java index b4f27ef4cad5..1453aec85c53 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/plugins/PointstoGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/plugins/PointstoGraphBuilderPlugins.java @@ -24,10 +24,7 @@ */ package com.oracle.graal.pointsto.plugins; -import java.util.Arrays; - import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; @@ -36,7 +33,6 @@ import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; import org.graalvm.compiler.replacements.nodes.MacroNode.MacroParams; -import com.oracle.graal.pointsto.nodes.AnalysisArraysCopyOfNode; import com.oracle.graal.pointsto.nodes.AnalysisObjectCloneNode; import jdk.vm.ci.meta.JavaKind; @@ -44,30 +40,6 @@ public class PointstoGraphBuilderPlugins { - public static void registerArraysPlugins(InvocationPlugins plugins) { - Registration r = new Registration(plugins, Arrays.class).setAllowOverwrite(true); - - r.register2("copyOf", Object[].class, int.class, new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode original, ValueNode newLength) { - b.addPush(JavaKind.Object, new AnalysisArraysCopyOfNode(b.getInvokeReturnStamp(b.getAssumptions()).getTrustedStamp(), original, newLength)); - return true; - } - }); - - r.register3("copyOf", Object[].class, int.class, Class.class, new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode original, ValueNode newLength, ValueNode newObjectElementType) { - if (newObjectElementType instanceof GetClassNode || newObjectElementType.isConstant()) { - // We can infer the concrete type of the new array - b.addPush(JavaKind.Object, new AnalysisArraysCopyOfNode(b.getInvokeReturnStamp(b.getAssumptions()).getTrustedStamp(), original, newLength, newObjectElementType)); - return true; - } - return false; - } - }); - } - public static void registerSystemPlugins(InvocationPlugins plugins) { Registration r = new Registration(plugins, System.class).setAllowOverwrite(true); r.register5("arraycopy", Object.class, int.class, Object.class, int.class, int.class, new InvocationPlugin() { From dbeba5eb16bb3580a761f00653deb68f59770fd6 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Fri, 17 Sep 2021 15:49:26 -0700 Subject: [PATCH 061/681] Filter MacroInvokable return when the inferred stamp is more precise the the return type. --- .../pointsto/flow/MethodTypeFlowBuilder.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java index e7172a1cf51f..58e5bc85844e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java @@ -1330,6 +1330,25 @@ private void processMethodInvocation(ValueNode invoke, InvokeKind invokeKind, in return actualReturn; }); + ObjectStamp stamp = (ObjectStamp) invoke.stamp(NodeView.DEFAULT); + if (stamp.nonNull() && !returnType.equals(stamp.type()) && returnType.isAssignableFrom(stamp.type())) { + /* + * If the invoke stamp has a more precise type than the return type use that to + * filter the returned values. This can happen for example for MacroInvokable + * nodes when more concrete stamp information can be inferred for example from + * parameter types. In that case the Graal graph optimizations may decide to + * remove a checkcast that would normally follow the invoke, so we need to + * introduce the filter to avoid loosing precision. + */ + TypeFlowBuilder filterBuilder = TypeFlowBuilder.create(bb, invoke, FilterTypeFlow.class, () -> { + FilterTypeFlow filterFlow = new FilterTypeFlow(invoke, (AnalysisType) stamp.type(), stamp.isExactType(), true, true); + methodFlow.addMiscEntry(filterFlow); + return filterFlow; + }); + filterBuilder.addUseDependency(actualReturnBuilder); + actualReturnBuilder = filterBuilder; + } + if (bb.strengthenGraalGraphs()) { typeFlowGraphBuilder.registerSinkBuilder(actualReturnBuilder); } From 7333e1db43a7f3738d0783a83d1a3d8cfb2daf9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Mon, 20 Sep 2021 22:42:39 +0200 Subject: [PATCH 062/681] Remove obsolete JUnit substitution --- .../Target_org_junit_runner_Description.java | 57 ------------------- ...get_org_junit_runners_model_TestClass.java | 13 +++-- 2 files changed, 7 insertions(+), 63 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.junit/src/com/oracle/svm/junit/Target_org_junit_runner_Description.java diff --git a/substratevm/src/com.oracle.svm.junit/src/com/oracle/svm/junit/Target_org_junit_runner_Description.java b/substratevm/src/com.oracle.svm.junit/src/com/oracle/svm/junit/Target_org_junit_runner_Description.java deleted file mode 100644 index 733f3e2356f9..000000000000 --- a/substratevm/src/com.oracle.svm.junit/src/com/oracle/svm/junit/Target_org_junit_runner_Description.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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.junit; - -import org.junit.runner.Description; - -import com.oracle.svm.core.annotate.Alias; -import com.oracle.svm.core.annotate.RecomputeFieldValue; -import com.oracle.svm.core.annotate.RecomputeFieldValue.CustomFieldValueComputer; -import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind; -import com.oracle.svm.core.annotate.Substitute; -import com.oracle.svm.core.annotate.TargetClass; - -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaField; - -@TargetClass(className = "org.junit.runner.Description", onlyWith = JUnitFeature.IsEnabled.class) -public final class Target_org_junit_runner_Description { - - public static final class TestClassComputer implements CustomFieldValueComputer { - - @Override - public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - Description description = (Description) receiver; - return description.getTestClass(); - } - } - - @Alias @RecomputeFieldValue(kind = Kind.Custom, declClass = TestClassComputer.class) Class fTestClass; - - @Substitute - public Class getTestClass() { - return fTestClass; - } -} diff --git a/substratevm/src/com.oracle.svm.junit/src/com/oracle/svm/junit/Target_org_junit_runners_model_TestClass.java b/substratevm/src/com.oracle.svm.junit/src/com/oracle/svm/junit/Target_org_junit_runners_model_TestClass.java index 66f1ade67a62..5edc311842df 100644 --- a/substratevm/src/com.oracle.svm.junit/src/com/oracle/svm/junit/Target_org_junit_runners_model_TestClass.java +++ b/substratevm/src/com.oracle.svm.junit/src/com/oracle/svm/junit/Target_org_junit_runners_model_TestClass.java @@ -28,12 +28,11 @@ import java.lang.reflect.Constructor; -import com.oracle.svm.core.annotate.Alias; -import jdk.vm.ci.meta.MetaAccessProvider; import org.graalvm.nativeimage.hosted.RuntimeReflection; import org.junit.Assert; import org.junit.runners.model.TestClass; +import com.oracle.svm.core.annotate.Alias; import com.oracle.svm.core.annotate.Inject; import com.oracle.svm.core.annotate.RecomputeFieldValue; import com.oracle.svm.core.annotate.RecomputeFieldValue.CustomFieldValueComputer; @@ -41,18 +40,20 @@ import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; @TargetClass(className = "org.junit.runners.model.TestClass", onlyWith = JUnitFeature.IsEnabled.class) public final class Target_org_junit_runners_model_TestClass { public static final class OnlyConstructorComputer implements CustomFieldValueComputer { - @Override public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - TestClass clazz = (TestClass) receiver; - if (clazz.getJavaClass() != null) { - Constructor constructor = clazz.getOnlyConstructor(); + TestClass testClass = (TestClass) receiver; + if (testClass.getJavaClass() != null) { + /* Make sure Class.forName works because Description.getTestClass can use it. */ + RuntimeReflection.register(testClass.getJavaClass()); + Constructor constructor = testClass.getOnlyConstructor(); RuntimeReflection.register(constructor); return constructor; } else { From 96bc6229464bb5e115e65e3d1bc712a226eee911 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Fri, 4 Jun 2021 20:00:06 +0200 Subject: [PATCH 063/681] Add helper method to AArch64Address. --- .../org/graalvm/compiler/asm/aarch64/AArch64Address.java | 9 +++++++++ .../graalvm/compiler/asm/aarch64/AArch64Assembler.java | 2 +- .../replacements/arraycopy/ArrayCopyCallNode.java | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java index f7cd220d04df..da9733e7ee79 100644 --- a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java +++ b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java @@ -315,6 +315,15 @@ public static AArch64Address createPCLiteralAddress(int bitMemoryTransferSize) { return new AArch64Address(bitMemoryTransferSize, zr, zr, 0, false, null, AddressingMode.PC_LITERAL); } + /** + * @param bitMemoryTransferSize Memory operation size. + * @param base May not be null or the zero register. + * @return an address specifying the address pointed to by base. + */ + public static AArch64Address createPairBaseRegisterOnlyAddress(int bitMemoryTransferSize, Register base) { + return createImmediateAddress(bitMemoryTransferSize, AddressingMode.IMMEDIATE_PAIR_SIGNED_SCALED, base, 0); + } + /** * AArch64Address specifying a structure memory access of the form "[Xn|SP]". */ diff --git a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java index 479122cbc938..bd38d2f567dd 100755 --- a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java +++ b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java @@ -1077,7 +1077,7 @@ private void unconditionalBranchRegInstruction(Instruction instr, Register reg) /** * Returns the log2 size of the number of bytes expected to be transferred. */ - protected static int getLog2TransferSize(int bitMemoryTransferSize) { + public static int getLog2TransferSize(int bitMemoryTransferSize) { switch (bitMemoryTransferSize) { case 8: return 0; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java index 5621210e8ff3..3e9c19deb54d 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java @@ -306,7 +306,7 @@ public void updateAlignedDisjoint(MetaAccessProvider metaAccess) { aligned = isHeapWordAligned(metaAccess, constantSrc, componentKind) && isHeapWordAligned(metaAccess, constantDst, componentKind); } if (constantSrc.asInt() >= constantDst.asInt()) { - // low to high copy so treat as disjoint + // low to high copy (copying forwards) so treat as disjoint disjoint = true; } } From 241163db34b6f72c95393b842baec3838a1f356b Mon Sep 17 00:00:00 2001 From: Andrew Craik Date: Tue, 21 Sep 2021 20:16:57 +1000 Subject: [PATCH 064/681] Fix DerivedConvertedInductionVariable zero extend Zero extension was added to DerivedConvertedInductionVariable to correctly handle some induction variables. The use of zero extension in the stride node is not correct since the direction is encoded in the sign and it must be preserved. This change forces the stride node to use signed extension in all cases. --- .../loop/DerivedConvertedInductionVariable.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedConvertedInductionVariable.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedConvertedInductionVariable.java index 67a9205a5ed5..0be5c1f04009 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedConvertedInductionVariable.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedConvertedInductionVariable.java @@ -53,12 +53,12 @@ public Direction direction() { @Override public ValueNode initNode() { - return op(base.initNode()); + return op(base.initNode(), true); } @Override public ValueNode strideNode() { - return op(base.strideNode()); + return op(base.strideNode(), false); } @Override @@ -88,7 +88,7 @@ public ValueNode extremumNode(boolean assumeLoopEntered, Stamp s) { @Override public ValueNode exitValueNode() { - return op(base.exitValueNode()); + return op(base.exitValueNode(), true); } @Override @@ -105,8 +105,8 @@ public long constantExtremum() { public void deleteUnusedNodes() { } - public ValueNode op(ValueNode v) { - boolean zeroExtend = value instanceof ZeroExtendNode; + private ValueNode op(ValueNode v, boolean allowZeroExtend) { + boolean zeroExtend = allowZeroExtend && value instanceof ZeroExtendNode; return IntegerConvertNode.convert(v, stamp, zeroExtend, graph(), NodeView.DEFAULT); } @@ -122,7 +122,7 @@ public InductionVariable copy(InductionVariable newBase, ValueNode newValue) { @Override public ValueNode copyValue(InductionVariable newBase) { - return op(newBase.valueNode()); + return op(newBase.valueNode(), true); } } From 16814aa7748a0b5a9683394aef97e4b8188243fe Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 21 Sep 2021 13:18:35 +0200 Subject: [PATCH 065/681] compiler: add Javadoc to MacroNode#getKilledLocationIdentity --- .../org/graalvm/compiler/replacements/nodes/MacroNode.java | 6 ++++++ .../compiler/replacements/nodes/MacroWithExceptionNode.java | 3 +++ 2 files changed, 9 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java index 2577ba0c5d8a..500aa02e314a 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java @@ -173,6 +173,12 @@ public boolean hasSideEffect() { return true; } + /** + * Returns {@link LocationIdentity#any()}. This node needs to kill any location because it might + * get {@linkplain #replaceWithInvoke() replaced with an invoke} and + * {@link InvokeNode#getKilledLocationIdentity()} kills {@link LocationIdentity#any()} and the + * kill location must not get broader. + */ @Override public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java index dc11570b441d..158fc20bf7f3 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java @@ -173,6 +173,9 @@ public boolean hasSideEffect() { return true; } + /** + * @see MacroNode#getKilledLocationIdentity() + */ @Override public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); From b5289c0e4407c88451bee54d91a83bfcb60aa760 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Thu, 9 Sep 2021 10:28:11 +0200 Subject: [PATCH 066/681] Set x-GraalVM-Working-Directories attr for tools. --- sdk/mx.sdk/mx_sdk_vm_impl.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index 79bcabb6ba4d..e8fdeec90e1e 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -2137,8 +2137,9 @@ def _gen_gu_manifest(components, formatter, bundled=False): dependencies = sorted(dependencies) if dependencies: manifest["Require-Bundle"] = ','.join(("org.graalvm." + d for d in dependencies)) - if isinstance(main_component, mx_sdk.GraalVmLanguage): - _wd_base = join('jre', 'languages') if _src_jdk_version < 9 else 'languages' + if isinstance(main_component, (mx_sdk.GraalVmLanguage, mx_sdk.GraalVmTool)): + _component_type_base = 'languages' if isinstance(main_component, mx_sdk.GraalVmLanguage) else 'tools' + _wd_base = join('jre', _component_type_base) if _src_jdk_version < 9 else _component_type_base manifest["x-GraalVM-Working-Directories"] = join(_wd_base, main_component.dir_name) post_install_msg = None From 8213042537979111c299877cef8a34b826f47d10 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Tue, 24 Nov 2020 17:22:04 +0100 Subject: [PATCH 067/681] Fix ArrayFullWrapper example. --- .../src/com/oracle/truffle/api/library/ExportLibrary.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/ExportLibrary.java b/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/ExportLibrary.java index 352c00d16d48..d980a653f16f 100644 --- a/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/ExportLibrary.java +++ b/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/ExportLibrary.java @@ -295,7 +295,7 @@ * *
      * @ExportLibrary(value = ArrayLibrary.class, delegateTo = "delegate")
-     * @ExportLibrary(ReflectionLibrary.class, delegateTo = "delegate")
+     * @ExportLibrary(value = ReflectionLibrary.class, delegateTo = "delegate")
      * final class ArrayFullWrapper {
      *
      *     final Object delegate;

From bc56ffa797b3bb70dfb1d9e345d3458976adc7d4 Mon Sep 17 00:00:00 2001
From: Fabio Niephaus 
Date: Wed, 10 Feb 2021 11:16:28 +0100
Subject: [PATCH 068/681] Improve TruffleObject wording.

---
 .../src/com/oracle/truffle/api/interop/InteropLibrary.java  | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropLibrary.java b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropLibrary.java
index 8f6977a9dbbd..3eb3726b9421 100644
--- a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropLibrary.java
+++ b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropLibrary.java
@@ -105,9 +105,9 @@
  * The interop protocol only allows interop values to be used as receivers, return values or
  * parameters of messages. Allowed Java types of interop values are:
  * 
    - *
  • {@link TruffleObject}: Any subclass of {@link TruffleObject} is interpreted depending on the - * interop messages it {@link ExportLibrary exports}. Truffle objects are expected but not required - * to export interop library messages. + *
  • {@link TruffleObject}: Any object that implements the {@link TruffleObject} interface is + * interpreted according to the interop messages it {@link ExportLibrary exports}. Truffle objects + * are expected but not required to export interop library messages. *
  • {@link String} and {@link Character} are interpreted as {@link #isString(Object) string} * value. *
  • {@link Boolean} is interpreted as {@link #isBoolean(Object) boolean} value. From f5332e432e4d6700c5db3c51218b55da918aa6dd Mon Sep 17 00:00:00 2001 From: Jirka Marsik Date: Tue, 21 Sep 2021 12:53:57 +0000 Subject: [PATCH 069/681] Fix changelog message for TRegex ASCII encoding --- regex/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regex/CHANGELOG.md b/regex/CHANGELOG.md index 52fef7b9502f..49f8154f8996 100644 --- a/regex/CHANGELOG.md +++ b/regex/CHANGELOG.md @@ -4,7 +4,7 @@ This changelog summarizes major changes between TRegex versions relevant to lang ## Version 22.0.0 -* Added new `ASCII` encoding that callers can use when compiling a regex to limit the range of code point matches to [0xx, 0x7f]. +* Added new `ASCII` encoding that callers can use when compiling a regex to limit the range of code point matches to [0x00, 0x7f]. ## Version 21.3.0 From c809a41293cd43f3cda9b535d6b8fed515810c2f Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 21 Sep 2021 15:08:47 +0100 Subject: [PATCH 070/681] Fix flamegraph width to take scrollbars into account. --- .../truffle/tools/profiler/impl/SVGSamplerOutput.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index c881096c782f..25af6887cc38 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -464,7 +464,7 @@ public String initFunction(String argName) { public String resizeFunction() { StringBuilder result = new StringBuilder(); result.append("function resize() {\n"); - result.append("owner_resize(window.innerWidth);\n"); + result.append("owner_resize(document.firstElementChild.clientWidth);\n"); for (SVGComponent component : components) { result.append(component.resizeFunction()); } @@ -828,7 +828,7 @@ public double height() { } public String resizeFunction() { - return "fg_resize(window.innerWidth);\n"; + return "fg_resize(document.firstElementChild.clientWidth);\n"; } public String initFunction(String argName) { @@ -1018,7 +1018,7 @@ public double height() { } public String resizeFunction() { - return "h_resize(window.innerWidth);\n"; + return "h_resize(document.firstElementChild.clientWidth);\n"; } public String initFunction(String argName) { From d20d4ef9e929a3c29c33a829223cb962f9b621e5 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 21 Sep 2021 16:35:07 +0200 Subject: [PATCH 071/681] bump timeout for gate-compiler-test-labsjdk-ee-11-linux-amd64-avx3 to 45:00 --- compiler/ci_common/gate_tasks.hocon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ci_common/gate_tasks.hocon b/compiler/ci_common/gate_tasks.hocon index 24c3d028996c..82d03f98bb6f 100644 --- a/compiler/ci_common/gate_tasks.hocon +++ b/compiler/ci_common/gate_tasks.hocon @@ -34,7 +34,7 @@ builds += [ ${gateStyle} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-style-linux-amd64", timelimit: "45:00"} ${gateCoverage} ${oraclejdk8} ${gateLinuxAMD64} {name: "weekly-compiler-coverage-8-linux-amd64"} ${graalWeekly} {timelimit: "1:50:00"} - ${gateTest} ${labsjdk-ee-11} ${gateLinuxAMD64AVX3} {name: "gate-compiler-test-labsjdk-ee-11-linux-amd64-avx3", targets: [gate]} + ${gateTest} ${labsjdk-ee-11} ${gateLinuxAMD64AVX3} {name: "gate-compiler-test-labsjdk-ee-11-linux-amd64-avx3", targets: [gate], timelimit: "45:00"} ${gateTestCompileImmediately} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-test-truffle-compile-immediately-8-linux-amd64", timelimit: "1:00:00"} # Linux AArch64 From 0e73661abe28efdc9358c9f97c7be99c13100b74 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Thu, 9 Sep 2021 12:00:04 +0200 Subject: [PATCH 072/681] Support newlines in Truffle's OptionProcessor. --- .../truffle/options/PolyglotCompilerOptions.java | 8 ++++---- .../src/org/graalvm/launcher/Launcher.java | 5 ++++- .../src/org/graalvm/options/OptionDescriptor.java | 7 ++++--- .../api/test/option/OptionProcessorTest.java | 14 ++++++++------ .../truffle/dsl/processor/OptionProcessor.java | 13 +++++++++++-- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.options/src/org/graalvm/compiler/truffle/options/PolyglotCompilerOptions.java b/compiler/src/org.graalvm.compiler.truffle.options/src/org/graalvm/compiler/truffle/options/PolyglotCompilerOptions.java index e10baf55e52b..8bcd42f7d6d0 100644 --- a/compiler/src/org.graalvm.compiler.truffle.options/src/org/graalvm/compiler/truffle/options/PolyglotCompilerOptions.java +++ b/compiler/src/org.graalvm.compiler.truffle.options/src/org/graalvm/compiler/truffle/options/PolyglotCompilerOptions.java @@ -178,7 +178,7 @@ public ExceptionAction apply(String s) { try { return ExceptionAction.valueOf(s); } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(ExceptionAction.HELP); + throw new IllegalArgumentException(String.format(ExceptionAction.HELP)); } } }); @@ -365,10 +365,10 @@ private String indent(int nameLength) { private static final String EXPANSION_VALUES = "Accepted values are:%n" + " true - Collect data for the default tier 'truffleTier'.%n" + " false - No data will be collected.%n" + - "Or one or multiple tiers separated by comma (e.g. truffleTier,lowTier) :%n" + + "Or one or multiple tiers separated by comma (e.g. truffleTier,lowTier):%n" + " peTier - After partial evaluation without additional phases applied.%n" + " truffleTier - After partial evaluation with additional phases applied.%n" + - " lowTier - After low tier phases were applied.%n"; + " lowTier - After low tier phases were applied."; @Option(help = "Print a tree of all expanded Java methods with statistics after each compilation. " + EXPANSION_VALUES, category = OptionCategory.INTERNAL) public static final OptionKey> TraceMethodExpansion = new OptionKey<>(Collections.emptySet(), COMPILATION_TIERS_TYPE); @@ -498,7 +498,7 @@ private String indent(int nameLength) { "On runtimes which doesn't support it the option has no effect.", category = OptionCategory.EXPERT) public static final OptionKey EncodedGraphCachePurgeDelay = new OptionKey<>(10_000); - + @Option(help = "Forces the frame clearing mechanism to be executed, even if Frame.clear() is not used.", category = OptionCategory.EXPERT) public static final OptionKey ForceFrameLivenessAnalysis = new OptionKey<>(false); diff --git a/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/Launcher.java b/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/Launcher.java index 8df6e4e1c20b..1b02e4cce29c 100644 --- a/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/Launcher.java +++ b/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/Launcher.java @@ -973,9 +973,12 @@ private static String wrap(String s) { private void printOption(String option, String description, int indentStart, int optionWidth) { String indent = spaces(indentStart); - String desc = wrap(description != null ? description : ""); + String desc = description != null ? description : ""; String nl = System.lineSeparator(); String[] descLines = desc.split(nl); + for (int i = 0; i < descLines.length; i++) { + descLines[i] = wrap(descLines[i]); + } if (option.length() >= optionWidth && description != null) { out.println(indent + option + nl + indent + spaces(optionWidth) + descLines[0]); } else { diff --git a/sdk/src/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java b/sdk/src/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java index 9b88f8120277..429cbdb5ccff 100644 --- a/sdk/src/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java +++ b/sdk/src/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -96,7 +96,7 @@ public boolean isDeprecated() { } /** - * Returns the deprecation reason and the recommended fix. + * Returns the deprecation reason and the recommended fix. For newlines, use %n. * * @since 20.1.0 */ @@ -133,7 +133,8 @@ public OptionStability getStability() { } /** - * Returns a human-readable description on how to use the option. + * Returns a human-readable description on how to use the option. For newlines, use + * %n. * * @since 19.0 */ diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/option/OptionProcessorTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/option/OptionProcessorTest.java index 95eaddb72684..cbcf2cecdeae 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/option/OptionProcessorTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/option/OptionProcessorTest.java @@ -86,6 +86,7 @@ public void testTestLang() { descriptor1 = descriptor = descriptors.get("optiontestlang1.StringOption1"); assertNotNull(descriptor); assertTrue(descriptor.isDeprecated()); + assertEquals(String.format("Deprecation message%nwith newline"), descriptor.getDeprecationMessage()); assertFalse(descriptor.isOptionMap()); assertSame(OptionCategory.USER, descriptor.getCategory()); assertSame(OptionStability.EXPERIMENTAL, descriptor.getStability()); @@ -94,7 +95,7 @@ public void testTestLang() { descriptor2 = descriptor = descriptors.get("optiontestlang1.StringOption2"); assertNotNull(descriptor); - assertEquals("StringOption2 help", descriptor.getHelp()); + assertEquals(String.format("StringOption2 help%nwith newline"), descriptor.getHelp()); assertFalse(descriptor.isDeprecated()); assertFalse(descriptor.isOptionMap()); assertSame(OptionCategory.EXPERT, descriptor.getCategory()); @@ -166,6 +167,7 @@ public void testOptionsInstrument() { descriptor1 = descriptor = descriptors.get("optiontestinstr1.StringOption1"); assertNotNull(descriptor); assertTrue(descriptor.isDeprecated()); + assertEquals(String.format("Deprecation message%nwith newline"), descriptor.getDeprecationMessage()); assertFalse(descriptor.isOptionMap()); assertSame(OptionCategory.USER, descriptor.getCategory()); assertEquals("StringOption1 help", descriptor.getHelp()); @@ -173,7 +175,7 @@ public void testOptionsInstrument() { descriptor2 = descriptor = descriptors.get("optiontestinstr1.StringOption2"); assertNotNull(descriptor); - assertEquals("StringOption2 help", descriptor.getHelp()); + assertEquals(String.format("StringOption2 help%nwith newline"), descriptor.getHelp()); assertFalse(descriptor.isDeprecated()); assertFalse(descriptor.isOptionMap()); assertSame(OptionCategory.EXPERT, descriptor.getCategory()); @@ -357,10 +359,10 @@ public enum EnumValue { @Registration(id = "optiontestlang1", version = "1.0", name = "optiontestlang1") public static class OptionTestLang1 extends TruffleLanguage { - @Option(help = "StringOption1 help", deprecated = true, category = OptionCategory.USER) // + @Option(help = "StringOption1 help", deprecated = true, deprecationMessage = "Deprecation message%nwith newline", category = OptionCategory.USER) // static final OptionKey StringOption1 = new OptionKey<>("defaultValue"); - @Option(help = "StringOption2 help", deprecated = false, category = OptionCategory.EXPERT, stability = OptionStability.EXPERIMENTAL) // + @Option(help = "StringOption2 help%nwith newline", deprecated = false, category = OptionCategory.EXPERT, stability = OptionStability.EXPERIMENTAL) // public static final OptionKey StringOption2 = new OptionKey<>("defaultValue"); // The variable name differs from the option name on purpose, to test they can be different @@ -397,10 +399,10 @@ public static Env getCurrentContext() { @TruffleInstrument.Registration(id = "optiontestinstr1", services = OptionValues.class) public static class OptionTestInstrument1 extends TruffleInstrument { - @Option(help = "StringOption1 help", deprecated = true, category = OptionCategory.USER, stability = OptionStability.STABLE) // + @Option(help = "StringOption1 help", deprecated = true, deprecationMessage = "Deprecation message%nwith newline", category = OptionCategory.USER, stability = OptionStability.STABLE) // public static final OptionKey StringOption1 = new OptionKey<>("defaultValue"); - @Option(help = "StringOption2 help", deprecated = false, category = OptionCategory.EXPERT) // + @Option(help = "StringOption2 help%nwith newline", deprecated = false, category = OptionCategory.EXPERT) // public static final OptionKey StringOption2 = new OptionKey<>("defaultValue"); @Option(help = "Instrument user-defined thresholds", deprecated = false, category = OptionCategory.EXPERT) // diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/OptionProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/OptionProcessor.java index 5f5b7a00ad11..a254eae51230 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/OptionProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/OptionProcessor.java @@ -451,11 +451,12 @@ private static CodeTree createBuildOptionDescriptor(ProcessorContext context, Op builder.end(); // newBuilder call if (info.deprecated) { builder.startCall("", "deprecated").string("true").end(); - builder.startCall("", "deprecationMessage").doubleQuote(info.deprecationMessage).end(); + addCallWithStringWithPossibleNewlines(builder, context, "deprecationMessage", info.deprecationMessage); } else { builder.startCall("", "deprecated").string("false").end(); } - builder.startCall("", "help").doubleQuote(info.help).end(); + addCallWithStringWithPossibleNewlines(builder, context, "help", info.help); + builder.startCall("", "category").staticReference(types.OptionCategory, info.category).end(); builder.startCall("", "stability").staticReference(types.OptionStability, info.stability).end(); @@ -463,6 +464,14 @@ private static CodeTree createBuildOptionDescriptor(ProcessorContext context, Op return builder.build(); } + private static void addCallWithStringWithPossibleNewlines(CodeTreeBuilder builder, ProcessorContext context, String callName, String value) { + if (value.contains("%n")) { + builder.startCall("", callName).startStaticCall(context.getType(String.class), "format").doubleQuote(value).end().end(); + } else { + builder.startCall("", callName).doubleQuote(value).end(); + } + } + static class OptionInfo implements Comparable { boolean valid = true; From 98ed01b8cf23696fc10e6b6eb8fd0f26e4f98c42 Mon Sep 17 00:00:00 2001 From: aben20807 Date: Tue, 13 Jul 2021 10:16:58 +0800 Subject: [PATCH 073/681] Fix typo in get-started-graalvm-community.md --- .../graalvm-community/get-started-graalvm-community.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/graalvm-community/get-started-graalvm-community.md b/docs/getting-started/graalvm-community/get-started-graalvm-community.md index 4945739eea13..f6142b394a12 100644 --- a/docs/getting-started/graalvm-community/get-started-graalvm-community.md +++ b/docs/getting-started/graalvm-community/get-started-graalvm-community.md @@ -14,7 +14,7 @@ GraalVM's polyglot capabilities make it possible to mix multiple programming lan Here you will find information about installing GraalVM Community Edition, running basic applications with it, and adding support for accompanying features. Further, you will learn about the polyglot capabilities of GraalVM and see how to build platform-specific native executables of JVM-based applications. -If you are new to GraaVM, we recommend starting with [Introduction to GraalVM](/docs/introduction/), where you will find information about GraalVM's architecture, distributions available, supported platforms, core and additional features, and much more. +If you are new to GraalVM, we recommend starting with [Introduction to GraalVM](/docs/introduction/), where you will find information about GraalVM's architecture, distributions available, supported platforms, core and additional features, and much more. If you have GraalVM already installed and have experience using it, you can skip this getting started guide and proceed to the in-depth [Reference Manuals](/reference-manual/). From a19006f595b95d6401cb6c0408bc5a5de6058812 Mon Sep 17 00:00:00 2001 From: Regan-Koopmans Date: Tue, 23 Feb 2021 16:23:14 +0200 Subject: [PATCH 074/681] Improve substitution conflict error message Fixes #1715 --- .../hosted/substitute/AnnotationSubstitutionProcessor.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java index 4837c9c75d1e..756fab20323b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java @@ -819,11 +819,13 @@ private static boolean isIncluded(TargetElement targetElementAnnotation, Class void register(Map substitutions, T annotated, T original, T target) { if (annotated != null) { - guarantee(!substitutions.containsKey(annotated) || substitutions.get(annotated) == original || substitutions.get(annotated) == target, "Already registered: %s", annotated); + guarantee(!substitutions.containsKey(annotated) || substitutions.get(annotated) == original || substitutions.get(annotated) == target, + "Substition: %s conflicts with previously registered: %s", annotated, substitutions.get(annotated)); substitutions.put(annotated, target); } if (original != null) { - guarantee(!substitutions.containsKey(original) || substitutions.get(original) == original || substitutions.get(original) == target, "Already registered: %s", original); + guarantee(!substitutions.containsKey(original) || substitutions.get(original) == original || substitutions.get(original) == target, + "Substition: %s conflicts with previously registered: %s", original, substitutions.get(original)); substitutions.put(original, target); } } From 267cc9557bdcb1d366589fc4295fa5f3f37c1b54 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Tue, 21 Sep 2021 14:28:06 +0200 Subject: [PATCH 075/681] Fix a typo. --- .../oracle/truffle/api/instrumentation/TruffleInstrument.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/TruffleInstrument.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/TruffleInstrument.java index e081314cdba6..c7aee91c0dae 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/TruffleInstrument.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/TruffleInstrument.java @@ -232,7 +232,7 @@ protected OptionDescriptors getOptionDescriptors() { * } * * @Registration(...) - * class MyInstrument extends TruffleInstruement { + * class MyInstrument extends TruffleInstrument { * * static final OptionDescriptors CONTEXT_OPTIONS = new MyContextOptionDescriptors(); * From f4595ad28028cdb5efeac66e961adb991e92f6ac Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 21 Sep 2021 19:01:14 +0200 Subject: [PATCH 076/681] Inline Node.getParent() into Node.getRootNode(). --- .../src/com/oracle/truffle/api/nodes/Node.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java index e90776cc40cf..48b7935ac2fb 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java @@ -524,7 +524,7 @@ private RootNode getRootNodeImpl() { Node prev; do { prev = node; - node = node.getParent(); + node = node.parent; } while (node != null); if (prev instanceof RootNode) { From eb69c07999e0d2ad78f0547eda020c5eb29f5ed9 Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 21 Sep 2021 17:39:17 +0100 Subject: [PATCH 077/681] Improve the tooltips. --- .../tools/profiler/impl/SVGSamplerOutput.java | 47 +++++++++++++++++-- .../profiler/impl/resources/flamegraph.js | 8 ++-- .../profiler/impl/resources/graphowner.js | 4 ++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index 25af6887cc38..b0ea04e60cfd 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -218,8 +218,11 @@ private static class GraphOwner implements SVGComponent { private Map> colorsForNames = new HashMap<>(); private int sampleId; public final Map nameHash = new HashMap<>(); + public final Map sourceHash = new HashMap<>(); public int nameCounter = 0; + public int sourceCounter = 0; public final JSONArray sampleNames = new JSONArray(); + public final JSONArray sourceNames = new JSONArray(); public final JSONObject sampleData = new JSONObject(); GraphOwner(StringBuilder output, Map data) { @@ -294,8 +297,12 @@ public String script() { private void buildSampleData() { sampleData.put("n", nameCounter); + sampleData.put("f", sourceCounter); + sampleData.put("fl", 0); nameHash.put("", nameCounter++); sampleNames.put(""); + sourceHash.put("", sourceCounter++); + sourceNames.put(""); sampleData.put("id", sampleId++); sampleData.put("i", 0); sampleData.put("c", 0); @@ -326,6 +333,11 @@ private JSONObject threadSampelData(Thread thread, List", k -> { + sourceNames.put(""); + return sourceCounter++; + })); + result.put("fl", 0); result.put("id", sampleId++); result.put("i", 0); result.put("c", 0); @@ -350,6 +362,9 @@ public String samples() { result.append("var profileNames = "); result.append(sampleNames.toString()); result.append(";\n"); + result.append("var sourceNames = "); + result.append(sourceNames.toString()); + result.append(";\n"); result.append("var profileData = "); result.append(sampleData.toString()); result.append(";\n"); @@ -392,6 +407,30 @@ public JSONObject sampleData(ProfilerNode sample, long x) { return nameCounter++; }); result.put("n", nameId); + final String sourceName; + int sourceLine = 0; + SourceSection section = sample.getSourceSection(); + if (section != null && section.isAvailable()) { + sourceLine = section.getStartLine(); + Source source = section.getSource(); + if (source != null) { + String path = source.getPath(); + if (path != null) { + sourceName = path; + } else { + sourceName = source.getName(); + } + } else { + sourceName = ""; + } + } else { + sourceName = ""; + } + result.put("f", sourceHash.computeIfAbsent(sourceName, k -> { + sourceNames.put(k); + return sourceCounter++; + })); + result.put("fl", sourceLine); result.put("id", sampleId++); result.put("i", sample.getPayload().getTierSelfCount(0)); int compiledSelfHits = 0; @@ -793,14 +832,16 @@ private String drawSample(double y, JSONObject sample) { groupAttrs.put("onmouseout", "c(this)"); groupAttrs.put("id", "f_" + Integer.toString(id)); StringBuilder title = new StringBuilder(); - title.append("Function: "); title.append(fullText); title.append("\n"); int interpreted = sample.getInt("i"); int compiled = sample.getInt("c"); - title.append(String.format("%d samples (%d interpreted, %d compiled).\n", interpreted + compiled, interpreted, compiled)); + int total = sample.getInt("h"); double percent = 100.0 * (compiled + interpreted) / sampleCount; - title.append(String.format("%.2f%% of displayed samples.\n", percent)); + double totalPercent = 100.0 * total / sampleCount; + title.append(String.format("Self samples: %d (%.2f%%)\n", interpreted + compiled, percent)); + title.append(String.format("total samples: %d (%.2f%%)\n", total, totalPercent)); + title.append(String.format("Source location: %s\n", owner.sourceHash.get(sample.getInt("f")), sample.getInt("fl"))); groupAttrs.put("title", escape(title.toString())); output.append(startGroup(groupAttrs)); diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index e52aed1756e6..944f2b57c020 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -118,10 +118,12 @@ function zoom_child(sample) { let r = e.children[1]; let t = e.lastElementChild; let name = name_for_sample(sample); + let source = source_for_sample(sample); - title.textContent = "Function: " + name + "\n" + - sample.h + " samples (" + sample.i + " interpreted, " + sample.c + " compiled).\n" + - (100 * (sample.c + sample.i) / (fg_xmax - fg_xmin)).toFixed(2) + "% of displayed samples.\n"; + title.textContent = name + "\n" + + "Self samples: " + (sample.i + sample.c) + " (" + (100 * (sample.c + sample.i) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + + "Total samples: " + (sample.h) + " (" + (100 * (sample.h + sample.i) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + + "Source location: " + source + ":" + sample.fl + "\n"; r.x.baseVal.value = x; t.x.baseVal[0].value = x + 3; diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index d07c2db9e87c..cc09b66d8101 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -208,6 +208,10 @@ function name_for_sample(sample) { return profileNames[sample.n]; } +function source_for_sample(sample) { + return sourceNames[sample.f]; +} + function function_name(e) { return title(e); } From bc03928d0dcad4766f1abafcaa87ba48a59ea476 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 21 Sep 2021 19:01:01 +0200 Subject: [PATCH 078/681] LoopNode OSR should preserve the frame in stack frames. --- .../runtime/GraalOSRFrameInstance.java | 12 +++++++- .../truffle/runtime/OptimizedOSRLoopNode.java | 28 ++++++++++++------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalOSRFrameInstance.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalOSRFrameInstance.java index 276287b47499..5a15680220f8 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalOSRFrameInstance.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalOSRFrameInstance.java @@ -25,6 +25,8 @@ package org.graalvm.compiler.truffle.runtime; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.nodes.RootNode; + import jdk.vm.ci.code.stack.InspectedFrame; /** @@ -42,7 +44,15 @@ public final class GraalOSRFrameInstance extends GraalFrameInstance { @Override public Frame getFrame(FrameAccess access) { - return getFrameFrom(osrFrame, access); + Frame materializedOSRFrame = getFrameFrom(osrFrame, access); + if (getOSRRootNode() instanceof OptimizedOSRLoopNode.LoopOSRRootNode) { + return (Frame) materializedOSRFrame.getArguments()[0]; + } + return materializedOSRFrame; + } + + private RootNode getOSRRootNode() { + return ((OptimizedCallTarget) osrFrame.getLocal(GraalFrameInstance.CALL_TARGET_INDEX)).getRootNode(); } @Override diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java index d64dd580dab7..dcd1a67d49f4 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java @@ -83,7 +83,7 @@ private OptimizedOSRLoopNode(RepeatingNode repeatingNode, int osrThreshold, bool /** * @param rootFrameDescriptor may be {@code null}. */ - protected LoopOSRRootNode createRootNode(FrameDescriptor rootFrameDescriptor, Class clazz) { + protected AbstractLoopOSRRootNode createRootNode(FrameDescriptor rootFrameDescriptor, Class clazz) { /* * Use a new frame descriptor, because the frame that this new root node creates is not * used. @@ -252,7 +252,7 @@ public void run() { }); } - private LoopOSRRootNode createRootNodeImpl(RootNode root, Class frameClass) { + private AbstractLoopOSRRootNode createRootNodeImpl(RootNode root, Class frameClass) { return createRootNode(root == null ? null : root.getFrameDescriptor(), frameClass); } @@ -415,7 +415,7 @@ private OptimizedVirtualizingOSRLoopNode(RepeatingNode repeatableNode, int osrTh } @Override - protected LoopOSRRootNode createRootNode(FrameDescriptor rootFrameDescriptor, Class clazz) { + protected AbstractLoopOSRRootNode createRootNode(FrameDescriptor rootFrameDescriptor, Class clazz) { if (readFrameSlots == null || writtenFrameSlots == null) { return super.createRootNode(rootFrameDescriptor, clazz); } else { @@ -433,7 +433,7 @@ protected LoopOSRRootNode createRootNode(FrameDescriptor rootFrameDescriptor, Cl } - public static class LoopOSRRootNode extends BaseOSRRootNode { + abstract static class AbstractLoopOSRRootNode extends BaseOSRRootNode { protected final Class clazz; @@ -443,7 +443,7 @@ public static class LoopOSRRootNode extends BaseOSRRootNode { */ @Child protected OptimizedOSRLoopNode loopNode; - LoopOSRRootNode(OptimizedOSRLoopNode loop, FrameDescriptor frameDescriptor, Class clazz) { + AbstractLoopOSRRootNode(OptimizedOSRLoopNode loop, FrameDescriptor frameDescriptor, Class clazz) { super(null, frameDescriptor); this.loopNode = loop; this.clazz = clazz; @@ -457,10 +457,11 @@ public SourceSection getSourceSection() { @Override protected Object executeOSR(VirtualFrame frame) { VirtualFrame parentFrame = clazz.cast(frame.getArguments()[0]); + RepeatingNode loopBody = loopNode.repeatingNode; Object status; - while (loopNode.repeatingNode.shouldContinue(status = loopNode.getRepeatingNode().executeRepeatingWithValue(parentFrame))) { + while (loopBody.shouldContinue(status = loopBody.executeRepeatingWithValue(parentFrame))) { if (CompilerDirectives.inInterpreter()) { - return loopNode.repeatingNode.initialLoopStatus(); + return loopBody.initialLoopStatus(); } TruffleSafepoint.poll(this); } @@ -478,7 +479,13 @@ public final String toString() { } } - private static final class VirtualizingLoopOSRRootNode extends LoopOSRRootNode { + static final class LoopOSRRootNode extends AbstractLoopOSRRootNode { + LoopOSRRootNode(OptimizedOSRLoopNode loop, FrameDescriptor frameDescriptor, Class clazz) { + super(loop, frameDescriptor, clazz); + } + } + + private static final class VirtualizingLoopOSRRootNode extends AbstractLoopOSRRootNode { @CompilationFinal(dimensions = 1) private final FrameSlot[] readFrameSlots; @CompilationFinal(dimensions = 1) private final FrameSlot[] writtenFrameSlots; @@ -534,10 +541,11 @@ protected Object executeOSR(VirtualFrame originalFrame) { FrameWithoutBoxing parentFrame = (FrameWithoutBoxing) (loopFrame.getArguments()[0]); executeTransfer(parentFrame, loopFrame, readFrameSlots, readFrameSlotsTags); try { + RepeatingNode loopBody = loopNode.repeatingNode; Object status; - while (loopNode.repeatingNode.shouldContinue(status = loopNode.getRepeatingNode().executeRepeatingWithValue(loopFrame))) { + while (loopBody.shouldContinue(status = loopBody.executeRepeatingWithValue(loopFrame))) { if (CompilerDirectives.inInterpreter()) { - return loopNode.repeatingNode.initialLoopStatus(); + return loopBody.initialLoopStatus(); } TruffleSafepoint.poll(this); } From 22181b8aadc9a127bf2c8366933893a4c71630a1 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 21 Sep 2021 19:40:12 +0200 Subject: [PATCH 079/681] [GR-33890] Add OSR stack frame introspection regression test. --- .../truffle/test/LoopNodeOSRTest.java | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodeOSRTest.java diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodeOSRTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodeOSRTest.java new file mode 100644 index 000000000000..1e39f6bbdde0 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodeOSRTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 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 org.graalvm.compiler.truffle.test; + +import java.util.stream.IntStream; + +import org.graalvm.compiler.truffle.runtime.BytecodeOSRMetadata; +import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; +import org.junit.Assert; +import org.junit.Test; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; +import com.oracle.truffle.api.frame.FrameUtil; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.LoopNode; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RepeatingNode; +import com.oracle.truffle.api.nodes.RootNode; + +public class LoopNodeOSRTest extends TestWithSynchronousCompiling { + + static final Object[] ARGUMENTS = IntStream.range(21, 36).mapToObj(Integer::valueOf).toArray(); + + private static class TestLoopRootNode extends RootNode { + @Child private LoopNode loop; + private final FrameSlot iterationSlot; + + TestLoopRootNode(RepeatingNode body, FrameDescriptor frameDescriptor, FrameSlot iterationSlot) { + super(null, frameDescriptor); + this.loop = Truffle.getRuntime().createLoopNode(body); + this.iterationSlot = iterationSlot; + } + + @Override + public Object execute(VirtualFrame frame) { + frame.setInt(iterationSlot, 0); + return loop.execute(frame); + } + } + + private final class CheckStackWalkBody extends Node implements RepeatingNode { + private final int total; + private final FrameSlot iterationSlot; + private final FrameDescriptor frameDescriptor; + boolean compiled; + + private CheckStackWalkBody(int total, FrameDescriptor frameDescriptor, FrameSlot iterationSlot) { + this.total = total; + this.iterationSlot = iterationSlot; + this.frameDescriptor = frameDescriptor; + } + + @Override + public boolean executeRepeating(VirtualFrame frame) { + int iteration = FrameUtil.getIntSafe(frame, iterationSlot); + if (iteration < total) { + if (iteration % (total / 10) == 0) { + checkStack(); + } + iteration++; + frame.setInt(iterationSlot, iteration); + return true; + } else { + if (CompilerDirectives.inCompiledCode()) { + compiled = true; + } + iteration = 0; + frame.setInt(iterationSlot, iteration); + return false; + } + } + + @TruffleBoundary + private void checkStack() { + Truffle.getRuntime().iterateFrames(frameInstance -> { + Frame frame = frameInstance.getFrame(FrameAccess.READ_ONLY); + Assert.assertArrayEquals(ARGUMENTS, frame.getArguments()); + Assert.assertSame(frameDescriptor, frame.getFrameDescriptor()); + return null; + }); + } + } + + @Test + public void testOSRStackFrame() { + int osrThreshold = 10 * BytecodeOSRMetadata.OSR_POLL_INTERVAL; + setupContext("engine.MultiTier", "false", + "engine.OSR", "true", + "engine.OSRCompilationThreshold", String.valueOf(osrThreshold)); + + FrameDescriptor desc = new FrameDescriptor(); + FrameSlot iterationSlot = desc.addFrameSlot("iteration", FrameSlotKind.Int); + CheckStackWalkBody loop = new CheckStackWalkBody(osrThreshold * 2, desc, iterationSlot); + TestLoopRootNode rootNode = new TestLoopRootNode(loop, desc, iterationSlot); + OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(rootNode); + + target.call(ARGUMENTS); + + Assert.assertTrue("Loop should have been OSR compiled", loop.compiled); + } + +} From d7b2c25254c4b6f2d1093bd86ec7dfeb36d3f341 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 21 Sep 2021 21:00:57 +0200 Subject: [PATCH 080/681] Add TruffleBoundary to GraalFrameInstance methods; required on SVM. --- .../compiler/truffle/runtime/GraalFrameInstance.java | 8 +++++++- .../compiler/truffle/runtime/GraalOSRFrameInstance.java | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalFrameInstance.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalFrameInstance.java index 18990eb4c02f..0cd277794331 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalFrameInstance.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalFrameInstance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -86,31 +86,37 @@ protected Frame getFrameFrom(InspectedFrame inspectedFrame, FrameAccess access) return frame; } + @TruffleBoundary @Override public Frame getFrame(FrameAccess access) { return getFrameFrom(callTargetFrame, access); } + @TruffleBoundary @Override public boolean isVirtualFrame() { return callTargetFrame.isVirtual(FRAME_INDEX); } + @TruffleBoundary @Override public int getCompilationTier() { return ((CompilationState) callTargetFrame.getLocal(OPTIMIZATION_TIER_FRAME_INDEX)).getTier(); } + @TruffleBoundary @Override public boolean isCompilationRoot() { return ((CompilationState) callTargetFrame.getLocal(OPTIMIZATION_TIER_FRAME_INDEX)).isCompilationRoot(); } + @TruffleBoundary @Override public CallTarget getCallTarget() { return (CallTarget) callTargetFrame.getLocal(CALL_TARGET_INDEX); } + @TruffleBoundary @Override public final Node getCallNode() { if (callNodeFrame != null) { diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalOSRFrameInstance.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalOSRFrameInstance.java index 5a15680220f8..d597132758eb 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalOSRFrameInstance.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalOSRFrameInstance.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.truffle.runtime; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.nodes.RootNode; @@ -42,6 +43,7 @@ public final class GraalOSRFrameInstance extends GraalFrameInstance { this.osrFrame = osrFrame; } + @TruffleBoundary @Override public Frame getFrame(FrameAccess access) { Frame materializedOSRFrame = getFrameFrom(osrFrame, access); @@ -55,16 +57,19 @@ private RootNode getOSRRootNode() { return ((OptimizedCallTarget) osrFrame.getLocal(GraalFrameInstance.CALL_TARGET_INDEX)).getRootNode(); } + @TruffleBoundary @Override public boolean isVirtualFrame() { return osrFrame.isVirtual(FRAME_INDEX); } + @TruffleBoundary @Override public int getCompilationTier() { return ((CompilationState) osrFrame.getLocal(OPTIMIZATION_TIER_FRAME_INDEX)).getTier(); } + @TruffleBoundary @Override public boolean isCompilationRoot() { return ((CompilationState) osrFrame.getLocal(OPTIMIZATION_TIER_FRAME_INDEX)).isCompilationRoot(); From a273a1c73400439883e6ed7b2fd51900bb6a55f4 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 21 Sep 2021 21:51:25 +0200 Subject: [PATCH 081/681] Avoid redundant field loads. --- .../src/com/oracle/truffle/api/nodes/ExecutableNode.java | 5 +++-- .../com/oracle/truffle/polyglot/PolyglotLanguageContext.java | 5 +++-- .../src/com/oracle/truffle/polyglot/WeakAssumedValue.java | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExecutableNode.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExecutableNode.java index 1b7828b408c2..0d0c605d83a1 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExecutableNode.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExecutableNode.java @@ -89,8 +89,9 @@ protected ExecutableNode(TruffleLanguage language) { } final TruffleLanguage getLanguage() { - if (engineRef instanceof TruffleLanguage) { - return (TruffleLanguage) engineRef; + Object ref = engineRef; + if (ref instanceof TruffleLanguage) { + return (TruffleLanguage) ref; } else { return null; } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java index 702183b069d0..7e8e8a3d707e 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java @@ -304,8 +304,9 @@ private void checkThreadAccess(Env localEnv) { } Object getContextImpl() { - if (env != null) { - return LANGUAGE.getContext(env); + Env localEnv = env; + if (localEnv != null) { + return LANGUAGE.getContext(localEnv); } else { CompilerDirectives.transferToInterpreterAndInvalidate(); return null; diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/WeakAssumedValue.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/WeakAssumedValue.java index b393e1281159..fe4e0a29f4cc 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/WeakAssumedValue.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/WeakAssumedValue.java @@ -174,10 +174,11 @@ private Profile(V value, String name) { } V get() { - if (reference == null) { + TruffleWeakReference ref = reference; + if (ref == null) { return null; } - return reference.get(); + return ref.get(); } } From f3cdb4963e9983042ec342516138b72af7f919a8 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 21 Sep 2021 22:45:57 +0200 Subject: [PATCH 082/681] Avoid redundant field accesses in reportChildLoopCount. --- .../compiler/truffle/runtime/OptimizedOSRLoopNode.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java index dcd1a67d49f4..4dc7e495564e 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java @@ -176,10 +176,11 @@ private void reportLoopIterations(long iterations) { } final void reportChildLoopCount(int iterations) { - baseLoopCount += iterations; - if (baseLoopCount < 0) { - baseLoopCount = Integer.MAX_VALUE; + int newBaseLoopCount = baseLoopCount + iterations; + if (newBaseLoopCount < 0) { // overflowed + newBaseLoopCount = Integer.MAX_VALUE; } + baseLoopCount = newBaseLoopCount; } /** From 897064936ad882feed7ea69fc9e262e7995d01bd Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 21 Sep 2021 23:00:20 +0200 Subject: [PATCH 083/681] Avoid redundant field loads. --- .../truffle/runtime/OptimizedOSRLoopNode.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java index 4dc7e495564e..66561b8a20b8 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedOSRLoopNode.java @@ -100,10 +100,11 @@ public final Node copy() { @Override public Object execute(VirtualFrame frame) { + RepeatingNode loopBody = repeatingNode; if (CompilerDirectives.inInterpreter()) { try { - Object status = repeatingNode.initialLoopStatus(); - while (repeatingNode.shouldContinue(status)) { + Object status = loopBody.initialLoopStatus(); + while (loopBody.shouldContinue(status)) { if (compiledOSRLoop == null) { status = profilingLoop(frame); } else { @@ -118,7 +119,7 @@ public Object execute(VirtualFrame frame) { long iterationsCompleted = 0; Object status; try { - while (inject(repeatingNode.shouldContinue((status = repeatingNode.executeRepeatingWithValue(frame))))) { + while (inject(loopBody.shouldContinue((status = loopBody.executeRepeatingWithValue(frame))))) { iterationsCompleted++; if (CompilerDirectives.inInterpreter()) { // compiled method got invalidated. We might need OSR again. @@ -134,7 +135,7 @@ public Object execute(VirtualFrame frame) { return status; } else { Object status; - while (inject(repeatingNode.shouldContinue((status = repeatingNode.executeRepeatingWithValue(frame))))) { + while (inject(loopBody.shouldContinue((status = loopBody.executeRepeatingWithValue(frame))))) { if (CompilerDirectives.inInterpreter()) { // compiled method got invalidated. We might need OSR again. return execute(frame); @@ -150,10 +151,11 @@ static int toIntOrMaxInt(long i) { } private Object profilingLoop(VirtualFrame frame) { + RepeatingNode loopBody = repeatingNode; long iterations = 0; try { Object status; - while (repeatingNode.shouldContinue(status = repeatingNode.executeRepeatingWithValue(frame))) { + while (loopBody.shouldContinue(status = loopBody.executeRepeatingWithValue(frame))) { // the baseLoopCount might be updated from a child loop during an iteration. if (++iterations + baseLoopCount > osrThreshold && !compilationDisabled) { compileLoop(frame); @@ -198,24 +200,25 @@ public final OptimizedCallTarget getCompiledOSRLoop() { } private Object compilingLoop(VirtualFrame frame) { + RepeatingNode loopBody = repeatingNode; long iterations = 0; try { Object status; do { OptimizedCallTarget target = compiledOSRLoop; if (target == null) { - return repeatingNode.initialLoopStatus(); + return loopBody.initialLoopStatus(); } if (!target.isSubmittedForCompilation()) { if (target.isValid()) { return callOSR(target, frame); } invalidateOSRTarget("OSR compilation failed or cancelled"); - return repeatingNode.initialLoopStatus(); + return loopBody.initialLoopStatus(); } iterations++; TruffleSafepoint.poll(this); - } while (repeatingNode.shouldContinue(status = repeatingNode.executeRepeatingWithValue(frame))); + } while (loopBody.shouldContinue(status = loopBody.executeRepeatingWithValue(frame))); return status; } finally { reportLoopIterations(iterations); From d72f22ab97a017becd5272f841d4f040f8f82983 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Wed, 22 Sep 2021 00:27:12 +0000 Subject: [PATCH 084/681] [GR-33413] Next dev cycle. PullRequest: graalpython/1965 --- vm/mx.vm/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 3eb70f303099..0aa0eb86e58b 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -75,7 +75,7 @@ }, { "name": "graalpython", - "version": "421dd8b08e0c329924705b5567c50771984c7774", + "version": "4130a1090c486309114e8f773c39ed31a21c887b", "dynamic": True, "urls": [ {"url": "https://github.com/graalvm/graalpython.git", "kind": "git"}, From e0b4f4535bef624096382ee1974488015ac6c3f4 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Wed, 22 Sep 2021 06:08:16 +0000 Subject: [PATCH 085/681] [GR-33413] Next dev cycle. PullRequest: js/2153 --- vm/mx.vm/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 0aa0eb86e58b..5e92b2fb0538 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -39,7 +39,7 @@ "name": "graal-nodejs", "subdir": True, "dynamic": True, - "version": "35a10cf868b801c69651155c2dd3306405c9975f", + "version": "5d6e27792ff4814ce47ff49f7b9845231e2048ec", "urls" : [ {"url" : "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, @@ -49,7 +49,7 @@ "name": "graal-js", "subdir": True, "dynamic": True, - "version": "35a10cf868b801c69651155c2dd3306405c9975f", + "version": "5d6e27792ff4814ce47ff49f7b9845231e2048ec", "urls": [ {"url": "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, From ed577f5e41280eea401d67a15bdb7d0f1c0c3142 Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Thu, 16 Sep 2021 22:31:33 +0200 Subject: [PATCH 086/681] Update digests of the HotSpot stub. --- .../src/org/graalvm/compiler/lir/amd64/AMD64MathCosOp.java | 4 ++-- .../src/org/graalvm/compiler/lir/amd64/AMD64MathExpOp.java | 4 ++-- .../src/org/graalvm/compiler/lir/amd64/AMD64MathLog10Op.java | 4 ++-- .../src/org/graalvm/compiler/lir/amd64/AMD64MathLogOp.java | 4 ++-- .../src/org/graalvm/compiler/lir/amd64/AMD64MathPowOp.java | 4 ++-- .../src/org/graalvm/compiler/lir/amd64/AMD64MathSinOp.java | 4 ++-- .../src/org/graalvm/compiler/lir/amd64/AMD64MathTanOp.java | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathCosOp.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathCosOp.java index 62a466425fe2..f6e22a38f003 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathCosOp.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathCosOp.java @@ -204,8 +204,8 @@ @StubPort(path = "src/hotspot/cpu/x86/macroAssembler_x86_cos.cpp", lineStart = 0, lineEnd = 630, - commit = "12bac3a02d7b0f17da78d5ee810fd2742ec43ba6", - sha1 = "1961922e2fb08f172595d18e5fe9bd79d9e3cc7a") + commit = "e58c12e61828485bfffbc9d1b865302b93a94158", + sha1 = "cb83822ed974ba4181ff2d55869b301686e0c8c3") // @formatter:on public final class AMD64MathCosOp extends AMD64MathIntrinsicUnaryOp { diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathExpOp.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathExpOp.java index d717e4817bb8..151a00f889f5 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathExpOp.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathExpOp.java @@ -89,8 +89,8 @@ @StubPort(path = "src/hotspot/cpu/x86/macroAssembler_x86_exp.cpp", lineStart = 0, lineEnd = 406, - commit = "51b218842f001f1c4fd5ca7a02a2ba21e9e8a82c", - sha1 = "d21d2a3439932fdbdcf20274798d8488ae1153a9") + commit = "e58c12e61828485bfffbc9d1b865302b93a94158", + sha1 = "e8777563cb0f0f275a490992a36bbdf06bb4c4af") // @formatter:on public final class AMD64MathExpOp extends AMD64MathIntrinsicUnaryOp { diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLog10Op.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLog10Op.java index 6972244f26eb..99904c9ce5d0 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLog10Op.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLog10Op.java @@ -82,8 +82,8 @@ @StubPort(path = "src/hotspot/cpu/x86/macroAssembler_x86_log10.cpp", lineStart = 0, lineEnd = 382, - commit = "12bac3a02d7b0f17da78d5ee810fd2742ec43ba6", - sha1 = "ce7879887e5360ad4c1ca8b776daca5497d6b349") + commit = "e58c12e61828485bfffbc9d1b865302b93a94158", + sha1 = "e03b4280eebe9392433389ab16c4aa52bb01270b") // @formatter:on public final class AMD64MathLog10Op extends AMD64MathIntrinsicUnaryOp { diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLogOp.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLogOp.java index c36a872271d4..2cf8c42ebf34 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLogOp.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLogOp.java @@ -84,8 +84,8 @@ @StubPort(path = "src/hotspot/cpu/x86/macroAssembler_x86_log.cpp", lineStart = 0, lineEnd = 362, - commit = "51b218842f001f1c4fd5ca7a02a2ba21e9e8a82c", - sha1 = "7711be0c6b6e72c57b39578e00000205f1315cde") + commit = "e58c12e61828485bfffbc9d1b865302b93a94158", + sha1 = "4fc26bdb838040042ba0a4f5c04d737705ad4a7a") // @formatter:on public final class AMD64MathLogOp extends AMD64MathIntrinsicUnaryOp { diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathPowOp.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathPowOp.java index cc25c363fc9f..a4b218d6d012 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathPowOp.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathPowOp.java @@ -113,8 +113,8 @@ @StubPort(path = "src/hotspot/cpu/x86/macroAssembler_x86_pow.cpp", lineStart = 0, lineEnd = 1880, - commit = "51b218842f001f1c4fd5ca7a02a2ba21e9e8a82c", - sha1 = "b9ee010c248b0a1ccb29e3348fc158eafbe00115") + commit = "e58c12e61828485bfffbc9d1b865302b93a94158", + sha1 = "ff1905731c30cf343460e72d58537d4672b0dce2") // @formatter:on public final class AMD64MathPowOp extends AMD64MathIntrinsicBinaryOp { diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathSinOp.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathSinOp.java index ef63e1e43be7..5b32f31c2c54 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathSinOp.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathSinOp.java @@ -207,8 +207,8 @@ @StubPort(path = "src/hotspot/cpu/x86/macroAssembler_x86_sin.cpp", lineStart = 0, lineEnd = 848, - commit = "12bac3a02d7b0f17da78d5ee810fd2742ec43ba6", - sha1 = "2ee75c53633f6044ce351d90bbb79081bfad1663") + commit = "e58c12e61828485bfffbc9d1b865302b93a94158", + sha1 = "4ac9bd6f8b98df9a93ab8ef7de250421605b323c") // @formatter:on public final class AMD64MathSinOp extends AMD64MathIntrinsicUnaryOp { diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathTanOp.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathTanOp.java index d2ebccf59bfd..917e1f89419a 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathTanOp.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathTanOp.java @@ -133,8 +133,8 @@ @StubPort(path = "src/hotspot/cpu/x86/macroAssembler_x86_tan.cpp", lineStart = 0, lineEnd = 1059, - commit = "12bac3a02d7b0f17da78d5ee810fd2742ec43ba6", - sha1 = "466fa030d8bf2c1ba0630839bce6f46549a4ebe0") + commit = "e58c12e61828485bfffbc9d1b865302b93a94158", + sha1 = "1f1f3a6d2437b250c0d5b13e596d9ed5a14c869e") // @formatter:on public final class AMD64MathTanOp extends AMD64MathIntrinsicUnaryOp { From 6c47ab69ac8b81da8f3d7aea9ee529394636b26b Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Wed, 22 Sep 2021 13:37:07 +0100 Subject: [PATCH 087/681] Include the language name in the tooltip. --- .../oracle/truffle/tools/profiler/impl/resources/flamegraph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index 944f2b57c020..33c906daaf91 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -120,7 +120,7 @@ function zoom_child(sample) { let name = name_for_sample(sample); let source = source_for_sample(sample); - title.textContent = name + "\n" + + title.textContent = name + " (" + languageNames[sample.l] + ")\n" + "Self samples: " + (sample.i + sample.c) + " (" + (100 * (sample.c + sample.i) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + "Total samples: " + (sample.h) + " (" + (100 * (sample.h + sample.i) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + "Source location: " + source + ":" + sample.fl + "\n"; From d11728e723493af8c5c2cf71752f6e3d55d06213 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Thu, 9 Sep 2021 19:44:30 +0200 Subject: [PATCH 088/681] Properly quote arguments passed via argument files NativeImage passes some arguments via the @file feature of the JDK launcher. When some arguments, separated by new lines, contain whitespace *and* aren't properly quoted, the JDK launcher code fails to parse the argument file and the native image generator class is never launched. Shell-quoting arguments before writing them to an @argument file avoids this issue. Due to a Windows argument file quirk, where '\' don't need to be escaped if NOT quoted, but DO need escaping when they are quoted we unconditionally escape '\'. Closes #3769 --- .../src/com/oracle/svm/driver/NativeImage.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java index ba01e3d1a970..06c3b8a07f46 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java @@ -50,6 +50,7 @@ import java.util.Map; import java.util.Optional; import java.util.Properties; +import java.util.StringJoiner; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -1301,7 +1302,22 @@ protected static List createImageBuilderArgs(ArrayList imageArgs protected static String createVMInvocationArgumentFile(List arguments) { try { Path argsFile = Files.createTempFile("vminvocation", ".args"); - String joinedOptions = String.join("\n", arguments); + StringJoiner joiner = new StringJoiner("\n"); + for (String arg : arguments) { + // Options in @argfile need to be properly quoted as + // this relies on the JDK's @argfile parsing when the + // native image generator is being launched. + String quoted = SubstrateUtil.quoteShellArg(arg); + // @argfile rules for Windows quirk: backslashes don't need to be + // escaped if the option they are used in isn't quoted. If it is + // though, then they need to be escaped. This might mean that + // user-supplied arguments containing '\' will be double escaped. + if (quoted.startsWith("'")) { + quoted = quoted.replace("\\", "\\\\"); + } + joiner.add(quoted); + } + String joinedOptions = joiner.toString(); Files.write(argsFile, joinedOptions.getBytes()); argsFile.toFile().deleteOnExit(); return "@" + argsFile; From 62154ef0fce75dc17d48865bac876276e64e58ab Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Wed, 22 Sep 2021 16:18:02 +0200 Subject: [PATCH 089/681] Extract ShapeImpl.getLayoutStrategy(). --- .../object/DynamicObjectLibraryImpl.java | 18 +++++++++--------- .../oracle/truffle/object/PropertyImpl.java | 4 ++-- .../com/oracle/truffle/object/ShapeImpl.java | 18 +++++++++++------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java index 9dd2cadb47ee..dade8737f479 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java @@ -279,7 +279,7 @@ public static boolean updateShape(DynamicObject object, @TruffleBoundary static boolean updateShapeImpl(DynamicObject object) { - return ((ShapeImpl) object.getShape()).getLayout().getStrategy().updateShape(object); + return ((ShapeImpl) object.getShape()).getLayoutStrategy().updateShape(object); } @ExportMessage @@ -338,12 +338,12 @@ private static boolean putUncachedSlow(DynamicObject object, Object key, Object if (Flags.isSetExisting(putFlags)) { return false; } else { - LayoutStrategy strategy = oldShape.getLayout().getStrategy(); + LayoutStrategy strategy = oldShape.getLayoutStrategy(); newShape = strategy.defineProperty(oldShape, key, value, Flags.getPropertyFlags(putFlags), null, existingProperty, putFlags); property = newShape.getProperty(key); } } else if (Flags.isUpdateFlags(putFlags) && Flags.getPropertyFlags(putFlags) != existingProperty.getFlags()) { - LayoutStrategy strategy = oldShape.getLayout().getStrategy(); + LayoutStrategy strategy = oldShape.getLayoutStrategy(); newShape = strategy.defineProperty(oldShape, key, value, Flags.getPropertyFlags(putFlags), null, existingProperty, putFlags); property = newShape.getProperty(key); } else { @@ -351,7 +351,7 @@ private static boolean putUncachedSlow(DynamicObject object, Object key, Object newShape = oldShape; property = existingProperty; } else { - LayoutStrategy strategy = oldShape.getLayout().getStrategy(); + LayoutStrategy strategy = oldShape.getLayoutStrategy(); newShape = strategy.defineProperty(oldShape, key, value, existingProperty.getFlags(), null, existingProperty, putFlags); property = newShape.getProperty(key); } @@ -380,7 +380,7 @@ private static boolean putUncachedSlow(DynamicObject object, Object key, Object static RemovePlan prepareRemove(ShapeImpl shapeBefore, ShapeImpl shapeAfter) { assert !shapeBefore.isShared(); - LayoutStrategy strategy = shapeBefore.getLayout().getStrategy(); + LayoutStrategy strategy = shapeBefore.getLayoutStrategy(); List moves = new ArrayList<>(); boolean canMoveInPlace = shapeAfter.getObjectArrayCapacity() <= shapeBefore.getObjectArrayCapacity() && shapeAfter.getPrimitiveArrayCapacity() <= shapeBefore.getPrimitiveArrayCapacity(); @@ -1514,7 +1514,7 @@ private ShapeImpl getNewShape(DynamicObject object, Object value, long putFlags, return oldShape; } else { int propertyFlags = Flags.getPropertyFlags(putFlags); - LayoutStrategy strategy = oldShape.getLayout().getStrategy(); + LayoutStrategy strategy = oldShape.getLayoutStrategy(); return strategy.defineProperty(oldShape, cachedKey, value, propertyFlags, null, putFlags); } } @@ -1522,7 +1522,7 @@ private ShapeImpl getNewShape(DynamicObject object, Object value, long putFlags, if (Flags.isUpdateFlags(putFlags)) { if (Flags.getPropertyFlags(putFlags) != property.getFlags()) { int propertyFlags = Flags.getPropertyFlags(putFlags); - LayoutStrategy strategy = oldShape.getLayout().getStrategy(); + LayoutStrategy strategy = oldShape.getLayoutStrategy(); return strategy.defineProperty(oldShape, cachedKey, value, propertyFlags, null, putFlags); } } @@ -1531,13 +1531,13 @@ private ShapeImpl getNewShape(DynamicObject object, Object value, long putFlags, if (!location.isDeclared() && !location.canSet(value)) { // generalize assert oldShape == ACCESS.getShape(object); - LayoutStrategy strategy = oldShape.getLayout().getStrategy(); + LayoutStrategy strategy = oldShape.getLayoutStrategy(); ShapeImpl newShape = strategy.definePropertyGeneralize(oldShape, property, value, null, putFlags); assert newShape != oldShape; return newShape; } else if (location.isDeclared()) { // redefine declared - LayoutStrategy strategy = oldShape.layout.getStrategy(); + LayoutStrategy strategy = oldShape.getLayoutStrategy(); return strategy.defineProperty(oldShape, cachedKey, value, property.getFlags(), null, putFlags); } else { // set existing diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java index 496e3845608c..8115e9b57391 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java @@ -249,12 +249,12 @@ public final Location getLocation() { private void setSlowCase(DynamicObject store, Object value) { ShapeImpl oldShape = (ShapeImpl) store.getShape(); - oldShape.getLayout().getStrategy().propertySetFallback(this, store, value, oldShape); + oldShape.getLayoutStrategy().propertySetFallback(this, store, value, oldShape); } private void setWithShapeSlowCase(DynamicObject store, Object value, Shape currentShape, Shape nextShape) { ShapeImpl oldShape = (ShapeImpl) currentShape; - oldShape.getLayout().getStrategy().propertySetWithShapeFallback(this, store, value, oldShape, (ShapeImpl) nextShape); + oldShape.getLayoutStrategy().propertySetWithShapeFallback(this, store, value, oldShape, (ShapeImpl) nextShape); } /** @since 0.17 or earlier */ diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java index 3e2785e6a0e5..a9ae65730339 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java @@ -563,7 +563,7 @@ public final R iterateTransitions(BiFunction consu public ShapeImpl addProperty(Property property) { assert isValid(); - return layout.getStrategy().addProperty(this, property); + return getLayoutStrategy().addProperty(this, property); } /** @since 0.17 or earlier */ @@ -588,14 +588,14 @@ final void onPropertyTransitionWithKey(Object propertyKey) { @TruffleBoundary @Override public ShapeImpl defineProperty(Object key, Object value, int propertyFlags) { - return layout.getStrategy().defineProperty(this, key, value, propertyFlags, null); + return getLayoutStrategy().defineProperty(this, key, value, propertyFlags, null); } /** @since 0.17 or earlier */ @TruffleBoundary @Override public ShapeImpl defineProperty(Object key, Object value, int propertyFlags, LocationFactory locationFactory) { - return layout.getStrategy().defineProperty(this, key, value, propertyFlags, locationFactory); + return getLayoutStrategy().defineProperty(this, key, value, propertyFlags, locationFactory); } /** @since 0.17 or earlier */ @@ -907,7 +907,7 @@ public final boolean hasProperty(Object name) { public final ShapeImpl removeProperty(Property prop) { onPropertyTransition(prop); - return layout.getStrategy().removeProperty(this, prop); + return getLayoutStrategy().removeProperty(this, prop); } /** @since 0.17 or earlier */ @@ -920,7 +920,7 @@ public final ShapeImpl append(Property oldProperty) { /** @since 0.17 or earlier */ @Override public final BaseAllocator allocator() { - return layout.getStrategy().createAllocator(this); + return getLayoutStrategy().createAllocator(this); } /** @@ -934,7 +934,7 @@ public ShapeImpl replaceProperty(Property oldProperty, Property newProperty) { assert oldProperty.getKey().equals(newProperty.getKey()); onPropertyTransition(oldProperty); - return layout.getStrategy().replaceProperty(this, oldProperty, newProperty); + return getLayoutStrategy().replaceProperty(this, oldProperty, newProperty); } /** @@ -1040,6 +1040,10 @@ public final LayoutImpl getLayout() { return layout; } + public final LayoutStrategy getLayoutStrategy() { + return getLayout().getStrategy(); + } + /** @since 0.17 or earlier */ @Override public final Object getSharedData() { @@ -1151,7 +1155,7 @@ protected ShapeImpl setFlags(int newShapeFlags) { @Override public final ShapeImpl reservePrimitiveExtensionArray() { if (layout.hasPrimitiveExtensionArray() && !hasPrimitiveArray()) { - return layout.getStrategy().addPrimitiveExtensionArray(this); + return getLayoutStrategy().addPrimitiveExtensionArray(this); } return this; } From 7e7f2e651702e5c2dd9ed82112bff4fa0684071a Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Thu, 9 Sep 2021 15:20:07 +0200 Subject: [PATCH 090/681] [GR-33657] Extend CEntryPoint annotation by include attribute. --- sdk/CHANGELOG.md | 3 + .../org.graalvm.nativeimage/snapshot.sigtest | 19 ++ .../nativeimage/c/function/CEntryPoint.java | 57 +++- .../llvm/runtime/LLVMExceptionUnwind.java | 4 +- .../posix/PosixSubstrateSegfaultHandler.java | 4 +- .../core/posix/thread/PosixJavaThreads.java | 4 +- .../svm/core/windows/WindowsJavaThreads.java | 4 +- .../WindowsSubstrateSegfaultHandler.java | 5 +- .../com/oracle/svm/core/JavaMainWrapper.java | 4 +- .../core/c/function/CEntryPointOptions.java | 20 +- .../hotspot/libgraal/LibGraalEntryPoints.java | 4 +- ...solateAwareConstantReflectionProvider.java | 32 +-- ...ateAwareObjectConstantEqualityFeature.java | 8 +- .../graal/isolated/IsolatedCompileClient.java | 4 +- .../isolated/IsolatedCompileContext.java | 8 +- .../graal/isolated/IsolatedGraalUtils.java | 12 +- .../isolated/IsolatedObjectConstant.java | 8 +- .../graal/isolated/IsolatedObjectProxy.java | 8 +- .../IsolatedRuntimeCodeInstaller.java | 20 +- .../isolated/IsolatedSpeculationLog.java | 16 +- .../svm/hosted/NativeImageGenerator.java | 15 +- .../svm/jni/functions/JNIFunctions.java | 244 +++++++++--------- .../jni/functions/JNIInvocationInterface.java | 32 +-- .../oracle/svm/truffle/nfi/NativeAPIImpl.java | 44 ++-- .../oracle/svm/truffle/nfi/NativeClosure.java | 16 +- .../isolated/IsolateAwareTruffleCompiler.java | 12 +- .../IsolatedCompilableTruffleAST.java | 60 ++--- .../IsolatedCompilationIdentifier.java | 8 +- .../isolated/IsolatedTruffleCallNode.java | 12 +- .../IsolatedTruffleCompilationTask.java | 20 +- ...IsolatedTruffleCompilerEventForwarder.java | 28 +- .../isolated/IsolatedTruffleInlining.java | 32 +-- .../IsolatedTruffleRuntimeSupport.java | 24 +- ...IsolatedTruffleSourceLanguagePosition.java | 16 +- 34 files changed, 453 insertions(+), 354 deletions(-) diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index 3d7ca70b21f8..063ed15bffd5 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -2,6 +2,9 @@ This changelog summarizes major changes between GraalVM SDK versions. The main focus is on APIs exported by GraalVM SDK. +## Version 22.0.0 +* (GR-33657) Native Image API: Added `CEntryPoint#include` attribute which can be used to controll if the entry point should be automatically added to the shared library. + ## Version 21.3.0 * Added the ability to share values between contexts. Please see `Context.Builder.allowValueSharing(boolean)` for further details. * (GR-20286) Polyglot API: Added support for scoped values in guest-to-host callbacks. [Scoped values](https://www.graalvm.org/reference-manual/embed-languages/#controlling-host-callback-parameter-scoping) are automatically released when the callback returns. They can be configured in `HostAccess`. diff --git a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest index df2964afe9ff..5dc7f0afe64f 100644 --- a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest +++ b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest @@ -114,6 +114,10 @@ CLSS public abstract interface !annotation java.lang.annotation.Target intf java.lang.annotation.Annotation meth public abstract java.lang.annotation.ElementType[] value() +CLSS public abstract interface java.util.function.BooleanSupplier + anno 0 java.lang.FunctionalInterface() +meth public abstract boolean getAsBoolean() + CLSS public final org.graalvm.nativeimage.CurrentIsolate meth public static org.graalvm.nativeimage.Isolate getIsolate() meth public static org.graalvm.nativeimage.IsolateThread getCurrentThread() @@ -457,13 +461,22 @@ CLSS public abstract interface !annotation org.graalvm.nativeimage.c.function.CE innr public abstract interface static !annotation IsolateContext innr public abstract interface static !annotation IsolateThreadContext innr public final static !enum Builtin +innr public final static AlwaysIncluded innr public final static FatalExceptionHandler +innr public final static NotIncludedAutomatically intf java.lang.annotation.Annotation +meth public abstract !hasdefault java.lang.Class include() meth public abstract !hasdefault java.lang.Class exceptionHandler() meth public abstract !hasdefault java.lang.String name() meth public abstract !hasdefault java.lang.String[] documentation() meth public abstract !hasdefault org.graalvm.nativeimage.c.function.CEntryPoint$Builtin builtin() +CLSS public final static org.graalvm.nativeimage.c.function.CEntryPoint$AlwaysIncluded + outer org.graalvm.nativeimage.c.function.CEntryPoint +intf java.util.function.BooleanSupplier +meth public boolean getAsBoolean() +supr java.lang.Object + CLSS public final static !enum org.graalvm.nativeimage.c.function.CEntryPoint$Builtin outer org.graalvm.nativeimage.c.function.CEntryPoint fld public final static org.graalvm.nativeimage.c.function.CEntryPoint$Builtin ATTACH_THREAD @@ -493,6 +506,12 @@ CLSS public abstract interface static !annotation org.graalvm.nativeimage.c.func anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[PARAMETER]) intf java.lang.annotation.Annotation +CLSS public final static org.graalvm.nativeimage.c.function.CEntryPoint$NotIncludedAutomatically + outer org.graalvm.nativeimage.c.function.CEntryPoint +intf java.util.function.BooleanSupplier +meth public boolean getAsBoolean() +supr java.lang.Object + CLSS public final org.graalvm.nativeimage.c.function.CEntryPointLiteral<%0 extends org.graalvm.nativeimage.c.function.CFunctionPointer> meth public !varargs static <%0 extends org.graalvm.nativeimage.c.function.CFunctionPointer> org.graalvm.nativeimage.c.function.CEntryPointLiteral<{%%0}> create(java.lang.Class,java.lang.String,java.lang.Class[]) meth public {org.graalvm.nativeimage.c.function.CEntryPointLiteral%0} getFunctionPointer() diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/c/function/CEntryPoint.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/c/function/CEntryPoint.java index 89c27d7207dc..853d0a91d48b 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/c/function/CEntryPoint.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/c/function/CEntryPoint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -44,6 +44,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.function.BooleanSupplier; import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.Isolate; @@ -135,6 +136,60 @@ private FatalExceptionHandler() { */ Builtin builtin() default Builtin.NO_BUILTIN; + /** + * If the supplier returns {@code true}, this entry point is added automatically when building a + * shared library. This means the method is a root method for compilation, and everything + * reachable from it is compiled too. + * + * The provided class must have a nullary constructor, which is used to instantiate the class. + * Then the supplier function is called on the newly instantiated instance. + * + * @since 22.0 + */ + Class include() default AlwaysIncluded.class; + + /** + * A {@link BooleanSupplier} that always returns {@code true}. + * + * @since 22.0 + */ + final class AlwaysIncluded implements BooleanSupplier { + + private AlwaysIncluded() { + } + + /** + * Returns {@code true}. + * + * @since 22.0 + */ + @Override + public boolean getAsBoolean() { + return true; + } + } + + /** + * A {@link BooleanSupplier} that always returns {@code false}. + * + * @since 22.0 + */ + final class NotIncludedAutomatically implements BooleanSupplier { + + private NotIncludedAutomatically() { + } + + /** + * Returns {@code false}. + * + * @since 22.0 + */ + @Override + public boolean getAsBoolean() { + return false; + } + } + /** * The built-in methods which can be {@linkplain #builtin() aliased}. * diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/runtime/LLVMExceptionUnwind.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/runtime/LLVMExceptionUnwind.java index 114528940cd3..d37a21b2c15c 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/runtime/LLVMExceptionUnwind.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/runtime/LLVMExceptionUnwind.java @@ -82,8 +82,8 @@ public class LLVMExceptionUnwind { * from which it will get extracted after the landingpad instruction (see * NodeLLVMBuilder.emitReadExceptionObject). */ - @CEntryPoint - @CEntryPointOptions(include = IncludeForLLVMOnly.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = IncludeForLLVMOnly.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) @SuppressWarnings("unused") public static int personality(int version, int action, IsolateThread thread, _Unwind_Exception unwindException, _Unwind_Context context) { Pointer ip = getIP(context); diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSubstrateSegfaultHandler.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSubstrateSegfaultHandler.java index 14edd6ac3147..4a407624f6c1 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSubstrateSegfaultHandler.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSubstrateSegfaultHandler.java @@ -60,8 +60,8 @@ public void afterRegistration(AfterRegistrationAccess access) { } class PosixSubstrateSegfaultHandler extends SubstrateSegfaultHandler { - @CEntryPoint - @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished) @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate in segfault signal handler.") @Uninterruptible(reason = "Must be uninterruptible until it gets immune to safepoints") private static void dispatch(@SuppressWarnings("unused") int signalNumber, @SuppressWarnings("unused") siginfo_t sigInfo, ucontext_t uContext) { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixJavaThreads.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixJavaThreads.java index c43b00e95c14..8bb596508002 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixJavaThreads.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixJavaThreads.java @@ -183,8 +183,8 @@ static void enter(ThreadStartData data) { } } - @CEntryPoint - @CEntryPointOptions(prologue = PthreadStartRoutinePrologue.class, epilogue = LeaveDetachThreadEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = PthreadStartRoutinePrologue.class, epilogue = LeaveDetachThreadEpilogue.class, publishAs = Publish.NotPublished) static WordBase pthreadStartRoutine(ThreadStartData data) { ObjectHandle threadHandle = data.getThreadHandle(); UnmanagedMemory.free(data); diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsJavaThreads.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsJavaThreads.java index 3f548cd0e44a..6ccec99fb0da 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsJavaThreads.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsJavaThreads.java @@ -127,8 +127,8 @@ static void enter(WindowsThreadStartData data) { } } - @CEntryPoint - @CEntryPointOptions(prologue = OSThreadStartRoutinePrologue.class, epilogue = LeaveDetachThreadEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = OSThreadStartRoutinePrologue.class, epilogue = LeaveDetachThreadEpilogue.class, publishAs = Publish.NotPublished) static WordBase osThreadStartRoutine(WindowsThreadStartData data) { ObjectHandle threadHandle = data.getThreadHandle(); WinBase.HANDLE osThreadHandle = data.getOSThreadHandle(); diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSubstrateSegfaultHandler.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSubstrateSegfaultHandler.java index 1d9788b83e81..52c1c497b65c 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSubstrateSegfaultHandler.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSubstrateSegfaultHandler.java @@ -44,7 +44,6 @@ import com.oracle.svm.core.c.function.CEntryPointOptions; import com.oracle.svm.core.c.function.CEntryPointOptions.NoEpilogue; import com.oracle.svm.core.c.function.CEntryPointOptions.NoPrologue; -import com.oracle.svm.core.c.function.CEntryPointOptions.NotIncludedAutomatically; import com.oracle.svm.core.c.function.CEntryPointOptions.Publish; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.util.VMError; @@ -89,8 +88,8 @@ protected void installInternal() { private static final CEntryPointLiteral HANDLER_LITERAL = CEntryPointLiteral.create(WindowsSubstrateSegfaultHandler.class, "handler", ErrHandlingAPI.EXCEPTION_POINTERS.class); - @CEntryPoint - @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly, include = NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) @Uninterruptible(reason = "Must be uninterruptible until we get immune to safepoints.") @RestrictHeapAccess(access = NO_HEAP_ACCESS, reason = "We have yet to enter the isolate.") private static int handler(ErrHandlingAPI.EXCEPTION_POINTERS exceptionInfo) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java index 8a10aa7acef5..21bb27cc087e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java @@ -176,8 +176,8 @@ public static int runCore() { return exitCode; } - @CEntryPoint - @CEntryPointOptions(prologue = EnterCreateIsolateWithCArgumentsPrologue.class, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterCreateIsolateWithCArgumentsPrologue.class) @SuppressWarnings("unused") public static int run(int argc, CCharPointerPointer argv) { return runCore(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointOptions.java index 61eaef0a2e63..aebf9b37560b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -74,10 +74,18 @@ public String apply(String name) { * * The provided class must have a nullary constructor, which is used to instantiate the class. * Then the supplier function is called on the newly instantiated instance. + * + * @deprecated Use {@link CEntryPoint#include()}. */ + @Deprecated Class include() default CEntryPointOptions.AlwaysIncluded.class; - /** A {@link BooleanSupplier} that always returns {@code true}. */ + /** + * A {@link BooleanSupplier} that always returns {@code true}. + * + * @deprecated Use {@link org.graalvm.nativeimage.c.function.CEntryPoint.AlwaysIncluded}. + */ + @Deprecated class AlwaysIncluded implements BooleanSupplier { @Override public boolean getAsBoolean() { @@ -85,7 +93,13 @@ public boolean getAsBoolean() { } } - /** A {@link BooleanSupplier} that always returns {@code false}. */ + /** + * A {@link BooleanSupplier} that always returns {@code false}. + * + * @deprecated Use + * {@link org.graalvm.nativeimage.c.function.CEntryPoint.NotIncludedAutomatically}. + */ + @Deprecated class NotIncludedAutomatically implements BooleanSupplier { @Override public boolean getAsBoolean() { diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java index d84475bac3cb..549fafd4f2c7 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java @@ -60,7 +60,6 @@ import com.oracle.svm.core.c.CGlobalData; import com.oracle.svm.core.c.CGlobalDataFactory; -import com.oracle.svm.core.c.function.CEntryPointOptions; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; @@ -202,8 +201,7 @@ public static long getIsolateId(PointerBase jniEnv, * @return a handle to a {@link InstalledCode} in HotSpot's heap or 0 if compilation failed */ @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_org_graalvm_compiler_hotspot_test_CompileTheWorld_compileMethodInLibgraal") - @CEntryPointOptions(include = LibGraalFeature.IsEnabled.class) + @CEntryPoint(name = "Java_org_graalvm_compiler_hotspot_test_CompileTheWorld_compileMethodInLibgraal", include = LibGraalFeature.IsEnabled.class) private static long compileMethod(PointerBase jniEnv, PointerBase jclass, @CEntryPoint.IsolateThreadContext long isolateThread, diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareConstantReflectionProvider.java index 3b2ab8058d84..f928c83d731a 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareConstantReflectionProvider.java @@ -85,8 +85,8 @@ private static JavaConstant read(JavaKind kind, Constant base, long displacement return ConstantDataConverter.toCompiler(resultData); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void read0(@SuppressWarnings("unused") ClientIsolateThread client, char kindChar, ConstantData baseData, long displacement, int primitiveBits, long compressBase, int compressShift, ConstantData resultData) { JavaConstant base = ConstantDataConverter.toClient(baseData); @@ -131,8 +131,8 @@ public Integer readArrayLength(JavaConstant array) { return Array.getLength(arrayObj); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static int readArrayLength0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle arrayHandle) { Object array = IsolatedCompileClient.get().unhand(arrayHandle); if (!array.getClass().isArray()) { @@ -156,8 +156,8 @@ public JavaConstant readArrayElement(JavaConstant array, int index) { return ConstantDataConverter.toCompiler(resultData); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void readArrayElement0(@SuppressWarnings("unused") ClientIsolateThread client, ConstantData arrayData, int index, ConstantData resultData) { JavaConstant array = ConstantDataConverter.toClient(arrayData); Object a = SubstrateObjectConstant.asObject(array); @@ -185,8 +185,8 @@ public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receive return ConstantDataConverter.toCompiler(resultData); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void readFieldValue0(@SuppressWarnings("unused") ClientIsolateThread client, ImageHeapRef fieldRef, ConstantData receiverData, ConstantData resultData) { JavaConstant receiver = ConstantDataConverter.toClient(receiverData); Constant result = readFieldValue(ImageHeapObjects.deref(fieldRef), receiver); @@ -208,8 +208,8 @@ public JavaConstant boxPrimitive(JavaConstant primitive) { return ConstantDataConverter.toCompiler(resultData); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void boxPrimitive0(@SuppressWarnings("unused") ClientIsolateThread client, ConstantData primitiveData, ConstantData resultData) { JavaConstant primitive = ConstantDataConverter.toClient(primitiveData); Constant result = SubstrateObjectConstant.forObject(primitive.asBoxedPrimitive()); @@ -229,8 +229,8 @@ public JavaConstant unboxPrimitive(JavaConstant boxed) { return super.unboxPrimitive(boxed); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void unboxPrimitive0(@SuppressWarnings("unused") ClientIsolateThread client, ConstantData boxedData, ConstantData resultData) { Constant boxed = ConstantDataConverter.toClient(boxedData); Constant result = JavaConstant.forBoxedPrimitive(SubstrateObjectConstant.asObject(boxed)); @@ -254,8 +254,8 @@ public ResolvedJavaType asJavaType(Constant hub) { return super.asJavaType(resolved); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ImageHeapRef getHubConstantAsImageHeapRef(@SuppressWarnings("unused") ClientIsolateThread client, ConstantData hubData) { JavaConstant hub = ConstantDataConverter.toClient(hubData); Object target = SubstrateObjectConstant.asObject(hub); @@ -283,8 +283,8 @@ public int getImageHeapOffset(JavaConstant constant) { return super.getImageHeapOffset(constant); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static int getImageHeapOffset0(@SuppressWarnings("unused") ClientIsolateThread client, ConstantData constantData) { Constant constant = ConstantDataConverter.toClient(constantData); return getImageHeapOffsetInternal((SubstrateObjectConstant) constant); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareObjectConstantEqualityFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareObjectConstantEqualityFeature.java index 32176312fc61..bd73afd2c54e 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareObjectConstantEqualityFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareObjectConstantEqualityFeature.java @@ -65,14 +65,14 @@ private static boolean compareIsolatedConstant(IsolatedObjectConstant a, Constan throw VMError.shouldNotReachHere("Unknown object constant: " + b); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) static boolean isolatedConstantHandleTargetsEqual(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle x, ClientHandle y) { return IsolatedCompileClient.get().unhand(x) == IsolatedCompileClient.get().unhand(y); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean isolatedHandleTargetEqualImageObject(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle x, ImageHeapRef y) { return IsolatedCompileClient.get().unhand(x) == ImageHeapObjects.deref(y); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileClient.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileClient.java index 20ffe9e193cb..b8f31b310517 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileClient.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileClient.java @@ -87,8 +87,8 @@ public CompilerHandle createStringInCompiler(String s) { } } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle createStringInCompiler0(@SuppressWarnings("unused") CompilerIsolateThread compiler, CCharPointer cstr) { return IsolatedCompileContext.get().hand(CTypeConversion.toJavaString(cstr)); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileContext.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileContext.java index d286403f4e25..f7b28a3dae60 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileContext.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileContext.java @@ -88,14 +88,14 @@ public ClientHandle createStringArrayInClient(String[] array) { } } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle createStringInClient0(@SuppressWarnings("unused") ClientIsolateThread client, CCharPointer cstr) { return IsolatedCompileClient.get().hand(CTypeConversion.toJavaString(cstr)); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle createStringArrayInClient0(@SuppressWarnings("unused") ClientIsolateThread client, int length, CCharPointerPointer ptrs) { String[] array = new String[length]; for (int i = 0; i < length; i++) { diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedGraalUtils.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedGraalUtils.java index b15a60762744..04cd8adca1ca 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedGraalUtils.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedGraalUtils.java @@ -78,8 +78,8 @@ public static InstalledCode compileInNewIsolateAndInstall(SubstrateMethod method return installedCode; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle compileInNewIsolateAndInstall0(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext CompilerIsolateThread isolate, ClientIsolateThread clientIsolate, ImageHeapRef methodRef, ClientHandle encodedOptions, int encodedOptionsLength) { @@ -115,8 +115,8 @@ public static void compileInNewIsolate(SubstrateMethod method) { } } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void compileInNewIsolate0(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext CompilerIsolateThread isolate, ClientIsolateThread clientIsolate, ImageHeapRef methodRef, ClientHandle encodedOptions, int encodedOptionsLength) { @@ -158,8 +158,8 @@ public static void applyClientRuntimeOptionValues(ClientHandle encodedOp } } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void copyOptions(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext ClientIsolateThread isolate, ClientHandle encodedOptionsHandle, PointerBase buffer) { byte[] encodedOptions = IsolatedCompileClient.get().unhand(encodedOptionsHandle); CTypeConversion.asByteBuffer(buffer, encodedOptions.length).put(encodedOptions); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedObjectConstant.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedObjectConstant.java index 3ed71f59624c..7e4190067799 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedObjectConstant.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedObjectConstant.java @@ -63,8 +63,8 @@ private Class getObjectClass() { return cachedClass; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ImageHeapRef> getObjectClass0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle h) { Object target = IsolatedCompileClient.get().unhand(h); return ImageHeapObjects.ref(target.getClass()); @@ -98,8 +98,8 @@ public int getIdentityHashCode() { return h; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static int getIdentityHashCode0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle h) { Object target = IsolatedCompileClient.get().unhand(h); return computeIdentityHashCode(target); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedObjectProxy.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedObjectProxy.java index 915d4fe9d009..ca8d5a8dfcbc 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedObjectProxy.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedObjectProxy.java @@ -81,14 +81,14 @@ public String toString() { return s; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static int hashCode0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle handle) { return IsolatedCompileClient.get().unhand(handle).hashCode(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle toString0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle handle) { Object obj = IsolatedCompileClient.get().unhand(handle); String s = "Isolated: " + obj; diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedRuntimeCodeInstaller.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedRuntimeCodeInstaller.java index 5326f0b09add..7a7a1a284fe8 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedRuntimeCodeInstaller.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedRuntimeCodeInstaller.java @@ -60,8 +60,8 @@ public static ClientHandle installInClientIsolate(ImageH return installInClientIsolate0(clientIsolate, methodRef, installInfo, installedCodeFactoryHandle); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle installInClientIsolate0(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext ClientIsolateThread isolate, ImageHeapRef methodRef, CodeInstallInfo installInfo, ClientHandle installedCodeFactoryHandle) { @@ -92,8 +92,8 @@ public static ClientHandle installInClientIsolate(Shared return installInClientIsolate1(clientIsolate, clientMethodHandle, installInfo, installedCodeFactoryHandle); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle installInClientIsolate1(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext ClientIsolateThread isolate, ClientHandle methodHandle, CodeInstallInfo installInfo, ClientHandle installedCodeFactoryHandle) { @@ -154,8 +154,8 @@ protected Pointer allocateCodeMemory(long size) { return (Pointer) memory; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CodePointer allocateCodeMemory0(@SuppressWarnings("unused") IsolateThread targetIsolate, UnsignedWord size) { return RuntimeCodeInfoAccess.allocateCodeMemory(size); } @@ -165,8 +165,8 @@ protected void makeCodeMemoryReadOnly(Pointer start, long size) { makeCodeMemoryReadOnly0(targetIsolate, start, size); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void makeCodeMemoryReadOnly0(@SuppressWarnings("unused") IsolateThread targetIsolate, Pointer start, long size) { RuntimeCodeInfoAccess.makeCodeMemoryExecutableReadOnly((CodePointer) start, WordFactory.unsigned(size)); } @@ -176,8 +176,8 @@ protected void makeCodeMemoryWriteableNonExecutable(Pointer start, long size) { makeCodeMemoryWriteableNonExecutable0(targetIsolate, start, size); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void makeCodeMemoryWriteableNonExecutable0(@SuppressWarnings("unused") IsolateThread targetIsolate, Pointer start, long size) { RuntimeCodeInfoAccess.makeCodeMemoryWriteableNonExecutable((CodePointer) start, WordFactory.unsigned(size)); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedSpeculationLog.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedSpeculationLog.java index 7dde34be0877..058f5058b007 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedSpeculationLog.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedSpeculationLog.java @@ -159,20 +159,20 @@ public Speculation lookupSpeculation(JavaConstant constant) { throw VMError.shouldNotReachHere("not required"); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void collectFailedSpeculations0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle logHandle) { IsolatedCompileClient.get().unhand(logHandle).collectFailedSpeculations(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean hasSpeculations0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle logHandle) { return IsolatedCompileClient.get().unhand(logHandle).hasSpeculations(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean maySpeculate0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle logHandle, PointerBase arrayData, int length) { byte[] bytes = new byte[length]; ByteBuffer.wrap(bytes).put(CTypeConversion.asByteBuffer(arrayData, length)); @@ -180,8 +180,8 @@ private static boolean maySpeculate0(@SuppressWarnings("unused") ClientIsolateTh return log.maySpeculate(new EncodedSpeculationReason(bytes)); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle speculate0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle logHandle, PointerBase arrayData, int length) { byte[] bytes = new byte[length]; ByteBuffer.wrap(bytes).put(CTypeConversion.asByteBuffer(arrayData, length)); 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 5773e53793b5..ff3fea8a9152 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 @@ -55,6 +55,7 @@ import java.util.Set; 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; @@ -1059,16 +1060,26 @@ private NativeLibraries setupNativeLibraries(String imageName, ConstantReflectio } } + @SuppressWarnings("deprecation") private void registerEntryPoints(Map entryPoints) { for (Method m : loader.findAnnotatedMethods(CEntryPoint.class)) { if (!Modifier.isStatic(m.getModifiers())) { throw UserError.abort("Entry point method %s.%s is not static. Add a static modifier to the method.", m.getDeclaringClass().getName(), m.getName()); } - boolean include = true; + Class cEntryPointIncludeClass = m.getAnnotation(CEntryPoint.class).include(); + boolean include = ReflectionUtil.newInstance(cEntryPointIncludeClass).getAsBoolean(); CEntryPointOptions options = m.getAnnotation(CEntryPointOptions.class); if (options != null) { - include = ReflectionUtil.newInstance(options.include()).getAsBoolean(); + Class cEntryPointOptionsIncludeClass = options.include(); + if (cEntryPointOptionsIncludeClass != CEntryPointOptions.AlwaysIncluded.class) { + if (cEntryPointIncludeClass != CEntryPoint.AlwaysIncluded.class) { + throw UserError.abort( + "The 'include' attribute for entry point method %s.%s is specified both in 'CEntryPoint' and 'CEntryPointOptions' annotations. Remove the deprecated 'CEntryPointOptions#include' attribute.", + m.getDeclaringClass().getName(), m.getName()); + } + include = ReflectionUtil.newInstance(cEntryPointOptionsIncludeClass).getAsBoolean(); + } } if (include) { entryPoints.put(m, CEntryPointData.create(m)); diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java index ac3e41004243..32815f040dcd 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java @@ -146,8 +146,8 @@ public final class JNIFunctions { private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe(); - @CEntryPoint - @CEntryPointOptions(prologue = CEntryPointOptions.NoPrologue.class, epilogue = CEntryPointOptions.NoEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = CEntryPointOptions.NoPrologue.class, epilogue = CEntryPointOptions.NoEpilogue.class, publishAs = Publish.NotPublished) @Uninterruptible(reason = "No need to enter the isolate and also no way to report errors if unable to.") static int GetVersion(JNIEnvironment env) { return JNIVersion.JNI_VERSION_1_8(); @@ -157,8 +157,8 @@ static int GetVersion(JNIEnvironment env) { * jobject NewLocalRef(JNIEnv *env, jobject ref); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle NewLocalRef(JNIEnvironment env, JNIObjectHandle ref) { return JNIObjectHandles.newLocalRef(ref); } @@ -167,8 +167,8 @@ static JNIObjectHandle NewLocalRef(JNIEnvironment env, JNIObjectHandle ref) { * void DeleteLocalRef(JNIEnv *env, jobject localRef); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void DeleteLocalRef(JNIEnvironment env, JNIObjectHandle localRef) { JNIObjectHandles.deleteLocalRef(localRef); } @@ -177,8 +177,8 @@ static void DeleteLocalRef(JNIEnvironment env, JNIObjectHandle localRef) { * jint EnsureLocalCapacity(JNIEnv *env, jint capacity); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished) static int EnsureLocalCapacity(JNIEnvironment env, int capacity) { if (capacity < 0) { return JNIErrors.JNI_ERR(); @@ -191,8 +191,8 @@ static int EnsureLocalCapacity(JNIEnvironment env, int capacity) { * jint PushLocalFrame(JNIEnv *env, jint capacity); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished) static int PushLocalFrame(JNIEnvironment env, int capacity) { if (capacity < 0) { return JNIErrors.JNI_ERR(); @@ -205,8 +205,8 @@ static int PushLocalFrame(JNIEnvironment env, int capacity) { * jobject PopLocalFrame(JNIEnv *env, jobject result); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle PopLocalFrame(JNIEnvironment env, JNIObjectHandle handle) { Object obj = JNIObjectHandles.getObject(handle); JNIObjectHandles.popLocalFrame(); @@ -217,8 +217,8 @@ static JNIObjectHandle PopLocalFrame(JNIEnvironment env, JNIObjectHandle handle) * jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnFalse.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnFalse.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static boolean IsSameObject(JNIEnvironment env, JNIObjectHandle ref1, JNIObjectHandle ref2) { Object obj1 = JNIObjectHandles.getObject(ref1); Object obj2 = JNIObjectHandles.getObject(ref2); @@ -229,8 +229,8 @@ static boolean IsSameObject(JNIEnvironment env, JNIObjectHandle ref1, JNIObjectH * jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnFalse.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnFalse.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static boolean IsInstanceOf(JNIEnvironment env, JNIObjectHandle obj, JNIObjectHandle clazz) { Object o = JNIObjectHandles.getObject(obj); if (o == null) { @@ -245,8 +245,8 @@ static boolean IsInstanceOf(JNIEnvironment env, JNIObjectHandle obj, JNIObjectHa * jclass GetObjectClass(JNIEnv *env, jobject obj); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle GetObjectClass(JNIEnvironment env, JNIObjectHandle handle) { Object obj = JNIObjectHandles.getObject(handle); Class clazz = obj.getClass(); @@ -257,8 +257,8 @@ static JNIObjectHandle GetObjectClass(JNIEnvironment env, JNIObjectHandle handle * jclass GetSuperclass(JNIEnv *env, jclass clazz); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle GetSuperclass(JNIEnvironment env, JNIObjectHandle handle) { Class clazz = JNIObjectHandles.getObject(handle); return JNIObjectHandles.createLocal(clazz.getSuperclass()); @@ -268,8 +268,8 @@ static JNIObjectHandle GetSuperclass(JNIEnvironment env, JNIObjectHandle handle) * jboolean IsAssignableFrom(JNIEnv *env, jclass clazz1, jclass clazz2); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnFalse.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnFalse.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static boolean IsAssignableFrom(JNIEnvironment env, JNIObjectHandle handle1, JNIObjectHandle handle2) { Class clazz1 = JNIObjectHandles.getObject(handle1); Class clazz2 = JNIObjectHandles.getObject(handle2); @@ -280,8 +280,8 @@ static boolean IsAssignableFrom(JNIEnvironment env, JNIObjectHandle handle1, JNI * jobject NewGlobalRef(JNIEnv *env, jobject obj); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle NewGlobalRef(JNIEnvironment env, JNIObjectHandle handle) { return JNIObjectHandles.newGlobalRef(handle); } @@ -290,8 +290,8 @@ static JNIObjectHandle NewGlobalRef(JNIEnvironment env, JNIObjectHandle handle) * void DeleteGlobalRef(JNIEnv *env, jobject globalRef); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void DeleteGlobalRef(JNIEnvironment env, JNIObjectHandle globalRef) { JNIObjectHandles.deleteGlobalRef(globalRef); } @@ -300,8 +300,8 @@ static void DeleteGlobalRef(JNIEnvironment env, JNIObjectHandle globalRef) { * jweak NewWeakGlobalRef(JNIEnv *env, jobject obj); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle NewWeakGlobalRef(JNIEnvironment env, JNIObjectHandle handle) { return JNIObjectHandles.newWeakGlobalRef(handle); } @@ -310,8 +310,8 @@ static JNIObjectHandle NewWeakGlobalRef(JNIEnvironment env, JNIObjectHandle hand * void DeleteWeakGlobalRef(JNIEnv *env, jweak obj); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void DeleteWeakGlobalRef(JNIEnvironment env, JNIObjectHandle weak) { JNIObjectHandles.deleteWeakGlobalRef(weak); } @@ -320,8 +320,8 @@ static void DeleteWeakGlobalRef(JNIEnvironment env, JNIObjectHandle weak) { * jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj); */ - @CEntryPoint - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectRefType GetObjectRefType(JNIEnvironment env, JNIObjectHandle handle) { try { return JNIObjectHandles.getHandleType(handle); @@ -334,8 +334,8 @@ static JNIObjectRefType GetObjectRefType(JNIEnvironment env, JNIObjectHandle han * jclass FindClass(JNIEnv *env, const char *name); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle FindClass(JNIEnvironment env, CCharPointer cname) { String name = Utf8.utf8ToString(cname); if (!name.startsWith("[")) { @@ -355,8 +355,8 @@ static JNIObjectHandle FindClass(JNIEnvironment env, CCharPointer cname) { * nMethods); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished) static int RegisterNatives(JNIEnvironment env, JNIObjectHandle hclazz, JNINativeMethod methods, int nmethods) { Class clazz = JNIObjectHandles.getObject(hclazz); Pointer p = (Pointer) methods; @@ -389,8 +389,8 @@ static int RegisterNatives(JNIEnvironment env, JNIObjectHandle hclazz, JNINative * jint UnregisterNatives(JNIEnv *env, jclass clazz); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished) static int UnregisterNatives(JNIEnvironment env, JNIObjectHandle hclazz) { Class clazz = JNIObjectHandles.getObject(hclazz); String internalName = MetaUtil.toInternalName(clazz.getName()); @@ -404,14 +404,14 @@ static int UnregisterNatives(JNIEnvironment env, JNIObjectHandle hclazz) { * jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIMethodId GetMethodID(JNIEnvironment env, JNIObjectHandle hclazz, CCharPointer cname, CCharPointer csig) { return Support.getMethodID(hclazz, cname, csig, false); } - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIMethodId GetStaticMethodID(JNIEnvironment env, JNIObjectHandle hclazz, CCharPointer cname, CCharPointer csig) { return Support.getMethodID(hclazz, cname, csig, true); } @@ -422,14 +422,14 @@ static JNIMethodId GetStaticMethodID(JNIEnvironment env, JNIObjectHandle hclazz, * jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIFieldId GetFieldID(JNIEnvironment env, JNIObjectHandle hclazz, CCharPointer cname, CCharPointer csig) { return Support.getFieldID(hclazz, cname, csig, false); } - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIFieldId GetStaticFieldID(JNIEnvironment env, JNIObjectHandle hclazz, CCharPointer cname, CCharPointer csig) { return Support.getFieldID(hclazz, cname, csig, true); } @@ -438,8 +438,8 @@ static JNIFieldId GetStaticFieldID(JNIEnvironment env, JNIObjectHandle hclazz, C * jobject AllocObject(JNIEnv *env, jclass clazz); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle AllocObject(JNIEnvironment env, JNIObjectHandle classHandle) { Class clazz = JNIObjectHandles.getObject(classHandle); Object instance; @@ -455,8 +455,8 @@ static JNIObjectHandle AllocObject(JNIEnvironment env, JNIObjectHandle classHand * jstring NewString(JNIEnv *env, const jchar *unicodeChars, jsize len); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle NewString(JNIEnvironment env, CShortPointer unicode, int len) { String str; char[] chars = new char[len]; @@ -472,8 +472,8 @@ static JNIObjectHandle NewString(JNIEnvironment env, CShortPointer unicode, int * jstring NewStringUTF(JNIEnv *env, const char *bytes); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle NewStringUTF(JNIEnvironment env, CCharPointer bytes) { return JNIObjectHandles.createLocal(Utf8.utf8ToString(bytes)); } @@ -482,8 +482,8 @@ static JNIObjectHandle NewStringUTF(JNIEnvironment env, CCharPointer bytes) { * jsize GetStringLength(JNIEnv *env, jstring string); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnMinusOne.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnMinusOneOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnMinusOne.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnMinusOneOnFailurePrologue.class, publishAs = Publish.NotPublished) static int GetStringLength(JNIEnvironment env, JNIObjectHandle hstr) { String str = JNIObjectHandles.getObject(hstr); return (str != null) ? str.length() : 0; @@ -493,8 +493,8 @@ static int GetStringLength(JNIEnvironment env, JNIObjectHandle hstr) { * jsize GetStringUTFLength(JNIEnv *env, jstring string); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnMinusOne.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnMinusOneOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnMinusOne.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnMinusOneOnFailurePrologue.class, publishAs = Publish.NotPublished) static int GetStringUTFLength(JNIEnvironment env, JNIObjectHandle hstr) { String str = JNIObjectHandles.getObject(hstr); return Utf8.utf8Length(str); @@ -506,14 +506,14 @@ static int GetStringUTFLength(JNIEnvironment env, JNIObjectHandle hstr) { * void ReleaseStringChars(JNIEnv *env, jstring string, const jchar *chars); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static CShortPointer GetStringChars(JNIEnvironment env, JNIObjectHandle hstr, CCharPointer isCopy) { return Support.getNulTerminatedStringCharsAndPin(hstr, isCopy); } - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void ReleaseStringChars(JNIEnvironment env, JNIObjectHandle hstr, CShortPointer chars) { Support.unpinString(chars); } @@ -524,8 +524,8 @@ static void ReleaseStringChars(JNIEnvironment env, JNIObjectHandle hstr, CShortP * void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static CCharPointer GetStringUTFChars(JNIEnvironment env, JNIObjectHandle hstr, CCharPointer isCopy) { String str = JNIObjectHandles.getObject(hstr); if (str == null) { @@ -538,8 +538,8 @@ static CCharPointer GetStringUTFChars(JNIEnvironment env, JNIObjectHandle hstr, return JNIThreadLocalPinnedObjects.pinArrayAndGetAddress(utf); } - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void ReleaseStringUTFChars(JNIEnvironment env, JNIObjectHandle hstr, CCharPointer chars) { JNIThreadLocalPinnedObjects.unpinArrayByAddress(chars); } @@ -550,14 +550,14 @@ static void ReleaseStringUTFChars(JNIEnvironment env, JNIObjectHandle hstr, CCha * void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *carray); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static CShortPointer GetStringCritical(JNIEnvironment env, JNIObjectHandle hstr, CCharPointer isCopy) { return Support.getNulTerminatedStringCharsAndPin(hstr, isCopy); } - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void ReleaseStringCritical(JNIEnvironment env, JNIObjectHandle hstr, CShortPointer carray) { Support.unpinString(carray); } @@ -566,8 +566,8 @@ static void ReleaseStringCritical(JNIEnvironment env, JNIObjectHandle hstr, CSho * void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void GetStringRegion(JNIEnvironment env, JNIObjectHandle hstr, int start, int len, CShortPointer buf) { String str = JNIObjectHandles.getObject(hstr); if (start < 0) { @@ -589,8 +589,8 @@ static void GetStringRegion(JNIEnvironment env, JNIObjectHandle hstr, int start, * void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, char *buf); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void GetStringUTFRegion(JNIEnvironment env, JNIObjectHandle hstr, int start, int len, CCharPointer buf) { String str = JNIObjectHandles.getObject(hstr); if (start < 0) { @@ -612,8 +612,8 @@ static void GetStringUTFRegion(JNIEnvironment env, JNIObjectHandle hstr, int sta * jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle NewDirectByteBuffer(JNIEnvironment env, WordPointer address, long capacity) { Target_java_nio_DirectByteBuffer bb = new Target_java_nio_DirectByteBuffer(address.rawValue(), (int) capacity); return JNIObjectHandles.createLocal(bb); @@ -628,8 +628,8 @@ static final class Target_java_nio_Buffer { @Alias long address; } - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static WordPointer GetDirectBufferAddress(JNIEnvironment env, JNIObjectHandle handle) { WordPointer address = WordFactory.nullPointer(); Object obj = JNIObjectHandles.getObject(handle); @@ -644,8 +644,8 @@ static WordPointer GetDirectBufferAddress(JNIEnvironment env, JNIObjectHandle ha * jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnMinusOne.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnMinusOneOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnMinusOne.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnMinusOneOnFailurePrologue.class, publishAs = Publish.NotPublished) static long GetDirectBufferCapacity(JNIEnvironment env, JNIObjectHandle hbuf) { Buffer buffer = JNIObjectHandles.getObject(hbuf); return buffer.capacity(); @@ -655,8 +655,8 @@ static long GetDirectBufferCapacity(JNIEnvironment env, JNIObjectHandle hbuf) { * jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject * initialElement); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle NewObjectArray(JNIEnvironment env, int length, JNIObjectHandle hElementClass, JNIObjectHandle hInitialElement) { if (length < 0) { return JNIObjectHandles.nullHandle(); @@ -674,8 +674,8 @@ static JNIObjectHandle NewObjectArray(JNIEnvironment env, int length, JNIObjectH /* * jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle GetObjectArrayElement(JNIEnvironment env, JNIObjectHandle harray, int index) { Object[] array = JNIObjectHandles.getObject(harray); Object value = array[index]; @@ -685,8 +685,8 @@ static JNIObjectHandle GetObjectArrayElement(JNIEnvironment env, JNIObjectHandle /* * void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void SetObjectArrayElement(JNIEnvironment env, JNIObjectHandle harray, int index, JNIObjectHandle hvalue) { Object[] array = JNIObjectHandles.getObject(harray); Object value = JNIObjectHandles.getObject(hvalue); @@ -696,8 +696,8 @@ static void SetObjectArrayElement(JNIEnvironment env, JNIObjectHandle harray, in /* * jvoid * GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static WordPointer GetPrimitiveArrayCritical(JNIEnvironment env, JNIObjectHandle harray, CCharPointer isCopy) { Object array = JNIObjectHandles.getObject(harray); if (array == null) { @@ -712,8 +712,8 @@ static WordPointer GetPrimitiveArrayCritical(JNIEnvironment env, JNIObjectHandle /* * void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void ReleasePrimitiveArrayCritical(JNIEnvironment env, JNIObjectHandle harray, WordPointer carray, int mode) { JNIThreadLocalPinnedObjects.unpinArrayByAddress(carray); } @@ -721,8 +721,8 @@ static void ReleasePrimitiveArrayCritical(JNIEnvironment env, JNIObjectHandle ha /* * jsize GetArrayLength(JNIEnv *env, jarray array); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnMinusOne.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnMinusOneOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnMinusOne.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnMinusOneOnFailurePrologue.class, publishAs = Publish.NotPublished) static int GetArrayLength(JNIEnvironment env, JNIObjectHandle harray) { /* * JNI does not specify the behavior for illegal arguments (e.g. null or non-array objects); @@ -739,14 +739,14 @@ static int GetArrayLength(JNIEnvironment env, JNIObjectHandle harray) { * jthrowable ExceptionOccurred(JNIEnv *env); */ - @CEntryPoint - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static boolean ExceptionCheck(JNIEnvironment env) { return JNIThreadLocalPendingException.get() != null; } - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle ExceptionOccurred(JNIEnvironment env) { return JNIObjectHandles.createLocal(JNIThreadLocalPendingException.get()); } @@ -754,8 +754,8 @@ static JNIObjectHandle ExceptionOccurred(JNIEnvironment env) { /* * void ExceptionClear(JNIEnv *env); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void ExceptionClear(JNIEnvironment env) { JNIThreadLocalPendingException.clear(); } @@ -763,8 +763,8 @@ static void ExceptionClear(JNIEnvironment env) { /* * void ExceptionDescribe(JNIEnv *env); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) static void ExceptionDescribe(JNIEnvironment env) { Throwable t = JNIThreadLocalPendingException.get(); JNIThreadLocalPendingException.clear(); @@ -786,8 +786,8 @@ static void ExceptionDescribe(JNIEnvironment env) { /* * jint Throw(JNIEnv *env, jthrowable obj); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnZero.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnZero.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished) static int Throw(JNIEnvironment env, JNIObjectHandle handle) throws Throwable { throw (Throwable) JNIObjectHandles.getObject(handle); } @@ -800,8 +800,8 @@ interface NewObjectWithObjectArrayArgFunctionPointer extends CFunctionPointer { /* * jint ThrowNew(JNIEnv *env, jclass clazz, const char *message); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnZero.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnZero.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished) static int ThrowNew(JNIEnvironment env, JNIObjectHandle clazzHandle, CCharPointer message) throws Throwable { Class clazz = JNIObjectHandles.getObject(clazzHandle); JNIMethodId ctor = Support.getMethodID(clazz, "", "(Ljava/lang/String;)V", false); @@ -822,8 +822,8 @@ static int ThrowNew(JNIEnvironment env, JNIObjectHandle clazzHandle, CCharPointe /* * void FatalError(JNIEnv *env, const char *msg); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class) - @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) @NeverInline("Access of caller frame.") static void FatalError(JNIEnvironment env, CCharPointer message) { CodePointer callerIP = KnownIntrinsics.readReturnAddress(); @@ -846,8 +846,8 @@ static void FatalError(JNIEnvironment env, CCharPointer message) { /* * jint GetJavaVM(JNIEnv *env, JavaVM **vm); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished) static int GetJavaVM(JNIEnvironment env, JNIJavaVMPointer vm) { vm.write(JNIFunctionTables.singleton().getGlobalJavaVM()); return JNIErrors.JNI_OK(); @@ -856,8 +856,8 @@ static int GetJavaVM(JNIEnvironment env, JNIJavaVMPointer vm) { /* * jfieldID FromReflectedField(JNIEnv *env, jobject field); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIFieldId FromReflectedField(JNIEnvironment env, JNIObjectHandle fieldHandle) { JNIFieldId fieldId = WordFactory.zero(); Field obj = JNIObjectHandles.getObject(fieldHandle); @@ -871,8 +871,8 @@ static JNIFieldId FromReflectedField(JNIEnvironment env, JNIObjectHandle fieldHa /* * jobject ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle ToReflectedField(JNIEnvironment env, JNIObjectHandle classHandle, JNIFieldId fieldId) { Field field = null; Class clazz = JNIObjectHandles.getObject(classHandle); @@ -892,8 +892,8 @@ static JNIObjectHandle ToReflectedField(JNIEnvironment env, JNIObjectHandle clas /* * jmethodID FromReflectedMethod(JNIEnv *env, jobject method); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullWord.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullWordOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIMethodId FromReflectedMethod(JNIEnvironment env, JNIObjectHandle methodHandle) { JNIMethodId methodId = WordFactory.nullPointer(); Executable method = JNIObjectHandles.getObject(methodHandle); @@ -908,8 +908,8 @@ static JNIMethodId FromReflectedMethod(JNIEnvironment env, JNIObjectHandle metho /* * jobject ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnNullHandle.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnNullHandleOnFailurePrologue.class, publishAs = Publish.NotPublished) static JNIObjectHandle ToReflectedMethod(JNIEnvironment env, JNIObjectHandle classHandle, JNIMethodId methodId, boolean isStatic) { Executable result = null; JNIAccessibleMethod jniMethod = JNIReflectionDictionary.getMethodByID(methodId); @@ -940,8 +940,8 @@ static JNIObjectHandle ToReflectedMethod(JNIEnvironment env, JNIObjectHandle cla /* * jint MonitorEnter(JNIEnv *env, jobject obj); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished) static int MonitorEnter(JNIEnvironment env, JNIObjectHandle handle) { Object obj = JNIObjectHandles.getObject(handle); if (obj == null) { @@ -956,8 +956,8 @@ static int MonitorEnter(JNIEnvironment env, JNIObjectHandle handle) { /* * jint MonitorExit(JNIEnv *env, jobject obj); */ - @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class) - @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(exceptionHandler = JNIExceptionHandlerReturnJniErr.class, include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvEnterReturnEDetachedOnFailurePrologue.class, publishAs = Publish.NotPublished) static int MonitorExit(JNIEnvironment env, JNIObjectHandle handle) { Object obj = JNIObjectHandles.getObject(handle); if (obj == null) { @@ -1179,8 +1179,8 @@ static class UnimplementedWithJNIEnvArgument { /** * Stub for unimplemented JNI functionality with a JNIEnv argument. */ - @CEntryPoint - @CEntryPointOptions(prologue = JNIEnvUnimplementedPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIEnvUnimplementedPrologue.class, publishAs = Publish.NotPublished) static int unimplemented(JNIEnvironment env) { /* * We do not catch and preserve this exception like we normally would with JNI because @@ -1206,8 +1206,8 @@ static class UnimplementedWithJavaVMArgument { /** * Stub for unimplemented JNI functionality with a JavaVM argument. */ - @CEntryPoint - @CEntryPointOptions(prologue = JNIJavaVMUnimplementedPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIJavaVMUnimplementedPrologue.class, publishAs = Publish.NotPublished) static int unimplemented(JNIJavaVM vm) { throw VMError.shouldNotReachHere("An unimplemented JNI function was called. Please refer to the stack trace."); } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIInvocationInterface.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIInvocationInterface.java index a12e7892a2f4..6b4e969b7354 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIInvocationInterface.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIInvocationInterface.java @@ -93,8 +93,8 @@ static class Exports { * jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs); */ - @CEntryPoint(name = "JNI_GetCreatedJavaVMs") - @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(name = "JNI_GetCreatedJavaVMs", include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) @Uninterruptible(reason = "No Java context.") static int JNI_GetCreatedJavaVMs(JNIJavaVMPointer vmBuf, int bufLen, CIntPointer nVMs) { JNIJavaVMList.gather(vmBuf, bufLen, nVMs); @@ -160,8 +160,8 @@ static void enter(JNIJavaVMPointer vmBuf, JNIEnvironmentPointer penv, JNIJavaVMI * @see LogHandler * @see "https://docs.oracle.com/en/java/javase/14/docs/specs/jni/invocation.html#jni_createjavavm" */ - @CEntryPoint(name = "JNI_CreateJavaVM") - @CEntryPointOptions(prologue = JNICreateJavaVMPrologue.class, publishAs = Publish.SymbolOnly, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(name = "JNI_CreateJavaVM", include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNICreateJavaVMPrologue.class, publishAs = Publish.SymbolOnly) static int JNI_CreateJavaVM(JNIJavaVMPointer vmBuf, JNIEnvironmentPointer penv, JNIJavaVMInitArgs vmArgs) { // NOTE: could check version, extra options (-verbose etc.), hooks etc. WordPointer javavmIdPointer = WordFactory.nullPointer(); @@ -206,8 +206,8 @@ public void run() { /* * jint JNI_GetDefaultJavaVMInitArgs(void *vm_args); */ - @CEntryPoint(name = "JNI_GetDefaultJavaVMInitArgs") - @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(name = "JNI_GetDefaultJavaVMInitArgs", include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) @Uninterruptible(reason = "No Java context") static int JNI_GetDefaultJavaVMInitArgs(JNIJavaVMInitArgs vmArgs) { int version = vmArgs.getVersion(); @@ -224,8 +224,8 @@ static int JNI_GetDefaultJavaVMInitArgs(JNIJavaVMInitArgs vmArgs) { /* * jint AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args); */ - @CEntryPoint - @CEntryPointOptions(prologue = JNIJavaVMEnterAttachThreadManualJavaThreadPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIJavaVMEnterAttachThreadManualJavaThreadPrologue.class, publishAs = Publish.NotPublished) static int AttachCurrentThread(JNIJavaVM vm, JNIEnvironmentPointer penv, JNIJavaVMAttachArgs args) { return Support.attachCurrentThread(vm, penv, args, false); } @@ -233,8 +233,8 @@ static int AttachCurrentThread(JNIJavaVM vm, JNIEnvironmentPointer penv, JNIJava /* * jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **p_env, void *thr_args); */ - @CEntryPoint - @CEntryPointOptions(prologue = JNIJavaVMEnterAttachThreadManualJavaThreadPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIJavaVMEnterAttachThreadManualJavaThreadPrologue.class, publishAs = Publish.NotPublished) static int AttachCurrentThreadAsDaemon(JNIJavaVM vm, JNIEnvironmentPointer penv, JNIJavaVMAttachArgs args) { return Support.attachCurrentThread(vm, penv, args, true); } @@ -242,8 +242,8 @@ static int AttachCurrentThreadAsDaemon(JNIJavaVM vm, JNIEnvironmentPointer penv, /* * jint DetachCurrentThread(JavaVM *vm); */ - @CEntryPoint - @CEntryPointOptions(prologue = JNIJavaVMEnterAttachThreadEnsureJavaThreadPrologue.class, epilogue = LeaveDetachThreadEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIJavaVMEnterAttachThreadEnsureJavaThreadPrologue.class, epilogue = LeaveDetachThreadEpilogue.class, publishAs = Publish.NotPublished) static int DetachCurrentThread(JNIJavaVM vm) { int result = JNIErrors.JNI_OK(); if (!vm.equal(JNIFunctionTables.singleton().getGlobalJavaVM())) { @@ -257,8 +257,8 @@ static int DetachCurrentThread(JNIJavaVM vm) { /* * jint DestroyJavaVM(JavaVM *vm); */ - @CEntryPoint - @CEntryPointOptions(prologue = JNIJavaVMEnterAttachThreadEnsureJavaThreadPrologue.class, epilogue = LeaveTearDownIsolateEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIJavaVMEnterAttachThreadEnsureJavaThreadPrologue.class, epilogue = LeaveTearDownIsolateEpilogue.class, publishAs = Publish.NotPublished) @SuppressWarnings("unused") static int DestroyJavaVM(JNIJavaVM vm) { JavaThreads.singleton().joinAllNonDaemons(); @@ -268,8 +268,8 @@ static int DestroyJavaVM(JNIJavaVM vm) { /* * jint GetEnv(JavaVM *vm, void **env, jint version); */ - @CEntryPoint - @CEntryPointOptions(prologue = JNIGetEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = JNIGetEnvPrologue.class, publishAs = Publish.NotPublished) @SuppressWarnings("unused") static int GetEnv(JNIJavaVM vm, WordPointer env, int version) { env.write(JNIThreadLocalEnvironment.getAddress()); diff --git a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeAPIImpl.java b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeAPIImpl.java index e428be3604ee..9ec0934e8dde 100644 --- a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeAPIImpl.java +++ b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeAPIImpl.java @@ -75,28 +75,28 @@ private static Target_com_oracle_truffle_nfi_backend_libffi_LibFFIContext lookup return support.resolveContextHandle(context.contextHandle()); } - @CEntryPoint - @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished) static NativeTruffleContext getTruffleContext(NativeTruffleEnv env) { return env.context(); } - @CEntryPoint - @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished) static TruffleObjectHandle newObjectRef(@SuppressWarnings("unused") NativeTruffleEnv env, TruffleObjectHandle handle) { TruffleNFISupport support = ImageSingletons.lookup(TruffleNFISupport.class); Object object = support.resolveHandle(handle); return support.createGlobalHandle(object); } - @CEntryPoint - @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished) static void releaseObjectRef(@SuppressWarnings("unused") NativeTruffleEnv env, TruffleObjectHandle handle) { ImageSingletons.lookup(TruffleNFISupport.class).destroyGlobalHandle(handle); } - @CEntryPoint - @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished) static TruffleObjectHandle releaseAndReturn(@SuppressWarnings("unused") NativeTruffleEnv env, TruffleObjectHandle handle) { TruffleNFISupport support = ImageSingletons.lookup(TruffleNFISupport.class); Object object = support.resolveHandle(handle); @@ -104,8 +104,8 @@ static TruffleObjectHandle releaseAndReturn(@SuppressWarnings("unused") NativeTr return TruffleNFISupport.createLocalHandle(object); } - @CEntryPoint - @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished) static int isSameObject(@SuppressWarnings("unused") NativeTruffleEnv env, TruffleObjectHandle handle1, TruffleObjectHandle handle2) { TruffleNFISupport support = ImageSingletons.lookup(TruffleNFISupport.class); Object object1 = support.resolveHandle(handle1); @@ -113,22 +113,22 @@ static int isSameObject(@SuppressWarnings("unused") NativeTruffleEnv env, Truffl return object1 == object2 ? 1 : 0; } - @CEntryPoint - @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished) static void newClosureRef(NativeTruffleEnv env, PointerBase closure) { Target_com_oracle_truffle_nfi_backend_libffi_LibFFIContext context = lookupContext(env.context()); context.newClosureRef(closure.rawValue()); } - @CEntryPoint - @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished) static void releaseClosureRef(NativeTruffleEnv env, PointerBase closure) { Target_com_oracle_truffle_nfi_backend_libffi_LibFFIContext context = lookupContext(env.context()); context.releaseClosureRef(closure.rawValue()); } - @CEntryPoint - @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterNativeTruffleEnvPrologue.class, publishAs = Publish.NotPublished) static TruffleObjectHandle getClosureObject(NativeTruffleEnv env, PointerBase closure) { TruffleNFISupport support = ImageSingletons.lookup(TruffleNFISupport.class); Target_com_oracle_truffle_nfi_backend_libffi_LibFFIContext context = lookupContext(env.context()); @@ -136,8 +136,8 @@ static TruffleObjectHandle getClosureObject(NativeTruffleEnv env, PointerBase cl return support.createGlobalHandle(ret); } - @CEntryPoint - @CEntryPointOptions(prologue = GetTruffleEnvPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = GetTruffleEnvPrologue.class, publishAs = Publish.NotPublished) static NativeTruffleEnv getTruffleEnv(NativeTruffleContext context) { TruffleNFISupport support = ImageSingletons.lookup(TruffleNFISupport.class); Target_com_oracle_truffle_nfi_backend_libffi_LibFFIContext ctx = support.resolveContextHandle(context.contextHandle()); @@ -152,8 +152,8 @@ static void enter(NativeTruffleContext context) { } } - @CEntryPoint - @CEntryPointOptions(prologue = AttachCurrentThreadPrologue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = AttachCurrentThreadPrologue.class, publishAs = Publish.NotPublished) static NativeTruffleEnv attachCurrentThread(NativeTruffleContext context) { TruffleNFISupport support = ImageSingletons.lookup(TruffleNFISupport.class); Target_com_oracle_truffle_nfi_backend_libffi_LibFFIContext ctx = support.resolveContextHandle(context.contextHandle()); @@ -172,8 +172,8 @@ static void enter(NativeTruffleContext context) { } } - @CEntryPoint - @CEntryPointOptions(prologue = EnterNativeTruffleContextPrologue.class, epilogue = LeaveDetachThreadEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = EnterNativeTruffleContextPrologue.class, epilogue = LeaveDetachThreadEpilogue.class, publishAs = Publish.NotPublished) static void detachCurrentThread(@SuppressWarnings("unused") NativeTruffleContext context) { TruffleNFISupport support = ImageSingletons.lookup(TruffleNFISupport.class); Target_com_oracle_truffle_nfi_backend_libffi_LibFFIContext ctx = support.resolveContextHandle(context.contextHandle()); diff --git a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeClosure.java b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeClosure.java index ddba7e7517f8..3b07efe23f00 100644 --- a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeClosure.java +++ b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeClosure.java @@ -186,8 +186,8 @@ private static PointerBase serializeStringRet(Object retValue) { static final FastThreadLocalObject pendingException = FastThreadLocalFactory.createObject(Throwable.class); - @CEntryPoint - @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished) @Uninterruptible(reason = "contains prologue and epilogue for thread state transition", calleeMustBe = false) static void invokeClosureBufferRet(@SuppressWarnings("unused") ffi_cif cif, Pointer ret, WordPointer args, ClosureData user) { /* Read the C error number before transitioning into the Java state. */ @@ -238,8 +238,8 @@ private static void doInvokeClosureBufferRet(Pointer ret, WordPointer args, Clos } } - @CEntryPoint - @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished) @Uninterruptible(reason = "contains prologue and epilogue for thread state transition", calleeMustBe = false) static void invokeClosureVoidRet(@SuppressWarnings("unused") ffi_cif cif, @SuppressWarnings("unused") WordPointer ret, WordPointer args, ClosureData user) { /* Read the C error number before transitioning into the Java state. */ @@ -271,8 +271,8 @@ private static void doInvokeClosureVoidRet(WordPointer args, ClosureData user) { lookup(user).call(args, null); } - @CEntryPoint - @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished) @Uninterruptible(reason = "contains prologue and epilogue for thread state transition", calleeMustBe = false) static void invokeClosureStringRet(@SuppressWarnings("unused") ffi_cif cif, WordPointer ret, WordPointer args, ClosureData user) { /* Read the C error number before transitioning into the Java state. */ @@ -305,8 +305,8 @@ private static void doInvokeClosureStringRet(WordPointer ret, WordPointer args, ret.write(serializeStringRet(retValue)); } - @CEntryPoint - @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished, include = CEntryPointOptions.NotIncludedAutomatically.class) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished) @Uninterruptible(reason = "contains prologue and epilogue for thread state transition", calleeMustBe = false) static void invokeClosureObjectRet(@SuppressWarnings("unused") ffi_cif cif, WordPointer ret, WordPointer args, ClosureData user) { /* Read the C error number before transitioning into the Java state. */ diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolateAwareTruffleCompiler.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolateAwareTruffleCompiler.java index 3f6e10a56ea4..a55709a476ff 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolateAwareTruffleCompiler.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolateAwareTruffleCompiler.java @@ -168,8 +168,8 @@ private void sharedIsolateShutdown() { Isolates.detachThread(context); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) protected static void compilerIsolateThreadShutdown(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext CompilerIsolateThread context) { VMRuntime.shutdown(); } @@ -179,8 +179,8 @@ protected void afterCompilation(CompilerIsolateThread context) { Isolates.detachThread(context); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle doCompile0(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext CompilerIsolateThread context, ClientIsolateThread client, ImageHeapRef delegateRef, @@ -232,8 +232,8 @@ private static Map decodeOptions(ClientIsolateThread client, Cli return OptionsEncoder.decode(encodedOptions); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void copyEncodedOptions(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext ClientIsolateThread client, ClientHandle encodedOptionsHandle, PointerBase buffer) { byte[] encodedOptions = IsolatedCompileClient.get().unhand(encodedOptionsHandle); CTypeConversion.asByteBuffer(buffer, encodedOptions.length).put(encodedOptions); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedCompilableTruffleAST.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedCompilableTruffleAST.java index 1e7fdbc4a6d0..0f0a8fe1abd1 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedCompilableTruffleAST.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedCompilableTruffleAST.java @@ -153,16 +153,16 @@ public boolean isTrivial() { return isTrivial0(IsolatedCompileContext.get().getClient(), handle); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle getCompilationSpeculationLog0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilableHandle) { SubstrateCompilableTruffleAST compilable = IsolatedCompileClient.get().unhand(compilableHandle); SpeculationLog log = compilable.getCompilationSpeculationLog(); return IsolatedCompileClient.get().hand(log); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void onCompilationFailed0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilableHandle, CompilerHandle> serializedExceptionHandle, boolean silent, boolean bailout, boolean permanentBailout, boolean graphTooBig) { @@ -173,30 +173,30 @@ private static void onCompilationFailed0(@SuppressWarnings("unused") ClientIsola IsolatedCompileClient.get().unhand(compilableHandle).onCompilationFailed(serializedException, silent, bailout, permanentBailout, graphTooBig); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle getReasonAndStackTrace0(@SuppressWarnings("unused") CompilerIsolateThread compiler, CompilerHandle> reasonAndStackTraceHandle) { Supplier supplier = IsolatedCompileContext.get().unhand(reasonAndStackTraceHandle); return IsolatedCompileContext.get().createStringInClient(supplier.get()); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle getName0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilableHandle) { String name = IsolatedCompileClient.get().unhand(compilableHandle).getName(); return IsolatedCompileClient.get().createStringInCompiler(name); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static int getNonTrivialNodeCount0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilableHandle) { SubstrateCompilableTruffleAST compilable = IsolatedCompileClient.get().unhand(compilableHandle); return compilable.getNonTrivialNodeCount(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle getCallNodes0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilableHandle) { SubstrateCompilableTruffleAST compilable = IsolatedCompileClient.get().unhand(compilableHandle); TruffleCallNode[] nodes = compilable.getCallNodes(); @@ -209,8 +209,8 @@ private static CompilerHandle getCallNodes0(@Suppress } } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle getCallNodes1(@SuppressWarnings("unused") CompilerIsolateThread compiler, WordPointer nodeHandleArray, int length) { IsolatedTruffleCallNode[] nodes = new IsolatedTruffleCallNode[length]; @@ -221,15 +221,15 @@ private static CompilerHandle getCallNodes1(@Suppress return IsolatedCompileContext.get().hand(nodes); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static int getCallCount0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilableHandle) { SubstrateCompilableTruffleAST compilable = IsolatedCompileClient.get().unhand(compilableHandle); return compilable.getCallCount(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean cancelCompilation0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilableHandle, ClientHandle reasonHandle) { final IsolatedCompileClient isolatedCompileClient = IsolatedCompileClient.get(); final SubstrateCompilableTruffleAST compilable = isolatedCompileClient.unhand(compilableHandle); @@ -237,16 +237,16 @@ private static boolean cancelCompilation0(@SuppressWarnings("unused") ClientIsol return compilable.cancelCompilation(reason); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void dequeueInlined0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle handle) { final IsolatedCompileClient isolatedCompileClient = IsolatedCompileClient.get(); final SubstrateCompilableTruffleAST compilable = isolatedCompileClient.unhand(handle); compilable.dequeueInlined(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean isSameOrSplit0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilableHandle, ClientHandle otherHandle) { @@ -255,15 +255,15 @@ private static boolean isSameOrSplit0(@SuppressWarnings("unused") ClientIsolateT return compilable.isSameOrSplit(other); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static int getKnownCallSiteCount0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilableHandle) { SubstrateCompilableTruffleAST compilable = IsolatedCompileClient.get().unhand(compilableHandle); return compilable.getKnownCallSiteCount(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle getNodeRewritingAssumption0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle handle) { CompilableTruffleAST ast = IsolatedCompileClient.get().unhand(handle); JavaConstant assumptionConstant = ast.getNodeRewritingAssumptionConstant(); @@ -271,8 +271,8 @@ private static ClientHandle getNodeRewritingAssumption0(@SuppressWar return IsolatedCompileClient.get().hand(assumption); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle getValidRootAssumption0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle handle) { CompilableTruffleAST ast = IsolatedCompileClient.get().unhand(handle); JavaConstant assumptionConstant = ast.getValidRootAssumptionConstant(); @@ -280,8 +280,8 @@ private static ClientHandle getValidRootAssumption0(@SuppressWarning return IsolatedCompileClient.get().hand(assumption); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean isTrivial0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle handle) { SubstrateCompilableTruffleAST compilable = IsolatedCompileClient.get().unhand(handle); return compilable.isTrivial(); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedCompilationIdentifier.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedCompilationIdentifier.java index 74efce924e50..b09c3d070678 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedCompilationIdentifier.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedCompilationIdentifier.java @@ -72,14 +72,14 @@ public String toString(Verbosity verbosity) { return descriptions[ordinal]; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void close0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle compilationHandle) { IsolatedCompileClient.get().unhand(compilationHandle).close(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle toString0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle idHandle, int verbosityOrdinal) { TruffleCompilationIdentifier id = IsolatedCompileClient.get().unhand(idHandle); String description = id.toString(VERBOSITIES[verbosityOrdinal]); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCallNode.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCallNode.java index 084c59838fd7..dab534d82fe8 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCallNode.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCallNode.java @@ -57,23 +57,23 @@ public boolean isInliningForced() { return isInliningForced0(IsolatedCompileContext.get().getClient(), handle); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle getCurrentCallTarget0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle nodeHandle) { TruffleCallNode node = IsolatedCompileClient.get().unhand(nodeHandle); CompilableTruffleAST target = node.getCurrentCallTarget(); return IsolatedCompileClient.get().hand((SubstrateCompilableTruffleAST) target); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static int getCallCount0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle nodeHandle) { TruffleCallNode node = IsolatedCompileClient.get().unhand(nodeHandle); return node.getCallCount(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean isInliningForced0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle nodeHandle) { TruffleCallNode node = IsolatedCompileClient.get().unhand(nodeHandle); return node.isInliningForced(); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilationTask.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilationTask.java index d4e3422b2622..d39687089e1d 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilationTask.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilationTask.java @@ -67,32 +67,32 @@ public boolean hasNextTier() { return hasNextTier0(IsolatedCompileContext.get().getClient(), handle); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean isCancelled0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle taskHandle) { return IsolatedCompileClient.get().unhand(taskHandle).isCancelled(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean isLastTier0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle taskHandle) { return IsolatedCompileClient.get().unhand(taskHandle).isLastTier(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean isFirstTier0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle taskHandle) { return IsolatedCompileClient.get().unhand(taskHandle).isFirstTier(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean hasNextTier0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle taskHandle) { return IsolatedCompileClient.get().unhand(taskHandle).hasNextTier(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle inliningData0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle taskHandle) { TruffleInliningData inliningData = IsolatedCompileClient.get().unhand(taskHandle).inliningData(); return IsolatedCompileClient.get().hand(inliningData); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java index 5e015ce40697..ad5e1e046153 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java @@ -89,24 +89,24 @@ public void onCompilationRetry(CompilableTruffleAST compilable, int tier) { onCompilationRetry0(IsolatedCompileContext.get().getClient(), contextHandle, tier); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void onGraalTierFinished0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle contextHandle, CompilerHandle graphInfo, int nodeCount) { IsolatedEventContext context = IsolatedCompileClient.get().unhand(contextHandle); context.listener.onGraalTierFinished(context.compilable, new IsolatedGraphInfo(graphInfo, nodeCount)); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void onTruffleTierFinished0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle contextHandle, CompilerHandle graphInfo, int nodeCount) { IsolatedEventContext context = IsolatedCompileClient.get().unhand(contextHandle); context.listener.onTruffleTierFinished(context.compilable, context.task.inliningData(), new IsolatedGraphInfo(graphInfo, nodeCount)); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void onSuccess0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle contextHandle, CompilerHandle graphInfo, int nodeCount, IsolatedCompilationResultData resultData, int tier) { @@ -114,16 +114,16 @@ private static void onSuccess0(@SuppressWarnings("unused") ClientIsolateThread c context.listener.onSuccess(context.compilable, context.task.inliningData(), new IsolatedGraphInfo(graphInfo, nodeCount), new IsolatedCompilationResultInfo(resultData), tier); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void onFailure0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle contextHandle, CCharPointer reason, boolean bailout, boolean permanentBailout, int tier) { IsolatedEventContext context = IsolatedCompileClient.get().unhand(contextHandle); context.listener.onFailure(context.compilable, CTypeConversion.toJavaString(reason), bailout, permanentBailout, tier); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void onCompilationRetry0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle contextHandle, int tier) { IsolatedEventContext context = IsolatedCompileClient.get().unhand(contextHandle); context.listener.onCompilationRetry(context.compilable, tier); @@ -163,8 +163,8 @@ public String[] getNodeTypes(boolean simpleNames) { return IsolatedCompileClient.get().unhand(handle); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle getNodeTypes0(@SuppressWarnings("unused") CompilerIsolateThread compiler, CompilerHandle infoHandle, boolean simpleNames) { GraphInfo info = IsolatedCompileContext.get().unhand(infoHandle); return IsolatedCompileContext.get().createStringArrayInClient(info.getNodeTypes(simpleNames)); @@ -226,8 +226,8 @@ public int getDataPatchesCount() { return dataPatchesCount; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle getInfopoints0(@SuppressWarnings("unused") CompilerIsolateThread compiler, CompilerHandle infoHandle) { CompilationResultInfo info = IsolatedCompileContext.get().unhand(infoHandle); return IsolatedCompileContext.get().createStringArrayInClient(info.getInfopoints()); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleInlining.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleInlining.java index d96b0c1cce89..5496a7ef5c49 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleInlining.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleInlining.java @@ -94,8 +94,8 @@ public void addInlinedTarget(CompilableTruffleAST target) { addInlinedTarget0(IsolatedCompileContext.get().getClient(), handle, targetHandle); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle findCallNode0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle inliningHandle, ClientHandle callNodeConstantHandle) { @@ -105,8 +105,8 @@ private static ClientHandle findCallNode0(@SuppressWarnings("un return IsolatedCompileClient.get().hand(callNode); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle getPosition0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle inliningHandle, ClientHandle callNodeConstantHandle) { @@ -120,8 +120,8 @@ private static CompilerHandle getPosition0(@Suppr position.getLineNumber(), position.getOffsetStart(), position.getOffsetEnd(), position.getNodeId()); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void addTargetToDequeue0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle providerHandle, ClientHandle targetHandle) { @@ -130,8 +130,8 @@ private static void addTargetToDequeue0(@SuppressWarnings("unused") ClientIsolat truffleInliningData.addTargetToDequeue(isolatedCompileClient.unhand(targetHandle)); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void addInlinedTarget0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle providerHandle, ClientHandle targetHandle) { @@ -140,31 +140,31 @@ private static void addInlinedTarget0(@SuppressWarnings("unused") ClientIsolateT truffleInliningData.addInlinedTarget(isolatedCompileClient.unhand(targetHandle)); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void setCallCount0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle handle, int count) { TruffleInliningData truffleInliningData = IsolatedCompileClient.get().unhand(handle); truffleInliningData.setCallCount(count); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void setInlinedCallCount0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle handle, int count) { TruffleInliningData truffleInliningData = IsolatedCompileClient.get().unhand(handle); truffleInliningData.setInlinedCallCount(count); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static int countInlinedCalls0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle handle) { TruffleInliningData truffleInliningData = IsolatedCompileClient.get().unhand(handle); return truffleInliningData.countInlinedCalls(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle createPositionInCompiler(@SuppressWarnings("unused") CompilerIsolateThread compiler, ClientHandle positionHandle, int lineNumber, int offsetStart, int offsetEnd, int nodeId) { diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleRuntimeSupport.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleRuntimeSupport.java index f8312145b6c5..a9cc201b2feb 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleRuntimeSupport.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleRuntimeSupport.java @@ -72,8 +72,8 @@ public static Consumer registerOptimizedAssumptio }; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle> registerOptimizedAssumptionDependency0( @SuppressWarnings("unused") ClientIsolateThread client, ClientHandle assumptionHandle) { @@ -82,8 +82,8 @@ private static ClientHandle> registerOpt return IsolatedCompileClient.get().hand(observer); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void notifyAssumption0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle> consumerHandle, ClientHandle dependencyHandle) { @@ -101,8 +101,8 @@ public static JavaConstant getCallTargetForCallNode(JavaConstant callNodeConstan return new IsolatedObjectConstant(getCallTargetForCallNode0(IsolatedCompileContext.get().getClient(), callNodeHandle), false); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle getCallTargetForCallNode0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle callNode) { OptimizedDirectCallNode node = IsolatedCompileClient.get().unhand(callNode); @@ -127,8 +127,8 @@ public static boolean tryLog(String loggerId, CompilableTruffleAST compilable, S return false; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static void log0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle id, ClientHandle ast, ClientHandle msg) { SubstrateTruffleRuntime runtime = (SubstrateTruffleRuntime) SubstrateTruffleRuntime.getRuntime(); @@ -146,8 +146,8 @@ public static TriState tryIsSuppressedFailure(CompilableTruffleAST compilable, S return TriState.UNDEFINED; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static boolean isSuppressedFailure0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle ast, CompilerHandle> serializedExceptionHandle) { Supplier serializedException = () -> { @@ -158,8 +158,8 @@ private static boolean isSuppressedFailure0(@SuppressWarnings("unused") ClientIs return runtime.isSuppressedFailure(IsolatedCompileClient.get().unhand(ast), serializedException); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static ClientHandle getReasonAndStackTrace0(@SuppressWarnings("unused") CompilerIsolateThread compiler, CompilerHandle> reasonAndStackTraceHandle) { Supplier supplier = IsolatedCompileContext.get().unhand(reasonAndStackTraceHandle); return IsolatedCompileContext.get().createStringInClient(supplier.get()); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleSourceLanguagePosition.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleSourceLanguagePosition.java index 367a6b6f63d2..26e98898cbfc 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleSourceLanguagePosition.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleSourceLanguagePosition.java @@ -103,29 +103,29 @@ public int getNodeId() { return nodeId; } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle getDescription0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle positionHandle) { String description = IsolatedCompileClient.get().unhand(positionHandle).getDescription(); return IsolatedCompileClient.get().createStringInCompiler(description); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle getURIString0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle positionHandle) { URI uri = IsolatedCompileClient.get().unhand(positionHandle).getURI(); return (uri != null) ? IsolatedCompileClient.get().createStringInCompiler(uri.toString()) : IsolatedHandles.nullHandle(); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle getLanguage0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle positionHandle) { String language = IsolatedCompileClient.get().unhand(positionHandle).getLanguage(); return IsolatedCompileClient.get().createStringInCompiler(language); } - @CEntryPoint - @CEntryPointOptions(include = CEntryPointOptions.NotIncludedAutomatically.class, publishAs = CEntryPointOptions.Publish.NotPublished) + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) + @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) private static CompilerHandle getNodeClassName0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle positionHandle) { String language = IsolatedCompileClient.get().unhand(positionHandle).getNodeClassName(); return IsolatedCompileClient.get().createStringInCompiler(language); From 71526f374a70481442d0f4c26e654a94af0423c4 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Wed, 22 Sep 2021 20:53:29 +0200 Subject: [PATCH 091/681] Fix static guards cannot be asserted in fallback guard, they always need to be executed. --- .../truffle/api/dsl/test/FallbackTest.java | 41 +++++++++++++++++++ .../generator/FlatNodeGenFactory.java | 4 +- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java index ee1b846ce816..b758ce2bb5ff 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java @@ -44,6 +44,7 @@ import static com.oracle.truffle.api.dsl.test.TestHelper.assertRuns; import static com.oracle.truffle.api.dsl.test.TestHelper.createRoot; import static com.oracle.truffle.api.dsl.test.TestHelper.executeWith; +import static org.junit.Assert.assertEquals; import org.junit.Assert; import org.junit.Test; @@ -76,6 +77,7 @@ import com.oracle.truffle.api.dsl.test.FallbackTestFactory.FallbackWithAssumptionNodeGen; import com.oracle.truffle.api.dsl.test.FallbackTestFactory.FallbackWithCachedNodeGen; import com.oracle.truffle.api.dsl.test.FallbackTestFactory.ImplicitCastInFallbackNodeGen; +import com.oracle.truffle.api.dsl.test.FallbackTestFactory.InvertedGuardNodeGen; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.dsl.test.examples.ExampleTypes; @@ -770,4 +772,43 @@ protected String f0(Object arg0, } + /* + * Test for GR-33857. + */ + @Test + public void testInvertedStaticGuard() { + setupEnv(); + InvertedGuardNode node; + + node = adoptNode(InvertedGuardNodeGen.create()).get(); + + assertEquals("f", node.execute(42L)); + assertEquals("f", node.execute(42L)); + } + + @SuppressWarnings("unused") + abstract static class InvertedGuardNode extends Node { + + public abstract String execute(Object left); + + @Specialization(guards = {"dynamicGuard(arg0)", "staticGuard()"}) + protected String s0(long arg0) { + return "s0"; + } + + static boolean staticGuard() { + return false; + } + + static boolean dynamicGuard(long arg0) { + return arg0 == 42; + } + + @Fallback + protected String f(Object arg0) { + return "f"; + } + + } + } diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java index fe5f87eaac2d..1dcd40c130b7 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java @@ -5038,12 +5038,12 @@ private IfTriple createMethodGuardCheck(FrameState frameState, SpecializationDat } CodeTree assertion = null; // overrule with assertion - if (mode.isFastPath() || mode.isGuardFallback()) { + if (mode.isFastPath()) { if (!specialization.isDynamicParameterBound(expression, true) && !guard.isWeakReferenceGuard()) { assertion = CodeTreeBuilder.createBuilder().startAssert().tree(expressionCode).end().build(); expressionCode = null; } - } else { + } else if (mode.isSlowPath() || mode.isUncached()) { if (guard.isConstantTrueInSlowPath(context, mode.isUncached())) { assertion = CodeTreeBuilder.createBuilder().startStatement().string("// assert ").tree(expressionCode).end().build(); expressionCode = null; From fddc9c8ab2cc1eda36d1c1f4646eab03a1de7596 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Wed, 22 Sep 2021 18:02:11 -0400 Subject: [PATCH 092/681] TRegex: Update assertion to allow usage of ASCII encoding. --- .../oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java index 4452e0fd89c8..240d3d0871ae 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java @@ -261,7 +261,7 @@ protected void inputSkipIntl(TRegexExecutorLocals locals, boolean forward) { } while (inputHasNext(locals, false) && inputUTF8IsTrailingByte(c)); } } else { - assert getEncoding() == Encodings.UTF_16_RAW || getEncoding() == Encodings.UTF_32 || getEncoding() == Encodings.LATIN_1; + assert getEncoding() == Encodings.UTF_16_RAW || getEncoding() == Encodings.UTF_32 || getEncoding() == Encodings.LATIN_1 || getEncoding() == Encodings.ASCII; inputIncRaw(locals, forward); } } From b24fd0b3c3228f04b0d24b2211e167445d4f2cbd Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 22 Sep 2021 08:27:29 +0200 Subject: [PATCH 093/681] compiler: make getKilledLocationIdentity and hasSideEffect of MacroNode final --- .../org/graalvm/compiler/replacements/nodes/MacroNode.java | 4 ++-- .../compiler/replacements/nodes/MacroWithExceptionNode.java | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java index 500aa02e314a..3f057960e741 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java @@ -169,7 +169,7 @@ public void setStateAfter(FrameState x) { } @Override - public boolean hasSideEffect() { + public final boolean hasSideEffect() { return true; } @@ -180,7 +180,7 @@ public boolean hasSideEffect() { * kill location must not get broader. */ @Override - public LocationIdentity getKilledLocationIdentity() { + public final LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java index 158fc20bf7f3..2b0b9dccb2ac 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java @@ -169,12 +169,14 @@ public void setStateAfter(FrameState x) { } @Override - public boolean hasSideEffect() { + public final boolean hasSideEffect() { return true; } /** * @see MacroNode#getKilledLocationIdentity() + * + * FIXME: make this final once [GR-32638] is fixed */ @Override public LocationIdentity getKilledLocationIdentity() { From 2da5878b8b98ea5066da724af29d3348b599a7b3 Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Fri, 28 May 2021 15:50:44 +0200 Subject: [PATCH 094/681] cfg: new reverse post order with loop body before exit first --- compiler/CHANGELOG.md | 3 + .../test/IterationDirectiveTest.java | 8 +- .../core/common/type/IntegerStamp.java | 20 +- .../compiler/core/test/GraalCompilerTest.java | 18 - .../core/test/NodePropertiesTest.java | 10 +- .../compiler/core/test/SimpleCFGTest.java | 139 +++++ .../compiler/core/test/SpectreFenceTest.java | 5 + .../graalvm/compiler/java/BytecodeParser.java | 1 - .../java/ComputeLoopFrequenciesClosure.java | 135 ----- .../loop/phases/LoopTransformations.java | 59 +- .../phases/SpeculativeGuardMovementPhase.java | 4 +- .../loop/test/LoopPartialUnrollTest.java | 2 - .../graalvm/compiler/nodes/LoopBeginNode.java | 15 - .../org/graalvm/compiler/nodes/PiNode.java | 9 + .../graalvm/compiler/nodes/ProfileData.java | 1 + .../compiler/nodes/calc/IntegerTestNode.java | 4 +- .../org/graalvm/compiler/nodes/cfg/Block.java | 22 +- .../compiler/nodes/cfg/ControlFlowGraph.java | 559 +++++++++++++----- .../compiler/nodes/cfg/ReversePostOrder.java | 388 ++++++++++++ .../nodes/loop/DefaultLoopPolicies.java | 6 +- .../graalvm/compiler/nodes/loop/LoopEx.java | 9 + .../nodes/loop/LoopFragmentInside.java | 1 - .../FixedNodeRelativeFrequencyCache.java | 9 +- .../compiler/printer/BinaryGraphPrinter.java | 10 + .../truffle/compiler/PartialEvaluator.java | 3 - .../test/InstrumentBranchesPhaseTest.java | 20 +- .../test/LoopNodePartialEvaluationTest.java | 7 +- .../test/SimplePartialEvaluationTest.java | 24 +- .../truffle/test/nodes/AddTestNode.java | 16 +- .../truffle/test/nodes/RootTestNode.java | 18 +- .../nodes/explosion/UnrollingTestNode.java | 9 + 31 files changed, 1152 insertions(+), 382 deletions(-) delete mode 100644 compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java create mode 100644 compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ReversePostOrder.java diff --git a/compiler/CHANGELOG.md b/compiler/CHANGELOG.md index f6f999f8baef..955871e68ff4 100644 --- a/compiler/CHANGELOG.md +++ b/compiler/CHANGELOG.md @@ -2,6 +2,9 @@ This changelog summarizes newly introduced optimizations that may be relevant to other teams. +## Version 21.3.0 +* (GR-22707) (GR-30838): New, inner loops first, reverse post order and loop frequency calculations for the compiler. + ## Version 21.2.0 * (GR-29770) Loop safepoint elimination: Not only consider 32bit loops for safepoint removal but also 64bit ones that iterate in 32bit ranges. diff --git a/compiler/src/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IterationDirectiveTest.java b/compiler/src/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IterationDirectiveTest.java index d32454431078..800f0baf3095 100644 --- a/compiler/src/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IterationDirectiveTest.java +++ b/compiler/src/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IterationDirectiveTest.java @@ -24,14 +24,14 @@ */ package org.graalvm.compiler.api.directives.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.junit.Assert; +import org.junit.Test; public class IterationDirectiveTest extends GraalCompilerTest { @@ -59,6 +59,6 @@ protected void checkLowTierGraph(StructuredGraph graph) { Assert.assertEquals("LoopBeginNode count", 1, loopBeginNodes.count()); LoopBeginNode loopBeginNode = loopBeginNodes.first(); - Assert.assertEquals("loop frequency of " + loopBeginNode, 128, loopBeginNode.loopFrequency(), 0); + Assert.assertEquals("loop frequency of " + loopBeginNode, 128, ControlFlowGraph.compute(graph, false, false, false, false).localLoopFrequency(loopBeginNode), 0); } } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java index 80763dc56fb7..abc5b5b156d6 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java @@ -43,6 +43,7 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp; import org.graalvm.compiler.debug.GraalError; + import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; @@ -77,6 +78,8 @@ private IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, assert upperBound <= CodeUtil.maxValue(bits) : this; assert (downMask & CodeUtil.mask(bits)) == downMask : this; assert (upMask & CodeUtil.mask(bits)) == upMask : this; + // Check for valid masks or the empty encoding + assert (downMask & ~upMask) == 0 || (upMask == 0 && downMask == CodeUtil.mask(bits)) : String.format("\u21ca: %016x \u21c8: %016x", downMask, upMask); } public static IntegerStamp create(int bits, long lowerBoundInput, long upperBoundInput) { @@ -132,7 +135,7 @@ private static long significantBit(long bits, long value) { private static long minValueForMasks(int bits, long downMask, long upMask) { if (significantBit(bits, upMask) == 0) { // Value is always positive. Minimum value always positive. - assert significantBit(bits, downMask) == 0; + assert significantBit(bits, downMask) == 0 : String.format("\u21ca: %016x \u21c8: %016x", downMask, upMask); return downMask; } else { // Value can be positive or negative. Minimum value always negative. @@ -152,6 +155,15 @@ private static long maxValueForMasks(int bits, long downMask, long upMask) { } public static IntegerStamp stampForMask(int bits, long downMask, long upMask) { + /* + * Determine if the new stamp created by down & upMask would be contradicting, i.e., empty + * by definition. This can happen for example if binary logic operations are evaluated + * repetitively on different branches creating values that are infeasible by definition + * (logic nodes on phi nodes of false evaluated predecessors). + */ + if ((downMask & ~upMask) != 0L) { + return createEmptyStamp(bits); + } return new IntegerStamp(bits, minValueForMasks(bits, downMask, upMask), maxValueForMasks(bits, downMask, upMask), downMask, upMask); } @@ -162,7 +174,11 @@ public IntegerStamp unrestricted() { @Override public IntegerStamp empty() { - return new IntegerStamp(getBits(), CodeUtil.maxValue(getBits()), CodeUtil.minValue(getBits()), CodeUtil.mask(getBits()), 0); + return createEmptyStamp(getBits()); + } + + private static IntegerStamp createEmptyStamp(int bits) { + return new IntegerStamp(bits, CodeUtil.maxValue(bits), CodeUtil.minValue(bits), CodeUtil.mask(bits), 0); } @Override diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java index 22e42e8edfc1..94eaf3642c3a 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java @@ -70,7 +70,6 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.java.BytecodeParser; -import org.graalvm.compiler.java.ComputeLoopFrequenciesClosure; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.phases.LIRSuites; @@ -266,23 +265,6 @@ protected Suites createSuites(OptionValues opts) { */ iter = ret.getHighTier().findPhase(CanonicalizerPhase.class); } - iter.add(new Phase() { - - @Override - protected void run(StructuredGraph graph) { - ComputeLoopFrequenciesClosure.compute(graph); - } - - @Override - public float codeSizeIncrease() { - return NodeSize.IGNORE_SIZE_CONTRACT_FACTOR; - } - - @Override - protected CharSequence getName() { - return "ComputeLoopFrequenciesPhase"; - } - }); ret.getHighTier().appendPhase(new Phase() { @Override diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java index 472ab5aea744..42b1b325dffe 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java @@ -27,13 +27,13 @@ import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.SimplifierTool; -import org.graalvm.compiler.java.ComputeLoopFrequenciesClosure; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.graalvm.compiler.nodes.spi.Canonicalizable; import org.graalvm.compiler.nodes.spi.CoreProviders; +import org.graalvm.compiler.nodes.spi.SimplifierTool; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase.CustomSimplification; @@ -177,14 +177,12 @@ public void testCanonicalizationExample() { private void prepareGraphForLoopFrequencies(StructuredGraph g, HighTierContext htc) { // let canonicalizer work away branch probability nodes createCanonicalizerPhase().apply(g, htc); - // recompute the loop frequencies - ComputeLoopFrequenciesClosure.compute(g); } private static void assertFrequency(StructuredGraph g, int iterations) { NodeIterable loopBeginNodes = g.getNodes(LoopBeginNode.TYPE); LoopBeginNode loopBeginNode = loopBeginNodes.first(); - Assert.assertEquals("loop frequency of " + loopBeginNode, iterations, loopBeginNode.loopFrequency(), 0); + Assert.assertEquals("loop frequency of " + loopBeginNode, iterations, ControlFlowGraph.compute(g, false, false, false, false).localLoopFrequency(loopBeginNode), 0); } @Test diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java index 2c90d3408a77..2b997db480b6 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java @@ -24,13 +24,24 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext.Builder; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; +import org.graalvm.compiler.nodeinfo.NodeCycles; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.BeginNode; +import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.EndNode; +import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.MergeNode; import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; import org.graalvm.compiler.nodes.ReturnNode; @@ -38,6 +49,8 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.graalvm.compiler.nodes.debug.ControlFlowAnchored; +import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.junit.Assert; @@ -50,6 +63,132 @@ private static void dumpGraph(final StructuredGraph graph) { debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); } + @NodeInfo(allowedUsageTypes = InputType.Anchor, cycles = NodeCycles.CYCLES_0, size = NodeSize.SIZE_0) + static class SingleSplit extends ControlSplitNode implements ControlFlowAnchored { + public static final NodeClass TYPE = NodeClass.create(SingleSplit.class); + + @Successor AbstractBeginNode singleSuccessor; + + protected SingleSplit() { + super(TYPE, StampFactory.forVoid()); + } + + void setSingleSuccessor(AbstractBeginNode node) { + updatePredecessor(singleSuccessor, node); + singleSuccessor = node; + } + + @Override + public double probability(AbstractBeginNode successor) { + return getProfileData().getDesignatedSuccessorProbability(); + } + + @Override + public int getSuccessorCount() { + return 1; + } + + @Override + public boolean setProbability(AbstractBeginNode successor, BranchProbabilityData profileData) { + throw new PermanentBailoutException("There is only one successor, so probability cannot change"); + } + + @Override + public BranchProbabilityData getProfileData() { + return BranchProbabilityNode.ALWAYS_TAKEN_PROFILE; + } + + @Override + public AbstractBeginNode getPrimarySuccessor() { + return singleSuccessor; + } + + } + + static int single() { + GraalDirectives.deoptimizeAndInvalidate(); + return -1; + } + + @Test + public void testSingleSplit() { + StructuredGraph g = parseEager(getResolvedJavaMethod("single"), AllowAssumptions.NO); + FixedNode next = g.start().next(); + g.start().setNext(null); + SingleSplit s = g.add(new SingleSplit()); + AbstractBeginNode b = g.add(new BeginNode()); + b.setNext(next); + s.setSingleSuccessor(b); + g.start().setNext(s); + + g.getDebug().dump(DebugContext.VERY_DETAILED_LEVEL, g, "after build"); + ControlFlowGraph.compute(g, true, true, true, true); + } + + static int singleLoop(int end) { + int i = 0; + while (true) { + switch (i) { + default: + } + if (i == end) { + break; + } + i++; + continue; + } + return i; + } + + @Test + public void testSingleSplitLoop() { + StructuredGraph g = parseEager(getResolvedJavaMethod("singleLoop"), AllowAssumptions.NO); + g.getDebug().dump(DebugContext.VERY_DETAILED_LEVEL, g, "after build"); + ControlFlowGraph.compute(g, true, true, true, true); + } + + static int foo(int a, int b) { + int res = 0; + int i = 0; + while (true) { + if (i >= a) { + break; + } + if (i == 123) { + GraalDirectives.deoptimizeAndInvalidate(); + } + if (i == 126) { + GraalDirectives.deoptimizeAndInvalidate(); + } + res += i; + i++; + } + if (b == 42) { + GraalDirectives.deoptimizeAndInvalidate(); + } + return res; + } + + @Override + protected void checkHighTierGraph(StructuredGraph graph) { + super.checkHighTierGraph(graph); + if (!modify) { + return; + } + for (LoopExitNode lex : graph.getNodes().filter(LoopExitNode.class)) { + lex.setStateAfter(lex.loopBegin().stateAfter()); + } + } + + private boolean modify = false; + + @Test + public void testFoo() { + modify = true; + test("foo", 12, 12); + modify = false; + } + @Test public void testImplies() { OptionValues options = getInitialOptions(); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SpectreFenceTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SpectreFenceTest.java index 201de65bf866..c75cf4417726 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SpectreFenceTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SpectreFenceTest.java @@ -64,6 +64,7 @@ public static long test1Snippet(double a) { } else { SideEffectL = UNSAFE.getLong(m, ARRAY_LONG_BASE_OFFSET); } + GraalDirectives.controlFlowAnchor(); return UNSAFE.getLong(m, ARRAY_LONG_BASE_OFFSET); } @@ -75,7 +76,9 @@ public static long test2Snippet(double a) { } else { return Memory[1]; } + GraalDirectives.controlFlowAnchor(); } + GraalDirectives.controlFlowAnchor(); return Memory[2]; } @@ -88,6 +91,7 @@ public static long test3Snippet(double a) { return 1; } } + GraalDirectives.controlFlowAnchor(); return 4; } @@ -102,6 +106,7 @@ private void assertNumberOfFences(String snip, int fences) { if (beginNode.hasSpeculationFence()) { computedFences++; } + GraalDirectives.controlFlowAnchor(); } Assert.assertEquals("Expected fences", fences, computedFences); } diff --git a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index ef93c22ae97f..3eda28121872 100644 --- a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -1031,7 +1031,6 @@ protected void buildRootMethod() { } cleanupFinalGraph(); - ComputeLoopFrequenciesClosure.compute(graph); } protected BciBlockMapping generateBlockMap() { diff --git a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java deleted file mode 100644 index 3771cdf022a1..000000000000 --- a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2011, 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 org.graalvm.compiler.java; - -import static org.graalvm.compiler.nodes.cfg.ControlFlowGraph.multiplyRelativeFrequencies; - -import java.util.List; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.compiler.nodes.AbstractBeginNode; -import org.graalvm.compiler.nodes.AbstractMergeNode; -import org.graalvm.compiler.nodes.ControlSplitNode; -import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.LoopBeginNode; -import org.graalvm.compiler.nodes.LoopExitNode; -import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; -import org.graalvm.compiler.nodes.ProfileData.LoopFrequencyData; -import org.graalvm.compiler.nodes.ProfileData.ProfileSource; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; -import org.graalvm.compiler.phases.Phase; -import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; - -public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.NodeIteratorClosure { - - private static final ComputeLoopFrequenciesClosure INSTANCE = new ComputeLoopFrequenciesClosure(); - - private static final BranchProbabilityData ZERO = BranchProbabilityData.create(0.0, ProfileSource.UNKNOWN); - private static final BranchProbabilityData ONE = BranchProbabilityData.create(1.0, ProfileSource.UNKNOWN); - - private ComputeLoopFrequenciesClosure() { - // nothing to do - } - - private static BranchProbabilityData add(BranchProbabilityData x, BranchProbabilityData y) { - double p = x.getDesignatedSuccessorProbability() + y.getDesignatedSuccessorProbability(); - return BranchProbabilityData.create(p, x.getProfileSource().combine(y.getProfileSource())); - } - - private static BranchProbabilityData scale(BranchProbabilityData x, double scaleFactor) { - return scaleAndCombine(x, scaleFactor, x.getProfileSource()); - } - - private static BranchProbabilityData scaleAndCombine(BranchProbabilityData x, double scaleFactor, ProfileSource otherSource) { - double p = multiplyRelativeFrequencies(x.getDesignatedSuccessorProbability(), scaleFactor); - return BranchProbabilityData.create(p, x.getProfileSource().combine(otherSource)); - } - - @Override - protected BranchProbabilityData processNode(FixedNode node, BranchProbabilityData currentState) { - // normal nodes never change the probability of a path - return currentState; - } - - @Override - protected BranchProbabilityData merge(AbstractMergeNode merge, List states) { - // a merge has the sum of all predecessor probabilities - BranchProbabilityData result = ZERO; - for (BranchProbabilityData s : states) { - result = add(result, s); - } - return result; - } - - @Override - protected BranchProbabilityData afterSplit(AbstractBeginNode node, BranchProbabilityData oldState) { - // a control split splits up the probability - ControlSplitNode split = (ControlSplitNode) node.predecessor(); - return scaleAndCombine(oldState, split.probability(node), split.getProfileData().getProfileSource()); - } - - @Override - protected EconomicMap processLoop(LoopBeginNode loop, BranchProbabilityData initialState) { - EconomicMap exitStates = ReentrantNodeIterator.processLoop(this, loop, ONE).exitStates; - - BranchProbabilityData exitState = ZERO; - for (BranchProbabilityData e : exitStates.getValues()) { - exitState = add(exitState, e); - } - double exitRelativeFrequency = exitState.getDesignatedSuccessorProbability(); - exitRelativeFrequency = Math.min(1.0, exitRelativeFrequency); - exitRelativeFrequency = Math.max(ControlFlowGraph.MIN_RELATIVE_FREQUENCY, exitRelativeFrequency); - double loopFrequency = 1.0 / exitRelativeFrequency; - loop.setLoopFrequency(LoopFrequencyData.create(loopFrequency, exitState.getProfileSource())); - - double adjustmentFactor = initialState.getDesignatedSuccessorProbability() * loopFrequency; - exitStates.replaceAll((exitNode, state) -> scale(state, adjustmentFactor)); - - return exitStates; - } - - /** - * Computes the frequencies of all loops in the given graph. This is done by performing a - * reverse postorder iteration and computing the probability of all fixed nodes. The combined - * probability of all exits of a loop can be used to compute the loop's expected frequency. - */ - public static void compute(StructuredGraph graph) { - if (graph.hasLoops()) { - ReentrantNodeIterator.apply(INSTANCE, graph.start(), ONE); - } - } - - public static class ComputeLoopFrequencyPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - compute(graph); - } - } - - public static final ComputeLoopFrequencyPhase PHASE_INSTANCE = new ComputeLoopFrequencyPhase(); - -} diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java index e400b0f1065e..90510c6243cb 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java @@ -55,7 +55,6 @@ import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; -import org.graalvm.compiler.nodes.ProfileData.LoopFrequencyData; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.SafepointNode; import org.graalvm.compiler.nodes.StateSplit; @@ -63,6 +62,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; import org.graalvm.compiler.nodes.StructuredGraph.StageFlag; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; import org.graalvm.compiler.nodes.VirtualState.NodePositionClosure; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.CompareNode; @@ -92,12 +92,17 @@ private LoopTransformations() { public static void peel(LoopEx loop) { loop.detectCounted(); - loop.inside().duplicate().insertBefore(loop); + double frequencyBefore = -1D; + AbstractBeginNode countedExit = null; if (loop.isCounted()) { - // For counted loops we assume that we have an effect on the loop frequency. - loop.loopBegin().setLoopFrequency(loop.loopBegin().profileData().decrementFrequency(1.0)); + frequencyBefore = loop.localLoopFrequency(); + countedExit = loop.counted().getCountedExit(); } + loop.inside().duplicate().insertBefore(loop); loop.loopBegin().incrementPeelings(); + if (countedExit != null) { + adaptCountedLoopExitProbability(countedExit, frequencyBefore - 1D); + } } @SuppressWarnings("try") @@ -208,20 +213,9 @@ public static void unswitch(LoopEx loop, List controlSplitNode public static void partialUnroll(LoopEx loop, EconomicMap opaqueUnrolledStrides) { assert loop.loopBegin().isMainLoop(); loop.loopBegin().graph().getDebug().log("LoopPartialUnroll %s", loop); - + adaptCountedLoopExitProbability(loop.counted().getCountedExit(), loop.localLoopFrequency() / 2D); LoopFragmentInside newSegment = loop.inside().duplicate(); newSegment.insertWithinAfter(loop, opaqueUnrolledStrides); - - // Try to update the corresponding post loop's frequency. - for (LoopExitNode exit : loop.loopBegin().loopExits()) { - if (exit.next().hasExactlyOneUsage() && exit.next().usages().first() instanceof LoopBeginNode) { - LoopBeginNode possiblePostLoopBegin = (LoopBeginNode) exit.next().usages().first(); - if (possiblePostLoopBegin.isPostLoop()) { - possiblePostLoopBegin.setLoopFrequency(loop.loopBegin().profileData().copy(loop.loopBegin().getUnrollFactor() - 1)); - break; - } - } - } } /** @@ -416,14 +410,18 @@ public static PreMainPostResult insertPrePostLoops(LoopEx loop) { } else { updatePreLoopLimit(preCounted); } - double originalFrequency = loop.loopBegin().loopFrequency(); - preLoopBegin.setLoopFrequency(LoopFrequencyData.injected(1.0)); - mainLoopBegin.setLoopFrequency(mainLoopBegin.profileData().decrementFrequency(2.0)); - postLoopBegin.setLoopFrequency(LoopFrequencyData.injected(1.0)); + double originalFrequency = loop.localLoopFrequency(); preLoopBegin.setLoopOrigFrequency(originalFrequency); mainLoopBegin.setLoopOrigFrequency(originalFrequency); postLoopBegin.setLoopOrigFrequency(originalFrequency); + assert preLoopExitNode.predecessor() instanceof IfNode; + assert mainLoopExitNode.predecessor() instanceof IfNode; + assert postLoopExitNode.predecessor() instanceof IfNode; + + setSingleVisitedLoopFrequencySplitProbability(preLoopExitNode); + setSingleVisitedLoopFrequencySplitProbability(postLoopExitNode); + if (graph.isAfterStage(StageFlag.VALUE_PROXY_REMOVAL)) { // The pre and post loops don't require safepoints at all for (SafepointNode safepoint : preLoop.nodes().filter(SafepointNode.class)) { @@ -438,6 +436,27 @@ public static PreMainPostResult insertPrePostLoops(LoopEx loop) { return new PreMainPostResult(preLoopBegin, mainLoopBegin, postLoopBegin, preLoop, mainLoop, postLoop); } + /** + * Inject a split probability for the (counted) loop check that will result in a loop frequency + * of 1 (in case this is the only loop exit). + */ + private static void setSingleVisitedLoopFrequencySplitProbability(AbstractBeginNode lex) { + IfNode ifNode = ((IfNode) lex.predecessor()); + boolean trueSucc = ifNode.trueSuccessor() == lex; + ifNode.setTrueSuccessorProbability(BranchProbabilityData.injected(0.01, trueSucc)); + } + + public static void adaptCountedLoopExitProbability(AbstractBeginNode lex, double newFrequency) { + double d = Math.abs(1D - newFrequency); + if (d <= 1D) { + setSingleVisitedLoopFrequencySplitProbability(lex); + return; + } + IfNode ifNode = ((IfNode) lex.predecessor()); + boolean trueSucc = ifNode.trueSuccessor() == lex; + ifNode.setTrueSuccessorProbability(BranchProbabilityData.injected((newFrequency - 1) / newFrequency, trueSucc)); + } + public static class PreMainPostResult { private final LoopBeginNode preLoop; private final LoopBeginNode mainLoop; diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java index f8735ab9788a..1d387a867079 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java @@ -46,6 +46,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.WithExceptionNode; import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; +import org.graalvm.compiler.nodes.ProfileData.ProfileSource; import org.graalvm.compiler.nodes.StructuredGraph.StageFlag; import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.IntegerBelowNode; @@ -435,7 +436,8 @@ private boolean shouldOptimizeCompare(InductionVariable iv, ValueNode bound, Gua loopFreqThreshold++; } } - if (loopBeginNode.loopFrequency() < loopFreqThreshold) { + if (ProfileSource.isTrusted(loopEx.localFrequencySource()) && + loopEx.localLoopFrequency() < loopFreqThreshold) { debug.log("shouldOptimizeCompare(%s):loop frequency too low.", guard); // loop frequency is too low -- the complexity introduced by hoisting this guard // will not pay off. diff --git a/compiler/src/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java b/compiler/src/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java index 50f392394f9f..15d150ae2f63 100644 --- a/compiler/src/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java +++ b/compiler/src/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java @@ -35,7 +35,6 @@ import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.java.ComputeLoopFrequenciesClosure; import org.graalvm.compiler.loop.phases.LoopPartialUnrollPhase; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -315,7 +314,6 @@ public String toString(Verbosity verbosity) { new FloatingReadPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); new ConditionalEliminationPhase(true).apply(graph, context); - ComputeLoopFrequenciesClosure.compute(graph); new GuardLoweringPhase().apply(graph, context); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context); new FrameStateAssignmentPhase().apply(graph); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java index 196531c2b868..a0c6bb5b1daa 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java @@ -36,7 +36,6 @@ import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ProfileData.LoopFrequencyData; import org.graalvm.compiler.nodes.StructuredGraph.FrameStateVerificationFeature; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.extended.GuardingNode; @@ -53,7 +52,6 @@ public final class LoopBeginNode extends AbstractMergeNode implements IterableNodeType, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(LoopBeginNode.class); - private LoopFrequencyData profileData; protected double loopOrigFrequency; protected int nextEndIndex; protected int unswitches; @@ -139,7 +137,6 @@ public boolean isProtectedNonOverflowingUnsigned() { public LoopBeginNode() { super(TYPE); - profileData = LoopFrequencyData.DEFAULT; loopOrigFrequency = 1; unswitches = 0; splits = 0; @@ -262,18 +259,6 @@ public void setLoopOrigFrequency(double loopOrigFrequency) { this.loopOrigFrequency = loopOrigFrequency; } - public LoopFrequencyData profileData() { - return profileData; - } - - public double loopFrequency() { - return profileData.getLoopFrequency(); - } - - public void setLoopFrequency(LoopFrequencyData newProfileData) { - this.profileData = newProfileData; - } - /** * Returns the unordered set of {@link LoopEndNode} that correspond to back-edges for * this loop. The order of the back-edges is unspecified, if you need to get an ordering diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java index 7b86b3f80b16..036ba0df7646 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java @@ -231,6 +231,15 @@ public Node canonical(CanonicalizerTool tool) { if (value != null) { return value; } + if (tool.allUsagesAvailable()) { + for (Node usage : usages()) { + if (!(usage instanceof VirtualState)) { + return this; + } + } + // Only state usages: for them a more precise stamp does not matter. + return object; + } return this; } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProfileData.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProfileData.java index 966200aa5ea1..d7f7977f1aad 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProfileData.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProfileData.java @@ -86,6 +86,7 @@ public ProfileSource combine(ProfileSource other) { public static boolean isTrusted(ProfileSource source) { return source == INJECTED || source == PROFILED; } + } public ProfileSource getProfileSource() { diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerTestNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerTestNode.java index b50dedbb1eb9..5bb1dc835bce 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerTestNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerTestNode.java @@ -30,14 +30,14 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable.BinaryCommutative; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.BinaryOpLogicNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.Canonicalizable.BinaryCommutative; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import jdk.vm.ci.meta.TriState; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java index d91d2d74821b..f75f0a7b367c 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; +import org.graalvm.compiler.nodes.ProfileData.ProfileSource; import org.graalvm.compiler.nodes.WithExceptionNode; import org.graalvm.compiler.nodes.memory.MultiMemoryKill; import org.graalvm.compiler.nodes.memory.SingleMemoryKill; @@ -51,7 +52,8 @@ public final class Block extends AbstractBlockBase { protected FixedNode endNode; - protected double relativeFrequency; + protected double relativeFrequency = -1D; + protected ProfileSource frequencySource; private Loop loop; protected Block postdominator; @@ -192,7 +194,13 @@ public String toString() { public String toString(Verbosity verbosity) { StringBuilder sb = new StringBuilder(); sb.append('B').append(id); - if (verbosity != Verbosity.Id) { + if (verbosity == Verbosity.Name) { + sb.append("{"); + sb.append(getBeginNode()); + sb.append("->"); + sb.append(getEndNode()); + sb.append("}"); + } else if (verbosity != Verbosity.Id) { if (isLoopHeader()) { sb.append(" lh"); } @@ -299,10 +307,18 @@ public double getRelativeFrequency() { } public void setRelativeFrequency(double relativeFrequency) { - assert relativeFrequency >= 0 && Double.isFinite(relativeFrequency); + assert relativeFrequency >= 0 && Double.isFinite(relativeFrequency) : "Relative Frequency=" + relativeFrequency; this.relativeFrequency = relativeFrequency; } + public void setFrequencySource(ProfileSource frequencySource) { + this.frequencySource = frequencySource; + } + + public ProfileSource getFrequencySource() { + return frequencySource; + } + @Override public Block getDominator(int distance) { Block result = this; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java index 25d1e232b507..bc751a9c5e68 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java @@ -30,27 +30,29 @@ import java.util.Arrays; import java.util.BitSet; import java.util.List; +import java.util.function.Consumer; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.CFGVerifier; import org.graalvm.compiler.core.common.cfg.Loop; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.AbstractBeginNode; -import org.graalvm.compiler.nodes.AbstractEndNode; -import org.graalvm.compiler.nodes.AbstractMergeNode; -import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.ControlSplitNode; -import org.graalvm.compiler.nodes.EndNode; +import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.ProfileData.LoopFrequencyData; +import org.graalvm.compiler.nodes.ProfileData.ProfileSource; +import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; public final class ControlFlowGraph implements AbstractControlFlowGraph { @@ -70,6 +72,7 @@ public final class ControlFlowGraph implements AbstractControlFlowGraph { private Block[] reversePostOrder; private List> loops; private int maxDominatorDepth; + private EconomicMap localLoopFrequencyData; public interface RecursiveVisitor { V enter(Block b); @@ -83,7 +86,9 @@ public static ControlFlowGraph computeForSchedule(StructuredGraph graph) { public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) { ControlFlowGraph cfg = new ControlFlowGraph(graph); + cfg.identifyBlocks(); + cfg.computeFrequencies(); if (computeLoops) { @@ -91,6 +96,7 @@ public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlo } if (computeDominators) { cfg.computeDominators(); + assert cfg.verifyRPOInnerLoopsFirst(); } if (computePostdominators) { cfg.computePostdominators(); @@ -101,6 +107,28 @@ public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlo return cfg; } + private void identifyBlocks() { + int numBlocks = 0; + for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.TYPE)) { + Block block = new Block(begin); + identifyBlock(block); + numBlocks++; + } + reversePostOrder = ReversePostOrder.identifyBlocks(this, numBlocks); + } + + public double localLoopFrequency(LoopBeginNode lb) { + return localLoopFrequencyData.get(lb).getLoopFrequency(); + } + + public ProfileSource localLoopFrequencySource(LoopBeginNode lb) { + return localLoopFrequencyData.get(lb).getProfileSource(); + } + + public EconomicMap getLocalLoopFrequencyData() { + return localLoopFrequencyData; + } + public String dominatorTreeString() { return dominatorTreeString(getStartBlock()); } @@ -309,6 +337,197 @@ private ControlFlowGraph(StructuredGraph graph) { this.nodeToBlock = graph.createNodeMap(); } + /** + * Utility class to verify that {@link ReversePostOrder} only produces reverse post order + * traversals of the graph that contain inner loops before outer ones. + */ + private static class RPOLoopVerification { + int endsVisited; + int exitsVisited; + LoopBeginNode lb; + + RPOLoopVerification(LoopBeginNode lb) { + this.lb = lb; + } + + boolean loopFullyProcessed() { + return lb.getLoopEndCount() == endsVisited && exitsVisited == lb.loopExits().count(); + } + + boolean allEndsVisited() { + return lb.getLoopEndCount() == endsVisited; + } + + } + + /** + * Verification method to ensure that inner loops are processed before outer ones: see + * {@link ControlFlowGraph#computeFrequencies()} for details. + */ + private boolean verifyRPOInnerLoopsFirst() { + return rpoInnerLoopsFirst(b -> { + }, b -> { + }); + } + + /** + * Special note on loop exit nodes and dominator tree loop exits: Graal has a "closed" loop + * form, this means every {@link LoopBeginNode} needs explicit {@link LoopEndNode} nodes and (if + * it is not an endless loop) {@link LoopExitNode}. For every path exiting a loop a + * {@link LoopExitNode} is required. There is one exception to that rule: + * {@link DeoptimizeNode}. + * + * Graal does not mandate that a {@link DeoptimizeNode} is preceded by a {@link LoopExitNode}. + * In the following example + * + *
    +     * for (int i = 0; i < end; i++) {
    +     *     if (condition) {
    +     *         deoptimize;
    +     *     }
    +     * }
    +     * 
    + * + * the IR does not have a preceding loop exit node before the deopt node. However, for regular + * control flow sinks (returns, throws, etc) like in the following example + * + *
    +     * for (int i = 0; i < end; i++) {
    +     *     if (condition) {
    +     *         return;
    +     *     }
    +     * }
    +     * 
    + * + * Graal IR creates a {@link LoopExitNode} before the {@link ReturnNode}. + * + * Because of the "imprecision" in the definition a regular basic block exiting a loop and a + * "dominator tree" loop exit are not necessarily the same. If a path after a control flow split + * unconditionally flows into a deopt it is a "dominator loop exit" while a regular loop exit + * block contains a {@linkplain LoopExitNode}. + */ + private boolean rpoInnerLoopsFirst(Consumer perBasicBlockOption, Consumer loopClosedAction) { + // worst case all loops in the graph are nested + RPOLoopVerification[] openLoops = new RPOLoopVerification[graph.getNodes(LoopBeginNode.TYPE).count()]; + int tos = 0; + for (Block b : reversePostOrder) { + // we see a loop end, open a new verification level in the loop stack + if (b.isLoopHeader()) { + RPOLoopVerification lv = new RPOLoopVerification((LoopBeginNode) b.getBeginNode()); + openLoops[tos++] = lv; + } + + // process this basic block + perBasicBlockOption.accept(b); + + /* + * General note on the verification of loop exits: A loop exit node and a dominator tree + * loop exit are not necessarily the same, see javadoc of this method. Ideally, we would + * like to visit all dominator loop exits during RPO verification, however we do not + * know how many there are (given the deopt issue above), thus we just determine by the + * loop exit nodes seen. + */ + boolean wasExit = predecessorBlockSequentialLoopExit(b); + + FixedNode f = b.getBeginNode(); + while (true) { + if (f instanceof LoopExitNode) { + LoopBeginNode closedLoop = ((LoopExitNode) f).loopBegin(); + RPOLoopVerification lv = openLoops[tos - 1]; + assert lv.lb == closedLoop : "Must close inner loops first before closing other ones stackLoop=" + lv.lb + " exited loop=" + closedLoop + " block=" + b; + if (!lv.allEndsVisited()) { + throw GraalError.shouldNotReachHere( + "Loop ends should be visited before exits. This is a major error in the reverse post order of the control " + + "flow graph of this method. This typically means wrongly specified control-split nodes have been processed in ReversePostOrder.java."); + } + lv.exitsVisited++; + if (lv.loopFullyProcessed()) { + loopClosedAction.accept(lv.lb); + tos--; + } + wasExit = true; + } + if (f == b.getEndNode()) { + break; + } + f = ((FixedWithNextNode) f).next(); + } + + if (b.isLoopEnd()) { + RPOLoopVerification lv = null; + LoopEndNode len = (LoopEndNode) b.getEndNode(); + int index = tos - 1; + if (wasExit) { + // irregular case a basic block that is a loop exit to an inner loop followed by + // a loop end to an outer loop, while the inner loop potentially is not + // finished, we still need to allow such cases since the code in the fraction + // between loop exit inner and end outer is fine, it does not change the + // verification logic since its a single basic block + while (openLoops[index].lb != len.loopBegin()) { + index--; + } + lv = openLoops[index]; + } else { + // regular case, this block contains a loop end to the inner most loop + lv = openLoops[tos - 1]; + } + LoopBeginNode closedLoop = ((LoopEndNode) b.getEndNode()).loopBegin(); + assert lv.lb == closedLoop : "Must close inner loops first before closing other ones stackLoop=" + lv.lb + " ended loop=" + closedLoop + " block=" + b; + lv.endsVisited++; + if (lv.loopFullyProcessed()) { + loopClosedAction.accept(lv.lb); + // the current loop was exited but we also end an outer loop, find this one and + // remove it from the verification stack since its done + if (lv.lb != openLoops[tos - 1].lb) { + // we actually finished the outer loop already completely through this + // exit-end scenario, remove it from the stack + RPOLoopVerification[] tmp = new RPOLoopVerification[openLoops.length]; + System.arraycopy(openLoops, 0, tmp, 0, index); + System.arraycopy(openLoops, index + 1, tmp, index, openLoops.length - (index + 1)); + openLoops = tmp; + } + tos--; + } + } + } + assert tos == 0 : "Unfinished loops on stack " + tos; + return true; + } + + /** + * Determine if sequential predecessor blocks of this block in a not-fully-canonicalized graph + * exit a loop. + * + * Example: Sequential basic block: loop exit -> invoke -> killing begin -> loopend/exit + * + * These cases cause problems in the {@link #verifyRPOInnerLoopsFirst()} loop verification of + * inner loop blocks because the granularity of loop ends and exits are not on block boundaries: + * a loop exit block can also be a loop end to an outer loop, which makes verification that the + * inner loop is fully processed before we process the rest of the outer loop tricky (since we + * already visit a loop end to an outer loop while we should first stricly process all loop + * ends/exits of inner loops). + */ + private static boolean predecessorBlockSequentialLoopExit(Block b) { + Block cur = b; + // while cur has a single predecessor which has a single successor which is cur, i.e., a + // sequential successor, this typically only happens in not-fully-canonicalized graphs + while (cur.getPredecessorCount() == 1 && cur.getPredecessors()[0].getSuccessorCount() == 1) { + Block pred = cur.getPredecessors()[0]; + FixedNode f = pred.getBeginNode(); + while (true) { + if (f instanceof LoopExitNode) { + return true; + } + if (f == pred.getEndNode()) { + break; + } + f = ((FixedWithNextNode) f).next(); + } + cur = cur.getPredecessors()[0]; + } + return false; + } + private void computeDominators() { assert reversePostOrder[0].getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator"; Block[] blocks = reversePostOrder; @@ -460,155 +679,215 @@ private void identifyBlock(Block block) { } } - /** - * Identify and connect blocks (including loop backward edges). Predecessors need to be in the - * order expected when iterating phi inputs. - */ - private void identifyBlocks() { - // Find all block headers. - int numBlocks = 0; - for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.TYPE)) { - Block block = new Block(begin); - identifyBlock(block); - numBlocks++; + private void finishLocalLoopFrequency(LoopBeginNode lb) { + calculateLocalLoopFrequency(lb); + for (LoopExitNode lex : lb.loopExits()) { + Block lexBlock = blockFor(lex); + assert lexBlock != null; + final double lexFrequency = lexBlock.getRelativeFrequency(); + final double localLoopFrequency = localLoopFrequencyData.get(lb).getLoopFrequency(); + /* + * While the local loop frequency is calculated without the predecessor frequency, the + * exit frequency needs to be adjusted already to compute any outer loop local + * frequencies correctly. + */ + final double loopPredFrequency = blockFor(lb.forwardEnd()).relativeFrequency; + final double virginExitFrequency = multiplyRelativeFrequencies(lexFrequency, localLoopFrequency, loopPredFrequency); + // exit path, we set the exit probability + lexBlock.setRelativeFrequency(virginExitFrequency); } + } - // Compute reverse post order. - int count = 0; - NodeMap nodeMap = this.nodeToBlock; - Block[] stack = new Block[numBlocks]; - int tos = 0; - Block startBlock = blockFor(graph.start()); - stack[0] = startBlock; - startBlock.setPredecessors(Block.EMPTY_ARRAY); - do { - Block block = stack[tos]; - int id = block.getId(); - if (id == BLOCK_ID_INITIAL) { - // First time we see this block: push all successors. - FixedNode last = block.getEndNode(); - if (last instanceof EndNode) { - EndNode endNode = (EndNode) last; - Block suxBlock = nodeMap.get(endNode.merge()); - if (suxBlock.getId() == BLOCK_ID_INITIAL) { - stack[++tos] = suxBlock; - } - block.setSuccessors(new Block[]{suxBlock}); - } else if (last instanceof IfNode) { - IfNode ifNode = (IfNode) last; - Block trueSucc = nodeMap.get(ifNode.trueSuccessor()); - stack[++tos] = trueSucc; - Block falseSucc = nodeMap.get(ifNode.falseSuccessor()); - stack[++tos] = falseSucc; - block.setSuccessors(new Block[]{trueSucc, falseSucc}); - Block[] ifPred = new Block[]{block}; - trueSucc.setPredecessors(ifPred); - falseSucc.setPredecessors(ifPred); - } else if (last instanceof LoopEndNode) { - LoopEndNode loopEndNode = (LoopEndNode) last; - block.setSuccessors(new Block[]{nodeMap.get(loopEndNode.loopBegin())}); - // Nothing to do push onto the stack. - } else if (last instanceof ControlSinkNode) { - block.setSuccessors(Block.EMPTY_ARRAY); - } else { - assert !(last instanceof AbstractEndNode) : "Algorithm only supports EndNode and LoopEndNode."; - int startTos = tos; - Block[] ifPred = new Block[]{block}; - for (Node suxNode : last.successors()) { - Block sux = nodeMap.get(suxNode); - stack[++tos] = sux; - sux.setPredecessors(ifPred); - } - int suxCount = tos - startTos; - Block[] successors = new Block[suxCount]; - System.arraycopy(stack, startTos + 1, successors, 0, suxCount); - block.setSuccessors(successors); - } - block.setId(BLOCK_ID_VISITED); - AbstractBeginNode beginNode = block.getBeginNode(); - if (beginNode instanceof LoopBeginNode) { - computeLoopPredecessors(nodeMap, block, (LoopBeginNode) beginNode); - } else if (beginNode instanceof AbstractMergeNode) { - AbstractMergeNode mergeNode = (AbstractMergeNode) beginNode; - int forwardEndCount = mergeNode.forwardEndCount(); - Block[] predecessors = new Block[forwardEndCount]; - for (int i = 0; i < forwardEndCount; ++i) { - predecessors[i] = nodeMap.get(mergeNode.forwardEndAt(i)); - } - block.setPredecessors(predecessors); - } - - } else if (id == BLOCK_ID_VISITED) { - // Second time we see this block: All successors have been processed, so add block - // to result list. Can safely reuse the stack for this. - --tos; - count++; - int index = numBlocks - count; - stack[index] = block; - block.setId(index); - } else { - throw GraalError.shouldNotReachHere(); - } - } while (tos >= 0); - - // Compute reverse postorder and number blocks. - assert count == numBlocks : "all blocks must be reachable"; - this.reversePostOrder = stack; + private void computeLocalLoopFrequencies() { + rpoInnerLoopsFirst(b -> { + perBasicBlockFrequencyAction(b, true); + }, lb -> { + finishLocalLoopFrequency(lb); + }); } - private static void computeLoopPredecessors(NodeMap nodeMap, Block block, LoopBeginNode loopBeginNode) { - int forwardEndCount = loopBeginNode.forwardEndCount(); - LoopEndNode[] loopEnds = loopBeginNode.orderedLoopEnds(); - Block[] predecessors = new Block[forwardEndCount + loopEnds.length]; - for (int i = 0; i < forwardEndCount; ++i) { - predecessors[i] = nodeMap.get(loopBeginNode.forwardEndAt(i)); + private double calculateLocalLoopFrequency(LoopBeginNode lb) { + Block header = blockFor(lb); + assert header != null; + double loopEndFrequency = 0D; + ProfileSource source = ProfileSource.UNKNOWN; + for (LoopEndNode len : lb.loopEnds()) { + Block endBlock = blockFor(len); + assert endBlock != null; + assert endBlock.relativeFrequency >= 0D; + loopEndFrequency += endBlock.relativeFrequency; + source = source.combine(endBlock.frequencySource); } - for (int i = 0; i < loopEnds.length; ++i) { - predecessors[i + forwardEndCount] = nodeMap.get(loopEnds[i]); + + loopEndFrequency = Math.min(1, loopEndFrequency); + loopEndFrequency = Math.max(ControlFlowGraph.MIN_RELATIVE_FREQUENCY, loopEndFrequency); + + double loopFrequency = -1; + if (loopEndFrequency == 1D) { + // endless loop, loop with exit and deopt unconditionally after the exit + loopFrequency = MAX_RELATIVE_FREQUENCY; + } else { + double exitFrequency = 1D - loopEndFrequency; + loopFrequency = 1D / exitFrequency; + + assert Double.isFinite(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " endFrequency=" + loopEndFrequency; + assert !Double.isNaN(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " endFrequency=" + loopEndFrequency; } - block.setPredecessors(predecessors); + localLoopFrequencyData.put(lb, LoopFrequencyData.create(loopFrequency, source)); + return loopFrequency; } - /** - * Computes the frequencies of all blocks relative to the start block. It uses the probability - * information attached to control flow splits to calculate the frequency of a block based on - * the frequency of its predecessor and the probability of its incoming control flow branch. - */ - private void computeFrequencies() { + private void resetBlockFrequencies() { + for (Block block : reversePostOrder) { + block.setRelativeFrequency(0); + } + } + private void computeFrequenciesFromLocal() { for (Block block : reversePostOrder) { - Block[] predecessors = block.getPredecessors(); - - double relativeFrequency; - if (predecessors.length == 0) { - relativeFrequency = 1D; - } else if (predecessors.length == 1) { - Block pred = predecessors[0]; - relativeFrequency = pred.relativeFrequency; - if (pred.getSuccessorCount() > 1) { - assert pred.getEndNode() instanceof ControlSplitNode; - ControlSplitNode controlSplit = (ControlSplitNode) pred.getEndNode(); - relativeFrequency = multiplyRelativeFrequencies(relativeFrequency, controlSplit.probability(block.getBeginNode())); - } - } else { - relativeFrequency = predecessors[0].relativeFrequency; - for (int i = 1; i < predecessors.length; ++i) { - relativeFrequency += predecessors[i].relativeFrequency; - } + perBasicBlockFrequencyAction(block, false); + } + } - if (block.getBeginNode() instanceof LoopBeginNode) { - LoopBeginNode loopBegin = (LoopBeginNode) block.getBeginNode(); - relativeFrequency = multiplyRelativeFrequencies(relativeFrequency, loopBegin.loopFrequency()); + private void perBasicBlockFrequencyAction(Block b, boolean computingLocalLoopFrequencies) { + double relativeFrequency = -1D; + ProfileSource source = ProfileSource.UNKNOWN; + Block[] predecessors = b.getPredecessors(); + if (predecessors.length == 0) { + relativeFrequency = 1D; + } else if (predecessors.length == 1) { + Block pred = predecessors[0]; + relativeFrequency = pred.relativeFrequency; + if (pred.getSuccessorCount() > 1) { + assert pred.getEndNode() instanceof ControlSplitNode; + ControlSplitNode controlSplit = (ControlSplitNode) pred.getEndNode(); + relativeFrequency = multiplyRelativeFrequencies(relativeFrequency, controlSplit.probability(b.getBeginNode())); + if (computingLocalLoopFrequencies) { + source = controlSplit.getProfileData().getProfileSource(); } } - if (relativeFrequency < MIN_RELATIVE_FREQUENCY) { - relativeFrequency = MIN_RELATIVE_FREQUENCY; - } else if (relativeFrequency > MAX_RELATIVE_FREQUENCY) { - relativeFrequency = MAX_RELATIVE_FREQUENCY; + } else { + relativeFrequency = predecessors[0].relativeFrequency; + for (int i = 1; i < predecessors.length; ++i) { + relativeFrequency += predecessors[i].relativeFrequency; + if (computingLocalLoopFrequencies) { + if (predecessors[i].frequencySource != null) { + source = source.combine(predecessors[i].frequencySource); + } + } + } + if (b.getBeginNode() instanceof LoopBeginNode) { + if (computingLocalLoopFrequencies) { + // start with a "local" loop, i.e., assume no dominating code with different + // frequencies + relativeFrequency = 1D; + source = ProfileSource.UNKNOWN; + } else { + // take the previously computed local frequency + LoopBeginNode loopBegin = (LoopBeginNode) b.getBeginNode(); + relativeFrequency = multiplyRelativeFrequencies(relativeFrequency, localLoopFrequencyData.get(loopBegin).getLoopFrequency()); + } } - block.setRelativeFrequency(relativeFrequency); } + if (relativeFrequency < MIN_RELATIVE_FREQUENCY) { + relativeFrequency = MIN_RELATIVE_FREQUENCY; + } else if (relativeFrequency > MAX_RELATIVE_FREQUENCY) { + relativeFrequency = MAX_RELATIVE_FREQUENCY; + } + b.setRelativeFrequency(relativeFrequency); + if (computingLocalLoopFrequencies) { + b.setFrequencySource(source); + } + } + + //@formatter:off + /* + * Compute the frequency data for the entire control flow graph. + * In the following documentation the term "local loop frequency" describes the frequency of a loop + * without any enclosing code, i.e., the loop in a form where it is not dominated by any other control flow. + * + * The real frequency of a loop is then the result of multiplying the local loop frequency with the frequency + * of the basic block dominating the loop. + * + * Consider the following CFG: + * + * + * + * [B0: Loop 1 Header] + * | + * [B1:if] + * / \ + * [B2: Loop 2 Header] [B9: Loop Exit Loop1 + Return] + * | + * [B3: If] + * / \ + * [B4: LoopEnd Loop2] [B5: LoopExit Loop2 + If] + * / \ + * [B6] [B7] + * \ / + * [B8:Merge + LoopEnd Loop1] + * + * + * The frequency of the loop exit basic blocks depends on the frequency of the loop header. + * Why? Because the loop header is visited multiple times so the frequency of the loop exit block + * has to be multiplied by the frequency of the loop header (which is the frequency of all loop + * end blocks combined). The frequency of the loop header can be derived by summing up the frequency + * of all loop end blocks which gives us the frequency for exiting the loop (1- sumLoopEndFrequency). + * The frequency of the loop can then be calculated by 1 / frequencyToExitTheLoop. + * + * In a final step we multiply the frequency of each exit with the frequency to exit the overall + * loop to account for the loop frequency. + * + * Ideally we would only process all basic blocks once here, however, given that the frequency of an + * outer loop depends on loop end frequencies which can depend on the frequency of inner loops, + * we either ensure to process inner loops first or perform the entire process until a fix point is reached. + * + * However, we can utilize a "smart" reverse post order with inner loops first to reach that goal. + * + * Graph theory states that there are multiple correct reverse post order (RPO) traversals + * for any given graph. Consider for example the following RPO for the CFG above: + * [B0,B1,B2,B3,B4,B5,B6,B7,B8,B9] + * + * The inner loop is sequentially in the traversal, thus we can compute its local frequency and + * then propagate it outwards by processing the entire CFG once again. + * + * However, there are other valid RPOs that do not allow a single pass over all loops to calculate local + * frequencies: e.g. [B0,B1,B9,B2,B3,B5,B6,B7,B8,B4], thus this phase ensures that we have the "right" RPO. + * + * Implementation notes: + * The algorithm to compute the loop frequencies works in two passes: the first pass computes + * the local loop frequencies, i.e., for every loop predecessor block a relative frequency of 1 + * is assumed, then the frequency inside the loop is propagated and multiplied by control split + * probabilities. If a loop is finished the exit frequency is set accordingly. + * + * The second pass then propagates relative frequencies into the entire CFG by using the, + * already correct, local loop frequencies for the body of the loop. + */ + //@formatter:on + private void computeFrequencies() { + /* + * General note: While it is not verified that the reverse post order contains inner loops + * first yet, this will be verified once we calculate dominance information, thus we should + * be good here. + */ + localLoopFrequencyData = EconomicMap.create(); + + // pass 1 compute "local" loop frequencies, i.e., the actual frequency of each self + // contained loop, inner loops first, then outer loops + computeLocalLoopFrequencies(); + // reset everything again + resetBlockFrequencies(); + + // pass 2 propagate the outer frequencies into the inner ones multiplying the local loop + // frequencies by the loop predecessor frequencies + computeFrequenciesFromLocal(); + + if (Assertions.assertionsEnabled()) { + for (Block block : reversePostOrder) { + assert block.getRelativeFrequency() >= 0 : "Must have a relative frequency set, block " + block; + } + } } private void computeLoopInformation() { @@ -758,6 +1037,10 @@ public void setNodeToBlock(NodeMap nodeMap) { this.nodeToBlock = nodeMap; } + public static double multiplyRelativeFrequencies(double a, double b, double c) { + return multiplyRelativeFrequencies(multiplyRelativeFrequencies(a, b), c); + } + /** * Multiplies a and b and clamps the between {@link ControlFlowGraph#MIN_RELATIVE_FREQUENCY} and * {@link ControlFlowGraph#MAX_RELATIVE_FREQUENCY}. diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ReversePostOrder.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ReversePostOrder.java new file mode 100644 index 000000000000..3711039030ef --- /dev/null +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ReversePostOrder.java @@ -0,0 +1,388 @@ +/* + * Copyright (c) 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 org.graalvm.compiler.nodes.cfg; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Deque; +import java.util.Iterator; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; +import org.graalvm.compiler.debug.Assertions; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeMap; +import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.AbstractEndNode; +import org.graalvm.compiler.nodes.AbstractMergeNode; +import org.graalvm.compiler.nodes.ControlSinkNode; +import org.graalvm.compiler.nodes.ControlSplitNode; +import org.graalvm.compiler.nodes.EndNode; +import org.graalvm.compiler.nodes.FixedNode; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.LoopEndNode; +import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.spi.Canonicalizable; +import org.graalvm.compiler.nodes.spi.Simplifiable; + +/** + * Utility class computing a reverse post order of the {@link ControlFlowGraph}. + * + * The block order is special in that {@linkplain LoopEndNode blocks} are processed before + * {@linkplain LoopExitNode blocks}. This has the advantage that for + * {@linkplain Block#getRelativeFrequency() basic block frequency calculations} nested loops are + * processed before the outer loop exit blocks allowing a linear computation of loop frequencies. + */ +public class ReversePostOrder { + + /** + * Utility class for eager basic block creation. The CFG will create the shortest possible basic + * blocks within the given control flow graph: this class has to ensure that predecessor and + * successor blocks are set accordingly. + * + * "Shortest" possible is a special case in that, if a {@link StructuredGraph} is not fully + * {@linkplain Canonicalizable canonicalized}, i.e., it contains redundant + * {@link AbstractBeginNode}, each {@link AbstractBeginNode} will form a new basic block. + * + * This is necessary given that we do not want to run a full canonicalization and CFG + * {@linkplain Simplifiable simplification}} every time to compute the {@link ControlFlowGraph}. + */ + private static class TraversalQueueHandler { + private final ControlFlowGraph cfg; + /** + * The result reverse post order block list. + */ + private final Block[] reversePostOrder; + /** + * Index of the next block to be added to {@link #reversePostOrder}. + */ + private int nextBlockIndex; + private final NodeMap nodeMap; + + TraversalQueueHandler(ControlFlowGraph cfg, int numBlocks) { + this.cfg = cfg; + this.nodeMap = cfg.getNodeToBlock(); + reversePostOrder = new Block[numBlocks]; + nextBlockIndex = 0; + } + + /** + * Graal IR has certain requirements with respect to what can be a + * {@link Block#getBeginNode()} and {@link Block#getEndNode()}: Every + * {@link AbstractBeginNode} forms a new {@link Block}. This method must ensure + * {@link Block#getPredecessors()} and {@link Block#getSuccessors()} are set accordingly. + */ + protected Block potentiallySplitBlock(FixedNode currentNode, Block currentBlock) { + assert currentBlock != null : "Block must not be null for node " + currentNode; + if (currentBlock.getBeginNode() == currentNode) { + /* + * We process a block begin node add the block to the next index in the traversal + * and set the predecessors accordingly. + */ + Block b = cfg.blockFor(currentNode); + reversePostOrder[nextBlockIndex] = b; + b.setId(nextBlockIndex); + nextBlockIndex++; + + if (currentNode instanceof LoopBeginNode) { + computeLoopPredecessors(nodeMap, currentBlock, (LoopBeginNode) currentNode); + } else if (currentNode instanceof AbstractMergeNode) { + AbstractMergeNode mergeNode = (AbstractMergeNode) currentNode; + int forwardEndCount = mergeNode.forwardEndCount(); + Block[] predecessors = new Block[forwardEndCount]; + for (int i = 0; i < forwardEndCount; ++i) { + predecessors[i] = nodeMap.get(mergeNode.forwardEndAt(i)); + } + currentBlock.setPredecessors(predecessors); + } + } + if (currentBlock.getEndNode() == currentNode) { + /** + * We process a block end node: create the necessary successor and set them + * accordingly. + */ + if (currentNode instanceof EndNode) { + // next node is a merge, update successors + EndNode endNode = (EndNode) currentNode; + Block suxBlock = nodeMap.get(endNode.merge()); + currentBlock.setSuccessors(new Block[]{suxBlock}); + } else if (currentNode instanceof ControlSplitNode) { + // next is a split, set successors and predecessors accordingly for the split + ArrayList succ = new ArrayList<>(); + Block[] ifPred = new Block[]{currentBlock}; + for (Node sux : currentNode.successors()) { + Block sucBlock = nodeMap.get(sux); + succ.add(sucBlock); + sucBlock.setPredecessors(ifPred); + } + currentBlock.setSuccessors(succ.toArray(new Block[succ.size()])); + } else if (currentNode instanceof LoopEndNode) { + LoopEndNode loopEndNode = (LoopEndNode) currentNode; + currentBlock.setSuccessors(new Block[]{nodeMap.get(loopEndNode.loopBegin())}); + } else if (currentNode instanceof ControlSinkNode) { + currentBlock.setSuccessors(Block.EMPTY_ARRAY); + } else { + assert !(currentNode instanceof AbstractEndNode) : "Algorithm only supports EndNode and LoopEndNode."; + Block[] ifPred = new Block[]{currentBlock}; + for (Node suxNode : currentNode.successors()) { + Block sux = nodeMap.get(suxNode); + sux.setPredecessors(ifPred); + } + assert currentNode.successors().count() == 1 : "Node " + currentNode; + Block sequentialSuc = nodeMap.get(currentNode.successors().first()); + currentBlock.setSuccessors(new Block[]{sequentialSuc}); + return sequentialSuc; + } + } + return currentBlock; + } + + private LoopInfo processLoop(LoopBeginNode loop) { + EconomicMap blockEndStates = apply(this, loop, cfg.blockFor(loop), loop); + LoopInfo info = new LoopInfo(loop.loopEnds().count(), loop.loopExits().count()); + for (LoopEndNode end : loop.loopEnds()) { + if (blockEndStates.containsKey(end)) { + info.endStates.put(end, blockEndStates.get(end)); + blockEndStates.removeKey(end); + } + } + for (LoopExitNode exit : loop.loopExits()) { + if (blockEndStates.containsKey(exit)) { + info.exitStates.put(exit, blockEndStates.get(exit)); + blockEndStates.removeKey(exit); + } + } + /* + * Deopt grouping can create loop exits without loop exit nodes that do not sink but + * merge + */ + for (FixedNode f : blockEndStates.getKeys()) { + info.naturalExits.put(f, blockEndStates.get(f)); + } + return info; + } + + private Block enqueBlockUnconditionally(FixedNode newBlockBegin) { + return cfg.blockFor(newBlockBegin); + } + + } + + private static class LoopInfo { + public final EconomicMap endStates; + public final EconomicMap exitStates; + public final EconomicMap naturalExits; + + LoopInfo(int endCount, int exitCount) { + endStates = EconomicMap.create(Equivalence.IDENTITY, endCount); + exitStates = EconomicMap.create(Equivalence.IDENTITY, exitCount); + naturalExits = EconomicMap.create(Equivalence.IDENTITY, exitCount); + } + } + + private static EconomicMap apply(TraversalQueueHandler traversalHandler, FixedNode start, Block initialBlock, LoopBeginNode boundary) { + assert start != null; + Deque nodeQueue = new ArrayDeque<>(); + EconomicMap blockEndStates = EconomicMap.create(Equivalence.IDENTITY); + + Block currentBlock = initialBlock; + + FixedNode currentFixedNode = start; + + do { + while (currentFixedNode instanceof FixedWithNextNode) { + if (boundary != null && currentFixedNode instanceof LoopExitNode && ((LoopExitNode) currentFixedNode).loopBegin() == boundary) { + blockEndStates.put(currentFixedNode, currentBlock); + currentFixedNode = null; + } else { + FixedNode next = ((FixedWithNextNode) currentFixedNode).next(); + currentBlock = traversalHandler.potentiallySplitBlock(currentFixedNode, currentBlock); + currentFixedNode = next; + } + } + + if (currentFixedNode != null) { + currentBlock = traversalHandler.potentiallySplitBlock(currentFixedNode, currentBlock); + + Iterator successors = currentFixedNode.successors().iterator(); + if (!successors.hasNext()) { + if (currentFixedNode instanceof LoopEndNode) { + blockEndStates.put(currentFixedNode, currentBlock); + } else if (currentFixedNode instanceof EndNode) { + // add the end node and see if the merge is ready for processing + AbstractMergeNode merge = ((EndNode) currentFixedNode).merge(); + if (merge instanceof LoopBeginNode) { + Block toProcess = processLoop(merge, currentFixedNode, currentBlock, blockEndStates, nodeQueue, traversalHandler); + if (toProcess != null) { + currentBlock = toProcess; + } + } else { + if (endsVisited(merge, currentFixedNode, blockEndStates)) { + currentBlock = merge(merge, currentFixedNode, currentBlock, blockEndStates, nodeQueue, traversalHandler); + } else { + assert !blockEndStates.containsKey(currentFixedNode); + blockEndStates.put(currentFixedNode, currentBlock); + } + } + } + } else { + FixedNode firstSuccessor = (FixedNode) successors.next(); + if (!successors.hasNext()) { + if (currentFixedNode instanceof ControlSplitNode) { + // strange split with a single successor, do not record the block end + // state since we will immediately process the next block + currentBlock = traversalHandler.enqueBlockUnconditionally(firstSuccessor); + } + currentFixedNode = firstSuccessor; + continue; + } else { + // first direct successor + currentBlock = traversalHandler.enqueBlockUnconditionally(firstSuccessor); + nodeQueue.addLast((AbstractBeginNode) firstSuccessor); + blockEndStates.put(firstSuccessor, currentBlock); + do { + AbstractBeginNode successor = (AbstractBeginNode) successors.next(); + Block successorState = traversalHandler.enqueBlockUnconditionally(successor); + blockEndStates.put(successor, successorState); + nodeQueue.addLast(successor); + + } while (successors.hasNext()); + } + + } + } + if (nodeQueue.isEmpty()) { + return blockEndStates; + } else { + currentFixedNode = nodeQueue.removeFirst(); + assert blockEndStates.containsKey(currentFixedNode); + currentBlock = blockEndStates.removeKey(currentFixedNode); + } + } while (true); + } + + private static Block processLoop(AbstractMergeNode merge, FixedNode currentFixedNode, Block currentBlock, EconomicMap blockEndStates, Deque nodeQueue, + TraversalQueueHandler blockSplitter) { + + Block nextCurrentBlock = null; + LoopInfo loopInfo = blockSplitter.processLoop((LoopBeginNode) merge); + EconomicMap loopExitState = loopInfo.exitStates; + MapCursor entry = loopExitState.getEntries(); + + // process loop exit blocks in their increasing node id next + ArrayList lexs = new ArrayList<>(); + while (entry.advance()) { + blockEndStates.put(entry.getKey(), entry.getValue()); + lexs.add(entry.getKey()); + } + for (int i = lexs.size() - 1; i >= 0; i--) { + // process loop exits next + nodeQueue.addFirst(lexs.get(i)); + } + MapCursor naturalExits = loopInfo.naturalExits.getEntries(); + while (naturalExits.advance()) { + FixedNode naturalExit = naturalExits.getKey(); + if (naturalExit instanceof EndNode) { + blockEndStates.put(naturalExit, naturalExits.getValue()); + MergeNode mergeAfter = (MergeNode) ((EndNode) naturalExit).merge(); + if (endsVisited(mergeAfter, currentFixedNode, blockEndStates)) { + nextCurrentBlock = merge(mergeAfter, currentFixedNode, currentBlock, blockEndStates, nodeQueue, blockSplitter); + } + } else { + GraalError.shouldNotReachHere("Can only exit a loop " + merge + " naturally with a merge without a loop exit " + naturalExit); + } + } + + return nextCurrentBlock; + } + + private static boolean endsVisited(AbstractMergeNode merge, FixedNode currentFixedNode, EconomicMap blockEndStates) { + for (AbstractEndNode forwardEnd : merge.forwardEnds()) { + if (forwardEnd != currentFixedNode && !blockEndStates.containsKey(forwardEnd)) { + return false; + } + } + return true; + } + + private static Block merge(AbstractMergeNode merge, FixedNode currentFixedNode, Block currentBlock, EconomicMap blockEndStates, Deque nodeQueue, + TraversalQueueHandler blockSplitter) { + ArrayList states = new ArrayList<>(merge.forwardEndCount()); + for (int i = 0; i < merge.forwardEndCount(); i++) { + AbstractEndNode forwardEnd = merge.forwardEndAt(i); + assert forwardEnd == currentFixedNode || blockEndStates.containsKey(forwardEnd); + Block other = forwardEnd == currentFixedNode ? currentBlock : blockEndStates.removeKey(forwardEnd); + states.add(other); + } + Block nextCurrentBlock = blockSplitter.enqueBlockUnconditionally(merge); + nodeQueue.addLast(merge); + blockEndStates.put(merge, nextCurrentBlock); + return nextCurrentBlock; + } + + private static void computeLoopPredecessors(NodeMap nodeMap, Block block, LoopBeginNode loopBeginNode) { + int forwardEndCount = loopBeginNode.forwardEndCount(); + LoopEndNode[] loopEnds = loopBeginNode.orderedLoopEnds(); + Block[] predecessors = new Block[forwardEndCount + loopEnds.length]; + for (int i = 0; i < forwardEndCount; ++i) { + predecessors[i] = nodeMap.get(loopBeginNode.forwardEndAt(i)); + } + for (int i = 0; i < loopEnds.length; ++i) { + predecessors[i + forwardEndCount] = nodeMap.get(loopEnds[i]); + } + block.setPredecessors(predecessors); + } + + public static Block[] identifyBlocks(ControlFlowGraph cfg, int numBlocks) { + NodeMap nodeMap = cfg.getNodeToBlock(); + TraversalQueueHandler c = new TraversalQueueHandler(cfg, numBlocks); + Block startBlock = cfg.blockFor(cfg.graph.start()); + startBlock.setPredecessors(Block.EMPTY_ARRAY); + apply(c, cfg.graph.start(), startBlock, null); + if (Assertions.detailedAssertionsEnabled(cfg.graph.getOptions())) { + outer: for (Block b : nodeMap.getValues()) { + for (int i = 0; i < c.reversePostOrder.length; i++) { + if (c.reversePostOrder[i] == b) { + continue outer; + } + } + GraalError.shouldNotReachHere("No mapping in reverse post oder for block " + b); + } + for (int i = 0; i < c.reversePostOrder.length; i++) { + assert c.reversePostOrder[i] != null : "Null entry for block " + i + " Blocks " + Arrays.toString(c.reversePostOrder); + assert c.reversePostOrder[i].getPredecessors() != null : "Pred null for block " + c.reversePostOrder[i]; + assert c.reversePostOrder[i].getSuccessors() != null : "Succ null for block " + c.reversePostOrder[i]; + } + } + return c.reversePostOrder; + } + +} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DefaultLoopPolicies.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DefaultLoopPolicies.java index d8cf93ae83ea..bb77250f3c1c 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DefaultLoopPolicies.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DefaultLoopPolicies.java @@ -204,7 +204,7 @@ public boolean shouldPartiallyUnroll(LoopEx loop, CoreProviders providers) { int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count()); int unrollFactor = loopBegin.getUnrollFactor(); if (unrollFactor == 1) { - double loopFrequency = loopBegin.loopFrequency(); + double loopFrequency = loop.localLoopFrequency(); if (loopBegin.isSimpleLoop() && loopFrequency < 5.0) { loopBegin.getDebug().log(DebugContext.VERBOSE_LEVEL, "shouldPartiallyUnroll %s frequency too low %s ", loopBegin, loopFrequency); return false; @@ -239,7 +239,7 @@ public boolean shouldPartiallyUnroll(LoopEx loop, CoreProviders providers) { @Override public boolean shouldTryUnswitch(LoopEx loop) { LoopBeginNode loopBegin = loop.loopBegin(); - double loopFrequency = loopBegin.loopFrequency(); + double loopFrequency = loop.localLoopFrequency(); if (loopFrequency <= 1.0) { return false; } @@ -285,7 +285,7 @@ public UnswitchingDecision shouldUnswitch(LoopEx loop, List co int inBranchTotal = branchNodes.count(); CountingClosure stateNodesCount = new CountingClosure(); - double loopFrequency = loop.loopBegin().loopFrequency(); + double loopFrequency = loop.localLoopFrequency(); OptionValues options = loop.loopBegin().getOptions(); int maxDiff = Options.LoopUnswitchTrivial.getValue(options) + (int) (Options.LoopUnswitchFrequencyBoost.getValue(options) * (loopFrequency - 1.0 + phis)); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java index 9a48948cc5c8..a2b1ccc42269 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java @@ -57,6 +57,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; +import org.graalvm.compiler.nodes.ProfileData.ProfileSource; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; import org.graalvm.compiler.nodes.calc.CompareNode; @@ -90,6 +91,14 @@ protected LoopEx(Loop loop, LoopsData data) { this.data = data; } + public double localLoopFrequency() { + return data.getCFG().localLoopFrequency(loopBegin()); + } + + public ProfileSource localFrequencySource() { + return data.getCFG().localLoopFrequencySource(loopBegin()); + } + public Loop loop() { return loop; } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentInside.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentInside.java index fc7619bd48d2..2bb380b9789d 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentInside.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentInside.java @@ -233,7 +233,6 @@ public void insertWithinAfter(LoopEx loop, EconomicMap currentForwardEnds = currentMerge.forwardEnds(); @@ -130,7 +133,7 @@ private double handleMerge(FixedNode current, double relativeFrequency) { result += applyAsDouble(endNode); } if (current instanceof LoopBeginNode) { - result = multiplyRelativeFrequencies(result, ((LoopBeginNode) current).loopFrequency()); + result = multiplyRelativeFrequencies(result, cfg.localLoopFrequency(((LoopBeginNode) current))); } return result; } diff --git a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java index 343a6463af3c..6891f7af3e48 100644 --- a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java +++ b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java @@ -58,6 +58,7 @@ import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.FixedNode; +import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -246,6 +247,15 @@ public void nodeProperties(GraphInfo info, Node node, Map props) } } + if (info.cfg != null) { + if (node instanceof LoopBeginNode) { + // check if cfg is up to date + if (info.cfg.getLocalLoopFrequencyData().containsKey((LoopBeginNode) node)) { + props.put("localLoopFrequency", info.cfg.localLoopFrequency((LoopBeginNode) node)); + } + } + } + if (node instanceof ControlSinkNode) { props.put("category", "controlSink"); } else if (node instanceof ControlSplitNode) { diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/PartialEvaluator.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/PartialEvaluator.java index 305730f02adc..f3e588ee394a 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/PartialEvaluator.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/PartialEvaluator.java @@ -49,7 +49,6 @@ import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.SourceLanguagePosition; import org.graalvm.compiler.graph.SourceLanguagePositionProvider; -import org.graalvm.compiler.java.ComputeLoopFrequenciesClosure; import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; @@ -351,8 +350,6 @@ public final StructuredGraph evaluate(Request request) { inliningGraphPE(request); assert GraphOrder.assertSchedulableGraph(request.graph) : "PE result must be schedulable in order to apply subsequent phases"; truffleTier(request); - // recompute loop frequencies now that BranchProbabilities have been canonicalized - ComputeLoopFrequenciesClosure.compute(request.graph); applyInstrumentationPhases(request); handler.reportPerformanceWarnings(request.compilable, request.graph); if (request.task.isCancelled()) { diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/InstrumentBranchesPhaseTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/InstrumentBranchesPhaseTest.java index 7b89c3bba841..213c069afabb 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/InstrumentBranchesPhaseTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/InstrumentBranchesPhaseTest.java @@ -24,22 +24,23 @@ */ package org.graalvm.compiler.truffle.test; -import com.oracle.truffle.api.test.ReflectionUtils; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.truffle.compiler.PartialEvaluator; import org.graalvm.compiler.truffle.compiler.phases.InstrumentPhase; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.compiler.truffle.test.nodes.AbstractTestNode; import org.graalvm.compiler.truffle.test.nodes.RootTestNode; +import org.graalvm.polyglot.Context; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; -import org.graalvm.polyglot.Context; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import com.oracle.truffle.api.test.ReflectionUtils; public class InstrumentBranchesPhaseTest extends PartialEvaluationTest { @@ -52,11 +53,14 @@ public SimpleIfTestNode(int constant) { @Override public int execute(VirtualFrame frame) { + int res; if (constant < 0) { - return -1 * constant; + res = -1 * constant; } else { - return 1; + res = 1; } + GraalDirectives.controlFlowAnchor(); + return res; } } @@ -124,7 +128,7 @@ private InstrumentPhase.Instrumentation getInstrumentation(OptimizedCallTarget t public void twoIfsTest() { FrameDescriptor descriptor = new FrameDescriptor(); TwoIfsTestNode result = new TwoIfsTestNode(5, -1); - RootTestNode rootNode = new RootTestNode(descriptor, "twoIfsRoot", result); + RootTestNode rootNode = new RootTestNode(descriptor, "twoIfsRoot", result, true); OptimizedCallTarget target = compileHelper("twoIfsRoot", rootNode, new Object[0]); Assert.assertTrue(target.isValid()); // We run this twice to make sure that it comes first in the sorted access list. diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java index ba3a573974c7..5456c05dd8e9 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.ProfileData.ProfileSource; +import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.polyglot.Context; @@ -106,8 +107,9 @@ public void testLoopConditionProfile() { List loopBegins = graph.getNodes().filter(LoopBeginNode.class).snapshot(); Assert.assertEquals(loopBegins.toString(), 1, loopBegins.size()); + ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, false, false); for (LoopBeginNode loopBegin : loopBegins) { - Assert.assertEquals("Expected loop frequency", 10.0, loopBegin.loopFrequency(), 0.01); + Assert.assertEquals("Expected loop frequency", 10.0, cfg.localLoopFrequency(loopBegin), 0.01); } } @@ -129,8 +131,9 @@ public void testPrepareLoopForAOT() { List loopBegins = graph.getNodes().filter(LoopBeginNode.class).snapshot(); Assert.assertEquals(loopBegins.toString(), 1, loopBegins.size()); + ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, false, false); for (LoopBeginNode loopBegin : loopBegins) { - Assert.assertEquals("Expected loop frequency", 2.0, loopBegin.loopFrequency(), 0.01); + Assert.assertEquals("Expected loop frequency", 2.0, cfg.localLoopFrequency(loopBegin), 0.01); } target.compile(true); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/SimplePartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/SimplePartialEvaluationTest.java index 72a9ecce3660..78d0f7644e1b 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/SimplePartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/SimplePartialEvaluationTest.java @@ -225,8 +225,8 @@ public void unrollUntilReturnNestedLoopsContinueOuter01() { FrameDescriptor fd = new FrameDescriptor(); final int loopIterations = 2; UnrollingTestNode t = new UnrollingTestNode(loopIterations); - AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter01(), new ConstantTestNode(37)); - compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result), new Object[]{}); + AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter01(), new ConstantTestNode(37), true); + compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result, true), new Object[]{}); StructuredGraph peResult = lastCompiledGraph; Assert.assertEquals(UnrollingTestNode.INSIDE_LOOP_MARKER, 4, UnrollingTestNode.countBlackholeNodes(peResult, UnrollingTestNode.INSIDE_LOOP_MARKER)); @@ -238,8 +238,8 @@ public void unrollUntilReturnNestedLoopsContinueOuter02() { FrameDescriptor fd = new FrameDescriptor(); final int loopIterations = 2; UnrollingTestNode t = new UnrollingTestNode(loopIterations); - AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter02(), new ConstantTestNode(37)); - compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result), new Object[]{}); + AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter02(), new ConstantTestNode(37), true); + compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result, true), new Object[]{}); StructuredGraph peResult = lastCompiledGraph; Assert.assertEquals(UnrollingTestNode.INSIDE_LOOP_MARKER, 8, UnrollingTestNode.countBlackholeNodes(peResult, UnrollingTestNode.INSIDE_LOOP_MARKER)); @@ -251,8 +251,8 @@ public void unrollUntilReturnNestedLoopsContinueOuter03() { FrameDescriptor fd = new FrameDescriptor(); final int loopIterations = 2; UnrollingTestNode t = new UnrollingTestNode(loopIterations); - AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter03(), new ConstantTestNode(37)); - compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result), new Object[]{}); + AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter03(), new ConstantTestNode(37), true); + compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result, true), new Object[]{}); StructuredGraph peResult = lastCompiledGraph; Assert.assertEquals(UnrollingTestNode.INSIDE_LOOP_MARKER, 4, UnrollingTestNode.countBlackholeNodes(peResult, UnrollingTestNode.INSIDE_LOOP_MARKER)); @@ -264,8 +264,8 @@ public void unrollUntilReturnNestedLoopsContinueOuter04() { FrameDescriptor fd = new FrameDescriptor(); final int loopIterations = 2; UnrollingTestNode t = new UnrollingTestNode(loopIterations); - AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter04(), new ConstantTestNode(37)); - compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result), new Object[]{}); + AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter04(), new ConstantTestNode(37), true); + compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result, true), new Object[]{}); StructuredGraph peResult = lastCompiledGraph; Assert.assertEquals(UnrollingTestNode.INSIDE_LOOP_MARKER, 4, UnrollingTestNode.countBlackholeNodes(peResult, UnrollingTestNode.INSIDE_LOOP_MARKER)); @@ -277,8 +277,8 @@ public void unrollUntilReturnNestedLoopsContinueOuter05() { FrameDescriptor fd = new FrameDescriptor(); final int loopIterations = 2; UnrollingTestNode t = new UnrollingTestNode(loopIterations); - AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter05(), new ConstantTestNode(37)); - compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result), new Object[]{}); + AbstractTestNode result = new AddTestNode(t.new FullUnrollUntilReturnNestedLoopsContinueOuter05(), new ConstantTestNode(37), true); + compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result, true), new Object[]{}); StructuredGraph peResult = lastCompiledGraph; Assert.assertEquals(UnrollingTestNode.INSIDE_LOOP_MARKER, 6, UnrollingTestNode.countBlackholeNodes(peResult, UnrollingTestNode.INSIDE_LOOP_MARKER)); @@ -458,7 +458,7 @@ public void complexUnrollFullUnrollUntilReturn() { final int loopIterations = 5; UnrollingTestNode t = new UnrollingTestNode(loopIterations); AbstractTestNode result = new AddTestNode(t.new Unroll01(), new ConstantTestNode(37)); - compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result), new Object[]{}); + compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result, true), new Object[]{}); StructuredGraph peResult = lastCompiledGraph; //@formatter:off /* @@ -499,7 +499,7 @@ public void complexUnrollFullExplodeUntilReturn() throws Exception { final int loopIterations = 5; UnrollingTestNode t = new UnrollingTestNode(loopIterations); AbstractTestNode result = new AddTestNode(t.new Unroll02(), new ConstantTestNode(37)); - compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result), new Object[]{}); + compileHelper("Test", new RootTestNode(fd, "nestedLoopExplosion", result, true), new Object[]{}); StructuredGraph peResult = lastCompiledGraph; //@formatter:off diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/AddTestNode.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/AddTestNode.java index f2adf0c8001f..5ac71ed93ed8 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/AddTestNode.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/AddTestNode.java @@ -24,20 +24,32 @@ */ package org.graalvm.compiler.truffle.test.nodes; +import org.graalvm.compiler.api.directives.GraalDirectives; + import com.oracle.truffle.api.frame.VirtualFrame; public class AddTestNode extends AbstractTestNode { @Child private AbstractTestNode left; @Child private AbstractTestNode right; + private final boolean cfgAnchorBeforeReturn; - public AddTestNode(AbstractTestNode left, AbstractTestNode right) { + public AddTestNode(AbstractTestNode left, AbstractTestNode right, boolean cfgAnchorBeforeReturn) { this.left = left; this.right = right; + this.cfgAnchorBeforeReturn = cfgAnchorBeforeReturn; + } + + public AddTestNode(AbstractTestNode left, AbstractTestNode right) { + this(left, right, false); } @Override public int execute(VirtualFrame frame) { - return left.execute(frame) + right.execute(frame); + int res = left.execute(frame) + right.execute(frame); + if (cfgAnchorBeforeReturn) { + GraalDirectives.controlFlowAnchor(); + } + return res; } } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/RootTestNode.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/RootTestNode.java index 52832610d95e..a3ab16d791db 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/RootTestNode.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/RootTestNode.java @@ -24,6 +24,8 @@ */ package org.graalvm.compiler.truffle.test.nodes; +import org.graalvm.compiler.api.directives.GraalDirectives; + import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.NodeInfo; @@ -35,6 +37,7 @@ public class RootTestNode extends RootNode { private final String name; private final boolean internal; private final boolean captureFramesForTrace; + private final boolean cfgAnchorBeforeReturn; @Child private AbstractTestNode node; @@ -46,17 +49,30 @@ public RootTestNode(FrameDescriptor descriptor, String name, AbstractTestNode no this(descriptor, name, node, false, false); } + public RootTestNode(FrameDescriptor descriptor, String name, AbstractTestNode node, boolean cfgAnchorBeforeReturn) { + this(descriptor, name, node, false, false, cfgAnchorBeforeReturn); + } + public RootTestNode(FrameDescriptor descriptor, String name, AbstractTestNode node, boolean internal, boolean captureFramesForTrace) { + this(descriptor, name, node, captureFramesForTrace, internal, false); + } + + public RootTestNode(FrameDescriptor descriptor, String name, AbstractTestNode node, boolean internal, boolean captureFramesForTrace, boolean cfgAnchorBeforeReturn) { super(null, descriptor); this.name = name; this.node = node; this.internal = internal; this.captureFramesForTrace = captureFramesForTrace; + this.cfgAnchorBeforeReturn = cfgAnchorBeforeReturn; } @Override public Object execute(VirtualFrame frame) { - return node.execute(frame); + Object o = node.execute(frame); + if (cfgAnchorBeforeReturn) { + GraalDirectives.controlFlowAnchor(); + } + return o; } @Override diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/explosion/UnrollingTestNode.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/explosion/UnrollingTestNode.java index efa16263af76..180aa75cf7e5 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/explosion/UnrollingTestNode.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/nodes/explosion/UnrollingTestNode.java @@ -361,6 +361,7 @@ public int execute(VirtualFrame frame) { GraalDirectives.blackhole(OUTSIDE_LOOP_MARKER); GraalDirectives.blackhole(i); CompilerAsserts.partialEvaluationConstant(i); + GraalDirectives.controlFlowAnchor(); } outer: for (int i = 0; i < count; i++) { GraalDirectives.blackhole(OUTER_LOOP_INSIDE_LOOP_MARKER); @@ -376,6 +377,7 @@ public int execute(VirtualFrame frame) { SideEffect1 = x; continue outer; } + GraalDirectives.controlFlowAnchor(); if (j == SideEffect2) { GraalDirectives.blackhole(CONTINUE_LOOP_MARKER); CompilerAsserts.partialEvaluationConstant(j); @@ -385,6 +387,7 @@ public int execute(VirtualFrame frame) { SideEffect1 = x; break; } + GraalDirectives.controlFlowAnchor(); if (j == SideEffect1) { GraalDirectives.blackhole(CONTINUE_LOOP_MARKER); CompilerAsserts.partialEvaluationConstant(j); @@ -394,6 +397,7 @@ public int execute(VirtualFrame frame) { SideEffect1 = x; continue outer; } + GraalDirectives.controlFlowAnchor(); } } GraalDirectives.blackhole(AFTER_LOOP_MARKER); @@ -614,6 +618,7 @@ public int execute(VirtualFrame frame) { // LEX 1 -> constant number of loop iterations break; } + GraalDirectives.controlFlowAnchor(); GraalDirectives.blackhole(INSIDE_LOOP_MARKER); SideEffect = i; if (i == SideEffect2) { @@ -626,6 +631,7 @@ public int execute(VirtualFrame frame) { CompilerAsserts.partialEvaluationConstant(i); return i; } + GraalDirectives.controlFlowAnchor(); if (i == SideEffect3) { // LEN 1 -> continue at header // that is the difference of unroll vs explode:unrolling will merge the ends, @@ -633,13 +639,16 @@ public int execute(VirtualFrame frame) { i++; continue; } + GraalDirectives.controlFlowAnchor(); if (i == SideEffect1) { // LEX 3 (2) -> continue at AFTER_LOOP_MARKER break; } + GraalDirectives.controlFlowAnchor(); i++; // LEN 2 -> continue at header } + GraalDirectives.controlFlowAnchor(); GraalDirectives.blackhole(AFTER_LOOP_MARKER); return count; } From eb9403833b855cbc055726be7fa0fb5dfea6a5a2 Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Thu, 16 Sep 2021 16:24:40 +0200 Subject: [PATCH 095/681] fixes after rebase --- .../org/graalvm/compiler/core/test/IntegerBoxEqualsTest.java | 5 ++++- .../compiler/truffle/test/LoopNodePartialEvaluationTest.java | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerBoxEqualsTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerBoxEqualsTest.java index 97b8ab13cc99..50643b2ee0e7 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerBoxEqualsTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerBoxEqualsTest.java @@ -30,7 +30,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; -public class IntegerBoxEqualsTest extends SubprocessTest { +public class IntegerBoxEqualsTest extends GraalCompilerTest { class Cell { private final Integer value; @@ -65,6 +65,9 @@ public void cellTest() { test(get, null, cell, value); final int equalsCount = lastCompiledGraph.getNodes().filter(ObjectEqualsNode.class).count(); final int ifCount = lastCompiledGraph.getNodes().filter(IfNode.class).count(); + if (!(equalsCount == 0 || ifCount > 1)) { + lastCompiledGraph.getDebug().forceDump(lastCompiledGraph, "There must be no reference comparisons in the graph, or everything reachable in equals."); + } assertTrue(equalsCount == 0 || ifCount > 1, "There must be no reference comparisons in the graph, or everything reachable in equals."); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java index 5456c05dd8e9..7d909a7789f4 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java @@ -267,8 +267,9 @@ public void testPropagateInjectedProfile(boolean twoEnds, boolean trueContinue) List loopBegins = graph.getNodes().filter(LoopBeginNode.class).snapshot(); Assert.assertEquals(loopBegins.toString(), 1, loopBegins.size()); + ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, false, false); for (LoopBeginNode loopBegin : loopBegins) { - Assert.assertEquals("Expected loop frequency", 10.0, loopBegin.loopFrequency(), 0.01); + Assert.assertEquals("Expected loop frequency", 10.0, cfg.localLoopFrequency(loopBegin), 0.01); } } From 3837bf70f17bf32e524168b0a7ab283c7c714df9 Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Wed, 22 Sep 2021 10:53:04 +0200 Subject: [PATCH 096/681] update changelog version --- compiler/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/CHANGELOG.md b/compiler/CHANGELOG.md index 955871e68ff4..9dbdd4837d9d 100644 --- a/compiler/CHANGELOG.md +++ b/compiler/CHANGELOG.md @@ -2,7 +2,7 @@ This changelog summarizes newly introduced optimizations that may be relevant to other teams. -## Version 21.3.0 +## Version 22.0.0 * (GR-22707) (GR-30838): New, inner loops first, reverse post order and loop frequency calculations for the compiler. ## Version 21.2.0 From 840a0cbae4068b96e2c951308c09267f06bf034d Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Wed, 22 Sep 2021 10:59:22 +0200 Subject: [PATCH 097/681] integer box equals test: make test more resilient towards bad profiles --- .../compiler/core/test/IntegerBoxEqualsTest.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerBoxEqualsTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerBoxEqualsTest.java index 50643b2ee0e7..2d53f24f18f5 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerBoxEqualsTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerBoxEqualsTest.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.calc.ObjectEqualsNode; import org.junit.Test; @@ -40,11 +41,16 @@ class Cell { } public String check(Integer i) { - if (value == i || value.equals(i)) { - return ""; - } else { + b: { + if (GraalDirectives.injectBranchProbability(0.01, value == i)) { + break b; + } + if (value.equals(i)) { + break b; + } return "nope"; } + return ""; } } From 21174300c731ec37a8ee48232689b6034197b920 Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Wed, 22 Sep 2021 11:24:34 +0200 Subject: [PATCH 098/681] style fixes --- .../loop/phases/SpeculativeGuardMovementPhase.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java index 1d387a867079..b162697cc935 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java @@ -41,13 +41,13 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; +import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; +import org.graalvm.compiler.nodes.ProfileData.ProfileSource; import org.graalvm.compiler.nodes.ShortCircuitOrNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.StageFlag; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.WithExceptionNode; -import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; -import org.graalvm.compiler.nodes.ProfileData.ProfileSource; -import org.graalvm.compiler.nodes.StructuredGraph.StageFlag; import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.IntegerBelowNode; import org.graalvm.compiler.nodes.calc.IntegerConvertNode; @@ -421,7 +421,6 @@ private boolean shouldOptimizeCompare(InductionVariable iv, ValueNode bound, Gua return false; // the bound must be loop invariant and schedulable above the loop. } - LoopBeginNode loopBeginNode = loopEx.loopBegin(); CountedLoopInfo countedLoop = loopEx.counted(); if (profilingInfo != null && !(profilingInfo instanceof DefaultProfilingInfo)) { From 6d332cca0a226495cccd7e6df708e7e0b869af57 Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Thu, 23 Sep 2021 08:34:02 +0200 Subject: [PATCH 099/681] loop partial unroll: run canon without simplification to avoid simplifications destroying counted loops --- .../loop/phases/LoopPartialUnrollPhase.java | 109 ++++++++++-------- 1 file changed, 64 insertions(+), 45 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPartialUnrollPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPartialUnrollPhase.java index de173df37bd0..56fea99a1af7 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPartialUnrollPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPartialUnrollPhase.java @@ -47,63 +47,82 @@ public LoopPartialUnrollPhase(LoopPolicies policies, CanonicalizerPhase canonica this.canonicalizer = canonicalizer; } - @Override @SuppressWarnings("try") - protected void run(StructuredGraph graph, CoreProviders context) { - if (graph.hasLoops()) { - EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener(); - boolean changed = true; - EconomicMap opaqueUnrolledStrides = null; - boolean prePostInserted = false; - while (changed) { - changed = false; - try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) { - LoopsData dataCounted = context.getLoopsDataProvider().getLoopsData(graph); - dataCounted.detectedCountedLoops(); - Graph.Mark mark = graph.getMark(); - for (LoopEx loop : dataCounted.countedLoops()) { - if (!LoopTransformations.isUnrollableLoop(loop)) { - continue; - } - if (getPolicies().shouldPartiallyUnroll(loop, context)) { - if (loop.loopBegin().isSimpleLoop()) { - // First perform the pre/post transformation and do the partial - // unroll when we come around again. - LoopTransformations.insertPrePostLoops(loop); - prePostInserted = true; - changed = true; - } else if (prePostInserted) { - if (opaqueUnrolledStrides == null) { - opaqueUnrolledStrides = EconomicMap.create(Equivalence.IDENTITY); - } - LoopTransformations.partialUnroll(loop, opaqueUnrolledStrides); - changed = true; + private void unroll(StructuredGraph graph, CoreProviders context) { + /* + * We run a canonicalizer without simplification here because simplifications after + * inserting pre/main/post can make loops non-counted: For example the ifNode swap + * optimization can cause the counted condition being swapped with another one destroying + * counted loop info. + */ + final CanonicalizerPhase canonicalizerWithoutSimplification = canonicalizer.copyWithoutSimplification(); + EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener(); + boolean changed = true; + EconomicMap opaqueUnrolledStrides = null; + boolean prePostInserted = false; + while (changed) { + changed = false; + try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) { + LoopsData dataCounted = context.getLoopsDataProvider().getLoopsData(graph); + dataCounted.detectedCountedLoops(); + Graph.Mark mark = graph.getMark(); + for (LoopEx loop : dataCounted.countedLoops()) { + if (!LoopTransformations.isUnrollableLoop(loop)) { + continue; + } + if (getPolicies().shouldPartiallyUnroll(loop, context)) { + if (loop.loopBegin().isSimpleLoop()) { + // First perform the pre/post transformation and do the partial + // unroll when we come around again. + LoopTransformations.insertPrePostLoops(loop); + prePostInserted = true; + changed = true; + } else if (prePostInserted) { + if (opaqueUnrolledStrides == null) { + opaqueUnrolledStrides = EconomicMap.create(Equivalence.IDENTITY); } + LoopTransformations.partialUnroll(loop, opaqueUnrolledStrides); + changed = true; } } - dataCounted.deleteUnusedNodes(); - - if (!listener.getNodes().isEmpty()) { - canonicalizer.applyIncremental(graph, context, listener.getNodes()); - listener.getNodes().clear(); - } + } + dataCounted.deleteUnusedNodes(); - assert !prePostInserted || checkCounted(graph, context.getLoopsDataProvider(), mark); + if (!listener.getNodes().isEmpty()) { + canonicalizerWithoutSimplification.applyIncremental(graph, context, listener.getNodes()); + listener.getNodes().clear(); } + + assert !prePostInserted || checkCounted(graph, context.getLoopsDataProvider(), mark); } - if (opaqueUnrolledStrides != null) { - try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) { - for (OpaqueNode opaque : opaqueUnrolledStrides.getValues()) { - opaque.remove(); - } - if (!listener.getNodes().isEmpty()) { - canonicalizer.applyIncremental(graph, context, listener.getNodes()); - } + } + if (opaqueUnrolledStrides != null) { + try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) { + for (OpaqueNode opaque : opaqueUnrolledStrides.getValues()) { + opaque.remove(); + } + if (!listener.getNodes().isEmpty()) { + canonicalizer.applyIncremental(graph, context, listener.getNodes()); } } } } + @Override + @SuppressWarnings("try") + protected void run(StructuredGraph graph, CoreProviders context) { + EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener(); + if (graph.hasLoops()) { + try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) { + unroll(graph, context); + } + if (!listener.getNodes().isEmpty()) { + // run a regular canonicalization with simplification after the entire unrolling + canonicalizer.applyIncremental(graph, context, listener.getNodes()); + } + } + } + private static boolean checkCounted(StructuredGraph graph, LoopsDataProvider loopsDataProvider, Graph.Mark mark) { LoopsData dataCounted; dataCounted = loopsDataProvider.getLoopsData(graph); From 1b318313107791ecb146bdf84cbabfd74e5ade75 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 22 Sep 2021 14:42:34 +0200 Subject: [PATCH 100/681] compiler: unconditional deopts in snippets are not yet supported [GR-33909] --- .../replacements/arraycopy/ArrayCopySnippets.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index 3aa0459427d2..3e00988f67f4 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -48,7 +48,6 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; -import org.graalvm.compiler.nodes.UnreachableNode; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; @@ -246,8 +245,11 @@ public static void arraycopyNativeExceptionSnippet(Object src, int srcPos, Objec counters.systemArraycopyCopiedCounter.add(length); System.arraycopy(src, srcPos, dest, destPos, length); - // the call will never return - UnreachableNode.unreachable(); + /* + * Since the call will never return, we would want an Unreachable here. Unfortunately + * unconditional deopts are not yet supported in snippets [GR-33909]. + */ + // UnreachableNode.unreachable(); } /** From bc36bf66d5d2ab33384daaf823f5cfae8573c3cf Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Thu, 23 Sep 2021 14:33:29 +0200 Subject: [PATCH 101/681] Disable db-shootout on unsupported architectures (GR-33879) --- java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py index dd5c0d0ab500..7509c01151e1 100644 --- a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py +++ b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py @@ -1850,6 +1850,11 @@ def renaissanceIterations(self): del benchmarks["movie-lens"] del benchmarks["naive-bayes"] del benchmarks["page-rank"] + + if mx.get_arch() != "amd64": + # GR-33879 + # JNA libraries needed are currently limited to amd64: https://github.com/renaissance-benchmarks/renaissance/issues/153 + del benchmarks["db-shootout"] return benchmarks def version(self): @@ -1895,7 +1900,7 @@ def createCommandLineArgs(self, benchmarks, bmSuiteArgs): return (self.vmArgs(bmSuiteArgs) + ["-jar", self.renaissancePath()] + runArgs + [benchArg]) def benchmarkList(self, bmSuiteArgs): - return sorted(_renaissanceConfig.keys()) + return [b for b, it in self.renaissanceIterations().items() if it != -1] def successPatterns(self): return [] From a754ba1a599b2da975558f1b6203c5af7c113d4e Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Thu, 23 Sep 2021 14:49:19 +0200 Subject: [PATCH 102/681] Add JDK range check for renaissance benchmark filtering --- .../mx.java-benchmarks/mx_java_benchmarks.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py index 7509c01151e1..fcdf2b39f391 100644 --- a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py +++ b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py @@ -1838,7 +1838,9 @@ def renaissanceLibraryName(self): def renaissanceIterations(self): benchmarks = _renaissanceConfig.copy() if self.version() == "0.9.0": - del benchmarks["scala-doku"] # was introduced in 0.10.0 + # benchmark was introduced in 0.10.0 + del benchmarks["scala-doku"] + if mx.get_jdk().javaCompliance >= '17' and self.version() in ["0.9.0", "0.10.0", "0.11.0", "0.12.0"]: # JDK17 support for Spark benchmarks was added in 0.13.0 # See: https://github.com/renaissance-benchmarks/renaissance/issues/295 @@ -1851,10 +1853,17 @@ def renaissanceIterations(self): del benchmarks["naive-bayes"] del benchmarks["page-rank"] - if mx.get_arch() != "amd64": + if mx.get_arch() != "amd64" or mx.get_jdk().javaCompliance >= '11': # GR-33879 # JNA libraries needed are currently limited to amd64: https://github.com/renaissance-benchmarks/renaissance/issues/153 del benchmarks["db-shootout"] + + if self.version() in ["0.9.0", "0.10.0", "0.11.0"]: + if mx.get_jdk().javaCompliance >= '11': + del benchmarks["neo4j-analytics"] + else: + if mx.get_jdk().javaCompliance < '11' or mx.get_jdk().javaCompliance >= '15': + del benchmarks["neo4j-analytics"] return benchmarks def version(self): From d9f08d8184d0774fb2536e3064f25014179e5771 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 23 Sep 2021 16:47:23 +0200 Subject: [PATCH 103/681] Send toNative when memcpy-ing to native --- .../memory/ManagedMemMoveHelperNode.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/memory/ManagedMemMoveHelperNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/memory/ManagedMemMoveHelperNode.java index b13e220c24fe..eea2519f814a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/memory/ManagedMemMoveHelperNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/memory/ManagedMemMoveHelperNode.java @@ -31,15 +31,19 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached.Shared; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.llvm.runtime.except.LLVMPolyglotException; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.library.internal.LLVMManagedReadLibrary; import com.oracle.truffle.llvm.runtime.library.internal.LLVMManagedWriteLibrary; +import com.oracle.truffle.llvm.runtime.library.internal.LLVMNativeLibrary; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode; import com.oracle.truffle.llvm.runtime.nodes.memory.ManagedMemMoveHelperNodeGen.MemReadI16NodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.ManagedMemMoveHelperNodeGen.MemReadI32NodeGen; @@ -479,6 +483,41 @@ void doNativeI32(LLVMNativePointer target, long value, @SuppressWarnings("unused void doNativeI64(LLVMNativePointer target, long value, @SuppressWarnings("unused") int unitSize) { getLanguage().getLLVMMemory().putI64(this, target, value); } + + private static long asPointer(LLVMPointer value, LLVMNativeLibrary lib) { + if (!lib.isPointer(value)) { + lib.toNativePointer(value); + } + try { + return lib.asPointer(value); + } catch (UnsupportedMessageException e) { + throw CompilerDirectives.shouldNotReachHere(); + } + } + + @Specialization(guards = "unitSize == 1") + void doObjectI8(LLVMNativePointer target, LLVMPointer value, @SuppressWarnings("unused") int unitSize, + @Shared("lib") @CachedLibrary(limit = "3") LLVMNativeLibrary lib) { + getLanguage().getLLVMMemory().putI8(this, target, (byte) asPointer(value, lib)); + } + + @Specialization(guards = "unitSize == 2") + void doObjectI16(LLVMNativePointer target, LLVMPointer value, @SuppressWarnings("unused") int unitSize, + @Shared("lib") @CachedLibrary(limit = "3") LLVMNativeLibrary lib) { + getLanguage().getLLVMMemory().putI16(this, target, (short) asPointer(value, lib)); + } + + @Specialization(guards = "unitSize == 4") + void doObjectI32(LLVMNativePointer target, LLVMPointer value, @SuppressWarnings("unused") int unitSize, + @Shared("lib") @CachedLibrary(limit = "3") LLVMNativeLibrary lib) { + getLanguage().getLLVMMemory().putI32(this, target, (int) asPointer(value, lib)); + } + + @Specialization(guards = "unitSize == 8") + void doObjectI64(LLVMNativePointer target, LLVMPointer value, @SuppressWarnings("unused") int unitSize, + @Shared("lib") @CachedLibrary(limit = "3") LLVMNativeLibrary lib) { + getLanguage().getLLVMMemory().putI64(this, target, asPointer(value, lib)); + } } abstract static class MemWriteManaged extends MemWriteHelperNode { From 1c46cec2686acf82ffeb36c1dc624d3373a9f38b Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Wed, 22 Sep 2021 18:58:38 +0200 Subject: [PATCH 104/681] Extract field to local variable. --- .../com/oracle/truffle/object/DynamicObjectLibraryImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java index dade8737f479..dc14eb70e9dc 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java @@ -1736,7 +1736,8 @@ static class MutateCacheData extends CacheData { @Override protected boolean isValid() { - return newShapeValidAssumption == neverValidAssumption() || newShapeValidAssumption == alwaysValidAssumption() || newShapeValidAssumption.isValid(); + Assumption newShapeValid = newShapeValidAssumption; + return newShapeValid == neverValidAssumption() || newShapeValid == alwaysValidAssumption() || newShapeValid.isValid(); } protected void maybeUpdateShape(DynamicObject store) { From 846e2857d2decd210f35ee171680e4ce3e784544 Mon Sep 17 00:00:00 2001 From: Felix Berlakovich Date: Wed, 8 Sep 2021 13:26:31 +0200 Subject: [PATCH 105/681] Add option for working directory to SubprocessUtil --- .../graalvm/compiler/test/SubprocessUtil.java | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java b/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java index 14d3de8bd567..7de08a0d0103 100644 --- a/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java +++ b/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java @@ -278,7 +278,7 @@ public static Subprocess java(List vmArgs, String... mainClassAndArgs) t * @param mainClassAndArgs the main class and its arguments */ public static Subprocess java(List vmArgs, List mainClassAndArgs) throws IOException, InterruptedException { - return javaHelper(vmArgs, null, mainClassAndArgs, null); + return javaHelper(vmArgs, null, null, mainClassAndArgs, null); } /** @@ -289,7 +289,20 @@ public static Subprocess java(List vmArgs, List mainClassAndArgs * @param timeout the timeout duration until the process is killed */ public static Subprocess java(List vmArgs, List mainClassAndArgs, Duration timeout) throws IOException, InterruptedException { - return javaHelper(vmArgs, null, mainClassAndArgs, timeout); + return javaHelper(vmArgs, null, null, mainClassAndArgs, timeout); + } + + /** + * Executes a Java subprocess with a timeout in the specified working directory. + * + * @param vmArgs the VM arguments + * @param workingDir the working directory of the subprocess. If null, the working directory of + * the current process is used. + * @param mainClassAndArgs the main class and its arguments + * @param timeout the timeout duration until the process is killed + */ + public static Subprocess java(List vmArgs, File workingDir, List mainClassAndArgs, Duration timeout) throws IOException, InterruptedException { + return javaHelper(vmArgs, null, workingDir, mainClassAndArgs, timeout); } /** @@ -311,19 +324,23 @@ public static Subprocess java(List vmArgs, Map env, Stri * @param mainClassAndArgs the main class and its arguments */ public static Subprocess java(List vmArgs, Map env, List mainClassAndArgs) throws IOException, InterruptedException { - return javaHelper(vmArgs, env, mainClassAndArgs, null); + return javaHelper(vmArgs, env, null, mainClassAndArgs, null); } /** * Executes a Java subprocess. * - * @param vmArgs the VM arguments + * @param vmArgs the VM arguments. If {@code vmArgs} contains {@link #PACKAGE_OPENING_OPTIONS}, + * the argument is replaced with arguments to do package opening (see + * {@link SubprocessUtil#getPackageOpeningOptions()} * @param env the environment variables + * @param workingDir the working directory of the subprocess. If null, the working directory of + * the current process is used. * @param mainClassAndArgs the main class and its arguments * @param timeout the duration to wait for the process to finish. If null, the calling thread * waits for the process indefinitely. */ - private static Subprocess javaHelper(List vmArgs, Map env, List mainClassAndArgs, Duration timeout) throws IOException, InterruptedException { + private static Subprocess javaHelper(List vmArgs, Map env, File workingDir, List mainClassAndArgs, Duration timeout) throws IOException, InterruptedException { List command = new ArrayList<>(vmArgs.size()); Path packageOpeningOptionsArgumentsFile = null; for (String vmArg : vmArgs) { @@ -342,6 +359,9 @@ private static Subprocess javaHelper(List vmArgs, Map en } command.addAll(mainClassAndArgs); ProcessBuilder processBuilder = new ProcessBuilder(command); + if (workingDir != null) { + processBuilder.directory(workingDir); + } if (env != null) { Map processBuilderEnv = processBuilder.environment(); processBuilderEnv.putAll(env); From b62c298da649c92462bf45504d685c2c9ad9f65b Mon Sep 17 00:00:00 2001 From: Felix Berlakovich Date: Thu, 9 Sep 2021 22:02:50 +0200 Subject: [PATCH 106/681] Add generic method to launch non-java subprocess --- .../graalvm/compiler/test/SubprocessUtil.java | 80 +++++++++++-------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java b/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java index 7de08a0d0103..a512ad51ad75 100644 --- a/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java +++ b/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java @@ -358,6 +358,30 @@ private static Subprocess javaHelper(List vmArgs, Map en } } command.addAll(mainClassAndArgs); + try { + return process(command, env, workingDir, timeout); + } finally { + if (packageOpeningOptionsArgumentsFile != null) { + if (!Boolean.getBoolean(KEEP_TEMPORARY_ARGUMENT_FILES_PROPERTY_NAME)) { + Files.delete(packageOpeningOptionsArgumentsFile); + } + } + } + } + + /** + * Executes a command in a subprocess. + * + * @param command the command to be executed in a separate process. + * @param env environment variables of the subprocess. If null, no environment variables are + * passed. + * @param workingDir the working directory of the subprocess. If null, the working directory of + * the current process is used. + * @param timeout the duration to wait for the process to finish. When the timeout is reached, + * the subprocess is terminated forcefully. If the timeout is null, the calling + * thread waits for the process indefinitely. + */ + public static Subprocess process(List command, Map env, File workingDir, Duration timeout) throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder(command); if (workingDir != null) { processBuilder.directory(workingDir); @@ -367,40 +391,32 @@ private static Subprocess javaHelper(List vmArgs, Map en processBuilderEnv.putAll(env); } processBuilder.redirectErrorStream(true); - try { - Process process = processBuilder.start(); - BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream())); - List output = new ArrayList<>(); - if (timeout == null) { - String line; - while ((line = stdout.readLine()) != null) { - output.add(line); - } - return new Subprocess(command, env, process.waitFor(), output, false); - } else { - // The subprocess might produce output forever. We need to grab the output in a - // separate thread, so we can terminate the process after the timeout if necessary. - Thread outputReader = new Thread(() -> { - try { - String line; - while ((line = stdout.readLine()) != null) { - output.add(line); - } - } catch (IOException e) { - // happens when the process ends - } - }); - outputReader.start(); - boolean finishedOnTime = process.waitFor(timeout.getSeconds(), TimeUnit.SECONDS); - int exitCode = process.destroyForcibly().waitFor(); - return new Subprocess(command, env, exitCode, output, !finishedOnTime); + Process process = processBuilder.start(); + BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream())); + List output = new ArrayList<>(); + if (timeout == null) { + String line; + while ((line = stdout.readLine()) != null) { + output.add(line); } - } finally { - if (packageOpeningOptionsArgumentsFile != null) { - if (!Boolean.getBoolean(KEEP_TEMPORARY_ARGUMENT_FILES_PROPERTY_NAME)) { - Files.delete(packageOpeningOptionsArgumentsFile); + return new Subprocess(command, env, process.waitFor(), output, false); + } else { + // The subprocess might produce output forever. We need to grab the output in a + // separate thread, so we can terminate the process after the timeout if necessary. + Thread outputReader = new Thread(() -> { + try { + String line; + while ((line = stdout.readLine()) != null) { + output.add(line); + } + } catch (IOException e) { + // happens when the process ends } - } + }); + outputReader.start(); + boolean finishedOnTime = process.waitFor(timeout.getSeconds(), TimeUnit.SECONDS); + int exitCode = process.destroyForcibly().waitFor(); + return new Subprocess(command, env, exitCode, output, !finishedOnTime); } } From 5a2fa17cd10391de1b22cb127197997edb804ee8 Mon Sep 17 00:00:00 2001 From: Felix Berlakovich Date: Mon, 13 Sep 2021 14:32:45 +0200 Subject: [PATCH 107/681] Fix race condition in SubprocessUtil output handling --- .../src/org/graalvm/compiler/test/SubprocessUtil.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java b/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java index a512ad51ad75..a44688f1b45e 100644 --- a/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java +++ b/compiler/src/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java @@ -415,8 +415,11 @@ public static Subprocess process(List command, Map env, }); outputReader.start(); boolean finishedOnTime = process.waitFor(timeout.getSeconds(), TimeUnit.SECONDS); - int exitCode = process.destroyForcibly().waitFor(); - return new Subprocess(command, env, exitCode, output, !finishedOnTime); + if (!finishedOnTime) { + process.destroyForcibly().waitFor(); + } + outputReader.join(); + return new Subprocess(command, env, process.exitValue(), output, !finishedOnTime); } } From 51a681f6320e1abec4c27772907f96881b81115a Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Thu, 23 Sep 2021 18:47:43 +0200 Subject: [PATCH 108/681] [GR-33933] HostClassLoader does not provide ProtectionDomain. --- .../test/polyglot/HostClassLoadingTest.java | 36 +++++++++++++ .../oracle/truffle/host/HostClassLoader.java | 50 +++++++++++++++---- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostClassLoadingTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostClassLoadingTest.java index da4b3226fbfa..2391d513263a 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostClassLoadingTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostClassLoadingTest.java @@ -58,6 +58,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; +import java.security.CodeSource; +import java.security.ProtectionDomain; import java.util.Collections; import java.util.Comparator; import java.util.concurrent.atomic.AtomicInteger; @@ -388,6 +390,40 @@ public void testResourceBundleFolder() throws IOException { } } + @Test + public void testProtectionDomainJar() throws IOException { + setupEnv(); + Class hostClass = HostClassLoadingTestClass1.class; + Path tempDir = renameHostClass(hostClass, TEST_REPLACE_CLASS_NAME); + Path jar = createJar(tempDir); + languageEnv.addToHostClassPath(languageEnv.getPublicTruffleFile(jar.toString())); + Object newSymbol = languageEnv.lookupHostSymbol(hostClass.getPackage().getName() + "." + TEST_REPLACE_CLASS_NAME); + Class clz = (Class) languageEnv.asHostObject(newSymbol); + ProtectionDomain protectionDomain = clz.getProtectionDomain(); + assertNotNull(protectionDomain); + CodeSource codeSource = protectionDomain.getCodeSource(); + assertNotNull(codeSource); + assertEquals(jar.toUri().toURL().toString(), codeSource.getLocation().toString()); + Files.deleteIfExists(jar); + deleteDir(tempDir); + } + + @Test + public void testProtectionDomainFolder() throws IOException { + setupEnv(); + Class hostClass = HostClassLoadingTestClass1.class; + Path tempDir = renameHostClass(hostClass, TEST_REPLACE_CLASS_NAME); + languageEnv.addToHostClassPath(languageEnv.getPublicTruffleFile(tempDir.toString())); + Object newSymbol = languageEnv.lookupHostSymbol(hostClass.getPackage().getName() + "." + TEST_REPLACE_CLASS_NAME); + Class clz = (Class) languageEnv.asHostObject(newSymbol); + ProtectionDomain protectionDomain = clz.getProtectionDomain(); + assertNotNull(protectionDomain); + CodeSource codeSource = protectionDomain.getCodeSource(); + assertNotNull(codeSource); + assertEquals(tempDir.toUri().toURL().toString(), codeSource.getLocation().toString()); + deleteDir(tempDir); + } + private static void assertHostClassPath(Env env, final Class hostClass, String newName, TruffleFile classPathEntry) { String newClassName = hostClass.getPackage().getName() + "." + newName; diff --git a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassLoader.java b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassLoader.java index b5f3bfe1ff29..d6f5a7565cac 100644 --- a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassLoader.java +++ b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassLoader.java @@ -54,6 +54,9 @@ import java.nio.ByteOrder; import java.nio.channels.SeekableByteChannel; import java.nio.file.StandardOpenOption; +import java.security.CodeSigner; +import java.security.CodeSource; +import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -157,7 +160,7 @@ protected Class findClass(String className) throws ClassNotFoundException { try { byte[] content = res.getContent(); definePackage(className); - return defineClass(className, content, 0, content.length); + return defineClass(className, content, 0, content.length, res.getProtectionDomain()); } catch (IOException ioe) { throw new ClassNotFoundException("Cannot load class: " + className, ioe); } @@ -223,12 +226,22 @@ private static String getPackageName(String className) { private abstract static class Resource { + private final ProtectionDomain protectionDomain; + + Resource(ProtectionDomain protectionDomain) { + this.protectionDomain = protectionDomain; + } + abstract URL getURL(); abstract long getLength() throws IOException; abstract InputStream getInputStream() throws IOException; + final ProtectionDomain getProtectionDomain() { + return protectionDomain; + } + byte[] getContent() throws IOException { long lenl = getLength(); if (lenl > Integer.MAX_VALUE) { @@ -273,8 +286,23 @@ byte[] getContent() throws IOException { } } - private interface Loader extends Closeable { - Resource findResource(String name); + private abstract static class Loader implements Closeable { + + final TruffleFile root; + final ProtectionDomain protectionDomain; + + Loader(TruffleFile root) { + this.root = root; + URL rootURL; + try { + rootURL = root.toUri().toURL(); + } catch (MalformedURLException e) { + rootURL = null; + } + this.protectionDomain = rootURL == null ? null : new ProtectionDomain(new CodeSource(rootURL, (CodeSigner[]) null), null); + } + + abstract Resource findResource(String name); } private static final class ResourceURLStreamHandler extends URLStreamHandler { @@ -300,11 +328,10 @@ public InputStream getInputStream() throws IOException { } } - private static final class FolderLoader implements Loader { - private final TruffleFile root; + private static final class FolderLoader extends Loader { FolderLoader(TruffleFile root) { - this.root = root; + super(root); } @Override @@ -313,7 +340,8 @@ public Resource findResource(String name) { if (!file.isRegularFile()) { return null; } - return new Resource() { + return new Resource(protectionDomain) { + @Override public URL getURL() { try { @@ -345,15 +373,15 @@ public void close() throws IOException { } } - private static final class JarLoader implements Loader { - private final TruffleFile root; + private static final class JarLoader extends Loader { + /** * Cache for fast resource lookup. Map of folder to files in the folder. */ private volatile Map> content; JarLoader(TruffleFile root) { - this.root = root; + super(root); } @Override @@ -369,7 +397,7 @@ public Resource findResource(String name) { return null; } - return new Resource() { + return new Resource(protectionDomain) { @Override URL getURL() { From 3a22e5bdeded804efe20275458f076de9df4fed0 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 23 Sep 2021 19:18:49 +0200 Subject: [PATCH 109/681] Inherit user declared constructor parameter annotations and copy them to generated node create factory methods. --- truffle/CHANGELOG.md | 4 + .../truffle/api/dsl/test/NodeFieldTest.java | 87 +++++++++++++++++++ .../processor/generator/GeneratorUtils.java | 2 +- 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index ebd44af3e83a..ef1717fe3721 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -2,6 +2,10 @@ This changelog summarizes major changes between Truffle versions relevant to languages implementors building upon the Truffle framework. The main focus is on APIs exported by Truffle. +## Version 22.0.0 +* Truffle DSL generated code now inherits all annotations on constructor parameters to the static create factory method. + + ## Version 21.3.0 * Added a `@GenerateWrapper.Ignore` annotation to prevent methods from being instrumented in wrapper classes. * The native image `TruffleCheckBlackListedMethods` option was deprecated and replaced by the `TruffleCheckBlockListMethods` option. diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java index 8b0b1536a284..b9728b27e861 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java @@ -43,13 +43,20 @@ import static com.oracle.truffle.api.dsl.test.TestHelper.createCallTarget; import static com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest.assertFails; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; + import org.junit.Test; import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.NodeField; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ConstructorAnnotationsTestNodeGen; import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory; import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory; import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.MultipleFieldsTestNodeFactory; @@ -295,4 +302,84 @@ Object s0() { } } + @Retention(RetentionPolicy.RUNTIME) + @interface OtherAnnotations { + + OtherAnnotation[] value(); + + } + + @Repeatable(OtherAnnotations.class) + @Retention(RetentionPolicy.RUNTIME) + @interface OtherAnnotation { + + } + + @Retention(RetentionPolicy.RUNTIME) + @interface MyAnnotation { + + String string(); + + String[] stringArray(); + + int primitive(); + + int[] primitiveArray(); + + Class type(); + + Class[] typeArray(); + + OtherAnnotation annotation(); + + OtherAnnotation[] annotationArray(); + + } + + public abstract static class ConstructorAnnotationsTestNode extends Node { + + private final int field; + + ConstructorAnnotationsTestNode(@MyAnnotation(string = "42", stringArray = {"41", "42"}, // + primitive = 42, primitiveArray = {41, 42}, // + type = ConstructorAnnotationsTestNode.class, // + typeArray = {ConstructorAnnotationsTestNode.class, ConstructorAnnotationsTestNode.class}, // + annotation = @OtherAnnotation, // + annotationArray = {@OtherAnnotation, @OtherAnnotation}) int arg0, + @OtherAnnotation @OtherAnnotation int arg1) { // also test repeatable + this.field = arg0 + arg1; + } + + abstract Object execute(); + + @Specialization + int s0() { + return field; + } + } + + @Test + public void testConstructorAnnotations() throws NoSuchMethodException, SecurityException { + assertEquals(42, ConstructorAnnotationsTestNodeGen.create(21, 21).execute()); + Method method = ConstructorAnnotationsTestNodeGen.class.getMethod("create", int.class, int.class); + MyAnnotation annotation = method.getParameters()[0].getAnnotation(MyAnnotation.class); + assertEquals("42", annotation.string()); + assertEquals("41", annotation.stringArray()[0]); + assertEquals("42", annotation.stringArray()[1]); + assertEquals(42, annotation.primitive()); + assertEquals(41, annotation.primitiveArray()[0]); + assertEquals(42, annotation.primitiveArray()[1]); + assertSame(ConstructorAnnotationsTestNode.class, annotation.type()); + assertSame(ConstructorAnnotationsTestNode.class, annotation.typeArray()[0]); + assertSame(ConstructorAnnotationsTestNode.class, annotation.typeArray()[1]); + + assertNotNull(annotation.annotation()); + assertNotNull(annotation.annotationArray()[0]); + assertNotNull(annotation.annotationArray()[1]); + + OtherAnnotations other = method.getParameters()[1].getAnnotation(OtherAnnotations.class); + assertNotNull(other.value()[0]); + assertNotNull(other.value()[1]); + } + } diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java index 1fcd50c9785c..2c7bc75d09ce 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java @@ -209,7 +209,7 @@ public static CodeExecutableElement createConstructorUsingFields(Set m builder.startStatement(); builder.startSuperCall(); for (VariableElement parameter : superConstructor.getParameters()) { - method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString())); + method.addParameter(CodeVariableElement.clone(parameter)); builder.string(parameter.getSimpleName().toString()); } builder.end(); // super From fc02a67fd8422e969a8762b1145d21d4b47a5aa8 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Thu, 23 Sep 2021 21:19:08 +0200 Subject: [PATCH 110/681] Fix blockSizes array length in partial blocks computation. --- .../truffle/runtime/OptimizedBlockNode.java | 12 +++++-- .../truffle/test/OptimizedBlockNodeTest.java | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedBlockNode.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedBlockNode.java index 723b319415a7..f49f7851c0eb 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedBlockNode.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedBlockNode.java @@ -320,10 +320,18 @@ private static PartialBlocks computePartialBlocks(OptimizedC if (i > 0) { if (blockRanges == null) { blockRanges = new int[8]; - blockSizes = new int[8]; + /* + * blockSizes array needs one more slot than blockRanges because of the + * assignment below the for-loop. + */ + blockSizes = new int[blockRanges.length + 1]; } else if (currentBlockIndex >= blockRanges.length) { blockRanges = Arrays.copyOf(blockRanges, blockRanges.length * 2); - blockSizes = Arrays.copyOf(blockSizes, blockSizes.length * 2); + /* + * blockSizes array needs one more slot than blockRanges because of the + * assignment below the for-loop. + */ + blockSizes = Arrays.copyOf(blockSizes, blockRanges.length + 1); } blockSizes[currentBlockIndex] = currentBlockSize; blockRanges[currentBlockIndex++] = i; diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedBlockNodeTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedBlockNodeTest.java index ec5d8bb04f85..67fcc6961b86 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedBlockNodeTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedBlockNodeTest.java @@ -104,6 +104,38 @@ public void testFirstBlockElementExceedsLimit() { assertEquals(1, target.call()); } + @Test + public void testBoundaryBlockSize() { + /* + * Internal blockRanges and blockSizes arrays grow during partial blocks computation as + * needed. This test tests that the growth of the arrays works correctly. + */ + for (int blockSize = 2; blockSize < 20; blockSize++) { + setup(1); + OptimizedBlockNode block = createBlock(blockSize, 1); + OptimizedCallTarget target = createTest(block); + target.computeBlockCompilations(); + target.call(); + target.compile(true); + + // should not trigger and block compilation + PartialBlocks partialBlocks = block.getPartialBlocks(); + assertNotNull(partialBlocks); + assertNotNull(partialBlocks.getBlockRanges()); + assertEquals(blockSize - 1, partialBlocks.getBlockRanges().length); + for (int i = 0; i < (blockSize - 1); i++) { + assertEquals(i + 1, partialBlocks.getBlockRanges()[i]); + } + assertNotNull(partialBlocks.getBlockTargets()); + assertEquals(blockSize, partialBlocks.getBlockTargets().length); + for (int i = 0; i < blockSize; i++) { + assertTrue(partialBlocks.getBlockTargets()[i].isValid()); + } + + assertEquals(blockSize - 1, target.call()); + } + } + @Test public void testBlockSizePlusOne() { int groupSize = 1; From c623a19f2d44ba3f6d2d460aceb5e9578bddb516 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 22 Sep 2021 15:08:02 +0200 Subject: [PATCH 111/681] compiler: verify snippet has returnNode [GR-33909]. --- .../compiler/replacements/SnippetTemplate.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index 7dd3066e6bcb..ada40300aa07 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -1601,6 +1601,17 @@ public UnmodifiableEconomicMap instantiate(MetaAccessProvider metaAc */ @SuppressWarnings("try") public UnmodifiableEconomicMap instantiate(MetaAccessProvider metaAccess, FixedNode replacee, UsageReplacer replacer, Arguments args, boolean killReplacee) { + if (!(replacee instanceof ControlSinkNode)) { + /* + * For all use cases of this, the replacee is killed sooner ({@code killReplacee == + * true}) or later (by the caller of this method). However, we cannot do that if the + * snippet does not have a return node we because that means we kill the {@code + * replacee.next()} which might be connected to a merge whose next node has not yet been + * lowered [GR-33909]. + */ + GraalError.guarantee(this.returnNode != null, "Cannot kill %s because snippet %s does not have a return node", replacee, this); + } + DebugContext debug = replacee.getDebug(); assert assertSnippetKills(replacee); try (DebugCloseable a = args.info.instantiationTimer.start(debug)) { From 15dd587fd17bf2a5187dcd0a12ce5b75dbed2cb8 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 23 Sep 2021 13:45:50 +0200 Subject: [PATCH 112/681] Revert "compiler: unconditional deopts in snippets are not yet supported [GR-33909]" This reverts commit 477c0dae39a7c1ecec5d84d4d72569f45f9a05b5. --- .../replacements/arraycopy/ArrayCopySnippets.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index 3e00988f67f4..3aa0459427d2 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -48,6 +48,7 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; +import org.graalvm.compiler.nodes.UnreachableNode; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; @@ -245,11 +246,8 @@ public static void arraycopyNativeExceptionSnippet(Object src, int srcPos, Objec counters.systemArraycopyCopiedCounter.add(length); System.arraycopy(src, srcPos, dest, destPos, length); - /* - * Since the call will never return, we would want an Unreachable here. Unfortunately - * unconditional deopts are not yet supported in snippets [GR-33909]. - */ - // UnreachableNode.unreachable(); + // the call will never return + UnreachableNode.unreachable(); } /** From 41c189caf11ffa9d5f452c23cc6d93503d046fb7 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 24 Sep 2021 10:21:32 +0200 Subject: [PATCH 113/681] Add test --- .../interop/polyglotArrayToNative.c | 60 ++++++ .../interop/PolyglotArrayToNativeTest.java | 177 ++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotArrayToNative.c create mode 100644 sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotArrayToNative.c b/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotArrayToNative.c new file mode 100644 index 000000000000..9825627b3496 --- /dev/null +++ b/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotArrayToNative.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#include + +typedef void* VoidPtr; + +typedef struct { + void *payload; +} Simple; + +POLYGLOT_DECLARE_TYPE(Simple); +POLYGLOT_DECLARE_TYPE(VoidPtr); + +void get_Simple_typeid(void (*ret)(polyglot_typeid typeid)) { + ret(polyglot_Simple_typeid()); +} + +void get_Simple_array_typeid(uint64_t len, void (*ret)(polyglot_typeid typeid)) { + ret(polyglot_array_typeid(polyglot_VoidPtr_typeid(), len)); +} + +#define WRAP(x) ((Simple){(x)}) + +void *simple_array_to_native(VoidPtr *polyglot_array, uint64_t size) { + Simple *native = (Simple *) malloc(size * sizeof(Simple)); + uint64_t i; + for (i = 0; i < size; i++) { + native[i] = WRAP(polyglot_array[i]); + } + return polyglot_from_Simple_array(native, size); +} diff --git a/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java b/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java new file mode 100644 index 000000000000..5d88781a2025 --- /dev/null +++ b/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java @@ -0,0 +1,177 @@ +package com.oracle.truffle.llvm.tests.interop; + +import org.graalvm.polyglot.Value; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.exception.AbstractTruffleException; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.llvm.spi.NativeTypeLibrary; +import com.oracle.truffle.llvm.tests.interop.values.TestCallback; + +public class PolyglotArrayToNativeTest extends PolyglotArrayTestBase { + public static final String PAYLOAD = "payload"; + public static final int ARRAY_SIZE = 10; + private static Value polyglotReadPointerLibrary; + private static Object pointerTypeId; + private static Value getArrayType; + + /** + * Load bitcode library. Method name needs to be different than in the base class, otherwise it + * is not executed. + */ + @BeforeClass + public static void loadPolygloArrayToNativeLibrary() { + polyglotReadPointerLibrary = loadTestBitcodeValue("polyglotArrayToNative.c"); + Value lib = runWithPolyglot.getPolyglotContext().asValue(polyglotReadPointerLibrary); + Value getTypes = lib.getMember("get_Simple_typeid"); + + getTypes.execute(new TestCallback(1, args -> { + pointerTypeId = args[0]; + return null; + })); + + getArrayType = lib.getMember("get_Simple_array_typeid"); + + } + + @ExportLibrary(InteropLibrary.class) + @ExportLibrary(value = NativeTypeLibrary.class, useForAOT = false) + @SuppressWarnings("static-method") + static class SimpleWrapper implements TruffleObject { + private final long delegate; + + private SimpleWrapper(long l) { + this.delegate = l; + } + + @ExportMessage + boolean hasMembers() { + return true; + } + + @ExportMessage + Object getMembers(@SuppressWarnings("unused") boolean b) { + throw CompilerDirectives.shouldNotReachHere(); + } + + @ExportMessage + boolean isMemberReadable(String key) { + return PAYLOAD.equals(key); + } + + @ExportMessage + Object readMember(String key) throws UnknownIdentifierException { + if (PAYLOAD.equals(key)) { + return delegate; + } + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw UnknownIdentifierException.create(key); + } + + @ExportMessage + boolean isPointer() { + return true; + } + + @ExportMessage + void toNative() { + // nop + } + + @ExportMessage + long asPointer() { + return delegate; + } + + @ExportMessage + boolean hasNativeType() { + return true; + } + + @ExportMessage + Object getNativeType() { + return pointerTypeId; + } + } + + @ExportLibrary(value = NativeTypeLibrary.class, useForAOT = false) + @ExportLibrary(InteropLibrary.class) + @SuppressWarnings("static-method") + static class SimpleArrayWrapper implements TruffleObject { + private final SimpleWrapper[] objects; + + private SimpleArrayWrapper(SimpleWrapper[] objects) { + this.objects = objects; + } + + @ExportMessage + boolean hasArrayElements() { + return true; + } + + @ExportMessage + boolean isArrayElementReadable(long idx) { + return 0 <= idx && idx < objects.length; + } + + @ExportMessage + long getArraySize() { + return objects.length; + } + + @ExportMessage + Object readArrayElement(long idx) { + return objects[(int) idx]; + } + + @ExportMessage + boolean hasNativeType() { + return true; + } + + @ExportMessage + Object getNativeType() { + try { + Object[] result = new Object[1]; + getArrayType.execute((long) objects.length, new TestCallback(1, args -> { + result[0] = args[0]; + return null; + })); + return result[0]; + } catch (AbstractTruffleException e) { + throw CompilerDirectives.shouldNotReachHere(e); + } + } + } + + @Test + public void test() { + Value read = polyglotReadPointerLibrary.getMember("simple_array_to_native"); + Assert.assertNotNull("Function not found: simple_array_to_native", read); + SimpleWrapper[] objects = new SimpleWrapper[ARRAY_SIZE]; + for (int i = 0; i < ARRAY_SIZE; i++) { + objects[i] = new SimpleWrapper(i); + } + Value ret = read.execute(new SimpleArrayWrapper(objects), (long) ARRAY_SIZE); + Assert.assertTrue(ret.hasArrayElements()); + Assert.assertEquals(ARRAY_SIZE, ret.getArraySize()); + /* + * 'ret' is of type 'Simple[]'; and 'Simple' is a struct with one field 'void *payload'. We + * want to have the int value of the pointer. + */ + for (int i = 0; i < ARRAY_SIZE; i++) { + Value arrayElement = ret.getArrayElement(i); + Assert.assertTrue(arrayElement.hasMember(PAYLOAD)); + Value payload = arrayElement.getMember(PAYLOAD); + Assert.assertTrue(payload.isNativePointer()); + Assert.assertEquals(i, payload.asNativePointer()); + } + } +} \ No newline at end of file From a88c591b157c0cb31a36aa17109224086ea86cd7 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 26 Aug 2020 12:53:50 +0200 Subject: [PATCH 114/681] Each CallTarget should have its own RootNode for InterpreterCallBenchmark * Remove unused state class. --- .../benchmark/InterpreterCallBenchmark.java | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/InterpreterCallBenchmark.java b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/InterpreterCallBenchmark.java index 43f595c7d6dc..7ba718f6d1ec 100644 --- a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/InterpreterCallBenchmark.java +++ b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/InterpreterCallBenchmark.java @@ -85,11 +85,7 @@ public static class BenchmarkState { for (int i = 0; i < ROOT_CLASSES.length; i++) { Class rootClass = ROOT_CLASSES[i]; - try { - rootNodes[i] = (AbstractRootNode) rootClass.getConstructor().newInstance(); - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { - throw new AssertionError(e); - } + rootNodes[i] = createRootNode(rootClass); callTargets[i] = Truffle.getRuntime().createCallTarget(rootNodes[i]); directCallNodes[i] = Truffle.getRuntime().createDirectCallNode(callTargets[i]); } @@ -98,6 +94,14 @@ public static class BenchmarkState { indirectCall = Truffle.getRuntime().createIndirectCallNode(); } + protected static AbstractRootNode createRootNode(Class rootClass) { + try { + return (AbstractRootNode) rootClass.getConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { + throw new AssertionError(e); + } + } + @TearDown public void tearDown() { context.leave(); @@ -133,7 +137,8 @@ public static class FirstCallState extends BenchmarkState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < TARGETS; i++) { - callTargets[i] = Truffle.getRuntime().createCallTarget(rootNodes[i % rootNodes.length]); + AbstractRootNode rootNode = createRootNode(ROOT_CLASSES[i % ROOT_CLASSES_LENGTH]); + callTargets[i] = Truffle.getRuntime().createCallTarget(rootNode); } } @@ -180,20 +185,6 @@ public int secondCall(SecondCallState state) { return sum; } - @State(Scope.Thread) - public static class CallTargetCreateState extends BenchmarkState { - - final CallTarget[] callTargets = new CallTarget[TARGETS]; - - @Setup(Level.Invocation) - public void setup() { - for (int i = 0; i < TARGETS; i++) { - callTargets[i] = Truffle.getRuntime().createCallTarget(rootNodes[i % rootNodes.length]); - } - } - - } - @Benchmark public Object callTargetCreate() { return Truffle.getRuntime().createCallTarget(new RootNode1()); From 31d315e9386ba88b5be936d393f2498072fe09e4 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Thu, 9 Sep 2021 13:43:14 +0200 Subject: [PATCH 115/681] Extend JavaDoc for TruffleRuntime::iterateFrames. --- .../src/com/oracle/truffle/api/TruffleRuntime.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java index bb8183c717f1..55d8a713fbcf 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java @@ -43,6 +43,7 @@ import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameInstance; +import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; import com.oracle.truffle.api.frame.FrameInstanceVisitor; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; @@ -167,6 +168,14 @@ public interface TruffleRuntime { * every {@link FrameInstance}, returns null. Any non-null result of the visitor indicates that * frame iteration should stop. * + *

    + * Note that this method can cause deoptimization if + * {@link FrameInstance#getFrame(FrameInstance.FrameAccess)} is called with + * {@link FrameAccess#READ_WRITE} or {@link FrameAccess#MATERIALIZE} on the fast path. + * Instructions and flags for debugging such deoptimizations can be found in /truffle/docs/Optimizing.md#debugging-deoptimizations + * + *

    * To get possible asynchronous stack frames, use * {@link TruffleStackTrace#getAsynchronousStackTrace(CallTarget, Frame)} and provide call * target and frame from the last {@link FrameInstance}. From 53bcb65ba1c2a4eb1240a2027d500ad492d600a7 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Sun, 12 Sep 2021 17:36:32 +0200 Subject: [PATCH 116/681] Add Espresso to Languages.md. --- truffle/docs/Languages.md | 1 + 1 file changed, 1 insertion(+) diff --git a/truffle/docs/Languages.md b/truffle/docs/Languages.md index 28322dda2ac9..ed6fd6ea70ef 100644 --- a/truffle/docs/Languages.md +++ b/truffle/docs/Languages.md @@ -9,6 +9,7 @@ permalink: /graalvm-as-a-platform/language-implementation-framework/Languages/ This page is intended to keep track of the growing number of language implementations and experiments on top of Truffle. The following language implementations exist already: +* [Espresso](https://github.com/oracle/graal/tree/master/espresso), a meta-circular Java bytecode interpreter. * * [FastR](https://github.com/graalvm/fastr), an implementation of GNU R. * * [Graal.js](https://github.com/graalvm/graaljs), an ECMAScript 2020 compliant JavaScript implementation. * * [Graal.Python](https://github.com/graalvm/graalpython), an early-stage implementation of Python. * From 69970372063deeb98c5293edbc547f96432fa7cd Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Tue, 21 Sep 2021 09:48:15 +0200 Subject: [PATCH 117/681] Create CallTargets lazily. --- .../truffle/runtime/GraalRuntimeSupport.java | 9 +++++++ .../truffle/runtime/GraalTruffleRuntime.java | 9 +++---- .../truffle/runtime/OptimizedCallTarget.java | 3 +-- truffle/CHANGELOG.md | 3 +++ .../truffle/api/test/TruffleRuntimeTest.java | 2 ++ .../com.oracle.truffle.api/snapshot.sigtest | 1 + .../oracle/truffle/api/TruffleRuntime.java | 4 ++- .../com/oracle/truffle/api/impl/Accessor.java | 4 +-- .../truffle/api/impl/DefaultCallTarget.java | 1 - .../api/impl/DefaultRuntimeAccessor.java | 8 ++++++ .../api/impl/DefaultTruffleRuntime.java | 4 +-- .../truffle/api/nodes/NodeAccessor.java | 5 ---- .../oracle/truffle/api/nodes/RootNode.java | 27 +++++++++++++++++-- 13 files changed, 58 insertions(+), 22 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalRuntimeSupport.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalRuntimeSupport.java index 247866ee18d3..00c3f356eab9 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalRuntimeSupport.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalRuntimeSupport.java @@ -32,6 +32,7 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.TruffleSafepoint; import com.oracle.truffle.api.frame.Frame; @@ -55,6 +56,14 @@ final class GraalRuntimeSupport extends RuntimeSupport { super(permission); } + @Override + public RootCallTarget newCallTarget(RootNode rootNode) { + CompilerAsserts.neverPartOfCompilation(); + final OptimizedCallTarget target = GraalTruffleRuntime.getRuntime().newCallTarget(rootNode, null); + TruffleSplittingStrategy.newTargetCreated(target); + return target; + } + @ExplodeLoop @Override public void onLoopCount(Node source, int count) { diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java index 624cae5c5496..ca53b6c4e9ba 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java @@ -692,13 +692,10 @@ public T getCapability(Class capability) { @Override public final RootCallTarget createCallTarget(RootNode rootNode) { - CompilerAsserts.neverPartOfCompilation(); - final OptimizedCallTarget target = createClonedCallTarget(rootNode, null); - TruffleSplittingStrategy.newTargetCreated(target); - return target; + return rootNode.getCallTarget(); } - public final OptimizedCallTarget createClonedCallTarget(RootNode rootNode, OptimizedCallTarget source) { + public final OptimizedCallTarget newCallTarget(RootNode rootNode, OptimizedCallTarget source) { CompilerAsserts.neverPartOfCompilation(); OptimizedCallTarget target = createOptimizedCallTarget(source, rootNode); GraalRuntimeAccessor.INSTRUMENT.onLoad(target.getRootNode()); @@ -713,7 +710,7 @@ public final OptimizedCallTarget createClonedCallTarget(RootNode rootNode, Optim public final OptimizedCallTarget createOSRCallTarget(RootNode rootNode) { CompilerAsserts.neverPartOfCompilation(); OptimizedCallTarget target = createOptimizedCallTarget(null, rootNode); - GraalRuntimeAccessor.INSTRUMENT.onLoad(target.getRootNode()); + GraalRuntimeAccessor.INSTRUMENT.onLoad(rootNode); return target; } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java index f12f710637a0..e4c5c33eab42 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java @@ -339,7 +339,6 @@ protected OptimizedCallTarget(OptimizedCallTarget sourceCallTarget, RootNode roo // Do not adopt children of OSRRootNodes; we want to preserve the parent of the child // node(s). this.uninitializedNodeCount = !isOSR() ? GraalRuntimeAccessor.NODES.adoptChildrenAndCount(rootNode) : -1; - GraalRuntimeAccessor.NODES.setCallTarget(rootNode, this); } final Assumption getNodeRewritingAssumption() { @@ -840,7 +839,7 @@ final OptimizedCallTarget cloneUninitialized() { } else { clonedRoot = NodeUtil.cloneNode(uninitializedRootNode); } - return runtime().createClonedCallTarget(clonedRoot, this); + return runtime().newCallTarget(clonedRoot, this); } /** diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index ebd44af3e83a..be71a4f1f14f 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -2,6 +2,9 @@ This changelog summarizes major changes between Truffle versions relevant to languages implementors building upon the Truffle framework. The main focus is on APIs exported by Truffle. +## Version 22.0.0 +* Changed behavior of `RootNode#getCallTarget()` such that it lazily initializes its call target. This enforces a one-to-one relationship between root nodes and call targets, which avoids several problems, for example, with regard to instrumentation. As a consequence, `RootNode.setCallTarget()` is deprecated and so will be `TruffleRuntime#createCallTarget()` soon. Please use `RootNode#getCallTarget()` to access the call target of a root node from now on. + ## Version 21.3.0 * Added a `@GenerateWrapper.Ignore` annotation to prevent methods from being instrumented in wrapper classes. * The native image `TruffleCheckBlackListedMethods` option was deprecated and replaced by the `TruffleCheckBlockListMethods` option. diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java index a7a19619b957..2da778bf60d4 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java @@ -114,6 +114,8 @@ public void testCreateCallTarget() { RootNode rootNode = createTestRootNode(null); RootCallTarget target = runtime.createCallTarget(rootNode); assertNotNull(target); + assertSame(target, rootNode.getCallTarget()); + assertSame(target, runtime.createCallTarget(rootNode)); for (int i = 0; i < 10000; i++) { assertEquals(target.call(), 42); } diff --git a/truffle/src/com.oracle.truffle.api/snapshot.sigtest b/truffle/src/com.oracle.truffle.api/snapshot.sigtest index d3b4dd7e95f2..624aa717e19d 100644 --- a/truffle/src/com.oracle.truffle.api/snapshot.sigtest +++ b/truffle/src/com.oracle.truffle.api/snapshot.sigtest @@ -1325,6 +1325,7 @@ meth protected boolean isTrivial() meth protected com.oracle.truffle.api.nodes.ExecutionSignature prepareForAOT() meth protected com.oracle.truffle.api.nodes.RootNode cloneUninitialized() meth protected final void setCallTarget(com.oracle.truffle.api.RootCallTarget) + anno 0 java.lang.Deprecated() meth protected java.lang.Object translateStackTraceElement(com.oracle.truffle.api.TruffleStackTraceElement) meth protected java.util.List findAsynchronousFrames(com.oracle.truffle.api.frame.Frame) meth public abstract java.lang.Object execute(com.oracle.truffle.api.frame.VirtualFrame) diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java index 55d8a713fbcf..526e7f2ac618 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java @@ -70,7 +70,9 @@ public interface TruffleRuntime { String getName(); /** - * Creates a new call target for a given root node. + * Creates a new call target for a given root node if none exists. Otherwise, the existing call + * target is returned. Note that this method is only kept for backward compatibility and will + * soon be deprecated. Please use {@link RootNode#getCallTarget()} instead. * * @param rootNode the root node whose * {@link RootNode#execute(com.oracle.truffle.api.frame.VirtualFrame)} method diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java index ee6ef15bd88d..a71a3669320c 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java @@ -153,8 +153,6 @@ protected NodeSupport() { public abstract boolean isInstrumentable(RootNode rootNode); - public abstract void setCallTarget(RootNode rootNode, RootCallTarget callTarget); - public abstract boolean isCloneUninitializedSupported(RootNode rootNode); public abstract RootNode cloneUninitialized(RootNode rootNode); @@ -969,6 +967,8 @@ protected RuntimeSupport(Object permission) { } } + public abstract RootCallTarget newCallTarget(RootNode rootNode); + public ThreadLocalHandshake getThreadLocalHandshake() { return DefaultThreadLocalHandshake.SINGLETON; } diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java index 8eb6dd87f62c..b73ead50676e 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java @@ -63,7 +63,6 @@ public final class DefaultCallTarget implements RootCallTarget { DefaultCallTarget(RootNode function) { this.rootNode = function; this.rootNode.adoptChildren(); - DefaultRuntimeAccessor.NODES.setCallTarget(function, this); } @Override diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultRuntimeAccessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultRuntimeAccessor.java index e0bb95e361bd..f35dc930ed76 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultRuntimeAccessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultRuntimeAccessor.java @@ -49,6 +49,7 @@ import org.graalvm.options.OptionValues; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.nodes.BlockNode; import com.oracle.truffle.api.nodes.BlockNode.ElementExecutor; @@ -76,6 +77,13 @@ static final class DefaultRuntimeSupport extends RuntimeSupport { super(permission); } + @Override + public RootCallTarget newCallTarget(RootNode rootNode) { + DefaultCallTarget target = new DefaultCallTarget(rootNode); + DefaultRuntimeAccessor.INSTRUMENT.onLoad(rootNode); + return target; + } + @Override public ThreadLocalHandshake getThreadLocalHandshake() { return DefaultThreadLocalHandshake.SINGLETON; diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java index 214f255aa188..548653969f93 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java @@ -120,9 +120,7 @@ public String getName() { @SuppressWarnings("deprecation") @Override public RootCallTarget createCallTarget(RootNode rootNode) { - DefaultCallTarget target = new DefaultCallTarget(rootNode); - DefaultRuntimeAccessor.INSTRUMENT.onLoad(target.getRootNode()); - return target; + return rootNode.getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeAccessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeAccessor.java index 87d139a98baf..13853cf49091 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeAccessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeAccessor.java @@ -73,11 +73,6 @@ public boolean isInstrumentable(RootNode rootNode) { return rootNode.isInstrumentable(); } - @Override - public void setCallTarget(RootNode rootNode, RootCallTarget callTarget) { - rootNode.setCallTarget(callTarget); - } - @Override public boolean isCloneUninitializedSupported(RootNode rootNode) { return rootNode.isCloneUninitializedSupported(); diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java index c3580d28146c..d7bf912541bc 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java @@ -47,6 +47,7 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.CompilerOptions; @@ -345,7 +346,21 @@ protected RootNode cloneUninitialized() { /** @since 0.8 or earlier */ public final RootCallTarget getCallTarget() { - return callTarget; + RootCallTarget target = this.callTarget; + if (target == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + ReentrantLock l = getLazyLock(); + l.lock(); + try { + target = this.callTarget; + if (target == null) { + this.callTarget = target = NodeAccessor.RUNTIME.newCallTarget(this); + } + } finally { + l.unlock(); + } + } + return target; } /** @since 0.8 or earlier */ @@ -353,8 +368,16 @@ public final FrameDescriptor getFrameDescriptor() { return frameDescriptor; } - /** @since 19.0 */ + /** + * @throws UnsupportedOperationException if a call target already exists. + * @since 19.0 + * @deprecated in 22.0, call targets are lazily initialized in {@link #getCallTarget()} now. + */ + @Deprecated protected final void setCallTarget(RootCallTarget callTarget) { + if (this.callTarget != null) { + throw new UnsupportedOperationException(); + } this.callTarget = callTarget; } From 449042237ddbbe3b25ac9a88d52eb1a7465a7c69 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 24 Sep 2021 10:49:51 +0200 Subject: [PATCH 118/681] Fix style and copyright. --- .../interop/PolyglotArrayToNativeTest.java | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java b/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java index 5d88781a2025..146976c75407 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java +++ b/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.oracle.truffle.llvm.tests.interop; import org.graalvm.polyglot.Value; @@ -44,7 +73,7 @@ public static void loadPolygloArrayToNativeLibrary() { @ExportLibrary(InteropLibrary.class) @ExportLibrary(value = NativeTypeLibrary.class, useForAOT = false) @SuppressWarnings("static-method") - static class SimpleWrapper implements TruffleObject { + static final class SimpleWrapper implements TruffleObject { private final long delegate; private SimpleWrapper(long l) { @@ -104,7 +133,7 @@ Object getNativeType() { @ExportLibrary(value = NativeTypeLibrary.class, useForAOT = false) @ExportLibrary(InteropLibrary.class) @SuppressWarnings("static-method") - static class SimpleArrayWrapper implements TruffleObject { + static final class SimpleArrayWrapper implements TruffleObject { private final SimpleWrapper[] objects; private SimpleArrayWrapper(SimpleWrapper[] objects) { @@ -174,4 +203,4 @@ public void test() { Assert.assertEquals(i, payload.asNativePointer()); } } -} \ No newline at end of file +} From 5464d007c023fa12a57c946cad683bff4e5a4643 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 24 Sep 2021 13:34:58 +0200 Subject: [PATCH 119/681] Fix: add TruffleBoundary to getNativeType --- .../truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java b/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java index 146976c75407..97c8f1570e52 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java +++ b/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/PolyglotArrayToNativeTest.java @@ -29,6 +29,7 @@ */ package com.oracle.truffle.llvm.tests.interop; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import org.graalvm.polyglot.Value; import org.junit.Assert; import org.junit.BeforeClass; @@ -166,6 +167,7 @@ boolean hasNativeType() { } @ExportMessage + @TruffleBoundary Object getNativeType() { try { Object[] result = new Object[1]; From 4f74d7871513f7123c87ad248ee7a2b3775a1170 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 24 Sep 2021 15:14:52 +0200 Subject: [PATCH 120/681] Fix format --- .../interop/polyglotArrayToNative.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotArrayToNative.c b/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotArrayToNative.c index 9825627b3496..b8fa7649a561 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotArrayToNative.c +++ b/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotArrayToNative.c @@ -31,7 +31,7 @@ #include -typedef void* VoidPtr; +typedef void *VoidPtr; typedef struct { void *payload; @@ -48,7 +48,7 @@ void get_Simple_array_typeid(uint64_t len, void (*ret)(polyglot_typeid typeid)) ret(polyglot_array_typeid(polyglot_VoidPtr_typeid(), len)); } -#define WRAP(x) ((Simple){(x)}) +#define WRAP(x) ((Simple){ (x) }) void *simple_array_to_native(VoidPtr *polyglot_array, uint64_t size) { Simple *native = (Simple *) malloc(size * sizeof(Simple)); From ad99cf7c1d5acef45fbb0c76fdc2bf4b9f7baeff Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Fri, 24 Sep 2021 16:19:16 +0200 Subject: [PATCH 121/681] Add multi-version renaissance support to native-image and upgrade to renaissance 0.13 --- .../mx_substratevm_benchmark.py | 174 ++++++++++++------ substratevm/mx.substratevm/suite.py | 4 +- 2 files changed, 123 insertions(+), 55 deletions(-) diff --git a/substratevm/mx.substratevm/mx_substratevm_benchmark.py b/substratevm/mx.substratevm/mx_substratevm_benchmark.py index ab64cb709e27..eb8a0e702f17 100644 --- a/substratevm/mx.substratevm/mx_substratevm_benchmark.py +++ b/substratevm/mx.substratevm/mx_substratevm_benchmark.py @@ -91,48 +91,114 @@ def list_jars(path): } _renaissance_config = { - "akka-uct" : ("actors", 11), # GR-17994 - "reactors" : ("actors", 11), - "scala-kmeans" : ("scala-stdlib", 12), - "mnemonics" : ("jdk-streams", 12), - "par-mnemonics" : ("jdk-streams", 12), - "rx-scrabble" : ("rx", 12), - "als" : ("apache-spark", 11), - "chi-square" : ("apache-spark", 11), - "db-shootout" : ("database", 11), # GR-17975, GR-17943 (with --report-unsupported-elements-at-runtime) - "dec-tree" : ("apache-spark", 11), - "dotty" : ("scala-dotty", 12), # GR-17985 - "finagle-chirper" : ("twitter-finagle", 11), - "finagle-http" : ("twitter-finagle", 11), - "fj-kmeans" : ("jdk-concurrent", 12), - "future-genetic" : ("jdk-concurrent", 12), # GR-17988 - "gauss-mix" : ("apache-spark", 11), - "log-regression" : ("apache-spark", 11), - "movie-lens" : ("apache-spark", 11), - "naive-bayes" : ("apache-spark", 11), - "neo4j-analytics" : ("neo4j", 11), - "page-rank" : ("apache-spark", 11), - "philosophers" : ("scala-stm", 12), - "scala-stm-bench7" : ("scala-stm", 12), - "scrabble" : ("jdk-streams", 12) + "akka-uct": { + "group": "actors-akka", + "legacy-group": "actors", + "requires-recompiled-harness": ["0.9.0", "0.10.0", "0.11.0"] + }, + "reactors": { + "group": "actors-reactors", + "legacy-group": "actors", + "requires-recompiled-harness": True + }, + "scala-kmeans": { + "group": "scala-stdlib" + }, + "scala-doku": { + "group": "scala-sat" + }, + "mnemonics": { + "group": "jdk-streams" + }, + "par-mnemonics": { + "group": "jdk-streams" + }, + "rx-scrabble": { + "group": "rx" + }, + "als": { + "group": "apache-spark", + "requires-recompiled-harness": True + }, + "chi-square": { + "group": "apache-spark", + "requires-recompiled-harness": True + }, + "db-shootout": { # GR-17975, GR-17943 (with --report-unsupported-elements-at-runtime) + "group": "database", + "requires-recompiled-harness": ["0.9.0", "0.10.0", "0.11.0"] + }, + "dec-tree": { + "group": "apache-spark", + "requires-recompiled-harness": True + }, + "dotty": { + "group": "scala-dotty" + }, + "finagle-chirper": { + "group": "twitter-finagle", + "requires-recompiled-harness": True + }, + "finagle-http": { + "group": "twitter-finagle", + "requires-recompiled-harness": True + }, + "fj-kmeans": { + "group": "jdk-concurrent" + }, + "future-genetic": { + "group": "jdk-concurrent" + }, + "gauss-mix": { + "group": "apache-spark", + "requires-recompiled-harness": True + }, + "log-regression": { + "group": "apache-spark", + "requires-recompiled-harness": True + }, + "movie-lens": { + "group": "apache-spark", + "requires-recompiled-harness": True + }, + "naive-bayes": { + "group": "apache-spark", + "requires-recompiled-harness": True + }, + "page-rank": { + "group": "apache-spark", + "requires-recompiled-harness": True + }, + "neo4j-analytics": { + "group": "neo4j", + "requires-recompiled-harness": True + }, + "philosophers": { + "group": "scala-stm", + "requires-recompiled-harness": ["0.12.0", "0.13.0"] + }, + "scala-stm-bench7": { + "group": "scala-stm", + "requires-recompiled-harness": ["0.12.0", "0.13.0"] + }, + "scrabble": { + "group": "jdk-streams" + } } -# breeze jar is replaced with a patched jar because of IncompatibleClassChange errors due to a bug in the Scala compiler. -_renaissance_additional_lib = { - 'apache-spark' : ['SPARK_BREEZE_PATCHED'] -} - -_renaissance_exclude_lib = { - 'apache-spark' : ['breeze_2.11-0.11.2.jar'] -} +def benchmark_group(benchmark, suite_version): + if suite_version in ["0.9.0", "0.10.0", "0.11.0"]: + return _renaissance_config[benchmark].get("legacy-group", _renaissance_config[benchmark]["group"]) + else: + return _renaissance_config[benchmark]["group"] -def benchmark_group(benchmark): - return _renaissance_config[benchmark][0] - -def benchmark_scalaversion(benchmark): - return _renaissance_config[benchmark][1] +def requires_recompiled_harness(benchmark, suite_version): + requires_harness = _renaissance_config[benchmark].get("requires-recompiled-harness", False) + if isinstance(requires_harness, list): + return suite_version in requires_harness + return requires_harness class RenaissanceNativeImageBenchmarkSuite(mx_java_benchmarks.RenaissanceBenchmarkSuite, mx_sdk_benchmark.NativeImageBenchmarkMixin): #pylint: disable=too-many-ancestors @@ -153,7 +219,7 @@ def benchSuiteName(self, bmSuiteArgs=None): return 'renaissance' def renaissance_harness_lib_name(self): - version_to_run = super(RenaissanceNativeImageBenchmarkSuite, self).version() + version_to_run = self.version() version_end_index = str(version_to_run).rindex('.') return 'RENAISSANCE_HARNESS_v' + str(version_to_run)[0:version_end_index] @@ -216,9 +282,10 @@ def successPatterns(self): _successful_stage_pattern ] - def create_classpath(self, benchArg): - harness_project = RenaissanceNativeImageBenchmarkSuite.RenaissanceProject('harness', benchmark_scalaversion(benchArg), self) - group_project = RenaissanceNativeImageBenchmarkSuite.RenaissanceProject(benchmark_group(benchArg), benchmark_scalaversion(benchArg), self, harness_project) + def create_classpath(self, benchmarkName): + custom_harness = requires_recompiled_harness(benchmarkName, self.version()) + harness_project = RenaissanceNativeImageBenchmarkSuite.RenaissanceProject('harness', custom_harness, self) + group_project = RenaissanceNativeImageBenchmarkSuite.RenaissanceProject(benchmark_group(benchmarkName, self.version()), custom_harness, self, harness_project) return ':'.join([mx.classpath(harness_project), mx.classpath(group_project)]) class RenaissanceDependency(mx.ClasspathDependency): @@ -233,10 +300,10 @@ def _walk_deps_visit_edges(self, *args, **kwargs): pass class RenaissanceProject(mx.ClasspathDependency): - def __init__(self, group, scala_version=12, renaissance_suite=None, dep_project=None): # pylint: disable=super-init-not-called + def __init__(self, group, requires_recompiled_harness, renaissance_suite, dep_project=None): # pylint: disable=super-init-not-called mx.Dependency.__init__(self, _suite, group, None) self.suite = renaissance_suite - self.deps = self.collect_group_dependencies(group, scala_version) + self.deps = self.collect_group_dependencies(group, requires_recompiled_harness) if dep_project is not None: self.deps.append(dep_project) @@ -251,24 +318,25 @@ def get_dependencies(self, path, group): deps = [] for jar in list_jars(path): deps.append(RenaissanceNativeImageBenchmarkSuite.RenaissanceDependency(os.path.basename(jar), mx.join(path, jar))) - if group in _renaissance_exclude_lib: - for lib in _renaissance_exclude_lib[group]: - lib_dep = RenaissanceNativeImageBenchmarkSuite.RenaissanceDependency(lib, mx.join(path, lib)) + + if self.suite.version() in ["0.9.0", "0.10.0", "0.11.0"]: + if group == 'apache-spark': + # breeze jar is replaced with a patched jar because of IncompatibleClassChange errors due to a bug in the Scala compiler + invalid_bytecode_jar = 'breeze_2.11-0.11.2.jar' + lib_dep = RenaissanceNativeImageBenchmarkSuite.RenaissanceDependency(invalid_bytecode_jar, mx.join(path, invalid_bytecode_jar)) if lib_dep in deps: deps.remove(lib_dep) - if group in _renaissance_additional_lib: - for lib in _renaissance_additional_lib[group]: - lib_path = RenaissanceNativeImageBenchmarkSuite.renaissance_additional_lib(self.suite, lib) + lib_path = RenaissanceNativeImageBenchmarkSuite.renaissance_additional_lib(self.suite, 'SPARK_BREEZE_PATCHED') deps.append(RenaissanceNativeImageBenchmarkSuite.RenaissanceDependency(os.path.basename(lib_path), lib_path)) return deps - def collect_group_dependencies(self, group, scala_version): + def collect_group_dependencies(self, group, requires_recompiled_harness): if group == 'harness': - if scala_version == 12: + if requires_recompiled_harness: + path = RenaissanceNativeImageBenchmarkSuite.harness_path(self.suite) + else: unpacked_renaissance = RenaissanceNativeImageBenchmarkSuite.renaissance_unpacked(self.suite) path = mx.join(unpacked_renaissance, 'renaissance-harness') - else: - path = RenaissanceNativeImageBenchmarkSuite.harness_path(self.suite) else: unpacked_renaissance = RenaissanceNativeImageBenchmarkSuite.renaissance_unpacked(self.suite) path = mx.join(unpacked_renaissance, 'benchmarks', group) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 0de5c71a4e7d..cc3da43c8acc 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -55,12 +55,12 @@ }, "RENAISSANCE_HARNESS_v0.12" : { "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/renaissance/renaissance-harness_v0.12.0.tar.gz"], - "sha1" : "c061f62ce6f2758ec30b92e69f20f14b93e34b35", + "sha1" : "84592bedd6f0afa842aadb8813d395317b1fa385", "packedResource": True, }, "RENAISSANCE_HARNESS_v0.13" : { "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/renaissance/renaissance-harness_v0.13.0.tar.gz"], - "sha1" : "ca32c080016c5659bbf3eddc184e14b742769372", + "sha1" : "8edc1db5c7ea977e2a9c037b5324bb4cbee40082", "packedResource": True, }, "DACAPO_SVM" : { From b19128328f93f8cfd4c7702ba9118cdf772648f4 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Fri, 24 Sep 2021 16:40:07 +0200 Subject: [PATCH 122/681] Do not use GNUR_FC env var --- vm/ci_common/common.hocon | 1 - 1 file changed, 1 deletion(-) diff --git a/vm/ci_common/common.hocon b/vm/ci_common/common.hocon index 21b8c9f98e51..32202174f47f 100644 --- a/vm/ci_common/common.hocon +++ b/vm/ci_common/common.hocon @@ -141,7 +141,6 @@ fastr_darwin: ${fastr} { environment: { PATH : "/usr/local/bin:$JAVA_HOME/bin:$PATH" FASTR_FC: "/cm/shared/apps/gcc/8.3.0/bin/gfortran" - GNUR_FC: "/cm/shared/apps/gcc/8.3.0/bin/gfortran" TZDIR: "/usr/share/zoneinfo" FASTR_LIBZ_VER: "1.2.11" PKG_INCLUDE_FLAGS_OVERRIDE : "-I/cm/shared/apps/pcre2/pcre2-10.37/include -I/cm/shared/apps/bzip2/1.0.6/include -I/cm/shared/apps/xz/5.2.2/include -I/cm/shared/apps/curl/7.50.1/include" From b94039578d2181b9d48b841c14fd4bd559ae327c Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Wed, 22 Sep 2021 18:50:02 +0200 Subject: [PATCH 123/681] Refactor property locations. --- .../oracle/truffle/object/CoreLocations.java | 193 +++++++++--------- .../truffle/object/DynamicObjectBasic.java | 30 +-- .../object/DynamicObjectLibraryImpl.java | 142 ++++--------- .../oracle/truffle/object/LocationImpl.java | 133 +++++++++--- .../com/oracle/truffle/object/Locations.java | 23 +-- 5 files changed, 268 insertions(+), 253 deletions(-) diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java index 4c4aa5cc9217..a88467793811 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java @@ -84,9 +84,9 @@ public interface ObjectLocation extends TypedLocation, com.oracle.truffle.api.ob } public interface IntLocation extends TypedLocation, com.oracle.truffle.api.object.IntLocation { - int getInt(DynamicObject store, boolean condition); + int getInt(DynamicObject store, boolean guard); - void setInt(DynamicObject store, int value, boolean condition); + void setInt(DynamicObject store, int value, boolean guard, boolean init); default Class getType() { return int.class; @@ -101,26 +101,26 @@ default int getInt(DynamicObject store, Shape shape) { @Override default void setInt(DynamicObject store, int value, Shape shape) throws FinalLocationException { - setInt(store, value, store.getShape() == shape); + setInt(store, value, store.getShape() == shape, false); } @Override default void setInt(DynamicObject store, int value) throws FinalLocationException { - setInt(store, value, false); + setInt(store, value, false, false); } @Override default void setInt(DynamicObject store, int value, Shape oldShape, Shape newShape) { ACCESS.grow(store, oldShape, newShape); - setInt(store, value, false); + setInt(store, value, false, false); ACCESS.setShapeWithStoreFence(store, newShape); } } public interface LongLocation extends TypedLocation, com.oracle.truffle.api.object.LongLocation { - long getLong(DynamicObject store, boolean condition); + long getLong(DynamicObject store, boolean guard); - void setLong(DynamicObject store, long value, boolean condition); + void setLong(DynamicObject store, long value, boolean guard, boolean init); default Class getType() { return long.class; @@ -137,26 +137,26 @@ default long getLong(DynamicObject store, Shape shape) { @Override default void setLong(DynamicObject store, long value, Shape shape) throws FinalLocationException { - setLong(store, value, store.getShape() == shape); + setLong(store, value, store.getShape() == shape, false); } @Override default void setLong(DynamicObject store, long value) throws FinalLocationException { - setLong(store, value, false); + setLong(store, value, false, false); } @Override default void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape) { ACCESS.grow(store, oldShape, newShape); - setLong(store, value, false); + setLong(store, value, false, false); ACCESS.setShapeWithStoreFence(store, newShape); } } public interface DoubleLocation extends TypedLocation, com.oracle.truffle.api.object.DoubleLocation { - double getDouble(DynamicObject store, boolean condition); + double getDouble(DynamicObject store, boolean guard); - void setDouble(DynamicObject store, double value, boolean condition); + void setDouble(DynamicObject store, double value, boolean guard, boolean init); default Class getType() { return double.class; @@ -173,26 +173,26 @@ default double getDouble(DynamicObject store, Shape shape) { @Override default void setDouble(DynamicObject store, double value, Shape shape) throws FinalLocationException { - setDouble(store, value, store.getShape() == shape); + setDouble(store, value, store.getShape() == shape, false); } @Override default void setDouble(DynamicObject store, double value) throws FinalLocationException { - setDouble(store, value, false); + setDouble(store, value, false, false); } @Override default void setDouble(DynamicObject store, double value, Shape oldShape, Shape newShape) { ACCESS.grow(store, oldShape, newShape); - setDouble(store, value, false); + setDouble(store, value, false, false); ACCESS.setShapeWithStoreFence(store, newShape); } } public interface BooleanLocation extends TypedLocation, com.oracle.truffle.api.object.BooleanLocation { - boolean getBoolean(DynamicObject store, boolean condition); + boolean getBoolean(DynamicObject store, boolean guard); - void setBoolean(DynamicObject store, boolean value, boolean condition); + void setBoolean(DynamicObject store, boolean value, boolean guard, boolean init); default Class getType() { return boolean.class; @@ -207,18 +207,18 @@ default boolean getBoolean(DynamicObject store, Shape shape) { @Override default void setBoolean(DynamicObject store, boolean value, Shape shape) throws FinalLocationException { - setBoolean(store, value, store.getShape() == shape); + setBoolean(store, value, store.getShape() == shape, false); } @Override default void setBoolean(DynamicObject store, boolean value) throws FinalLocationException { - setBoolean(store, value, false); + setBoolean(store, value, false, false); } @Override default void setBoolean(DynamicObject store, boolean value, Shape oldShape, Shape newShape) { ACCESS.grow(store, oldShape, newShape); - setBoolean(store, value, false); + setBoolean(store, value, false, false); ACCESS.setShapeWithStoreFence(store, newShape); } } @@ -246,7 +246,7 @@ public boolean equals(Object obj) { } @Override - public final Object get(DynamicObject store, boolean condition) { + public final Object get(DynamicObject store, boolean guard) { return value; } @@ -256,17 +256,14 @@ public boolean canStore(Object val) { } @Override - public final void set(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException, FinalLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { if (!canStore(value)) { - throw finalLocation(); - } - } - - @Override - public final void setInternal(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException { - if (!canStore(value)) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw new UnsupportedOperationException(); + if (init) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw new UnsupportedOperationException(); + } else { + throw finalLocation(); + } } } @@ -318,9 +315,9 @@ protected ArrayLocation(int index, CoreLocation arrayLocation) { this.arrayLocation = arrayLocation; } - protected final Object getArray(DynamicObject store, boolean condition) { + protected final Object getArray(DynamicObject store, boolean guard) { // non-null cast - return arrayLocation.get(store, condition); + return arrayLocation.get(store, guard); } @Override @@ -410,13 +407,13 @@ protected ObjectArrayLocation(int index, CoreLocation arrayLocation) { } @Override - public Object get(DynamicObject store, boolean condition) { - return ((Object[]) getArray(store, condition))[index]; + public Object get(DynamicObject store, boolean guard) { + return ((Object[]) getArray(store, guard))[index]; } @Override - public final void setInternal(DynamicObject store, Object value, boolean condition) { - ((Object[]) getArray(store, condition))[index] = value; + public final void set(DynamicObject store, Object value, boolean guard, boolean init) { + ((Object[]) getArray(store, guard))[index] = value; } @Override @@ -435,7 +432,7 @@ public final boolean isNonNull() { @Override protected void clear(DynamicObject store) { - setInternal(store, null, false); + set(store, null, false, true); } @Override @@ -456,10 +453,10 @@ protected SimpleObjectFieldLocation(int index) { } @Override - public abstract Object get(DynamicObject store, boolean condition); + public abstract Object get(DynamicObject store, boolean guard); @Override - public abstract void setInternal(DynamicObject store, Object value, boolean condition); + public abstract void set(DynamicObject store, Object value, boolean guard, boolean init); @Override public boolean canStore(Object value) { @@ -477,7 +474,7 @@ public boolean isNonNull() { @Override protected void clear(DynamicObject store) { - setInternal(store, null, false); + set(store, null, false, true); } @Override @@ -509,14 +506,14 @@ protected LongArrayLocation(int index, CoreLocation arrayLocation) { } @Override - public final Object get(DynamicObject store, boolean condition) { - return getLong(store, condition); + public final Object get(DynamicObject store, boolean guard) { + return getLong(store, guard); } @Override - public final void setInternal(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException { if (canStore(value)) { - setLongInternal(store, longValue(value)); + setLong(store, longValue(value), guard, init); } else { throw incompatibleLocation(); } @@ -531,8 +528,8 @@ private long longValue(Object value) { } @Override - public long getLong(DynamicObject store, boolean condition) { - int[] array = (int[]) getArray(store, condition); + public long getLong(DynamicObject store, boolean guard) { + int[] array = (int[]) getArray(store, guard); return UNSAFE.getLong(array, getOffset(array)); } @@ -543,7 +540,7 @@ public final void setLongInternal(DynamicObject store, long value) { } @Override - public void setLong(DynamicObject store, long value, boolean condition) { + public void setLong(DynamicObject store, long value, boolean guard, boolean init) { setLongInternal(store, value); } @@ -604,27 +601,27 @@ protected LongLocationDecorator(LongLocation longLocation, boolean allowInt) { } @Override - public final Object get(DynamicObject store, boolean condition) { - return getLong(store, condition); + public final Object get(DynamicObject store, boolean guard) { + return getLong(store, guard); } @Override - public long getLong(DynamicObject store, boolean condition) { - return super.getLongInternal(store, condition); + public long getLong(DynamicObject store, boolean guard) { + return super.getLongInternal(store, guard); } @Override - public final void setInternal(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException { if (canStore(value)) { - setLong(store, longValue(value), condition); + setLong(store, longValue(value), guard, init); } else { throw incompatibleLocation(); } } @Override - public void setLong(DynamicObject store, long value, boolean condition) { - super.setLongInternal(store, value, condition); + public void setLong(DynamicObject store, long value, boolean guard, boolean init) { + super.setLongInternal(store, value, guard); } private long longValue(Object value) { @@ -663,14 +660,14 @@ protected SimpleLongFieldLocation(int index) { } @Override - public final Object get(DynamicObject store, boolean condition) { - return getLong(store, condition); + public final Object get(DynamicObject store, boolean guard) { + return getLong(store, guard); } @Override - public final void setInternal(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException { if (canStore(value)) { - setLong(store, ((Long) value).longValue(), condition); + setLong(store, ((Long) value).longValue(), guard, init); } else { throw incompatibleLocation(); } @@ -682,7 +679,7 @@ public final boolean canStore(Object value) { } @Override - public abstract long getLong(DynamicObject store, boolean condition); + public abstract long getLong(DynamicObject store, boolean guard); @Override public final long getLong(DynamicObject store, Shape shape) { @@ -690,7 +687,7 @@ public final long getLong(DynamicObject store, Shape shape) { } @Override - public abstract void setLong(DynamicObject store, long value, boolean condition); + public abstract void setLong(DynamicObject store, long value, boolean guard, boolean init); @Override public int primitiveFieldCount() { @@ -720,12 +717,12 @@ protected PrimitiveLocationDecorator(LongLocation longLocation) { this.longLocation = longLocation; } - public final long getLongInternal(DynamicObject store, boolean condition) { - return longLocation.getLong(store, condition); + public final long getLongInternal(DynamicObject store, boolean guard) { + return longLocation.getLong(store, guard); } - public final void setLongInternal(DynamicObject store, long value, boolean condition) { - longLocation.setLong(store, value, condition); + public final void setLongInternal(DynamicObject store, long value, boolean guard) { + longLocation.setLong(store, value, guard, true); } public final LongLocation getInternalLongLocation() { @@ -774,24 +771,24 @@ protected IntLocationDecorator(LongLocation longLocation) { } @Override - public final Object get(DynamicObject store, boolean condition) { - return getInt(store, condition); + public final Object get(DynamicObject store, boolean guard) { + return getInt(store, guard); } @Override - public int getInt(DynamicObject store, boolean condition) { - return (int) getLongInternal(store, condition); + public int getInt(DynamicObject store, boolean guard) { + return (int) getLongInternal(store, guard); } @Override - public void setInt(DynamicObject store, int value, boolean condition) { - setLongInternal(store, value, condition); + public void setInt(DynamicObject store, int value, boolean guard, boolean init) { + setLongInternal(store, value, guard); } @Override - public final void setInternal(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException { if (canStore(value)) { - setLongInternal(store, (int) value, condition); + setLongInternal(store, (int) value, guard); } else { throw incompatibleLocation(); } @@ -822,24 +819,24 @@ protected DoubleLocationDecorator(LongLocation longLocation, boolean allowInt) { } @Override - public final Object get(DynamicObject store, boolean condition) { - return getDouble(store, condition); + public final Object get(DynamicObject store, boolean guard) { + return getDouble(store, guard); } @Override - public double getDouble(DynamicObject store, boolean condition) { - return Double.longBitsToDouble(getLongInternal(store, condition)); + public double getDouble(DynamicObject store, boolean guard) { + return Double.longBitsToDouble(getLongInternal(store, guard)); } @Override - public void setDouble(DynamicObject store, double value, boolean condition) { - setLongInternal(store, Double.doubleToRawLongBits(value), condition); + public void setDouble(DynamicObject store, double value, boolean guard, boolean init) { + setLongInternal(store, Double.doubleToRawLongBits(value), guard); } @Override - public final void setInternal(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException { if (canStore(value)) { - setDouble(store, doubleValue(value), condition); + setDouble(store, doubleValue(value), guard, init); } else { throw incompatibleLocation(); } @@ -885,24 +882,24 @@ protected BooleanLocationDecorator(LongLocation longLocation) { } @Override - public final Object get(DynamicObject store, boolean condition) { - return getBoolean(store, condition); + public final Object get(DynamicObject store, boolean guard) { + return getBoolean(store, guard); } @Override - public boolean getBoolean(DynamicObject store, boolean condition) { - return getLongInternal(store, condition) != 0; + public boolean getBoolean(DynamicObject store, boolean guard) { + return getLongInternal(store, guard) != 0; } @Override - public void setBoolean(DynamicObject store, boolean value, boolean condition) { - setLongInternal(store, value ? 1 : 0, condition); + public void setBoolean(DynamicObject store, boolean value, boolean guard, boolean init) { + setLongInternal(store, value ? 1 : 0, guard); } @Override - public final void setInternal(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException { if (canStore(value)) { - setBoolean(store, (boolean) value, condition); + setBoolean(store, (boolean) value, guard, init); } else { throw incompatibleLocation(); } @@ -958,13 +955,13 @@ private DynamicObjectFieldLocation(int index, long offset, Class getDeclaringClass() { PRIMITIVE_ARRAY_LOCATION = new SimpleObjectFieldLocation(index++) { @Override - public int[] get(DynamicObject store, boolean condition) { + public int[] get(DynamicObject store, boolean guard) { return LayoutImpl.ACCESS.getPrimitiveArray(store); } @Override - public void setInternal(DynamicObject store, Object value, boolean condition) { + public void set(DynamicObject store, Object value, boolean guard, boolean init) { LayoutImpl.ACCESS.setPrimitiveArray(store, (int[]) value); } diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectBasic.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectBasic.java index 8f1234bbd00b..35845839be7d 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectBasic.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectBasic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -280,32 +280,32 @@ public final Class getDeclaringClass() { index = 0; PRIMITIVE_FIELD_LOCATIONS = new BasicLongFieldLocation[]{new BasicLongFieldLocation(index++) { @Override - public long getLong(DynamicObject store, boolean condition) { + public long getLong(DynamicObject store, boolean guard) { return ((DynamicObjectBasic) store).primitive1; } @Override - public void setLong(DynamicObject store, long value, boolean condition) { + public void setLong(DynamicObject store, long value, boolean guard, boolean init) { ((DynamicObjectBasic) store).primitive1 = value; } }, new BasicLongFieldLocation(index++) { @Override - public long getLong(DynamicObject store, boolean condition) { + public long getLong(DynamicObject store, boolean guard) { return ((DynamicObjectBasic) store).primitive2; } @Override - public void setLong(DynamicObject store, long value, boolean condition) { + public void setLong(DynamicObject store, long value, boolean guard, boolean init) { ((DynamicObjectBasic) store).primitive2 = value; } }, new BasicLongFieldLocation(index++) { @Override - public long getLong(DynamicObject store, boolean condition) { + public long getLong(DynamicObject store, boolean guard) { return ((DynamicObjectBasic) store).primitive3; } @Override - public void setLong(DynamicObject store, long value, boolean condition) { + public void setLong(DynamicObject store, long value, boolean guard, boolean init) { ((DynamicObjectBasic) store).primitive3 = value; } }}; @@ -313,42 +313,42 @@ public void setLong(DynamicObject store, long value, boolean condition) { index = 0; OBJECT_FIELD_LOCATIONS = new BasicObjectFieldLocation[]{new BasicObjectFieldLocation(index++) { @Override - public Object get(DynamicObject store, boolean condition) { + public Object get(DynamicObject store, boolean guard) { return ((DynamicObjectBasic) store).object1; } @Override - public void setInternal(DynamicObject store, Object value, boolean condition) { + public void set(DynamicObject store, Object value, boolean guard, boolean init) { ((DynamicObjectBasic) store).object1 = value; } }, new BasicObjectFieldLocation(index++) { @Override - public Object get(DynamicObject store, boolean condition) { + public Object get(DynamicObject store, boolean guard) { return ((DynamicObjectBasic) store).object2; } @Override - public void setInternal(DynamicObject store, Object value, boolean condition) { + public void set(DynamicObject store, Object value, boolean guard, boolean init) { ((DynamicObjectBasic) store).object2 = value; } }, new BasicObjectFieldLocation(index++) { @Override - public Object get(DynamicObject store, boolean condition) { + public Object get(DynamicObject store, boolean guard) { return ((DynamicObjectBasic) store).object3; } @Override - public void setInternal(DynamicObject store, Object value, boolean condition) { + public void set(DynamicObject store, Object value, boolean guard, boolean init) { ((DynamicObjectBasic) store).object3 = value; } }, new BasicObjectFieldLocation(index++) { @Override - public Object get(DynamicObject store, boolean condition) { + public Object get(DynamicObject store, boolean guard) { return ((DynamicObjectBasic) store).object4; } @Override - public void setInternal(DynamicObject store, Object value, boolean condition) { + public void set(DynamicObject store, Object value, boolean guard, boolean init) { ((DynamicObjectBasic) store).object4 = value; } }}; diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java index dc14eb70e9dc..7b697ff15259 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java @@ -73,9 +73,7 @@ import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.DynamicObjectLibrary; -import com.oracle.truffle.api.object.FinalLocationException; import com.oracle.truffle.api.object.HiddenKey; -import com.oracle.truffle.api.object.IncompatibleLocationException; import com.oracle.truffle.api.object.Location; import com.oracle.truffle.api.object.Property; import com.oracle.truffle.api.object.Shape; @@ -301,7 +299,7 @@ public static Property[] getPropertyArray(@SuppressWarnings("unused") DynamicObj return ((ShapeImpl) cachedShape).getPropertyArray(); } - private static LocationImpl getLocation(Property existing) { + static LocationImpl getLocation(Property existing) { return (LocationImpl) existing.getLocation(); } @@ -313,11 +311,7 @@ protected static boolean putUncached(DynamicObject object, Object key, Object va return false; } if (existingProperty != null && !Flags.isUpdateFlags(putFlags) && existingProperty.getLocation().canSet(value)) { - try { - getLocation(existingProperty).set(object, value, false); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } + getLocation(existingProperty).setSafe(object, value, false, false); return true; } else { return putUncachedSlow(object, key, value, putFlags); @@ -359,21 +353,14 @@ private static boolean putUncachedSlow(DynamicObject object, Object key, Object } while (updateShapeImpl(object)); assert ACCESS.getShape(object) == oldShape; + LocationImpl location = getLocation(property); if (oldShape != newShape) { ACCESS.grow(object, oldShape, newShape); - try { - getLocation(property).setInternal(object, value, false); - } catch (IncompatibleLocationException e) { - throw shouldNotHappen(e); - } + location.setSafe(object, value, false, true); ACCESS.setShapeWithStoreFence(object, newShape); updateShapeImpl(object); } else { - try { - getLocation(property).set(object, value, false); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } + location.setSafe(object, value, false, false); } return true; } @@ -440,11 +427,7 @@ Object performGet(DynamicObject obj) { } void performSet(DynamicObject obj, Object value) { - try { - toLoc.setInternal(obj, value, false); - } catch (IncompatibleLocationException e) { - throw shouldNotHappen(e); - } + toLoc.setSafe(obj, value, false, true); } void clear(DynamicObject obj) { @@ -1240,16 +1223,12 @@ protected boolean putImpl(DynamicObject object, Shape cachedShape, Object key, O Shape newShape = c.newShape; if (newShape != oldShape) { ACCESS.grow(object, oldShape, newShape); + location.setSafe(object, value, guardCondition, true); + ACCESS.setShapeWithStoreFence(object, newShape); } else if (location.isFinal()) { continue; - } - try { - location.set(object, value, guardCondition); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } - if (newShape != oldShape) { - ACCESS.setShapeWithStoreFence(object, newShape); + } else { + location.setSafe(object, value, guardCondition, false); } c.maybeUpdateShape(object); return true; @@ -1284,64 +1263,48 @@ protected boolean putIntImpl(DynamicObject object, Shape cachedShape, Object key if (location.isIntLocation()) { if (newShape != oldShape) { ACCESS.grow(object, oldShape, newShape); + location.setIntSafe(object, value, guardCondition, true); + ACCESS.setShapeWithStoreFence(object, newShape); } else if (location.isFinal()) { continue; - } - try { - location.setInt(object, value, guardCondition); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } - if (newShape != oldShape) { - ACCESS.setShapeWithStoreFence(object, newShape); + } else { + location.setIntSafe(object, value, guardCondition, false); } c.maybeUpdateShape(object); return true; } else if (location.isImplicitCastIntToLong()) { if (newShape != oldShape) { ACCESS.grow(object, oldShape, newShape); + location.setLongSafe(object, value, guardCondition, true); + ACCESS.setShapeWithStoreFence(object, newShape); } else if (location.isFinal()) { continue; - } - try { - location.setLong(object, value, guardCondition); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } - if (newShape != oldShape) { - ACCESS.setShapeWithStoreFence(object, newShape); + } else { + location.setLongSafe(object, value, guardCondition, false); } c.maybeUpdateShape(object); return true; } else if (location.isImplicitCastIntToDouble()) { if (newShape != oldShape) { ACCESS.grow(object, oldShape, newShape); + location.setDoubleSafe(object, value, guardCondition, true); + ACCESS.setShapeWithStoreFence(object, newShape); } else if (location.isFinal()) { continue; - } - try { - location.setDouble(object, value, guardCondition); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } - if (newShape != oldShape) { - ACCESS.setShapeWithStoreFence(object, newShape); + } else { + location.setDoubleSafe(object, value, guardCondition, false); } c.maybeUpdateShape(object); return true; } else if (location.canStore(value)) { if (newShape != oldShape) { ACCESS.grow(object, oldShape, newShape); + location.setSafe(object, value, guardCondition, true); + ACCESS.setShapeWithStoreFence(object, newShape); } else if (location.isFinal()) { continue; - } - try { - location.set(object, value, guardCondition); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } - if (newShape != oldShape) { - ACCESS.setShapeWithStoreFence(object, newShape); + } else { + location.setSafe(object, value, guardCondition, false); } c.maybeUpdateShape(object); return true; @@ -1374,16 +1337,12 @@ protected boolean putLongImpl(DynamicObject object, Shape cachedShape, Object ke Shape newShape = c.newShape; if (newShape != oldShape) { ACCESS.grow(object, oldShape, newShape); + location.setLongSafe(object, value, guardCondition, true); + ACCESS.setShapeWithStoreFence(object, newShape); } else if (location.isFinal()) { continue; - } - try { - location.setLong(object, value, guardCondition); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } - if (newShape != oldShape) { - ACCESS.setShapeWithStoreFence(object, newShape); + } else { + location.setLongSafe(object, value, guardCondition, false); } c.maybeUpdateShape(object); return true; @@ -1391,16 +1350,12 @@ protected boolean putLongImpl(DynamicObject object, Shape cachedShape, Object ke Shape newShape = c.newShape; if (newShape != oldShape) { ACCESS.grow(object, oldShape, newShape); + location.setSafe(object, value, guardCondition, true); + ACCESS.setShapeWithStoreFence(object, newShape); } else if (location.isFinal()) { continue; - } - try { - location.set(object, value, guardCondition); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } - if (newShape != oldShape) { - ACCESS.setShapeWithStoreFence(object, newShape); + } else { + location.setSafe(object, value, guardCondition, false); } c.maybeUpdateShape(object); return true; @@ -1433,16 +1388,12 @@ protected boolean putDoubleImpl(DynamicObject object, Shape cachedShape, Object Shape newShape = c.newShape; if (newShape != oldShape) { ACCESS.grow(object, oldShape, newShape); + location.setDoubleSafe(object, value, guardCondition, true); + ACCESS.setShapeWithStoreFence(object, newShape); } else if (location.isFinal()) { continue; - } - try { - location.setDouble(object, value, guardCondition); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } - if (newShape != oldShape) { - ACCESS.setShapeWithStoreFence(object, newShape); + } else { + location.setDoubleSafe(object, value, guardCondition, false); } c.maybeUpdateShape(object); return true; @@ -1450,16 +1401,12 @@ protected boolean putDoubleImpl(DynamicObject object, Shape cachedShape, Object Shape newShape = c.newShape; if (newShape != oldShape) { ACCESS.grow(object, oldShape, newShape); + location.setSafe(object, value, guardCondition, true); + ACCESS.setShapeWithStoreFence(object, newShape); } else if (location.isFinal()) { continue; - } - try { - location.set(object, value, guardCondition); - } catch (IncompatibleLocationException | FinalLocationException e) { - throw shouldNotHappen(e); - } - if (newShape != oldShape) { - ACCESS.setShapeWithStoreFence(object, newShape); + } else { + location.setSafe(object, value, guardCondition, false); } c.maybeUpdateShape(object); return true; @@ -1703,11 +1650,6 @@ static > T filterValid(T cache) { } } - static RuntimeException shouldNotHappen(Exception e) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw new IllegalStateException(e); - } - abstract static class CacheData> { final T next; diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java index d85d1e197149..ed40279f81a5 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java @@ -41,6 +41,7 @@ package com.oracle.truffle.object; import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.object.DynamicObject; @@ -86,7 +87,7 @@ public interface LocationVisitor { /** @since 0.17 or earlier */ @Override public void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException { - set(store, value, checkShape(store, shape)); + set(store, value, checkShape(store, shape), false); } @Override @@ -96,7 +97,7 @@ public void set(DynamicObject store, Object value, Shape oldShape, Shape newShap try { setInternal(store, value); } catch (IncompatibleLocationException ex) { - throw DynamicObjectLibraryImpl.shouldNotHappen(ex); + throw shouldNotHappen(ex); } LayoutImpl.ACCESS.setShapeWithStoreFence(store, newShape); } else { @@ -113,33 +114,75 @@ protected final Object getInternal(DynamicObject store) { /** * Get object value as object at this location in store. For internal use only. * - * @param condition the result of a shape check or {@code false} + * @param guard the result of a shape check or {@code false} */ @Override - public abstract Object get(DynamicObject store, boolean condition); + public abstract Object get(DynamicObject store, boolean guard); - protected long getLong(DynamicObject store, boolean condition) throws UnexpectedResultException { - return expectLong(get(store, condition)); + /** + * @see #get(DynamicObject, boolean) + */ + protected long getLong(DynamicObject store, boolean guard) throws UnexpectedResultException { + return expectLong(get(store, guard)); } - protected int getInt(DynamicObject store, boolean condition) throws UnexpectedResultException { - return expectInteger(get(store, condition)); + /** + * @see #get(DynamicObject, boolean) + */ + protected int getInt(DynamicObject store, boolean guard) throws UnexpectedResultException { + return expectInteger(get(store, guard)); } - protected double getDouble(DynamicObject store, boolean condition) throws UnexpectedResultException { - return expectDouble(get(store, condition)); + /** + * @see #get(DynamicObject, boolean) + */ + protected double getDouble(DynamicObject store, boolean guard) throws UnexpectedResultException { + return expectDouble(get(store, guard)); } - protected boolean getBoolean(DynamicObject store, boolean condition) throws UnexpectedResultException { - return expectBoolean(get(store, condition)); + /** + * @see #get(DynamicObject, boolean) + */ + protected boolean getBoolean(DynamicObject store, boolean guard) throws UnexpectedResultException { + return expectBoolean(get(store, guard)); } - @SuppressWarnings("unused") - protected void set(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException, FinalLocationException { - setInternal(store, value, condition); + /** + * Sets the value of this property storage location. + * + * @param store the {@link DynamicObject} that holds this storage location. + * @param value the value to be stored. + * @param guard the result of the shape check guarding this property write or {@code false}. + * @param init if true, this is the initial assignment of a property location; ignore final. + * @throws IncompatibleLocationException if the value cannot be stored in this storage location. + * @throws FinalLocationException if the property location is effectively final and init=false. + * @see #setSafe(DynamicObject, Object, boolean, boolean) + */ + protected abstract void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException; + + /** + * @see #set(DynamicObject, Object, boolean, boolean) + * @see #setIntSafe(DynamicObject, int, boolean, boolean) + */ + protected void setInt(DynamicObject store, int value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { + set(store, value, guard, init); + } + + /** + * @see #set(DynamicObject, Object, boolean, boolean) + * @see #setLongSafe(DynamicObject, long, boolean, boolean) + */ + protected void setLong(DynamicObject store, long value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { + set(store, value, guard, init); } - protected abstract void setInternal(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException; + /** + * @see #set(DynamicObject, Object, boolean, boolean) + * @see #setDoubleSafe(DynamicObject, double, boolean, boolean) + */ + protected void setDouble(DynamicObject store, double value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { + set(store, value, guard, init); + } /** * Equivalent to {@link Shape#check(DynamicObject)}. @@ -151,7 +194,11 @@ protected static final boolean checkShape(DynamicObject store, Shape shape) { /** @since 0.17 or earlier */ @Override protected final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException { - setInternal(store, value, false); + try { + set(store, value, false, true); + } catch (FinalLocationException e) { + throw shouldNotHappen(e); + } } /** @since 0.17 or earlier */ @@ -279,19 +326,48 @@ static boolean isSameLocation(LocationImpl loc1, LocationImpl loc2) { return loc1 == loc2 || loc1.getInternalLocation().equals(loc2.getInternalLocation()); } - @SuppressWarnings("unused") - protected void setInt(DynamicObject store, int value, boolean condition) throws IncompatibleLocationException, FinalLocationException { - set(store, value, condition); + /** + * @see #set(DynamicObject, Object, boolean, boolean) + */ + protected final void setSafe(DynamicObject store, Object value, boolean guard, boolean init) { + try { + set(store, value, guard, init); + } catch (IncompatibleLocationException | FinalLocationException e) { + throw shouldNotHappen(e); + } } - @SuppressWarnings("unused") - protected void setLong(DynamicObject store, long value, boolean condition) throws IncompatibleLocationException, FinalLocationException { - set(store, value, condition); + /** + * @see #setInt(DynamicObject, int, boolean, boolean) + */ + protected final void setIntSafe(DynamicObject store, int value, boolean guard, boolean init) { + try { + setInt(store, value, guard, init); + } catch (IncompatibleLocationException | FinalLocationException e) { + throw shouldNotHappen(e); + } } - @SuppressWarnings("unused") - protected void setDouble(DynamicObject store, double value, boolean condition) throws IncompatibleLocationException, FinalLocationException { - set(store, value, condition); + /** + * @see #setLong(DynamicObject, long, boolean, boolean) + */ + protected final void setLongSafe(DynamicObject store, long value, boolean guard, boolean init) { + try { + setLong(store, value, guard, init); + } catch (IncompatibleLocationException | FinalLocationException e) { + throw shouldNotHappen(e); + } + } + + /** + * @see #setDouble(DynamicObject, double, boolean, boolean) + */ + protected final void setDoubleSafe(DynamicObject store, double value, boolean guard, boolean init) { + try { + setDouble(store, value, guard, init); + } catch (IncompatibleLocationException | FinalLocationException e) { + throw shouldNotHappen(e); + } } protected boolean isIntLocation() { @@ -358,6 +434,11 @@ public Assumption getFinalAssumption() { return neverValidAssumption(); } + protected static RuntimeException shouldNotHappen(Exception e) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw new IllegalStateException(e); + } + /** Not using NeverValidAssumption.INSTANCE in order not to pollute profiles. */ protected static Assumption neverValidAssumption() { return NEVER_VALID_ASSUMPTION; diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java index f585d2b76bdc..649f765c3c10 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -95,18 +95,10 @@ public boolean equals(Object obj) { /** @since 0.17 or earlier */ @Override - public final Object get(DynamicObject store, boolean condition) { + public final Object get(DynamicObject store, boolean guard) { return value; } - /** @since 0.17 or earlier */ - @Override - public final void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException { - if (!canStore(value)) { - throw finalLocation(); - } - } - /** @since 0.17 or earlier */ @SuppressWarnings("deprecation") @Override @@ -114,12 +106,15 @@ public boolean canStore(Object val) { return CoreLocation.valueEquals(this.value, val); } - /** @since 0.17 or earlier */ @Override - public final void setInternal(DynamicObject store, Object value, boolean condition) throws IncompatibleLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { if (!canStore(value)) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throw new UnsupportedOperationException(); + if (init) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw new UnsupportedOperationException(); + } else { + throw finalLocation(); + } } } From d77b8f758ca65386d496015ae82b15cf8e9cedb2 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 23 Sep 2021 17:42:06 +0200 Subject: [PATCH 124/681] Simplify DynamicObjectSupport.grow method. --- .../truffle/object/DynamicObjectSupport.java | 125 ++++++++---------- 1 file changed, 57 insertions(+), 68 deletions(-) diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectSupport.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectSupport.java index 103fa0186762..8659c0609303 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectSupport.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectSupport.java @@ -52,20 +52,49 @@ import com.oracle.truffle.api.object.Property; import com.oracle.truffle.api.object.Shape; -@SuppressWarnings({"static-method", "deprecation"}) +@SuppressWarnings("deprecation") final class DynamicObjectSupport { private DynamicObjectSupport() { } static void ensureCapacity(DynamicObject object, Shape otherShape) { - growObjectStore(object, object.getShape(), otherShape); - growPrimitiveStore(object, object.getShape(), otherShape); + grow(object, object.getShape(), otherShape); } static void grow(DynamicObject object, Shape thisShape, Shape otherShape) { - growObjectStore(object, thisShape, otherShape); - growPrimitiveStore(object, thisShape, otherShape); + ShapeImpl thisShapeImpl = (ShapeImpl) thisShape; + ShapeImpl otherShapeImpl = (ShapeImpl) otherShape; + int sourceObjectCapacity = thisShapeImpl.getObjectArrayCapacity(); + int targetObjectCapacity = otherShapeImpl.getObjectArrayCapacity(); + if (sourceObjectCapacity < targetObjectCapacity) { + growObjectStore(object, thisShapeImpl, sourceObjectCapacity, targetObjectCapacity); + } + int sourcePrimitiveCapacity = thisShapeImpl.getPrimitiveArrayCapacity(); + int targetPrimitiveCapacity = otherShapeImpl.getPrimitiveArrayCapacity(); + if (sourcePrimitiveCapacity < targetPrimitiveCapacity) { + growPrimitiveStore(object, thisShapeImpl, sourcePrimitiveCapacity, targetPrimitiveCapacity); + } + } + + private static void growObjectStore(DynamicObject object, ShapeImpl thisShape, int sourceCapacity, int targetCapacity) { + Object[] newObjectStore = new Object[targetCapacity]; + if (sourceCapacity != 0) { + int sourceSize = thisShape.getObjectArraySize(); + Object[] oldObjectStore = ACCESS.getObjectArray(object); + ACCESS.arrayCopy(oldObjectStore, newObjectStore, sourceSize); + } + ACCESS.setObjectArray(object, newObjectStore); + } + + private static void growPrimitiveStore(DynamicObject object, ShapeImpl thisShape, int sourceCapacity, int targetCapacity) { + int[] newPrimitiveArray = new int[targetCapacity]; + if (sourceCapacity != 0) { + int sourceSize = thisShape.getPrimitiveArraySize(); + int[] oldPrimitiveArray = ACCESS.getPrimitiveArray(object); + ACCESS.arrayCopy(oldPrimitiveArray, newPrimitiveArray, sourceSize); + } + ACCESS.setPrimitiveArray(object, newPrimitiveArray); } static void resize(DynamicObject object, Shape thisShape, Shape otherShape) { @@ -78,32 +107,20 @@ static void trimToSize(DynamicObject object, Shape thisShape, Shape otherShape) trimPrimitiveStore(object, thisShape, otherShape); } - private static void growObjectStore(DynamicObject object, Shape oldShape, Shape newShape) { - int sourceCapacity = getObjectArrayCapacity(oldShape); - int destinationCapacity = getObjectArrayCapacity(newShape); - if (sourceCapacity < destinationCapacity) { - Object[] newObjectStore = new Object[destinationCapacity]; - if (sourceCapacity != 0) { - int sourceSize = getObjectArraySize(oldShape); - Object[] oldObjectStore = ACCESS.getObjectArray(object); - ACCESS.arrayCopy(oldObjectStore, newObjectStore, sourceSize); - } - ACCESS.setObjectArray(object, newObjectStore); - } - } - private static void resizeObjectStore(DynamicObject object, Shape oldShape, Shape newShape) { - int destinationCapacity = getObjectArrayCapacity(newShape); + ShapeImpl oldShapeImpl = (ShapeImpl) oldShape; + ShapeImpl newShapeImpl = (ShapeImpl) newShape; + int destinationCapacity = newShapeImpl.getObjectArrayCapacity(); if (destinationCapacity == 0) { ACCESS.setObjectArray(object, null); } else { - int sourceCapacity = getObjectArrayCapacity(oldShape); + int sourceCapacity = oldShapeImpl.getObjectArrayCapacity(); if (sourceCapacity != destinationCapacity) { - int sourceSize = getObjectArraySize(oldShape); + int sourceSize = oldShapeImpl.getObjectArraySize(); Object[] newObjectStore = new Object[destinationCapacity]; if (sourceSize != 0) { Object[] oldObjectStore = ACCESS.getObjectArray(object); - int destinationSize = getObjectArraySize(newShape); + int destinationSize = newShapeImpl.getObjectArraySize(); int length = Math.min(sourceSize, destinationSize); ACCESS.arrayCopy(oldObjectStore, newObjectStore, length); } @@ -112,33 +129,21 @@ private static void resizeObjectStore(DynamicObject object, Shape oldShape, Shap } } - private static void growPrimitiveStore(DynamicObject object, Shape oldShape, Shape newShape) { - int sourceCapacity = getPrimitiveArrayCapacity(oldShape); - int destinationCapacity = getPrimitiveArrayCapacity(newShape); - if (sourceCapacity < destinationCapacity) { - int[] newPrimitiveArray = new int[destinationCapacity]; - if (sourceCapacity != 0) { - int sourceSize = getPrimitiveArraySize(oldShape); - int[] oldPrimitiveArray = ACCESS.getPrimitiveArray(object); - ACCESS.arrayCopy(oldPrimitiveArray, newPrimitiveArray, sourceSize); - } - ACCESS.setPrimitiveArray(object, newPrimitiveArray); - } - } - private static void resizePrimitiveStore(DynamicObject object, Shape oldShape, Shape newShape) { - assert hasPrimitiveArray(newShape); - int destinationCapacity = getPrimitiveArrayCapacity(newShape); + ShapeImpl oldShapeImpl = (ShapeImpl) oldShape; + ShapeImpl newShapeImpl = (ShapeImpl) newShape; + assert newShapeImpl.hasPrimitiveArray(); + int destinationCapacity = newShapeImpl.getPrimitiveArrayCapacity(); if (destinationCapacity == 0) { ACCESS.setPrimitiveArray(object, null); } else { - int sourceCapacity = getPrimitiveArrayCapacity(oldShape); + int sourceCapacity = oldShapeImpl.getPrimitiveArrayCapacity(); if (sourceCapacity != destinationCapacity) { - int sourceSize = getPrimitiveArraySize(oldShape); + int sourceSize = oldShapeImpl.getPrimitiveArraySize(); int[] newPrimitiveArray = new int[destinationCapacity]; if (sourceSize != 0) { int[] oldPrimitiveArray = ACCESS.getPrimitiveArray(object); - int destinationSize = getPrimitiveArraySize(newShape); + int destinationSize = newShapeImpl.getPrimitiveArraySize(); int length = Math.min(sourceSize, destinationSize); ACCESS.arrayCopy(oldPrimitiveArray, newPrimitiveArray, length); } @@ -148,18 +153,20 @@ private static void resizePrimitiveStore(DynamicObject object, Shape oldShape, S } private static void trimObjectStore(DynamicObject object, Shape thisShape, Shape newShape) { + ShapeImpl thisShapeImpl = (ShapeImpl) thisShape; + ShapeImpl newShapeImpl = (ShapeImpl) newShape; Object[] oldObjectStore = ACCESS.getObjectArray(object); - int destinationCapacity = getObjectArrayCapacity(newShape); + int destinationCapacity = newShapeImpl.getObjectArrayCapacity(); if (destinationCapacity == 0) { if (oldObjectStore != null) { ACCESS.setObjectArray(object, null); } // else nothing to do } else { - int sourceCapacity = getObjectArrayCapacity(thisShape); + int sourceCapacity = thisShapeImpl.getObjectArrayCapacity(); if (sourceCapacity > destinationCapacity) { Object[] newObjectStore = new Object[destinationCapacity]; - int destinationSize = getObjectArraySize(newShape); + int destinationSize = newShapeImpl.getObjectArraySize(); ACCESS.arrayCopy(oldObjectStore, newObjectStore, destinationSize); ACCESS.setObjectArray(object, newObjectStore); } @@ -167,44 +174,26 @@ private static void trimObjectStore(DynamicObject object, Shape thisShape, Shape } private static void trimPrimitiveStore(DynamicObject object, Shape thisShape, Shape newShape) { + ShapeImpl thisShapeImpl = (ShapeImpl) thisShape; + ShapeImpl newShapeImpl = (ShapeImpl) newShape; int[] oldPrimitiveStore = ACCESS.getPrimitiveArray(object); - int destinationCapacity = getPrimitiveArrayCapacity(newShape); + int destinationCapacity = newShapeImpl.getPrimitiveArrayCapacity(); if (destinationCapacity == 0) { if (oldPrimitiveStore != null) { ACCESS.setPrimitiveArray(object, null); } // else nothing to do } else { - int sourceCapacity = getPrimitiveArrayCapacity(thisShape); + int sourceCapacity = thisShapeImpl.getPrimitiveArrayCapacity(); if (sourceCapacity > destinationCapacity) { int[] newPrimitiveStore = new int[destinationCapacity]; - int destinationSize = getPrimitiveArraySize(newShape); + int destinationSize = newShapeImpl.getPrimitiveArraySize(); ACCESS.arrayCopy(oldPrimitiveStore, newPrimitiveStore, destinationSize); ACCESS.setPrimitiveArray(object, newPrimitiveStore); } } } - private static int getObjectArrayCapacity(Shape shape) { - return ((ShapeImpl) shape).getObjectArrayCapacity(); - } - - private static int getObjectArraySize(Shape shape) { - return ((ShapeImpl) shape).getObjectArraySize(); - } - - private static int getPrimitiveArrayCapacity(Shape shape) { - return ((ShapeImpl) shape).getPrimitiveArrayCapacity(); - } - - private static int getPrimitiveArraySize(Shape shape) { - return ((ShapeImpl) shape).getPrimitiveArraySize(); - } - - private static boolean hasPrimitiveArray(Shape shape) { - return ((ShapeImpl) shape).hasPrimitiveArray(); - } - static Map archive(DynamicObject object) { Map archive = new HashMap<>(); Property[] properties = ((ShapeImpl) object.getShape()).getPropertyArray(); From 369330939957d6dc4c3d0a44489b3387d1168832 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 23 Sep 2021 17:49:45 +0200 Subject: [PATCH 125/681] Make leaf classes final. --- .../object/DynamicObjectLibraryImpl.java | 8 ++--- .../oracle/truffle/object/PropertyImpl.java | 36 ++++++++----------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java index 7b697ff15259..ec5932ebc900 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectLibraryImpl.java @@ -566,7 +566,7 @@ public boolean acceptsKey(@SuppressWarnings("unused") Object key) { } } - static class Generic extends KeyCacheEntry { + static final class Generic extends KeyCacheEntry { private static final Generic INSTANCE = new Generic(); Generic() { @@ -696,7 +696,7 @@ public boolean removeKey(DynamicObject obj, Shape cachedShape, Object key) { * The generic case is used if the number of property keys accessed overflows the limit of the * polymorphic inline cache. */ - static class AnyKey extends KeyCacheNode { + static final class AnyKey extends KeyCacheNode { @Child private KeyCacheEntry keyCache; @@ -1169,7 +1169,7 @@ public boolean removeKey(DynamicObject object, Shape cachedShape, Object key) { } } - static class ExistingKeyIdentity extends ExistingKey { + static final class ExistingKeyIdentity extends ExistingKey { ExistingKeyIdentity(Object key, Property property, KeyCacheEntry next) { super(key, property, next); } @@ -1185,7 +1185,7 @@ boolean isIdentity() { } } - static class MissingKeyIdentity extends MissingKey { + static final class MissingKeyIdentity extends MissingKey { MissingKeyIdentity(Object key, KeyCacheEntry next) { super(key, next); } diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java index 8115e9b57391..affaefec1966 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java @@ -58,7 +58,7 @@ * @since 0.17 or earlier */ @SuppressWarnings("deprecation") -public class PropertyImpl extends Property { +public final class PropertyImpl extends Property { private final Object key; private final Location location; private final int flags; @@ -80,7 +80,7 @@ public class PropertyImpl extends Property { /** @since 0.17 or earlier */ @Override - public final Object getKey() { + public Object getKey() { return key; } @@ -94,26 +94,26 @@ public int getFlags() { @Override public Property relocate(Location newLocation) { if (!getLocation().equals(newLocation)) { - return construct(key, newLocation, flags); + return new PropertyImpl(key, newLocation, flags); } return this; } /** @since 0.17 or earlier */ @Override - public final Object get(DynamicObject store, Shape shape) { + public Object get(DynamicObject store, Shape shape) { return getLocation().get(store, shape); } /** @since 0.17 or earlier */ @Override - public final Object get(DynamicObject store, boolean condition) { + public Object get(DynamicObject store, boolean condition) { return getLocation().get(store, condition); } /** @since 0.17 or earlier */ @Override - public final void setInternal(DynamicObject store, Object value) { + public void setInternal(DynamicObject store, Object value) { try { ((LocationImpl) getLocation()).setInternal(store, value); } catch (IncompatibleLocationException e) { @@ -128,14 +128,14 @@ private static boolean verifyShapeParameter(DynamicObject store, Shape shape) { /** @since 0.17 or earlier */ @Override - public final void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException { + public void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException { assert verifyShapeParameter(store, shape); getLocation().set(store, value, shape); } /** @since 0.17 or earlier */ @Override - public final void setSafe(DynamicObject store, Object value, Shape shape) { + public void setSafe(DynamicObject store, Object value, Shape shape) { assert verifyShapeParameter(store, shape); try { getLocation().set(store, value, shape); @@ -146,7 +146,7 @@ public final void setSafe(DynamicObject store, Object value, Shape shape) { /** @since 0.17 or earlier */ @Override - public final void setGeneric(DynamicObject store, Object value, Shape shape) { + public void setGeneric(DynamicObject store, Object value, Shape shape) { assert verifyShapeParameter(store, shape); try { set(store, value, shape); @@ -163,14 +163,14 @@ private static boolean verifyShapeParameters(DynamicObject store, Shape oldShape /** @since 0.17 or earlier */ @Override - public final void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException { + public void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException { assert verifyShapeParameters(store, oldShape, newShape); getLocation().set(store, value, oldShape, newShape); } /** @since 0.17 or earlier */ @Override - public final void setSafe(DynamicObject store, Object value, Shape oldShape, Shape newShape) { + public void setSafe(DynamicObject store, Object value, Shape oldShape, Shape newShape) { assert verifyShapeParameters(store, oldShape, newShape); try { getLocation().set(store, value, oldShape, newShape); @@ -181,7 +181,7 @@ public final void setSafe(DynamicObject store, Object value, Shape oldShape, Sha /** @since 0.17 or earlier */ @Override - public final void setGeneric(DynamicObject store, Object value, Shape oldShape, Shape newShape) { + public void setGeneric(DynamicObject store, Object value, Shape oldShape, Shape newShape) { assert verifyShapeParameters(store, oldShape, newShape); try { getLocation().set(store, value, oldShape, newShape); @@ -243,7 +243,7 @@ public String toString() { /** @since 0.17 or earlier */ @Override - public final Location getLocation() { + public Location getLocation() { return location; } @@ -259,20 +259,14 @@ private void setWithShapeSlowCase(DynamicObject store, Object value, Shape curre /** @since 0.17 or earlier */ @Override - public final boolean isHidden() { + public boolean isHidden() { return key instanceof HiddenKey; } - /** @since 0.17 or earlier */ - @SuppressWarnings("hiding") - protected Property construct(Object name, Location location, int flags) { - return new PropertyImpl(name, location, flags); - } - /** @since 0.17 or earlier */ @Override public Property copyWithFlags(int newFlags) { - return construct(key, location, newFlags); + return new PropertyImpl(key, location, newFlags); } /** @since 0.17 or earlier */ From 7668e0370995d6f53d4bec0ead349080ac49a4f5 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 23 Sep 2021 19:05:35 +0200 Subject: [PATCH 126/681] Remove legacy DynamicObject grow/resize code. --- .../truffle/object/DynamicObjectBasic.java | 88 ------------------- .../truffle/object/DynamicObjectImpl.java | 22 +---- 2 files changed, 2 insertions(+), 108 deletions(-) diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectBasic.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectBasic.java index 35845839be7d..73abc95bc509 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectBasic.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectBasic.java @@ -74,76 +74,6 @@ protected final void initialize(Shape shape) { } } - /** - * Simpler version of {@link #resizeObjectStore} when the object is only increasing in size. - */ - @Override - protected final void growObjectStore(Shape oldShape, Shape newShape) { - int oldObjectArrayCapacity = ((ShapeImpl) oldShape).getObjectArrayCapacity(); - int newObjectArrayCapacity = ((ShapeImpl) newShape).getObjectArrayCapacity(); - if (oldObjectArrayCapacity != newObjectArrayCapacity) { - growObjectStoreIntl(oldObjectArrayCapacity, newObjectArrayCapacity, oldShape); - } - } - - private void growObjectStoreIntl(int oldObjectArrayCapacity, int newObjectArrayCapacity, Shape newShape) { - Object[] newObjectStore = new Object[newObjectArrayCapacity]; - if (oldObjectArrayCapacity != 0) { - // monotonic growth assumption - assert oldObjectArrayCapacity < newObjectArrayCapacity; - Object[] oldObjectStore = this.getObjectStore(newShape); - for (int i = 0; i < oldObjectArrayCapacity; ++i) { - newObjectStore[i] = oldObjectStore[i]; - } - } - this.setObjectStore(newObjectStore, newShape); - } - - /** - * Simpler version of {@link #resizePrimitiveStore} when the object is only increasing in size. - */ - @Override - protected final void growPrimitiveStore(Shape oldShape, Shape newShape) { - assert ((ShapeImpl) newShape).hasPrimitiveArray(); - int oldPrimitiveCapacity = ((ShapeImpl) oldShape).getPrimitiveArrayCapacity(); - int newPrimitiveCapacity = ((ShapeImpl) newShape).getPrimitiveArrayCapacity(); - if (newPrimitiveCapacity == 0) { - // due to obsolescence, we might have to reserve an empty primitive array slot - this.setPrimitiveStore(null, newShape); - } else if (oldPrimitiveCapacity != newPrimitiveCapacity) { - growPrimitiveStoreIntl(oldPrimitiveCapacity, newPrimitiveCapacity, oldShape); - } - } - - private void growPrimitiveStoreIntl(int oldPrimitiveCapacity, int newPrimitiveCapacity, Shape newShape) { - int[] newPrimitiveArray = new int[newPrimitiveCapacity]; - if (oldPrimitiveCapacity != 0) { - // primitive array can shrink due to type changes - int[] oldPrimitiveArray = this.getPrimitiveStore(newShape); - for (int i = 0; i < Math.min(oldPrimitiveCapacity, newPrimitiveCapacity); ++i) { - newPrimitiveArray[i] = oldPrimitiveArray[i]; - } - } - this.setPrimitiveStore(newPrimitiveArray, newShape); - } - - @Override - protected final void resizeObjectStore(Shape oldShape, Shape newShape) { - Object[] newObjectStore = null; - int destinationCapacity = ((ShapeImpl) newShape).getObjectArrayCapacity(); - if (destinationCapacity != 0) { - newObjectStore = new Object[destinationCapacity]; - int sourceCapacity = ((ShapeImpl) oldShape).getObjectArrayCapacity(); - if (sourceCapacity != 0) { - Object[] oldObjectStore = getObjectStore(newShape); - for (int i = 0; i < Math.min(sourceCapacity, destinationCapacity); ++i) { - newObjectStore[i] = oldObjectStore[i]; - } - } - } - this.setObjectStore(newObjectStore, newShape); - } - private Object[] getObjectStore(@SuppressWarnings("unused") Shape currentShape) { return LayoutImpl.ACCESS.getObjectArray(this); } @@ -160,24 +90,6 @@ private void setPrimitiveStore(int[] newArray, @SuppressWarnings("unused") Shape LayoutImpl.ACCESS.setPrimitiveArray(this, newArray); } - @Override - protected final void resizePrimitiveStore(Shape oldShape, Shape newShape) { - assert ((ShapeImpl) newShape).hasPrimitiveArray(); - int[] newPrimitiveArray = null; - int destinationCapacity = ((ShapeImpl) newShape).getPrimitiveArrayCapacity(); - if (destinationCapacity != 0) { - newPrimitiveArray = new int[destinationCapacity]; - int sourceCapacity = ((ShapeImpl) oldShape).getPrimitiveArrayCapacity(); - if (sourceCapacity != 0) { - int[] oldPrimitiveArray = this.getPrimitiveStore(newShape); - for (int i = 0; i < Math.min(sourceCapacity, destinationCapacity); ++i) { - newPrimitiveArray[i] = oldPrimitiveArray[i]; - } - } - } - this.setPrimitiveStore(newPrimitiveArray, newShape); - } - /** * Check whether fast transition is valid. * diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java index dafa8135e336..246981ce9fd6 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java @@ -126,31 +126,13 @@ public final void setShapeAndGrow(Shape oldShape, Shape newShape) { * Simpler version of {@link #resizeStore} when the object is only increasing in size. */ private void growStore(Shape oldShape, Shape newShape) { - growObjectStore(oldShape, newShape); - if (((ShapeImpl) newShape).hasPrimitiveArray) { - growPrimitiveStore(oldShape, newShape); - } + DynamicObjectSupport.grow(this, oldShape, newShape); } - /** @since 0.17 or earlier */ - protected abstract void growObjectStore(Shape oldShape, Shape newShape); - - /** @since 0.17 or earlier */ - protected abstract void growPrimitiveStore(Shape oldShape, Shape newShape); - protected void resizeStore(Shape oldShape, Shape newShape) { - resizeObjectStore(oldShape, newShape); - if (((ShapeImpl) newShape).hasPrimitiveArray) { - resizePrimitiveStore(oldShape, newShape); - } + DynamicObjectSupport.resize(this, oldShape, newShape); } - /** @since 0.17 or earlier */ - protected abstract void resizePrimitiveStore(Shape oldShape, Shape newShape); - - /** @since 0.17 or earlier */ - protected abstract void resizeObjectStore(Shape oldShape, Shape newShape); - /** * Check whether fast transition is valid. * From 8380dd90cf13d1da2f993af711a395e462f0ff38 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 23 Sep 2021 19:55:11 +0200 Subject: [PATCH 127/681] Assert that always valid assumption is valid. --- .../src/com/oracle/truffle/object/LocationImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java index ed40279f81a5..dbf67e3751c6 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java @@ -446,6 +446,7 @@ protected static Assumption neverValidAssumption() { /** Not using AlwaysValidAssumption.INSTANCE in order not to pollute profiles. */ protected static Assumption alwaysValidAssumption() { + assert ALWAYS_VALID_ASSUMPTION.isValid(); return ALWAYS_VALID_ASSUMPTION; } From 8b871e7d849b1c1582a4635ba4a8a8c300619e5c Mon Sep 17 00:00:00 2001 From: Andrew Graham Date: Wed, 21 Apr 2021 14:12:21 +0100 Subject: [PATCH 128/681] AArch64: Changes to combine shift and negate to a single instruction. Add three node match rules to handle the three varieties of shift, together with capability to emit a combined negate instruction with shift. Change-Id: I151b787742d1d7ff0401ab9270af9f000e736d53 --- .../asm/aarch64/AArch64MacroAssembler.java | 17 ++- .../aarch64/test/AArch64BitFieldTest.java | 6 +- .../aarch64/test/AArch64NegateShiftTest.java | 102 ++++++++++++++++++ .../core/aarch64/AArch64NodeMatchRules.java | 19 +++- .../lir/aarch64/AArch64ArithmeticOp.java | 30 +++++- 5 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64NegateShiftTest.java diff --git a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java index 82e56e994a80..2de2d574e462 100755 --- a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java +++ b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java @@ -965,7 +965,7 @@ public void add(int size, Register dst, Register src1, Register src2, ShiftType } /** - * dst = src1 + shiftType(src2, shiftAmt & (size-1)) and sets condition flags. + * dst = src1 - shiftType(src2, shiftAmt & (size-1)) and sets condition flags. * * @param size register size. Has to be 32 or 64. * @param dst general purpose register. May not be null or stackpointer. @@ -986,7 +986,7 @@ public void sub(int size, Register dst, Register src1, Register src2, ShiftType } /** - * dst = -src1. + * dst = -src. * * @param size register size. Has to be 32 or 64. * @param dst general purpose register. May not be null or stackpointer. @@ -996,6 +996,19 @@ public void neg(int size, Register dst, Register src) { sub(size, dst, zr, src); } + /** + * dst = -(shiftType(src, shiftAmt & (size - 1))). + * + * @param size register size. Has to be 32 or 64. + * @param dst general purpose register. May not be null or stackpointer. + * @param src general purpose register. May not be null or stackpointer. + * @param shiftType right or left shift, arithmetic or logical. + * @param shiftAmt number of shift bits. Has to be between 0 and (size - 1). + */ + public void neg(int size, Register dst, Register src, ShiftType shiftType, int shiftAmt) { + sub(size, dst, zr, src, shiftType, shiftAmt); + } + /** * dst = src + immediate. * diff --git a/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64BitFieldTest.java b/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64BitFieldTest.java index 7212af4f80fd..18ed28f5b4bd 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64BitFieldTest.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64BitFieldTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2019, 2020, Arm Limited and affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Arm Limited and 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 @@ -207,7 +207,7 @@ public void testSignedI2LInsert() { // SBFIZ with B2I. public int signedB2IInsert(int input) { byte b = (byte) input; - return b << 31; + return b << 30; } @Test diff --git a/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64NegateShiftTest.java b/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64NegateShiftTest.java new file mode 100644 index 000000000000..0f74f5096bc7 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64NegateShiftTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Arm Limited and 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 org.graalvm.compiler.core.aarch64.test; + +import org.graalvm.compiler.lir.LIRInstruction; +import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp; +import org.junit.Test; + +import java.util.function.Predicate; + +public class AArch64NegateShiftTest extends AArch64MatchRuleTest { + private static final Predicate predicate = op -> (op instanceof AArch64ArithmeticOp.NegShiftOp); + + /** + * negateShift match rule tests for shift operations with int type. + */ + public int negShiftLeftLogicInt(int input) { + return -(input << 5); + } + + @Test + public void testNegShiftLeftLogicInt() { + test("negShiftLeftLogicInt", 123); + checkLIR("negShiftLeftLogicInt", predicate, 1); + } + + public int negShiftRightLogicInt(int input) { + return -(input >>> 6); + } + + @Test + public void testNegShiftRightLogicInt() { + test("negShiftRightLogicInt", 123); + checkLIR("negShiftRightLogicInt", predicate, 1); + } + + public int negShiftRightArithInt(int input) { + return -(input >> 7); + } + + @Test + public void testNegShiftRightArithInt() { + test("negShiftRightArithInt", 123); + checkLIR("negShiftRightArithInt", predicate, 1); + } + + /** + * negateShift match rule tests for shift operations with long type. + */ + public long negShiftLeftLogicLong(long input) { + return -(input << 8); + } + + @Test + public void testNegShiftLeftLogicLong() { + test("negShiftLeftLogicLong", 123L); + checkLIR("negShiftLeftLogicLong", predicate, 1); + } + + public long negShiftRightLogicLong(long input) { + return -(input >>> 9); + } + + @Test + public void testNegShiftRightLogicLong() { + test("negShiftRightLogicLong", 123L); + checkLIR("negShiftRightLogicLong", predicate, 1); + } + + public long negShiftRightArithLong(long input) { + return -(input >> 10); + } + + @Test + public void testNegShiftRightArithLong() { + test("negShiftRightArithLong", 123L); + checkLIR("negShiftRightArithLong", predicate, 1); + } +} diff --git a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java index 4b5aab8615c5..103d8f5cb21b 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -27,6 +27,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.LIRKind; @@ -667,6 +668,22 @@ public ComplexMatchResult logicShift(BinaryNode binary, ValueNode a, BinaryNode return emitBinaryShift(op, a, (ShiftNode) shift); } + @MatchRule("(Negate (UnsignedRightShift=shift a Constant=b))") + @MatchRule("(Negate (RightShift=shift a Constant=b))") + @MatchRule("(Negate (LeftShift=shift a Constant=b))") + public ComplexMatchResult negShift(BinaryNode shift, ValueNode a, ConstantNode b) { + assert b.getStackKind().isNumericInteger(); + assert a.getStackKind().isNumericInteger(); + int shiftAmt = b.asJavaConstant().asInt(); + AArch64Assembler.ShiftType shiftType = shiftTypeMap.get(shift.getClass()); + return builder -> { + AllocatableValue src = moveSp(gen.asAllocatable(operand(a))); + Variable result = gen.newVariable(LIRKind.combine(operand(a))); + gen.append(new AArch64ArithmeticOp.NegShiftOp(result, src, shiftType, shiftAmt)); + return result; + }; + } + /** * Goal: use AArch64's and not (bic) & or not (orn) instructions. */ diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java index 349f3f3b7a33..8f44d473baa3 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -679,6 +679,34 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { } } + public static class NegShiftOp extends AArch64LIRInstruction { + private static final LIRInstructionClass TYPE = LIRInstructionClass.create(NegShiftOp.class); + @Def(REG) protected AllocatableValue result; + @Use(REG) protected AllocatableValue src; + private final AArch64Assembler.ShiftType shiftType; + private final int shiftAmt; + + /** + * Computes result = - shiftType(src, shiftAmt). + * + * @param shiftType defines left shift, right shift, arithmetic, logical. + * @param shiftAmt must be in range 0 to 31 for ints (63 for longs). + */ + public NegShiftOp(AllocatableValue result, AllocatableValue src, AArch64Assembler.ShiftType shiftType, int shiftAmt) { + super(TYPE); + this.result = result; + this.src = src; + this.shiftType = shiftType; + this.shiftAmt = shiftAmt; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + int size = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; + masm.neg(size, asRegister(result), asRegister(src), shiftType, shiftAmt); + } + } + public static class MultiplyAddSubOp extends AArch64LIRInstruction { private static final LIRInstructionClass TYPE = LIRInstructionClass.create(MultiplyAddSubOp.class); From 9d47e4a939c73a495e4a7bf97ae104494a2a0b54 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Fri, 24 Sep 2021 18:05:45 +0200 Subject: [PATCH 129/681] Make WasmVoidResult.instance field final. --- .../src/org/graalvm/wasm/WasmVoidResult.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmVoidResult.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmVoidResult.java index ab1c6061ba5c..a888c10e080b 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmVoidResult.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmVoidResult.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -49,11 +49,7 @@ @ExportLibrary(InteropLibrary.class) @SuppressWarnings({"static-method", "unused"}) public final class WasmVoidResult implements TruffleObject { - private static WasmVoidResult instance; - - static { - instance = new WasmVoidResult(); - } + private static final WasmVoidResult instance = new WasmVoidResult(); private WasmVoidResult() { } From 6518d7cd857440fee036a868ed9085d601c00e16 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Fri, 24 Sep 2021 18:21:03 +0200 Subject: [PATCH 130/681] Make constant fields static final. --- .../src/org.graalvm.wasm/src/org/graalvm/wasm/ModuleLimits.java | 2 +- wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java | 2 +- .../src/org/graalvm/wasm/predefined/wasi/types/Ciovec.java | 2 +- .../src/org/graalvm/wasm/predefined/wasi/types/Dirent.java | 2 +- .../src/org/graalvm/wasm/predefined/wasi/types/Event.java | 2 +- .../graalvm/wasm/predefined/wasi/types/EventFdReadwrite.java | 2 +- .../src/org/graalvm/wasm/predefined/wasi/types/Fdstat.java | 2 +- .../src/org/graalvm/wasm/predefined/wasi/types/Filestat.java | 2 +- .../src/org/graalvm/wasm/predefined/wasi/types/Iovec.java | 2 +- .../src/org/graalvm/wasm/predefined/wasi/types/Prestat.java | 2 +- .../src/org/graalvm/wasm/predefined/wasi/types/PrestatDir.java | 2 +- .../org/graalvm/wasm/predefined/wasi/types/Subscription.java | 2 +- .../graalvm/wasm/predefined/wasi/types/SubscriptionClock.java | 2 +- .../wasm/predefined/wasi/types/SubscriptionFdReadwrite.java | 2 +- .../org/graalvm/wasm/predefined/wasi/types/SubscriptionU.java | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/ModuleLimits.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/ModuleLimits.java index a65ec680c326..14214b479dde 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/ModuleLimits.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/ModuleLimits.java @@ -87,7 +87,7 @@ private static int minUnsigned(int a, int b) { return Integer.compareUnsigned(a, b) < 0 ? a : b; } - static ModuleLimits DEFAULTS = new ModuleLimits( + static final ModuleLimits DEFAULTS = new ModuleLimits( Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java index 7b3ccef9fab7..93ed2ce3e0c3 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java @@ -66,7 +66,7 @@ public enum ConstantsStorePolicy { NONE } - public static OptionType StoreConstantsPolicyOptionType = new OptionType<>("StoreConstantsPolicy", ConstantsStorePolicy::valueOf); + public static final OptionType StoreConstantsPolicyOptionType = new OptionType<>("StoreConstantsPolicy", ConstantsStorePolicy::valueOf); @Option(help = "Whenever to store the constants in a pool or not. Deprecated: no longer has any effect.", category = OptionCategory.EXPERT, stability = OptionStability.EXPERIMENTAL, deprecated = true)// public static final OptionKey StoreConstantsPolicy = new OptionKey<>(ConstantsStorePolicy.NONE, StoreConstantsPolicyOptionType); diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Ciovec.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Ciovec.java index cfb7f9e1dddf..cbba481cf5c7 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Ciovec.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Ciovec.java @@ -56,7 +56,7 @@ private Ciovec() { } /** Size of this structure, in bytes. */ - public static int BYTES = 8; + public static final int BYTES = 8; /** Reads the address of the buffer to be written. */ public static int readBuf(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Dirent.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Dirent.java index 0319de30ecad..d982bdcc482a 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Dirent.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Dirent.java @@ -56,7 +56,7 @@ private Dirent() { } /** Size of this structure, in bytes. */ - public static int BYTES = 24; + public static final int BYTES = 24; /** Reads the offset of the next directory entry stored in this directory. */ public static long readDNext(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Event.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Event.java index d1000ce896b2..fd54d1d2341b 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Event.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Event.java @@ -56,7 +56,7 @@ private Event() { } /** Size of this structure, in bytes. */ - public static int BYTES = 32; + public static final int BYTES = 32; /** Reads user-provided value that got attached to {@code subscription::userdata}. */ public static long readUserdata(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/EventFdReadwrite.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/EventFdReadwrite.java index 43aa0f4785b5..47d279abbd55 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/EventFdReadwrite.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/EventFdReadwrite.java @@ -59,7 +59,7 @@ private EventFdReadwrite() { } /** Size of this structure, in bytes. */ - public static int BYTES = 16; + public static final int BYTES = 16; /** Reads the number of bytes available for reading or writing. */ public static long readNbytes(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Fdstat.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Fdstat.java index 296470607f49..9aeb8bb11c74 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Fdstat.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Fdstat.java @@ -56,7 +56,7 @@ private Fdstat() { } /** Size of this structure, in bytes. */ - public static int BYTES = 24; + public static final int BYTES = 24; /** Reads file type. */ public static Filetype readFsFiletype(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Filestat.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Filestat.java index 6255ed530af6..e766fc4d5ab1 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Filestat.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Filestat.java @@ -56,7 +56,7 @@ private Filestat() { } /** Size of this structure, in bytes. */ - public static int BYTES = 64; + public static final int BYTES = 64; /** Reads device id of device containing the file. */ public static long readDev(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Iovec.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Iovec.java index 911be6c10f3b..07a5eb95d085 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Iovec.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Iovec.java @@ -56,7 +56,7 @@ private Iovec() { } /** Size of this structure, in bytes. */ - public static int BYTES = 8; + public static final int BYTES = 8; /** Reads the address of the buffer to be filled. */ public static int readBuf(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Prestat.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Prestat.java index f01585dddd29..24975c663163 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Prestat.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Prestat.java @@ -56,7 +56,7 @@ private Prestat() { } /** Size of this structure, in bytes. */ - public static int CONTENTSOFFSET = 4; + public static final int CONTENTSOFFSET = 4; /** Reads union tag. */ public static Preopentype readTag(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/PrestatDir.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/PrestatDir.java index 8b83d4b8b4a4..c132106daa2c 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/PrestatDir.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/PrestatDir.java @@ -56,7 +56,7 @@ private PrestatDir() { } /** Size of this structure, in bytes. */ - public static int BYTES = 4; + public static final int BYTES = 4; /** Reads the length of the directory name for use with {@code fd_prestat_dir_name}. */ public static int readPrNameLen(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Subscription.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Subscription.java index 4ffae02dd2e5..9a08817b8ecd 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Subscription.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/Subscription.java @@ -56,7 +56,7 @@ private Subscription() { } /** Size of this structure, in bytes. */ - public static int BYTES = 48; + public static final int BYTES = 48; /** * Reads user-provided value that is attached to the subscription in the implementation and diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionClock.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionClock.java index 5a666267171c..12a58bd06047 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionClock.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionClock.java @@ -56,7 +56,7 @@ private SubscriptionClock() { } /** Size of this structure, in bytes. */ - public static int BYTES = 32; + public static final int BYTES = 32; /** Reads the clock against which to compare the timestamp. */ public static Clockid readId(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionFdReadwrite.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionFdReadwrite.java index 2265aa337298..c5d4bd9c6da5 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionFdReadwrite.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionFdReadwrite.java @@ -59,7 +59,7 @@ private SubscriptionFdReadwrite() { } /** Size of this structure, in bytes. */ - public static int BYTES = 4; + public static final int BYTES = 4; /** Reads the file descriptor on which to wait for it to become ready for reading or writing. */ public static int readFileDescriptor(Node node, WasmMemory memory, int address) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionU.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionU.java index f47bc9e01ae1..437b86d284d1 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionU.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/types/SubscriptionU.java @@ -56,7 +56,7 @@ private SubscriptionU() { } /** Size of this structure, in bytes. */ - public static int CONTENTSOFFSET = 8; + public static final int CONTENTSOFFSET = 8; /** Reads union tag. */ public static Eventtype readTag(Node node, WasmMemory memory, int address) { From 36111c3e126fc5a153e1ebc92e7bfbdea9622ec3 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 7 Sep 2021 14:53:15 +0200 Subject: [PATCH 131/681] Make UnsafeWasmMemory implement isPointer(), asPointer(). --- .../org/graalvm/wasm/memory/UnsafeWasmMemory.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/UnsafeWasmMemory.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/UnsafeWasmMemory.java index 040f212b0c41..3b3eb0dd9677 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/UnsafeWasmMemory.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/UnsafeWasmMemory.java @@ -55,10 +55,14 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.nodes.Node; import sun.misc.Unsafe; +@ExportLibrary(InteropLibrary.class) public final class UnsafeWasmMemory extends WasmMemory implements AutoCloseable { /** * @see #declaredMinSize() @@ -360,6 +364,17 @@ public void close() { } } + @SuppressWarnings("static-method") + @ExportMessage + public boolean isPointer() { + return true; + } + + @ExportMessage + public long asPointer() { + return startAddress; + } + static { try { final Field f = Unsafe.class.getDeclaredField("theUnsafe"); From ade781816b068eb3f18f4ca5f8ec571e0fb875e5 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 24 Sep 2021 11:16:56 +0200 Subject: [PATCH 132/681] Update graal-nodejs and graal-js imports. --- vm/mx.vm/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 58d333064c9c..d42698e45da2 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -39,7 +39,7 @@ "name": "graal-nodejs", "subdir": True, "dynamic": True, - "version": "5d6e27792ff4814ce47ff49f7b9845231e2048ec", + "version": "cfd51cdf034ed67678574ad99b957cb7cb752c31", "urls" : [ {"url" : "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, @@ -49,7 +49,7 @@ "name": "graal-js", "subdir": True, "dynamic": True, - "version": "5d6e27792ff4814ce47ff49f7b9845231e2048ec", + "version": "cfd51cdf034ed67678574ad99b957cb7cb752c31", "urls": [ {"url": "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, From 09348a3a3a0ec7e7972d7b93ff796f53a26b6e67 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Fri, 24 Sep 2021 15:39:41 -0700 Subject: [PATCH 133/681] Refactor FastThreadLocal to take a name argument. --- .../genscavenge/ThreadLocalAllocation.java | 3 +- .../oracle/svm/core/SubstrateDiagnostics.java | 2 +- .../core/deopt/DeoptimizationCounters.java | 2 +- .../svm/core/graal/snippets/DeoptTester.java | 2 +- .../snippets/StackOverflowCheckImpl.java | 4 +- .../svm/core/heap/NoAllocationVerifier.java | 2 +- .../IdentityHashCodeSupport.java | 2 +- .../monitor/MultiThreadedMonitorSupport.java | 2 +- .../svm/core/snippets/ExceptionUnwind.java | 2 +- .../svm/core/snippets/ImplicitExceptions.java | 2 +- .../svm/core/stack/JavaFrameAnchors.java | 2 +- .../oracle/svm/core/thread/JavaThreads.java | 2 +- .../com/oracle/svm/core/thread/Safepoint.java | 2 +- .../svm/core/thread/ThreadingSupportImpl.java | 4 +- .../com/oracle/svm/core/thread/VMThreads.java | 26 ++++++------- .../svm/core/threadlocal/FastThreadLocal.java | 15 ++++++-- .../threadlocal/FastThreadLocalBytes.java | 3 +- .../threadlocal/FastThreadLocalFactory.java | 35 +++++++++++++++--- .../core/threadlocal/FastThreadLocalInt.java | 3 +- .../core/threadlocal/FastThreadLocalLong.java | 3 +- .../threadlocal/FastThreadLocalObject.java | 3 +- .../core/threadlocal/FastThreadLocalWord.java | 3 +- .../core/threadlocal/VMThreadLocalInfo.java | 4 +- .../graal/isolated/IsolatedCompileClient.java | 2 +- .../isolated/IsolatedCompileContext.java | 2 +- .../hosted/thread/VMThreadLocalCollector.java | 37 +------------------ .../svm/hosted/thread/VMThreadMTFeature.java | 2 +- .../svm/hosted/thread/VMThreadSTFeature.java | 2 +- .../com/oracle/svm/jfr/JfrThreadLocal.java | 13 ++++--- .../com/oracle/svm/jni/JNIObjectHandles.java | 2 +- .../svm/jni/JNIThreadLocalEnvironment.java | 3 +- .../jni/JNIThreadLocalPendingException.java | 2 +- .../svm/jni/JNIThreadLocalPinnedObjects.java | 3 +- .../svm/jni/JNIThreadOwnedMonitors.java | 2 +- .../oracle/svm/truffle/nfi/ErrnoMirror.java | 2 +- .../oracle/svm/truffle/nfi/NativeClosure.java | 2 +- .../svm/truffle/nfi/TruffleNFISupport.java | 2 +- .../truffle/api/SubstrateFastThreadLocal.java | 2 +- .../api/SubstrateThreadLocalHandshake.java | 4 +- .../polyglot/nativeapi/PolyglotNativeAPI.java | 2 +- 40 files changed, 109 insertions(+), 103 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java index 40219c028e52..323dbc14b516 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java @@ -112,7 +112,8 @@ public interface Descriptor extends PointerBase { * Don't read this value directly, use the {@link Uninterruptible} accessor methods instead. * This is necessary to avoid races between the GC and code that accesses or modifies the TLAB. */ - private static final FastThreadLocalBytes regularTLAB = FastThreadLocalFactory.createBytes(ThreadLocalAllocation::getTlabDescriptorSize).setMaxOffset(FastThreadLocal.BYTE_OFFSET); + private static final FastThreadLocalBytes regularTLAB = FastThreadLocalFactory.createBytes(ThreadLocalAllocation::getTlabDescriptorSize, "ThreadLocalAllocation.regularTLAB") + .setMaxOffset(FastThreadLocal.BYTE_OFFSET); private ThreadLocalAllocation() { } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java index 2ae835b6f177..f2fb6cc092bc 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java @@ -79,7 +79,7 @@ import com.oracle.svm.core.util.Counter; public class SubstrateDiagnostics { - private static final FastThreadLocalBytes threadOnlyAttachedForCrashHandler = FastThreadLocalFactory.createBytes(() -> 1); + private static final FastThreadLocalBytes threadOnlyAttachedForCrashHandler = FastThreadLocalFactory.createBytes(() -> 1, "SubstrateDiagnostics.threadOnlyAttachedForCrashHandler"); @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void setOnlyAttachedForCrashHandler(IsolateThread thread) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/DeoptimizationCounters.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/DeoptimizationCounters.java index de24ee4fea0c..98d3a00f1761 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/DeoptimizationCounters.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/DeoptimizationCounters.java @@ -51,7 +51,7 @@ public static class Options { * Rewriting the stack pointer does not allow passing the start time properly through the call * stack. */ - static final FastThreadLocalLong startTime = FastThreadLocalFactory.createLong(); + static final FastThreadLocalLong startTime = FastThreadLocalFactory.createLong("DeoptimizationCounters.startTime"); @Fold public static DeoptimizationCounters counters() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/DeoptTester.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/DeoptTester.java index c76f5a555165..cf23fa5a53ae 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/DeoptTester.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/DeoptTester.java @@ -71,7 +71,7 @@ public static class Options { private static final Set handledPCs = new HashSet<>(); - private static final FastThreadLocalInt inDeoptTest = FastThreadLocalFactory.createInt(); + private static final FastThreadLocalInt inDeoptTest = FastThreadLocalFactory.createInt("DeoptTester.inDeoptTest"); private static final StackFrameVisitor collectPcVisitor = new StackFrameVisitor() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/StackOverflowCheckImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/StackOverflowCheckImpl.java index bc9e1cbeaef1..79d6808d1aad 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/StackOverflowCheckImpl.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/StackOverflowCheckImpl.java @@ -100,7 +100,7 @@ public final class StackOverflowCheckImpl implements StackOverflowCheck { // The stack boundary for the stack overflow check - public static final FastThreadLocalWord stackBoundaryTL = FastThreadLocalFactory.createWord().setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); + public static final FastThreadLocalWord stackBoundaryTL = FastThreadLocalFactory.createWord("StackOverflowCheckImpl.stackBoundaryTL").setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); /** * Stores a counter how often the yellow zone has been made available, so that the yellow zone @@ -108,7 +108,7 @@ public final class StackOverflowCheckImpl implements StackOverflowCheck { * 0 is the default value of thread local variables, so disallowing 0 as a valid value allows us * to to detect error in the state transitions. */ - static final FastThreadLocalInt yellowZoneStateTL = FastThreadLocalFactory.createInt(); + static final FastThreadLocalInt yellowZoneStateTL = FastThreadLocalFactory.createInt("StackOverflowCheckImpl.yellowZoneStateTL"); static final int STATE_UNINITIALIZED = 0; static final int STATE_YELLOW_ENABLED = 1; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/NoAllocationVerifier.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/NoAllocationVerifier.java index 031de7685d7c..047ca080dbc2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/NoAllocationVerifier.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/NoAllocationVerifier.java @@ -61,7 +61,7 @@ public static void exit(final String callSite, final String typeName) { throw VMError.shouldNotReachHere(ERROR_MSG); } - private static final FastThreadLocalObject openVerifiers = FastThreadLocalFactory.createObject(NoAllocationVerifier.class); + private static final FastThreadLocalObject openVerifiers = FastThreadLocalFactory.createObject(NoAllocationVerifier.class, "NoAllocationVerifier.openVerifiers"); /** * Create an opened instance. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/identityhashcode/IdentityHashCodeSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/identityhashcode/IdentityHashCodeSupport.java index 8796e8e3ddf2..f58dcb60df8b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/identityhashcode/IdentityHashCodeSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/identityhashcode/IdentityHashCodeSupport.java @@ -46,7 +46,7 @@ public final class IdentityHashCodeSupport { public static final LocationIdentity IDENTITY_HASHCODE_LOCATION = NamedLocationIdentity.mutable("identityHashCode"); - private static final FastThreadLocalObject hashCodeGeneratorTL = FastThreadLocalFactory.createObject(SplittableRandom.class); + private static final FastThreadLocalObject hashCodeGeneratorTL = FastThreadLocalFactory.createObject(SplittableRandom.class, "IdentityHashCodeSupport.hashCodeGeneratorTL"); /** * Initialization can require synchronization which is not allowed during safepoints, so this diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java index 04fc1fa38d78..558def22f7aa 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java @@ -100,7 +100,7 @@ public class MultiThreadedMonitorSupport extends MonitorSupport { * This is only used for preempting a continuation in the experimental Loom JDK support. There's * performance impact in this solution. */ - protected static final FastThreadLocalInt lockedMonitors = FastThreadLocalFactory.createInt(); + protected static final FastThreadLocalInt lockedMonitors = FastThreadLocalFactory.createInt("MultiThreadedMonitorSupport.lockedMonitors"); protected static void onMonitorLocked() { if (JavaContinuations.useLoom()) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/ExceptionUnwind.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/ExceptionUnwind.java index 65cf964e0130..89d65429ac00 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/ExceptionUnwind.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/ExceptionUnwind.java @@ -68,7 +68,7 @@ public abstract class ExceptionUnwind { UNWIND_EXCEPTION_WITH_CALLEE_SAVED_REGISTERS }; - public static final FastThreadLocalObject currentException = FastThreadLocalFactory.createObject(Throwable.class); + public static final FastThreadLocalObject currentException = FastThreadLocalFactory.createObject(Throwable.class, "ExceptionUnwind.currentException"); @Uninterruptible(reason = "Called from uninterruptible callers.", mayBeInlined = true) static boolean exceptionsAreFatal() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/ImplicitExceptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/ImplicitExceptions.java index 3c9c511c6984..0d77e718dcc5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/ImplicitExceptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/ImplicitExceptions.java @@ -113,7 +113,7 @@ public class ImplicitExceptions { THROW_CACHED_ILLEGAL_ARGUMENT_EXCEPTION, THROW_CACHED_ARITHMETIC_EXCEPTION, THROW_CACHED_ASSERTION_ERROR, }; - private static final FastThreadLocalInt implicitExceptionsAreFatal = FastThreadLocalFactory.createInt(); + private static final FastThreadLocalInt implicitExceptionsAreFatal = FastThreadLocalFactory.createInt("ImplicitExceptions.implicitExceptionsAreFatal"); /** * Switch the current thread into a mode where implicit exceptions such as NullPointerException diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/stack/JavaFrameAnchors.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/stack/JavaFrameAnchors.java index cbc86c4908f0..1156f3bdea51 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/stack/JavaFrameAnchors.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/stack/JavaFrameAnchors.java @@ -36,7 +36,7 @@ */ public class JavaFrameAnchors { - private static final FastThreadLocalWord lastAnchor = FastThreadLocalFactory.createWord().setMaxOffset(FastThreadLocal.BYTE_OFFSET); + private static final FastThreadLocalWord lastAnchor = FastThreadLocalFactory.createWord("JavaFrameAnchors.lastAnchor").setMaxOffset(FastThreadLocal.BYTE_OFFSET); public static void pushFrameAnchor(JavaFrameAnchor anchor) { anchor.setPreviousAnchor(lastAnchor.get()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java index 76d3e06361c3..bb208acc802d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java @@ -86,7 +86,7 @@ public static JavaThreads singleton() { } /** The {@link java.lang.Thread} for the {@link IsolateThread}. */ - static final FastThreadLocalObject currentThread = FastThreadLocalFactory.createObject(Thread.class).setMaxOffset(FastThreadLocal.BYTE_OFFSET); + static final FastThreadLocalObject currentThread = FastThreadLocalFactory.createObject(Thread.class, "JavaThreads.currentThread").setMaxOffset(FastThreadLocal.BYTE_OFFSET); /** * The number of running non-daemon threads. The initial value accounts for the main thread, diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java index 5d6be7983115..e7dd8fa0483c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java @@ -329,7 +329,7 @@ private static void notInlinedLockNoTransition() { * value.

  • *
*/ - static final FastThreadLocalInt safepointRequested = FastThreadLocalFactory.createInt().setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); + static final FastThreadLocalInt safepointRequested = FastThreadLocalFactory.createInt("Safepoint.safepointRequested").setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); /** The value to reset a thread's {@link #safepointRequested} value to after a safepoint. */ static final int THREAD_REQUEST_RESET = Integer.MAX_VALUE; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadingSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadingSupportImpl.java index 990d9b3db3bb..d250d33229f8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadingSupportImpl.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadingSupportImpl.java @@ -233,9 +233,9 @@ private void invokeCallback() { } } - private static final FastThreadLocalObject activeTimer = FastThreadLocalFactory.createObject(RecurringCallbackTimer.class); + private static final FastThreadLocalObject activeTimer = FastThreadLocalFactory.createObject(RecurringCallbackTimer.class, "ThreadingSupportImpl.activeTimer"); - private static final FastThreadLocalInt currentPauseDepth = FastThreadLocalFactory.createInt(); + private static final FastThreadLocalInt currentPauseDepth = FastThreadLocalFactory.createInt("ThreadingSupportImpl.currentPauseDepth"); private static final String enableSupportOption = SubstrateOptionsParser.commandArgument(SupportRecurringCallback, "+"); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java index 25d7d2c58f7c..1cb5883f88b4 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java @@ -138,17 +138,17 @@ public static VMThreads singleton() { * The next element in the linked list of {@link IsolateThread}s. A thread points to itself with * this field after being removed from the linked list. */ - public static final FastThreadLocalWord nextTL = FastThreadLocalFactory.createWord(); - private static final FastThreadLocalWord OSThreadIdTL = FastThreadLocalFactory.createWord(); - protected static final FastThreadLocalWord OSThreadHandleTL = FastThreadLocalFactory.createWord(); - public static final FastThreadLocalWord IsolateTL = FastThreadLocalFactory.createWord(); + public static final FastThreadLocalWord nextTL = FastThreadLocalFactory.createWord("VMThreads.nextTL"); + private static final FastThreadLocalWord OSThreadIdTL = FastThreadLocalFactory.createWord("VMThreads.OSThreadIdTL"); + protected static final FastThreadLocalWord OSThreadHandleTL = FastThreadLocalFactory.createWord("VMThreads.OSThreadHandleTL"); + public static final FastThreadLocalWord IsolateTL = FastThreadLocalFactory.createWord("VMThreads.IsolateTL"); /** The highest stack address. */ - public static final FastThreadLocalWord StackBase = FastThreadLocalFactory.createWord(); + public static final FastThreadLocalWord StackBase = FastThreadLocalFactory.createWord("VMThreads.StackBase"); /** * The lowest stack address. Note that this value does not necessarily match the value that is * used for the stack overflow check. */ - public static final FastThreadLocalWord StackEnd = FastThreadLocalFactory.createWord(); + public static final FastThreadLocalWord StackEnd = FastThreadLocalFactory.createWord("VMThreads.StackEnd"); private static final int STATE_UNINITIALIZED = 1; private static final int STATE_INITIALIZING = 2; @@ -206,7 +206,7 @@ public static boolean ensureInitialized() { * Stores the unaligned memory address returned by calloc, so that we can properly free the * memory again. */ - private static final FastThreadLocalWord unalignedIsolateThreadMemoryTL = FastThreadLocalFactory.createWord(); + private static final FastThreadLocalWord unalignedIsolateThreadMemoryTL = FastThreadLocalFactory.createWord("VMThreads.unalignedIsolateThreadMemoryTL"); /** * Allocate native memory for a {@link IsolateThread}. The returned memory must be initialized @@ -611,7 +611,7 @@ public static boolean printLocationInfo(Log log, UnsignedWord value, boolean all public static class StatusSupport { /** The status of a {@link IsolateThread}. */ - public static final FastThreadLocalInt statusTL = FastThreadLocalFactory.createInt().setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); + public static final FastThreadLocalInt statusTL = FastThreadLocalFactory.createInt("StatusSupport.statusTL").setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); /** * Boolean flag whether safepoints are disabled. This is a separate thread local in addition @@ -620,7 +620,7 @@ public static class StatusSupport { * detached, or a fatal error occurred and we are printing diagnostics before killing the * VM. */ - private static final FastThreadLocalInt safepointsDisabledTL = FastThreadLocalFactory.createInt(); + private static final FastThreadLocalInt safepointsDisabledTL = FastThreadLocalFactory.createInt("StatusSupport.safepointsDisabledTL"); /** An illegal thread state for places where we need to pass a value. */ public static final int STATUS_ILLEGAL = -1; @@ -834,7 +834,7 @@ public static int getNewThreadStatus(CFunctionOptions.Transition transition) { public static class ActionOnTransitionToJavaSupport { /** The actions to be performed. */ - private static final FastThreadLocalInt actionTL = FastThreadLocalFactory.createInt(); + private static final FastThreadLocalInt actionTL = FastThreadLocalFactory.createInt("ActionOnTransitionToJavaSupport.actionTL"); /** The thread does not need to take any action. */ private static final int NO_ACTION = 0; @@ -878,7 +878,7 @@ public static void requestAllThreadsSynchronizeCode() { */ public static class ActionOnExitSafepointSupport { - private static final FastThreadLocalInt actionTL = FastThreadLocalFactory.createInt(); + private static final FastThreadLocalInt actionTL = FastThreadLocalFactory.createInt("ActionOnExitSafepointSupport.actionTL"); private static final int NO_ACTION = 0; /** * The thread needs to start execution from a different stack, used for preempting a @@ -887,8 +887,8 @@ public static class ActionOnExitSafepointSupport { private static final int SWITCH_STACK = NO_ACTION + 1; /** Target of stack switching. */ - private static final FastThreadLocalWord returnSP = FastThreadLocalFactory.createWord(); - private static final FastThreadLocalWord returnIP = FastThreadLocalFactory.createWord(); + private static final FastThreadLocalWord returnSP = FastThreadLocalFactory.createWord("ActionOnExitSafepointSupport.returnSP"); + private static final FastThreadLocalWord returnIP = FastThreadLocalFactory.createWord("ActionOnExitSafepointSupport.returnIP"); @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean isActionPending() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocal.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocal.java index e243629930ec..58d4a2a26a89 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocal.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocal.java @@ -32,8 +32,7 @@ * Base class for fast thread local variables. */ public abstract class FastThreadLocal { - - static class FastThreadLocalLocationIdentity extends LocationIdentity { + class FastThreadLocalLocationIdentity extends LocationIdentity { @Override public boolean isImmutable() { return false; @@ -41,15 +40,18 @@ public boolean isImmutable() { @Override public String toString() { - return "THREAD_LOCAL@" + Integer.toHexString(hashCode()); + return "FastThreadLocal:" + name; } + } private final LocationIdentity locationIdentity; + private final String name; @Platforms(Platform.HOSTED_ONLY.class) - FastThreadLocal() { + FastThreadLocal(String name) { this.locationIdentity = new FastThreadLocalLocationIdentity(); + this.name = name; } /** @@ -122,4 +124,9 @@ public T setAllowFloatingReads(boolean allow) { public boolean getAllowFloatingReads() { return this.allowFloatingReads; } + + public String getName() { + return name; + } + } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalBytes.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalBytes.java index 9c0bd277f9af..1c6c6de2f290 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalBytes.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalBytes.java @@ -49,7 +49,8 @@ public final class FastThreadLocalBytes extends FastThrea private final IntSupplier sizeSupplier; @Platforms(Platform.HOSTED_ONLY.class) - FastThreadLocalBytes(IntSupplier sizeSupplier) { + FastThreadLocalBytes(IntSupplier sizeSupplier, String name) { + super(name); this.sizeSupplier = sizeSupplier; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalFactory.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalFactory.java index a731255b7f64..bac87244c121 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalFactory.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalFactory.java @@ -68,35 +68,60 @@ private FastThreadLocalFactory() { /** * Creates a new fast thread local variable of the primitive type {@code int}. */ + public static FastThreadLocalInt createInt(String name) { + return new FastThreadLocalInt(name); + } + + @Deprecated public static FastThreadLocalInt createInt() { - return new FastThreadLocalInt(); + return new FastThreadLocalInt("FastThreadLocalInt"); } /** * Creates a new fast thread local variable of the primitive type {@code long}. */ + public static FastThreadLocalLong createLong(String name) { + return new FastThreadLocalLong(name); + } + + @Deprecated public static FastThreadLocalLong createLong() { - return new FastThreadLocalLong(); + return new FastThreadLocalLong("FastThreadLocalLong"); } /** * Creates a new fast thread local variable of type {@link WordBase word}. */ + public static FastThreadLocalWord createWord(String name) { + return new FastThreadLocalWord<>(name); + } + + @Deprecated public static FastThreadLocalWord createWord() { - return new FastThreadLocalWord<>(); + return new FastThreadLocalWord<>("FastThreadLocalWord"); } /** * Creates a new fast thread local variable of type {@link Object}. */ + public static FastThreadLocalObject createObject(Class valueClass, String name) { + return new FastThreadLocalObject<>(valueClass, name); + } + + @Deprecated public static FastThreadLocalObject createObject(Class valueClass) { - return new FastThreadLocalObject<>(valueClass); + return new FastThreadLocalObject<>(valueClass, "FastThreadLocalObject"); } /** * Creates a new fast thread local memory block that has a user-defined size. */ + public static FastThreadLocalBytes createBytes(IntSupplier sizeSupplier, String name) { + return new FastThreadLocalBytes<>(sizeSupplier, name); + } + + @Deprecated public static FastThreadLocalBytes createBytes(IntSupplier sizeSupplier) { - return new FastThreadLocalBytes<>(sizeSupplier); + return new FastThreadLocalBytes<>(sizeSupplier, "FastThreadLocalBytes"); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalInt.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalInt.java index 8061c247cdc5..5612a73ff261 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalInt.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalInt.java @@ -36,7 +36,8 @@ public final class FastThreadLocalInt extends FastThreadLocal { @Platforms(Platform.HOSTED_ONLY.class) - FastThreadLocalInt() { + FastThreadLocalInt(String name) { + super(name); } public int get() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalLong.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalLong.java index 3cba1561ddd6..c54ecaafe33e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalLong.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalLong.java @@ -36,7 +36,8 @@ public final class FastThreadLocalLong extends FastThreadLocal { @Platforms(Platform.HOSTED_ONLY.class) - FastThreadLocalLong() { + FastThreadLocalLong(String name) { + super(name); } public long get() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalObject.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalObject.java index 65ed12d1abf7..59956878ffd9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalObject.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalObject.java @@ -44,7 +44,8 @@ public final class FastThreadLocalObject extends FastThreadLocal { private final Class valueClass; @Platforms(Platform.HOSTED_ONLY.class) - FastThreadLocalObject(Class clazz) { + FastThreadLocalObject(Class clazz, String name) { + super(name); this.valueClass = clazz; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalWord.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalWord.java index e39681199ea1..c07b761f9c63 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalWord.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/FastThreadLocalWord.java @@ -38,7 +38,8 @@ public final class FastThreadLocalWord extends FastThreadLocal { @Platforms(Platform.HOSTED_ONLY.class) - FastThreadLocalWord() { + FastThreadLocalWord(String name) { + super(name); } public T get() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalInfo.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalInfo.java index ef08028e9fc0..fda3e4039cda 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalInfo.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalInfo.java @@ -36,7 +36,6 @@ import org.graalvm.word.WordBase; import com.oracle.svm.core.FrameAccess; -import com.oracle.svm.core.annotate.UnknownObjectField; import com.oracle.svm.core.annotate.UnknownPrimitiveField; import jdk.vm.ci.meta.JavaKind; @@ -74,8 +73,8 @@ public static Class getValueClass(Class threadLoca public final Class valueClass; public final int maxOffset; public final boolean allowFloatingReads; + public final String name; - @UnknownObjectField(types = {String.class}) public String name; @UnknownPrimitiveField public int offset; @UnknownPrimitiveField public int sizeInBytes; @@ -85,6 +84,7 @@ public VMThreadLocalInfo(FastThreadLocal threadLocal) { this.locationIdentity = threadLocal.getLocationIdentity(); this.maxOffset = threadLocal.getMaxOffset(); this.allowFloatingReads = threadLocal.getAllowFloatingReads(); + this.name = threadLocal.getName(); if (threadLocalClass == FastThreadLocalBytes.class) { sizeSupplier = ((FastThreadLocalBytes) threadLocal).getSizeSupplier(); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileClient.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileClient.java index b8f31b310517..2483a24f3f66 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileClient.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileClient.java @@ -44,7 +44,7 @@ public final class IsolatedCompileClient { private static final FastThreadLocalObject currentClient = // - FastThreadLocalFactory.createObject(IsolatedCompileClient.class); + FastThreadLocalFactory.createObject(IsolatedCompileClient.class, "IsolatedCompileClient.currentClient"); @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static IsolatedCompileClient get() { diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileContext.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileContext.java index f7b28a3dae60..c4e58c8ec915 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileContext.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCompileContext.java @@ -44,7 +44,7 @@ */ public final class IsolatedCompileContext { private static final FastThreadLocalObject currentContext = // - FastThreadLocalFactory.createObject(IsolatedCompileContext.class); + FastThreadLocalFactory.createObject(IsolatedCompileContext.class, "IsolatedCompileContext.currentContext"); public static IsolatedCompileContext get() { return currentContext.get(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadLocalCollector.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadLocalCollector.java index 2c709b5aa467..6850a186cb57 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadLocalCollector.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadLocalCollector.java @@ -36,17 +36,11 @@ import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import org.graalvm.nativeimage.hosted.Feature; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.core.threadlocal.FastThreadLocal; import com.oracle.svm.core.threadlocal.VMThreadLocalInfo; -import com.oracle.svm.hosted.FeatureImpl.CompilationAccessImpl; -import com.oracle.svm.hosted.meta.HostedField; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaField; /** * Collects all {@link FastThreadLocal} instances that are actually used by the application. @@ -90,37 +84,9 @@ public VMThreadLocalInfo findInfo(GraphBuilderContext b, ValueNode threadLocalNo return result; } - public List sortThreadLocals(Feature.CompilationAccess a) { - CompilationAccessImpl config = (CompilationAccessImpl) a; - + public List sortThreadLocals() { sealed = true; - - /* - * Find a unique static field for every VM thread local object. The field name is used to - * make the layout of VMThread deterministic. - */ - for (ResolvedJavaField f : config.getFields()) { - HostedField field = (HostedField) f; - if (field.isStatic() && field.getStorageKind() == JavaKind.Object) { - Object fieldValue = SubstrateObjectConstant.asObject(field.readValue(null)); - if (fieldValue instanceof FastThreadLocal) { - FastThreadLocal threadLocal = (FastThreadLocal) fieldValue; - VMThreadLocalInfo info = threadLocals.get(threadLocal); - String fieldName = field.format("%H.%n"); - if (!field.isFinal()) { - throw shouldNotReachHere("VMThreadLocal referenced from non-final field: " + fieldName); - } else if (info.name != null) { - throw shouldNotReachHere("VMThreadLocal referenced from two static final fields: " + info.name + ", " + fieldName); - } - info.name = fieldName; - } - } - } for (VMThreadLocalInfo info : threadLocals.values()) { - if (info.name == null) { - shouldNotReachHere("VMThreadLocal found that is not referenced from a static final field"); - } - assert info.sizeInBytes == -1; if (info.sizeSupplier != null) { int unalignedSize = info.sizeSupplier.getAsInt(); @@ -158,7 +124,6 @@ private static int compareThreadLocal(VMThreadLocalInfo info1, VMThreadLocalInfo } } } - assert result != 0 : "not distinguishable: " + info1 + ", " + info2; return result; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadMTFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadMTFeature.java index aecf007945d6..815d2acefc0e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadMTFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadMTFeature.java @@ -238,7 +238,7 @@ public void duringAnalysis(DuringAnalysisAccess access) { @Override public void beforeCompilation(BeforeCompilationAccess config) { - List sortedThreadLocalInfos = threadLocalCollector.sortThreadLocals(config); + List sortedThreadLocalInfos = threadLocalCollector.sortThreadLocals(); SubstrateReferenceMap referenceMap = new SubstrateReferenceMap(); int nextOffset = 0; for (VMThreadLocalInfo info : sortedThreadLocalInfos) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadSTFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadSTFeature.java index e585700d56c4..13ec85cf0ca4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadSTFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadSTFeature.java @@ -217,7 +217,7 @@ public void duringAnalysis(DuringAnalysisAccess access) { @Override public void beforeCompilation(BeforeCompilationAccess config) { - List sortedThreadLocalInfos = threadLocalCollector.sortThreadLocals(config); + List sortedThreadLocalInfos = threadLocalCollector.sortThreadLocals(); ObjectLayout layout = ConfigurationValues.getObjectLayout(); int nextObject = 0; int nextPrimitive = 0; diff --git a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrThreadLocal.java b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrThreadLocal.java index 0bee57ab6d75..06cac6b8d089 100644 --- a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrThreadLocal.java +++ b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrThreadLocal.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.jfr; -import com.oracle.svm.core.thread.VMOperation; import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.Platform; @@ -38,6 +37,7 @@ import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.thread.Target_java_lang_Thread; import com.oracle.svm.core.thread.ThreadListener; +import com.oracle.svm.core.thread.VMOperation; import com.oracle.svm.core.threadlocal.FastThreadLocalFactory; import com.oracle.svm.core.threadlocal.FastThreadLocalLong; import com.oracle.svm.core.threadlocal.FastThreadLocalObject; @@ -63,11 +63,12 @@ * modify the buffers of other threads). */ public class JfrThreadLocal implements ThreadListener { - private static final FastThreadLocalObject javaEventWriter = FastThreadLocalFactory.createObject(Target_jdk_jfr_internal_EventWriter.class); - private static final FastThreadLocalWord javaBuffer = FastThreadLocalFactory.createWord(); - private static final FastThreadLocalWord nativeBuffer = FastThreadLocalFactory.createWord(); - private static final FastThreadLocalWord dataLost = FastThreadLocalFactory.createWord(); - private static final FastThreadLocalLong traceId = FastThreadLocalFactory.createLong(); + private static final FastThreadLocalObject javaEventWriter = FastThreadLocalFactory.createObject(Target_jdk_jfr_internal_EventWriter.class, + "JfrThreadLocal.javaEventWriter"); + private static final FastThreadLocalWord javaBuffer = FastThreadLocalFactory.createWord("JfrThreadLocal.javaBuffer"); + private static final FastThreadLocalWord nativeBuffer = FastThreadLocalFactory.createWord("JfrThreadLocal.nativeBuffer"); + private static final FastThreadLocalWord dataLost = FastThreadLocalFactory.createWord("JfrThreadLocal.dataLost"); + private static final FastThreadLocalLong traceId = FastThreadLocalFactory.createLong("JfrThreadLocal.traceId"); private long threadLocalBufferSize; diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIObjectHandles.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIObjectHandles.java index 42479d409c0a..55331510b234 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIObjectHandles.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIObjectHandles.java @@ -80,7 +80,7 @@ public static T nullHandle() { static final int NATIVE_CALL_MIN_LOCAL_HANDLE_CAPACITY = 16; @SuppressWarnings("rawtypes") private static final FastThreadLocalObject handles // - = FastThreadLocalFactory.createObject(ThreadLocalHandles.class); + = FastThreadLocalFactory.createObject(ThreadLocalHandles.class, "JNIObjectHandles.handles"); @Fold static boolean useImageHeapHandles() { diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalEnvironment.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalEnvironment.java index 7c9806ce0b6e..9dc92fae76fa 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalEnvironment.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalEnvironment.java @@ -41,7 +41,8 @@ public class JNIThreadLocalEnvironment { * structure. For that reason, it has the same address as the VMThread and can be used to * restore the designated VMThread register when transitioning from native to Java. */ - static final FastThreadLocalBytes jniFunctions = FastThreadLocalFactory.createBytes(() -> SizeOf.get(JNIEnvironment.class)).setMaxOffset(0); + static final FastThreadLocalBytes jniFunctions = FastThreadLocalFactory.createBytes(() -> SizeOf.get(JNIEnvironment.class), "JNIThreadLocalEnvironment.jniFunctions") + .setMaxOffset(0); public static JNIEnvironment getAddress() { JNIEnvironment env = jniFunctions.getAddress(); diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalPendingException.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalPendingException.java index 37e1a3d427f4..fcc91a33b110 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalPendingException.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalPendingException.java @@ -31,7 +31,7 @@ * Retains one exception per thread that is pending to be handled in that thread (or none). */ public class JNIThreadLocalPendingException { - private static final FastThreadLocalObject pendingException = FastThreadLocalFactory.createObject(Throwable.class); + private static final FastThreadLocalObject pendingException = FastThreadLocalFactory.createObject(Throwable.class, "JNIThreadLocalPendingException.pendingException"); public static Throwable get() { return pendingException.get(); diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalPinnedObjects.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalPinnedObjects.java index d93e7ab170f2..9f30fc6cf3dd 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalPinnedObjects.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadLocalPinnedObjects.java @@ -47,7 +47,8 @@ private static class PinnedObjectListNode { } } - private static final FastThreadLocalObject pinnedObjectsListHead = FastThreadLocalFactory.createObject(PinnedObjectListNode.class); + private static final FastThreadLocalObject pinnedObjectsListHead = FastThreadLocalFactory.createObject(PinnedObjectListNode.class, + "JNIThreadLocalPinnedObjects.pinnedObjectsListHead"); public static T pinArrayAndGetAddress(Object array) { PinnedObject pin = PinnedObject.create(array); diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadOwnedMonitors.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadOwnedMonitors.java index 83a29bda54c4..2b3e8e40550a 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadOwnedMonitors.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNIThreadOwnedMonitors.java @@ -36,7 +36,7 @@ public class JNIThreadOwnedMonitors { @SuppressWarnings("rawtypes") // - private static final FastThreadLocalObject ownedMonitors = FastThreadLocalFactory.createObject(IdentityHashMap.class); + private static final FastThreadLocalObject ownedMonitors = FastThreadLocalFactory.createObject(IdentityHashMap.class, "JNIThreadOwnedMonitors.ownedMonitors"); @SuppressWarnings("unchecked") private static IdentityHashMap mutableMap() { diff --git a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/ErrnoMirror.java b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/ErrnoMirror.java index 48c49e780739..753c717d03a3 100644 --- a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/ErrnoMirror.java +++ b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/ErrnoMirror.java @@ -43,7 +43,7 @@ @SuppressWarnings("static-method") public final class ErrnoMirror implements TruffleObject { - static final FastThreadLocalBytes errnoMirror = FastThreadLocalFactory.createBytes(() -> SizeOf.get(CIntPointer.class)); + static final FastThreadLocalBytes errnoMirror = FastThreadLocalFactory.createBytes(() -> SizeOf.get(CIntPointer.class), "ErrnoMirror.errnoMirror"); private static final KeysArray KEYS = new KeysArray(new String[]{"bind"}); diff --git a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeClosure.java b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeClosure.java index 3b07efe23f00..20c932efc479 100644 --- a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeClosure.java +++ b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeClosure.java @@ -184,7 +184,7 @@ private static PointerBase serializeStringRet(Object retValue) { } } - static final FastThreadLocalObject pendingException = FastThreadLocalFactory.createObject(Throwable.class); + static final FastThreadLocalObject pendingException = FastThreadLocalFactory.createObject(Throwable.class, "NativeClosure.pendingException"); @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) @CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.NotPublished) diff --git a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/TruffleNFISupport.java b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/TruffleNFISupport.java index 18c449f6ed88..1466a40415ec 100644 --- a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/TruffleNFISupport.java +++ b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/TruffleNFISupport.java @@ -47,7 +47,7 @@ public abstract class TruffleNFISupport { static final Charset UTF8 = Charset.forName("utf8"); - private static final FastThreadLocalObject currentScope = FastThreadLocalFactory.createObject(LocalNativeScope.class); + private static final FastThreadLocalObject currentScope = FastThreadLocalFactory.createObject(LocalNativeScope.class, "TruffleNFISupport.currentScope"); private final ObjectHandles globalHandles; private final ObjectHandles closureHandles; diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateFastThreadLocal.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateFastThreadLocal.java index 0630dfe5b98e..a39dcd4e284b 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateFastThreadLocal.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateFastThreadLocal.java @@ -36,7 +36,7 @@ final class SubstrateFastThreadLocal extends GraalFastThreadLocal { static final SubstrateFastThreadLocal SINGLETON = new SubstrateFastThreadLocal(); - private static final FastThreadLocalObject CONTEXT = FastThreadLocalFactory.createObject(Object[].class) + private static final FastThreadLocalObject CONTEXT = FastThreadLocalFactory.createObject(Object[].class, "SubstrateFastThreadLocal.CONTEXT") .setAllowFloatingReads(true) .setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateThreadLocalHandshake.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateThreadLocalHandshake.java index cc841c2ec78c..39cb82a86fb2 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateThreadLocalHandshake.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateThreadLocalHandshake.java @@ -65,8 +65,8 @@ public final class SubstrateThreadLocalHandshake extends ThreadLocalHandshake { static final SubstrateThreadLocalHandshake SINGLETON = new SubstrateThreadLocalHandshake(); - static final FastThreadLocalInt PENDING = FastThreadLocalFactory.createInt().setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); - static final FastThreadLocalObject STATE = FastThreadLocalFactory.createObject(TruffleSafepointImpl.class) + static final FastThreadLocalInt PENDING = FastThreadLocalFactory.createInt("SubstrateThreadLocalHandshake.PENDING").setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); + static final FastThreadLocalObject STATE = FastThreadLocalFactory.createObject(TruffleSafepointImpl.class, "SubstrateThreadLocalHandshake.STATE") .setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); @Platforms(Platform.HOSTED_ONLY.class)// diff --git a/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPI.java b/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPI.java index 2985cb89487b..c48b15321432 100644 --- a/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPI.java +++ b/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPI.java @@ -119,7 +119,7 @@ public final class PolyglotNativeAPI { private static ThreadLocal exceptionsTL = new ThreadLocal<>(); private static ThreadLocal errorHolder = new ThreadLocal<>(); - @SuppressWarnings("rawtypes") private static final FastThreadLocalObject handles = FastThreadLocalFactory.createObject(ThreadLocalHandles.class); + @SuppressWarnings("rawtypes") private static final FastThreadLocalObject handles = FastThreadLocalFactory.createObject(ThreadLocalHandles.class, "PolyglotNativeAPI.handles"); @SuppressWarnings("unchecked") private static ThreadLocalHandles getHandles() { From 3467df19e881c672d11b8d7352af285935ca1c5c Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 24 Sep 2021 13:31:19 +0200 Subject: [PATCH 134/681] compiler: guarantee that the last fixed node was not deleted by a previous lowering --- .../src/org/graalvm/compiler/phases/common/LoweringPhase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java index c0e5d0db99eb..e0892b30c18c 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java @@ -190,11 +190,12 @@ public GuardingNode createGuard(FixedNode before, LogicNode condition, Deoptimiz @Override public FixedWithNextNode lastFixedNode() { + GraalError.guarantee(lastFixedNode.isAlive(), "The last fixed node %s was deleted by a previous lowering", lastFixedNode); return lastFixedNode; } private void setLastFixedNode(FixedWithNextNode n) { - assert n.isAlive() : n; + GraalError.guarantee(n.isAlive(), "Cannot add last fixed node %s because it is not alive", n); lastFixedNode = n; } } From d1479fd0a6afaa944351401b594ead2b3169e9a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Fri, 10 Sep 2021 13:59:26 +0200 Subject: [PATCH 135/681] Remove obsolete special handling in org.graalvm.compiler.options.ModuleSupport --- .../compiler/options/ModuleSupport.java | 5 --- .../compiler/options/ModuleSupport.java | 6 ---- .../com/oracle/svm/driver/NativeImage.java | 6 ++-- ...veImageClassLoaderSupportJDK11OrLater.java | 2 +- .../com/oracle/svm/util/ModuleSupport.java | 2 +- .../com/oracle/svm/util/ModuleSupport.java | 2 +- .../oracle/svm/util/ModuleSupportBase.java | 34 +++++++++++++++++++ 7 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupportBase.java diff --git a/compiler/src/org.graalvm.compiler.options.jdk11/src/org/graalvm/compiler/options/ModuleSupport.java b/compiler/src/org.graalvm.compiler.options.jdk11/src/org/graalvm/compiler/options/ModuleSupport.java index 04a67c8a9616..b2025d468faf 100644 --- a/compiler/src/org.graalvm.compiler.options.jdk11/src/org/graalvm/compiler/options/ModuleSupport.java +++ b/compiler/src/org.graalvm.compiler.options.jdk11/src/org/graalvm/compiler/options/ModuleSupport.java @@ -28,8 +28,6 @@ public class ModuleSupport { - public static final boolean USE_NI_JPMS = Boolean.parseBoolean(System.getenv().get("USE_NATIVE_IMAGE_JAVA_PLATFORM_MODULE_SYSTEM")); - static Iterable getOptionsLoader() { /* * The Graal module (i.e., jdk.internal.vm.compiler) is loaded by the platform class loader @@ -37,9 +35,6 @@ static Iterable getOptionsLoader() { * As such, we need to start the provider search at the app class loader instead of the * platform class loader. */ - if (USE_NI_JPMS) { - return ServiceLoader.load(ModuleSupport.class.getModule().getLayer(), OptionDescriptors.class); - } return ServiceLoader.load(OptionDescriptors.class, ClassLoader.getSystemClassLoader()); } } diff --git a/compiler/src/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModuleSupport.java b/compiler/src/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModuleSupport.java index e93e35cfc103..6e101bb5cff5 100644 --- a/compiler/src/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModuleSupport.java +++ b/compiler/src/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModuleSupport.java @@ -28,12 +28,6 @@ public class ModuleSupport { - public static final boolean USE_NI_JPMS; - - static { - USE_NI_JPMS = false; - } - static Iterable getOptionsLoader() { // On JDK 8, Graal and its extensions are loaded by the same class loader. return ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java index 06c3b8a07f46..23b737a9f4b6 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java @@ -91,8 +91,6 @@ public class NativeImage { - private static final String ENV_VAR_USE_MODULE_SYSTEM = "USE_NATIVE_IMAGE_JAVA_PLATFORM_MODULE_SYSTEM"; - private static final String DEFAULT_GENERATOR_CLASS_NAME = NativeImageGeneratorRunner.class.getName(); private static final String DEFAULT_GENERATOR_MODULE_NAME = ModuleSupport.getModuleName(NativeImageGeneratorRunner.class); @@ -280,7 +278,7 @@ protected BuildConfiguration(List args) { @SuppressWarnings("deprecation") BuildConfiguration(Path rootDir, Path workDir, List args) { - modulePathBuild = Boolean.parseBoolean(System.getenv().get(ENV_VAR_USE_MODULE_SYSTEM)); + modulePathBuild = Boolean.parseBoolean(System.getenv().get(ModuleSupport.ENV_VAR_USE_MODULE_SYSTEM)); this.args = args; this.workDir = workDir != null ? workDir : Paths.get(".").toAbsolutePath().normalize(); if (rootDir != null) { @@ -1401,7 +1399,7 @@ protected int buildImage(List javaArgs, LinkedHashSet bcp, LinkedH ProcessBuilder pb = new ProcessBuilder(); pb.command(command); if (config.modulePathBuild) { - pb.environment().put(ENV_VAR_USE_MODULE_SYSTEM, Boolean.toString(true)); + pb.environment().put(ModuleSupport.ENV_VAR_USE_MODULE_SYSTEM, Boolean.toString(true)); } p = pb.inheritIO().start(); exitStatus = p.waitFor(); diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java index b828e15acc54..4be2040efd4d 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java @@ -150,7 +150,7 @@ private void adjustLibrarySupportReadAllUnnamed() { VMError.shouldNotReachHere("Could not adjust org.graalvm.nativeimage.librarysupport to read all unnamed modules", e); } } else { - VMError.guarantee(!org.graalvm.compiler.options.ModuleSupport.USE_NI_JPMS, + VMError.guarantee(!ModuleSupport.modulePathBuild, "Image-builder on module-path requires module org.graalvm.nativeimage.librarysupport"); } } diff --git a/substratevm/src/com.oracle.svm.util.jdk11/src/com/oracle/svm/util/ModuleSupport.java b/substratevm/src/com.oracle.svm.util.jdk11/src/com/oracle/svm/util/ModuleSupport.java index d33b3e208d21..7fd67edbf257 100644 --- a/substratevm/src/com.oracle.svm.util.jdk11/src/com/oracle/svm/util/ModuleSupport.java +++ b/substratevm/src/com.oracle.svm.util.jdk11/src/com/oracle/svm/util/ModuleSupport.java @@ -43,7 +43,7 @@ import jdk.internal.module.Modules; @Platforms(Platform.HOSTED_ONLY.class) -public final class ModuleSupport { +public final class ModuleSupport extends ModuleSupportBase { private ModuleSupport() { } diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupport.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupport.java index 2f451deab2d2..677786c41e06 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupport.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupport.java @@ -35,7 +35,7 @@ import org.graalvm.nativeimage.Platforms; @Platforms(Platform.HOSTED_ONLY.class) -public final class ModuleSupport { +public final class ModuleSupport extends ModuleSupportBase { private ModuleSupport() { } diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupportBase.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupportBase.java new file mode 100644 index 000000000000..ccde5b99230f --- /dev/null +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupportBase.java @@ -0,0 +1,34 @@ +/* + * 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.util; + +public class ModuleSupportBase { + + public static final String ENV_VAR_USE_MODULE_SYSTEM = "USE_NATIVE_IMAGE_JAVA_PLATFORM_MODULE_SYSTEM"; + + public static final boolean modulePathBuild = Boolean.parseBoolean(System.getenv().get(ENV_VAR_USE_MODULE_SYSTEM)); + +} From 3b30905ed4f17add51d3a9a134e488e542c43c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Fri, 10 Sep 2021 18:43:00 +0200 Subject: [PATCH 136/681] Decouple HostedOptionParser setup from classpath/modulepath scanning --- substratevm/mx.substratevm/suite.py | 1 + .../oracle/svm/driver/APIOptionHandler.java | 15 +++----- ...veImageClassLoaderSupportJDK11OrLater.java | 7 ++-- ...AbstractNativeImageClassLoaderSupport.java | 26 +++++++++++++- .../oracle/svm/hosted/ImageClassLoader.java | 5 --- .../hosted/NativeImageClassLoaderSupport.java | 2 +- .../hosted/NativeImageGeneratorRunner.java | 36 +++++++++---------- .../svm/hosted/option/HostedOptionParser.java | 24 ++++--------- 8 files changed, 58 insertions(+), 58 deletions(-) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 0c863b180c16..32c101a167b8 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1121,6 +1121,7 @@ ], "uses" : [ "org.graalvm.nativeimage.Platform", + "org.graalvm.compiler.options.OptionDescriptors", "com.oracle.truffle.api.TruffleLanguage.Provider", "com.oracle.truffle.api.instrumentation.TruffleInstrument.Provider", "com.oracle.svm.hosted.agent.NativeImageBytecodeInstrumentationAgentExtension", diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/APIOptionHandler.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/APIOptionHandler.java index 8c52503484ae..987c8340a069 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/APIOptionHandler.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/APIOptionHandler.java @@ -106,20 +106,15 @@ boolean isDeprecated() { groupInfos = support.groupInfos; apiOptions = support.options; } else { - List> optionDescriptorsList = new ArrayList<>(); - ServiceLoader serviceLoader = ServiceLoader.load(OptionDescriptors.class, nativeImage.getClass().getClassLoader()); - for (OptionDescriptors optionDescriptors : serviceLoader) { - optionDescriptorsList.add(optionDescriptors.getClass()); - } groupInfos = new HashMap<>(); - apiOptions = extractOptions(optionDescriptorsList, groupInfos); + apiOptions = extractOptions(ServiceLoader.load(OptionDescriptors.class, nativeImage.getClass().getClassLoader()), groupInfos); } } - static SortedMap extractOptions(List> optionsClasses, Map groupInfos) { + static SortedMap extractOptions(ServiceLoader optionDescriptors, Map groupInfos) { EconomicMap hostedOptions = EconomicMap.create(); EconomicMap runtimeOptions = EconomicMap.create(); - HostedOptionParser.collectOptions(optionsClasses, hostedOptions, runtimeOptions); + HostedOptionParser.collectOptions(optionDescriptors, hostedOptions, runtimeOptions); SortedMap apiOptions = new TreeMap<>(); Map, APIOptionGroup> groupInstances = new HashMap<>(); hostedOptions.getValues().forEach(o -> extractOption(NativeImage.oH, o, apiOptions, groupInfos, groupInstances)); @@ -450,9 +445,9 @@ final class APIOptionFeature implements Feature { @Override public void duringSetup(DuringSetupAccess access) { FeatureImpl.DuringSetupAccessImpl accessImpl = (FeatureImpl.DuringSetupAccessImpl) access; - List> optionClasses = accessImpl.getImageClassLoader().findSubclasses(OptionDescriptors.class, true); Map groupInfos = new HashMap<>(); - SortedMap options = APIOptionHandler.extractOptions(optionClasses, groupInfos); + ServiceLoader optionDescriptors = ServiceLoader.load(OptionDescriptors.class, accessImpl.getImageClassLoader().getClassLoader()); + SortedMap options = APIOptionHandler.extractOptions(optionDescriptors, groupInfos); ImageSingletons.add(APIOptionSupport.class, new APIOptionSupport(groupInfos, options)); } } diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java index 4be2040efd4d..ed31cde2e425 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java @@ -77,8 +77,6 @@ public NativeImageClassLoaderSupportJDK11OrLater(ClassLoader defaultSystemClassL adjustBootLayerQualifiedExports(moduleLayer); moduleLayerForImageBuild = moduleLayer; classLoader = getSingleClassloader(moduleLayer); - - adjustLibrarySupportReadAllUnnamed(); } private static ModuleLayer createModuleLayer(Path[] modulePaths, ClassLoader parent) { @@ -171,7 +169,7 @@ protected Optional findModule(String moduleName) { } @Override - protected void processAddExportsAndAddOpens(OptionValues parsedHostedOptions) { + protected void processClassLoaderOptions(OptionValues parsedHostedOptions) { LocatableMultiOptionValue.Strings addExports = NativeImageClassLoaderOptions.AddExports.getValue(parsedHostedOptions); addExports.getValuesWithOrigins().map(this::asAddExportsAndOpensFormatValue).forEach(val -> { if (val.targetModules.isEmpty()) { @@ -192,6 +190,9 @@ protected void processAddExportsAndAddOpens(OptionValues parsedHostedOptions) { } } }); + + /* TODO: Implement real --add-reads instead */ + adjustLibrarySupportReadAllUnnamed(); } private static final class AddExportsAndOpensFormatValue { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AbstractNativeImageClassLoaderSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AbstractNativeImageClassLoaderSupport.java index 38e429d4abac..0a5a8a6aa2e0 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AbstractNativeImageClassLoaderSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AbstractNativeImageClassLoaderSupport.java @@ -62,6 +62,7 @@ import com.oracle.svm.core.util.InterruptImageBuilding; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; +import com.oracle.svm.hosted.option.HostedOptionParser; public abstract class AbstractNativeImageClassLoaderSupport { @@ -109,7 +110,30 @@ public ClassLoader getClassLoader() { protected abstract Optional findModule(String moduleName); - protected abstract void processAddExportsAndAddOpens(OptionValues parsedHostedOptions); + private HostedOptionParser hostedOptionParser; + private OptionValues parsedHostedOptions; + private List remainingArguments; + + public void setupHostedOptionParser(List arguments) { + hostedOptionParser = new HostedOptionParser(getClassLoader()); + remainingArguments = Collections.unmodifiableList(Arrays.asList(hostedOptionParser.parse(arguments.toArray(new String[0])))); + parsedHostedOptions = new OptionValues(hostedOptionParser.getHostedValues()); + processClassLoaderOptions(parsedHostedOptions); + } + + public HostedOptionParser getHostedOptionParser() { + return hostedOptionParser; + }; + + public List getRemainingArguments() { + return remainingArguments; + } + + public OptionValues getParsedHostedOptions() { + return parsedHostedOptions; + } + + protected abstract void processClassLoaderOptions(OptionValues parsedHostedOptions); protected abstract void initAllClasses(ForkJoinPool executor, ImageClassLoader imageClassLoader); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java index be8f57d91714..7ab7aa98bd6c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java @@ -44,7 +44,6 @@ import java.util.stream.StreamSupport; import org.graalvm.collections.EconomicSet; -import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -427,8 +426,4 @@ public Optional getMainClassFromModule(Object module) { public Optional findModule(String moduleName) { return classLoaderSupport.findModule(moduleName); } - - public void processAddExportsAndAddOpens(OptionValues parsedHostedOptions) { - classLoaderSupport.processAddExportsAndAddOpens(parsedHostedOptions); - } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java index 8ac65f886623..ab62ac5c4a67 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java @@ -54,7 +54,7 @@ protected Optional findModule(String moduleName) { } @Override - protected void processAddExportsAndAddOpens(OptionValues parsedHostedOptions) { + protected void processClassLoaderOptions(OptionValues parsedHostedOptions) { /* Nothing to do for Java 8 */ } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index 6c50c57e7ae6..56efbffcb0f3 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -118,8 +118,12 @@ public void run() { int exitStatus; ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader(); try { - ImageClassLoader imageClassLoader = installNativeImageClassLoader(classPath, modulePath); - exitStatus = new NativeImageGeneratorRunner().build(arguments.toArray(new String[0]), imageClassLoader); + ImageClassLoader imageClassLoader = installNativeImageClassLoader(classPath, modulePath, arguments); + List remainingArguments = imageClassLoader.classLoaderSupport.getRemainingArguments(); + if (!remainingArguments.isEmpty()) { + throw UserError.abort("Unknown options: %s", String.join(" ", remainingArguments)); + } + exitStatus = new NativeImageGeneratorRunner().build(imageClassLoader); } finally { uninstallNativeImageClassLoader(); Thread.currentThread().setContextClassLoader(applicationClassLoader); @@ -149,12 +153,14 @@ public static void uninstallNativeImageClassLoader() { * * @param classpath for the application and image should be built for. * @param modulepath for the application and image should be built for (only for Java >= 11). + * @param arguments * @return NativeImageClassLoaderSupport that exposes the {@code ClassLoader} for image building * via {@link NativeImageClassLoaderSupport#getClassLoader()}. */ - public static ImageClassLoader installNativeImageClassLoader(String[] classpath, String[] modulepath) { + public static ImageClassLoader installNativeImageClassLoader(String[] classpath, String[] modulepath, List arguments) { NativeImageSystemClassLoader nativeImageSystemClassLoader = NativeImageSystemClassLoader.singleton(); AbstractNativeImageClassLoaderSupport nativeImageClassLoaderSupport = createNativeImageClassLoaderSupport(nativeImageSystemClassLoader.defaultSystemClassLoader, classpath, modulepath); + nativeImageClassLoaderSupport.setupHostedOptionParser(arguments); ClassLoader nativeImageClassLoader = nativeImageClassLoaderSupport.getClassLoader(); Thread.currentThread().setContextClassLoader(nativeImageClassLoader); /* @@ -259,32 +265,24 @@ private static boolean isValidOperatingSystem() { } @SuppressWarnings("try") - private int buildImage(String[] arguments, ImageClassLoader classLoader) { + private int buildImage(ImageClassLoader classLoader) { if (!verifyValidJavaVersionAndPlatform()) { return 1; } String imageName = null; Timer totalTimer = new Timer("[total]", false); + + HostedOptionParser optionParser = classLoader.classLoaderSupport.getHostedOptionParser(); + OptionValues parsedHostedOptions = classLoader.classLoaderSupport.getParsedHostedOptions(); + ForkJoinPool analysisExecutor = null; ForkJoinPool compilationExecutor = null; - OptionValues parsedHostedOptions = null; try (StopTimer ignored = totalTimer.start()) { Timer classlistTimer = new Timer("classlist", false); try (StopTimer ignored1 = classlistTimer.start()) { classLoader.initAllClasses(); } - HostedOptionParser optionParser = new HostedOptionParser(classLoader); - String[] remainingArgs = optionParser.parse(arguments); - if (remainingArgs.length > 0) { - throw UserError.abort("Unknown options: %s", Arrays.toString(remainingArgs)); - } - - /* - * We do not have the VMConfiguration and the HostedOptionValues set up yet, so we need - * to pass the OptionValues explicitly when accessing options. - */ - parsedHostedOptions = new OptionValues(optionParser.getHostedValues()); DebugContext debug = new DebugContext.Builder(parsedHostedOptions, new GraalDebugHandlersFactory(GraalAccess.getOriginalSnippetReflection())).build(); imageName = SubstrateOptions.Name.getValue(parsedHostedOptions); @@ -323,8 +321,6 @@ private int buildImage(String[] arguments, ImageClassLoader classLoader) { SubstrateOptionsParser.commandArgument(SubstrateOptions.Class, "")); } - classLoader.processAddExportsAndAddOpens(parsedHostedOptions); - if (!className.isEmpty() || !moduleName.isEmpty()) { Method mainEntryPoint; Class mainClass; @@ -565,8 +561,8 @@ private static void warn(String msg) { System.err.println("Warning: " + msg); } - public int build(String[] args, ImageClassLoader imageClassLoader) { - return buildImage(args, imageClassLoader); + public int build(ImageClassLoader imageClassLoader) { + return buildImage(imageClassLoader); } /** diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java index d3cc32ea3c04..6654e36002b6 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java @@ -27,17 +27,16 @@ import static com.oracle.svm.core.option.SubstrateOptionsParser.BooleanOptionFormat.PLUS_MINUS; import static com.oracle.svm.core.util.VMError.shouldNotReachHere; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.ServiceLoader; import java.util.Set; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.options.OptionDescriptor; import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionDescriptorsMap; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import org.graalvm.nativeimage.Platforms; @@ -47,7 +46,6 @@ import com.oracle.svm.core.option.SubstrateOptionsParser; import com.oracle.svm.core.util.InterruptImageBuilding; import com.oracle.svm.core.util.UserError; -import com.oracle.svm.hosted.ImageClassLoader; public class HostedOptionParser implements HostedOptionProvider { @@ -56,24 +54,14 @@ public class HostedOptionParser implements HostedOptionProvider { private EconomicMap allHostedOptions = EconomicMap.create(); private EconomicMap allRuntimeOptions = EconomicMap.create(); - public HostedOptionParser(ImageClassLoader imageClassLoader) { - collectOptions(imageClassLoader.findSubclasses(OptionDescriptors.class, true), allHostedOptions, allRuntimeOptions); + public HostedOptionParser(ClassLoader imageClassLoader) { + collectOptions(ServiceLoader.load(OptionDescriptors.class, imageClassLoader), allHostedOptions, allRuntimeOptions); } - public static void collectOptions(List> optionsClasses, EconomicMap allHostedOptions, + public static void collectOptions(ServiceLoader optionDescriptors, EconomicMap allHostedOptions, EconomicMap allRuntimeOptions) { - for (Class optionsClass : optionsClasses) { - if (Modifier.isAbstract(optionsClass.getModifiers()) || OptionDescriptorsMap.class.isAssignableFrom(optionsClass)) { - continue; - } - - OptionDescriptors descriptors; - try { - descriptors = optionsClass.getDeclaredConstructor().newInstance(); - } catch (Exception ex) { - throw shouldNotReachHere(ex); - } - for (OptionDescriptor descriptor : descriptors) { + for (OptionDescriptors optionDescriptor : optionDescriptors) { + for (OptionDescriptor descriptor : optionDescriptor) { String name = descriptor.getName(); if (descriptor.getDeclaringClass().getAnnotation(Platforms.class) != null) { From ba6c9b2fe611d1842062b1128531f67f6aa9c98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Fri, 10 Sep 2021 22:28:30 +0200 Subject: [PATCH 137/681] Implement --add-reads and use it to make library-support read ALL_UNNAMED --- substratevm/mx.substratevm/suite.py | 5 +- .../jdk11/NativeImageClassLoaderOptions.java | 6 ++ ...veImageClassLoaderSupportJDK11OrLater.java | 66 ++++++++++--------- .../native-image.properties | 1 + 4 files changed, 45 insertions(+), 33 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/org.graalvm.nativeimage.librarysupport/com.oracle.svm.junit/native-image.properties diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 32c101a167b8..a158ba35e9b9 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -645,7 +645,10 @@ "com.oracle.svm.junit": { "subDir": "src", - "sourceDirs": ["src"], + "sourceDirs": [ + "src", + "resources", + ], "dependencies": [ "com.oracle.svm.reflect", "mx:JUNIT_TOOL", diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderOptions.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderOptions.java index 36847454afe9..8f1dec73a5cb 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderOptions.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderOptions.java @@ -32,6 +32,7 @@ public class NativeImageClassLoaderOptions { static final String AddExportsAndOpensFormat = "/=(,)*"; + static final String AddReadsFormat = "=(,)*"; @APIOption(name = "add-exports", extra = true)// @Option(help = "Value " + AddExportsAndOpensFormat + " updates to export to , regardless of module declaration." + @@ -41,4 +42,9 @@ public class NativeImageClassLoaderOptions { @APIOption(name = "add-opens", extra = true)// @Option(help = "Value " + AddExportsAndOpensFormat + " updates to open to , regardless of module declaration.")// public static final HostedOptionKey AddOpens = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings()); + + @APIOption(name = "add-reads", extra = true)// + @Option(help = "Value " + AddReadsFormat + " updates to read , regardless of module declaration." + + " can be ALL-UNNAMED to read all unnamed modules.")// + public static final HostedOptionKey AddReads = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings()); } diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java index ed31cde2e425..e757507c4f9b 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java @@ -127,29 +127,14 @@ private ClassLoader getSingleClassloader(ModuleLayer moduleLayer) { return singleClassloader; } - private void adjustLibrarySupportReadAllUnnamed() { - /* - * org.graalvm.nativeimage.librarysupport depends on junit. Unfortunately using junit as - * automatic module is not possible because we have to support non-modularized tests as - * well. Thus, we have to explicitly allow org.graalvm.nativeimage.librarysupport to read - * ALL-UNNAMED so that junit from classpath is accessible to it. - * - * This workaround can be replaced with --add-reads use once GR-33504 is implemented. - */ - Optional librarySupportModule = findModule("org.graalvm.nativeimage.librarysupport"); - if (!librarySupportModule.isEmpty()) { - try { - Module moduleLibrarySupport = librarySupportModule.get(); - Method implAddReadsAllUnnamed = Module.class.getDeclaredMethod("implAddReadsAllUnnamed"); - ModuleSupport.openModuleByClass(Module.class, NativeImageClassLoaderSupportJDK11OrLater.class); - implAddReadsAllUnnamed.setAccessible(true); - implAddReadsAllUnnamed.invoke(moduleLibrarySupport); - } catch (ReflectiveOperationException | NoSuchElementException e) { - VMError.shouldNotReachHere("Could not adjust org.graalvm.nativeimage.librarysupport to read all unnamed modules", e); - } - } else { - VMError.guarantee(!ModuleSupport.modulePathBuild, - "Image-builder on module-path requires module org.graalvm.nativeimage.librarysupport"); + private void implAddReadsAllUnnamed(Module module) { + try { + Method implAddReadsAllUnnamed = Module.class.getDeclaredMethod("implAddReadsAllUnnamed"); + ModuleSupport.openModuleByClass(Module.class, NativeImageClassLoaderSupportJDK11OrLater.class); + implAddReadsAllUnnamed.setAccessible(true); + implAddReadsAllUnnamed.invoke(module); + } catch (ReflectiveOperationException | NoSuchElementException e) { + VMError.shouldNotReachHere("Could reflectively call Module.implAddReadsAllUnnamed", e); } } @@ -191,27 +176,44 @@ protected void processClassLoaderOptions(OptionValues parsedHostedOptions) { } }); - /* TODO: Implement real --add-reads instead */ - adjustLibrarySupportReadAllUnnamed(); + LocatableMultiOptionValue.Strings addReads = NativeImageClassLoaderOptions.AddReads.getValue(parsedHostedOptions); + addReads.getValuesWithOrigins().map(this::asAddReadsFormatValue).forEach(val -> { + if (val.targetModules.isEmpty()) { + implAddReadsAllUnnamed(val.module); + } else { + for (Module targetModule : val.targetModules) { + Modules.addReads(val.module, targetModule); + } + } + }); } - private static final class AddExportsAndOpensFormatValue { + private static final class AddExportsAndOpensAndReadsFormatValue { private final Module module; private final String packageName; private final List targetModules; - private AddExportsAndOpensFormatValue(Module module, String packageName, List targetModules) { + private AddExportsAndOpensAndReadsFormatValue(Module module, String packageName, List targetModules) { this.module = module; this.packageName = packageName; this.targetModules = targetModules; } } - private AddExportsAndOpensFormatValue asAddExportsAndOpensFormatValue(Pair valueOrigin) { + private AddExportsAndOpensAndReadsFormatValue asAddExportsAndOpensFormatValue(Pair valueOrigin) { + return asAddExportsAndOpensAndReadsFormatValue(valueOrigin, false); + } + + private AddExportsAndOpensAndReadsFormatValue asAddReadsFormatValue(Pair valueOrigin) { + return asAddExportsAndOpensAndReadsFormatValue(valueOrigin, true); + } + + private AddExportsAndOpensAndReadsFormatValue asAddExportsAndOpensAndReadsFormatValue(Pair valueOrigin, boolean reads) { String optionOrigin = valueOrigin.getRight(); String optionValue = valueOrigin.getLeft(); - String syntaxErrorMessage = " Allowed value format: " + NativeImageClassLoaderOptions.AddExportsAndOpensFormat; + String format = reads ? NativeImageClassLoaderOptions.AddReadsFormat : NativeImageClassLoaderOptions.AddExportsAndOpensFormat; + String syntaxErrorMessage = " Allowed value format: " + format; String[] modulePackageAndTargetModules = optionValue.split("=", 2); if (modulePackageAndTargetModules.length != 2) { @@ -221,11 +223,11 @@ private AddExportsAndOpensFormatValue asAddExportsAndOpensFormatValue(Pair 1 + (reads ? 0 : 1)) { throw userErrorAddExportsAndOpens(optionOrigin, optionValue, syntaxErrorMessage); } String moduleName = moduleAndPackage[0]; - String packageName = moduleAndPackage[1]; + String packageName = moduleAndPackage.length > 1 ? moduleAndPackage[1] : null; List targetModuleNamesList = Arrays.asList(targetModuleNames.split(",")); if (targetModuleNamesList.isEmpty()) { @@ -245,7 +247,7 @@ private AddExportsAndOpensFormatValue asAddExportsAndOpensFormatValue(Pair Date: Mon, 13 Sep 2021 14:17:40 +0200 Subject: [PATCH 138/681] Refactor NativeImageClassLoaderOptions processing Having Options defined in a JDK11 only is not compatible with Multi-release jar standard (JEP 238 states META-INF/services is not versioned) thus NativeImageClassLoaderOptions need to moved to base. In case the image builder runs on classpath we need to be tolerant towards invalid use of --add-exports -add-opens and --add-reads. This should be removed once we switch to unconditionally running image builder on module-path. --- ...veImageClassLoaderSupportJDK11OrLater.java | 61 +++++++++++-------- ...AbstractNativeImageClassLoaderSupport.java | 6 +- .../NativeImageClassLoaderOptions.java | 6 +- .../hosted/NativeImageClassLoaderSupport.java | 2 +- .../svm/hosted/option/HostedOptionParser.java | 4 +- 5 files changed, 46 insertions(+), 33 deletions(-) rename substratevm/src/{com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11 => com.oracle.svm.hosted/src/com/oracle/svm/hosted}/NativeImageClassLoaderOptions.java (91%) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java index e757507c4f9b..8fd5e7c4f666 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java @@ -46,6 +46,7 @@ import java.util.stream.Stream; import org.graalvm.collections.Pair; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import com.oracle.svm.core.option.LocatableMultiOptionValue; @@ -54,6 +55,7 @@ import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.AbstractNativeImageClassLoaderSupport; import com.oracle.svm.hosted.ImageClassLoader; +import com.oracle.svm.hosted.NativeImageClassLoaderOptions; import com.oracle.svm.util.ModuleSupport; import jdk.internal.module.Modules; @@ -154,9 +156,8 @@ protected Optional findModule(String moduleName) { } @Override - protected void processClassLoaderOptions(OptionValues parsedHostedOptions) { - LocatableMultiOptionValue.Strings addExports = NativeImageClassLoaderOptions.AddExports.getValue(parsedHostedOptions); - addExports.getValuesWithOrigins().map(this::asAddExportsAndOpensFormatValue).forEach(val -> { + protected void processClassLoaderOptions(OptionValues optionValues) { + processOption(optionValues, NativeImageClassLoaderOptions.AddExports).forEach(val -> { if (val.targetModules.isEmpty()) { Modules.addExportsToAllUnnamed(val.module, val.packageName); } else { @@ -165,8 +166,7 @@ protected void processClassLoaderOptions(OptionValues parsedHostedOptions) { } } }); - LocatableMultiOptionValue.Strings addOpens = NativeImageClassLoaderOptions.AddOpens.getValue(parsedHostedOptions); - addOpens.getValuesWithOrigins().map(this::asAddExportsAndOpensFormatValue).forEach(val -> { + processOption(optionValues, NativeImageClassLoaderOptions.AddOpens).forEach(val -> { if (val.targetModules.isEmpty()) { Modules.addOpensToAllUnnamed(val.module, val.packageName); } else { @@ -175,9 +175,7 @@ protected void processClassLoaderOptions(OptionValues parsedHostedOptions) { } } }); - - LocatableMultiOptionValue.Strings addReads = NativeImageClassLoaderOptions.AddReads.getValue(parsedHostedOptions); - addReads.getValuesWithOrigins().map(this::asAddReadsFormatValue).forEach(val -> { + processOption(optionValues, NativeImageClassLoaderOptions.AddReads).forEach(val -> { if (val.targetModules.isEmpty()) { implAddReadsAllUnnamed(val.module); } else { @@ -188,6 +186,28 @@ protected void processClassLoaderOptions(OptionValues parsedHostedOptions) { }); } + private Stream processOption(OptionValues parsedHostedOptions, OptionKey specificOption) { + Stream> valuesWithOrigins = specificOption.getValue(parsedHostedOptions).getValuesWithOrigins(); + Stream parsedOptions = valuesWithOrigins.flatMap(valWithOrig -> { + try { + return Stream.of(asAddExportsAndOpensAndReadsFormatValue(specificOption, valWithOrig)); + } catch (UserError.UserException e) { + if (ModuleSupport.modulePathBuild) { + throw e; + } else { + /* + * Until we switch to always running the image-builder on module-path we have to + * be tolerant if invalid --add-exports -add-opens or --add-reads options are + * used. GR-30433 + */ + System.out.println("Warning: " + e.getMessage()); + return Stream.empty(); + } + } + }); + return parsedOptions; + } + private static final class AddExportsAndOpensAndReadsFormatValue { private final Module module; private final String packageName; @@ -200,42 +220,35 @@ private AddExportsAndOpensAndReadsFormatValue(Module module, String packageName, } } - private AddExportsAndOpensAndReadsFormatValue asAddExportsAndOpensFormatValue(Pair valueOrigin) { - return asAddExportsAndOpensAndReadsFormatValue(valueOrigin, false); - } - - private AddExportsAndOpensAndReadsFormatValue asAddReadsFormatValue(Pair valueOrigin) { - return asAddExportsAndOpensAndReadsFormatValue(valueOrigin, true); - } - - private AddExportsAndOpensAndReadsFormatValue asAddExportsAndOpensAndReadsFormatValue(Pair valueOrigin, boolean reads) { + private AddExportsAndOpensAndReadsFormatValue asAddExportsAndOpensAndReadsFormatValue(OptionKey option, Pair valueOrigin) { String optionOrigin = valueOrigin.getRight(); String optionValue = valueOrigin.getLeft(); + boolean reads = option.equals(NativeImageClassLoaderOptions.AddReads); String format = reads ? NativeImageClassLoaderOptions.AddReadsFormat : NativeImageClassLoaderOptions.AddExportsAndOpensFormat; String syntaxErrorMessage = " Allowed value format: " + format; String[] modulePackageAndTargetModules = optionValue.split("=", 2); if (modulePackageAndTargetModules.length != 2) { - throw userErrorAddExportsAndOpens(optionOrigin, optionValue, syntaxErrorMessage); + throw userErrorAddExportsAndOpensAndReads(option, optionOrigin, optionValue, syntaxErrorMessage); } String modulePackage = modulePackageAndTargetModules[0]; String targetModuleNames = modulePackageAndTargetModules[1]; String[] moduleAndPackage = modulePackage.split("/"); if (moduleAndPackage.length > 1 + (reads ? 0 : 1)) { - throw userErrorAddExportsAndOpens(optionOrigin, optionValue, syntaxErrorMessage); + throw userErrorAddExportsAndOpensAndReads(option, optionOrigin, optionValue, syntaxErrorMessage); } String moduleName = moduleAndPackage[0]; String packageName = moduleAndPackage.length > 1 ? moduleAndPackage[1] : null; List targetModuleNamesList = Arrays.asList(targetModuleNames.split(",")); if (targetModuleNamesList.isEmpty()) { - throw userErrorAddExportsAndOpens(optionOrigin, optionValue, syntaxErrorMessage); + throw userErrorAddExportsAndOpensAndReads(option, optionOrigin, optionValue, syntaxErrorMessage); } Module module = findModule(moduleName).orElseThrow(() -> { - return userErrorAddExportsAndOpens(optionOrigin, optionValue, " Specified module '" + moduleName + "' is unknown."); + return userErrorAddExportsAndOpensAndReads(option, optionOrigin, optionValue, " Specified module '" + moduleName + "' is unknown."); }); List targetModules; if (targetModuleNamesList.contains("ALL-UNNAMED")) { @@ -243,16 +256,16 @@ private AddExportsAndOpensAndReadsFormatValue asAddExportsAndOpensAndReadsFormat } else { targetModules = targetModuleNamesList.stream().map(mn -> { return findModule(mn).orElseThrow(() -> { - throw userErrorAddExportsAndOpens(optionOrigin, optionValue, " Specified target-module '" + mn + "' is unknown."); + throw userErrorAddExportsAndOpensAndReads(option, optionOrigin, optionValue, " Specified target-module '" + mn + "' is unknown."); }); }).collect(Collectors.toList()); } return new AddExportsAndOpensAndReadsFormatValue(module, packageName, targetModules); } - private static UserError.UserException userErrorAddExportsAndOpens(String origin, String value, String detailMessage) { + private static UserError.UserException userErrorAddExportsAndOpensAndReads(OptionKey option, String origin, String value, String detailMessage) { Objects.requireNonNull(detailMessage, "missing detailMessage"); - return UserError.abort("Invalid option %s provided by %s." + detailMessage, SubstrateOptionsParser.commandArgument(NativeImageClassLoaderOptions.AddExports, value), origin); + return UserError.abort("Invalid option %s provided by %s." + detailMessage, SubstrateOptionsParser.commandArgument(option, value), origin); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AbstractNativeImageClassLoaderSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AbstractNativeImageClassLoaderSupport.java index 0a5a8a6aa2e0..37c0e461fbf5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AbstractNativeImageClassLoaderSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AbstractNativeImageClassLoaderSupport.java @@ -116,14 +116,14 @@ public ClassLoader getClassLoader() { public void setupHostedOptionParser(List arguments) { hostedOptionParser = new HostedOptionParser(getClassLoader()); - remainingArguments = Collections.unmodifiableList(Arrays.asList(hostedOptionParser.parse(arguments.toArray(new String[0])))); + remainingArguments = Collections.unmodifiableList((hostedOptionParser.parse(arguments))); parsedHostedOptions = new OptionValues(hostedOptionParser.getHostedValues()); processClassLoaderOptions(parsedHostedOptions); } public HostedOptionParser getHostedOptionParser() { return hostedOptionParser; - }; + } public List getRemainingArguments() { return remainingArguments; @@ -133,7 +133,7 @@ public OptionValues getParsedHostedOptions() { return parsedHostedOptions; } - protected abstract void processClassLoaderOptions(OptionValues parsedHostedOptions); + protected abstract void processClassLoaderOptions(OptionValues optionValues); protected abstract void initAllClasses(ForkJoinPool executor, ImageClassLoader imageClassLoader); diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderOptions.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderOptions.java similarity index 91% rename from substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderOptions.java rename to substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderOptions.java index 8f1dec73a5cb..58fa54f1cde3 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderOptions.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderOptions.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.hosted.jdk11; +package com.oracle.svm.hosted; import org.graalvm.compiler.options.Option; @@ -31,8 +31,8 @@ import com.oracle.svm.core.option.LocatableMultiOptionValue; public class NativeImageClassLoaderOptions { - static final String AddExportsAndOpensFormat = "/=(,)*"; - static final String AddReadsFormat = "=(,)*"; + public static final String AddExportsAndOpensFormat = "/=(,)*"; + public static final String AddReadsFormat = "=(,)*"; @APIOption(name = "add-exports", extra = true)// @Option(help = "Value " + AddExportsAndOpensFormat + " updates to export to , regardless of module declaration." + diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java index ab62ac5c4a67..a21f19a7e8b2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java @@ -54,7 +54,7 @@ protected Optional findModule(String moduleName) { } @Override - protected void processClassLoaderOptions(OptionValues parsedHostedOptions) { + protected void processClassLoaderOptions(OptionValues optionValues) { /* Nothing to do for Java 8 */ } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java index 6654e36002b6..657da655ed43 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java @@ -85,7 +85,7 @@ public static void collectOptions(ServiceLoader optionDescrip } } - public String[] parse(String[] args) { + public List parse(List args) { List remainingArgs = new ArrayList<>(); Set errors = new HashSet<>(); @@ -124,7 +124,7 @@ public String[] parse(String[] args) { } } - return remainingArgs.toArray(new String[remainingArgs.size()]); + return remainingArgs; } @Override From 64cc9ba7362f0a0ab90ec7cec6c2dd10998021b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Mon, 13 Sep 2021 18:00:58 +0200 Subject: [PATCH 139/681] Run mx native-unittest always with imagebuilder on module-path 1. Moved com.oracle.svm.junit into its own module so that org.graalvm.nativeimage.librarysupport does not contain code that is only needed when building junit-images. 2. Adjusted --add-reads to make org.graalvm.nativeimage.junitsupport read ALL-UNNAMED. 3. Adjusted junit macro option to have org.graalvm.nativeimage.junitsupport on the module-path. This also takes care of making the imagebuilder run on module-path (ImageModulePath counts as module-related option for the driver). 4. Remove now obsolete hacks to have com.oracle.mxtool.junit, junit, hamcrest as optional module dependencies all over the place. --- compiler/mx.compiler/suite.py | 2 +- .../mx.substratevm/macro-junit.properties | 1 + substratevm/mx.substratevm/mx_substratevm.py | 2 +- substratevm/mx.substratevm/suite.py | 53 ++++++++----------- .../native-image.properties | 2 +- 5 files changed, 27 insertions(+), 33 deletions(-) diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index c4d7d5abd557..44c8551c3b11 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -2173,7 +2173,7 @@ "org.graalvm.compiler.debug to jdk.internal.vm.compiler.management,org.graalvm.nativeimage.objectfile", "org.graalvm.compiler.hotspot to jdk.internal.vm.compiler.management", "org.graalvm.compiler.nodes.graphbuilderconf to org.graalvm.nativeimage.driver", - "org.graalvm.compiler.options to jdk.internal.vm.compiler.management,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.librarysupport", + "org.graalvm.compiler.options to jdk.internal.vm.compiler.management,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.junitsupport", "org.graalvm.compiler.phases.common to org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.configure", "org.graalvm.compiler.phases.common.jmx to jdk.internal.vm.compiler.management", "org.graalvm.compiler.serviceprovider to jdk.internal.vm.compiler.management,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.diagnostics", diff --git a/substratevm/mx.substratevm/macro-junit.properties b/substratevm/mx.substratevm/macro-junit.properties index 8c093a44d0f1..6f802d0e00a0 100644 --- a/substratevm/mx.substratevm/macro-junit.properties +++ b/substratevm/mx.substratevm/macro-junit.properties @@ -2,6 +2,7 @@ ImageName = svmjunit +ImageModulePath = ${.}/junit-support.jar ImageClasspath = ${.}/junit-tool.jar:${.}/junit.jar:${.}/hamcrest.jar Args = -H:Features=com.oracle.svm.junit.JUnitFeature \ diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 2e5dc90cb77f..a0b45889c280 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -928,7 +928,7 @@ def _native_image_launcher_extra_jvm_args(): license_files=[], third_party_license_files=[], dependencies=['SubstrateVM'], - jar_distributions=['mx:JUNIT_TOOL', 'mx:JUNIT', 'mx:HAMCREST'], + jar_distributions=['substratevm:JUNIT_SUPPORT', 'mx:JUNIT_TOOL', 'mx:JUNIT', 'mx:HAMCREST'], support_distributions=['substratevm:NATIVE_IMAGE_JUNIT_SUPPORT'], jlink=False, )) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index a158ba35e9b9..53e0398678b8 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1103,7 +1103,7 @@ "com.oracle.svm.hosted to java.base", "com.oracle.svm.hosted.agent to java.instrument", "com.oracle.svm.truffle.api to org.graalvm.truffle", - "* to jdk.internal.vm.compiler,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.configure,org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.llvm,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.agent.diagnostics,com.oracle.svm.svm_enterprise", + "* to jdk.internal.vm.compiler,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.configure,org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.junitsupport,org.graalvm.nativeimage.llvm,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.agent.diagnostics,com.oracle.svm.svm_enterprise", ], "opens" : [ "com.oracle.svm.core.nodes to jdk.internal.vm.compiler", @@ -1192,11 +1192,6 @@ "com.oracle.svm.jvmtiagentbase", "com.oracle.svm.jvmtiagentbase.jvmti", ], - "requires" : [ - "static com.oracle.mxtool.junit", - "static junit", - "static hamcrest", - ], }, }, @@ -1204,27 +1199,43 @@ "subDir": "src", "description" : "SubstrateVM basic library-support components", "dependencies": [ - "com.oracle.svm.junit", "com.oracle.svm.polyglot", "com.oracle.svm.thirdparty", ], "distDependencies": [ "sdk:GRAAL_SDK", "SVM", - "OBJECTFILE", + ], + "moduleInfo" : { + "name" : "org.graalvm.nativeimage.librarysupport", + "exports" : [ + "* to org.graalvm.nativeimage.builder", + ], + }, + }, + + "JUNIT_SUPPORT": { + "subDir": "src", + "description" : "SubstrateVM suppoprt for building JUnit test into image", + "dependencies": [ + "com.oracle.svm.junit", + ], + "distDependencies": [ + "sdk:GRAAL_SDK", + "SVM", "compiler:GRAAL", "mx:JUNIT_TOOL", ], "moduleInfo" : { - "name" : "org.graalvm.nativeimage.librarysupport", + "name" : "org.graalvm.nativeimage.junitsupport", + "exports" : [ + "* to org.graalvm.nativeimage.builder", + ], "requires" : [ "static com.oracle.mxtool.junit", "static junit", "static hamcrest", ], - "exports" : [ - "* to org.graalvm.nativeimage.builder", - ], }, }, @@ -1322,9 +1333,6 @@ "org.graalvm.nativeimage.builder", "java.management", "jdk.management", - "static com.oracle.mxtool.junit", - "static junit", - "static hamcrest", ], }, }, @@ -1347,11 +1355,6 @@ "exports" : [ "com.oracle.svm.agent", ], - "requires" : [ - "static com.oracle.mxtool.junit", - "static junit", - "static hamcrest", - ], "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", @@ -1376,11 +1379,6 @@ "exports" : [ "com.oracle.svm.diagnosticsagent", ], - "requires" : [ - "static com.oracle.mxtool.junit", - "static junit", - "static hamcrest", - ], }, }, @@ -1401,11 +1399,6 @@ "* to org.graalvm.nativeimage.agent.tracing", "com.oracle.svm.configure", ], - "requires" : [ - "static com.oracle.mxtool.junit", - "static junit", - "static hamcrest", - ], }, }, diff --git a/substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/org.graalvm.nativeimage.librarysupport/com.oracle.svm.junit/native-image.properties b/substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/org.graalvm.nativeimage.librarysupport/com.oracle.svm.junit/native-image.properties index e0e5fcbb6694..14446be07331 100644 --- a/substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/org.graalvm.nativeimage.librarysupport/com.oracle.svm.junit/native-image.properties +++ b/substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/org.graalvm.nativeimage.librarysupport/com.oracle.svm.junit/native-image.properties @@ -1 +1 @@ -Args = --add-reads=org.graalvm.nativeimage.librarysupport=ALL-UNNAMED +Args = --add-reads=org.graalvm.nativeimage.junitsupport=ALL-UNNAMED From 8b5111adf50afe51fc7a8dd0f10f9ddf008ffee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Wed, 15 Sep 2021 17:43:32 +0200 Subject: [PATCH 140/681] Use builder on mp only when running Task('native unittests') --- .../mx.substratevm/macro-junitcp.properties | 10 ++++++++ substratevm/mx.substratevm/mx_substratevm.py | 25 +++++++++++++++---- substratevm/mx.substratevm/suite.py | 8 ++++++ .../native-image.properties | 0 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 substratevm/mx.substratevm/macro-junitcp.properties rename substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/{org.graalvm.nativeimage.librarysupport => org.graalvm.nativeimage.junitsupport}/com.oracle.svm.junit/native-image.properties (100%) diff --git a/substratevm/mx.substratevm/macro-junitcp.properties b/substratevm/mx.substratevm/macro-junitcp.properties new file mode 100644 index 000000000000..3fb002782ec9 --- /dev/null +++ b/substratevm/mx.substratevm/macro-junitcp.properties @@ -0,0 +1,10 @@ +# This file contains support for building a set of junit tests into a native-image + +ImageName = svmjunit + +ImageClasspath = ${.}/junit-support.jar:${.}/junit-tool.jar:${.}/junit.jar:${.}/hamcrest.jar + +Args = -H:Features=com.oracle.svm.junit.JUnitFeature \ + -H:Class=com.oracle.svm.junit.SVMJUnitRunner \ + -H:TestFile=${*} \ + --initialize-at-build-time=org.junit,com.oracle.mxtool.junit.MxJUnitRequest diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index a0b45889c280..b9ddd68be848 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -434,7 +434,7 @@ def native_unittests_task(): '-H:AdditionalSecurityServiceTypes=com.oracle.svm.test.SecurityServiceTest$JCACompliantNoOpService' ] - native_unittest(['--build-args', _native_unittest_features] + additional_build_args) + native_unittest(['--builder-on-modulepath', '--build-args', _native_unittest_features] + additional_build_args) def javac_image_command(javac_path): @@ -442,7 +442,7 @@ def javac_image_command(javac_path): join(mx_compiler.jdk.home, "jre", "lib", "rt.jar")] -def _native_junit(native_image, unittest_args, build_args=None, run_args=None, blacklist=None, whitelist=None, preserve_image=False): +def _native_junit(native_image, unittest_args, build_args=None, run_args=None, blacklist=None, whitelist=None, preserve_image=False, builder_on_modulepath=False): build_args = build_args or [] javaProperties = {} for dist in suite.dists: @@ -469,7 +469,8 @@ def dummy_harness(test_deps, vm_launcher, vm_args): with open(unittest_file, 'r') as f: mx.log('Building junit image for matching: ' + ' '.join(l.rstrip() for l in f)) extra_image_args = mx.get_runtime_jvm_args(unittest_deps, jdk=mx_compiler.jdk, exclude_names=['substratevm:LIBRARY_SUPPORT']) - unittest_image = native_image(['-ea', '-esa'] + build_args + extra_image_args + ['--macro:junit=' + unittest_file, '-H:Path=' + junit_test_dir]) + macro_junit = '--macro:junit' + ('' if builder_on_modulepath else 'cp') + unittest_image = native_image(['-ea', '-esa'] + build_args + extra_image_args + [macro_junit + '=' + unittest_file, '-H:Path=' + junit_test_dir]) mx.log('Running: ' + ' '.join(map(pipes.quote, [unittest_image] + run_args))) mx.run([unittest_image] + run_args) finally: @@ -492,13 +493,14 @@ def unmask(args): def _native_unittest(native_image, cmdline_args): parser = ArgumentParser(prog='mx native-unittest', description='Run unittests as native image.') - all_args = ['--build-args', '--run-args', '--blacklist', '--whitelist', '-p', '--preserve-image'] + all_args = ['--build-args', '--run-args', '--blacklist', '--whitelist', '-p', '--preserve-image', '--builder-on-modulepath'] cmdline_args = [_mask(arg, all_args) for arg in cmdline_args] parser.add_argument(all_args[0], metavar='ARG', nargs='*', default=[]) parser.add_argument(all_args[1], metavar='ARG', nargs='*', default=[]) parser.add_argument('--blacklist', help='run all testcases not specified in ', metavar='') parser.add_argument('--whitelist', help='run testcases specified in only', metavar='') parser.add_argument('-p', '--preserve-image', help='do not delete the generated native image', action='store_true') + parser.add_argument('--builder-on-modulepath', help='perform image build with builder on module-path', action='store_true') parser.add_argument('unittest_args', metavar='TEST_ARG', nargs='*') pargs = parser.parse_args(cmdline_args) @@ -519,7 +521,7 @@ def _native_unittest(native_image, cmdline_args): mx.log('warning: could not read blacklist: ' + blacklist) unittest_args = unmask(pargs.unittest_args) if unmask(pargs.unittest_args) else ['com.oracle.svm.test', 'com.oracle.svm.configure.test'] - _native_junit(native_image, unittest_args, unmask(pargs.build_args), unmask(pargs.run_args), blacklist, whitelist, pargs.preserve_image) + _native_junit(native_image, unittest_args, unmask(pargs.build_args), unmask(pargs.run_args), blacklist, whitelist, pargs.preserve_image, pargs.builder_on_modulepath) def js_image_test(binary, bench_location, name, warmup_iterations, iterations, timeout=None, bin_args=None): @@ -933,6 +935,19 @@ def _native_image_launcher_extra_jvm_args(): jlink=False, )) +mx_sdk_vm.register_graalvm_component(mx_sdk_vm.GraalVMSvmMacro( + suite=suite, + name='Native Image JUnit with image-builder on classpath', + short_name='njucp', + dir_name='junitcp', + license_files=[], + third_party_license_files=[], + dependencies=['SubstrateVM'], + jar_distributions=['substratevm:JUNIT_SUPPORT', 'mx:JUNIT_TOOL', 'mx:JUNIT', 'mx:HAMCREST'], + support_distributions=['substratevm:NATIVE_IMAGE_JUNITCP_SUPPORT'], + jlink=False, +)) + jar_distributions = [ 'substratevm:GRAAL_HOTSPOT_LIBRARY', 'compiler:GRAAL_TRUFFLE_COMPILER_LIBGRAAL', diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 53e0398678b8..a0ef98a360cf 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1569,6 +1569,14 @@ }, }, + "NATIVE_IMAGE_JUNITCP_SUPPORT" : { + "native" : True, + "description" : "Native-image based junit testing support but with running image-builder on classpath", + "layout" : { + "native-image.properties" : "file:mx.substratevm/macro-junitcp.properties", + }, + }, + "SVM_LLVM" : { "subDir" : "src", "description" : "LLVM backend for Native Image", diff --git a/substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/org.graalvm.nativeimage.librarysupport/com.oracle.svm.junit/native-image.properties b/substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/org.graalvm.nativeimage.junitsupport/com.oracle.svm.junit/native-image.properties similarity index 100% rename from substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/org.graalvm.nativeimage.librarysupport/com.oracle.svm.junit/native-image.properties rename to substratevm/src/com.oracle.svm.junit/resources/META-INF/native-image/org.graalvm.nativeimage.junitsupport/com.oracle.svm.junit/native-image.properties From 82b2acd45565ab3611338d548f5469fcc1f0ca6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Wed, 15 Sep 2021 18:05:50 +0200 Subject: [PATCH 141/681] Add newly added njucp to graalvm components list --- vm/mx.vm/mx_vm.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index a1f7a979916f..23527feb4938 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -131,7 +131,7 @@ ce_components = ['bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'poly', 'polynative', 'pro', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] ce_complete_components = ['bpolyglot', 'cmp', 'cov', 'dap', 'ejvm', 'gu', 'gvm', 'gwa', 'ins', 'insight', 'insightheap', 'java', 'js', 'lg', 'libpoly', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nil', 'njs', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rby', 'rbyl', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] ce_ruby_components = ['cmp', 'cov', 'dap', 'gvm', 'ins', 'insight', 'insightheap', 'lg', 'llp', 'llrc', 'llrn', 'lsp', 'nfi', 'pro', 'rby', 'rbyl', 'rgx', 'sdk', 'svm', 'svmnfi', 'tfl', 'tflm', 'vvm'] -ce_python_components = ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgu', 'bjs', 'blli', 'bllimul', 'bnative-image', 'bnative-image-configure', 'bpolybench', 'bpolyglot', 'cmp', 'cov', 'dap', 'dis', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llmulrl', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nic', 'nil', 'nju', 'pbm', 'pmh', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svml', 'svmnfi', 'tfl', 'tflm', 'vvm'] +ce_python_components = ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgu', 'bjs', 'blli', 'bllimul', 'bnative-image', 'bnative-image-configure', 'bpolybench', 'bpolyglot', 'cmp', 'cov', 'dap', 'dis', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llmulrl', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nic', 'nil', 'nju', 'njucp', 'pbm', 'pmh', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svml', 'svmnfi', 'tfl', 'tflm', 'vvm'] ce_fastr_components = ce_components + ['R', 'llp', 'bRMain'] ce_no_native_components = ['bgu', 'bjs', 'blli', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgraalvm-native-binutil', 'bnative-image', 'bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lsp', 'nfi', 'ni', 'nil', 'polynative', 'pro', 'rgx', 'sdk', 'llrc', 'llrn', 'llrl', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'libpoly', 'poly', 'vvm'] @@ -153,9 +153,9 @@ mx_sdk_vm.register_vm_config('ce', ce_components + ['llmulrl'], _suite, env_file='ce-llimul') if mx.get_os() == 'windows': - mx_sdk_vm.register_vm_config('svm', ['bnative-image', 'bnative-image-configure', 'bpolyglot', 'cmp', 'gvm', 'nfi', 'ni', 'nil', 'nju', 'nic', 'poly', 'polynative', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmnfi', 'tfl', 'tflm'], _suite, env_file=False) + mx_sdk_vm.register_vm_config('svm', ['bnative-image', 'bnative-image-configure', 'bpolyglot', 'cmp', 'gvm', 'nfi', 'ni', 'nil', 'nju', 'njucp', 'nic', 'poly', 'polynative', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmnfi', 'tfl', 'tflm'], _suite, env_file=False) else: - mx_sdk_vm.register_vm_config('svm', ['bnative-image', 'bnative-image-configure', 'bpolyglot', 'cmp', 'gu', 'gvm', 'nfi', 'ni', 'nil', 'nju', 'nic', 'poly', 'polynative', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm'], _suite, env_file=False) + mx_sdk_vm.register_vm_config('svm', ['bnative-image', 'bnative-image-configure', 'bpolyglot', 'cmp', 'gu', 'gvm', 'nfi', 'ni', 'nil', 'nju', 'njucp', 'nic', 'poly', 'polynative', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm'], _suite, env_file=False) # pylint: enable=line-too-long From d93cfbe2cff0b3b04687b0bd83447b0c78ef29fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 16 Sep 2021 10:10:37 +0200 Subject: [PATCH 142/681] Add missing org.graalvm.nativeimage.builder moduleinfo --- substratevm/mx.substratevm/suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index a0ef98a360cf..dfb7d69b4a81 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1106,6 +1106,7 @@ "* to jdk.internal.vm.compiler,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.configure,org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.junitsupport,org.graalvm.nativeimage.llvm,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.agent.diagnostics,com.oracle.svm.svm_enterprise", ], "opens" : [ + "com.oracle.svm.core to jdk.internal.vm.compiler", "com.oracle.svm.core.nodes to jdk.internal.vm.compiler", "com.oracle.svm.core.graal.nodes to jdk.internal.vm.compiler", "com.oracle.svm.core.graal.snippets to jdk.internal.vm.compiler", From 88b055ff473f1a1a60e450917de69932847097c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 16 Sep 2021 10:33:07 +0200 Subject: [PATCH 143/681] Ensure mx native-unittest remains usable on Java 8 --- substratevm/mx.substratevm/mx_substratevm.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index b9ddd68be848..a87f11929cfc 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -521,7 +521,11 @@ def _native_unittest(native_image, cmdline_args): mx.log('warning: could not read blacklist: ' + blacklist) unittest_args = unmask(pargs.unittest_args) if unmask(pargs.unittest_args) else ['com.oracle.svm.test', 'com.oracle.svm.configure.test'] - _native_junit(native_image, unittest_args, unmask(pargs.build_args), unmask(pargs.run_args), blacklist, whitelist, pargs.preserve_image, pargs.builder_on_modulepath) + builder_on_modulepath = pargs.builder_on_modulepath + if builder_on_modulepath and svm_java8(): + mx.log('On Java 8, unittests cannot be built with imagebuilder on module-path. Reverting to imagebuilder on classpath.') + builder_on_modulepath = False + _native_junit(native_image, unittest_args, unmask(pargs.build_args), unmask(pargs.run_args), blacklist, whitelist, pargs.preserve_image, builder_on_modulepath) def js_image_test(binary, bench_location, name, warmup_iterations, iterations, timeout=None, bin_args=None): From 728da3c6138dbff4fb230a0c95c6647fc3f2150e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 16 Sep 2021 10:47:01 +0200 Subject: [PATCH 144/681] Add missing org.graalvm.nativeimage.builder moduleinfo --- substratevm/mx.substratevm/suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index dfb7d69b4a81..341eeaefee3e 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1111,6 +1111,7 @@ "com.oracle.svm.core.graal.nodes to jdk.internal.vm.compiler", "com.oracle.svm.core.graal.snippets to jdk.internal.vm.compiler", "com.oracle.svm.hosted.fieldfolding to jdk.internal.vm.compiler", + "com.oracle.svm.reflect.hosted to jdk.internal.vm.compiler", ], "requires": [ "java.management", From 5bfb17dcb74aea3ec80bf08f1565207a496334cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 16 Sep 2021 11:03:07 +0200 Subject: [PATCH 145/681] Add newly added njucp to EXCLUDE_COMPONENTS --- vm/mx.vm/ce | 2 +- vm/mx.vm/ce-aarch64 | 2 +- vm/mx.vm/ce-complete | 2 +- vm/mx.vm/ce-fastr | 2 +- vm/mx.vm/ce-llimul | 2 +- vm/mx.vm/ce-no_native | 2 +- vm/mx.vm/ce-nodejs | 2 +- vm/mx.vm/ce-win | 2 +- vm/mx.vm/libgraal | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/vm/mx.vm/ce b/vm/mx.vm/ce index 676188ca8274..7b181de18acf 100644 --- a/vm/mx.vm/ce +++ b/vm/mx.vm/ce @@ -1,4 +1,4 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-js -EXCLUDE_COMPONENTS=nju,nic,ni,nil,llp,dis,pbm,pmh,llmulrl +EXCLUDE_COMPONENTS=nju,njucp,nic,ni,nil,llp,dis,pbm,pmh,llmulrl FORCE_BASH_LAUNCHERS=polyglot,polybench SKIP_LIBRARIES=polyglot diff --git a/vm/mx.vm/ce-aarch64 b/vm/mx.vm/ce-aarch64 index 676188ca8274..7b181de18acf 100644 --- a/vm/mx.vm/ce-aarch64 +++ b/vm/mx.vm/ce-aarch64 @@ -1,4 +1,4 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-js -EXCLUDE_COMPONENTS=nju,nic,ni,nil,llp,dis,pbm,pmh,llmulrl +EXCLUDE_COMPONENTS=nju,njucp,nic,ni,nil,llp,dis,pbm,pmh,llmulrl FORCE_BASH_LAUNCHERS=polyglot,polybench SKIP_LIBRARIES=polyglot diff --git a/vm/mx.vm/ce-complete b/vm/mx.vm/ce-complete index ce308d20846d..29f1021891a8 100644 --- a/vm/mx.vm/ce-complete +++ b/vm/mx.vm/ce-complete @@ -1,5 +1,5 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-nodejs,truffleruby,graalpython,/wasm,/espresso DISABLE_INSTALLABLES=true -EXCLUDE_COMPONENTS=nju,nic,dis,pbm,pmh,llmulrl,elau +EXCLUDE_COMPONENTS=nju,njucp,nic,dis,pbm,pmh,llmulrl,elau FORCE_BASH_LAUNCHERS=polyglot SKIP_LIBRARIES=polyglot diff --git a/vm/mx.vm/ce-fastr b/vm/mx.vm/ce-fastr index e0b62f319b2b..f2b4758d9b82 100644 --- a/vm/mx.vm/ce-fastr +++ b/vm/mx.vm/ce-fastr @@ -1,4 +1,4 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-js,fastr -EXCLUDE_COMPONENTS=nju,nic,ni,nil,dis,pbm,pmh,llmulrl +EXCLUDE_COMPONENTS=nju,njucp,nic,ni,nil,dis,pbm,pmh,llmulrl FORCE_BASH_LAUNCHERS=polyglot,polybench,RMain SKIP_LIBRARIES=polyglot diff --git a/vm/mx.vm/ce-llimul b/vm/mx.vm/ce-llimul index 546fc458261a..fc626e8b25f3 100644 --- a/vm/mx.vm/ce-llimul +++ b/vm/mx.vm/ce-llimul @@ -1,4 +1,4 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-js -EXCLUDE_COMPONENTS=nju,nic,ni,nil,llp,dis,pbm,pmh +EXCLUDE_COMPONENTS=nju,njucp,nic,ni,nil,llp,dis,pbm,pmh FORCE_BASH_LAUNCHERS=polyglot,polybench SKIP_LIBRARIES=polyglot diff --git a/vm/mx.vm/ce-no_native b/vm/mx.vm/ce-no_native index 73ac59f549d2..8372159778ee 100644 --- a/vm/mx.vm/ce-no_native +++ b/vm/mx.vm/ce-no_native @@ -2,4 +2,4 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-js DISABLE_INSTALLABLES=ni,nil FORCE_BASH_LAUNCHERS=true SKIP_LIBRARIES=true -EXCLUDE_COMPONENTS=nju,nic,llp,lg,dis,pbm,pmh,llmulrl +EXCLUDE_COMPONENTS=nju,njucp,nic,llp,lg,dis,pbm,pmh,llmulrl diff --git a/vm/mx.vm/ce-nodejs b/vm/mx.vm/ce-nodejs index 50467538a39f..faeee88a6033 100644 --- a/vm/mx.vm/ce-nodejs +++ b/vm/mx.vm/ce-nodejs @@ -1,4 +1,4 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-nodejs -EXCLUDE_COMPONENTS=nju,nic,ni,nil,llp,dis,pbm,pmh,llmulrl +EXCLUDE_COMPONENTS=nju,njucp,nic,ni,nil,llp,dis,pbm,pmh,llmulrl FORCE_BASH_LAUNCHERS=polyglot,polybench SKIP_LIBRARIES=polyglot diff --git a/vm/mx.vm/ce-win b/vm/mx.vm/ce-win index 792bb33844e1..e4da0dd26b49 100644 --- a/vm/mx.vm/ce-win +++ b/vm/mx.vm/ce-win @@ -1,4 +1,4 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/graal-js -EXCLUDE_COMPONENTS=nju,nic,ni,nil,svml,llp,dis,pbm,pmh,llmulrl +EXCLUDE_COMPONENTS=nju,njucp,nic,ni,nil,svml,llp,dis,pbm,pmh,llmulrl FORCE_BASH_LAUNCHERS=polyglot SKIP_LIBRARIES=polyglot diff --git a/vm/mx.vm/libgraal b/vm/mx.vm/libgraal index ec20d587bb20..258f33eb5bd8 100644 --- a/vm/mx.vm/libgraal +++ b/vm/mx.vm/libgraal @@ -1,4 +1,4 @@ DYNAMIC_IMPORTS=/substratevm FORCE_BASH_LAUNCHERS=true DISABLE_LIBPOLYGLOT=true -EXCLUDE_COMPONENTS=svmag,nju,nic,ni,nil,llp,pbm,pmh +EXCLUDE_COMPONENTS=svmag,nju,njucp,nic,ni,nil,llp,pbm,pmh From 94573d875e8aedccc3e37a94965328cb45cfa007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 16 Sep 2021 15:54:18 +0200 Subject: [PATCH 146/681] Move InterruptImageBuilding handling outer so that it catches InterruptImageBuilding used in HostedOptionParser --- .../hosted/NativeImageGeneratorRunner.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index 56efbffcb0f3..62fa12334605 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -124,6 +124,16 @@ public void run() { throw UserError.abort("Unknown options: %s", String.join(" ", remainingArguments)); } exitStatus = new NativeImageGeneratorRunner().build(imageClassLoader); + } catch (InterruptImageBuilding e) { + if (e.getReason().isPresent()) { + if (!e.getReason().get().isEmpty()) { + NativeImageGeneratorRunner.info(e.getReason().get()); + } + exitStatus = 0; + } else { + /* InterruptImageBuilding without explicit reason is exit code 3 */ + exitStatus = 3; + } } finally { uninstallNativeImageClassLoader(); Thread.currentThread().setContextClassLoader(applicationClassLoader); @@ -405,15 +415,7 @@ private int buildImage(ImageClassLoader classLoader) { if (compilationExecutor != null) { compilationExecutor.shutdownNow(); } - if (e.getReason().isPresent()) { - if (!e.getReason().get().isEmpty()) { - NativeImageGeneratorRunner.info(e.getReason().get()); - } - return 0; - } else { - /* InterruptImageBuilding without explicit reason is exit code 3 */ - return 3; - } + throw e; } catch (FallbackFeature.FallbackImageRequest e) { if (FallbackExecutor.class.getName().equals(SubstrateOptions.Class.getValue())) { NativeImageGeneratorRunner.reportFatalError(e, "FallbackImageRequest while building fallback image."); From 37dd4e1e9b2284a2c8c911b686063d5725bb04e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 16 Sep 2021 16:09:40 +0200 Subject: [PATCH 147/681] Ensure UserException during HostedOptionParser parsing gets handled --- .../src/com/oracle/svm/core/option/SubstrateOptionsParser.java | 2 +- .../src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java index f049bd43c7e9..0a7c8961ad3b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java @@ -224,7 +224,7 @@ static OptionParseResult parseOption(EconomicMap optio msg.append(' ').append(match.getName()); } } - msg.append(". Use ").append(optionPrefix).append(SubstrateOptions.PrintFlags.getName()).append("= to list all available options."); + msg.append(". Use --expert-options-all to list all available options."); return OptionParseResult.error(msg.toString()); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index 62fa12334605..e6b41c5127fe 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -124,6 +124,9 @@ public void run() { throw UserError.abort("Unknown options: %s", String.join(" ", remainingArguments)); } exitStatus = new NativeImageGeneratorRunner().build(imageClassLoader); + } catch (UserException e) { + reportUserError(e.getMessage()); + exitStatus = 1; } catch (InterruptImageBuilding e) { if (e.getReason().isPresent()) { if (!e.getReason().get().isEmpty()) { From 62dd4db0b34cbef8f1378959f766f9f7c80ad7e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Fri, 17 Sep 2021 15:42:37 +0200 Subject: [PATCH 148/681] Require mx version with fix for META-INF/services in stripped jars --- substratevm/mx.substratevm/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 341eeaefee3e..d293d7acf91c 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1,6 +1,6 @@ # pylint: disable=line-too-long suite = { - "mxversion": "5.308.1", + "mxversion": "5.310.0", "name": "substratevm", "version" : "22.0.0", "release" : False, From ac5c420b430883fecaa7970f45330a348e920a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Fri, 17 Sep 2021 17:28:09 +0200 Subject: [PATCH 149/681] Revert to more general error message for image-runtime compatibility --- .../src/com/oracle/svm/core/option/SubstrateOptionsParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java index 0a7c8961ad3b..f049bd43c7e9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java @@ -224,7 +224,7 @@ static OptionParseResult parseOption(EconomicMap optio msg.append(' ').append(match.getName()); } } - msg.append(". Use --expert-options-all to list all available options."); + msg.append(". Use ").append(optionPrefix).append(SubstrateOptions.PrintFlags.getName()).append("= to list all available options."); return OptionParseResult.error(msg.toString()); } From 1760897a441a7b4fcac1b5cd8a02ffbb6693acb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Tue, 21 Sep 2021 13:12:56 +0200 Subject: [PATCH 150/681] Fix moduleinfo to build com.oracle.svm.test.jdk11.jfr.JFRTests with mx native-unittest --builder-on-modulepath --- substratevm/mx.substratevm/suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index d293d7acf91c..7ef121a698ca 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1100,6 +1100,7 @@ "com.oracle.svm.core.snippets", # Uses of com.oracle.svm.core.snippets.KnownIntrinsics "com.oracle.svm.core", # Uses of com.oracle.svm.core.TypeResult "com.oracle.svm.core.util", # Uses of com.oracle.svm.core.util.VMError + "com.oracle.svm.jfr", # Uses of com.oracle.svm.jfr.JfrEnabled "com.oracle.svm.hosted to java.base", "com.oracle.svm.hosted.agent to java.instrument", "com.oracle.svm.truffle.api to org.graalvm.truffle", From d9dc2df98180c2bc250ed26c131c8fb4ff2523d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 23 Sep 2021 15:47:06 +0200 Subject: [PATCH 151/681] Handle service loading related errors during HostedOptionParser#collectOptions --- .../com/oracle/svm/hosted/NativeImageGeneratorRunner.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index e6b41c5127fe..4c7f6f0e60cd 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -137,6 +137,9 @@ public void run() { /* InterruptImageBuilding without explicit reason is exit code 3 */ exitStatus = 3; } + } catch (Throwable err) { + reportFatalError(err); + exitStatus = 1; } finally { uninstallNativeImageClassLoader(); Thread.currentThread().setContextClassLoader(applicationClassLoader); @@ -497,7 +500,7 @@ public static String getJavaVersion() { * @param e error to be reported. */ protected static void reportFatalError(Throwable e) { - System.err.print("Fatal error:"); + System.err.print("Fatal error: "); e.printStackTrace(); } From c5748a3dd96f2ba454ab3adca7ac7e42bc75ea5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Mon, 27 Sep 2021 09:54:37 +0200 Subject: [PATCH 152/681] Add changelog entries --- substratevm/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/substratevm/CHANGELOG.md b/substratevm/CHANGELOG.md index ef9f442ed7fd..5a799f92a3d2 100644 --- a/substratevm/CHANGELOG.md +++ b/substratevm/CHANGELOG.md @@ -2,4 +2,8 @@ This changelog summarizes major changes to Native Image, developed under the codename **Substrate VM**. +## Version 22.0.0 +* (GR-33930) Decouple HostedOptionParser setup from classpath/modulepath scanning (use ServiceLoader for collecting options). +* (GR-33504) Implement --add-reads for native-image and fix --add-opens error handling. + ## Version 21.3.0
 From a923eb1c1f9a47ed4c6f59317622dfdd7b35a803 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 23 Sep 2021 16:05:45 +0200 Subject: [PATCH 153/681] compiler: insert artificial return node for snippets that do not have one --- .../replacements/SnippetTemplate.java | 79 ++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index ada40300aa07..c1d879df51af 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -98,8 +98,10 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.InliningLog; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; +import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopExitNode; @@ -109,6 +111,7 @@ import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode.Placeholder; import org.graalvm.compiler.nodes.PiNode.PlaceholderStamp; +import org.graalvm.compiler.nodes.ProfileData; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StateSplit; @@ -139,6 +142,8 @@ import org.graalvm.compiler.nodes.memory.MultiMemoryKill; import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; +import org.graalvm.compiler.nodes.spi.Canonicalizable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.spi.MemoryEdgeProxy; @@ -1057,10 +1062,34 @@ protected SnippetTemplate(OptionValues options, DebugContext debug, final Provid debug.dump(DebugContext.INFO_LEVEL, snippet, "SnippetTemplate after fixing memory anchoring"); List returnNodes = snippet.getNodes(ReturnNode.TYPE).snapshot(); if (returnNodes.isEmpty()) { - this.returnNode = null; + /* + * The snippet does not have a return node. That can cause issues for subsequent + * lowerings if the replacee gets killed, because killCFG might kill a MergeNode + * that is still referenced by the LoweringTool. To solve this, we create an + * artificial return node and insert it into a temporary branch right after the + * start node. That way, the next node of the replacee will be attached to the + * artificial branch and killing the replacee will not affect its successor. The + * branch will fold away after snippet instantiation during canonicalization, + * together with the original successor. + */ + this.returnNode = snippet.add(new ReturnNode(getDefaultReturnValue(snippet, replacee))); + // insert empty memory map + MemoryMapImpl mmap = new MemoryMapImpl(); + MemoryMapNode memoryMap = snippet.unique(new MemoryMapNode(mmap.getMap())); + returnNode.setMemoryMap(memoryMap); + // this is the condition that controls the lifetime of the branch + this.artificialReturnCondition = snippet.unique(new PlaceholderLogicNode()); + // insert the temporary branch + FixedWithNextNode insertAfter = snippet.start(); + FixedNode next = insertAfter.next(); + insertAfter.setNext(null); + IfNode branch = snippet.add(new IfNode(artificialReturnCondition, next, this.returnNode, ProfileData.BranchProbabilityData.unknown())); + insertAfter.setNext(branch); } else if (returnNodes.size() == 1) { + this.artificialReturnCondition = null; this.returnNode = returnNodes.get(0); } else { + this.artificialReturnCondition = null; AbstractMergeNode merge = snippet.add(new MergeNode()); List memMaps = new ArrayList<>(); for (ReturnNode retNode : returnNodes) { @@ -1125,6 +1154,19 @@ protected SnippetTemplate(OptionValues options, DebugContext debug, final Provid } } + /** + * Gets a default return value that is compatible with {@code replacee}. + */ + private static ValueNode getDefaultReturnValue(StructuredGraph snippet, Node replacee) { + if (replacee instanceof ValueNode) { + JavaKind javaKind = ((ValueNode) replacee).stamp(NodeView.DEFAULT).getStackKind(); + if (javaKind != JavaKind.Void) { + return ConstantNode.defaultForKind(javaKind, snippet); + } + } + return null; + } + private static boolean verifyIntrinsicsProcessed(StructuredGraph snippetCopy) { if (IS_IN_NATIVE_IMAGE) { return true; @@ -1244,6 +1286,14 @@ private static boolean checkNonNull(ResolvedJavaMethod method, String parameterN */ private final ReturnNode returnNode; + /** + * The condition that keeps an artificial return node alive or {@code null} if no such return + * node has been added. During {@link SnippetTemplate#instantiate}, + * {@link PlaceholderLogicNode#markForDeletion()} will be called which cause the branch with the + * artificial return to fold away. + */ + private final PlaceholderLogicNode artificialReturnCondition; + /** * The node that will be replaced with the exception handler of the replacee node, or null if * the snippet does not have an exception handler path. @@ -1718,6 +1768,10 @@ public UnmodifiableEconomicMap instantiate(MetaAccessProvider metaAc } } + if (artificialReturnCondition != null) { + ((PlaceholderLogicNode) duplicates.get(artificialReturnCondition)).markForDeletion(); + } + if (fallbackInvoke != null) { GraalError.guarantee(replacee instanceof MacroStateSplitWithExceptionNode, "%s can only be used in snippets replacing %s", FallbackInvokeWithExceptionNode.class.getSimpleName(), MacroStateSplitWithExceptionNode.class.getSimpleName()); @@ -2187,3 +2241,26 @@ public void simplify(SimplifierTool tool) { graph().removeSplit(this, next()); } } + +@NodeInfo(size = NodeSize.SIZE_0, cycles = NodeCycles.CYCLES_0, cyclesRationale = "This node is immediately removed on next simplification pass") +final class PlaceholderLogicNode extends LogicNode implements Canonicalizable { + static final NodeClass TYPE = NodeClass.create(PlaceholderLogicNode.class); + private boolean delete; + + protected PlaceholderLogicNode() { + super(TYPE); + delete = false; + } + + public void markForDeletion() { + delete = true; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (delete) { + return LogicConstantNode.tautology(); + } + return this; + } +} From 71008c5b1b32063fed4f836db882cb0cf27df6b7 Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Thu, 23 Sep 2021 17:26:17 +0200 Subject: [PATCH 154/681] Fix substitution of macro options that contain a path on Windows --- .../src/com/oracle/svm/driver/NativeImage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java index 23b737a9f4b6..1373baa0d0c9 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java @@ -1873,7 +1873,7 @@ static String resolvePropertyValue(String val, String optionArg, Path componentD * substitutions of kind ${} -> on resultVal. */ for (String argNameValue : optionArg.split(",")) { - String[] splitted = argNameValue.split(":"); + String[] splitted = argNameValue.split(":", 2); if (splitted.length == 2) { String argName = splitted[0]; String argValue = splitted[1]; From cb671ab1621b165a15d258f6dada4509fbb1afc6 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Mon, 27 Sep 2021 11:14:45 +0200 Subject: [PATCH 155/681] The arrays in array-based SOM are final non-null --- .../api/staticobject/ArrayBasedStaticShape.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java b/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java index 08ac9c352156..3c6cde4010af 100644 --- a/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java +++ b/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java @@ -40,17 +40,17 @@ */ package com.oracle.truffle.api.staticobject; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import static com.oracle.truffle.api.staticobject.StaticPropertyKind.N_PRIMITIVES; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import sun.misc.Unsafe; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import static com.oracle.truffle.api.staticobject.StaticPropertyKind.N_PRIMITIVES; +import sun.misc.Unsafe; final class ArrayBasedStaticShape extends StaticShape { @CompilationFinal(dimensions = 1) // @@ -94,7 +94,13 @@ Object getStorage(Object obj, boolean primitive) { } else { assert checkShape(receiverObject); } - return UNSAFE.getObject(receiverObject, (long) (primitive ? propertyLayout.generator.getByteArrayOffset() : propertyLayout.generator.getObjectArrayOffset())); + if (primitive) { + Object storage = UNSAFE.getObject(receiverObject, (long) propertyLayout.generator.getByteArrayOffset()); + return SomAccessor.RUNTIME.unsafeCast(storage, byte[].class, true, true, true); + } else { + Object storage = UNSAFE.getObject(receiverObject, (long) propertyLayout.generator.getObjectArrayOffset()); + return SomAccessor.RUNTIME.unsafeCast(storage, Object[].class, true, true, true); + } } private boolean checkShape(Object receiverObject) { From 296a36182ec2a34ba4e168541df971fe94f0755f Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Mon, 27 Sep 2021 10:54:00 +0100 Subject: [PATCH 156/681] Fix size of docs flamegraph screenshot. --- docs/tools/img/profiler_flamegraph.png | Bin 15652 -> 10072 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/tools/img/profiler_flamegraph.png b/docs/tools/img/profiler_flamegraph.png index 86a0deb01d5c1c06d65c443b54afbb57b5a1f70e..4d849d45ff4453a7355c6776210105640312b7a5 100644 GIT binary patch literal 10072 zcmaKSbwE^KxArIkBA^1&B`vKWDKPwC=u+u!kj|k?a%jn+ySqD-?(XjHZtlVNe(!tl z{p0&%&Y82$%sTt*RnK0}_Wvp^g8qu&6$k`E7ZZhi2Z5gR0N?jsJ_nAEeY?HD3B^)W z*#-nc#d`WY1H~oa0YYS3F)1PBbreDrHY{3Hx>ykCJxC1lkDSBI{=BoA9CQKsh?%uD zp;dq5!$(%D_*X<|(9ftNQi`l963T^2>R9^%GklTt^wR`FR7OIfl_yJlv3pr>VkwJo zS)}MVSkN1OMx!s_z14lIk0d;ZhG4UCbN7=2t@eY`#^ybDu|_MG;Xr~LxZ}+tYx5}~ zY5BAyFeZ-Y7;(VqtqO2>$p`}R|9A!rtKz>!9z(!8UFnCvbsPp>*Fzi?kVoNwKq(_n zav#5FT-4}zYcBOFYQuq;oT1~|N{)r@x=}6{u;C@-y_V`cmx-XxjM}9NUOUuz^U!L$B1NUh71~i#LQ&wAq z6jaej_Ue(vpegDrTYj8;dD#&(SbcFpCRF~r6shd)-OC#zCBZ3_auu=|6nV4}edk`JcCB4!@R%kPPXN;iUyuscg*D#h?xh`?&|T`ytE(QV zBpok|QJL5iF$@rWmoK@}p>6M)F^&U{=YC(Ci$-n`iIM|sENgmIK@iR!(=D?VpA!R7c`{Vk0x6KpR0=86@s3DbTveSBB%3uVa_HQ=xSMnBLVS+d7p80}hYx(dD{zLgat-!% zW-}R@OaU>RBnv8Td-MqHMhIk1J=dmly-!0m!%jK;TwtGBb9q85NDxS3xVPPB6CF_x=) zbUlBVl5b|9d%!DCe(QtmPA%o=oK(H>5l;j=>4BO2v*+mBTTrF*w`^vUP&Sm=+_z!bxLca7r42hqHA8wjHx0Oqsiawj+l9x zq0%Ef%j1pLqjHcspV`0wXQH6EZHod)f751bOC8UKl&!!XIVrSW_`8ELlWeKIBi`KG z#avmA;DrXZFG*ClS+R)qMMrcz7^Mt#7;fx&-W*k~kMOcIclVgvnGAu}=tOsITkM9g z?*3fzg^ZA(3aml+9sOjE+=K$kMg3qi7%y6>FuJ$*qw&aR2;^OC44&9s>M8O@BoWjR zOQhPjArRl)F-3H#zoB*e*g}G=IFy+X??YpWO!Kb?0h7S}py@w|$ZAdF!^6MTLbc2; zZfqVfEp7vUoki4lZ}o7*sb4@m=+%a5t~6IFHkl?WAMc0Z3QA+6e)&v`w$rP2esx#2 zOag@&ID#%JlB`BY%Z%4iY^((T3 zjwmUW1WGxOqv*a^Hne%qy!o4|xmCO}U@Y#L%XLxUsux2;VpKW20iDS;y}g~5zUrWE zXPI#2>A*qkrFe|g$h%6#kgu_j!#Dutgup{Y-Z;-x=ijrCi27F99l=@ z+1m;BIFGssV4A1Ha7<*6pBK{6)U=u{vA5q<4tyUD<7N6|ZUVhUdQpO@7${{~?~Rkq z$-lvjAx61B3F8f!Q24V>5hmUsV3NOtBbK34-PnF`2E!L7Z*g$i+S0rZUk|haPZx5` z1f3%_hWQhd;5)d%{k#@@uJevGV-qNus=%CioRp~Wm3sYN`=>B zzO3OT&(zvGF3Y0V%od8?G*K*d9a!@g2N2@Yn+`Hg8RmfN3{SHW>G|jsdCNb4;quL# zS!tN_ET-#YVlq8SG(LsX^G%(cf1>Et6aQ^;; zoS8npF76xUW-?{R^~YAIEH$b4V&ITx{7b%3PfbSoyD>=rEOy*x*$C3t{eWX#4V8#r z$$jdp-vq~YURH`TDT?GrqJ{C0v9W$i%JhZG3Nz5gHL-jrE>vI<5BO>#Fw939E{*P17WJns7dg&nwSH}5+@WORFVQRhjbtF! z^|(NRTD?zRcl*X?9XUW^SJ<$ySA6NJ40~Vt>Ta0+bVITq0~0e!c%CeMqZWJmjcx`R zu*|6W$I-vRW&7gQ_)+9?D}G^v5-SzGeuK23(rJr9zjJa{`;iYT4Fh9hq(-dfmzzd( zTJff`fFGA50^4Va%)!)x`iwT+v)*ET2|{a`k?`=rV$&g4*~seH@5wS+ji$3s<2JEy z1vyh&ospyV^`448W#c?`KHB8o8**6*xr>_^+!GPAc($DtWie(~2|5v}Zb>($Ldy#n z8*&*Y`9#CWfj1o8$Qgy2dYKQJL`Jo%&xju_6IWH^a98$1^6W)U1<0I7!0h-Izp`!A z12I3Dr2jiUM(f*QP~k>zf_UK9Be&Ng!qjmT|KM}XU0q?ZniytgNfSu*eK-%{iqMdj zN{mXFx|YBTwBew~bt(C0yfLAKlxbWjA%2A1prq`Cu+cU8q(#~2ivv<;xBrX!#=3@k z6nopVE>6Z%|Dq5~q?E&Fsfd=X+G8k#`kCt6nny5yqd_Vg$Qcm^Mq`6nr-;&P zSK10NnfhQR3AO5;MvW&Bx5JljjTm`IDk_}7rxzD*_=Lh*h8slVioG~3kw8`7`19~0 zwxrZ*hFiT5-X#&`7c{f1av@$WAX|?N=2{LhATS$J9QjpaY0Dd}x$7y8>Q?D6zftHU zA=v86X2lvVB7%u=j4V#iDC{Pp+%o1c?h#pS(C4_`P3tpkeBQNfBr9J@$g;5yTV>!r z*tRXq)as!ZTK5t)6c;7#g*w$1YZ<-Hk0n~1{%xZxcC4+-D67Qj;xwX8tIVp=)vc5h zMF@?KEWkH@;9qVpud}=`%dX32vC1gT7%-obT{zOZ#UhbtcSdtj|7I1XAlT-v`0LcI z^teR2{=La(z9ArrNz1Px_7~-DwRPvW7L9gO55ms@84UT2 ziVwHS^R+xvZ1CJB{Xtw&1`ucqRl~0l`Z)PoP~Ki3f7b-Ygk{hVx@tcm;nb9*&(ls>f(6EID*x=$hU$547Wi*g!naat*>P(`&ykl3H`BBD(Cgxuk$Ge0|Y86 z*c|0VJWFO($kZY#L&r{zC)b&$(Ev|dj8o7d4u|bfV@jghbCbrhA3gK+uFG{fWl}fR0bNhX(=QU%bq|rogq9_|rZ!uve}&#ndQB#-(Do`-8G5eFJSC zBS7`?87M_+Qkzm*=FwzwJt|j&v!S?Px1aMMX77rm(ewAl0udPxKJPA z3hC1B`0ft-XD7kPGS$p2R**;hJ66jYi!HOn!&P1O-Flv1_m*7E4~+|4w0#^1AP{kw zl+(;((Wk^i3IWzd;!a^c@R01ME7i~pd!;QU_ z->j~__QSNZ$`X%>1P4(TWh+O|d zm&+N4q&x5uV9m^NGG&Ly>`r90vKGOnzTXq&syhM?1V3xh0cV+{D>Olm`iQN|tDRq~ z7yNZpF0XFg{b8xvRd=-goXHk2o?3nqx??eTcw|b4x!6i&*OWW3{KPxa*XMz;`_LlpxR963<`nS}6a*UelND--XNwq#oA}-Q~n( zBu%Eh9ePH$&Du7=$Xl{Zr$%m@z5|!rvuP0SLTxgN9hIJxMDUdhHdHAYEHtt@ftA;JtIH$XiXXHG01=XR&WJ znwEvcsh6D>ibAfuMs>@Ywxq3n%B9J|NqtbQa`=*f?YE3EyqU#c*I{%oSbBdHgEa@b zofnZQ74Y-VmIMeSr!r4Y;v~|1VFD4PxG%Wf4}Ql_8Sd}T+5FQtOBW4`nvDDvs!oCY zg)qFPoBFjjOq5)APN6<~zjpJ2=CU-eBQ#W8fWdRg_>nCvsJM@c69#J|E6Bze-G2_6 zJBymAbk79@!!yQiPv$RLdxz)Ov>LZ%Ru0pgiiUgdz4uHbXZ z;@69nJc9JMX=o_5w#-6H{He7ILfV*l9H?Ze|B$uu*!mrgxMqLw(7S|4FVB$5TYjO` z@rA)Y3IHDMw9U$>xVzzsF8Q@NRU5K410DK7)%hvOdEMSkAmTcvf17hyZ4lA7^nPP; zw&4t%?e@}=balP>j>)6z!RwELc}XNz*xFu^Y}h03l$F)vklW=!fxEecjhcsqacML= zqBkDV>%hW>ZgAh6+99SmddO_d2C1pJh-<$5wx2N?XvtthmmO|jR?EJ-om^m|UYEyb zDtC1EJ7R#kev_~wdA+l^`T{gxNzj!Pod(Taz8|#(q#C1Y>tg#ri*PC z%haiDg92$y4Stj7PkHs4yIuN{ZC=fEwrY6P;guAi#-$@);i1cbX1v*hX;mxk+2?fgK_SO4>Z`88&V zSDC9F6Rw6-?n!TxC{Oq1?QiI5TR&HRUck9o98OyWvl|@XGT)_t*HC|)GdDE#F0Rb2 zl*YMxxN;L^0V3L%oZKS2w{|{_{CRp?Uj)i>{^Q#VehK>dth>YGFbluwKx+Z1mS4kh+43qFRxTIF-LA z*-xNx1rI=k!@K4kcKY&+OVg&wYVM07Ltgp5aG?RHi8I&C@m$}m&3xD72G*_a53~l_ zKrwI1uW-^mOKIJI8+eqc1Og3B)_r-KJ}_lHvVT>zfZsmVWMPHks}M1EYZfs(HsW-r zaBWf8G2PC1c~zgOFk5YS-xAD7?RQG=^*&o6qP4d84>pz2eN%fo9%3qKYs&aD&{7^? z*~~;!_DpavJKz($!lgCLO)`KXmg;un;{$=5S~S8Yxk{-p=Xrqu+)wWv+SciE{(a>q zMAii`FIzTgzf_-hfL)|Ga0Bn|DYeBzoAC;tEK8_z?xRt;7nN}m7 zbE&->p)-l=A|xq|?GJ{j)=AqxwdEDf9P-TL)vomZoGMt?Gi$0MQ|PCY_chtru0T@Z z9hx7~5%3B}hBb{QE*Mxp*qWT@8te@A_`_V%ZvsOSjBEAM7ZXzf+{mORWIH*I$Fajp zu^QESKlA`N1HybWPZwIV$!|-;-K0Zf4aQSKEK+uj;nDc&xvaQRNA7qvEIxZ{&LVUm z`a~KM{S;)bZh{+V3^K~0BFgvdVr!!0U}u5xI&Xtm4d-x>vuNZtJDF( z`iQOD!3vH$YnEJ2FF>H1nh|4Mb=|{YO7gNxMHf|8_jr?ot1U&7GmCfA>D^9Bsg6<< zS*#Gd-i}1@foT=V>+uG=`k2(CG11SQ04Asw-(^XyE{b(FnQes~3wCH!MMXVo_Z50Q zz08q~!V{MV7RekJ(R{wmS74E6Qf11c(^}XD0KP;zMytp7m-se=Z|F&E2Zs_bQyhW3 zK(jmy-io7RYH;C8stW~G3E`1x1DVcyDcf4f({QuZNCw$)qVB+Zj z#|7%s|KtY$%J?$@wEchh!vDzrvW?9zYj|FQK)?bS1p4{}KK`xiU$Q5j@jtSE=}LXl z`ou|kKiz!7iJ&LZ6LI+;k(-oDp8=~1pz*KTzhvgquZ|>ql@|c%zZL&)uG6yo4?h|} zfc_mh@C=XmXjoSuVy{%$5mi3R2IT_AJEz&0Y!>ULA}Z#vYU|zj)2yJ^=&y*`x7&S8 zdK^zMAFmU%1!)*3)7wk5t}_{PDwe2Qg57u|TIFy^K2kUQiej(Xhl8m%r_kW=BIW4szx+`a&eWrhj`@WDg8uztkQa|7fL&%-z)MkZd@i}jE zgIVGuHj@+Y<}P;`53h}st+<`=bHn1fn~Su$*0%2bhHqcN2}x|upC@r-k)sEl>qWnQ zzz=XI@XlxfiB)2wK`De~RuMY@j8$y8A6wNG8F(F{U+dvr|2KSTh7N6ewtefVM08LQGv25yq5 zlxqe8A?-fx1;Fa)?EHEcj%YX0o5h1WYRCWI#GTHphG$^V_xv@;Nk&H4=_@I5Xhi_U zN(YT`EP48{v<43EtCx%(npT;aVooL!8%u$^;w-*W3qw{v+WSR=XD@oZ(gO~XKlADf zi?3)E&A*1|4ecV1cw25Riks?Hgja1DtBTR z80c1ZuGB~&!}XIGj$$%kK?_^Leyd{13Pg;Dbg5VJ{P&al4a8CTamR8}V%AN(puo!_aOiZanYh`R5zx+); zURi#UMzfQ!Br+S;aUHKyfOM!KcU}&+yQBjuf&l80VzNBAap_{T*Ghw&d3#|n$JI{1 z%o7F+W7&C2<>(()rpGZs;QtOX;vKn2Z)na`AnC^L3zHNwX)5i^q-uBY&w~$YD5Z+2 z{vsNVHuN0UQmo`{I$MW*^Z967Q_+`%H+WPhD10JpXQ@i1eoXnyoB*IbYJVWsh#lz@ z;%u5T%)5_lRpG_ovmIAkLn>9_%nz1^xlKPe%{(dB20o5%%!R%RY%Z>x7Io>}H&z_} za=7NItfF>x=xKdjKF!RRqa!+!oVyrXedg6d%w50nuy|)+>RHF)etgohLhM7&w}6$< zU^b?{{{uc&Sm!B1||S+LBfq zAa$s}4loRh&?=oez{jgj7@IRXN@75+ZCa&0TP0jX-MH zXlspEW{y0JZ2LPwj&L04(j;|HhT*2aWR&> z!{{?LD$;W0PzBHyp}=|^2QGF3Wo81|PmWh=EwZt>x??rPua*b|@-Yj6)X(ukjpPN$ zgAfTx2e|rMN1h7Azqhe~8ebrM0t(pVcOw+P3)O1(9dl!TiN75R+3elcl){EE#XU`e%M3ZyXv9iRlXe$;T;hzC7%#TQOQUBS1m}7y?cd%sbyNcpS^*_ zPrA9Dyl?gX^>vl>L8D_@R_F;7nmWM4KL$0ueFH4k zxGK~_y!?WNFmv12ti7GP+DQLrt8GR$WOnt=9|m)M9~T0jE?`d%?NRAoMuV5Pv?KT* zpuH(^vta!OasoPdH?a~(%;kp zlkY^JGEdC=!`MoKDm-vd*0QvU^_BtGE&4TT6bbKuW>?|Sd+@H&gM$dOBndo&A^_kv(JQGJKKJTx_yx-pV1xm|fWNhqdYQhuoVN%GUNt3@l2o z@zq)6Q`i}P%gdi0{9&z^RyE;uyM$cUw>zBd-*0$j7qXEw*L(5QL$gSU4kD0rhhyDr zL=YFrF;LOZ=|d_pX$Z+%O@Xan{E&AJi{8>zH-DFP=1MUW64}EIYpZcbA{C*_5l<}+ z7I_0{8r9-MhQk_q0I}2^p~hgeTJP))43@f)I+M`%z%2iT zME^op?_&ahzyEIp^cOm9QQ^S=6!aH&J^l2r@GlfP!vsS0UvTdK>;-c|`Ts}OzcAGk v9{c<7Cp_k%;rSET^!6X^|3+&=5)Y)u@-zI$ul=FG<3M6U(vTtnEzkb~RHaEy literal 15652 zcmch;cU03$@F>o`dO<{bldeHTq)C^K(xj{Ou5<_;LN6*xFCtBP?pY@i(?+$*my|`@wg7rt5-(LqLA<_ZLo5%57{Vo~we2EZ#CcKH)!%pk-|)9Gp8i z3NlYLJf=72ymd5ItB?0O`o1zQ@!sSme{mm*Yiec^PGWcO{(6qWwefrW_v38HX_KXG zymGvptrW7ybE*U*Ixyeyt*e%vvS=$;eVT|jxMlQh7MI+-=^me)8HsD%58K zB&j)sD72WE1mBJyvQY@W9EC2itap1ZEggWR>lcvV5Z=8iUk^6myDZ;%zLfOWW%(@t za_h2qgQDKzvM81DL*UwF`R`ovJ@S998txPTaWBi)L;r*EaOkoY=Xz+v1sa3vHtbrQ z>7t;ekNP)L&^s&QN193&Dzsu|S|LHH*Ku&9T4fC{C_)i*H8ib;hNW|Z9>mLp%^w%k zPMCMkweX@_$BR}KALcSiz~uBsnbLHRloKC{rC{mGI3FRsIG987_^}e$?OBI75pt?B z&%2ubwqxr1F(>U8Bp$0}2VHzoLek$;3oX$8OCyY@8~NH(&6^jC=Tc?#?jFoj^~%X| zsPx{<93GySo?UvuqQOMJv~vgwCS#f)|`+MsLami4(cVfrt)t*}fwU{YARAv1K`+(s)_Ca0yj+ieLm6oPZG%>fYe%>q% zWX(}Hl~HwjZn2PUVQPP5hw&#mSCl&Zm z$J!sZ*%H-S4xwER+=`AA+`gS$fQ3>WR6uQFz|RvMs3I!q=V!5aP`M(e?z^A1XglSv*9hv8@68*F7c+YP?Fh?JKYcWp zmz(11c0**t7!9j7)rjvGoe!M9hnzP4h3@iyS2dk65UEPq8ay~Nxk*`?SIPW|n|KYlDKA`Q5eIXxOl^f7*-Mo`5i#zLwNqXS$U&>D;uR0*DdLA}QEWjbU6T?7_~>R47AT|WTX#14_{RoB*@@XrU}5@sy&8B3a`|;VsCCBKV#8xA|umgLilSNFh zOkU3YB@R$y2lq=|gN4w+CN`rpfQgFgBMMs%@R9x^dv6czVr3^yJ2zmZ9T=YG{*VEq z0fc1sb1jeHcR-!zM>NU1Bmofs_zW3E*@3<|xk z*DQAicp_3tZ|8vQPGlzY$@;FBjlX}|!405|I95Aa#47QxEX$M98K4!l@X+%^r`BN0 zxmnTG;?`+B*C>VdmgCfsFMN!O-YB1iVw1#^$)51K(XOuCX+W3~tZ0Cq0gQ}Iu-(_& zQ3%<=#MUlE`|r=TQKjc=mXx{N zlG?j#Rb-H9LP_;aO~%@nA6H4DX6S|b*yY8R2Px_z%jbz>T&YU6wIqtCLRj2WfB@CE~kMjpP7o~Ioj{b_vwV&uL{bd!jXm{^#{`sdFF z)d;KJ`8K=2wQ|0w8c?lm{`A-a)2j^h#bx@pS^0feWKql5U}POmVpy)~K5@gJ8B4%prq0I!kJ%*)C`rM++Zuxhhrp4Si?hX;kJ|IXXwR9w z!xZ^q4#}P$b*!A|G*|tU4L8u~owCp2p_@>hc}mi#=As}f#_dlFDqb_q))q$uSe(Xj z#5WHl9xv03TM33t@lLDPuP?C|($O`01z=*kX4RQ;$jKu#;ev)b4Z6vx%^5S-Qn#R5 z;MzH+oMD>)kcjLm(B5YK#t3fE255^@g%etHB$&ST^xfFX%7mM7@&*AdNggo~{zQtG zM*d!HZIy>_79r6DZbbdo)!d zYs*%2y2$PN`cqfG>T1ocp|z(~4A5-ok!oqy8vm0sLac#daC3H9jhj=axqIH;iOErT zwr3LGX}*hCvjo)}`UzP~92Xv~YSrJ*nuzN7%4s8Zww!6PXZKd1k8P`2Y zs9(Da%;EC$*$h%!6+<95A`nJhdc4{gH-kJ`Fi8a(8&q=pj37+)1u3Y|qvkC<9kk=>){a=?mrxYTJ~)SO z^Tk*zJ$m-fG)y5bO_lfH@%3e%`VjHSuIZ)F4~zNQ=JuSPAN4G-eGOb)o1C!*Db5=C zDSaF*x_S`8;2J|tJ z`k+#yrt;k-eZ0mx_M4S?k;XbtK3;5`!#@K2J_;0AoV$eD`g=Vi@_sLhl+`LXfW>op zhaL6SPJe+LtTD&t69{%f0(%`Hm)@Rs|GvSg5+V6ems(cOZ!t94ik2!y*aiTy#QNxj ziMw%o$uq4LCJA((m~QMS(|jbi4`ULy1zr!t(H2PRZ|l1+o#R>6T|gaDWsVUMP~ffx z&kC$}k0kns@I?vIA>?Q*YEsge-L~C=O-Qn*dIm0#cJ10rVLyk=ex$9pgE~TH(CbG{ zv!_b^E@aLAU=>b1Dx{6-H~VZ|P+e>FZg=D2oWp=|)6^@ilwTyPV-Z-EwUJGO?V#JE@UZkdV9Ht)rC#4*L%xw5RbBmwz6 z9%`kywHdZ1RcTQVq(rR=pAs@%e^WsUfkYa}JPICX3vx1JP^4|y>0 zgSR()He7$}2whCoWbJ8Vr`42iHc{Fuq&ir}<$Qm&HU9OX#tzj~Qx)C(vg?Q9 zqLWQ2A)})f9Gr~;usq9AEaUC=%U?QWqa?nB!Si-4hO7D+)j*+rcW8f)%ZPlCH*fT>3{gP;@)_f-O z2$;IowlL3g{gx@ahWngAUF?-T*PPvCuwYl2z}cip-zeV9xkL)Coft*JjS{Wq9Na^L zpCR(?;n#~Xe>>EP+RInpyGLZ|eL*Gnko1NBjDFMAVv(9%QF9ch8B#eCvnV4Y#$;P! z@9GULE$@HE8_{#zUs4~{*HUa2J9So?sLQ83pzXZU8e?TuMYlaz;}yEo!(B?x>Q>8n zfGf>S{1wX3(R*G{tE{HDv1~NEY%V&hnww+xy{`($>ukyS`{;tb!7tikA#$EdU!s9--_A^%M%^$3R*g@7z51F^0o8%wyCjRpH zeIH8)g+4a{@0jzVFV63c0};4+Q#}8)Z2{ESeEnjR zus9JzA%m&V1}G~$m>OHN8xBIwbuLYO;YwV9l<{G_a^5eu{^IAI=VO1u z6b;Ke2)OlsqZ7Y~`aSCTpCHGvNc4XK7>u+R?O1qYzxPWaU6jAJl7jj#3Rrm4l2LZy zDPMqN+Pl~_@^k^z8k9BW4-!}Ab`KTDzHva-usmE|dB=DE!{N~G_$H8p(+1WWq;s)C zEPR!HMqLtKKfT+m3wQzmklkB2-|)7gpVO1ey28(;*Ww0}mxT}1PQxWAqE&b9?zFTb z{5t;`7l1I`8T*X~$Iwc|Bg-PH`$Ys+|x>cn6)MIcuco?cC>0kfW z7rWsX@Wvqty5HIGHGX@xX7~ja8I|)77pt7*TGOXvfekQwyXOE(Yg_z^NPS1$10@Il zlZvccR3O-!Of?q5$X%mE8qSf&Mtbgo!CNz?eqEE{KoI@SA$B6_n>xeW@)ol$kF_KCr{u=tzpknvA?h~GiT8G_=9x2 zIdo^nal$9uV2|_aE>=!Zuf*8E$^34yZ<=xIPmX5i6izwh^3Z%MW486#tkWuP?N-|4 z(gVZA$$2D^CGhw1a57*+|4fj#xm%sTrPh0jD^y(rk_iTz>l?21^U#t;mp>5-s&1~T zu#;K9AtfD#i7A?$e;d?5l!l@yNAfx!gnBt={`Oh4U&t2H87w}V(r5t-I3`JVSuD%qc zhLgviCy>bW2dYFglK0G3jRw124>E$IBhsSu8|sOx%dB_qwCSWi0E`TGUj&#g;H!|b zgQuyT+mZBYqY*r4$6b(-iWGl*^K>`tJGXv|mA!kzc<(~^sQg-w(2n=(D9f2A4*ELB zAm;DBjY#pmy?GV9SKS^$;Ua|{z5gs1lt(BN|$WSy4ZtnbCy3KOc`)y!c{njbcj|JJV zwber%Xml`kn{ejBKfM6hgG?c#srh1wJy7niMXl$0G3=g+O4IQ7nd z5rHLm&&}vf-upceXRV7Xr%adHSN9a-Yy7RF4Hvzi*8M9+chSM;nspmD{IPRMP@o(W zLUTf(aV|*E0h6Iu-v@j|W_5|9?g7ZAN+mD)C_XcSwldh&iW$ND(o2%1AoI06lQyj0 zvPlvFHAI6R5yUW}w_+hlOHV&LnsTs~`2ywTG(B$fSt9($g|@@OSC-r+ zFH6nw0eo^YucRReBW=<2#DvddWiU(L?;bdgg)}(@+X2Q$yib@Hb`I2}#sY%AoI6_? zizZ(p!9l-pz&D%wrzBsnX1i$XWAMk|iJH8hA4%Ju0wN>4-N#SyhzTO%Y79?jl6=Ur zMjwt0FU15uFdX$p#GN9J2HOCEK}19r+LsglTo^|B^|R&+Y!&t!jk~t9rY7A`?k5fiC} z+~2>%I<#~6S#84Lt4RR4GAwLZCW@{BRdFoeiCf=db>eeAugP@G)e1VCHtsNFnngva z1yrtf=H3nv5m%wx;D^9OH;DNHB_7EYx67c71w$+@vDQtl{VgJ@Bg&yXIyL2a_|g4* zcwoAETpben-YSsZ+95Q&M>(Q^W1pTzc=P=J^{}D*f7RjYxODbvqC{)(cEhQ>IM2Kc z>&k$y{B-2AkF8}DSx`s1>b@)5TTfaS7-=mD7;_A$=4UFi5kq^Vh*xMZX1(#X-l3K8 zL8XHLBN;vwKG{a{6_*2C@9yA=RaMTTQ3K3rfs}O98teId5G6 z#taL|e9)fIgyTZJ>svS`&-a4x{K{^ffIt8I$v{ZVA?7^l-*G;j#d3H>4ERtB;&T_B z#LN}dlW1y1j*mYcD(qA9OeU7sVt;KZS#OIlbvSQG$9g7?Bsz1nQx3>|KD4KZPRdoMLg7t99wWi31bkmGFg|t%hM4A4Gcvb1jCTAZt8&Hu zQihH`Pv0#+g%WxkR@%u!z2_j$y-m#CJX4fuJW#^VO1GzKe4rmZVSsDSra)9x1xhI5eR1}Z;;4l^x9`#&8yUWM@SVaIYeup5G5dQcle&Qa3X_gU@Fp*e=sFkwL zjAYTYLo;ycHnQ-b-&De_Is1KJT{4{0NvUkt;cRua^)ZQaOs1)J05`yXNJUXUx7a*^ zYag5QBAl%G8B6IX;MeFG;@uks;S}QzuKvvju zk))D5Oqso2zZTxQM|{q!a)E zH1U&Mu|t5Am({Tz#I{&73)hH}9nhk})R>%Om(aEQ!~N+vD$tN~%Pw7r>CyYH4Lk`S z!-IYQ2_LeFieB=QAMW2}n$qj^9vVi(0kTBD6yD!8-ykx77w{ zfrgl~x08)>{Wst<(=8LNEu$&Nsh@cOBhE{!{s`ssy=9^GVByQ5he|6cmfj++7<7`a zZ`zdO(vAdr*VI^qg@Zp{=IYVTARILUKKYz?O{Gz9S^_r3Z~juo)>!osQBr2HuZc9U zWW*`soByag7oBv|C2M9d!Fkf@$A-#tXRZkhicK3CD=l44i31>`x1-%RjzYLrburQg z7S_VE!v6?kMi?(`9uzwBKFubrdW%6(-Md_#CHQivW60?BTHuVR*Lvo#si8|RYCJWF zi0sK_tJG>{04H1<$(z~LuoBro`yKDHVQu7vw#!{mKXpON_7Maw!Mt&Wk8Rku15Sg> zr5YdIPI+0$#nND8lO`*ZJqx`Ff5l$a*hfF zsQk-dG`2Sz&AqtEUB%Oc?`Tj1H|aB&|HELn!bfi1*s^=7_RnDH40K&=MC$q#+EjU3 zz1n7%yW;#JL=bX`-_zqrB|u|3lhO``#H}10Y^g~R(h1WLeJeZdsXzRO9B3`87u^VA z+Qf|O<4Gby>J0q9c%ORdxwP#-G^j=Nx*z}X)e57)7~uI~%r)>%0zNsH|5?&2YloAW z73p+F`%`qyKpzm#rw+O&lrGV^ItQlPx9a)YX(!4H-ANGnaIe`?Yf;(PvJZo=sdU!?DBXqP~5ELGEbi-E5BGw!`^#Hf^d|2ei>#+Hxcj z*1w7T(k?E7-d8Y!w1Ispa^rqn@q8<}6fvRsGYyngf6!3?96miL(U6~~i@VM&EAvjC zXv9a$;{O6fbPc{hPIOOJc#VU05qUrQ)}@)J{&3!H zL~hv$#kWi$18P>l0t3YXrX>h+x-!SRp?yjp73U?dFq+R3FVCqb%&}nS17kqE?@@yQfhe)o> zc&Ru101TramvUErBnsUh0rsEBA~U?~SXXcut9FE(l$I8KP_*dSc4DmHyS_58}{)vx)x(YNJ;rAmZF34YE6*RgoYKtpt(|^_iLruebir^rMpLj z9%_=3R^*7Cn1wFG&XP5o>Rqdo39nS1e*hyq3CIp*2USgJqglX54av(9r|EPj3n-ev zeeKnOxwHn1ySgA(YN~qjD?ZOnQNtA)ZmQgNB^OU4zsyl9!K%lz%&UVXoLn%V4k~oM zWrkBzmLNV*vL5mFp0Gj9@gPgl@ES-IA+)-pdKjBh9f^!N5n6($d)*gWpG@`Ga_CD! zz|MCeX#|Mo8B6%4hv?RvJtSQj`o;of7}M` zJHz{AW;u`}nINp*H?T?-t7dR8-G86-w4pz6DOzh3`hJt95SMgRvoqIQwq0NA^Wx{G zmNnb}esB_^lEr**DZN^?$#bc1(=|lWlhq5}ZZ?XWC?v_=f(@Y1beQ*B*KjJ`{Jv`U z5%;OAuh`a57}Y<3I>aEd_zmuDtCuqalRM!UT0lD~FAqt~0BejdJ4 zq)i_u+9A?+4*-}La{$e_wY`S1Tf{t(xi@PbX$4e$eOxK zwXv&OWM{nT9cR&a4l?*z9Vb%4^c#~BhY+iJ=dH^b&W)Oz=!URiK|`jq{9C9&TGAKj z{K16Em0mU`FQe62cYw(kXaY$4tdQBLb&5<&uc=uORJ2}&xYGB=;FfU#xa=PN(V<9( z3B!6RHsvEf%4;x%S+!PPCTD7%q8Oy(&Mu%`GX2~sGAyFv@m5@QKGAqQ1(PZ}3U(@1 z93LwX7HlMwllm_MUc-i0`s|54irH@(%`REd+!i&N{1F|!;mys>c6P`YG_yBsi=_+nCzc0DaixpKhaaE|4#FtY_b3E{Ihqow6wwhF5}-g@8AD-Gl`H&zPMyX zoa^uY)tUc8IsS*T|3@C%#bBxb_EtwePt}?*A(|fiYwp?u=lJtrp3)v*#KEm+Ne(GV)gLfBt(8qTz6N}@GU-!qeY=f|u zhWl@4jwI`K@eQM@_X?vp_&j=`ZY&mDy0JyndtqcTuT&m=X7={pF7<0vKDSFw%(&Pa z>d0RXe_g>ktAvh5O0vzSXJGLoR`0mQChDU}n1`2UT*8fu;|Dzb{i?%vzUPk?ztzx7 za9-}Z&OT5DksL^UuuwtG)yL*Ucgrhk#xAY)A#8<9_sgRly99oy5O91g+&pUX7IXtt zuXMAh{nf75Y|+Wl<}BVPLI7Z43Uhb{i~VoHntlONgKCAtzyLradv0ogT>X`>Mx~>) z+Ry1q7mn++bEHGH#NF7>vHhjv!1*RLj?KNR9yX<;$=d0}c0iQ_7Xm-@v^33C;(!^} zW!(`^6UTbCQvSb_1-VQ*m%`IiY$IQwzt46=(8zYk%6PA?u*f+tQXLbKioR zs??|5g2dtE`;<#@o|x`S4UOaJ>F>98)GIBTe^QX{#r6&A6k!Sq3SKSuEKnk8G&Ns@ z0|G;64qAXz33J;jeFmRW>Dd5AgKOcG9kT2Mq5C^pVU-6xvh7y-hmwNXfIW8(Zv@)+ zv}SomtT;gosP;Kk|8THW{~*r;YVfi=gb=&wQscqD)+ zPq0~As!g41p7|s5YSnI~OxD%DLTpB#(hN4oPZ2c49qyb~e-gAB-ru#4ouXhPON@7$ zJ0q(d7MnIB;h9ac(NvtPHrj(vX=1tJP)+11_VdQC|I<-pbr_kdANL@mBsy+8|Ng*$ z^4TeKt?EPc(H0+{g=NnD+XE>Tu=(d5CSp8gQFL~(LR+d}9ZFel)<(YKqKCKv&J!$$ zUd_+!P6&F#BzI{62Fh`UnE5Ko0ec)@lcgRFeKV(Z{qaQN4!HO-OLEghqxu5cGL_xL z-=;HMCJn8G$c4o@j4x}Pi?Z69q)V`q`_|K9i)R*D_F%U4%p>!N(MC_3m(DXg#@b6d~t<|TW26}2d}X&DWU!t_-_*KpbJpqvI6 zs}%m+mjQAstWSHgglpb-y5YAL9b`+D%L%9K<}gs(mnUn(KD_;;q^Dzge6~TY@%FX7dPg<5$1e^M^Y@)rtffD$3;21l zKrBd|kLVLexY&64`EF%CX^=K9TFj3;c@jJ3+k&i32N6Y#(HFt1<^)j|cK_Qu;W`EZ zr8du!VbqlFj6{Vv?`F2vGcV%F@e6KgFt5M__e0z8w00aqX1_>&7uj5SaC8+vMu{6T zDSnoANaJ<3`n*zE6XkdM0g3loB}}La=7hCiDPJHV4&*1c@NFU7j@DRysrFN_xCFul z@+CV!8%9++=IggQv&}Ti=Xmy}O`0|Q?1|Z`Je_2Bq3y%wyI!_By_7LQb0s8KAJrQtKvRIr^@{+Oo(9m$@Otc(l|m2Y!Zv&N_(!0AnJ@R|c7i#NMo zlHNO`0;{;1qs(Y8#M0BG;-EkQ-?5jhuWhe7?R*yPa!Ul56x2@!Zw`2ELZ?{dxx6RP1`4C?| z6^6JT3>6IJ1*A348QMC`4S(Z#&0}cnvw0yJ7jVce-a_|0IaR!NhEETwKZAJvynF}I zU*-;vVzhlJDM9a3+TrS=VfrnQTgfm&bhhP&dYyn^U#&NcoQVnQTHZZHRxP zb6uR_BI-H3^>(_0*hf~|!EYaY8VG%j{>$*{KMXP?`8ZK7YC#x7^A3j1D~k>rCz}Hc zOGOCCyD@6^x-(!tz52t06Q->ehHBR4bFX4{p47yT*WAZg|{`@l8m*tt*C;dhH>@jo?QeTPLP-s$g+H&>?%I~i#iks)lC3^Ut)#l!m(%6eWu*aKqJ61nqurs_vk0;L13C3Wr2o$N~KSR z0Bq-ov*$_W$UX{tFGCBEL4>}CN05dV`Bl$}T^+^SV?`KY!9%ZQdiA~uohYJkfVc-?|Os2ZH+bVUa=R|MipW1R>L|k$TolwYoiUd1j9e$XPGloQ8?{Kr8xITte(KM#AYQ*~S z^Yt?AUWr11D!Y<0cTd47_4^IIHe&Xta;uzzd^1-91iOKC6659=9ak{N;iPSdTDr1U zbodj8?sp2y>rC9qlU?xfGH>U4v5(2LceAFc&mn)efgzTJmRIj^8ODv+L-eJSOm3(! z)1J-REmLm-IITQrczwBzQvUe_n}^rT%>@{{P@0r`>k6d4pTU#7Epe5H-5v2(P7sf9 z;^jQq@+*>tVAzC5Tlmq}1T}Ma{)u!E-s4kAhDR&3|B=4D{A&R%E^6gYlOf>DJ?$8) zE5URv?(*wzDERrPI5WGR<*~)=n`3KQ@rbx9fu4i&KxXxtYev0wWTxS6RfP1JLdI(4 zS4=XuQ4u7komH>oJ(q8MU^kYqY95h(^yy$Jc!R^=dgA!>ps2MoOp8K75Ol`Ge$0M3 z?#8UwjFR$%UO}=yF6GX>9N^R-0NpVYOt7jcdw0(C~k;_vjY%d!YChLwh zkt^>~iu6vY?R)1=dRt5-JcX;h#>th0?v%`5yA1uwFC9x@9 zrFY|mTR)pJC0LiTA)xhsQ)U>G%f0()OC1lCKoskI>VLW5nDjEQJt!f}_|_tCWj@s^ z|GJ7_v?I^-7xjLN!Rw1JgMwl8+k}?;3lQEc@p0qe_qT1kI%Q>eRDbj}cX0@O7-iIH zvLERgTcj>RLq5IR^`v7|-uHXtKhpE*(0m=Y^_jHi6QhBRn&}>5dZ)@XWg=={53eJJ zfB1;7Tay*V+nH}R%|$Nk>XYYD1Sdb}(p4dkoLlWSzB_A^{7R2AQI~D6I=6D5E`E#G zDYCb(ziNv3NLcHN3#^BI8NxPVcAiCl_^>Q#WHI?uQCYY;`U{U!iuci(?tnKhpI!G{ zy7)aFo~H8sjGRDvI>*g&ZyT-E=DHWO8gPNvOClU2F~Bn3ws?Lpnb4(Lr_NHAFzb%#xJisVJ&-UX~p{4*wyell(i zChg7f*wbdBLxzP9{0L6ds>|$~=4WBvh^?XX^L@F3LY8rJa_Kqt#&06RMh`Kg$0SJwCF%gPi#bPP98i19$h4Fn zmUN|1jC!`^{fDg5yP zj&V4Yqrj67wC^V(q%aXTG52d2)@v43KR17zE-Wdi%~@vN;f|%F-}v;@E4Qgt@62!G z%&cmAxmt~jxJ<}$m1^H@%-<@q31q)8aD2)%-s{^OWW(fN*IHi@RLE{=FXuWP)_?oN zq)AIBDtL{7zRXA1kl{h6S9`!_XWvt3B)AOrfL>B_JtTNwA=UrLlYb*(Ibs|prn6;0 z%LHdkeZ04%mz#^48*nxiq4Q`QS# Date: Mon, 27 Sep 2021 10:53:37 +0200 Subject: [PATCH 157/681] Avoid createCallTarget() in regex, nfi, sl, and tck. --- .../src/com/oracle/truffle/regex/RegexLanguage.java | 3 +-- .../src/com/oracle/truffle/regex/RegexObject.java | 3 +-- .../oracle/truffle/regex/tregex/nodes/TRegexExecNode.java | 6 ++---- .../oracle/truffle/nfi/backend/libffi/LibFFIClosure.java | 3 +-- .../oracle/truffle/nfi/backend/libffi/LibFFILanguage.java | 4 ++-- .../truffle/nfi/backend/libffi/LibFFINFIBackend.java | 3 +-- .../truffle/nfi/backend/libffi/LibFFISignature.java | 3 +-- .../oracle/truffle/nfi/test/ImplicitConvertNFITest.java | 5 ++--- .../src/com/oracle/truffle/nfi/test/NFITest.java | 5 ++--- .../truffle/nfi/test/parser/backend/NFITestBackend.java | 8 +++----- .../src/com/oracle/truffle/nfi/NFILanguage.java | 7 ++++--- .../src/com/oracle/truffle/nfi/NFISignature.java | 5 ++--- .../com/oracle/truffle/sl/test/SLParseInContextTest.java | 5 ++--- .../src/com/oracle/truffle/sl/SLLanguage.java | 8 ++++---- .../src/com/oracle/truffle/sl/parser/SLNodeFactory.java | 3 +-- .../src/com/oracle/truffle/tck/impl/TckLanguage.java | 2 +- 16 files changed, 30 insertions(+), 43 deletions(-) diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexLanguage.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexLanguage.java index d44c86e330e0..e58ca41393a5 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexLanguage.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexLanguage.java @@ -43,7 +43,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.instrumentation.ProvidedTags; @@ -147,7 +146,7 @@ public GroupBoundaries[] getCachedGroupBoundaries() { @Override protected CallTarget parse(ParsingRequest parsingRequest) { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(createRegexObject(createRegexSource(parsingRequest.getSource())))); + return RootNode.createConstantNode(createRegexObject(createRegexSource(parsingRequest.getSource()))).getCallTarget(); } private static RegexSource createRegexSource(Source source) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexObject.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexObject.java index 8bd0171d0682..2355339ac7f0 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexObject.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexObject.java @@ -45,7 +45,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateUncached; @@ -136,7 +135,7 @@ public RegexObject(RegexExecNode execNode, RegexSource source, AbstractRegexObje this.flags = flags; this.numberOfCaptureGroups = numberOfCaptureGroups; this.namedCaptureGroups = namedCaptureGroups != null ? createNamedCaptureGroupMap(namedCaptureGroups) : TruffleNull.INSTANCE; - this.execCallTarget = Truffle.getRuntime().createCallTarget(new RegexRootNode(execNode.getRegexLanguage(), execNode)); + this.execCallTarget = new RegexRootNode(execNode.getRegexLanguage(), execNode).getCallTarget(); this.backtracking = execNode.isBacktracking(); } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecNode.java index b5477d6f7e43..b97cfd5c168b 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecNode.java @@ -43,7 +43,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.regex.RegexBodyNode; @@ -408,7 +407,7 @@ public LazyCaptureGroupRegexSearchNode(RegexLanguage language, } else { bodyNode = new TRegexLazyFindStartRootNode(language, source, backwardNode, captureGroupNode == null); } - backwardCallTarget = Truffle.getRuntime().createCallTarget(new RegexRootNode(language, bodyNode)); + backwardCallTarget = new RegexRootNode(language, bodyNode).getCallTarget(); } this.captureGroupEntryNode = insert(captureGroupNode); if (captureGroupNode == null) { @@ -420,8 +419,7 @@ public LazyCaptureGroupRegexSearchNode(RegexLanguage language, } else { findStartCallTarget = backwardCallTarget; } - captureGroupCallTarget = Truffle.getRuntime().createCallTarget( - new RegexRootNode(language, new TRegexLazyCaptureGroupsRootNode(language, source, captureGroupNode, rootNode, findStartCallTarget))); + captureGroupCallTarget = new RegexRootNode(language, new TRegexLazyCaptureGroupsRootNode(language, source, captureGroupNode, rootNode, findStartCallTarget)).getCallTarget(); } } diff --git a/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFIClosure.java b/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFIClosure.java index 291ba1616c4f..a729ee8d232b 100644 --- a/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFIClosure.java +++ b/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFIClosure.java @@ -43,7 +43,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; @@ -115,7 +114,7 @@ abstract static class CachedClosureInfo { final CallTarget closureCallTarget; CachedClosureInfo(RootNode rootNode) { - this.closureCallTarget = Truffle.getRuntime().createCallTarget(rootNode); + this.closureCallTarget = rootNode.getCallTarget(); } } diff --git a/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFILanguage.java b/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFILanguage.java index 75f19415579e..938a34c028b1 100644 --- a/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFILanguage.java +++ b/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFILanguage.java @@ -136,14 +136,14 @@ protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { CompilerDirectives.transferToInterpreter(); throw new UnsupportedOperationException("illegal access to internal language"); } - }); + }.getCallTarget(); } protected static LibFFIContext getCurrentContext() { diff --git a/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFINFIBackend.java b/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFINFIBackend.java index e3a311c37fc9..30db9edd30fe 100644 --- a/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFINFIBackend.java +++ b/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFINFIBackend.java @@ -42,7 +42,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropLibrary; @@ -112,7 +111,7 @@ public CallTarget parse(NativeLibraryDescriptor descriptor) { } root = new LoadLibraryNode(language, descriptor.getFilename(), flags); } - return Truffle.getRuntime().createCallTarget(root); + return root.getCallTarget(); } private static class LoadLibraryNode extends RootNode { diff --git a/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFISignature.java b/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFISignature.java index 2e95a41e93db..34f3ba23d54f 100644 --- a/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFISignature.java +++ b/truffle/src/com.oracle.truffle.nfi.backend.libffi/src/com/oracle/truffle/nfi/backend/libffi/LibFFISignature.java @@ -44,7 +44,6 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateAOT; import com.oracle.truffle.api.dsl.ImportStatic; @@ -244,7 +243,7 @@ static final class CachedSignatureInfo { this.objectCount = objectCount; this.allowedCallDirection = allowedCallDirection; - this.callTarget = Truffle.getRuntime().createCallTarget(new SignatureExecuteNode(language, this)); + this.callTarget = new SignatureExecuteNode(language, this).getCallTarget(); } NativeArgumentBuffer.Array prepareBuffer() { diff --git a/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/ImplicitConvertNFITest.java b/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/ImplicitConvertNFITest.java index d0084cbb160b..c790c3c8376a 100644 --- a/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/ImplicitConvertNFITest.java +++ b/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/ImplicitConvertNFITest.java @@ -56,7 +56,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.nfi.backend.spi.types.NativeSimpleType; @@ -128,12 +127,12 @@ public void testConvert(@Inject(TestConvertNode.class) CallTarget callTarget) { } private static boolean isCompileImmediately() { - CallTarget target = Truffle.getRuntime().createCallTarget(new RootNode(null) { + CallTarget target = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return CompilerDirectives.inCompiledCode(); } - }); + }.getCallTarget(); return (boolean) target.call(); } diff --git a/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/NFITest.java b/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/NFITest.java index 405fde7022df..610d9be02a92 100644 --- a/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/NFITest.java +++ b/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/NFITest.java @@ -40,6 +40,7 @@ */ package com.oracle.truffle.nfi.test; +import org.graalvm.polyglot.Context; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -47,14 +48,12 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.tck.TruffleRunner; -import org.graalvm.polyglot.Context; public class NFITest { @@ -85,7 +84,7 @@ protected static Object loadLibrary(String lib) { public static void loadLibraries() { defaultLibrary = loadLibrary("default"); testLibrary = loadLibrary("load '" + System.getProperty("native.test.lib") + "'"); - lookupAndBind = Truffle.getRuntime().createCallTarget(new LookupAndBindNode()); + lookupAndBind = new LookupAndBindNode().getCallTarget(); } private static final class LookupAndBindNode extends RootNode { diff --git a/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/parser/backend/NFITestBackend.java b/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/parser/backend/NFITestBackend.java index ea5fe16dae8d..5ee52d0cf8d4 100644 --- a/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/parser/backend/NFITestBackend.java +++ b/truffle/src/com.oracle.truffle.nfi.test/src/com/oracle/truffle/nfi/test/parser/backend/NFITestBackend.java @@ -43,7 +43,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleLanguage.Registration; @@ -84,7 +83,7 @@ static final class NFITestBackendImpl implements NFIBackend { @Override public CallTarget parse(NativeLibraryDescriptor descriptor) { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(new TestLibrary(descriptor))); + return RootNode.createConstantNode(new TestLibrary(descriptor)).getCallTarget(); } @ExportMessage @@ -129,14 +128,13 @@ public NFIBackend createBackend(NFIBackendTools t) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(this) { - + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { CompilerDirectives.transferToInterpreter(); throw new UnsupportedOperationException("illegal access to internal language"); } - }); + }.getCallTarget(); } private static final LanguageReference REFERENCE = LanguageReference.create(NFITestBackend.class); diff --git a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/NFILanguage.java b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/NFILanguage.java index c42aa389ed2b..75b33d728d1b 100644 --- a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/NFILanguage.java +++ b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/NFILanguage.java @@ -93,14 +93,15 @@ protected CallTarget parse(ParsingRequest request) throws Exception { Content c = source.getContent(); assert c != null; + RootNode root; if (c instanceof ParsedLibrary) { ParsedLibrary lib = (ParsedLibrary) c; - return Truffle.getRuntime().createCallTarget(new NFIRootNode(this, lib, backendId)); + root = new NFIRootNode(this, lib, backendId); } else { ParsedSignature sig = (ParsedSignature) c; - RootNode buildSignature = new SignatureRootNode(this, backendId, sig.getBuildSignatureNode()); - return Truffle.getRuntime().createCallTarget(buildSignature); + root = new SignatureRootNode(this, backendId, sig.getBuildSignatureNode()); } + return root.getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/NFISignature.java b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/NFISignature.java index 9c3b2825ffba..ab5df26a8a95 100644 --- a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/NFISignature.java +++ b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/NFISignature.java @@ -43,7 +43,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.ImportStatic; @@ -205,7 +204,7 @@ private synchronized void initPolymorphicSignatureCall() { if (polymorphicSignatureCall == null) { CallSignatureNode call = createOptimizedSignatureCall(); CallSignatureRootNode rootNode = new CallSignatureRootNode(NFILanguage.get(null), call); - polymorphicSignatureCall = Truffle.getRuntime().createCallTarget(rootNode); + polymorphicSignatureCall = rootNode.getCallTarget(); } } @@ -222,7 +221,7 @@ private synchronized void initPolymorphicClosureCall() { if (polymorphicClosureCall == null) { CallSignatureNode call = createOptimizedClosureCall(); CallSignatureRootNode rootNode = new CallSignatureRootNode(NFILanguage.get(null), call); - polymorphicClosureCall = Truffle.getRuntime().createCallTarget(rootNode); + polymorphicClosureCall = rootNode.getCallTarget(); } } diff --git a/truffle/src/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLParseInContextTest.java b/truffle/src/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLParseInContextTest.java index 69524487e7a6..13ad88e6bdcd 100644 --- a/truffle/src/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLParseInContextTest.java +++ b/truffle/src/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLParseInContextTest.java @@ -52,7 +52,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.VirtualFrame; @@ -89,7 +88,7 @@ protected Env createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { @@ -101,7 +100,7 @@ private Object parseAndEval() { Source aPlusB = Source.newBuilder("sl", "a + b", "plus.sl").build(); return CONTEXT_REF.get(this).parsePublic(aPlusB, "a", "b").call(30, 12); } - }); + }.getCallTarget(); } private static final ContextReference CONTEXT_REF = ContextReference.create(EvalLang.class); diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java index 4f0e8a6f1463..2c74950dec77 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java @@ -230,7 +230,7 @@ protected boolean patchContext(SLContext context, Env newEnv) { public RootCallTarget getOrCreateUndefinedFunction(String name) { RootCallTarget target = undefinedFunctions.get(name); if (target == null) { - target = Truffle.getRuntime().createCallTarget(new SLUndefinedFunctionRootNode(this, name)); + target = new SLUndefinedFunctionRootNode(this, name).getCallTarget(); RootCallTarget other = undefinedFunctions.putIfAbsent(name, target); if (other != null) { target = other; @@ -275,8 +275,8 @@ public RootCallTarget lookupBuiltin(NodeFactory factory * Register the builtin function in the builtin registry. Call targets for builtins may be * reused across multiple contexts. */ - RootCallTarget newTarget = Truffle.getRuntime().createCallTarget(rootNode); - RootCallTarget oldTarget = builtinTargets.put(factory, newTarget); + RootCallTarget newTarget = rootNode.getCallTarget(); + RootCallTarget oldTarget = builtinTargets.putIfAbsent(factory, newTarget); if (oldTarget != null) { return oldTarget; } @@ -339,7 +339,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { */ evalMain = new SLEvalRootNode(this, null, functions); } - return Truffle.getRuntime().createCallTarget(evalMain); + return evalMain.getCallTarget(); } /** diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java index 8bfc5e2f2fd0..b27392cb2909 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java @@ -50,7 +50,6 @@ import org.antlr.v4.runtime.Token; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -189,7 +188,7 @@ public void finishFunction(SLStatementNode bodyNode) { functionBodyNode.setSourceSection(functionSrc.getCharIndex(), functionSrc.getCharLength()); final SLRootNode rootNode = new SLRootNode(language, frameDescriptor, functionBodyNode, functionSrc, functionName); - allFunctions.put(functionName, Truffle.getRuntime().createCallTarget(rootNode)); + allFunctions.put(functionName, rootNode.getCallTarget()); } functionStartPos = 0; diff --git a/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/impl/TckLanguage.java b/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/impl/TckLanguage.java index 60f92a051d03..282ba989f862 100644 --- a/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/impl/TckLanguage.java +++ b/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/impl/TckLanguage.java @@ -78,7 +78,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { final double value = Double.parseDouble(txt); root = RootNode.createConstantNode(value); } - return Truffle.getRuntime().createCallTarget(root); + return root.getCallTarget(); } @ExportLibrary(InteropLibrary.class) From ac8868b6114640fffddb77cf9e46f0b340848d6f Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Wed, 22 Sep 2021 16:50:11 +0200 Subject: [PATCH 158/681] induction variable duplication must not gvn --- .../nodes/calc/IntegerConvertNode.java | 41 +++++++++++++++---- .../DerivedConvertedInductionVariable.java | 10 ++++- .../nodes/loop/DerivedInductionVariable.java | 4 +- .../loop/DerivedOffsetInductionVariable.java | 17 ++++++-- .../loop/DerivedScaledInductionVariable.java | 7 +++- .../graalvm/compiler/nodes/loop/MathUtil.java | 37 ++++++++++++++--- 6 files changed, 95 insertions(+), 21 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java index 3a030a21841f..40ac5dc7342d 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java @@ -28,11 +28,11 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.PrimitiveStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ArithmeticOperation; import org.graalvm.compiler.nodes.ConstantNode; @@ -40,6 +40,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.StampInverter; import jdk.vm.ci.meta.Constant; @@ -119,14 +120,24 @@ public static ValueNode convert(ValueNode input, Stamp stamp, NodeView view) { } public static ValueNode convert(ValueNode input, Stamp stamp, StructuredGraph graph, NodeView view) { - return convert(input, stamp, false, graph, view); + return convert(input, stamp, false, graph, view, true); } public static ValueNode convert(ValueNode input, Stamp stamp, boolean zeroExtend, StructuredGraph graph, NodeView view) { - ValueNode convert = convert(input, stamp, zeroExtend, view); - if (!convert.isAlive()) { - assert !convert.isDeleted(); - convert = graph.addOrUniqueWithInputs(convert); + return convert(input, stamp, zeroExtend, graph, view, true); + } + + public static ValueNode convert(ValueNode input, Stamp stamp, boolean zeroExtend, StructuredGraph graph, NodeView view, boolean gvn) { + ValueNode convert = convert(input, stamp, zeroExtend, view, gvn); + if (gvn) { + if (!convert.isAlive()) { + assert !convert.isDeleted(); + convert = graph.addOrUniqueWithInputs(convert); + } + } else { + GraalError.guarantee(!convert.isAlive(), "Convert must not GVN"); + GraalError.guarantee(!convert.isDeleted(), "Convert must not GVN"); + convert = graph.addWithoutUniqueWithInputs(convert); } return convert; } @@ -145,20 +156,32 @@ public static ValueNode convertUnsigned(ValueNode input, Stamp stamp, Structured } public static ValueNode convert(ValueNode input, Stamp stamp, boolean zeroExtend, NodeView view) { + return convert(input, stamp, zeroExtend, view, true); + } + + private static ValueNode convert(ValueNode input, Stamp stamp, boolean zeroExtend, NodeView view, boolean gvn) { IntegerStamp fromStamp = (IntegerStamp) input.stamp(view); IntegerStamp toStamp = (IntegerStamp) stamp; ValueNode result; - if (toStamp.getBits() == fromStamp.getBits()) { + if (gvn && toStamp.getBits() == fromStamp.getBits()) { result = input; } else if (toStamp.getBits() < fromStamp.getBits()) { result = new NarrowNode(input, fromStamp.getBits(), toStamp.getBits()); } else if (zeroExtend) { // toStamp.getBits() > fromStamp.getBits() - result = ZeroExtendNode.create(input, toStamp.getBits(), view); + if (gvn) { + result = ZeroExtendNode.create(input, toStamp.getBits(), view); + } else { + result = new ZeroExtendNode(input, toStamp.getBits()); + } } else { // toStamp.getBits() > fromStamp.getBits() - result = SignExtendNode.create(input, toStamp.getBits(), view); + if (gvn) { + result = SignExtendNode.create(input, toStamp.getBits(), view); + } else { + result = new SignExtendNode(input, toStamp.getBits()); + } } IntegerStamp resultStamp = (IntegerStamp) result.stamp(view); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedConvertedInductionVariable.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedConvertedInductionVariable.java index 0be5c1f04009..30e780e5607a 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedConvertedInductionVariable.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedConvertedInductionVariable.java @@ -106,8 +106,12 @@ public void deleteUnusedNodes() { } private ValueNode op(ValueNode v, boolean allowZeroExtend) { + return op(v, allowZeroExtend, true); + } + + private ValueNode op(ValueNode v, boolean allowZeroExtend, boolean gvn) { boolean zeroExtend = allowZeroExtend && value instanceof ZeroExtendNode; - return IntegerConvertNode.convert(v, stamp, zeroExtend, graph(), NodeView.DEFAULT); + return IntegerConvertNode.convert(v, stamp, zeroExtend, graph(), NodeView.DEFAULT, gvn); } @Override @@ -125,4 +129,8 @@ public ValueNode copyValue(InductionVariable newBase) { return op(newBase.valueNode(), true); } + @Override + public ValueNode copyValue(InductionVariable newBase, boolean gvn) { + return op(newBase.valueNode(), true, gvn); + } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedInductionVariable.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedInductionVariable.java index adb08ee01be5..7e2a54d75aa8 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedInductionVariable.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedInductionVariable.java @@ -51,10 +51,12 @@ public InductionVariable getBase() { @Override public InductionVariable duplicate() { InductionVariable newBase = base.duplicate(); - return copy(newBase, copyValue(newBase)); + return copy(newBase, copyValue(newBase, false/* no gvn */)); } public abstract ValueNode copyValue(InductionVariable newBase); + public abstract ValueNode copyValue(InductionVariable newBase, boolean gvn); + public abstract InductionVariable copy(InductionVariable newBase, ValueNode newValue); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedOffsetInductionVariable.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedOffsetInductionVariable.java index c530f73189e6..eb94eed1af83 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedOffsetInductionVariable.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedOffsetInductionVariable.java @@ -141,15 +141,19 @@ private long op(long b, long o) { } public ValueNode op(ValueNode b, ValueNode o) { + return op(b, o, true); + } + + public ValueNode op(ValueNode b, ValueNode o, boolean gvn) { if (value instanceof AddNode) { - return add(graph(), b, o); + return add(graph(), b, o, gvn); } if (value instanceof SubNode) { if (base.valueNode() == value.getX()) { - return sub(graph(), b, o); + return sub(graph(), b, o, gvn); } else { assert base.valueNode() == value.getY(); - return sub(graph(), o, b); + return sub(graph(), o, b, gvn); } } throw GraalError.shouldNotReachHere(); @@ -197,7 +201,12 @@ public String toString() { @Override public ValueNode copyValue(InductionVariable newBase) { - return op(newBase.valueNode(), offset); + return copyValue(newBase, true); + } + + @Override + public ValueNode copyValue(InductionVariable newBase, boolean gvn) { + return op(newBase.valueNode(), offset, gvn); } @Override diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedScaledInductionVariable.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedScaledInductionVariable.java index 2ce1afbd55f6..56e28cf51f3e 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedScaledInductionVariable.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DerivedScaledInductionVariable.java @@ -167,9 +167,14 @@ public String toString() { return String.format("DerivedScaleInductionVariable base (%s) %s %s", base, value.getNodeClass().shortName(), scale); } + @Override + public ValueNode copyValue(InductionVariable newBase, boolean gvn) { + return MathUtil.mul(graph(), newBase.valueNode(), scale, gvn); + } + @Override public ValueNode copyValue(InductionVariable newBase) { - return MathUtil.mul(graph(), newBase.valueNode(), scale); + return copyValue(newBase, true); } @Override diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/MathUtil.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/MathUtil.java index 3759c3404300..788ea54cceeb 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/MathUtil.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/MathUtil.java @@ -24,19 +24,22 @@ */ package org.graalvm.compiler.nodes.loop; +import java.util.function.BiFunction; + import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; import org.graalvm.compiler.nodes.calc.FixedBinaryNode; +import org.graalvm.compiler.nodes.calc.MulNode; import org.graalvm.compiler.nodes.calc.SignedDivNode; +import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.calc.UnsignedDivNode; import org.graalvm.compiler.nodes.extended.GuardingNode; -import java.util.function.BiFunction; - /** * Utility methods to perform integer math with some obvious constant folding first. */ @@ -50,30 +53,54 @@ private static boolean isConstantZero(ValueNode v1) { } public static ValueNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) { + return add(graph, v1, v2, true); + } + + public static ValueNode add(StructuredGraph graph, ValueNode v1, ValueNode v2, boolean gvn) { if (isConstantZero(v1)) { return v2; } if (isConstantZero(v2)) { return v1; } - return BinaryArithmeticNode.add(graph, v1, v2, NodeView.DEFAULT); + if (gvn) { + return BinaryArithmeticNode.add(graph, v1, v2, NodeView.DEFAULT); + } else { + return graph.addWithoutUniqueWithInputs(new AddNode(v1, v2)); + } } public static ValueNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) { + return mul(graph, v1, v2, true); + } + + public static ValueNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2, boolean gvn) { if (isConstantOne(v1)) { return v2; } if (isConstantOne(v2)) { return v1; } - return BinaryArithmeticNode.mul(graph, v1, v2, NodeView.DEFAULT); + if (gvn) { + return BinaryArithmeticNode.mul(graph, v1, v2, NodeView.DEFAULT); + } else { + return graph.addWithoutUniqueWithInputs(new MulNode(v1, v2)); + } } public static ValueNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) { + return sub(graph, v1, v2, true); + } + + public static ValueNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2, boolean gvn) { if (isConstantZero(v2)) { return v1; } - return BinaryArithmeticNode.sub(graph, v1, v2, NodeView.DEFAULT); + if (gvn) { + return BinaryArithmeticNode.sub(graph, v1, v2, NodeView.DEFAULT); + } else { + return graph.addWithoutUniqueWithInputs(new SubNode(v1, v2)); + } } public static ValueNode divBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor, GuardingNode zeroCheck) { From f982ad40b54a3d3944d56539e76e7c8f883ace0a Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Mon, 27 Sep 2021 11:28:41 +0100 Subject: [PATCH 159/681] Add small help text to legend. --- .../tools/profiler/impl/resources/color_change.js | 13 ++++++++++++- .../tools/profiler/impl/resources/graphowner.js | 6 ++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js index 8a47d40fd927..97263e6a4cbf 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js @@ -128,8 +128,19 @@ function color_create_legend() { t.style.fill = "rgb(0, 0, 0)"; t.textContent = "Legend"; + let t2 = document.createElementNS("http://www.w3.org/2000/svg", "text"); + t2.className.baseVal = "title"; + t2.style.textAnchor = "middle"; + t2.setAttribute("x", 125); + t2.setAttribute("y", fg_frameheight * 3); + t2.style.fontSize = fontSize; + t2.style.fontFamily = "Verdana"; + t2.style.fill = "rgb(0, 0, 0)"; + t2.textContent = "Press \"l\" to toggle legend"; + e.appendChild(r); e.appendChild(t); + e.appendChild(t2); e.style.display = "none"; svg.appendChild(e); @@ -176,7 +187,7 @@ function color_insert_legend(e) { } function color_legend_entry(e, i, color, text) { - let y = (fg_frameheight * 2) + (i + 1) * fg_frameheight * 1.5; + let y = (fg_frameheight * 2.3) + (i + 1) * fg_frameheight * 1.5; let box = document.createElementNS("http://www.w3.org/2000/svg", "rect"); box.x.baseVal.value = xpad; diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index cc09b66d8101..0f79a98ae683 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -399,8 +399,10 @@ function graph_popup_fix_width(e, right_justify) { max_label_end = label_end; } } - let title = e.getElementsByClassName("title")[0]; - title.x.baseVal.value = max_label_end / 2; + let titles = e.getElementsByClassName("title"); + for (const title of titles) { + title.x.baseVal.value = max_label_end / 2; + } let popup = e.getElementsByClassName("popup")[0]; popup.width.baseVal.value = max_label_end; if (right_justify) { From 3f8f0481eb2a5d5b2b4e75e4d6e023b2009046e6 Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Mon, 27 Sep 2021 11:41:39 +0100 Subject: [PATCH 160/681] Improve text shown at bottom of graph. --- .../truffle/tools/profiler/impl/resources/graphowner.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index 0f79a98ae683..95c1333d5c5d 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -26,8 +26,11 @@ // highlighting and info text function s(node) { // show - let info = title(node); - flamegraph_details.nodeValue = "function: " + info; + let sample = sample_for_id(node.getAttribute("id").substring(2)); + let name = name_for_sample(sample) + flamegraph_details.textContent = name + " (" + languageNames[sample.l] + ") - " + + "(Self:" + (sample.i + sample.c) + " samples " + + "Total: " + (sample.h) + " samples)"; } function c(node) { // clear From e3421d145b0af0c075bd3c160fbee3d72a14ecc2 Mon Sep 17 00:00:00 2001 From: Aleksandar Prokopec Date: Mon, 27 Sep 2021 12:50:21 +0200 Subject: [PATCH 161/681] Add changelog entries for GraalWasm 21.3.0 release. --- wasm/CHANGELOG.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/wasm/CHANGELOG.md b/wasm/CHANGELOG.md index e6e83856aa7e..1737d16dbd21 100644 --- a/wasm/CHANGELOG.md +++ b/wasm/CHANGELOG.md @@ -3,3 +3,24 @@ This changelog summarizes major changes to the WebAssembly engine implemented in GraalVM (GraalWasm). ## Version 21.3.0 + +* (GR-32924) Add support for importing and exporting mutable globals to GraalWasm, + as defined by the respective WebAssembly proposal: + https://github.com/WebAssembly/mutable-global/blob/master/proposals/mutable-global/Overview.md +* (GR-26941) Ensure that the module is completely validated when it is first parsed, + instead of being validated late, during linking and instantiation. + All validation errors are now properly reported when `Context#eval` from the Polyglot API is invoked, + and similarly when invoking `WebAssembly.validate` from the JS-WebAssembly Interface API. +* (GR-33183) Memory-access performance is improved by avoiding a branch due to a out-of-bounds check. +* (GR-32714) Loop-profiling in GraalWasm was made more accurate to enable more loop optimizations. +* (GR-33227) Change the Interop objects in GraalWasm to allow object-caching in the + JS-WebAssembly Interface: https://webassembly.github.io/spec/js-api/index.html#object-caches +* (GR-32356) Fix bug in which memory or table initialization could lead to an integer overflow. +* (GR-33296) Notify JavaScript when the memory grows (i.e. `mem_grow` instruction executes). + This improves the compliance of the JS-WebAssembly Interface API. +* (GR-33333) Add support for `BigInt`-to-`i64` conversion in the JS-WebAssembly Interface API: + https://github.com/WebAssembly/JS-BigInt-integration +* (GR-32590) Improve internal design of GraalWasm to make JS-WebAssembly Interface API + more compliant. + + From fabb4bf858cc5f4a3b0624c5d13ba211ec7ccce4 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 27 Sep 2021 13:16:06 +0200 Subject: [PATCH 162/681] Avoid createCallTarget() in Truffle polyglot. --- .../truffle/polyglot/HostToGuestRootNode.java | 6 ----- .../truffle/polyglot/PolyglotEngineImpl.java | 2 +- .../truffle/polyglot/PolyglotFunction.java | 2 +- .../PolyglotFunctionProxyHandler.java | 2 +- .../truffle/polyglot/PolyglotIterable.java | 4 ++-- .../truffle/polyglot/PolyglotIterator.java | 6 ++--- .../polyglot/PolyglotLanguageInstance.java | 3 +-- .../oracle/truffle/polyglot/PolyglotList.java | 14 +++++------- .../oracle/truffle/polyglot/PolyglotMap.java | 22 ++++++++----------- .../truffle/polyglot/PolyglotMapEntry.java | 10 +++------ .../polyglot/PolyglotObjectProxyHandler.java | 2 +- .../polyglot/PolyglotValueDispatch.java | 3 +-- 12 files changed, 28 insertions(+), 48 deletions(-) diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostToGuestRootNode.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostToGuestRootNode.java index 50ca69331d49..362b85221831 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostToGuestRootNode.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostToGuestRootNode.java @@ -40,10 +40,8 @@ */ package com.oracle.truffle.polyglot; -import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.TruffleObject; @@ -151,10 +149,6 @@ private E handleException(PolyglotLanguageContext language protected abstract Object executeImpl(PolyglotLanguageContext languageContext, Object receiver, Object[] args); - protected static CallTarget createTarget(HostToGuestRootNode node) { - return Truffle.getRuntime().createCallTarget(node); - } - static T installHostCodeCache(PolyglotLanguageContext languageContext, Object key, T value, Class expectedType) { T result = expectedType.cast(languageContext.getLanguageInstance().hostToGuestCodeCache.putIfAbsent(key, value)); if (result != null) { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java index 5918313ebc90..7445dfed8b22 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java @@ -355,7 +355,7 @@ private PolyglotLanguage[] createLanguageStaticIndex() { private static UncachedLocationNode createUncachedLocation(TruffleLanguage hostLanguage) { UncachedLocationNode location = new UncachedLocationNode(hostLanguage); // this is intended to trigger Truffle runtime initialization in the background - Truffle.getRuntime().createCallTarget(location); + location.getCallTarget(); return location; } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotFunction.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotFunction.java index a95b327a521d..f85c21fbcecd 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotFunction.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotFunction.java @@ -170,7 +170,7 @@ private static CallTarget lookup(PolyglotLanguageContext languageContext, Class< Apply apply = new Apply(receiverClass, returnClass, returnType, paramClass, paramType); CallTarget target = lookupHostCodeCache(languageContext, apply, CallTarget.class); if (target == null) { - target = installHostCodeCache(languageContext, apply, createTarget(apply), CallTarget.class); + target = installHostCodeCache(languageContext, apply, apply.getCallTarget(), CallTarget.class); } return target; } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotFunctionProxyHandler.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotFunctionProxyHandler.java index 0eb056327a8a..1715e3e2ab4e 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotFunctionProxyHandler.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotFunctionProxyHandler.java @@ -255,7 +255,7 @@ static CallTarget lookup(PolyglotLanguageContext languageContext, Class recei FunctionProxyNode node = FunctionProxyNodeGen.create(receiverClass, method); CallTarget target = lookupHostCodeCache(languageContext, node, CallTarget.class); if (target == null) { - target = installHostCodeCache(languageContext, node, createTarget(node), CallTarget.class); + target = installHostCodeCache(languageContext, node, node.getCallTarget(), CallTarget.class); } return target; } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotIterable.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotIterable.java index 87651c5f24b4..e0b57e270723 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotIterable.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotIterable.java @@ -121,8 +121,8 @@ private Cache(Class receiverClass, Class valueClass, Type valueType) { this.receiverClass = receiverClass; this.valueClass = valueClass; this.valueType = valueType; - this.getIterator = HostToGuestRootNode.createTarget(GetIteratorNodeGen.create(this)); - this.apply = HostToGuestRootNode.createTarget(new Apply(this)); + this.getIterator = GetIteratorNodeGen.create(this).getCallTarget(); + this.apply = new Apply(this).getCallTarget(); this.iteratorType = new ParameterizedIteratorType(valueType); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotIterator.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotIterator.java index f375440c1cad..9050be8b613e 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotIterator.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotIterator.java @@ -168,9 +168,9 @@ private Cache(Class receiverClass, Class valueClass, Type valueType) { this.receiverClass = receiverClass; this.valueClass = valueClass; this.valueType = valueType; - this.hasNext = HostToGuestRootNode.createTarget(HasNextNodeGen.create(this)); - this.next = HostToGuestRootNode.createTarget(NextNodeGen.create(this)); - this.apply = HostToGuestRootNode.createTarget(new Apply(this)); + this.hasNext = HasNextNodeGen.create(this).getCallTarget(); + this.next = NextNodeGen.create(this).getCallTarget(); + this.apply = new Apply(this).getCallTarget(); } static Cache lookup(PolyglotLanguageContext languageContext, Class receiverClass, Class valueClass, Type valueType) { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageInstance.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageInstance.java index a3b0146faaad..214af67e179e 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageInstance.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageInstance.java @@ -52,7 +52,6 @@ import org.graalvm.polyglot.Source; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.ContextPolicy; import com.oracle.truffle.api.interop.TruffleObject; @@ -105,7 +104,7 @@ CallTarget lookupCallTarget(Class rootNodeClass) { } CallTarget installCallTarget(RootNode rootNode) { - return callTargetCache.computeIfAbsent(rootNode.getClass(), (r) -> Truffle.getRuntime().createCallTarget(rootNode)); + return callTargetCache.computeIfAbsent(rootNode.getClass(), (r) -> rootNode.getCallTarget()); } public PolyglotEngineImpl getEngine() { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotList.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotList.java index 7d3ccc97a277..563650e08c6c 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotList.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotList.java @@ -158,15 +158,11 @@ static final class Cache { this.receiverClass = receiverClass; this.valueClass = valueClass; this.valueType = valueType; - this.get = initializeCall(PolyglotListFactory.CacheFactory.GetNodeGen.create(this)); - this.size = initializeCall(SizeNodeGen.create(this)); - this.set = initializeCall(SetNodeGen.create(this)); - this.remove = initializeCall(RemoveNodeGen.create(this)); - this.apply = initializeCall(new Apply(this)); - } - - private static CallTarget initializeCall(PolyglotListNode node) { - return HostToGuestRootNode.createTarget(node); + this.get = PolyglotListFactory.CacheFactory.GetNodeGen.create(this).getCallTarget(); + this.size = SizeNodeGen.create(this).getCallTarget(); + this.set = SetNodeGen.create(this).getCallTarget(); + this.remove = RemoveNodeGen.create(this).getCallTarget(); + this.apply = new Apply(this).getCallTarget(); } static Cache lookup(PolyglotLanguageContext languageContext, Class receiverClass, Class valueClass, Type valueType) { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMap.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMap.java index b92fb51ddc0a..b153b85eea46 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMap.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMap.java @@ -402,19 +402,15 @@ static final class Cache { this.valueType = valueType; this.memberKey = keyClass == Object.class || keyClass == String.class || keyClass == CharSequence.class; this.numberKey = keyClass == Object.class || keyClass == Number.class || keyClass == Integer.class || keyClass == Long.class || keyClass == Short.class || keyClass == Byte.class; - this.get = initializeCall(PolyglotMapFactory.CacheFactory.GetNodeGen.create(this)); - this.containsKey = initializeCall(PolyglotMapFactory.CacheFactory.ContainsKeyNodeGen.create(this)); - this.entrySet = initializeCall(EntrySetNodeGen.create(this)); - this.put = initializeCall(PutNodeGen.create(this)); - this.remove = initializeCall(PolyglotMapFactory.CacheFactory.RemoveNodeGen.create(this)); - this.removeBoolean = initializeCall(RemoveBooleanNodeGen.create(this)); - this.hashEntriesIterator = initializeCall(HashEntriesIteratorNodeGen.create(this)); - this.hashSize = initializeCall(HashSizeNodeGen.create(this)); - this.apply = initializeCall(new Apply(this)); - } - - private static CallTarget initializeCall(PolyglotMapNode node) { - return HostToGuestRootNode.createTarget(node); + this.get = PolyglotMapFactory.CacheFactory.GetNodeGen.create(this).getCallTarget(); + this.containsKey = PolyglotMapFactory.CacheFactory.ContainsKeyNodeGen.create(this).getCallTarget(); + this.entrySet = EntrySetNodeGen.create(this).getCallTarget(); + this.put = PutNodeGen.create(this).getCallTarget(); + this.remove = PolyglotMapFactory.CacheFactory.RemoveNodeGen.create(this).getCallTarget(); + this.removeBoolean = RemoveBooleanNodeGen.create(this).getCallTarget(); + this.hashEntriesIterator = HashEntriesIteratorNodeGen.create(this).getCallTarget(); + this.hashSize = HashSizeNodeGen.create(this).getCallTarget(); + this.apply = new Apply(this).getCallTarget(); } static Cache lookup(PolyglotLanguageContext languageContext, Class receiverClass, Class keyClass, Type keyType, Class valueClass, Type valueType) { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMapEntry.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMapEntry.java index 8795064fe88e..1b1133fef7ba 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMapEntry.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMapEntry.java @@ -144,13 +144,9 @@ static final class Cache { this.keyType = keyType; this.valueClass = valueClass; this.valueType = valueType; - this.getKey = initializeCall(PolyglotMapEntryFactory.CacheFactory.GetNodeGen.create(this, "getKey", 0, keyClass, keyType)); - this.getValue = initializeCall(PolyglotMapEntryFactory.CacheFactory.GetNodeGen.create(this, "getValue", 1, valueClass, valueType)); - this.apply = initializeCall(new Apply(this)); - } - - private static CallTarget initializeCall(PolyglotMapEntry.Cache.PolyglotMapEntryNode node) { - return HostToGuestRootNode.createTarget(node); + this.getKey = PolyglotMapEntryFactory.CacheFactory.GetNodeGen.create(this, "getKey", 0, keyClass, keyType).getCallTarget(); + this.getValue = PolyglotMapEntryFactory.CacheFactory.GetNodeGen.create(this, "getValue", 1, valueClass, valueType).getCallTarget(); + this.apply = new Apply(this).getCallTarget(); } static PolyglotMapEntry.Cache lookup(PolyglotLanguageContext languageContext, Class receiverClass, diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotObjectProxyHandler.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotObjectProxyHandler.java index d072e09b66b3..f5f635e7c1e0 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotObjectProxyHandler.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotObjectProxyHandler.java @@ -168,7 +168,7 @@ static CallTarget lookup(PolyglotLanguageContext languageContext, Class recei ObjectProxyNode node = new ObjectProxyNode(receiverClass, interfaceClass); CallTarget target = lookupHostCodeCache(languageContext, node, CallTarget.class); if (target == null) { - target = installHostCodeCache(languageContext, node, createTarget(node), CallTarget.class); + target = installHostCodeCache(languageContext, node, node.getCallTarget(), CallTarget.class); } return target; } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValueDispatch.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValueDispatch.java index b0879dce2736..d91475da8fd3 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValueDispatch.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValueDispatch.java @@ -67,7 +67,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.ArityException; @@ -1601,7 +1600,7 @@ public String getMetaSimpleName(Object languageContext, Object receiver) { } static CallTarget createTarget(InteropNode root) { - CallTarget target = Truffle.getRuntime().createCallTarget(root); + CallTarget target = root.getCallTarget(); Class[] types = root.getArgumentTypes(); if (types != null) { RUNTIME.initializeProfile(target, types); From 65b28e7c8d8d0063fa89a2658fcd799a2ebae3af Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 27 Sep 2021 13:16:20 +0200 Subject: [PATCH 163/681] Avoid createCallTarget() in Truffle host. --- .../truffle/host/GuestToHostCodeCache.java | 121 +++++++++--------- .../truffle/host/GuestToHostRootNode.java | 5 - .../com/oracle/truffle/host/HostLanguage.java | 5 +- 3 files changed, 62 insertions(+), 69 deletions(-) diff --git a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/GuestToHostCodeCache.java b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/GuestToHostCodeCache.java index e3fa175edde6..458150273424 100644 --- a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/GuestToHostCodeCache.java +++ b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/GuestToHostCodeCache.java @@ -40,8 +40,6 @@ */ package com.oracle.truffle.host; -import static com.oracle.truffle.host.GuestToHostRootNode.createGuestToHost; - import java.lang.invoke.MethodHandle; import java.time.Duration; import java.time.Instant; @@ -50,8 +48,6 @@ import java.time.ZoneId; import java.util.NoSuchElementException; -import com.oracle.truffle.api.interop.InteropException; -import com.oracle.truffle.api.interop.StopIterationException; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.proxy.ProxyArray; import org.graalvm.polyglot.proxy.ProxyDate; @@ -69,9 +65,11 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleOptions; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.TruffleOptions; +import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.interop.InvalidArrayIndexException; +import com.oracle.truffle.api.interop.StopIterationException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.host.HostMethodDesc.SingleMethod; import com.oracle.truffle.host.HostMethodDesc.SingleMethod.MHBase; @@ -84,7 +82,7 @@ final class GuestToHostCodeCache { this.language = language; } - final CallTarget methodHandleHostInvoke = GuestToHostRootNode.createGuestToHost(new GuestToHostRootNode(HostObject.class, "doInvoke") { + final CallTarget methodHandleHostInvoke = new GuestToHostRootNode(HostObject.class, "doInvoke") { @Override protected Object executeImpl(Object receiver, Object[] callArguments) { if (TruffleOptions.AOT) { @@ -101,9 +99,9 @@ protected Object executeImpl(Object receiver, Object[] callArguments) { } return ret; } - }); + }.getCallTarget(); - final CallTarget reflectionHostInvoke = GuestToHostRootNode.createGuestToHost(new GuestToHostRootNode(HostObject.class, "doInvoke") { + final CallTarget reflectionHostInvoke = new GuestToHostRootNode(HostObject.class, "doInvoke") { @Override protected Object executeImpl(Object obj, Object[] callArguments) { SingleMethod.ReflectBase method = (SingleMethod.ReflectBase) callArguments[ARGUMENT_OFFSET]; @@ -116,9 +114,9 @@ protected Object executeImpl(Object obj, Object[] callArguments) { } return ret; } - }); + }.getCallTarget(); - final CallTarget execute = createGuestToHost(new GuestToHostRootNode(ProxyExecutable.class, "execute") { + final CallTarget execute = new GuestToHostRootNode(ProxyExecutable.class, "execute") { @Override @TruffleBoundary @@ -129,18 +127,18 @@ protected Object executeImpl(Object proxy, Object[] arguments) throws Unsupporte throw UnsupportedMessageException.create(); } } - }); + }.getCallTarget(); - final CallTarget asPointer = createGuestToHost(new GuestToHostRootNode(ProxyNativeObject.class, "asPointer") { + final CallTarget asPointer = new GuestToHostRootNode(ProxyNativeObject.class, "asPointer") { @Override @TruffleBoundary protected Object executeImpl(Object proxy, Object[] arguments) { return ((ProxyNativeObject) proxy).asPointer(); } - }); + }.getCallTarget(); - final CallTarget instantiate = createGuestToHost(new GuestToHostRootNode(ProxyInstantiable.class, "newInstance") { + final CallTarget instantiate = new GuestToHostRootNode(ProxyInstantiable.class, "newInstance") { @Override @TruffleBoundary @@ -151,9 +149,9 @@ protected Object executeImpl(Object proxy, Object[] arguments) throws Unsupporte throw UnsupportedMessageException.create(); } } - }); + }.getCallTarget(); - final CallTarget arrayGet = createGuestToHost(new GuestToHostRootNode(ProxyArray.class, "get") { + final CallTarget arrayGet = new GuestToHostRootNode(ProxyArray.class, "get") { @Override protected Object executeImpl(Object proxy, Object[] arguments) throws InvalidArrayIndexException, UnsupportedMessageException { @@ -171,9 +169,9 @@ protected Object executeImpl(Object proxy, Object[] arguments) throws InvalidArr private Object boundaryGet(ProxyArray proxy, long index) { return proxy.get(index); } - }); + }.getCallTarget(); - final CallTarget arraySet = createGuestToHost(new GuestToHostRootNode(ProxyArray.class, "set") { + final CallTarget arraySet = new GuestToHostRootNode(ProxyArray.class, "set") { @Override protected Object executeImpl(Object proxy, Object[] arguments) throws InvalidArrayIndexException, UnsupportedMessageException { @@ -192,9 +190,9 @@ protected Object executeImpl(Object proxy, Object[] arguments) throws InvalidArr private void boundarySet(ProxyArray proxy, long index, Value value) { proxy.set(index, value); } - }); + }.getCallTarget(); - final CallTarget arrayRemove = createGuestToHost(new GuestToHostRootNode(ProxyArray.class, "remove") { + final CallTarget arrayRemove = new GuestToHostRootNode(ProxyArray.class, "remove") { @Override protected Object executeImpl(Object proxy, Object[] arguments) throws InvalidArrayIndexException, UnsupportedMessageException { @@ -212,27 +210,27 @@ protected Object executeImpl(Object proxy, Object[] arguments) throws InvalidArr private boolean boundaryRemove(ProxyArray proxy, long index) { return proxy.remove(index); } - }); + }.getCallTarget(); - final CallTarget arraySize = createGuestToHost(new GuestToHostRootNode(ProxyArray.class, "getSize") { + final CallTarget arraySize = new GuestToHostRootNode(ProxyArray.class, "getSize") { @Override @TruffleBoundary protected Object executeImpl(Object proxy, Object[] arguments) { return ((ProxyArray) proxy).getSize(); } - }); + }.getCallTarget(); - final CallTarget memberKeys = createGuestToHost(new GuestToHostRootNode(ProxyObject.class, "getMemberKeys") { + final CallTarget memberKeys = new GuestToHostRootNode(ProxyObject.class, "getMemberKeys") { @Override @TruffleBoundary protected Object executeImpl(Object proxy, Object[] arguments) { return ((ProxyObject) proxy).getMemberKeys(); } - }); + }.getCallTarget(); - final CallTarget getMember = createGuestToHost(new GuestToHostRootNode(ProxyObject.class, "getMember") { + final CallTarget getMember = new GuestToHostRootNode(ProxyObject.class, "getMember") { @Override protected Object executeImpl(Object proxy, Object[] arguments) throws UnsupportedMessageException { @@ -247,9 +245,9 @@ protected Object executeImpl(Object proxy, Object[] arguments) throws Unsupporte private Object boundaryGetMember(ProxyObject proxy, String argument) { return proxy.getMember(argument); } - }); + }.getCallTarget(); - final CallTarget putMember = createGuestToHost(new GuestToHostRootNode(ProxyObject.class, "putMember") { + final CallTarget putMember = new GuestToHostRootNode(ProxyObject.class, "putMember") { @Override protected Object executeImpl(Object proxy, Object[] arguments) throws UnsupportedMessageException { @@ -265,9 +263,9 @@ protected Object executeImpl(Object proxy, Object[] arguments) throws Unsupporte private void boundaryPutMember(ProxyObject proxy, String member, Value value) { proxy.putMember(member, value); } - }); + }.getCallTarget(); - final CallTarget removeMember = createGuestToHost(new GuestToHostRootNode(ProxyObject.class, "removeMember") { + final CallTarget removeMember = new GuestToHostRootNode(ProxyObject.class, "removeMember") { @Override protected Object executeImpl(Object proxy, Object[] arguments) throws UnsupportedMessageException { @@ -282,18 +280,18 @@ protected Object executeImpl(Object proxy, Object[] arguments) throws Unsupporte private boolean removeBoundary(ProxyObject proxy, String member) { return proxy.removeMember(member); } - }); + }.getCallTarget(); - final CallTarget hasMember = createGuestToHost(new GuestToHostRootNode(ProxyObject.class, "hasMember") { + final CallTarget hasMember = new GuestToHostRootNode(ProxyObject.class, "hasMember") { @Override @TruffleBoundary protected Object executeImpl(Object proxy, Object[] arguments) { return ((ProxyObject) proxy).hasMember((String) arguments[ARGUMENT_OFFSET]); } - }); + }.getCallTarget(); - final CallTarget asTimezone = createGuestToHost(new GuestToHostRootNode(ProxyTimeZone.class, "asTimeZone") { + final CallTarget asTimezone = new GuestToHostRootNode(ProxyTimeZone.class, "asTimeZone") { @Override @TruffleBoundary @@ -304,9 +302,9 @@ protected Object executeImpl(Object proxy, Object[] arguments) { } return zone; } - }); + }.getCallTarget(); - final CallTarget asDate = createGuestToHost(new GuestToHostRootNode(ProxyDate.class, "asDate") { + final CallTarget asDate = new GuestToHostRootNode(ProxyDate.class, "asDate") { @Override @TruffleBoundary @@ -317,8 +315,9 @@ protected Object executeImpl(Object proxy, Object[] arguments) { } return date; } - }); - final CallTarget asTime = createGuestToHost(new GuestToHostRootNode(ProxyTime.class, "asTime") { + }.getCallTarget(); + + final CallTarget asTime = new GuestToHostRootNode(ProxyTime.class, "asTime") { @Override @TruffleBoundary @@ -329,9 +328,9 @@ protected Object executeImpl(Object proxy, Object[] arguments) { } return time; } - }); + }.getCallTarget(); - final CallTarget asInstant = createGuestToHost(new GuestToHostRootNode(ProxyInstant.class, "asInstant") { + final CallTarget asInstant = new GuestToHostRootNode(ProxyInstant.class, "asInstant") { @Override @TruffleBoundary @@ -342,9 +341,9 @@ protected Object executeImpl(Object proxy, Object[] arguments) { } return instant; } - }); + }.getCallTarget(); - final CallTarget asDuration = createGuestToHost(new GuestToHostRootNode(ProxyDuration.class, "asDuration") { + final CallTarget asDuration = new GuestToHostRootNode(ProxyDuration.class, "asDuration") { @Override @TruffleBoundary @@ -355,27 +354,27 @@ protected Object executeImpl(Object proxy, Object[] arguments) { } return duration; } - }); + }.getCallTarget(); - final CallTarget getIterator = createGuestToHost(new GuestToHostRootNode(ProxyIterable.class, "getIterator") { + final CallTarget getIterator = new GuestToHostRootNode(ProxyIterable.class, "getIterator") { @Override @TruffleBoundary protected Object executeImpl(Object proxy, Object[] arguments) { return ((ProxyIterable) proxy).getIterator(); } - }); + }.getCallTarget(); - final CallTarget hasIteratorNextElement = createGuestToHost(new GuestToHostRootNode(ProxyIterator.class, "hasIteratorNextElement") { + final CallTarget hasIteratorNextElement = new GuestToHostRootNode(ProxyIterator.class, "hasIteratorNextElement") { @Override @TruffleBoundary protected Object executeImpl(Object proxy, Object[] arguments) { return ((ProxyIterator) proxy).hasNext(); } - }); + }.getCallTarget(); - final CallTarget getIteratorNextElement = createGuestToHost(new GuestToHostRootNode(ProxyIterator.class, "getIteratorNextElement") { + final CallTarget getIteratorNextElement = new GuestToHostRootNode(ProxyIterator.class, "getIteratorNextElement") { @Override @TruffleBoundary @@ -388,27 +387,27 @@ protected Object executeImpl(Object proxy, Object[] arguments) throws StopIterat throw UnsupportedMessageException.create(); } } - }); + }.getCallTarget(); - final CallTarget hasHashEntry = createGuestToHost(new GuestToHostRootNode(ProxyHashMap.class, "hasEntry") { + final CallTarget hasHashEntry = new GuestToHostRootNode(ProxyHashMap.class, "hasEntry") { @Override @TruffleBoundary protected Object executeImpl(Object receiver, Object[] arguments) throws InteropException { return ((ProxyHashMap) receiver).hasHashEntry((Value) arguments[ARGUMENT_OFFSET]); } - }); + }.getCallTarget(); - final CallTarget getHashSize = createGuestToHost(new GuestToHostRootNode(ProxyHashMap.class, "getSize") { + final CallTarget getHashSize = new GuestToHostRootNode(ProxyHashMap.class, "getSize") { @Override @TruffleBoundary protected Object executeImpl(Object receiver, Object[] arguments) throws InteropException { return ((ProxyHashMap) receiver).getHashSize(); } - }); + }.getCallTarget(); - final CallTarget getHashValue = createGuestToHost(new GuestToHostRootNode(ProxyHashMap.class, "getValue") { + final CallTarget getHashValue = new GuestToHostRootNode(ProxyHashMap.class, "getValue") { @Override @TruffleBoundary protected Object executeImpl(Object receiver, Object[] arguments) throws InteropException { @@ -418,9 +417,9 @@ protected Object executeImpl(Object receiver, Object[] arguments) throws Interop throw UnsupportedMessageException.create(); } } - }); + }.getCallTarget(); - final CallTarget putHashEntry = createGuestToHost(new GuestToHostRootNode(ProxyHashMap.class, "putEntry") { + final CallTarget putHashEntry = new GuestToHostRootNode(ProxyHashMap.class, "putEntry") { @Override @TruffleBoundary protected Object executeImpl(Object receiver, Object[] arguments) throws InteropException { @@ -431,9 +430,9 @@ protected Object executeImpl(Object receiver, Object[] arguments) throws Interop throw UnsupportedMessageException.create(); } } - }); + }.getCallTarget(); - final CallTarget removeHashEntry = createGuestToHost(new GuestToHostRootNode(ProxyHashMap.class, "removeEntry") { + final CallTarget removeHashEntry = new GuestToHostRootNode(ProxyHashMap.class, "removeEntry") { @Override @TruffleBoundary protected Object executeImpl(Object receiver, Object[] arguments) throws InteropException { @@ -443,13 +442,13 @@ protected Object executeImpl(Object receiver, Object[] arguments) throws Interop throw UnsupportedMessageException.create(); } } - }); + }.getCallTarget(); - final CallTarget getHashEntriesIterator = createGuestToHost(new GuestToHostRootNode(ProxyHashMap.class, "getEntriesIterator") { + final CallTarget getHashEntriesIterator = new GuestToHostRootNode(ProxyHashMap.class, "getEntriesIterator") { @Override @TruffleBoundary protected Object executeImpl(Object receiver, Object[] arguments) throws InteropException { return ((ProxyHashMap) receiver).getHashEntriesIterator(); } - }); + }.getCallTarget(); } diff --git a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/GuestToHostRootNode.java b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/GuestToHostRootNode.java index 66e5fdb3d5c9..993c67079712 100644 --- a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/GuestToHostRootNode.java +++ b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/GuestToHostRootNode.java @@ -41,7 +41,6 @@ package com.oracle.truffle.host; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.nodes.EncapsulatingNodeReference; @@ -93,10 +92,6 @@ static RuntimeException silenceException(Class type, Th protected abstract Object executeImpl(Object receiver, Object[] arguments) throws InteropException; - static CallTarget createGuestToHost(GuestToHostRootNode rootNode) { - return Truffle.getRuntime().createCallTarget(rootNode); - } - static Object guestToHostCall(Node node, CallTarget target, Object... arguments) { Node encapsulatingNode; if (node.isAdoptable()) { diff --git a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostLanguage.java b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostLanguage.java index 05f3cf3797ee..c77631432843 100644 --- a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostLanguage.java +++ b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostLanguage.java @@ -51,7 +51,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.VirtualFrame; @@ -176,13 +175,13 @@ protected Object getLanguageView(HostContext hostContext, Object value) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { String sourceString = request.getSource().getCharacters().toString(); - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { return service.findDynamicClass(HostContext.get(this), sourceString); } - }); + }.getCallTarget(); } static final LanguageReference REFERENCE = LanguageReference.create(HostLanguage.class); From 9066a6f3d2d45f7a3748baf3f32e2bc28dbf7dc8 Mon Sep 17 00:00:00 2001 From: Aleksandar Prokopec Date: Mon, 27 Sep 2021 13:35:04 +0200 Subject: [PATCH 164/681] Address style comments. --- wasm/CHANGELOG.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/wasm/CHANGELOG.md b/wasm/CHANGELOG.md index 1737d16dbd21..bab45fba70f3 100644 --- a/wasm/CHANGELOG.md +++ b/wasm/CHANGELOG.md @@ -4,23 +4,23 @@ This changelog summarizes major changes to the WebAssembly engine implemented in ## Version 21.3.0 -* (GR-32924) Add support for importing and exporting mutable globals to GraalWasm, +* (GR-32924) Added support for importing and exporting mutable globals to GraalWasm, as defined by the respective WebAssembly proposal: https://github.com/WebAssembly/mutable-global/blob/master/proposals/mutable-global/Overview.md -* (GR-26941) Ensure that the module is completely validated when it is first parsed, - instead of being validated late, during linking and instantiation. +* (GR-26941) Moved the module-validation checks to an earlier stage, so that the module + is completely validated during parsing, instead of being validated late, during linking and instantiation. All validation errors are now properly reported when `Context#eval` from the Polyglot API is invoked, and similarly when invoking `WebAssembly.validate` from the JS-WebAssembly Interface API. -* (GR-33183) Memory-access performance is improved by avoiding a branch due to a out-of-bounds check. +* (GR-33183) Memory-access performance was improved by avoiding a branch due to a out-of-bounds check. * (GR-32714) Loop-profiling in GraalWasm was made more accurate to enable more loop optimizations. -* (GR-33227) Change the Interop objects in GraalWasm to allow object-caching in the +* (GR-33227) Changed the Interop objects in GraalWasm to allow object-caching in the JS-WebAssembly Interface: https://webassembly.github.io/spec/js-api/index.html#object-caches -* (GR-32356) Fix bug in which memory or table initialization could lead to an integer overflow. -* (GR-33296) Notify JavaScript when the memory grows (i.e. `mem_grow` instruction executes). +* (GR-32356) Fixed a bug that caused an overflow during memory or table initialization. +* (GR-33296) Added notifications to JavaScript when the memory grows (i.e., when `mem_grow` instruction executes). This improves the compliance of the JS-WebAssembly Interface API. -* (GR-33333) Add support for `BigInt`-to-`i64` conversion in the JS-WebAssembly Interface API: +* (GR-33333) Added support for `BigInt`-to-`i64` conversion in the JS-WebAssembly Interface API: https://github.com/WebAssembly/JS-BigInt-integration -* (GR-32590) Improve internal design of GraalWasm to make JS-WebAssembly Interface API +* (GR-32590) Improved internal implementation of GraalWasm to make JS-WebAssembly Interface API more compliant. From a708515ef3fda6e74c484770dfcb65c4a46aa47f Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Mon, 27 Sep 2021 12:41:05 +0100 Subject: [PATCH 165/681] Fix compiled / interpreted colors. --- .../oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index b0ea04e60cfd..d0beb461df43 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -434,7 +434,7 @@ public JSONObject sampleData(ProfilerNode sample, long x) { result.put("id", sampleId++); result.put("i", sample.getPayload().getTierSelfCount(0)); int compiledSelfHits = 0; - for (int i = 0; i < sample.getPayload().getNumberOfTiers(); i++) { + for (int i = 1; i < sample.getPayload().getNumberOfTiers(); i++) { compiledSelfHits += sample.getPayload().getTierSelfCount(i); } result.put("c", compiledSelfHits); From 0c72ea2a267cceed41ffe0cac61b39dc1415e936 Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Mon, 27 Sep 2021 12:49:42 +0100 Subject: [PATCH 166/681] Change help text at top of graph and make legend off by default. --- .../oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java | 2 +- .../oracle/truffle/tools/profiler/impl/resources/flamegraph.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index d0beb461df43..4a26747fd3b6 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -790,7 +790,7 @@ public String drawCanvas(double x, double y) { output.append(ttfString(black(), owner.fontName(), owner.fontSize() + 5, width() / 2, owner.fontSize() * 2, "Flamegraph", "middle", "id=\"fg_title\"")); output.append(ttfString(black(), owner.fontName(), owner.fontSize(), width() / 2, owner.fontSize() * 3, - "Press \"?\" for help", "middle", "id=\"fg_help\"")); + "Press \"?\" for help, or \"l\" for legend.", "middle", "id=\"fg_help\"")); output.append(ttfString(black(), owner.fontName(), owner.fontSize(), XPAD, owner.fontSize() * 2, "Reset zoom", "", "id=\"unzoom\" onclick=\"unzoom()\" style=\"opacity:0.1;cursor:pointer\"")); output.append(ttfString(black(), owner.fontName(), owner.fontSize(), width() - XPAD, owner.fontSize() * 2, diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index 33c906daaf91..183deb9358c4 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -36,7 +36,6 @@ function fg_init(evt) { var el = flamegraph.getElementsByTagName("g"); for(let i=0;i Date: Mon, 27 Sep 2021 13:33:05 +0100 Subject: [PATCH 167/681] Generate the correct details for histogram entries. --- .../profiler/impl/resources/graphowner.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index 95c1333d5c5d..5d43edab3e37 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -26,11 +26,22 @@ // highlighting and info text function s(node) { // show - let sample = sample_for_id(node.getAttribute("id").substring(2)); + let sample = null; + if (node.getAttribute("class") == "func_g") { + sample = sample_for_id(node.getAttribute("id").substring(2)); + } else if (node.getAttribute("class") == "func_h") { + sample = histogram_entry_for_id(node.getAttribute("id").substring(2)); + } let name = name_for_sample(sample) - flamegraph_details.textContent = name + " (" + languageNames[sample.l] + ") - " + - "(Self:" + (sample.i + sample.c) + " samples " + - "Total: " + (sample.h) + " samples)"; + let details = name + " (" + languageNames[sample.l] + ") - "; + if (sample.hasOwnProperty("h")) { + details = details + "(Self:" + (sample.i + sample.c) + " samples " + + "Total: " + (sample.h) + " samples)"; + } else { + details = details + "(" + (sample.i + sample.c) + " samples)"; + } + + flamegraph_details.textContent = details; } function c(node) { // clear From 3a837503e306b6c8fafd040f02b7024a058ab78b Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Mon, 27 Sep 2021 15:48:12 +0300 Subject: [PATCH 168/681] Include no_jlinking option in GraalVM distribution's hash encoding Makes the following two commands return a different GraalVM distribution: ``` mx --primary-suite-path substratevm graalvm-show mx --primary-suite-path substratevm --no-jlinking graalvm-show ``` --- sdk/mx.sdk/mx_sdk_vm_impl.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index 07c320137872..d17455695618 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -958,6 +958,10 @@ def _get_graalvm_configuration(base_name, components=None, stage1=False): m = hashlib.sha1() for component in components_sorted_set: m.update(_encode(component)) + if _jlink_libraries(): + m.update(_encode("jlinked")) + else: + m.update(_encode("not-jlinked")) short_sha1_digest = m.hexdigest()[:10] # to keep paths short base_dir = '{base_name}_{hash}_java{jdk_version}'.format(base_name=base_name, hash=short_sha1_digest, jdk_version=_src_jdk_version) name = '{base_dir}{stage_suffix}'.format(base_dir=base_dir, stage_suffix='_stage1' if stage1 else '') From ac0db4894e9ca029a6ac810c252c7c1d2c542e0f Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Mon, 27 Sep 2021 15:18:19 +0100 Subject: [PATCH 169/681] Overwrite profile output files if they already exist. --- .../com/oracle/truffle/tools/profiler/impl/ProfilerCLI.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/ProfilerCLI.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/ProfilerCLI.java index 2cf63856aff8..879333a6a402 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/ProfilerCLI.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/ProfilerCLI.java @@ -312,9 +312,6 @@ protected static PrintStream chooseOutputStream(TruffleInstrument.Env env, Optio if (option.hasBeenSet(env.getOptions())) { final String outputPath = option.getValue(env.getOptions()); final File file = new File(outputPath); - if (file.exists()) { - throw new IllegalArgumentException("Cannot redirect output to an existing file!"); - } return new PrintStream(new FileOutputStream(file)); } else { return new PrintStream(env.out()); From dca89bbec0f8a869178ef3913cc15649dd062690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C3=B6=20Barany?= Date: Mon, 27 Sep 2021 17:31:08 +0200 Subject: [PATCH 170/681] Avoid ConcurrentModificationException in GraphUtil --- .../src/org/graalvm/compiler/nodes/util/GraphUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java index 0b5e8c8b7923..33fa9efc4c11 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java @@ -536,7 +536,7 @@ private static void normalizeLoopBegin(LoopBeginNode begin) { for (PhiNode phi : begin.phis().snapshot()) { GraphUtil.checkRedundantPhi(phi); } - for (LoopExitNode exit : begin.loopExits()) { + for (LoopExitNode exit : begin.loopExits().snapshot()) { for (ProxyNode vpn : exit.proxies().snapshot()) { GraphUtil.checkRedundantProxy(vpn); } From 35cdc326041ace8ff23b1fd3b36e97e47ea6c889 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Fri, 24 Sep 2021 16:47:25 +0200 Subject: [PATCH 171/681] Make ValueLocation.set throw IncompatibleLocationException, not FinalLocationException. --- .../truffle/object/basic/test/ConstantLocationTest.java | 7 ++++--- .../truffle/object/basic/test/DeclaredLocationTest.java | 7 ++++--- .../object/basic/test/LegacyConstantLocationTest.java | 7 ++++--- .../object/basic/test/LegacyDeclaredLocationTest.java | 7 ++++--- .../src/com/oracle/truffle/object/CoreLocations.java | 4 ++-- .../src/com/oracle/truffle/object/Locations.java | 5 ++--- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/ConstantLocationTest.java b/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/ConstantLocationTest.java index 5813ff0fe4e6..544a08475083 100644 --- a/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/ConstantLocationTest.java +++ b/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/ConstantLocationTest.java @@ -43,6 +43,7 @@ import java.util.Arrays; import java.util.List; +import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -100,8 +101,8 @@ public void testConstantLocation() { try { property.set(object, newValue, shapeWithConstant); Assert.fail(); - } catch (FinalLocationException | IncompatibleLocationException e) { - Assert.assertTrue(e instanceof FinalLocationException); + } catch (IncompatibleLocationException | FinalLocationException e) { + Assert.assertThat(e, CoreMatchers.instanceOf(IncompatibleLocationException.class)); } Assert.assertSame(value, library.getOrDefault(object, "constant", null)); @@ -143,7 +144,7 @@ public void testAddConstantLocation() { property.set(object2, newValue, rootShape, shapeWithConstant); Assert.fail(); } catch (IncompatibleLocationException e) { - // Expected + Assert.assertThat(e, CoreMatchers.instanceOf(IncompatibleLocationException.class)); } Assert.assertSame(rootShape, object2.getShape()); Assert.assertEquals(false, library.containsKey(object2, "constant")); diff --git a/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/DeclaredLocationTest.java b/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/DeclaredLocationTest.java index 5946a9e949d9..7d8959904a9e 100644 --- a/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/DeclaredLocationTest.java +++ b/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/DeclaredLocationTest.java @@ -43,6 +43,7 @@ import java.util.Arrays; import java.util.List; +import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -100,8 +101,8 @@ public void testDeclaredLocation() { try { property.set(object, newValue, shapeWithDeclared); Assert.fail(); - } catch (FinalLocationException | IncompatibleLocationException e) { - Assert.assertTrue(e instanceof FinalLocationException); + } catch (IncompatibleLocationException | FinalLocationException e) { + Assert.assertThat(e, CoreMatchers.instanceOf(IncompatibleLocationException.class)); } Assert.assertSame(value, library.getOrDefault(object, "declared", null)); @@ -143,7 +144,7 @@ public void testAddDeclaredLocation() { property.set(object2, newValue, rootShape, shapeWithDeclared); Assert.fail(); } catch (IncompatibleLocationException e) { - // Expected + Assert.assertThat(e, CoreMatchers.instanceOf(IncompatibleLocationException.class)); } Assert.assertSame(rootShape, object2.getShape()); Assert.assertEquals(false, library.containsKey(object2, "declared")); diff --git a/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/LegacyConstantLocationTest.java b/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/LegacyConstantLocationTest.java index edbc1fec1766..7034da727042 100644 --- a/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/LegacyConstantLocationTest.java +++ b/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/LegacyConstantLocationTest.java @@ -40,6 +40,7 @@ */ package com.oracle.truffle.object.basic.test; +import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.Test; @@ -83,8 +84,8 @@ public void testConstantLocation() { try { property.set(object, newValue, shapeWithConstant); Assert.fail(); - } catch (FinalLocationException | IncompatibleLocationException e) { - Assert.assertTrue(e instanceof FinalLocationException); + } catch (IncompatibleLocationException | FinalLocationException e) { + Assert.assertThat(e, CoreMatchers.instanceOf(IncompatibleLocationException.class)); } Assert.assertSame(value, object.get("constant")); @@ -119,7 +120,7 @@ public void testAddConstantLocation() { property.set(object2, newValue, rootShape, shapeWithConstant); Assert.fail(); } catch (IncompatibleLocationException e) { - // Expected + Assert.assertThat(e, CoreMatchers.instanceOf(IncompatibleLocationException.class)); } Assert.assertSame(rootShape, object2.getShape()); Assert.assertEquals(false, object2.containsKey("constant")); diff --git a/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/LegacyDeclaredLocationTest.java b/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/LegacyDeclaredLocationTest.java index 60a51f77682f..e4febd05afa3 100644 --- a/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/LegacyDeclaredLocationTest.java +++ b/truffle/src/com.oracle.truffle.object.basic.test/src/com/oracle/truffle/object/basic/test/LegacyDeclaredLocationTest.java @@ -40,6 +40,7 @@ */ package com.oracle.truffle.object.basic.test; +import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.Test; @@ -83,8 +84,8 @@ public void testDeclaredLocation() { try { property.set(object, newValue, shapeWithDeclared); Assert.fail(); - } catch (FinalLocationException | IncompatibleLocationException e) { - Assert.assertTrue(e instanceof FinalLocationException); + } catch (IncompatibleLocationException | FinalLocationException e) { + Assert.assertThat(e, CoreMatchers.instanceOf(IncompatibleLocationException.class)); } Assert.assertSame(value, object.get("declared")); @@ -119,7 +120,7 @@ public void testAddDeclaredLocation() { property.set(object2, newValue, rootShape, shapeWithDeclared); Assert.fail(); } catch (IncompatibleLocationException e) { - // Expected + Assert.assertThat(e, CoreMatchers.instanceOf(IncompatibleLocationException.class)); } Assert.assertSame(rootShape, object2.getShape()); Assert.assertEquals(false, object2.containsKey("declared")); diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java index a88467793811..93e5c4d6fbd6 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java @@ -256,13 +256,13 @@ public boolean canStore(Object val) { } @Override - public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException { if (!canStore(value)) { if (init) { CompilerDirectives.transferToInterpreterAndInvalidate(); throw new UnsupportedOperationException(); } else { - throw finalLocation(); + throw incompatibleLocation(); } } } diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java index 649f765c3c10..933197736736 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java @@ -44,7 +44,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.object.DynamicObject; -import com.oracle.truffle.api.object.FinalLocationException; import com.oracle.truffle.api.object.IncompatibleLocationException; import com.oracle.truffle.api.object.Location; import com.oracle.truffle.api.object.Property; @@ -107,13 +106,13 @@ public boolean canStore(Object val) { } @Override - public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { + public final void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException { if (!canStore(value)) { if (init) { CompilerDirectives.transferToInterpreterAndInvalidate(); throw new UnsupportedOperationException(); } else { - throw finalLocation(); + throw incompatibleLocation(); } } } From 3dd6c84ea0a22f972e28e20710e876862018f9fe Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Fri, 24 Sep 2021 16:58:00 +0200 Subject: [PATCH 172/681] LocationImpl.set no longer throws FinalLocationException. --- .../oracle/truffle/object/CoreLocations.java | 17 ++++++------ .../oracle/truffle/object/LocationImpl.java | 26 +++++++------------ 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java index 93e5c4d6fbd6..266d33c37e79 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/CoreLocations.java @@ -48,7 +48,6 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.object.DynamicObject; -import com.oracle.truffle.api.object.FinalLocationException; import com.oracle.truffle.api.object.IncompatibleLocationException; import com.oracle.truffle.api.object.Location; import com.oracle.truffle.api.object.Property; @@ -100,12 +99,12 @@ default int getInt(DynamicObject store, Shape shape) { } @Override - default void setInt(DynamicObject store, int value, Shape shape) throws FinalLocationException { + default void setInt(DynamicObject store, int value, Shape shape) { setInt(store, value, store.getShape() == shape, false); } @Override - default void setInt(DynamicObject store, int value) throws FinalLocationException { + default void setInt(DynamicObject store, int value) { setInt(store, value, false, false); } @@ -136,12 +135,12 @@ default long getLong(DynamicObject store, Shape shape) { } @Override - default void setLong(DynamicObject store, long value, Shape shape) throws FinalLocationException { + default void setLong(DynamicObject store, long value, Shape shape) { setLong(store, value, store.getShape() == shape, false); } @Override - default void setLong(DynamicObject store, long value) throws FinalLocationException { + default void setLong(DynamicObject store, long value) { setLong(store, value, false, false); } @@ -172,12 +171,12 @@ default double getDouble(DynamicObject store, Shape shape) { } @Override - default void setDouble(DynamicObject store, double value, Shape shape) throws FinalLocationException { + default void setDouble(DynamicObject store, double value, Shape shape) { setDouble(store, value, store.getShape() == shape, false); } @Override - default void setDouble(DynamicObject store, double value) throws FinalLocationException { + default void setDouble(DynamicObject store, double value) { setDouble(store, value, false, false); } @@ -206,12 +205,12 @@ default boolean getBoolean(DynamicObject store, Shape shape) { } @Override - default void setBoolean(DynamicObject store, boolean value, Shape shape) throws FinalLocationException { + default void setBoolean(DynamicObject store, boolean value, Shape shape) { setBoolean(store, value, store.getShape() == shape, false); } @Override - default void setBoolean(DynamicObject store, boolean value) throws FinalLocationException { + default void setBoolean(DynamicObject store, boolean value) { setBoolean(store, value, false, false); } diff --git a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java index dbf67e3751c6..d480f864d544 100644 --- a/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java +++ b/truffle/src/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java @@ -45,7 +45,6 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.object.DynamicObject; -import com.oracle.truffle.api.object.FinalLocationException; import com.oracle.truffle.api.object.IncompatibleLocationException; import com.oracle.truffle.api.object.Location; import com.oracle.truffle.api.object.LongLocation; @@ -86,7 +85,7 @@ public interface LocationVisitor { /** @since 0.17 or earlier */ @Override - public void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException { + public void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException { set(store, value, checkShape(store, shape), false); } @@ -155,16 +154,15 @@ protected boolean getBoolean(DynamicObject store, boolean guard) throws Unexpect * @param guard the result of the shape check guarding this property write or {@code false}. * @param init if true, this is the initial assignment of a property location; ignore final. * @throws IncompatibleLocationException if the value cannot be stored in this storage location. - * @throws FinalLocationException if the property location is effectively final and init=false. * @see #setSafe(DynamicObject, Object, boolean, boolean) */ - protected abstract void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException; + protected abstract void set(DynamicObject store, Object value, boolean guard, boolean init) throws IncompatibleLocationException; /** * @see #set(DynamicObject, Object, boolean, boolean) * @see #setIntSafe(DynamicObject, int, boolean, boolean) */ - protected void setInt(DynamicObject store, int value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { + protected void setInt(DynamicObject store, int value, boolean guard, boolean init) throws IncompatibleLocationException { set(store, value, guard, init); } @@ -172,7 +170,7 @@ protected void setInt(DynamicObject store, int value, boolean guard, boolean ini * @see #set(DynamicObject, Object, boolean, boolean) * @see #setLongSafe(DynamicObject, long, boolean, boolean) */ - protected void setLong(DynamicObject store, long value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { + protected void setLong(DynamicObject store, long value, boolean guard, boolean init) throws IncompatibleLocationException { set(store, value, guard, init); } @@ -180,7 +178,7 @@ protected void setLong(DynamicObject store, long value, boolean guard, boolean i * @see #set(DynamicObject, Object, boolean, boolean) * @see #setDoubleSafe(DynamicObject, double, boolean, boolean) */ - protected void setDouble(DynamicObject store, double value, boolean guard, boolean init) throws IncompatibleLocationException, FinalLocationException { + protected void setDouble(DynamicObject store, double value, boolean guard, boolean init) throws IncompatibleLocationException { set(store, value, guard, init); } @@ -194,11 +192,7 @@ protected static final boolean checkShape(DynamicObject store, Shape shape) { /** @since 0.17 or earlier */ @Override protected final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException { - try { - set(store, value, false, true); - } catch (FinalLocationException e) { - throw shouldNotHappen(e); - } + set(store, value, false, true); } /** @since 0.17 or earlier */ @@ -332,7 +326,7 @@ static boolean isSameLocation(LocationImpl loc1, LocationImpl loc2) { protected final void setSafe(DynamicObject store, Object value, boolean guard, boolean init) { try { set(store, value, guard, init); - } catch (IncompatibleLocationException | FinalLocationException e) { + } catch (IncompatibleLocationException e) { throw shouldNotHappen(e); } } @@ -343,7 +337,7 @@ protected final void setSafe(DynamicObject store, Object value, boolean guard, b protected final void setIntSafe(DynamicObject store, int value, boolean guard, boolean init) { try { setInt(store, value, guard, init); - } catch (IncompatibleLocationException | FinalLocationException e) { + } catch (IncompatibleLocationException e) { throw shouldNotHappen(e); } } @@ -354,7 +348,7 @@ protected final void setIntSafe(DynamicObject store, int value, boolean guard, b protected final void setLongSafe(DynamicObject store, long value, boolean guard, boolean init) { try { setLong(store, value, guard, init); - } catch (IncompatibleLocationException | FinalLocationException e) { + } catch (IncompatibleLocationException e) { throw shouldNotHappen(e); } } @@ -365,7 +359,7 @@ protected final void setLongSafe(DynamicObject store, long value, boolean guard, protected final void setDoubleSafe(DynamicObject store, double value, boolean guard, boolean init) { try { setDouble(store, value, guard, init); - } catch (IncompatibleLocationException | FinalLocationException e) { + } catch (IncompatibleLocationException e) { throw shouldNotHappen(e); } } From 61537f5a55c47b8da97d94c93148a19387b67795 Mon Sep 17 00:00:00 2001 From: Cosmin Basca Date: Mon, 27 Sep 2021 18:39:16 +0200 Subject: [PATCH 173/681] mx_vm_benchmark.py: hardcode and fix name of host-vm field when measuring binary file sizes --- vm/mx.vm/mx_vm_benchmark.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vm/mx.vm/mx_vm_benchmark.py b/vm/mx.vm/mx_vm_benchmark.py index c4f1a44f76bd..9101e681b099 100644 --- a/vm/mx.vm/mx_vm_benchmark.py +++ b/vm/mx.vm/mx_vm_benchmark.py @@ -1063,6 +1063,9 @@ def get_vm_registry(self): return _polybench_vm_registry def runAndReturnStdOut(self, benchmarks, bmSuiteArgs): + from mx_sdk_vm import graalvm_components, GraalVmLanguage, GraalVmJreComponent + from mx_sdk_vm_impl import get_native_image_locations, has_component + vm = self.get_vm_registry().get_vm_from_suite_args(bmSuiteArgs) vm.extract_vm_info(self.vmArgs(bmSuiteArgs)) host_vm = None @@ -1071,15 +1074,13 @@ def runAndReturnStdOut(self, benchmarks, bmSuiteArgs): assert host_vm dims = { "vm": vm.name(), - "host-vm": host_vm.name() if host_vm else vm.name(), + # the host-vm is hardcoded to one of the accepted names of the field + "host-vm": 'graalvm-ee' if has_component('svmee') else 'graalvm-ce', "host-vm-config": self.host_vm_config_name(host_vm, vm), "guest-vm": vm.name() if host_vm else "none", "guest-vm-config": self.guest_vm_config_name(host_vm, vm), } - from mx_sdk_vm import graalvm_components, GraalVmLanguage, GraalVmJreComponent - from mx_sdk_vm_impl import get_native_image_locations - out = "" for gcomponent in graalvm_components(): sz_msg = None From 43535a7d5014814309d9833690c0d71a93a10560 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 27 Sep 2021 18:42:52 +0200 Subject: [PATCH 174/681] Fix JVMCI reserved field method lookup did not find accessor method on JDK >= 11; Add test to validate all JVMCI features are available in the gate. --- .../hotspot/AbstractHotSpotTruffleRuntime.java | 15 +++++++++++++-- .../truffle/runtime/GraalTruffleRuntime.java | 4 ++++ .../test/ContextLookupCompilationTest.java | 13 +++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot/src/org/graalvm/compiler/truffle/runtime/hotspot/AbstractHotSpotTruffleRuntime.java b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot/src/org/graalvm/compiler/truffle/runtime/hotspot/AbstractHotSpotTruffleRuntime.java index ae911adc5ed9..2cf0b48d2099 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot/src/org/graalvm/compiler/truffle/runtime/hotspot/AbstractHotSpotTruffleRuntime.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot/src/org/graalvm/compiler/truffle/runtime/hotspot/AbstractHotSpotTruffleRuntime.java @@ -181,9 +181,9 @@ public AbstractHotSpotTruffleRuntime() { installReservedOopMethods(null); try { - setReservedReference0 = MethodHandles.publicLookup().findVirtual(HotSpotJVMCIRuntime.class, + setReservedReference0 = MethodHandles.lookup().findVirtual(HotSpotJVMCIRuntime.class, "setThreadLocalObject", MethodType.methodType(void.class, int.class, Object.class)); - getReservedReference0 = MethodHandles.publicLookup().findVirtual(HotSpotJVMCIRuntime.class, + getReservedReference0 = MethodHandles.lookup().findVirtual(HotSpotJVMCIRuntime.class, "getThreadLocalObject", MethodType.methodType(Object.class, int.class)); } catch (NoSuchMethodException | IllegalAccessException e) { /* @@ -268,6 +268,17 @@ public void accept(CompilationTask task) { } } + @Override + public boolean isLatestJVMCI() { + if (getJVMCIReservedReference0 == null) { + return false; + } + if (getJVMCIReservedLongOffset0() == -1) { + return false; + } + return true; + } + /* * Used reflectively in CompilerInitializationTest. */ diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java index ca53b6c4e9ba..5adb60c3040a 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java @@ -186,6 +186,10 @@ public GraalTruffleRuntime(Iterable> extraLookupTypes) { this.floodControlHandler = loadGraalRuntimeServiceProvider(FloodControlHandler.class, null, false); } + public boolean isLatestJVMCI() { + return true; + } + public abstract ThreadLocalHandshake getThreadLocalHandshake(); @Override diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ContextLookupCompilationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ContextLookupCompilationTest.java index 393d7ea59abd..e4149a45b545 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ContextLookupCompilationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ContextLookupCompilationTest.java @@ -36,11 +36,13 @@ import org.graalvm.compiler.nodes.FieldLocationIdentity; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.memory.ReadNode; +import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Engine; import org.graalvm.word.LocationIdentity; import org.junit.Assert; +import org.junit.Assume; import org.junit.Test; import com.oracle.truffle.api.CompilerAsserts; @@ -48,6 +50,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.ContextLocal; import com.oracle.truffle.api.ContextThreadLocal; +import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.ContextPolicy; @@ -92,6 +95,16 @@ private static Context enter(Context context) { return context; } + /* + * This test verifies that JVMCI has all the features it needs for a GraalTruffleRuntime. + */ + @Test + public void testJVMCIIsLatest() { + Assume.assumeTrue(Truffle.getRuntime() instanceof GraalTruffleRuntime); + GraalTruffleRuntime runtime = (GraalTruffleRuntime) Truffle.getRuntime(); + assertTrue(runtime.isLatestJVMCI()); + } + @Test public void testContextLocalRead() { Engine engine = Engine.create(); From bb3f0d13bd4478776e2f4101b4d710eb26e9b9d8 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 21 Sep 2021 11:34:05 -0700 Subject: [PATCH 175/681] Be more strict about InputType.Memory --- .../compiler/graph/MemoryKillMarker.java | 33 +++++++++++++++++++ .../org/graalvm/compiler/graph/NodeClass.java | 4 +++ .../replacements/UnsafeCopyMemoryNode.java | 10 +++--- .../compiler/nodes/extended/BoxNode.java | 8 ++--- .../compiler/nodes/extended/UnboxNode.java | 6 ++-- .../compiler/nodes/memory/MemoryKill.java | 3 +- .../replacements/nodes/ArrayEqualsNode.java | 6 ++-- .../replacements/nodes/ZeroMemoryNode.java | 8 ++++- 8 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/MemoryKillMarker.java diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/MemoryKillMarker.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/MemoryKillMarker.java new file mode 100644 index 000000000000..9f3db2a57b31 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/MemoryKillMarker.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 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 org.graalvm.compiler.graph; + +/** + * Any node that includes {@link org.graalvm.compiler.nodeinfo.InputType#Memory InputType.Memory} in + * {@link org.graalvm.compiler.nodeinfo.NodeInfo#allowedUsageTypes() NodeInfo.allowedUsageTypes} + * must also implement a subtype of this interface. + */ +public interface MemoryKillMarker { +} diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java index 74ae7c4b5751..d1a4c0d57027 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java @@ -222,6 +222,8 @@ public NodeClass(Class clazz, NodeClass superNodeClass, FieldsScan try (DebugCloseable t1 = Init_AllowedUsages.start(debug)) { allowedUsageTypes = superNodeClass == null ? EnumSet.noneOf(InputType.class) : superNodeClass.allowedUsageTypes.clone(); allowedUsageTypes.addAll(Arrays.asList(info.allowedUsageTypes())); + GraalError.guarantee(!allowedUsageTypes.contains(InputType.Memory) || MemoryKillMarker.class.isAssignableFrom(clazz), + "Node of type %s with allowedUsageType of memory must inherit from MemoryKill", clazz); } if (presetIterableIds != null) { @@ -503,6 +505,8 @@ protected void scanField(Field field, long offset) { } else { inputType = optionalInputAnnotation.value(); } + GraalError.guarantee(inputType != InputType.Memory || MemoryKillMarker.class.isAssignableFrom(type) || NodeInputList.class.isAssignableFrom(type), + "field type of input annotated with Memory must inherit from MemoryKill: %s", field); inputs.add(new InputInfo(offset, field.getName(), type, field.getDeclaringClass(), inputType, field.isAnnotationPresent(Node.OptionalInput.class))); } else if (successorAnnotation != null) { if (SUCCESSOR_LIST_CLASS.isAssignableFrom(type)) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeCopyMemoryNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeCopyMemoryNode.java index e4d98f92c5db..be4063ea21bd 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeCopyMemoryNode.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeCopyMemoryNode.java @@ -29,7 +29,6 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.AbstractStateSplit; @@ -53,7 +52,7 @@ public class UnsafeCopyMemoryNode extends AbstractStateSplit implements Lowerabl @Input ValueNode desOffset; @Input ValueNode bytes; - @OptionalInput(Memory) Node lastLocationAccess; + @OptionalInput(Memory) MemoryKill lastLocationAccess; private final boolean guarded; @@ -85,14 +84,13 @@ public LocationIdentity getLocationIdentity() { @Override public MemoryKill getLastLocationAccess() { - return (MemoryKill) lastLocationAccess; + return lastLocationAccess; } @Override public void setLastLocationAccess(MemoryKill lla) { - Node newLla = ValueNodeUtil.asNode(lla); - updateUsages(lastLocationAccess, newLla); - lastLocationAccess = newLla; + updateUsages(ValueNodeUtil.asNode(lastLocationAccess), ValueNodeUtil.asNode(lla)); + lastLocationAccess = lla; } @NodeIntrinsic diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java index 3e3798cd662c..bb109c7a7d37 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BoxNode.java @@ -36,8 +36,6 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Node.IndirectCanonicalization; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -48,6 +46,8 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.memory.SingleMemoryKill; +import org.graalvm.compiler.nodes.spi.Canonicalizable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.spi.Virtualizable; @@ -65,7 +65,7 @@ * This node represents the boxing of a primitive value. This corresponds to a call to the valueOf * methods in Integer, Long, etc. */ -@NodeInfo(cycles = NodeCycles.CYCLES_8, size = SIZE_16, allowedUsageTypes = {InputType.Memory, InputType.Value}) +@NodeInfo(cycles = NodeCycles.CYCLES_8, size = SIZE_16, allowedUsageTypes = {InputType.Value}) public abstract class BoxNode extends AbstractBoxingNode implements IterableNodeType, VirtualizableAllocation, Lowerable, Canonicalizable.Unary, IndirectCanonicalization { public static final NodeClass TYPE = NodeClass.create(BoxNode.class); @@ -154,7 +154,7 @@ public void virtualize(VirtualizerTool tool) { tool.replaceWithVirtual(newVirtual); } - @NodeInfo(cycles = NodeCycles.CYCLES_8, size = SIZE_8, allowedUsageTypes = {InputType.Memory, InputType.Value}) + @NodeInfo(cycles = NodeCycles.CYCLES_8, size = SIZE_8, allowedUsageTypes = {InputType.Value}) private static class PureBoxNode extends BoxNode { public static final NodeClass TYPE = NodeClass.create(PureBoxNode.class); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnboxNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnboxNode.java index 35dcb908bec3..883ac62796e4 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnboxNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnboxNode.java @@ -29,13 +29,13 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FieldLocationIdentity; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.Canonicalizable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; @@ -49,7 +49,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; -@NodeInfo(cycles = CYCLES_2, size = SIZE_16, allowedUsageTypes = {InputType.Memory, InputType.Value}) +@NodeInfo(cycles = CYCLES_2, size = SIZE_16, allowedUsageTypes = {InputType.Value}) public final class UnboxNode extends AbstractBoxingNode implements Virtualizable, Lowerable, Canonicalizable.Unary { public static final NodeClass TYPE = NodeClass.create(UnboxNode.class); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryKill.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryKill.java index e0c4c01230d2..0d6e46acf625 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryKill.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryKill.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.nodes.memory; +import org.graalvm.compiler.graph.MemoryKillMarker; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.ValueNodeInterface; import org.graalvm.word.LocationIdentity; @@ -36,6 +37,6 @@ * i.e., nodes in the memory graph that mark the last accesses to such a location, like a * {@linkplain MemoryPhiNode} node. */ -public interface MemoryKill extends ValueNodeInterface { +public interface MemoryKill extends ValueNodeInterface, MemoryKillMarker { } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java index b52e59130570..c490fbf9bd3e 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java @@ -33,8 +33,6 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; @@ -46,6 +44,8 @@ import org.graalvm.compiler.nodes.ValueNodeUtil; import org.graalvm.compiler.nodes.memory.MemoryAccess; import org.graalvm.compiler.nodes.memory.MemoryKill; +import org.graalvm.compiler.nodes.spi.Canonicalizable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.spi.Virtualizable; @@ -64,7 +64,7 @@ /** * Compares two arrays with the same length. */ -@NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = NodeSize.SIZE_128, allowedUsageTypes = {Memory}) +@NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = NodeSize.SIZE_128) public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess { public static final NodeClass TYPE = NodeClass.create(ArrayEqualsNode.class); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java index 7d2ece935f3c..f3e41dc2dceb 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; +import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -44,7 +45,7 @@ * Zeros a chunk of memory. */ @NodeInfo(nameTemplate = "ZeroMemory#{p#location/s}", allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_8, size = SIZE_8) -public class ZeroMemoryNode extends FixedAccessNode implements LIRLowerable { +public class ZeroMemoryNode extends FixedAccessNode implements LIRLowerable, SingleMemoryKill { public static final NodeClass TYPE = NodeClass.create(ZeroMemoryNode.class); @Input ValueNode length; @@ -72,4 +73,9 @@ public boolean canNullCheck() { @NodeIntrinsic public static native void zero(Word address, long length, @ConstantNodeParameter boolean isAligned, @ConstantNodeParameter LocationIdentity locationIdentity); + + @Override + public LocationIdentity getKilledLocationIdentity() { + return location; + } } From b0fe420c074f8e34aa60a65f60a8ca0a17f8bd40 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 22 Sep 2021 22:09:40 -0700 Subject: [PATCH 176/681] Add isAssignableFrom checks in edge updates --- .../src/org/graalvm/compiler/graph/Edges.java | 8 ++++++-- .../org/graalvm/compiler/graph/NodeClass.java | 20 +++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java index 19533162e23d..e77fffef5da4 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java @@ -77,6 +77,11 @@ public static NodeList getNodeListUnsafe(Node node, long offset) { return (NodeList) UNSAFE.getObject(node, offset); } + public void putNodeUnsafeChecked(Node node, long offset, Node value, int index) { + verifyUpdateValid(node, index, value); + putNodeUnsafe(node, offset, value); + } + public static void putNodeUnsafe(Node node, long offset, Node value) { UNSAFE.putObject(node, offset, value); } @@ -208,8 +213,7 @@ public void copy(Node fromNode, Node toNode) { * @param value the node to be written to the edge */ public void initializeNode(Node node, int index, Node value) { - verifyUpdateValid(node, index, value); - putNodeUnsafe(node, offsets[index], value); + putNodeUnsafeChecked(node, offsets[index], value, index); } public void initializeList(Node node, int index, NodeList value) { diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java index d1a4c0d57027..17533816a7cf 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java @@ -1254,14 +1254,15 @@ private static void pushAllHelper(NodeStack stack, Node node, long offset) { } public void applySuccessors(Node node, EdgeVisitor consumer) { - applyEdges(node, consumer, this.successorIteration); + applyEdges(node, consumer, this.successorIteration, successors); } public void applyInputs(Node node, EdgeVisitor consumer) { - applyEdges(node, consumer, this.inputsIteration); + applyEdges(node, consumer, this.inputsIteration, inputs); } - private static void applyEdges(Node node, EdgeVisitor consumer, long mask) { + private static void applyEdges(Node node, EdgeVisitor consumer, long mask, Edges edges) { + int index = 0; long myMask = mask; while (myMask != 0) { long offset = (myMask & OFFSET_MASK); @@ -1270,13 +1271,14 @@ private static void applyEdges(Node node, EdgeVisitor consumer, long mask) { if (curNode != null) { Node newNode = consumer.apply(node, curNode); if (newNode != curNode) { - Edges.putNodeUnsafe(node, offset, newNode); + edges.putNodeUnsafeChecked(node, offset, newNode, index); } } } else { applyHelper(node, consumer, offset); } myMask >>>= NEXT_EDGE; + index++; } } @@ -1356,21 +1358,22 @@ private static void registerAtSuccessorsAsPredecessorHelper(Node node, long offs } public boolean replaceFirstInput(Node node, Node key, Node replacement) { - return replaceFirstEdge(node, key, replacement, this.inputsIteration); + return replaceFirstEdge(node, key, replacement, this.inputsIteration, inputs); } public boolean replaceFirstSuccessor(Node node, Node key, Node replacement) { - return replaceFirstEdge(node, key, replacement, this.successorIteration); + return replaceFirstEdge(node, key, replacement, this.successorIteration, successors); } - public static boolean replaceFirstEdge(Node node, Node key, Node replacement, long mask) { + public static boolean replaceFirstEdge(Node node, Node key, Node replacement, long mask, Edges edges) { + int index = 0; long myMask = mask; while (myMask != 0) { long offset = (myMask & OFFSET_MASK); if ((myMask & LIST_MASK) == 0) { Object curNode = Edges.getNodeUnsafe(node, offset); if (curNode == key) { - Edges.putNodeUnsafe(node, offset, replacement); + edges.putNodeUnsafeChecked(node, offset, replacement, index); return true; } } else { @@ -1380,6 +1383,7 @@ public static boolean replaceFirstEdge(Node node, Node key, Node replacement, lo } } myMask >>>= NEXT_EDGE; + index++; } return false; } From 05ec8fc466943966136821022774785caa7767c5 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Mon, 27 Sep 2021 16:22:20 -0700 Subject: [PATCH 177/681] Add check for implementing either SingleMemoryKill or MultiMemoryKill --- .../graalvm/compiler/core/test/CheckGraalInvariants.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java index 66219aeaec90..bd0cc6fc1601 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java @@ -74,6 +74,9 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.java.LoadFieldNode; +import org.graalvm.compiler.nodes.memory.MemoryKill; +import org.graalvm.compiler.nodes.memory.MultiMemoryKill; +import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionDescriptor; @@ -579,6 +582,10 @@ private static void checkClass(Class c, MetaAccessProvider metaAccess, List verifier : verifiers) { verifier.verifyClass(c, metaAccess); From fd3ae9cca0aca715bd6a4fb0556ca8cdd50f5646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Mon, 27 Sep 2021 17:06:22 +0200 Subject: [PATCH 178/681] Don't create DebugContext when scanning objects --- .../com/oracle/graal/pointsto/ObjectScanner.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java index b633afcb2b81..5d33edfcaf97 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java @@ -30,10 +30,14 @@ import java.util.Comparator; import java.util.Deque; import java.util.IdentityHashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.atomic.AtomicInteger; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.word.WordBase; import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; @@ -42,6 +46,7 @@ import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.graal.pointsto.util.CompletionExecutor; +import com.oracle.graal.pointsto.util.CompletionExecutor.DebugContextRunnable; import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.meta.JavaConstant; @@ -102,12 +107,19 @@ public void scanBootImageHeapRoots(Comparator fieldComparator, Co private void execute(Runnable runnable) { if (executor != null) { - executor.execute(debug -> runnable.run()); + executor.execute((ObjectScannerRunnable) debug -> runnable.run()); } else { runnable.run(); } } + private interface ObjectScannerRunnable extends DebugContextRunnable { + @Override + default DebugContext getDebug(OptionValues options, List factories) { + return DebugContext.disabled(null); + } + } + private void scanEmbeddedRoot(JavaConstant root, BytecodePosition position) { AnalysisMethod method = (AnalysisMethod) position.getMethod(); try { @@ -256,7 +268,7 @@ public final void scanConstant(JavaConstant value, ScanReason reason, WorklistEn scannedObjects.release(valueObj); WorklistEntry worklistEntry = new WorklistEntry(previous, value, reason); if (executor != null) { - executor.execute(debug -> doScan(worklistEntry)); + executor.execute((ObjectScannerRunnable) debug -> doScan(worklistEntry)); } else { worklist.push(worklistEntry); } From 75a32e3a6b04ff49e1c84cc83aa6520f2a5dcd66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Galder=20Zamarren=CC=83o?= Date: Tue, 28 Sep 2021 10:58:33 +0200 Subject: [PATCH 179/681] Add call tree csv links for easier imports into graph db --- .../pointsto/reports/CallTreePrinter.java | 51 ++++++++++++------- .../graal/pointsto/reports/ReportUtils.java | 3 +- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/CallTreePrinter.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/CallTreePrinter.java index a4b3a12e2648..8f0c4d7ed3a6 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/CallTreePrinter.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/CallTreePrinter.java @@ -31,7 +31,12 @@ import static com.oracle.graal.pointsto.reports.ReportUtils.invokeComparator; import static com.oracle.graal.pointsto.reports.ReportUtils.methodComparator; +import java.io.IOException; import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; @@ -46,6 +51,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -333,26 +339,33 @@ private static void printCsvFiles(Map methodToNode, walkNodes(node, directEdges, virtualEdges, overridenByEdges, virtualNodes, nonVirtualNodes, virtualNodeId); } - ReportUtils.report("call tree for vm entry point", reportsPath, "csv_call_tree_vm_" + reportName, "csv", - CallTreePrinter::printVMEntryPoint); - - ReportUtils.report("call tree for methods", reportsPath, "csv_call_tree_methods_" + reportName, "csv", - writer -> printMethodNodes(methodToNode.values(), writer)); - - ReportUtils.report("call tree for virtual methods", reportsPath, "csv_call_tree_virtual_methods_" + reportName, "csv", - writer -> printVirtualNodes(virtualNodes, writer)); - - ReportUtils.report("call tree for entry points", reportsPath, "csv_call_tree_entry_points_" + reportName, "csv", - writer -> printEntryPointIds(entryPointIds, writer)); - - ReportUtils.report("call tree for direct edges", reportsPath, "csv_call_tree_direct_edges_" + reportName, "csv", - writer -> printBciEdges(directEdges, writer)); - - ReportUtils.report("call tree for overriden by edges", reportsPath, "csv_call_tree_override_by_edges_" + reportName, "csv", - writer -> printNonBciEdges(overridenByEdges, writer)); + toCsvFile("call tree for vm entry point", reportsPath, "csv_call_tree_vm", reportName, CallTreePrinter::printVMEntryPoint); + toCsvFile("call tree for methods", reportsPath, "csv_call_tree_methods", reportName, writer -> printMethodNodes(methodToNode.values(), writer)); + toCsvFile("call tree for virtual methods", reportsPath, "csv_call_tree_virtual_methods", reportName, writer -> printVirtualNodes(virtualNodes, writer)); + toCsvFile("call tree for entry points", reportsPath, "csv_call_tree_entry_points", reportName, writer -> printEntryPointIds(entryPointIds, writer)); + toCsvFile("call tree for direct edges", reportsPath, "csv_call_tree_direct_edges", reportName, writer -> printBciEdges(directEdges, writer)); + toCsvFile("call tree for overriden by edges", reportsPath, "csv_call_tree_override_by_edges", reportName, writer -> printNonBciEdges(overridenByEdges, writer)); + toCsvFile("call tree for virtual edges", reportsPath, "csv_call_tree_virtual_edges", reportName, writer -> printBciEdges(virtualEdges, writer)); + } + + private static void toCsvFile(String description, String reportsPath, String prefix, String reportName, Consumer reporter) { + final String name = prefix + "_" + reportName; + final String csvFile = ReportUtils.report(description, reportsPath, name, "csv", reporter); + final Path csvLink = Paths.get(reportsPath).resolve(prefix + ".csv"); + + if (Files.exists(csvLink, LinkOption.NOFOLLOW_LINKS)) { + try { + Files.delete(csvLink); + } catch (IOException e) { + // Ignore + } + } - ReportUtils.report("call tree for virtual edges", reportsPath, "csv_call_tree_virtual_edges_" + reportName, "csv", - writer -> printBciEdges(virtualEdges, writer)); + try { + Files.createSymbolicLink(csvLink, Paths.get(csvFile)); + } catch (IOException e) { + throw new RuntimeException(e); + } } private static void printVMEntryPoint(PrintWriter writer) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/ReportUtils.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/ReportUtils.java index 8b743b0544a0..63e4a8218dfa 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/ReportUtils.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/ReportUtils.java @@ -75,10 +75,11 @@ public class ReportUtils { * @param extension the extension of the report * @param reporter a consumer that writes to a PrintWriter */ - public static void report(String description, String path, String name, String extension, Consumer reporter) { + public static String report(String description, String path, String name, String extension, Consumer reporter) { String fileName = timeStampedFileName(name, extension); Path reportDir = Paths.get(path); reportImpl(description, reportDir, fileName, reporter); + return fileName; } public static String timeStampedFileName(String name, String extension) { From 83464af7dd45f84b406fe4abc2918a93734975a5 Mon Sep 17 00:00:00 2001 From: "thomas.garcia" Date: Tue, 28 Sep 2021 11:45:57 +0200 Subject: [PATCH 180/681] Overlays for Reference.refersTo --- espresso/mx.espresso/suite.py | 33 ++++++++++++++ .../espresso/overlay/ReferenceSupport.java | 38 ++++++++++++++++ .../espresso/overlay/ReferenceSupport.java | 44 +++++++++++++++++++ .../com/oracle/truffle/espresso/vm/VM.java | 20 ++++++--- 4 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 espresso/src/com.oracle.truffle.espresso.jdk17/src/com/oracle/truffle/espresso/overlay/ReferenceSupport.java create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/overlay/ReferenceSupport.java diff --git a/espresso/mx.espresso/suite.py b/espresso/mx.espresso/suite.py index 030b5f9e1f77..211446bf9dbd 100644 --- a/espresso/mx.espresso/suite.py +++ b/espresso/mx.espresso/suite.py @@ -121,6 +121,39 @@ "checkPackagePrefix": False, # java.lang.ref.PublicFinalReference }, + "com.oracle.truffle.espresso.jdk8": { + "subDir": "src", + "sourceDirs": ["src"], + "overlayTarget": "com.oracle.truffle.espresso", + "checkPackagePrefix": "false", + "checkstyle": "com.oracle.truffle.espresso", + "javaCompliance": "8", + }, + + "com.oracle.truffle.espresso.jdk11": { + "subDir": "src", + "sourceDirs": ["src"], + "overlayTarget": "com.oracle.truffle.espresso", + "checkPackagePrefix": "false", + "multiReleaseJarVersion": "11", + "checkstyle": "com.oracle.truffle.espresso", + "javaCompliance": "11+", + }, + + "com.oracle.truffle.espresso.jdk17": { + "subDir": "src", + "sourceDirs": ["src"], + "overlayTarget": "com.oracle.truffle.espresso", + "dependencies": [ + "com.oracle.truffle.espresso", + ], + "checkPackagePrefix": "false", + "multiReleaseJarVersion": "17", + "checkstyle": "com.oracle.truffle.espresso", + "javaCompliance": "17+", + }, + + "com.oracle.truffle.espresso.processor": { "subDir": "src", "sourceDirs": ["src"], diff --git a/espresso/src/com.oracle.truffle.espresso.jdk17/src/com/oracle/truffle/espresso/overlay/ReferenceSupport.java b/espresso/src/com.oracle.truffle.espresso.jdk17/src/com/oracle/truffle/espresso/overlay/ReferenceSupport.java new file mode 100644 index 000000000000..9800ede6ec92 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso.jdk17/src/com/oracle/truffle/espresso/overlay/ReferenceSupport.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, 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. + * + * 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.truffle.espresso.overlay; + +import java.lang.ref.Reference; + +import com.oracle.truffle.espresso.runtime.StaticObject; + +public class ReferenceSupport { + public static boolean phantomReferenceRefersTo(Reference ref, StaticObject object) { + return ref.refersTo(object); + } + + public static boolean referenceRefersTo(Reference ref, StaticObject object) { + return ref.refersTo(object); + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/overlay/ReferenceSupport.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/overlay/ReferenceSupport.java new file mode 100644 index 000000000000..009da4415068 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/overlay/ReferenceSupport.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, 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. + * + * 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.truffle.espresso.overlay; + +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; + +import com.oracle.truffle.espresso.runtime.StaticObject; + +public class ReferenceSupport { + @SuppressWarnings("unused") + public static boolean phantomReferenceRefersTo(Reference ref, StaticObject object) { + assert (ref instanceof PhantomReference); + return false; + } + + public static boolean referenceRefersTo(Reference ref, StaticObject object) { + assert !(ref instanceof PhantomReference); + StaticObject value = ref.get(); + value = value == null ? StaticObject.NULL : value; + return value == object; + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java index 8879610cd08b..0611052872ce 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java @@ -128,6 +128,7 @@ import com.oracle.truffle.espresso.nodes.EspressoRootNode; import com.oracle.truffle.espresso.nodes.interop.ToEspressoNode; import com.oracle.truffle.espresso.nodes.interop.ToEspressoNodeGen; +import com.oracle.truffle.espresso.overlay.ReferenceSupport; import com.oracle.truffle.espresso.runtime.Attribute; import com.oracle.truffle.espresso.runtime.Classpath; import com.oracle.truffle.espresso.runtime.EspressoContext; @@ -138,6 +139,7 @@ import com.oracle.truffle.espresso.runtime.MethodHandleIntrinsics; import com.oracle.truffle.espresso.runtime.StaticObject; import com.oracle.truffle.espresso.substitutions.CallableFromNative; +import com.oracle.truffle.espresso.substitutions.EspressoReference; import com.oracle.truffle.espresso.substitutions.GenerateNativeEnv; import com.oracle.truffle.espresso.substitutions.Inject; import com.oracle.truffle.espresso.substitutions.JavaType; @@ -3432,19 +3434,21 @@ public boolean JVM_HasReferencePendingList() { return getContext().hasReferencePendingList(); } + @SuppressWarnings({"rawtypes", "unchecked"}) @VmImpl(isJni = true) - public boolean JVM_PhantomReferenceRefersTo(@JavaType(Reference.class) StaticObject ref, @SuppressWarnings("unused") @JavaType(Object.class) StaticObject object, + public boolean JVM_PhantomReferenceRefersTo(@JavaType(Reference.class) StaticObject ref, @JavaType(Object.class) StaticObject object, @Inject SubstitutionProfiler profiler) { if (StaticObject.isNull(ref)) { profiler.profile(0); getMeta().throwNullPointerException(); } - assert InterpreterToVM.instanceOf(ref, getMeta().java_lang_ref_PhantomReference) : "Cannot call Reference.get on PhantomReference"; - // At this point, we would need to call the host's PhantomReference.refersTo() method, but - // it is not available in Java 8 or 11. - return false; + EspressoReference host = (EspressoReference) getMeta().HIDDEN_HOST_REFERENCE.getHiddenObject(ref); + assert host instanceof Reference; + // Call host's refersTo. Not available in 8 or 11. + return ReferenceSupport.phantomReferenceRefersTo((Reference) host, object); } + @SuppressWarnings({"rawtypes", "unchecked"}) @VmImpl(isJni = true) public boolean JVM_ReferenceRefersTo(@JavaType(Reference.class) StaticObject ref, @JavaType(Object.class) StaticObject object, @Inject SubstitutionProfiler profiler) { @@ -3452,8 +3456,10 @@ public boolean JVM_ReferenceRefersTo(@JavaType(Reference.class) StaticObject ref profiler.profile(0); getMeta().throwNullPointerException(); } - assert !InterpreterToVM.instanceOf(ref, getMeta().java_lang_ref_PhantomReference) : "Cannot call Reference.get on PhantomReference"; - return Target_java_lang_ref_Reference.get(ref, getMeta()) == object; + EspressoReference host = (EspressoReference) getMeta().HIDDEN_HOST_REFERENCE.getHiddenObject(ref); + assert host instanceof Reference; + // Call host's refersTo. Not available in 8 or 11. + return ReferenceSupport.referenceRefersTo((Reference) host, object); } @VmImpl(isJni = true) From a7da464c538fc039289954af837c552c15cdbf88 Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Tue, 2 Mar 2021 08:54:17 +0100 Subject: [PATCH 181/681] Support illegal constant types --- .../oracle/svm/core/graal/llvm/LLVMGenerator.java | 4 ++++ .../oracle/svm/core/graal/llvm/NodeLLVMBuilder.java | 12 ++++++++++-- .../svm/core/graal/llvm/util/LLVMIRBuilder.java | 9 +++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java index c120085082ae..fc117c5a3ae1 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java @@ -63,6 +63,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.LIRKindTool; +import org.graalvm.compiler.core.common.type.IllegalStamp; import org.graalvm.compiler.core.common.type.RawPointerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -365,6 +366,9 @@ LLVMTypeRef getLLVMType(Stamp stamp) { if (stamp instanceof RawPointerStamp) { return builder.rawPointerType(); } + if (stamp instanceof IllegalStamp) { + return builder.undefType(); + } return getLLVMType(getTypeKind(stamp.javaType(getMetaAccess()), false), stamp instanceof NarrowOopStamp); } diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java index 8e9a5f4e1936..0b2ea1f335e3 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java @@ -35,6 +35,8 @@ import java.util.Map; import java.util.Set; +import jdk.vm.ci.meta.PlatformKind; +import jdk.vm.ci.meta.ValueKind; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.Condition; @@ -760,8 +762,14 @@ public Value setResult(ValueNode node, Value operand) { if (operand instanceof LLVMValueWrapper) { llvmOperand = (LLVMValueWrapper) operand; } else if (operand instanceof ConstantValue) { - /* This only happens when emitting null object constants */ - llvmOperand = new LLVMVariable(builder.constantNull(((LLVMKind) operand.getPlatformKind()).get())); + /* This only happens when emitting null or illegal object constants */ + PlatformKind kind = operand.getPlatformKind(); + if (kind instanceof LLVMKind) { + llvmOperand = new LLVMVariable(builder.constantNull(((LLVMKind) kind).get())); + } else { + assert kind == ValueKind.Illegal.getPlatformKind(); + llvmOperand = new LLVMVariable(builder.getUndef()); + } } else if (operand instanceof LLVMAddressValue) { LLVMAddressValue addressValue = (LLVMAddressValue) operand; Value wrappedBase = addressValue.getBase(); diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/util/LLVMIRBuilder.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/util/LLVMIRBuilder.java index 10604167a0ac..55fa100c396d 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/util/LLVMIRBuilder.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/util/LLVMIRBuilder.java @@ -464,6 +464,11 @@ private LLVMTypeRef metadataType() { return LLVM.LLVMMetadataTypeInContext(context); } + public LLVMTypeRef undefType() { + /* Use a non-standard integer size to make sure the value is never used in an instruction */ + return integerType(42); + } + public static boolean compatibleTypes(LLVMTypeRef a, LLVMTypeRef b) { int aKind = LLVM.LLVMGetTypeKind(a); int bKind = LLVM.LLVMGetTypeKind(b); @@ -655,6 +660,10 @@ public void setValueName(LLVMValueRef value, String name) { LLVM.LLVMSetValueName(value, name); } + public LLVMValueRef getUndef() { + return LLVM.LLVMGetUndef(undefType()); + } + /* Control flow */ public LLVMValueRef buildCall(LLVMValueRef callee, LLVMValueRef... args) { From de91bd789151d02b2292be96687681ede9717c67 Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Tue, 28 Sep 2021 12:18:29 +0200 Subject: [PATCH 182/681] Reinitialize ThreadLocalRandom at runtime for JDK 17 or higher --- .../src/com/oracle/svm/hosted/jdk/JDKRegistrations.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JDKRegistrations.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JDKRegistrations.java index 0cb6f66e0d64..fc7f993d28d8 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JDKRegistrations.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JDKRegistrations.java @@ -62,6 +62,9 @@ public void duringSetup(DuringSetupAccess a) { */ rerunClassInit(a, "sun.nio.ch.UnixDomainSockets"); } + if (JavaVersionUtil.JAVA_SPEC >= 17) { + rerunClassInit(a, "java.util.concurrent.ThreadLocalRandom$ThreadLocalRandomProxy"); + } /* * Re-initialize the registered shutdown hooks, because any hooks registered during native From 3e90ff7d8264bef580eb89c1dd4ea53422d369b8 Mon Sep 17 00:00:00 2001 From: "thomas.garcia" Date: Tue, 28 Sep 2021 13:07:17 +0200 Subject: [PATCH 183/681] Invalidate interface methods leaf assumptions during itable creation --- .../espresso/impl/InterfaceTables.java | 47 ++++++++++++++++++- .../oracle/truffle/espresso/impl/Method.java | 9 +--- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/InterfaceTables.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/InterfaceTables.java index b31c19e8e121..706a6fb725c7 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/InterfaceTables.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/InterfaceTables.java @@ -197,6 +197,7 @@ public static CreationResult create(ObjectKlass superKlass, ObjectKlass[] superI * @return the final itable */ public static Method[][] fixTables(Method[] vtable, Method[] mirandas, Method[] declaredMethods, Entry[][] tables, ObjectKlass[] iklassTable) { + assert tables.length == iklassTable.length; ArrayList tmpTables = new ArrayList<>(); // Second step @@ -205,12 +206,54 @@ public static Method[][] fixTables(Method[] vtable, Method[] mirandas, Method[] fixVTable(tables[i], vtable, mirandas, declaredMethods, iklassTable[i].getInterfaceMethodsTable()); } // Third step - for (Entry[] entries : tables) { - tmpTables.add(getITable(entries, vtable, mirandas, declaredMethods)); + for (int tableIndex = 0; tableIndex < tables.length; tableIndex++) { + Entry[] entries = tables[tableIndex]; + Method[] itable = getITable(entries, vtable, mirandas, declaredMethods); + tmpTables.add(itable); + + // Update leaf assumptions for super interfaces + ObjectKlass currInterface = iklassTable[tableIndex]; + updateLeafAssumptions(itable, currInterface); + } return tmpTables.toArray(EMPTY_METHOD_DUAL_ARRAY); } + /** + * Note: Leaf assumptions are not invalidated on creation of an interface. This means that in + * the following example: + * + *
+     * interface A {
+     *     default void m() {
+     *     }
+     * }
+     * 
+     * interface B extends A {
+     *     default void m() {
+     *     }
+     * }
+     * 
+ * + * Unless a concrete class that implements B is loaded, the leaf assumption for A.m() will not + * be invalidated. + */ + private static void updateLeafAssumptions(Method[] itable, ObjectKlass currInterface) { + for (int methodIndex = 0; methodIndex < itable.length; methodIndex++) { + Method m = itable[methodIndex]; + // This class' itable entry for this method is not the interface's declared method. + if (m.getDeclaringKlass() != currInterface) { + Method intfMethod = currInterface.getInterfaceMethodsTable()[methodIndex]; + // sanity checks + assert intfMethod.getDeclaringKlass() == currInterface; + assert m.canOverride(intfMethod) && m.getName() == intfMethod.getName() && m.getRawSignature() == intfMethod.getRawSignature(); + if (intfMethod.leafAssumption()) { + intfMethod.invalidateLeaf(); + } + } + } + } + // Actual implementations private CreationResult create() { diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java index b6b86f7830cc..613c06fa6562 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java @@ -263,13 +263,8 @@ private Method(Method method, CodeAttribute split) { initRefKind(); this.proxy = null; - if (getDeclaringKlass().isInterface() || isAbstract()) { - /* - * TODO(peterssen): GR-33781 Leaf method assumption cannot be trusted for default - * methods. - * - * Also disabled for abstract methods to reduce footprint. - */ + if (isAbstract()) { + // Disabled for abstract methods to reduce footprint. this.isLeaf = NeverValidAssumption.INSTANCE; } else if (isStatic() || isPrivate() || isFinalFlagSet() || getDeclaringKlass().isFinalFlagSet()) { // Nothing to assume, spare an assumption. From 0794624cf1999ba0ef233f74db343211b4c1e8bd Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 27 Sep 2021 13:16:40 +0200 Subject: [PATCH 184/681] Avoid createCallTarget() in Truffle API. --- .../benchmark/EncapsulatingNodeBenchmark.java | 9 ++- .../api/benchmark/EngineBenchmark.java | 7 +- .../benchmark/InterpreterCallBenchmark.java | 8 +-- .../api/debug/test/DebugStackFrameTest.java | 15 ++-- .../api/debug/test/DebugValueTest.java | 6 +- .../InstrumentablePositionsTestLanguage.java | 3 +- .../debug/test/NoCallNodeTestLanguage.java | 5 +- .../debug/test/TestDebugBuggyLanguage.java | 7 +- .../test/TestDebugNoContentLanguage.java | 3 +- .../test/TestExecutableNamesLanguage.java | 11 ++- .../api/debug/test/TestFramesRootTag.java | 10 +-- .../debug/test/TestLazyParsingLanguage.java | 5 +- .../test/TestNonInteractiveInlineParse.java | 6 +- .../api/debug/test/TestReceiverLanguage.java | 3 +- .../debug/test/ValueLanguageLegacyTest.java | 5 +- .../api/debug/test/ValueLanguageTest.java | 5 +- .../truffle/api/dsl/test/AOTSupportTest.java | 2 +- .../truffle/api/dsl/test/ArrayTest.java | 3 +- .../truffle/api/dsl/test/CachedTest.java | 11 ++- .../api/dsl/test/CachedThreadSafetyTest.java | 3 +- .../truffle/api/dsl/test/TestHelper.java | 8 +-- .../api/dsl/test/examples/AOTTutorial.java | 7 +- .../api/dsl/test/examples/ExampleNode.java | 5 +- .../test/AllocationReporterTest.java | 5 +- .../test/CompileImmediatelyCheck.java | 5 +- .../test/ContextInterruptStandaloneTest.java | 9 ++- .../test/ContextsEventsTest.java | 5 +- .../instrumentation/test/DeadlockTest.java | 13 ++-- .../test/FindSourcesVisitorNestingTest.java | 9 ++- .../api/instrumentation/test/GR25718Test.java | 11 ++- .../test/InstrumentableNodeTest.java | 5 +- .../test/InstrumentationTest.java | 14 ++-- .../test/InstrumentationTestLanguage.java | 6 +- .../test/InstrumentationUpdateTest.java | 3 +- ...aterializationAssertionsViolationTest.java | 5 +- .../test/ParsingFromInstrumentTest.java | 22 +++--- .../test/SourceListenerTest.java | 19 +++--- .../test/SourceSectionFilterTest.java | 3 +- .../test/SourceSectionListenerTest.java | 5 +- .../api/instrumentation/test/TagsTest.java | 11 ++- .../test/ThreadsActivationListenerTest.java | 16 ++--- .../test/TruffleContextTest.java | 11 ++- .../test/VariablesScopeLegacyTest.java | 3 +- .../test/VariablesScopeTest.java | 12 ++-- .../instrumentation/InstrumentableNode.java | 9 ++- .../instrumentation/LoadSourceListener.java | 8 +-- .../LoadSourceSectionListener.java | 8 +-- .../library/test/examples/ArrayStrategy1.java | 3 +- .../library/test/examples/ArrayStrategy2.java | 5 +- .../library/test/examples/ArrayStrategy3.java | 3 +- .../test/examples/DynamicDispatchExample.java | 5 +- .../test/examples/TaintTrackingExample.java | 5 +- .../truffle/api/test/ArgumentsTest.java | 6 +- .../api/test/AssumptionInvalidationTest.java | 2 +- .../com/oracle/truffle/api/test/CallTest.java | 15 ++-- .../truffle/api/test/ChildNodeTest.java | 5 +- .../truffle/api/test/ChildrenNodesTest.java | 8 +-- .../api/test/CompileImmediatelyCheck.java | 5 +- .../truffle/api/test/FinalFieldTest.java | 7 +- .../test/FrameSlotTypeSpecializationTest.java | 7 +- .../oracle/truffle/api/test/FrameTest.java | 7 +- .../api/test/InterfaceChildFieldTest.java | 8 +-- .../oracle/truffle/api/test/IteratorTest.java | 2 +- .../api/test/LegacyTruffleExceptionTest.java | 14 ++-- .../oracle/truffle/api/test/LoopNodeTest.java | 2 +- .../oracle/truffle/api/test/ReplaceTest.java | 5 +- .../test/ReturnTypeSpecializationTest.java | 7 +- .../oracle/truffle/api/test/RootNodeTest.java | 30 ++++---- .../truffle/api/test/StackTraceTest.java | 2 +- .../truffle/api/test/ThreadSafetyTest.java | 8 +-- .../api/test/TruffleExceptionTest.java | 66 +++++++++--------- .../api/test/TruffleSafepointTest.java | 5 +- .../oracle/truffle/api/test/host/GR31558.java | 7 +- .../api/test/host/HostExceptionTest.java | 3 +- .../api/test/host/MultiClassLoaderTest.java | 7 +- .../truffle/api/test/nodes/BlockNodeTest.java | 3 +- .../nodes/EncapsulatedNodeLegacyTest.java | 17 ++--- .../api/test/nodes/EncapsulatedNodeTest.java | 25 +++---- .../truffle/api/test/parser/PEParser.java | 2 +- .../test/polyglot/AbstractPolyglotTest.java | 4 +- .../api/test/polyglot/ChildContextTest.java | 3 +- .../api/test/polyglot/ContextAPITest.java | 13 ++-- .../ContextAPITestInternalLanguage.java | 3 +- .../test/polyglot/ContextAPITestLanguage.java | 5 +- .../api/test/polyglot/ContextPolicyTest.java | 7 +- .../polyglot/ContextPolyglotAccessTest.java | 3 +- ...ntextPreInitializationNativeImageTest.java | 5 +- .../ContextPreInitializationTest.java | 5 +- .../api/test/polyglot/EngineAPITest.java | 2 +- .../test/polyglot/EngineAPITestLanguage.java | 3 +- .../api/test/polyglot/FileSystemsTest.java | 5 +- .../api/test/polyglot/HostStackTraceTest.java | 3 +- .../test/polyglot/InteractiveEvalTest.java | 9 ++- .../test/polyglot/LanguageSPIOrderTest.java | 3 +- .../api/test/polyglot/LanguageSPITest.java | 31 ++++----- .../polyglot/LanguageSPITestLanguage.java | 5 +- .../api/test/polyglot/LoggingTest.java | 3 +- .../api/test/polyglot/MIMETypeTest.java | 9 ++- .../test/polyglot/MultiThreadedCloseTest.java | 16 +++-- .../test/polyglot/MultiThreadedLanguage.java | 5 +- .../test/polyglot/PolyglotCachingTest.java | 9 ++- .../test/polyglot/PolyglotExceptionTest.java | 15 ++-- .../api/test/polyglot/RequireContextTest.java | 16 ++--- .../RetainedSizeContextBoundaryTest.java | 8 +-- .../test/polyglot/ScopedViewLegacyTest.java | 2 +- .../api/test/polyglot/ScopedViewTest.java | 2 +- .../test/polyglot/SourceAPITestLanguage.java | 3 +- .../api/test/polyglot/ValueAPITest.java | 3 +- .../polyglot/ValueHostConversionTest.java | 68 +++++++++---------- .../com/oracle/truffle/api/CallTarget.java | 5 +- .../oracle/truffle/api/RootCallTarget.java | 4 +- .../oracle/truffle/api/TruffleLanguage.java | 8 +-- .../truffle/api/impl/DefaultCallTarget.java | 3 +- .../api/impl/DefaultTruffleRuntime.java | 2 +- .../oracle/truffle/api/nodes/RootNode.java | 15 ++-- 115 files changed, 413 insertions(+), 552 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/EncapsulatingNodeBenchmark.java b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/EncapsulatingNodeBenchmark.java index 17991f066e81..3556e4293811 100644 --- a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/EncapsulatingNodeBenchmark.java +++ b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/EncapsulatingNodeBenchmark.java @@ -48,7 +48,6 @@ import org.openjdk.jmh.annotations.TearDown; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.EncapsulatingNodeReference; import com.oracle.truffle.api.nodes.Node; @@ -69,7 +68,7 @@ public static class PushPopOldCompiled { context.initialize(TEST_LANGUAGE); } final Integer intValue = 42; - final CallTarget callTarget = Truffle.getRuntime().createCallTarget(new RootNode(null) { + final CallTarget callTarget = new RootNode(null) { private final Integer constant = 42; @@ -84,7 +83,7 @@ public Object execute(VirtualFrame frame) { NodeUtil.popEncapsulatingNode(prev0); return constant; } - }); + }.getCallTarget(); private final Node node = new Node() { }; @@ -143,7 +142,7 @@ public static class PushPopNewCompiled { context.initialize(TEST_LANGUAGE); } final Integer intValue = 42; - final CallTarget callTarget = Truffle.getRuntime().createCallTarget(new RootNode(null) { + final CallTarget callTarget = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { @@ -162,7 +161,7 @@ public Object execute(VirtualFrame frame) { nodeRef0.set(prev0); return null; } - }); + }.getCallTarget(); final Node node = new Node() { }; diff --git a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/EngineBenchmark.java b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/EngineBenchmark.java index 8838052dbe5a..fa7dcd2d6c88 100644 --- a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/EngineBenchmark.java +++ b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/EngineBenchmark.java @@ -60,7 +60,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.ContextReference; @@ -329,7 +328,7 @@ public static class CallTargetCallState { context.initialize(TEST_LANGUAGE); } final Integer intValue = 42; - final CallTarget callTarget = Truffle.getRuntime().createCallTarget(new RootNode(null) { + final CallTarget callTarget = new RootNode(null) { private final Integer constant = 42; @@ -337,7 +336,7 @@ public static class CallTargetCallState { public Object execute(VirtualFrame frame) { return constant; } - }); + }.getCallTarget(); @TearDown public void tearDown() { @@ -489,7 +488,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { } else { result = getCurrentContext(BenchmarkTestLanguage.class).object; } - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(result)); + return RootNode.createConstantNode(result).getCallTarget(); } } diff --git a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/InterpreterCallBenchmark.java b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/InterpreterCallBenchmark.java index 7ba718f6d1ec..bb89d833be8b 100644 --- a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/InterpreterCallBenchmark.java +++ b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/InterpreterCallBenchmark.java @@ -86,7 +86,7 @@ public static class BenchmarkState { for (int i = 0; i < ROOT_CLASSES.length; i++) { Class rootClass = ROOT_CLASSES[i]; rootNodes[i] = createRootNode(rootClass); - callTargets[i] = Truffle.getRuntime().createCallTarget(rootNodes[i]); + callTargets[i] = rootNodes[i].getCallTarget(); directCallNodes[i] = Truffle.getRuntime().createDirectCallNode(callTargets[i]); } @@ -138,7 +138,7 @@ public static class FirstCallState extends BenchmarkState { public void setup() { for (int i = 0; i < TARGETS; i++) { AbstractRootNode rootNode = createRootNode(ROOT_CLASSES[i % ROOT_CLASSES_LENGTH]); - callTargets[i] = Truffle.getRuntime().createCallTarget(rootNode); + callTargets[i] = rootNode.getCallTarget(); } } @@ -186,8 +186,8 @@ public int secondCall(SecondCallState state) { } @Benchmark - public Object callTargetCreate() { - return Truffle.getRuntime().createCallTarget(new RootNode1()); + public Object callTargetCreation() { + return new RootNode1().getCallTarget(); } @Benchmark diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/DebugStackFrameTest.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/DebugStackFrameTest.java index 3eb7b0365373..377e53fec570 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/DebugStackFrameTest.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/DebugStackFrameTest.java @@ -49,11 +49,11 @@ import static org.junit.Assert.fail; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; -import com.oracle.truffle.api.frame.FrameInstance; -import com.oracle.truffle.api.instrumentation.test.InstrumentationTestLanguage; +import org.graalvm.polyglot.Source; import org.junit.Test; import com.oracle.truffle.api.CallTarget; @@ -67,6 +67,7 @@ import com.oracle.truffle.api.debug.DebuggerSession; import com.oracle.truffle.api.debug.SuspendedEvent; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameInstance; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.FrameSlotTypeException; @@ -76,14 +77,12 @@ import com.oracle.truffle.api.instrumentation.ProbeNode; import com.oracle.truffle.api.instrumentation.StandardTags; import com.oracle.truffle.api.instrumentation.Tag; +import com.oracle.truffle.api.instrumentation.test.InstrumentationTestLanguage; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.test.polyglot.ProxyLanguage; -import java.util.Arrays; - -import org.graalvm.polyglot.Source; public class DebugStackFrameTest extends AbstractDebugTest { @@ -592,7 +591,7 @@ static final class TestStackLanguage extends ProxyLanguage { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { com.oracle.truffle.api.source.Source source = request.getSource(); - return Truffle.getRuntime().createCallTarget(new TestStackRootNode(languageInstance, source, DEPTH)); + return new TestStackRootNode(languageInstance, source, DEPTH).getCallTarget(); } private static final class TestStackRootNode extends RootNode { @@ -652,7 +651,7 @@ protected List findAsynchronousFrames(Frame frame) { List asyncStack = new ArrayList<>(depth); TestStackRootNode asyncRoot = new TestStackRootNode(language, rootSection.getSource(), depth - 1); do { - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(asyncRoot); + RootCallTarget callTarget = asyncRoot.getCallTarget(); TestNode leaf = asyncRoot.child; while (leaf.testChild != null) { leaf = leaf.testChild; @@ -678,7 +677,7 @@ protected List findAsynchronousFrames(Frame frame) { private TestNode createTestNodes() { TestNode node; if (depth > 0) { - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(new TestStackRootNode(language, rootSection.getSource(), depth - 1)); + RootCallTarget callTarget = new TestStackRootNode(language, rootSection.getSource(), depth - 1).getCallTarget(); DirectCallNode callNode = Truffle.getRuntime().createDirectCallNode(callTarget); if (depth % 2 == 0) { node = new TestNode() { diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/DebugValueTest.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/DebugValueTest.java index d2780a976541..11783f784388 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/DebugValueTest.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/DebugValueTest.java @@ -52,14 +52,12 @@ import java.util.List; import java.util.Map; +import org.graalvm.collections.Pair; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; -import org.graalvm.collections.Pair; - import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.DebugStackFrame; import com.oracle.truffle.api.debug.DebugValue; @@ -318,7 +316,7 @@ public void testNull() { ProxyLanguage.setDelegate(new ProxyLanguage() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance)); + return new TestRootNode(languageInstance).getCallTarget(); } final class TestRootNode extends RootNode { diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/InstrumentablePositionsTestLanguage.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/InstrumentablePositionsTestLanguage.java index 07e625bcc223..a524a3265049 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/InstrumentablePositionsTestLanguage.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/InstrumentablePositionsTestLanguage.java @@ -54,7 +54,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.Option; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.frame.VirtualFrame; @@ -287,7 +286,7 @@ TestNode getNode() { synchronized (this) { if (node == null) { if (hasTag('F')) { - RootCallTarget taget = Truffle.getRuntime().createCallTarget(new TestRootNode(lang, this)); + RootCallTarget taget = new TestRootNode(lang, this).getCallTarget(); node = new CallNode(taget); } else { node = new BaseNode(this); diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/NoCallNodeTestLanguage.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/NoCallNodeTestLanguage.java index d90b11b689e5..f6dcd648f169 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/NoCallNodeTestLanguage.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/NoCallNodeTestLanguage.java @@ -41,7 +41,6 @@ package com.oracle.truffle.api.debug.test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.debug.DebuggerTags; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.GenerateWrapper; @@ -64,7 +63,7 @@ public class NoCallNodeTestLanguage extends ProxyLanguage { protected CallTarget parse(ParsingRequest request) throws Exception { Source source = request.getSource(); NCRootNode root = new NCRootNode(source.createSection(0, source.getLength())); - return Truffle.getRuntime().createCallTarget(root); + return root.getCallTarget(); } private static final class NCRootNode extends RootNode { @@ -104,7 +103,7 @@ static class NCStatement extends Node implements InstrumentableNode { if (sectionLength > 1) { Source source = sourceSection.getSource(); SourceSection childSection = source.createSection(sourceSection.getCharIndex() + 1, sectionLength - 1); - childTarget = Truffle.getRuntime().createCallTarget(new NCRootNode(childSection)); + childTarget = new NCRootNode(childSection).getCallTarget(); } else { childTarget = null; } diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestDebugBuggyLanguage.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestDebugBuggyLanguage.java index 75b710fa955f..404a036fce06 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestDebugBuggyLanguage.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestDebugBuggyLanguage.java @@ -40,12 +40,13 @@ */ package com.oracle.truffle.api.debug.test; +import java.util.Objects; import java.util.function.BiFunction; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -59,7 +60,6 @@ import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; import com.oracle.truffle.api.interop.NodeLibrary; -import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; @@ -70,7 +70,6 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.test.polyglot.ProxyInteropObject; import com.oracle.truffle.api.test.polyglot.ProxyLanguage; -import java.util.Objects; /** * A buggy language for debugger tests. Use {@link ProxyLanguage#setDelegate(ProxyLanguage)} to @@ -116,7 +115,7 @@ protected final Object getDefaultScope(Node node, Frame frame, boolean enterNode @Override protected final CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, request.getSource(), scopeProvider())); + return new TestRootNode(languageInstance, request.getSource(), scopeProvider()).getCallTarget(); } @SuppressWarnings("static-method") diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestDebugNoContentLanguage.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestDebugNoContentLanguage.java index 91b65d463f28..359760420ba6 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestDebugNoContentLanguage.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestDebugNoContentLanguage.java @@ -41,7 +41,6 @@ package com.oracle.truffle.api.debug.test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -90,7 +89,7 @@ protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Except } } varLocation = sourceInfo.copySection(source.createSection(varStartPos, source.getLength() - varStartPos)); - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, source, sourceInfo)); + return new TestRootNode(languageInstance, source, sourceInfo).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestExecutableNamesLanguage.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestExecutableNamesLanguage.java index 618b95d7f4ea..9077688d292d 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestExecutableNamesLanguage.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestExecutableNamesLanguage.java @@ -85,7 +85,7 @@ public TestExecutableNamesLanguage(int depth, String rootName, String... executa @Override protected CallTarget parse(ParsingRequest request) throws Exception { Source source = request.getSource(); - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { CallTarget target = createCallTarget(); @@ -102,10 +102,9 @@ public Object execute(VirtualFrame frame) { @TruffleBoundary private CallTarget createCallTarget() { - TestNamedRoot root = new TestNamedRoot(languageInstance, depth, rootName, source); - return Truffle.getRuntime().createCallTarget(root); + return new TestNamedRoot(languageInstance, depth, rootName, source).getCallTarget(); } - }); + }.getCallTarget(); } private static class TestNamedRoot extends RootNode { @@ -121,7 +120,7 @@ private static class TestNamedRoot extends RootNode { CallTarget target = null; TestNamedRootStatement statement = null; if (depth > 0) { - target = Truffle.getRuntime().createCallTarget(new TestNamedRoot(language, depth - 1, rootName, source)); + target = new TestNamedRoot(language, depth - 1, rootName, source).getCallTarget(); } else { statement = new TestNamedRootStatement(source.createSection(1)); } @@ -323,7 +322,7 @@ static class Executable implements TruffleObject { Executable(String name, RootNode rootNode) { this.name = name; - this.target = Truffle.getRuntime().createCallTarget(rootNode); + this.target = rootNode.getCallTarget(); } @ExportMessage diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestFramesRootTag.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestFramesRootTag.java index 6a98eeb95522..e1181dae2eb4 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestFramesRootTag.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestFramesRootTag.java @@ -44,10 +44,12 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import org.junit.Test; import java.util.Iterator; +import org.graalvm.polyglot.Source; +import org.junit.Test; + import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; @@ -66,8 +68,6 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.SourceSection; -import org.graalvm.polyglot.Source; - /** * Test that debugger stack frames are based only on call nodes that are enclosed in a node tagged * with {@link StandardTags.RootTag}. @@ -163,11 +163,11 @@ protected CallTarget parse(ParsingRequest request) throws Exception { if (root == null) { root = newRoot; } else { - lastRoot.setDescendant(Truffle.getRuntime().createCallTarget(newRoot)); + lastRoot.setDescendant(newRoot.getCallTarget()); } lastRoot = newRoot; } - return Truffle.getRuntime().createCallTarget(root); + return root.getCallTarget(); } private static final class TestRoot extends RootNode { diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestLazyParsingLanguage.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestLazyParsingLanguage.java index 4f8edee3acac..7124f413d912 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestLazyParsingLanguage.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestLazyParsingLanguage.java @@ -41,7 +41,6 @@ package com.oracle.truffle.api.debug.test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.GenerateWrapper; @@ -65,7 +64,7 @@ public class TestLazyParsingLanguage extends ProxyLanguage { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new LazyRootNode(languageInstance, request.getSource(), 1)); + return new LazyRootNode(languageInstance, request.getSource(), 1).getCallTarget(); } private static class LazyRootNode extends RootNode { @@ -137,7 +136,7 @@ public Object execute(VirtualFrame frame) { Source source = sourceSection.getSource(); if (nextLine <= source.getLineCount()) { LazyRootNode root = new LazyRootNode(language, source, nextLine); - Truffle.getRuntime().createCallTarget(root).call(); + root.getCallTarget().call(); } return 42; } diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestNonInteractiveInlineParse.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestNonInteractiveInlineParse.java index 83f8ae65c279..dad760cf9e6f 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestNonInteractiveInlineParse.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestNonInteractiveInlineParse.java @@ -41,10 +41,11 @@ package com.oracle.truffle.api.debug.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Registration; import com.oracle.truffle.api.debug.DebugStackFrame; @@ -65,7 +66,6 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; -import static org.junit.Assert.fail; /** * Test that {@link TruffleLanguage#parse(TruffleLanguage.InlineParsingRequest)} is called for @@ -86,7 +86,7 @@ protected Object createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new TestRootNode(this, request.getSource())); + return new TestRootNode(this, request.getSource()).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestReceiverLanguage.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestReceiverLanguage.java index 5cd025aaac99..54435975c611 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestReceiverLanguage.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/TestReceiverLanguage.java @@ -45,7 +45,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.VirtualFrame; @@ -81,7 +80,7 @@ public TestReceiverLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { Source source = request.getSource(); - return Truffle.getRuntime().createCallTarget(new TestReceiverRootNode(languageInstance, source)); + return new TestReceiverRootNode(languageInstance, source).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/ValueLanguageLegacyTest.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/ValueLanguageLegacyTest.java index ddf5064b1d82..31aaf3e026a2 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/ValueLanguageLegacyTest.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/ValueLanguageLegacyTest.java @@ -57,7 +57,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.Breakpoint; import com.oracle.truffle.api.debug.DebugStackFrame; @@ -289,7 +288,7 @@ protected Context createContext(TruffleLanguage.Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { final com.oracle.truffle.api.source.Source source = request.getSource(); - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Node.Child private BlockNode variables = parse(source); @@ -298,7 +297,7 @@ public Object execute(VirtualFrame frame) { return variables.execute(frame); } - }); + }.getCallTarget(); } private BlockNode parse(com.oracle.truffle.api.source.Source source) { diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/ValueLanguageTest.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/ValueLanguageTest.java index dd8198266f31..4e92427d970c 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/ValueLanguageTest.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/ValueLanguageTest.java @@ -57,7 +57,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.Breakpoint; import com.oracle.truffle.api.debug.DebugStackFrame; @@ -302,7 +301,7 @@ protected Context createContext(TruffleLanguage.Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { final com.oracle.truffle.api.source.Source source = request.getSource(); - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Node.Child private BlockNode variables = parse(source); @@ -311,7 +310,7 @@ public Object execute(VirtualFrame frame) { return variables.execute(frame); } - }); + }.getCallTarget(); } private BlockNode parse(com.oracle.truffle.api.source.Source source) { diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AOTSupportTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AOTSupportTest.java index df3effcb051b..15b5fcc4324b 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AOTSupportTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AOTSupportTest.java @@ -242,7 +242,7 @@ private TestRootNode setup(BaseNode node) { context.initialize(LANGUAGE_ID); context.enter(); TestRootNode root = new TestRootNode(TestLanguage.getCurrentLanguage(), node, null); - Truffle.getRuntime().createCallTarget(root); + root.getCallTarget(); context.leave(); return root; } diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java index 865ed40bce1f..ef8cb70b7f19 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java @@ -44,7 +44,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.ImplicitCast; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; @@ -71,7 +70,7 @@ public Object execute(VirtualFrame frame) { return test.executeWith(frame, frame.getArguments()[0]); } }; - CallTarget target = Truffle.getRuntime().createCallTarget(root); + CallTarget target = root.getCallTarget(); Assert.assertEquals(1, (int) target.call(1)); Assert.assertArrayEquals(new double[0], (double[]) target.call(new int[0]), 0.0d); diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java index caba5c7b36e1..fc85a5bbf2ed 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java @@ -51,16 +51,12 @@ import java.lang.reflect.Field; -import com.oracle.truffle.api.dsl.test.CachedTestFactory.ProfileNodeGen; -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.api.profiles.LoopConditionProfile; import org.junit.Assert; import org.junit.Test; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.NodeChild; @@ -89,6 +85,7 @@ import com.oracle.truffle.api.dsl.test.CachedTestFactory.ChildrenNoAdoption6Factory; import com.oracle.truffle.api.dsl.test.CachedTestFactory.NullChildAdoptionNodeGen; import com.oracle.truffle.api.dsl.test.CachedTestFactory.NullLiteralNodeGen; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.ProfileNodeGen; import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestBoundCacheOverflowContainsFactory; import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheFieldFactory; import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheMethodFactory; @@ -106,6 +103,8 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeInterface; import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.LoopConditionProfile; @SuppressWarnings("unused") public class CachedTest { @@ -332,12 +331,12 @@ static boolean someMethod(int value) { } private static boolean isCompileImmediately() { - CallTarget target = Truffle.getRuntime().createCallTarget(new RootNode(null) { + CallTarget target = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return CompilerDirectives.inCompiledCode(); } - }); + }.getCallTarget(); return (boolean) target.call(); } diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedThreadSafetyTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedThreadSafetyTest.java index 78db84b5655b..e375075da215 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedThreadSafetyTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedThreadSafetyTest.java @@ -54,7 +54,6 @@ import org.junit.Test; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -119,7 +118,7 @@ private static SingleCachedFieldNode[] createNodes() { for (int nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++) { SingleCachedFieldNode node = SingleCachedFieldNodeGen.create(); TestRootNode root = new TestRootNode(null, node); - Truffle.getRuntime().createCallTarget(root); + root.getCallTarget(); nodes[nodeIndex] = node; assertNotNull(node.getParent()); } diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java index 0fce30e10381..f891b982b41c 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java @@ -119,15 +119,11 @@ static TestRootNode createRootPrefix(NodeFactory fac } static CallTarget createCallTarget(ValueNode node) { - return createCallTarget(new TestRootNode<>(node)); - } - - static CallTarget createCallTarget(TestRootNode node) { - return Truffle.getRuntime().createCallTarget(node); + return new TestRootNode<>(node).getCallTarget(); } static RootCallTarget createCallTarget(NodeFactory factory, Object... constants) { - return Truffle.getRuntime().createCallTarget(createRoot(factory, constants)); + return createRoot(factory, constants).getCallTarget(); } static boolean assertionsEnabled() { diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/AOTTutorial.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/AOTTutorial.java index 3f5f3556dbc8..9bf7876dbd75 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/AOTTutorial.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/AOTTutorial.java @@ -55,7 +55,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleLanguage.Registration; @@ -210,9 +209,7 @@ protected static boolean isString(Object a, Object b) { /** * The doDouble specialization is only enabled depending on an option stored in the language - * instance. Note that only the current language associated with the RootNode maybe used in - * {@link CachedLanguage}. Any other language instance used will result in a - * {@link IllegalStateException} when the node is prepared for AOT. + * instance. * * In this case since doublesEnabled is not set to true this specialization will not produce * any code after AOT preparation. @@ -348,7 +345,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { // program // this is equivalent to (arg0 + arg1) + arg2 BaseNode body = AddNodeGen.create(AddNodeGen.create(new ArgumentNode(0), new ArgumentNode(1)), new ArgumentNode(2)); - return Truffle.getRuntime().createCallTarget(new AOTRootNode(this, body, returnType, argumentTypes)); + return new AOTRootNode(this, body, returnType, argumentTypes).getCallTarget(); } else { throw CompilerDirectives.shouldNotReachHere("not-implemented"); } diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java index 39928a7a8b5d..754ef00c1884 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java @@ -42,7 +42,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; @@ -76,7 +75,7 @@ public long executeLong(VirtualFrame frame) throws UnexpectedResultException { } public static CallTarget createTarget(ExampleNode node) { - return Truffle.getRuntime().createCallTarget(new ExampleRootNode(node)); + return new ExampleRootNode(node).getCallTarget(); } public static ExampleArgumentNode[] getArguments(CallTarget target) { @@ -160,7 +159,7 @@ public long executeLong(VirtualFrame frame) throws UnexpectedResultException { } public static CallTarget createDummyTarget(int argumentIndex) { - return Truffle.getRuntime().createCallTarget(new DummyCallRootNode(argumentIndex)); + return new DummyCallRootNode(argumentIndex).getCallTarget(); } private static class DummyCallRootNode extends RootNode { diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/AllocationReporterTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/AllocationReporterTest.java index d98a34a52158..e86ed794f726 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/AllocationReporterTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/AllocationReporterTest.java @@ -64,7 +64,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.AllocationEvent; @@ -626,7 +625,7 @@ public static class AllocationReporterLanguage extends ProxyLanguage { @Override protected CallTarget parse(ParsingRequest request) throws Exception { final com.oracle.truffle.api.source.Source code = request.getSource(); - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Node.Child private AllocNode alloc = parse(code.getCharacters().toString()); @@ -635,7 +634,7 @@ public Object execute(VirtualFrame frame) { return alloc.execute(frame); } - }); + }.getCallTarget(); } private static AllocNode parse(String code) { diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/CompileImmediatelyCheck.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/CompileImmediatelyCheck.java index 5b4acb33d1f9..26efb042266a 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/CompileImmediatelyCheck.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/CompileImmediatelyCheck.java @@ -42,19 +42,18 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; public class CompileImmediatelyCheck { public static boolean isCompileImmediately() { - CallTarget target = Truffle.getRuntime().createCallTarget(new RootNode(null) { + CallTarget target = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return CompilerDirectives.inCompiledCode(); } - }); + }.getCallTarget(); return (boolean) target.call(); } diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptStandaloneTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptStandaloneTest.java index 72ec1094de1c..1a964516bc2c 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptStandaloneTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptStandaloneTest.java @@ -67,7 +67,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleSafepoint; import com.oracle.truffle.api.frame.VirtualFrame; @@ -103,7 +102,7 @@ public void testCancelDuringHostSleep() throws ExecutionException, InterruptedEx new ProxyLanguage() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Child InteropLibrary library = InteropLibrary.getFactory().createDispatched(1); @Override @@ -122,7 +121,7 @@ private void callHostSleep() { throw new AssertionError(e); } } - }); + }.getCallTarget(); } @Override @@ -179,7 +178,7 @@ private void testCancelFromHostCall(boolean nestedContextEntered) { new ProxyLanguage() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Child InteropLibrary library = InteropLibrary.getFactory().createDispatched(1); @Override @@ -192,7 +191,7 @@ public Object execute(VirtualFrame frame) { } return 0; } - }); + }.getCallTarget(); } }); try { diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextsEventsTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextsEventsTest.java index ec356274b917..f9be601b2365 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextsEventsTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextsEventsTest.java @@ -61,7 +61,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.ContextsListener; @@ -493,12 +492,12 @@ static class LanguageContextFailureLanguage extends ProxyLanguage { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { return null; } - }); + }.getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/DeadlockTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/DeadlockTest.java index 6c39b4519b40..cc8310b61160 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/DeadlockTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/DeadlockTest.java @@ -55,7 +55,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.ExecuteSourceEvent; @@ -203,14 +202,14 @@ protected CallTarget parse(ParsingRequest request) throws Exception { final CharSequence codeCharacters = code.getCharacters(); if (CODE_LATCH.equals(codeCharacters)) { ((InstrumentationThread) Thread.currentThread()).setExecutionLatch(executionLatch); - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { return Boolean.TRUE; } - }); + }.getCallTarget(); } - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { @@ -240,13 +239,13 @@ public SourceSection getSourceSection() { } catch (InterruptedException ex) { } } - codeExec = Truffle.getRuntime().createCallTarget(codeExecRoot); + codeExec = codeExecRoot.getCallTarget(); } targets.add(codeExec); return codeExec.call(); } - }); + }.getCallTarget(); } @GenerateWrapper @@ -320,7 +319,7 @@ public SourceSection getSourceSection() { }; synchronized (language.lock) { - this.statementCall = Truffle.getRuntime().createCallTarget(codeExecRoot); + this.statementCall = codeExecRoot.getCallTarget(); } } return this; diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/FindSourcesVisitorNestingTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/FindSourcesVisitorNestingTest.java index d5042e83fad3..31c1dea84518 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/FindSourcesVisitorNestingTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/FindSourcesVisitorNestingTest.java @@ -52,7 +52,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.EventContext; import com.oracle.truffle.api.instrumentation.ExecutionEventListener; @@ -190,7 +189,7 @@ public InstrumentableNode materializeInstrumentableNodes(Set stack = TruffleStackTrace.getAsynchronousStackTrace(root.getCallTarget(), frame); // No asynchronous stack by default @@ -2311,7 +2311,7 @@ public void testAsynchronousStacks3() { ProxyLanguage.setDelegate(new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new AsyncRootNode(language, 0)); + return new AsyncRootNode(language, 0).getCallTarget(); } class AsyncRootNode extends RootNode { @@ -2356,7 +2356,7 @@ protected boolean isInstrumentable() { protected List findAsynchronousFrames(Frame frame) { assertSame(this.getFrameDescriptor(), frame.getFrameDescriptor()); AsyncRootNode invoker = new AsyncRootNode(language, level + 1); - RootCallTarget invokerTarget = Truffle.getRuntime().createCallTarget(invoker); + RootCallTarget invokerTarget = invoker.getCallTarget(); Frame invokerFrame = Truffle.getRuntime().createMaterializedFrame(new Object[]{level + 1}, invoker.getFrameDescriptor()); TruffleStackTraceElement element = TruffleStackTraceElement.create(invoker.child, invokerTarget, invokerFrame); return Collections.singletonList(element); diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationTestLanguage.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationTestLanguage.java index 72f10961af0b..a337f9457c59 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationTestLanguage.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationTestLanguage.java @@ -258,7 +258,7 @@ protected void initializeContext(InstrumentContext context) throws Exception { if (code != null) { SourceSection outer = code.createSection(0, code.getLength()); BaseNode node = parse(code); - RootCallTarget rct = Truffle.getRuntime().createCallTarget(new InstrumentationTestRootNode(this, "", outer, node)); + RootCallTarget rct = new InstrumentationTestRootNode(this, "", outer, node).getCallTarget(); rct.call(); if (context.runInitAfterExec) { context.afterTarget = rct; @@ -282,7 +282,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { throw new IOException(e); } RootCallTarget afterTarget = InstrumentContext.get(null).afterTarget; - return lastParsed = Truffle.getRuntime().createCallTarget(new InstrumentationTestRootNode(this, "", outer, afterTarget, node)); + return lastParsed = new InstrumentationTestRootNode(this, "", outer, afterTarget, node).getCallTarget(); } public static RootNode parse(String code) { @@ -1456,7 +1456,7 @@ static class DefineNode extends InstrumentedNode { int index = code.indexOf('(') + 1; index = code.indexOf(',', index) + 1; SourceSection functionSection = source.getSource().createSection(source.getCharIndex() + index, source.getCharLength() - index - 1); - this.target = Truffle.getRuntime().createCallTarget(new InstrumentationTestRootNode(lang, identifier, functionSection, children)); + this.target = new InstrumentationTestRootNode(lang, identifier, functionSection, children).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationUpdateTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationUpdateTest.java index 7f5740411e0f..3da32c61d445 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationUpdateTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationUpdateTest.java @@ -52,7 +52,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.EventBinding; @@ -346,7 +345,7 @@ public static class InstrumentationUpdateLanguage extends TruffleLanguage executedSources = new TreeSet<>(); @@ -588,7 +587,7 @@ private void testBindingDisposalImpl(boolean load) throws Exception { Node node2a = new SourceSectionFilterTest.SourceSectionNode(source2a.createSection(1)); Node node2b = new SourceSectionFilterTest.SourceSectionNode(source2b.createSection(1)); RootNode root2 = SourceSectionFilterTest.createRootNode(null, Boolean.FALSE, node2a, node2b); - Truffle.getRuntime().createCallTarget(root2).call(); + root2.getCallTarget().call(); assertEvents(impl.onlyNewEvents, source1); assertEvents(impl.allEvents, source1); @@ -870,7 +869,7 @@ public void testNoMaterializationOnSourceListener() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { com.oracle.truffle.api.source.Source source = request.getSource(); - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Node.Child private NeverMaterializedNode child = new NeverMaterializedNode(); @Override @@ -882,7 +881,7 @@ public Object execute(VirtualFrame frame) { public SourceSection getSourceSection() { return source.createSection(1); } - }); + }.getCallTarget(); } }); context.eval(Source.create(ProxyLanguage.ID, "a")); @@ -1414,7 +1413,7 @@ static class MultiSourceASTLanguage extends ProxyLanguage { @Override protected CallTarget parse(ParsingRequest request) throws Exception { com.oracle.truffle.api.source.Source source = request.getSource(); - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Node.Child private MultiSourceBlock block = new MultiSourceBlock(source, source.getCharacters().toString()); @Override @@ -1426,7 +1425,7 @@ public Object execute(VirtualFrame frame) { public SourceSection getSourceSection() { return source.createSection(1); } - }); + }.getCallTarget(); } @GenerateWrapper diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionFilterTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionFilterTest.java index 8ee8a95e4b63..2726d2e71f2b 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionFilterTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionFilterTest.java @@ -51,7 +51,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.InstrumentableNode; @@ -1048,7 +1047,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { Assert.assertTrue(SourceSectionFilter.ANY.includes(rootNode, rootNode.getSourceSection(), rootTags)); Assert.assertTrue(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build().includes(rootNode, rootNode.getSourceSection(), rootTags)); Assert.assertFalse(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build().includes(rootNode, rootNode.getSourceSection(), statementTags)); - return Truffle.getRuntime().createCallTarget(rootNode); + return rootNode.getCallTarget(); } } diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionListenerTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionListenerTest.java index bc02d92531d1..4b10e2739c2a 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionListenerTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionListenerTest.java @@ -54,7 +54,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.EventContext; import com.oracle.truffle.api.instrumentation.ExecutionEventListener; @@ -394,7 +393,7 @@ static class SingleSourceSectionLanguage extends ProxyLanguage { @Override protected CallTarget parse(ParsingRequest request) throws Exception { com.oracle.truffle.api.source.Source source = request.getSource(); - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Node.Child private SingleSourceSectionNode onlyChild = new SingleSourceSectionNode(source); @Override @@ -406,7 +405,7 @@ public Object execute(VirtualFrame frame) { public com.oracle.truffle.api.source.SourceSection getSourceSection() { return source.createSection(1); } - }); + }.getCallTarget(); } @GenerateWrapper diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TagsTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TagsTest.java index 11d89a6fd340..baf575f707c7 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TagsTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TagsTest.java @@ -45,13 +45,13 @@ import static org.junit.Assert.assertSame; import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.PolyglotException; import org.junit.Assert; import org.junit.Test; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.VirtualFrame; @@ -79,7 +79,6 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.test.polyglot.ProxyInstrument; -import org.graalvm.polyglot.PolyglotException; public class TagsTest { @@ -189,7 +188,7 @@ protected Env createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Child private TaggedNode child = new TaggedNode(request.getSource().getCharacters().toString()); @@ -202,7 +201,7 @@ protected boolean isInstrumentable() { public Object execute(VirtualFrame frame) { return child.execute(frame); } - }); + }.getCallTarget(); } @GenerateWrapper @@ -299,7 +298,7 @@ protected Env createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Child private RWTaggedNode child = new RWTaggedNode(request.getSource()); @@ -312,7 +311,7 @@ protected boolean isInstrumentable() { public Object execute(VirtualFrame frame) { return child.execute(frame); } - }); + }.getCallTarget(); } @GenerateWrapper diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ThreadsActivationListenerTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ThreadsActivationListenerTest.java index b313814784ca..ccf3a6c7b7a8 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ThreadsActivationListenerTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ThreadsActivationListenerTest.java @@ -50,12 +50,12 @@ import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.PolyglotException; import org.junit.Test; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.instrumentation.EventBinding; import com.oracle.truffle.api.instrumentation.ThreadsActivationListener; @@ -64,8 +64,6 @@ import com.oracle.truffle.api.test.polyglot.ProxyLanguage; import com.oracle.truffle.api.test.polyglot.ProxyLanguage.LanguageContext; -import org.graalvm.polyglot.PolyglotException; - public class ThreadsActivationListenerTest extends AbstractPolyglotTest { public ThreadsActivationListenerTest() { @@ -78,7 +76,7 @@ public void testInternalContext() { setupEnv(Context.create(), new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } }); @@ -158,7 +156,7 @@ public void testMultiContext() { setupEnv(Context.newBuilder().engine(engine).build(), new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } }); Context c0 = this.context; @@ -167,7 +165,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { setupEnv(Context.newBuilder().engine(engine).build(), new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } }); @@ -230,7 +228,7 @@ public void testSingleContext() { setupEnv(Context.create(), new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } }); List entered = new ArrayList<>(); @@ -289,7 +287,7 @@ public void testMultiThreading() throws InterruptedException { setupEnv(Context.create(), new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } @Override @@ -387,7 +385,7 @@ private void testExceptionImpl(Runnable body, boolean throwOnEnter, boolean thro setupEnv(Context.create(), new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } }); diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TruffleContextTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TruffleContextTest.java index 1648c70e5f3e..d7c3ba496aa7 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TruffleContextTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TruffleContextTest.java @@ -77,7 +77,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleSafepoint; @@ -356,7 +355,7 @@ protected CallTarget parse(ParsingRequest request) { default: throw CompilerDirectives.shouldNotReachHere("Unknown request: " + command); } - return Truffle.getRuntime().createCallTarget(rootNode); + return rootNode.getCallTarget(); } }); context.eval(Source.newBuilder(ProxyLanguage.ID, "controller", "test").buildLiteral()); @@ -643,7 +642,7 @@ public void testNoInitializeMultiContextForInnerContext() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } @Override @@ -669,7 +668,7 @@ public void testInitializeMultiContextForInnerContext() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } @Override @@ -690,7 +689,7 @@ private void setupLanguageThatReturns(Supplier supplier) { setupEnv(Context.create(), new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(ProxyLanguage.get(null)) { + return new RootNode(ProxyLanguage.get(null)) { @Override public Object execute(VirtualFrame frame) { return get(); @@ -700,7 +699,7 @@ public Object execute(VirtualFrame frame) { private Object get() { return supplier.get(); } - }); + }.getCallTarget(); } }); } diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/VariablesScopeLegacyTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/VariablesScopeLegacyTest.java index 80a867dc9483..65ded08d7f2e 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/VariablesScopeLegacyTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/VariablesScopeLegacyTest.java @@ -55,7 +55,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.Frame; @@ -289,7 +288,7 @@ protected Env createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new CustomRoot(this)); + return new CustomRoot(this).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/VariablesScopeTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/VariablesScopeTest.java index b6dfd6cbfae3..61a1496530c4 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/VariablesScopeTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/VariablesScopeTest.java @@ -45,13 +45,14 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; import org.junit.Test; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.Frame; @@ -82,9 +83,6 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.test.polyglot.ProxyLanguage; -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Value; - /** * Test of {@link Scope}. */ @@ -352,7 +350,7 @@ private static void createDefaultScopeLanguage(Context context) { ProxyLanguage language = new ProxyLanguage() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(ProxyLanguage.get(null)) { + return new RootNode(ProxyLanguage.get(null)) { @Node.Child private DefaultRootBlockNode block = insert(new DefaultRootBlockNode()); @@ -365,7 +363,7 @@ protected boolean isInstrumentable() { public Object execute(VirtualFrame frame) { return block.execute(frame); } - }); + }.getCallTarget(); } }; ProxyLanguage.setDelegate(language); @@ -463,7 +461,7 @@ protected Env createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new CustomRoot(this)); + return new CustomRoot(this).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentableNode.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentableNode.java index e50598280705..de68601f0187 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentableNode.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentableNode.java @@ -45,7 +45,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.InstrumentableNode.WrapperNode; import com.oracle.truffle.api.nodes.Node; @@ -109,8 +108,8 @@ public interface InstrumentableNode extends NodeInterface { *

* The implementation of this method must ensure that its result is stable after the parent * {@link RootNode root node} was wrapped in a {@link CallTarget} using - * {@link TruffleRuntime#createCallTarget(RootNode)}. The result is stable if the result of - * calling this method remains always the same. + * {@link RootNode#getCallTarget()}. The result is stable if the result of calling this method + * remains always the same. *

* This method might be called in parallel from multiple threads even if the language is single * threaded. The method may be invoked without a language context currently being active. @@ -183,8 +182,8 @@ public interface InstrumentableNode extends NodeInterface { *

* The implementation of hasTag method must ensure that its result is stable after the parent * {@link RootNode root node} was wrapped in a {@link CallTarget} using - * {@link TruffleRuntime#createCallTarget(RootNode)}. The result is stable if the result of - * calling this method for a particular tag remains always the same. + * {@link RootNode#getCallTarget()}. The result is stable if the result of calling this method + * for a particular tag remains always the same. *

* This method might be called in parallel from multiple threads even if the language is single * threaded. The method may be invoked without a language context currently being active. diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/LoadSourceListener.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/LoadSourceListener.java index 737d83c93793..8a3160ab2aa2 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/LoadSourceListener.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/LoadSourceListener.java @@ -40,7 +40,6 @@ */ package com.oracle.truffle.api.instrumentation; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; @@ -60,10 +59,9 @@ public interface LoadSourceListener { * attached}. *

* Implementation Note: Source load events are notified when the guest language - * implementation uses a new {@link Source source} by invoking - * {@link TruffleRuntime#createCallTarget(RootNode)} with a root node that uses a new source in - * {@link Node#getSourceSection()}. It assumes that all nodes of an AST have the same - * {@link Source source} as their root. + * implementation uses a new {@link Source source} by invoking {@link RootNode#getCallTarget()} + * with a root node that uses a new source in {@link Node#getSourceSection()}. It assumes that + * all nodes of an AST have the same {@link Source source} as their root. *

* * @param event an event with context information diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/LoadSourceSectionListener.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/LoadSourceSectionListener.java index 45ab2bcd2b84..f0a10ecfca02 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/LoadSourceSectionListener.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/LoadSourceSectionListener.java @@ -40,7 +40,6 @@ */ package com.oracle.truffle.api.instrumentation; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; @@ -63,10 +62,9 @@ public interface LoadSourceSectionListener { * attached}. * * Implementation Note: Source load events are notified when the guest language - * implementation uses a new {@link Source source} by invoking - * {@link TruffleRuntime#createCallTarget(RootNode)} with a root node that uses a new source in - * {@link Node#getSourceSection()}. It assumes that all nodes of an AST have the same - * {@link Source source} as their root. + * implementation uses a new {@link Source source} by invoking {@link RootNode#getCallTarget()} + * with a root node that uses a new source in {@link Node#getSourceSection()}. It assumes that + * all nodes of an AST have the same {@link Source source} as their root. *

* * @param event an event with context information diff --git a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy1.java b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy1.java index 5ea7f97b30aa..9baf83f5054f 100644 --- a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy1.java +++ b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy1.java @@ -45,7 +45,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; @@ -133,7 +132,7 @@ public Object execute(VirtualFrame frame) { @Test public void runExample() { ArrayReadNode read = ArrayReadNodeGen.create(new ArgumentNode(0), new ArgumentNode(1)); - CallTarget target = Truffle.getRuntime().createCallTarget(new ExampleRootNode(read)); + CallTarget target = new ExampleRootNode(read).getCallTarget(); assertEquals(3, target.call(new SequenceArray(1, 2, 3), 1)); assertEquals(0, target.call(new BufferArray(2), 1)); diff --git a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy2.java b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy2.java index 773c9769ba66..3cbe24ecefbe 100644 --- a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy2.java +++ b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy2.java @@ -45,13 +45,12 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ArgumentNode; -import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ExpressionNode; import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ExampleRootNode; +import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ExpressionNode; import com.oracle.truffle.api.library.test.examples.ArrayStrategy2Factory.ArrayReadNodeGen; /** @@ -118,7 +117,7 @@ int doDefault(Array array, int index) { @Test public void runExample() { ArrayReadNode read = ArrayReadNodeGen.create(new ArgumentNode(0), new ArgumentNode(1)); - CallTarget target = Truffle.getRuntime().createCallTarget(new ExampleRootNode(read)); + CallTarget target = new ExampleRootNode(read).getCallTarget(); assertEquals(3, target.call(new SequenceArray(1, 2, 3), 1)); assertEquals(0, target.call(new BufferArray(2), 1)); diff --git a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy3.java b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy3.java index 3fb4dfb3c6ec..e88148de590b 100644 --- a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy3.java +++ b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/ArrayStrategy3.java @@ -47,7 +47,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.library.CachedLibrary; @@ -142,7 +141,7 @@ int doDefault(Object array, int index, @Test public void runExample() { ArrayReadNode read = ArrayReadNodeGen.create(new ArgumentNode(0), new ArgumentNode(1)); - CallTarget target = Truffle.getRuntime().createCallTarget(new ExampleRootNode(read)); + CallTarget target = new ExampleRootNode(read).getCallTarget(); assertEquals(3, target.call(new SequenceArray(1, 2, 3), 1)); assertEquals(0, target.call(new BufferArray(2), 1)); diff --git a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/DynamicDispatchExample.java b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/DynamicDispatchExample.java index 9b8d585eefe1..f73c6564651f 100644 --- a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/DynamicDispatchExample.java +++ b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/DynamicDispatchExample.java @@ -45,7 +45,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.library.CachedLibrary; @@ -55,8 +54,8 @@ import com.oracle.truffle.api.library.GenerateLibrary; import com.oracle.truffle.api.library.Library; import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ArgumentNode; -import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ExpressionNode; import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ExampleRootNode; +import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ExpressionNode; import com.oracle.truffle.api.library.test.examples.DynamicDispatchExampleFactory.SampleOperationNodeGen; /** @@ -120,7 +119,7 @@ String doDefault(Object sample, @Test public void runExample() { SampleOperationNode read = SampleOperationNodeGen.create(new ArgumentNode(0)); - CallTarget target = Truffle.getRuntime().createCallTarget(new ExampleRootNode(read)); + CallTarget target = new ExampleRootNode(read).getCallTarget(); assertEquals("export1", target.call(new DynamicDispatchObject(SampleExport1.class))); assertEquals("export2", target.call(new DynamicDispatchObject(SampleExport2.class))); diff --git a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/TaintTrackingExample.java b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/TaintTrackingExample.java index cb3099f4aef1..857fc5b07e85 100644 --- a/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/TaintTrackingExample.java +++ b/truffle/src/com.oracle.truffle.api.library.test/src/com/oracle/truffle/api/library/test/examples/TaintTrackingExample.java @@ -46,7 +46,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.library.CachedLibrary; @@ -58,8 +57,8 @@ import com.oracle.truffle.api.library.Message; import com.oracle.truffle.api.library.ReflectionLibrary; import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ArgumentNode; -import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ExpressionNode; import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ExampleRootNode; +import com.oracle.truffle.api.library.test.examples.ArrayStrategy1.ExpressionNode; import com.oracle.truffle.api.library.test.examples.TaintTrackingExampleFactory.UnknownOperationNodeGen; /** @@ -159,7 +158,7 @@ Object doDefault(Object sample, public void runExample() { TaintLibrary taintLibrary = LibraryFactory.resolve(TaintLibrary.class).getUncached(); UnknownOperationNode sample = UnknownOperationNodeGen.create(new ArgumentNode(0)); - CallTarget target = Truffle.getRuntime().createCallTarget(new ExampleRootNode(sample)); + CallTarget target = new ExampleRootNode(sample).getCallTarget(); Object value = new UnknownValue(); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java index d23bf8905f20..eecbd871ae1b 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java @@ -44,8 +44,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; @@ -75,10 +73,8 @@ public class ArgumentsTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); TestRootNode rootNode = new TestRootNode(new TestArgumentNode[]{new TestArgumentNode(0), new TestArgumentNode(1)}); - CallTarget target = runtime.createCallTarget(rootNode); - Object result = target.call(new Object[]{20, 22}); + Object result = rootNode.getCallTarget().call(new Object[]{20, 22}); Assert.assertEquals(42, result); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/AssumptionInvalidationTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/AssumptionInvalidationTest.java index 319e961a267b..c06426e4414f 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/AssumptionInvalidationTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/AssumptionInvalidationTest.java @@ -63,7 +63,7 @@ public void test() throws InterruptedException { Assumption assumption = runtime.createAssumption("propagated assumption invalidation"); CountingNode countingNode = new CountingNode(assumption); TestRootNode countingRootNode = new TestRootNode(countingNode); - final CallTarget countingTarget = runtime.createCallTarget(countingRootNode); + final CallTarget countingTarget = countingRootNode.getCallTarget(); Thread thread = new Thread(new Runnable() { public void run() { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java index 75a4cf441c17..afa7f040389b 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java @@ -44,8 +44,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; @@ -53,9 +51,9 @@ *

Calling Another Tree

* *

- * A guest language implementation can create multiple call targets using the - * {@link TruffleRuntime#createCallTarget(RootNode)} method. Those call targets can be passed around - * as normal Java objects and used for calling guest language methods. + * A guest language implementation can create multiple root nodes and thus multiple call targets + * using the {@link RootNode#getCallTarget()} method. Those call targets can be passed around as + * normal Java objects and used for calling guest language methods. *

* *

@@ -67,10 +65,9 @@ public class CallTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); - CallTarget foo = runtime.createCallTarget(new ConstantRootNode(20)); - CallTarget bar = runtime.createCallTarget(new ConstantRootNode(22)); - CallTarget main = runtime.createCallTarget(new DualCallNode(foo, bar)); + CallTarget foo = new ConstantRootNode(20).getCallTarget(); + CallTarget bar = new ConstantRootNode(22).getCallTarget(); + CallTarget main = new DualCallNode(foo, bar).getCallTarget(); Object result = main.call(); Assert.assertEquals(42, result); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java index 9e7cb53ec9d6..a98df47593ec 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java @@ -49,8 +49,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.Node.Child; @@ -80,11 +78,10 @@ public class ChildNodeTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); TestChildNode leftChild = new TestChildNode(); TestChildNode rightChild = new TestChildNode(); TestRootNode rootNode = new TestRootNode(leftChild, rightChild); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); assertEquals(rootNode, leftChild.getParent()); assertEquals(rootNode, rightChild.getParent()); Iterator iterator = rootNode.getChildren().iterator(); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java index f10178ba477a..4344fd73e5dc 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java @@ -46,8 +46,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; @@ -73,11 +71,10 @@ public class ChildrenNodesTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); TestChildNode firstChild = new TestChildNode(); TestChildNode secondChild = new TestChildNode(); TestRootNode rootNode = new TestRootNode(new TestChildNode[]{firstChild, secondChild}); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); Assert.assertEquals(rootNode, firstChild.getParent()); Assert.assertEquals(rootNode, secondChild.getParent()); Iterator iterator = rootNode.getChildren().iterator(); @@ -119,13 +116,12 @@ public int execute() { @Test public void testMultipleChildrenFields() { - TruffleRuntime runtime = Truffle.getRuntime(); TestChildNode firstChild = new TestChildNode(); TestChildNode secondChild = new TestChildNode(); TestChildNode thirdChild = new TestChildNode(); TestChildNode forthChild = new TestChildNode(); TestRootNode rootNode = new TestRoot2Node(new TestChildNode[]{firstChild, secondChild}, new TestChildNode[]{thirdChild, forthChild}); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); Assert.assertEquals(rootNode, firstChild.getParent()); Assert.assertEquals(rootNode, secondChild.getParent()); Assert.assertEquals(rootNode, thirdChild.getParent()); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CompileImmediatelyCheck.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CompileImmediatelyCheck.java index d90cffa550f8..5b16117c7422 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CompileImmediatelyCheck.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CompileImmediatelyCheck.java @@ -42,7 +42,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; @@ -51,12 +50,12 @@ public class CompileImmediatelyCheck { public static boolean isCompileImmediately() { // we try twice, as sometimes some classes deopt. for (int i = 0; i < 2; i++) { - CallTarget target = Truffle.getRuntime().createCallTarget(new RootNode(null) { + CallTarget target = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return CompilerDirectives.inCompiledCode(); } - }); + }.getCallTarget(); boolean result = (boolean) target.call(); if (result) { return true; diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java index 5ca406f63b52..73058b0cf17b 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java @@ -43,9 +43,6 @@ import org.junit.Assert; import org.junit.Test; -import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; @@ -75,10 +72,8 @@ public class FinalFieldTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); TestRootNode rootNode = new TestRootNode(new TestChildNode[]{new TestChildNode(20), new TestChildNode(22)}); - CallTarget target = runtime.createCallTarget(rootNode); - Object result = target.call(); + Object result = rootNode.getCallTarget().call(); Assert.assertEquals(42, result); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java index 271e9a5570f9..cd52f5ba559b 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java @@ -43,9 +43,6 @@ import org.junit.Assert; import org.junit.Test; -import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -72,13 +69,11 @@ public class FrameSlotTypeSpecializationTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); FrameDescriptor frameDescriptor = new FrameDescriptor(); FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int); TestRootNode rootNode = new TestRootNode(frameDescriptor, new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot)); - CallTarget target = runtime.createCallTarget(rootNode); Assert.assertEquals(FrameSlotKind.Int, frameDescriptor.getFrameSlotKind(slot)); - Object result = target.call(); + Object result = rootNode.getCallTarget().call(); Assert.assertEquals("42", result); Assert.assertEquals(FrameSlotKind.Object, frameDescriptor.getFrameSlotKind(slot)); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java index 2da8901c604a..5a8c72fa341b 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java @@ -47,7 +47,6 @@ import org.junit.Assume; import org.junit.Test; -import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.Frame; @@ -96,13 +95,11 @@ public class FrameTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); FrameDescriptor frameDescriptor = new FrameDescriptor(); String varName = "localVar"; FrameSlot slot = frameDescriptor.addFrameSlot(varName, FrameSlotKind.Int); TestRootNode rootNode = new TestRootNode(frameDescriptor, new AssignLocal(slot), new ReadLocal(slot)); - CallTarget target = runtime.createCallTarget(rootNode); - Object result = target.call(); + Object result = rootNode.getCallTarget().call(); assertEquals(42, result); frameDescriptor.removeFrameSlot(varName); assertNull(frameDescriptor.findFrameSlot(varName)); @@ -195,7 +192,7 @@ public Object execute(VirtualFrame frame) { } FrameRootNode frn = new FrameRootNode(); - Object ret = Truffle.getRuntime().createCallTarget(frn).call(); + Object ret = frn.getCallTarget().call(); assertEquals("Returns itself", frn, ret); } } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InterfaceChildFieldTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InterfaceChildFieldTest.java index 722b625239e0..fa47a8332192 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InterfaceChildFieldTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InterfaceChildFieldTest.java @@ -47,8 +47,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeInterface; @@ -62,12 +60,11 @@ public class InterfaceChildFieldTest { @Test public void testChild() { - TruffleRuntime runtime = Truffle.getRuntime(); TestChildInterface leftChild = new TestLeafNode(); TestChildInterface rightChild = new TestLeafNode(); TestChildNode parent = new TestChildNode(leftChild, rightChild); TestRootNode rootNode = new TestRootNode(parent); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); Iterator iterator = parent.getChildren().iterator(); Assert.assertEquals(leftChild, iterator.next()); Assert.assertEquals(rightChild, iterator.next()); @@ -81,14 +78,13 @@ public void testChild() { @Test public void testChildren() { - TruffleRuntime runtime = Truffle.getRuntime(); TestChildInterface[] children = new TestChildInterface[5]; for (int i = 0; i < children.length; i++) { children[i] = new TestLeafNode(); } TestChildrenNode parent = new TestChildrenNode(children); TestRootNode rootNode = new TestRootNode(parent); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); Iterator iterator = parent.getChildren().iterator(); for (int i = 0; i < children.length; i++) { Assert.assertEquals(children[i], iterator.next()); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/IteratorTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/IteratorTest.java index c01ec2c24890..307958632e68 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/IteratorTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/IteratorTest.java @@ -493,7 +493,7 @@ private static CallTarget createAST(TruffleLanguage lang, Object iterable) { StatementNode main = new BlockStatement( new ExpressionStatement(IteratorTestFactory.WriteVariableNodeGen.create(new ConstantNode(iterable), iterableSlot)), new ForEachStatement(iterableSlot, itemSlot, log)); - return Truffle.getRuntime().createCallTarget(new TestRootNode(lang, fd, main)); + return new TestRootNode(lang, fd, main).getCallTarget(); } private static Context createContext(VerifyingHandler handler) { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/LegacyTruffleExceptionTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/LegacyTruffleExceptionTest.java index c9368d5ad7da..1e246814368f 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/LegacyTruffleExceptionTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/LegacyTruffleExceptionTest.java @@ -43,8 +43,13 @@ import static com.oracle.truffle.api.test.TruffleExceptionTest.createAST; import static com.oracle.truffle.api.test.TruffleExceptionTest.createContext; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.PolyglotException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.interop.ExceptionType; import com.oracle.truffle.api.interop.InteropLibrary; @@ -58,11 +63,6 @@ import com.oracle.truffle.api.test.TruffleExceptionTest.ThrowNode; import com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest; import com.oracle.truffle.api.test.polyglot.ProxyLanguage; -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.PolyglotException; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; public class LegacyTruffleExceptionTest extends AbstractPolyglotTest { @@ -135,7 +135,7 @@ protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Except ThrowNode throwNode = new ThrowNode((n) -> { return new LegacyCatchableException("Test exception", n); }); - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test", null, throwNode)); + return new TestRootNode(languageInstance, "test", null, throwNode).getCallTarget(); } }); assertFails(() -> context.eval(ProxyLanguage.ID, "Test"), PolyglotException.class, (pe) -> { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/LoopNodeTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/LoopNodeTest.java index 342841113ed9..2a7dfbc4568c 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/LoopNodeTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/LoopNodeTest.java @@ -162,7 +162,7 @@ public Object execute(VirtualFrame frame) { } }; - CallTarget target = Truffle.getRuntime().createCallTarget(root); + CallTarget target = root.getCallTarget(); for (int i = 0; i < 1000; i++) { Assert.assertEquals(15, target.call()); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java index 3e31f31af6cd..8c97e49e3caa 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java @@ -48,8 +48,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; @@ -77,11 +75,10 @@ public class ReplaceTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); UnresolvedNode leftChild = new UnresolvedNode("20"); UnresolvedNode rightChild = new UnresolvedNode("22"); TestRootNode rootNode = new TestRootNode(new ValueNode[]{leftChild, rightChild}); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); assertEquals(rootNode, leftChild.getParent()); assertEquals(rootNode, rightChild.getParent()); Iterator iterator = rootNode.getChildren().iterator(); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java index 1dd0ca1a93bc..62b0de0f7d96 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java @@ -43,9 +43,6 @@ import org.junit.Assert; import org.junit.Test; -import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -72,13 +69,11 @@ public class ReturnTypeSpecializationTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); FrameDescriptor frameDescriptor = new FrameDescriptor(); FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int); TestRootNode rootNode = new TestRootNode(frameDescriptor, new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot)); - CallTarget target = runtime.createCallTarget(rootNode); Assert.assertEquals(FrameSlotKind.Int, frameDescriptor.getFrameSlotKind(slot)); - Object result = target.call(); + Object result = rootNode.getCallTarget().call(); Assert.assertEquals("42", result); Assert.assertEquals(FrameSlotKind.Object, frameDescriptor.getFrameSlotKind(slot)); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java index c70087c8abab..184a09daa711 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java @@ -42,13 +42,12 @@ import java.util.List; +import org.graalvm.polyglot.Context; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.TruffleStackTrace; import com.oracle.truffle.api.TruffleStackTraceElement; import com.oracle.truffle.api.exception.AbstractTruffleException; @@ -62,7 +61,6 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest; -import org.graalvm.polyglot.Context; /** *

Creating a Root Node

@@ -71,10 +69,9 @@ * A Truffle root node is the entry point into a Truffle tree that represents a guest language * method. It contains a {@link RootNode#execute(VirtualFrame)} method that can return a * {@link java.lang.Object} value as the result of the guest language method invocation. This method - * must however never be called directly. Instead, the Truffle runtime must be used to create a - * {@link CallTarget} object from a root node using the - * {@link TruffleRuntime#createCallTarget(RootNode)} method. This call target object can then be - * executed using the {@link CallTarget#call(Object...)} method or one of its overloads. + * must however never be called directly. Instead, its {@link CallTarget} object must be obtained + * via {@link RootNode#getCallTarget()}. This call target object can then be executed using the + * {@link CallTarget#call(Object...)} method or one of its overloads. *

* *

@@ -86,10 +83,7 @@ public class RootNodeTest { @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); - TestRootNode rootNode = new TestRootNode(); - CallTarget target = runtime.createCallTarget(rootNode); - Object result = target.call(); + Object result = new TestRootNode().getCallTarget().call(); Assert.assertEquals(42, result); } @@ -122,7 +116,7 @@ public void testNotCapturingFrames() { TestRootNode3 rootNode = new TestRootNode3(false); Object marker = new Object(); try { - Truffle.getRuntime().createCallTarget(rootNode).call(marker); + rootNode.getCallTarget().call(marker); Assert.fail(); } catch (TestException e) { List stackTrace = TruffleStackTrace.getStackTrace(e); @@ -138,7 +132,7 @@ public void testCapturingFrames() { TestRootNode3 rootNode = new TestRootNode3(true); Object marker = new Object(); try { - Truffle.getRuntime().createCallTarget(rootNode).call(marker); + rootNode.getCallTarget().call(marker); Assert.fail(); } catch (TestException e) { asserCapturedFrames(rootNode, marker, e, e.frame); @@ -150,7 +144,7 @@ public void testCapturingFramesLegacyException() { TestRootNode4 rootNode = new TestRootNode4(true); Object marker = new Object(); try { - Truffle.getRuntime().createCallTarget(rootNode).call(marker); + rootNode.getCallTarget().call(marker); Assert.fail(); } catch (LegacyTestException e) { asserCapturedFrames(rootNode, marker, e, e.frame); @@ -161,7 +155,7 @@ public void testCapturingFramesLegacyException() { public void testTranslateStackTraceElementNotEntered() { RootNode rootNode = new TestRootNode3(true); try { - Truffle.getRuntime().createCallTarget(rootNode).call(); + rootNode.getCallTarget().call(); Assert.fail(); } catch (TestException e) { TruffleStackTraceElement stackTraceElement = getStackTraceElementFor(e, rootNode); @@ -176,7 +170,7 @@ public void testTranslateStackTraceElementEntered() throws UnsupportedMessageExc ctx.enter(); RootNode rootNode = new TestRootNode3(true); try { - Truffle.getRuntime().createCallTarget(rootNode).call(); + rootNode.getCallTarget().call(); Assert.fail(); } catch (TestException e) { TruffleStackTraceElement stackTraceElement = getStackTraceElementFor(e, rootNode); @@ -202,7 +196,7 @@ private static void testTranslateStackTraceElementCustomGuestObjectImpl(boolean boolean hasDeclaringMetaObject, boolean isString, boolean isMetaObject) throws UnsupportedMessageException { RootNode rootNode = new TestRootNode5(hasExecutableName, hasDeclaringMetaObject, isString, isMetaObject); try { - Truffle.getRuntime().createCallTarget(rootNode).call(); + rootNode.getCallTarget().call(); Assert.fail(); } catch (TestException e) { TruffleStackTraceElement stackTraceElement = getStackTraceElementFor(e, rootNode); @@ -225,7 +219,7 @@ private static void testTranslateStackTraceElementInvalidCustomGuestObjectImpl(b boolean hasDeclaringMetaObject, boolean isString, boolean isMetaObject) { RootNode rootNode = new TestRootNode5(hasExecutableName, hasDeclaringMetaObject, isString, isMetaObject); try { - Truffle.getRuntime().createCallTarget(rootNode).call(); + rootNode.getCallTarget().call(); Assert.fail(); } catch (TestException e) { TruffleStackTraceElement stackTraceElement = getStackTraceElementFor(e, rootNode); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/StackTraceTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/StackTraceTest.java index 96cbdaa11c21..f5ab296fafd0 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/StackTraceTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/StackTraceTest.java @@ -326,7 +326,7 @@ private static void assertFrameEquals(FrameInstance expected, FrameInstance othe } private static CallTarget createCallTarget(TestCallNode callNode) { - return Truffle.getRuntime().createCallTarget(new TestRootNode(callNode)); + return new TestRootNode(callNode).getCallTarget(); } private static class TestCallWithCallTargetNode extends TestCallNode { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java index 765c6179d026..806c62439b6b 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java @@ -54,7 +54,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.Node; @@ -69,15 +68,14 @@ public class ThreadSafetyTest { @Test @Ignore("sporadic failures with \"expected:<1000000> but was:<999999>\"") public void test() throws InterruptedException { - TruffleRuntime runtime = Truffle.getRuntime(); TestRootNode rootNode1 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new ConstNode(42))))))); - final CallTarget target1 = runtime.createCallTarget(rootNode1); + final CallTarget target1 = rootNode1.getCallTarget(); NodeUtil.verify(rootNode1); RecursiveCallNode callNode = new RecursiveCallNode(new ConstNode(42)); TestRootNode rootNode2 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(callNode)))))); - final CallTarget target2 = runtime.createCallTarget(rootNode2); - callNode.setCallNode(runtime.createDirectCallNode(target2)); + final CallTarget target2 = rootNode2.getCallTarget(); + callNode.setCallNode(Truffle.getRuntime().createDirectCallNode(target2)); NodeUtil.verify(rootNode2); testTarget(target1, 47, 1_000_000); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleExceptionTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleExceptionTest.java index afc924f5ef6a..351f29854faa 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleExceptionTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleExceptionTest.java @@ -42,6 +42,26 @@ import static com.oracle.truffle.api.test.RootNodeTest.verifyStackTraceElementGuestObject; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Queue; +import java.util.Set; +import java.util.function.Consumer; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.regex.Pattern; + +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.PolyglotException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -50,12 +70,12 @@ import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.TruffleStackTrace; import com.oracle.truffle.api.TruffleStackTraceElement; +import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ExceptionType; +import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.exception.AbstractTruffleException; -import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.ExportLibrary; @@ -69,24 +89,6 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest; import com.oracle.truffle.api.test.polyglot.ProxyLanguage; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; -import java.util.Queue; -import java.util.Set; -import java.util.function.Consumer; -import java.util.logging.Handler; -import java.util.logging.LogRecord; -import java.util.regex.Pattern; -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.PolyglotException; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; public class TruffleExceptionTest extends AbstractPolyglotTest { @@ -129,7 +131,7 @@ protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Except ThrowNode throwNode = new ThrowNode((n) -> { return new TruffleExceptionImpl("Test exception", n); }); - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test", null, throwNode)); + return new TestRootNode(languageInstance, "test", null, throwNode).getCallTarget(); } }, " test", @@ -144,9 +146,9 @@ protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Except ThrowNode throwNode = new ThrowNode((n) -> { return new TruffleExceptionImpl("Test exception", n); }); - CallTarget throwTarget = Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test-throw", null, throwNode)); - CallTarget innerInvokeTarget = Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test-call-inner", null, new InvokeNode(throwTarget))); - CallTarget outerInvokeTarget = Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test-call-outer", null, new InvokeNode(innerInvokeTarget))); + CallTarget throwTarget = new TestRootNode(languageInstance, "test-throw", null, throwNode).getCallTarget(); + CallTarget innerInvokeTarget = new TestRootNode(languageInstance, "test-call-inner", null, new InvokeNode(throwTarget)).getCallTarget(); + CallTarget outerInvokeTarget = new TestRootNode(languageInstance, "test-call-outer", null, new InvokeNode(innerInvokeTarget)).getCallTarget(); return outerInvokeTarget; } }, @@ -164,10 +166,10 @@ protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Except ThrowNode throwNode = new ThrowNode((n) -> { return new TruffleExceptionImpl("Test exception", n); }); - CallTarget throwTarget = Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test-throw-internal", null, true, throwNode)); - CallTarget innerInvokeTarget = Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test-call-inner", null, new InvokeNode(throwTarget))); - CallTarget internalInvokeTarget = Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test-call-internal", null, true, new InvokeNode(innerInvokeTarget))); - CallTarget outerInvokeTarget = Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test-call-outer", null, new InvokeNode(internalInvokeTarget))); + CallTarget throwTarget = new TestRootNode(languageInstance, "test-throw-internal", null, true, throwNode).getCallTarget(); + CallTarget innerInvokeTarget = new TestRootNode(languageInstance, "test-call-inner", null, new InvokeNode(throwTarget)).getCallTarget(); + CallTarget internalInvokeTarget = new TestRootNode(languageInstance, "test-call-internal", null, true, new InvokeNode(innerInvokeTarget)).getCallTarget(); + CallTarget outerInvokeTarget = new TestRootNode(languageInstance, "test-call-outer", null, new InvokeNode(internalInvokeTarget)).getCallTarget(); return outerInvokeTarget; } }, @@ -186,7 +188,7 @@ protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Except TruffleStackTrace.fillIn(e); return e; }); - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test", null, throwNode)); + return new TestRootNode(languageInstance, "test", null, throwNode).getCallTarget(); } }, " test", @@ -199,7 +201,7 @@ public void testPolyglotStackTraceInternalError() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { ThrowNode throwNode = new ThrowNode(new InternalExceptionFactory()); - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test", null, throwNode)); + return new TestRootNode(languageInstance, "test", null, throwNode).getCallTarget(); } }, Pattern.quote("com.oracle.truffle.api.test.TruffleExceptionTest$InternalExceptionFactory.apply"), @@ -270,7 +272,7 @@ private void testExceptionFromPolyglotExceptionConstructorImpl(ExceptionType typ @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { ThrowNode throwNode = new ThrowNode((n) -> new TruffleExceptionImpl("test", n, type, new InjectException(failOn))); - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, "test", "unnamed", throwNode)); + return new TestRootNode(languageInstance, "test", "unnamed", throwNode).getCallTarget(); } }); assertFails(() -> context.eval(ProxyLanguage.ID, "Test"), PolyglotException.class, (pe) -> { @@ -288,7 +290,7 @@ static CallTarget createAST(Class testClass, TruffleLanguage(); for (int i = 0; i < threads; i++) { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/GR31558.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/GR31558.java index 148639959c7d..e627d926ce5e 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/GR31558.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/GR31558.java @@ -60,7 +60,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -97,7 +96,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { String src = request.getSource().getCharacters().toString(); RootCallTarget invokeTestApi; if ("testFunction".equals(src)) { - invokeTestApi = Truffle.getRuntime().createCallTarget(new RootNode(ProxyLanguage.get(null)) { + invokeTestApi = new RootNode(ProxyLanguage.get(null)) { @Override public Object execute(VirtualFrame frame) { try { @@ -128,11 +127,11 @@ public Object execute(VirtualFrame frame) { throw new AssertionError(e); } } - }); + }.getCallTarget(); } else { throw new IllegalArgumentException(src); } - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(new HostExceptionTest.CatcherObject(invokeTestApi))); + return RootNode.createConstantNode(new HostExceptionTest.CatcherObject(invokeTestApi)).getCallTarget(); } }); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/HostExceptionTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/HostExceptionTest.java index 8147731cc64d..cce233012a8e 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/HostExceptionTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/HostExceptionTest.java @@ -66,7 +66,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -118,7 +117,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { default: throw new IllegalArgumentException(); } - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(new CatcherObject(Truffle.getRuntime().createCallTarget(rootNode)))); + return RootNode.createConstantNode(new CatcherObject(rootNode.getCallTarget())).getCallTarget(); } }); context.initialize(ProxyLanguage.ID); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/MultiClassLoaderTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/MultiClassLoaderTest.java index 20b7cc4fc381..5843d4751ade 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/MultiClassLoaderTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/MultiClassLoaderTest.java @@ -56,7 +56,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropLibrary; @@ -85,7 +84,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { String req = request.getSource().getCharacters().toString(); if (req.startsWith("get:")) { String name = req.substring(4); - RootCallTarget reader = Truffle.getRuntime().createCallTarget(new RootNode(ProxyLanguage.get(null)) { + RootCallTarget reader = new RootNode(ProxyLanguage.get(null)) { @Override public Object execute(VirtualFrame frame) { Object obj = frame.getArguments()[0]; @@ -96,8 +95,8 @@ public Object execute(VirtualFrame frame) { throw new IllegalStateException(e); } } - }); - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(new CatcherObject(reader))); + }.getCallTarget(); + return RootNode.createConstantNode(new CatcherObject(reader)).getCallTarget(); } throw new IllegalArgumentException(); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/BlockNodeTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/BlockNodeTest.java index 441f55d15635..dc2cd4a0adc5 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/BlockNodeTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/BlockNodeTest.java @@ -56,7 +56,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.BlockNode; import com.oracle.truffle.api.nodes.ControlFlowException; @@ -309,7 +308,7 @@ static BlockNode create(TestBlockElement[] elements, BlockNode DummyRootNode root = new DummyRootNode(); BlockNode block = BlockNode.create(elements, executor); root.block = block; - Truffle.getRuntime().createCallTarget(root); + root.getCallTarget(); assertNotNull(root.block.getParent()); return block; } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/EncapsulatedNodeLegacyTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/EncapsulatedNodeLegacyTest.java index 0233d67a39cb..701e5af92488 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/EncapsulatedNodeLegacyTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/EncapsulatedNodeLegacyTest.java @@ -53,7 +53,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleStackTrace; import com.oracle.truffle.api.TruffleStackTraceElement; import com.oracle.truffle.api.frame.VirtualFrame; @@ -68,22 +67,22 @@ public class EncapsulatedNodeLegacyTest { @Test @SuppressWarnings("unchecked") public void testCallNodePickedByCallTargetCall() { - CallTarget iterateFrames = create(new RootNode(null) { + CallTarget iterateFrames = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return captureStack(); } - }); + }.getCallTarget(); Node callLocation = adopt(new Node() { }); - CallTarget root = create(new RootNode(null) { + CallTarget root = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return boundary(callLocation, () -> IndirectCallNode.getUncached().call(iterateFrames, new Object[0])); } - }); + }.getCallTarget(); List frames = (List) root.call(); assertEquals(2, frames.size()); Iterator iterator = frames.iterator(); @@ -103,12 +102,12 @@ public Object execute(VirtualFrame frame) { public void testCallNodePickedWithoutCallTarget() { Node callLocation = adopt(new Node() { }); - CallTarget root = create(new RootNode(null) { + CallTarget root = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return boundary(callLocation, () -> captureStack()); } - }); + }.getCallTarget(); List frames = (List) root.call(); assertEquals(1, frames.size()); @@ -209,10 +208,6 @@ private static void assertAssertionError(Runnable r) { fail(); } - static CallTarget create(RootNode root) { - return Truffle.getRuntime().createCallTarget(root); - } - @TruffleBoundary private static Object captureStack() { Exception e = new Exception(); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/EncapsulatedNodeTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/EncapsulatedNodeTest.java index 8d25e4b4310f..4d337cdabce7 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/EncapsulatedNodeTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/EncapsulatedNodeTest.java @@ -53,17 +53,16 @@ import java.util.concurrent.TimeUnit; import java.util.function.Supplier; -import com.oracle.truffle.api.nodes.IndirectCallNode; import org.junit.Test; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleStackTrace; import com.oracle.truffle.api.TruffleStackTraceElement; -import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.exception.AbstractTruffleException; +import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.EncapsulatingNodeReference; +import com.oracle.truffle.api.nodes.IndirectCallNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; @@ -75,7 +74,7 @@ public void testCallNodePickedByCallTargetCall() { CallTarget getStackTrace = createGetStackTraceNode(); Node callLocation = adopt(new Node() { }); - CallTarget root = create(new RootNode(null) { + CallTarget root = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { try { @@ -84,7 +83,7 @@ public Object execute(VirtualFrame frame) { return TruffleStackTrace.getStackTrace(e); } } - }); + }.getCallTarget(); Supplier eager = EncapsulatedNodeTest::captureStackEagerly; List framesEager = (List) root.call(eager); @@ -101,7 +100,7 @@ public void testCallNodePickedByUncachedIndirectCallNode() { CallTarget getStackTrace = createGetStackTraceNode(); Node callLocation = adopt(new Node() { }); - CallTarget root = create(new RootNode(null) { + CallTarget root = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { try { @@ -110,7 +109,7 @@ public Object execute(VirtualFrame frame) { return TruffleStackTrace.getStackTrace(e); } } - }); + }.getCallTarget(); Supplier eager = EncapsulatedNodeTest::captureStackEagerly; List framesEager = (List) root.call(eager); @@ -136,13 +135,13 @@ private static void assertCorrectStackTrace(CallTarget getStackTrace, Node callL } private static CallTarget createGetStackTraceNode() { - return create(new RootNode(null) { + return new RootNode(null) { @SuppressWarnings("unchecked") @Override public Object execute(VirtualFrame frame) { return ((Supplier) frame.getArguments()[0]).get(); } - }); + }.getCallTarget(); } @Test @@ -162,12 +161,12 @@ public void testAccessWrongThread() throws InterruptedException, ExecutionExcept public void testCallNodePickedWithoutCallTarget() { Node callLocation = adopt(new Node() { }); - CallTarget root = create(new RootNode(null) { + CallTarget root = new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return boundary(callLocation, () -> captureStackEagerly()); } - }); + }.getCallTarget(); List frames = (List) root.call(); assertEquals(1, frames.size()); @@ -273,10 +272,6 @@ private static void assertAssertionError(Runnable r) { fail(); } - static CallTarget create(RootNode root) { - return Truffle.getRuntime().createCallTarget(root); - } - @TruffleBoundary private static List captureStackEagerly() { Exception e = new Exception(); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/parser/PEParser.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/parser/PEParser.java index 2348123a78cb..e3710e089fe0 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/parser/PEParser.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/parser/PEParser.java @@ -201,7 +201,7 @@ final class Rule extends Element { public CallTarget getCallTarget() { if (target == null) { - target = Truffle.getRuntime().createCallTarget(new RuleRootNode(this)); + target = new RuleRootNode(this).getCallTarget(); } return target; } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/AbstractPolyglotTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/AbstractPolyglotTest.java index 5f85c87bb9e8..b2952e8e0afe 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/AbstractPolyglotTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/AbstractPolyglotTest.java @@ -51,7 +51,6 @@ import org.graalvm.polyglot.Instrument; import org.junit.After; -import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Registration; @@ -194,9 +193,8 @@ protected final Supplier adoptNode(T node) { @SuppressWarnings({"unchecked", "static-method"}) protected final Supplier adoptNode(TruffleLanguage lang, T node) { TestRootNode root = new TestRootNode(lang, node); - CallTarget target = Truffle.getRuntime().createCallTarget(root); // execute it to trigger instrumentations - target.call(); + root.getCallTarget().call(); return () -> (T) root.node; } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ChildContextTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ChildContextTest.java index fa81cc3971b6..9c8edaca978b 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ChildContextTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ChildContextTest.java @@ -44,7 +44,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; @@ -97,7 +96,7 @@ protected LanguageContext createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { REFERENCE.get(null).env.newContextBuilder().build(); - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode("foo")); + return RootNode.createConstantNode("foo").getCallTarget(); } private static final ContextReference REFERENCE = ContextReference.create(InternalLang.class); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITest.java index a14bd244a5ac..b6cb37aceb77 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITest.java @@ -90,7 +90,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.ContextLocal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.VirtualFrame; @@ -325,7 +324,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { throw new SyntaxError(request.getSource().createSection(0, 5)); } - return Truffle.getRuntime().createCallTarget(new RootNode(ProxyLanguage.get(null)) { + return new RootNode(ProxyLanguage.get(null)) { private final com.oracle.truffle.api.source.Source source = request.getSource(); @Override @@ -337,7 +336,7 @@ public Object execute(VirtualFrame frame) { } return source.getCharacters(); } - }); + }.getCallTarget(); } }); } @@ -905,7 +904,7 @@ public void testTransferControlToOtherThreadWhileEntered() { new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(ProxyLanguage.get(null)) { + return new RootNode(ProxyLanguage.get(null)) { @Override public Object execute(VirtualFrame frame) { try { @@ -921,7 +920,7 @@ private Object boundary() throws UnsupportedMessageException, UnsupportedTypeExc "test"); return InteropLibrary.getUncached().execute(o); } - }); + }.getCallTarget(); } }); context.enter(); @@ -1229,14 +1228,14 @@ private static void testContextClassLoaderImpl(Context context, ClassLoader expe ProxyLanguage.setDelegate(new ProxyLanguage() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(this.languageInstance) { + return new RootNode(this.languageInstance) { @Override @TruffleBoundary public Object execute(VirtualFrame frame) { assertEquals(expectedContextClassLoader, Thread.currentThread().getContextClassLoader()); return true; } - }); + }.getCallTarget(); } }); context.eval(Source.newBuilder(ProxyLanguage.ID, "", "test").cached(false).buildLiteral()); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITestInternalLanguage.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITestInternalLanguage.java index 6654c3536f9b..ef8257740f3c 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITestInternalLanguage.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITestInternalLanguage.java @@ -41,7 +41,6 @@ package com.oracle.truffle.api.test.polyglot; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.nodes.RootNode; @@ -57,7 +56,7 @@ protected Object createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode("")); + return RootNode.createConstantNode("").getCallTarget(); } } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITestLanguage.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITestLanguage.java index 156e9a928f79..588e7e93229e 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITestLanguage.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextAPITestLanguage.java @@ -44,7 +44,6 @@ import java.util.function.Function; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; @@ -81,12 +80,12 @@ protected CallTarget parse(ParsingRequest request) throws Exception { result = "null result"; } final Object finalResult = result; - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { return finalResult; } - }); + }.getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolicyTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolicyTest.java index 33daf2c48018..755085e63133 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolicyTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolicyTest.java @@ -64,7 +64,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Option; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.ContextPolicy; @@ -642,7 +641,7 @@ static class SharedObject implements TruffleObject { this.context = context; this.expectedLanguage = language; this.expectedEnvironment = env; - this.target = Truffle.getRuntime().createCallTarget(new RootNode(language) { + this.target = new RootNode(language) { @Child InteropLibrary library = InteropLibrary.getFactory().createDispatched(5); @SuppressWarnings("unchecked") @@ -663,7 +662,7 @@ public Object execute(VirtualFrame frame) { return "done"; } } - }); + }.getCallTarget(); } @ExportMessage @@ -793,7 +792,7 @@ protected OptionDescriptors getOptionDescriptors() { protected CallTarget parse(ParsingRequest request) throws Exception { parseRequest.add(this); boolean innerContext = request.getSource().getName().equals(RUN_INNER_CONTEXT); - return Truffle.getRuntime().createCallTarget(new LanguageRootNode(this, innerContext)); + return new LanguageRootNode(this, innerContext).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java index 6117135f0a7a..b4ebfef74446 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java @@ -57,7 +57,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleLanguage.Registration; @@ -819,7 +818,7 @@ protected Env createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(true)); + return RootNode.createConstantNode(true).getCallTarget(); } public static Env getContext(String language) { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationNativeImageTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationNativeImageTest.java index ffdb56ff1125..9a03673559b2 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationNativeImageTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationNativeImageTest.java @@ -51,7 +51,6 @@ import com.oracle.truffle.api.ContextLocal; import com.oracle.truffle.api.ContextThreadLocal; import com.oracle.truffle.api.ThreadLocalAction; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleOptions; @@ -127,7 +126,7 @@ protected void perform(Access access) { } }); - Truffle.getRuntime().createCallTarget(new RootNode(this) { + new RootNode(this) { @Override public Object execute(VirtualFrame frame) { /* @@ -160,7 +159,7 @@ public Object execute(VirtualFrame frame) { return null; } - }).call(); + }.getCallTarget().call(); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java index 4dfbe0c2af34..ea13b05bcd00 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java @@ -102,7 +102,6 @@ import com.oracle.truffle.api.InstrumentInfo; import com.oracle.truffle.api.Option; import com.oracle.truffle.api.ThreadLocalAction; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.TruffleLanguage; @@ -2293,13 +2292,13 @@ protected void disposeThread(CountingContext context, Thread thread) { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { final CharSequence result = request.getSource().getCharacters(); - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { executeImpl(getContextReference0().get(this)); return result; } - }); + }.getCallTarget(); } protected abstract ContextReference getContextReference0(); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/EngineAPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/EngineAPITest.java index e3869b26aa5c..a9be81eb73ee 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/EngineAPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/EngineAPITest.java @@ -262,7 +262,7 @@ public void testEngineName() { Engine engine = Engine.create(); String implName = engine.getImplementationName(); assertEquals(Truffle.getRuntime().getName(), engine.getImplementationName()); - String name = Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(0)).getClass().getSimpleName(); + String name = RootNode.createConstantNode(0).getCallTarget().getClass().getSimpleName(); if (name.equals("DefaultCallTarget")) { assertEquals(implName, "Interpreted"); } else if (name.endsWith("OptimizedCallTarget")) { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/EngineAPITestLanguage.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/EngineAPITestLanguage.java index 8ffb8441b86a..05ad908c33a1 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/EngineAPITestLanguage.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/EngineAPITestLanguage.java @@ -46,7 +46,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.Option; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.test.polyglot.EngineAPITestLanguage.LanguageContext; @@ -99,7 +98,7 @@ protected OptionDescriptors getOptionDescriptors() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/FileSystemsTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/FileSystemsTest.java index 5a919c7630d5..b988719220db 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/FileSystemsTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/FileSystemsTest.java @@ -106,7 +106,6 @@ import org.junit.runners.Parameterized; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; @@ -2157,13 +2156,13 @@ protected LanguageContext createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { final CharSequence result = request.getSource().getCharacters(); - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { languageAction.accept(CONTEXT_REF.get(this).env()); return result; } - }); + }.getCallTarget(); } private static final ContextReference CONTEXT_REF = ContextReference.create(VirtualizedFileSystemTestLanguage.class); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostStackTraceTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostStackTraceTest.java index 6f134ba7b1dd..d7e83d0e79e1 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostStackTraceTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostStackTraceTest.java @@ -55,7 +55,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; @@ -79,7 +78,7 @@ class HostStackTraceExecutable implements TruffleObject { final CallTarget callTarget; HostStackTraceExecutable(String name, SourceSection rootSection, SourceSection callSection) { - this.callTarget = Truffle.getRuntime().createCallTarget(new ExecuteRootNode(name, rootSection, callSection)); + this.callTarget = new ExecuteRootNode(name, rootSection, callSection).getCallTarget(); } @ExportMessage diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/InteractiveEvalTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/InteractiveEvalTest.java index 68c9573fe97d..9746eb95a8ff 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/InteractiveEvalTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/InteractiveEvalTest.java @@ -58,7 +58,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.VirtualFrame; @@ -148,13 +147,13 @@ protected InteractiveContext createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { return CONTEXT_REF.get(this).getValue(); } - }); + }.getCallTarget(); } private static final ContextReference CONTEXT_REF = ContextReference.create(DefaultInteractiveLanguage.class); @@ -172,7 +171,7 @@ protected InteractiveContext createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { boolean interactive = request.getSource().isInteractive(); - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { @@ -192,7 +191,7 @@ public Object execute(VirtualFrame frame) { private void write(InteractiveContext ic, Object value) throws IOException { ic.env.out().write(("\"" + value + "\"").getBytes(StandardCharsets.UTF_8)); } - }); + }.getCallTarget(); } private static final ContextReference CONTEXT_REF = ContextReference.create(SpecialInteractiveLanguage.class); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPIOrderTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPIOrderTest.java index b098e4dccc5a..e9e03d63cdfe 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPIOrderTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPIOrderTest.java @@ -58,7 +58,6 @@ import com.oracle.truffle.api.TruffleLanguage.Registration; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.source.Source; public class LanguageSPIOrderTest { @@ -292,7 +291,7 @@ private static int nextId() { @Override protected CallTarget parse(com.oracle.truffle.api.TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java index 7638b3865a3a..ab2deb9d04c0 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java @@ -95,7 +95,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.InstrumentInfo; import com.oracle.truffle.api.Option; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.ContextPolicy; @@ -814,7 +813,7 @@ public static LanguageContext getContext() { protected CallTarget parse(ParsingRequest request) throws Exception { executionIndex++; parseCalled.add(request.getSource()); - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return RootNode.createConstantNode(42).getCallTarget(); } @Override @@ -1222,7 +1221,7 @@ protected Object findMetaObject(LanguageContext context, Object value) { @Override protected CallTarget parse(com.oracle.truffle.api.TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(testObject)); + return RootNode.createConstantNode(testObject).getCallTarget(); } @Override @@ -1845,12 +1844,12 @@ public void testPolyglotBindings() { ProxyLanguage.setDelegate(new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { return LanguageContext.get(this).env.getPolyglotBindings(); } - }); + }.getCallTarget(); } }); @@ -1883,12 +1882,12 @@ protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { return LanguageContext.get(this).env.getPolyglotBindings(); } - }); + }.getCallTarget(); } }); @@ -1931,7 +1930,7 @@ public void testFindSourceLocation() { ProxyLanguage.setDelegate(new ProxyLanguage() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(new SourceHolder(request.getSource()))); + return RootNode.createConstantNode(new SourceHolder(request.getSource())).getCallTarget(); } @Override @@ -1968,7 +1967,7 @@ public void testToString() { ProxyLanguage.setDelegate(new ProxyLanguage() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(new SourceHolder(request.getSource()))); + return RootNode.createConstantNode(new SourceHolder(request.getSource())).getCallTarget(); } @Override @@ -2109,7 +2108,7 @@ protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Except } catch (IllegalStateException e) { // expected } - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(true)); + return RootNode.createConstantNode(true).getCallTarget(); } }; ProxyLanguage.setDelegate(registerServiceLanguage); @@ -2201,7 +2200,7 @@ private static void testInitializeInternalImpl(Context context, Function context.eval(ProxyLanguage.ID, "test"), PolyglotException.class, (e) -> { @@ -487,7 +486,7 @@ protected CallTarget parse(ParsingRequest request) { Source source = request.getSource(); SizeNode callHost = PolyglotExceptionTestFactory.SizeNodeGen.create( PolyglotExceptionTestFactory.ReadBindingsNodeGen.create()); - return Truffle.getRuntime().createCallTarget(new CallHostRootNode(languageInstance, source, callHost)); + return new CallHostRootNode(languageInstance, source, callHost).getCallTarget(); } }); context.getPolyglotBindings().putMember("receiver", new BrokenList<>()); @@ -538,7 +537,7 @@ public void testCancelDoesNotMaskInternalError() throws InterruptedException, Ex setupEnv(Context.create(), new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(ProxyLanguage.get(null)) { + return new RootNode(ProxyLanguage.get(null)) { @Override public Object execute(VirtualFrame frame) { @@ -568,7 +567,7 @@ public String getName() { return "testRootName"; } - }); + }.getCallTarget(); } }); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/RequireContextTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/RequireContextTest.java index c063990414c0..ab921c36c958 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/RequireContextTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/RequireContextTest.java @@ -40,23 +40,23 @@ */ package com.oracle.truffle.api.test.polyglot; -import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.nio.file.Paths; +import java.util.function.Consumer; + +import org.graalvm.polyglot.Context; +import org.junit.Test; + +import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Registration; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.test.polyglot.ProxyLanguage.LanguageContext; -import java.nio.file.Paths; -import java.util.function.Consumer; -import org.graalvm.polyglot.Context; -import org.junit.Test; - public class RequireContextTest extends AbstractPolyglotTest { public RequireContextTest() { @@ -82,7 +82,7 @@ public void testInstrument() throws Exception { setupEnv(Context.create(), new ProxyLanguage() { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(true)); + return RootNode.createConstantNode(true).getCallTarget(); } }); assertFails(() -> instrumentEnv.getTruffleFile("file"), IllegalStateException.class, NoCurrentContextVerifier.INSTANCE); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/RetainedSizeContextBoundaryTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/RetainedSizeContextBoundaryTest.java index 1b39fcdf0949..8da9b19a1915 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/RetainedSizeContextBoundaryTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/RetainedSizeContextBoundaryTest.java @@ -234,7 +234,7 @@ public void testRetainedSizeWithHostToGuestRootNode() { protected CallTarget parse(ParsingRequest request) { com.oracle.truffle.api.source.Source source = request.getSource(); if (target == null) { - target = Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + target = new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { @@ -246,7 +246,7 @@ public SourceSection getSourceSection() { return source.createSection(1); } - }); + }.getCallTarget(); } return target; } @@ -279,7 +279,7 @@ public void testRetainedSizeWithGuestToHostRootNode() { protected CallTarget parse(ParsingRequest request) { com.oracle.truffle.api.source.Source source = request.getSource(); if (target == null) { - target = Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + target = new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { @@ -296,7 +296,7 @@ public SourceSection getSourceSection() { return source.createSection(1); } - }); + }.getCallTarget(); } return target; } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ScopedViewLegacyTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ScopedViewLegacyTest.java index d95a3aa3ff08..59aa14b300f8 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ScopedViewLegacyTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ScopedViewLegacyTest.java @@ -164,7 +164,7 @@ public Object execute(VirtualFrame frame) { static TestRootNode createRoot(TruffleLanguage lang) { TestRootNode root = new TestRootNode(lang); - Truffle.getRuntime().createCallTarget(new TestRootNode(lang)); + root.getCallTarget(); return root; } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ScopedViewTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ScopedViewTest.java index 9d4ea4f6a584..4ade6cba89d0 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ScopedViewTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ScopedViewTest.java @@ -146,7 +146,7 @@ public Object execute(VirtualFrame frame) { static TestRootNode createRoot(TruffleLanguage lang) { TestRootNode root = new TestRootNode(lang); - Truffle.getRuntime().createCallTarget(new TestRootNode(lang)); + root.getCallTarget(); return root; } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITestLanguage.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITestLanguage.java index 4bbb31806e8f..3c9327ea3ac9 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITestLanguage.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITestLanguage.java @@ -43,7 +43,6 @@ import java.util.function.Function; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.test.polyglot.SourceAPITestLanguage.LanguageContext; @@ -81,7 +80,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { if (result == null) { result = "null result"; } - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(result)); + return RootNode.createConstantNode(result).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ValueAPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ValueAPITest.java index 96dd4a4195a3..7b78cd9b0cf0 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ValueAPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ValueAPITest.java @@ -123,7 +123,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -1875,7 +1874,7 @@ public void testValueContextPropagation() { ProxyLanguage.setDelegate(new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(o)); + return RootNode.createConstantNode(o).getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ValueHostConversionTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ValueHostConversionTest.java index 1e39a407e918..881485b2ecb6 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ValueHostConversionTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ValueHostConversionTest.java @@ -40,24 +40,20 @@ */ package com.oracle.truffle.api.test.polyglot; -import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleOptions; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.api.test.examples.TargetMappings; -import com.oracle.truffle.tck.tests.ValueAssert.Trait; -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.HostAccess; -import org.graalvm.polyglot.HostAccess.TargetMappingPrecedence; -import org.graalvm.polyglot.PolyglotException; -import org.graalvm.polyglot.PolyglotException.StackFrame; -import org.graalvm.polyglot.Value; -import org.graalvm.polyglot.proxy.Proxy; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; +import static com.oracle.truffle.tck.tests.ValueAssert.assertUnsupported; +import static com.oracle.truffle.tck.tests.ValueAssert.assertValue; +import static com.oracle.truffle.tck.tests.ValueAssert.Trait.BOOLEAN; +import static com.oracle.truffle.tck.tests.ValueAssert.Trait.HOST_OBJECT; +import static com.oracle.truffle.tck.tests.ValueAssert.Trait.MEMBERS; +import static com.oracle.truffle.tck.tests.ValueAssert.Trait.NULL; +import static com.oracle.truffle.tck.tests.ValueAssert.Trait.NUMBER; +import static com.oracle.truffle.tck.tests.ValueAssert.Trait.PROXY_OBJECT; +import static com.oracle.truffle.tck.tests.ValueAssert.Trait.STRING; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -72,20 +68,24 @@ import java.util.function.Function; import java.util.function.Supplier; -import static com.oracle.truffle.tck.tests.ValueAssert.Trait.BOOLEAN; -import static com.oracle.truffle.tck.tests.ValueAssert.Trait.HOST_OBJECT; -import static com.oracle.truffle.tck.tests.ValueAssert.Trait.MEMBERS; -import static com.oracle.truffle.tck.tests.ValueAssert.Trait.NULL; -import static com.oracle.truffle.tck.tests.ValueAssert.Trait.NUMBER; -import static com.oracle.truffle.tck.tests.ValueAssert.Trait.PROXY_OBJECT; -import static com.oracle.truffle.tck.tests.ValueAssert.Trait.STRING; -import static com.oracle.truffle.tck.tests.ValueAssert.assertUnsupported; -import static com.oracle.truffle.tck.tests.ValueAssert.assertValue; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.HostAccess; +import org.graalvm.polyglot.HostAccess.TargetMappingPrecedence; +import org.graalvm.polyglot.PolyglotException; +import org.graalvm.polyglot.PolyglotException.StackFrame; +import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.proxy.Proxy; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.TruffleOptions; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.test.examples.TargetMappings; +import com.oracle.truffle.tck.tests.ValueAssert.Trait; /** * Tests class for {@link Context#asValue(Object)}. @@ -280,12 +280,12 @@ private Value getStaticClass(Class clazz) { ProxyLanguage.setDelegate(new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) { - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { return LanguageContext.get(this).env.lookupHostSymbol(clazz.getName()); } - }); + }.getCallTarget(); } }); return context.asValue(context.eval(ProxyLanguage.ID, clazz.getName())); diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java index 796e3f6b6793..b1a1a087c894 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java @@ -44,9 +44,8 @@ /** * Represents the target of a call. Do not subclass {@link CallTarget} directly but implement - * {@link RootNode} instead and create a {@link CallTarget target} using {@link Truffle}. - * {@link Truffle#getRuntime() getRuntime()}.{@link TruffleRuntime#createCallTarget(RootNode) - * createCallTarget(rootNode)}. + * {@link RootNode} instead and retrieve its {@link CallTarget target} via + * {@link RootNode#getCallTarget()}. * * @see RootNode * @since 0.8 or earlier diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java index c8186229118f..2c28b3776015 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java @@ -44,8 +44,8 @@ /** * Represents the target of a call to a {@link RootNode}, i.e., to another tree of nodes. Instances - * of this class can be created using {@link TruffleRuntime#createCallTarget(RootNode)}. - * + * of this class are created lazily and can be accessed via {@link RootNode#getCallTarget()}. + * * @since 0.8 or earlier */ public interface RootCallTarget extends CallTarget { diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java index d60d2c71baa0..5413cbe096c1 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @@ -1570,7 +1570,7 @@ protected static > C getCurrentContext(Class * * @Override * protected CallTarget parse(ParsingRequest request) throws Exception { - * return Truffle.getRuntime().createCallTarget(new RootNode(this) { + * return new RootNode(this) { * @Override * public Object execute(VirtualFrame frame) { * // fast read @@ -1578,7 +1578,7 @@ protected static > C getCurrentContext(Class * // access local * return ""; * } - * }); + * }.getCallTarget(); * } * * static final class ExampleLocal { @@ -1640,7 +1640,7 @@ protected final ContextLocal createContextLocal(ContextLocalFactory * * @Override * protected CallTarget parse(ParsingRequest request) throws Exception { - * return Truffle.getRuntime().createCallTarget(new RootNode(this) { + * return new RootNode(this) { * @Override * public Object execute(VirtualFrame frame) { * // fast read @@ -1648,7 +1648,7 @@ protected final ContextLocal createContextLocal(ContextLocalFactory * // access local * return ""; * } - * }); + * }.getCallTarget(); * } * * static final class ExampleLocal { diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java index b73ead50676e..c3a06b1f654f 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java @@ -43,7 +43,6 @@ import static com.oracle.truffle.api.impl.DefaultTruffleRuntime.getRuntime; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.TruffleSafepoint; import com.oracle.truffle.api.impl.DefaultTruffleRuntime.DefaultFrameInstance; import com.oracle.truffle.api.nodes.EncapsulatingNodeReference; @@ -52,7 +51,7 @@ /** * This is an implementation-specific class. Do not use or instantiate it. Instead, use - * {@link TruffleRuntime#createCallTarget(RootNode)} to create a {@link RootCallTarget}. + * {@link RootNode#getCallTarget()} to get the {@link RootCallTarget} of a root node. */ public final class DefaultCallTarget implements RootCallTarget { diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java index 548653969f93..74b34ea6207e 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java @@ -89,7 +89,7 @@ protected Closeable createTestContext(String testName) { @Override public CallTarget createTestCallTarget(Closeable testContext, RootNode testNode) { - return createCallTarget(testNode); + return testNode.getCallTarget(); } @Override diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java index d7bf912541bc..c1febe3c9bbd 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java @@ -57,7 +57,6 @@ import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleLanguage.ParsingRequest; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.TruffleStackTraceElement; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; @@ -85,13 +84,13 @@ * *

Execution

* - * In order to execute a root node, a call target needs to be created using - * {@link TruffleRuntime#createCallTarget(RootNode)}. This allows the runtime system to optimize the - * execution of the AST. The {@link CallTarget} can either be {@link CallTarget#call(Object...) - * called} directly from runtime code or {@link DirectCallNode direct} and {@link IndirectCallNode - * indirect} call nodes can be created, inserted in a child field and - * {@link DirectCallNode#call(Object[]) called}. The use of direct call nodes allows the framework - * to automatically inline and further optimize call sites based on heuristics. + * In order to execute a root node, its call target is lazily created and can be accessed via + * {@link RootNode#getCallTarget()}. This allows the runtime system to optimize the execution of the + * AST. The {@link CallTarget} can either be {@link CallTarget#call(Object...) called} directly from + * runtime code or {@link DirectCallNode direct} and {@link IndirectCallNode indirect} call nodes + * can be created, inserted in a child field and {@link DirectCallNode#call(Object[]) called}. The + * use of direct call nodes allows the framework to automatically inline and further optimize call + * sites based on heuristics. *

* After several calls to a call target or call node, the root node might get compiled using partial * evaluation. The details of the compilation heuristic are unspecified, therefore the Truffle From 8d7cf23dabfa9a15d26b620f83c423ff39b95013 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 27 Sep 2021 13:17:11 +0200 Subject: [PATCH 185/681] Avoid createCallTarget() in compiler. --- .../truffle/runtime/GraalTestTVMCI.java | 2 +- .../truffle/runtime/OptimizedBlockNode.java | 2 +- .../jdk11/VarHandlePartialEvaluationTest.java | 3 +- .../test/AOTSupportCompilationTest.java | 3 +- .../test/AbstractSplittingStrategyTest.java | 2 +- .../test/AgnosticInliningPhaseTest.java | 6 +- ...locationReporterPartialEvaluationTest.java | 12 +-- .../AssumedValuePartialEvaluationTest.java | 12 +-- ...ecodeInterpreterPartialEvaluationTest.java | 3 +- .../truffle/test/BytecodeOSRNodeTest.java | 79 +++++++++--------- .../test/CastExactPartialEvaluationTest.java | 3 +- .../truffle/test/ClearFrameSlotTest.java | 3 +- .../truffle/test/CodeInvalidationTest.java | 4 +- .../truffle/test/CompilationMemoryTest.java | 11 +-- .../truffle/test/CompilerLoggingTest.java | 2 +- ...rolFlowExceptionPartialEvaluationTest.java | 2 +- .../test/DFAPartialEvaluationTest.java | 5 +- .../truffle/test/EncodedGraphCacheTest.java | 5 +- .../compiler/truffle/test/EngineModeTest.java | 20 ++--- .../truffle/test/ExceptionActionTest.java | 21 ++--- .../test/ExplodeLoopBlockDuplicationTest.java | 3 +- .../truffle/test/FlushEngineQueueTest.java | 5 +- .../test/GraalTruffleRuntimeListenerTest.java | 12 +-- .../truffle/test/IndirectCallSiteTest.java | 38 ++++----- .../test/LanguageContextFreedTest.java | 7 +- .../truffle/test/LazyClassLoadingTest.java | 4 +- .../test/LibrarySplittingStrategyTest.java | 27 +++---- .../truffle/test/LoopNodeOSRTest.java | 2 +- .../test/LoopNodePartialEvaluationTest.java | 8 +- .../truffle/test/MaterializedFrameTest.java | 3 +- .../truffle/test/MergeExplodeProxyTest.java | 15 ++-- .../test/MultiTierCompilationTest.java | 24 +++--- .../compiler/truffle/test/NodeLimitTest.java | 9 +-- .../test/NodeSplittingStrategyTest.java | 81 +++++++++---------- .../compiler/truffle/test/OSRCancelTest.java | 4 +- ...tsRequireNonNullPartialEvaluationTest.java | 9 +-- .../truffle/test/OptimizedBlockNodeTest.java | 2 +- .../truffle/test/OptimizedCallTargetTest.java | 54 ++++++------- .../test/OptimizedOSRLoopNodeTest.java | 54 ++++++------- .../truffle/test/OverrideOptionsTest.java | 3 +- .../truffle/test/PartialEvaluationTest.java | 12 ++- .../truffle/test/PerformanceWarningTest.java | 10 +-- ...hiStampInferencePartialEvaluationTest.java | 3 +- .../test/PolyglotEngineOptionsTest.java | 7 +- .../test/RewriteDuringCompilationTest.java | 4 +- .../ThreadsActivationCompilationTest.java | 4 +- .../truffle/test/TraceCompilationTest.java | 18 +++-- .../test/TransferToInterpreterTest.java | 2 +- .../test/TruffleBoundaryExceptionsTest.java | 8 +- .../test/TruffleBoundaryInliningTest.java | 11 +-- .../truffle/test/TruffleCompilerImplTest.java | 6 +- .../test/TruffleDirectCallNodeTest.java | 2 +- ...TruffleExceptionPartialEvaluationTest.java | 6 +- .../test/TruffleReturnBoxedParameterTest.java | 3 +- ...ffleToTruffleCallExceptionHandlerTest.java | 16 ++-- .../test/UnrollLoopBlockDuplicationTest.java | 3 +- .../truffle/test/inlining/InlineOnlyTest.java | 23 +++--- .../truffle/test/inlining/InliningTest.java | 12 ++- .../libgraal/JNIExceptionWrapperTest.java | 2 +- 59 files changed, 333 insertions(+), 383 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTestTVMCI.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTestTVMCI.java index 2a46c58dc2ea..ae21216aa02c 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTestTVMCI.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTestTVMCI.java @@ -109,7 +109,7 @@ protected GraalTestContext createTestContext(String testName) { @Override public OptimizedCallTarget createTestCallTarget(GraalTestContext testContext, RootNode testNode) { - OptimizedCallTarget target = (OptimizedCallTarget) truffleRuntime.createCallTarget(testNode); + OptimizedCallTarget target = (OptimizedCallTarget) testNode.getCallTarget(); testContext.init(target); return target; } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedBlockNode.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedBlockNode.java index f49f7851c0eb..50f81a9eceb2 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedBlockNode.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedBlockNode.java @@ -647,7 +647,7 @@ public static final class PartialBlocks { PartialBlockRootNode partialRootNode = new PartialBlockRootNode<>(new FrameDescriptor(), block, startIndex, endIndex, blockIndex); GraalRuntimeAccessor.NODES.applyPolyglotEngine(rootNode, partialRootNode); - targets[i] = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(partialRootNode); + targets[i] = (OptimizedCallTarget) partialRootNode.getCallTarget(); targets[i].setNonTrivialNodeCount(blockSizes[i]); // we know the parameter types for block compilations. No need to check, lets cast // them unsafely. diff --git a/compiler/src/org.graalvm.compiler.truffle.test.jdk11/src/org/graalvm/compiler/truffle/test/jdk11/VarHandlePartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test.jdk11/src/org/graalvm/compiler/truffle/test/jdk11/VarHandlePartialEvaluationTest.java index b3ae1ded3fae..037c1cf474f9 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test.jdk11/src/org/graalvm/compiler/truffle/test/jdk11/VarHandlePartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test.jdk11/src/org/graalvm/compiler/truffle/test/jdk11/VarHandlePartialEvaluationTest.java @@ -38,7 +38,6 @@ import org.junit.Test; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; @@ -89,7 +88,7 @@ public void byteBufferHandleSet() { private void testCommon(AbstractTestNode testNode, String testName, Object... args) { FrameDescriptor fd = new FrameDescriptor(); RootNode rootNode = new RootTestNode(fd, testName, testNode); - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); + RootCallTarget callTarget = rootNode.getCallTarget(); Assert.assertEquals(42, callTarget.call(args)); assertPartialEvalNoInvokes(callTarget, args); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AOTSupportCompilationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AOTSupportCompilationTest.java index fe8a66b95fff..0ece769184e5 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AOTSupportCompilationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AOTSupportCompilationTest.java @@ -26,7 +26,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; -import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.polyglot.Context; import org.junit.Test; @@ -115,7 +114,7 @@ private TestRootNode setup(BaseNode node, Object receiver) { context.initialize(ProxyLanguage.ID); context.enter(); TestRootNode root = new TestRootNode(TestLanguage.getCurrentLanguage(), node, receiver); - GraalTruffleRuntime.getRuntime().createCallTarget(root); + root.getCallTarget(); context.leave(); return root; } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AbstractSplittingStrategyTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AbstractSplittingStrategyTest.java index 4a25d91ac58d..c12fbdb541cc 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AbstractSplittingStrategyTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AbstractSplittingStrategyTest.java @@ -134,7 +134,7 @@ protected static void reflectivelySetField(Object o, String fieldName, Object va protected static void createDummyTargetsToBoostGrowingSplitLimit() { for (int i = 0; i < 10; i++) { - runtime.createCallTarget(new DummyRootNode()); + new DummyRootNode().getCallTarget(); } } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AgnosticInliningPhaseTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AgnosticInliningPhaseTest.java index 5174697b39ca..7701221859c1 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AgnosticInliningPhaseTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AgnosticInliningPhaseTest.java @@ -91,13 +91,13 @@ public boolean hasNextTier() { return request.graph; } - protected final OptimizedCallTarget createDummyNode() { - return (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + protected static final OptimizedCallTarget createDummyNode() { + return (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return null; } - }); + }.getCallTarget(); } protected class CallsInnerNodeTwice extends RootNode { diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AllocationReporterPartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AllocationReporterPartialEvaluationTest.java index 8fe0b00967cd..4a6cad5a3184 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AllocationReporterPartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AllocationReporterPartialEvaluationTest.java @@ -28,13 +28,11 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.PolyglotAccess; import org.junit.Test; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.AllocationEvent; @@ -52,8 +50,6 @@ */ public class AllocationReporterPartialEvaluationTest extends TestWithSynchronousCompiling { - private static final GraalTruffleRuntime runtime = (GraalTruffleRuntime) Truffle.getRuntime(); - @Test public void testConsistentAssertions() { // Test that onEnter()/onReturnValue() are not broken @@ -64,20 +60,20 @@ public void testConsistentAssertions() { assertNotNull(tester); final AllocationReporter reporter = (AllocationReporter) context.getPolyglotBindings().getMember(AllocationReporter.class.getSimpleName()).asHostObject(); final Long[] value = new Long[]{1L}; - OptimizedCallTarget enterTarget = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + OptimizedCallTarget enterTarget = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { reporter.onEnter(value[0], 4, 8); return null; } - }); - OptimizedCallTarget returnTarget = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + }.getCallTarget(); + OptimizedCallTarget returnTarget = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { reporter.onReturnValue(value[0], 4, 8); return null; } - }); + }.getCallTarget(); // Interpret both: assertNotCompiled(enterTarget); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AssumedValuePartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AssumedValuePartialEvaluationTest.java index 4a223433ac01..46ce97d04eff 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AssumedValuePartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/AssumedValuePartialEvaluationTest.java @@ -24,10 +24,6 @@ */ package org.graalvm.compiler.truffle.test; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.frame.FrameDescriptor; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.utilities.AssumedValue; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.compiler.truffle.test.nodes.AbstractTestNode; @@ -35,6 +31,10 @@ import org.junit.Assert; import org.junit.Test; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.utilities.AssumedValue; + public class AssumedValuePartialEvaluationTest extends PartialEvaluationTest { public static Object constant42() { @@ -73,7 +73,7 @@ public void testDynamic() { AssumedValue value = new AssumedValue<>(42); RootTestNode root = new RootTestNode(new FrameDescriptor(), "assumedValue", new ReadDynamicAssumedValueNode()); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); + OptimizedCallTarget target = (OptimizedCallTarget) root.getCallTarget(); StructuredGraph graph = partialEval(target, new Object[]{value}); compile(target, graph); @@ -87,7 +87,7 @@ public void testDynamicNoDeopt() { AssumedValue value = new AssumedValue<>(42); RootTestNode root = new RootTestNode(new FrameDescriptor(), "assumedValue", new ReadDynamicAssumedValueNode()); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); + OptimizedCallTarget target = (OptimizedCallTarget) root.getCallTarget(); StructuredGraph graph = partialEval(target, new Object[]{value}); compile(target, graph); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/BytecodeInterpreterPartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/BytecodeInterpreterPartialEvaluationTest.java index f788de91a007..2f5a99971334 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/BytecodeInterpreterPartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/BytecodeInterpreterPartialEvaluationTest.java @@ -40,7 +40,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -257,7 +256,7 @@ public static Object constant42() { } private static void assertReturns42(RootNode program) { - Object result = Truffle.getRuntime().createCallTarget(program).call(); + Object result = program.getCallTarget().call(); Assert.assertEquals(Integer.valueOf(42), result); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/BytecodeOSRNodeTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/BytecodeOSRNodeTest.java index 2d58147c9534..42e79fffb343 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/BytecodeOSRNodeTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/BytecodeOSRNodeTest.java @@ -24,6 +24,19 @@ */ package org.graalvm.compiler.truffle.test; +import java.util.concurrent.TimeUnit; + +import org.graalvm.compiler.truffle.runtime.BytecodeOSRMetadata; +import org.graalvm.compiler.truffle.runtime.FrameWithoutBoxing; +import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; +import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; + import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -38,22 +51,10 @@ import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.BytecodeOSRNode; +import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; -import org.graalvm.compiler.truffle.runtime.BytecodeOSRMetadata; -import org.graalvm.compiler.truffle.runtime.FrameWithoutBoxing; -import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; -import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; - -import java.util.concurrent.TimeUnit; public class BytecodeOSRNodeTest extends TestWithSynchronousCompiling { @@ -79,7 +80,7 @@ public void before() { @Test public void testSimpleInterpreterLoop() { RootNode rootNode = new Program(new InfiniteInterpreterLoop(), new FrameDescriptor()); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); // Interpreter invocation should be OSR compiled and break out of the interpreter loop. Assert.assertEquals(42, target.call()); } @@ -92,7 +93,7 @@ public void testFixedIterationLoop() { FrameDescriptor frameDescriptor = new FrameDescriptor(); FixedIterationLoop osrNode = new FixedIterationLoop(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(FixedIterationLoop.OSR_RESULT, target.call(osrThreshold + 1)); } @@ -104,7 +105,7 @@ public void testFixedIterationLoopBelowThreshold() { FrameDescriptor frameDescriptor = new FrameDescriptor(); FixedIterationLoop osrNode = new FixedIterationLoop(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(FixedIterationLoop.NORMAL_RESULT, target.call(osrThreshold)); } @@ -117,21 +118,21 @@ public void testMultipleLoops() { FrameDescriptor frameDescriptor = new FrameDescriptor(); TwoFixedIterationLoops osrNode = new TwoFixedIterationLoops(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(TwoFixedIterationLoops.OSR_IN_FIRST_LOOP, target.call(osrThreshold + 1)); // Each loop runs for osrThreshold/2 + 1 iterations, so the second loop should trigger OSR. frameDescriptor = new FrameDescriptor(); osrNode = new TwoFixedIterationLoops(frameDescriptor); rootNode = new Program(osrNode, frameDescriptor); - target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(TwoFixedIterationLoops.OSR_IN_SECOND_LOOP, target.call(osrThreshold / 2 + 1)); // Each loop runs for osrThreshold/2 iterations, so OSR should not get triggered. frameDescriptor = new FrameDescriptor(); osrNode = new TwoFixedIterationLoops(frameDescriptor); rootNode = new Program(osrNode, frameDescriptor); - target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(TwoFixedIterationLoops.NO_OSR, target.call(osrThreshold / 2)); } @@ -143,7 +144,7 @@ public void testFailedCompilation() { FrameDescriptor frameDescriptor = new FrameDescriptor(); UncompilableFixedIterationLoop osrNode = new UncompilableFixedIterationLoop(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(FixedIterationLoop.NORMAL_RESULT, target.call(osrThreshold + 1)); // Compilation should be disabled after a compilation failure. Assert.assertEquals(osrNode.getGraalOSRMetadata(), BytecodeOSRMetadata.DISABLED); @@ -157,7 +158,7 @@ public void testDeoptimizeAndRecompile() { FrameDescriptor frameDescriptor = new FrameDescriptor(); DeoptimizingFixedIterationLoop osrNode = new DeoptimizingFixedIterationLoop(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); // After osrThreshold+1 iterations, it should trigger OSR and deoptimize. OSR should not be // disabled, but the target should be invalid pending recompilation. Assert.assertEquals(FixedIterationLoop.NORMAL_RESULT, target.call(osrThreshold + 1)); @@ -183,7 +184,7 @@ public void testInvalidateOnNodeReplaced() { }; FixedIterationLoop osrNode = new FixedIterationLoopWithChild(frameDescriptor, childToReplace); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(FixedIterationLoop.OSR_RESULT, target.call(osrThreshold + 1)); BytecodeOSRMetadata osrMetadata = osrNode.getGraalOSRMetadata(); OptimizedCallTarget osrTarget = osrMetadata.getOSRCompilations().get(BytecodeOSRTestNode.DEFAULT_TARGET); @@ -214,7 +215,7 @@ public void testOSRWithMaterializeableFrame() { runtime.markFrameMaterializeCalled(frameDescriptor); MaterializedFixedIterationLoop osrNode = new MaterializedFixedIterationLoop(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); // OSR should succeed. Assert.assertEquals(FixedIterationLoop.OSR_RESULT, target.call(osrThreshold + 1)); // Since the frame could be materialized, we should reuse the parent frame instead of @@ -235,7 +236,7 @@ public void testOSRPolling() { ); InfiniteInterpreterLoop osrNode = new InfiniteInterpreterLoop(); RootNode rootNode = new Program(osrNode, new FrameDescriptor()); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(42, target.call()); BytecodeOSRMetadata osrMetadata = osrNode.getGraalOSRMetadata(); int backEdgeCount = osrMetadata.getBackEdgeCount(); @@ -249,7 +250,7 @@ public void testOSRPolling() { @Test public void testInterpreterStateObject() { RootNode rootNode = new Program(new InterpreterStateInfiniteLoop(), new FrameDescriptor()); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(42, target.call()); } @@ -259,7 +260,7 @@ public void testInterpreterStateObject() { @Test public void testBeforeTransferCallback() { RootNode rootNode = new Program(new BeforeTransferInfiniteLoop(), new FrameDescriptor()); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(42, target.call()); } @@ -271,7 +272,7 @@ public void testStackTraceHidesOSRCallTarget() { FrameDescriptor frameDescriptor = new FrameDescriptor(); CheckStackWalkCallTarget osrNode = new CheckStackWalkCallTarget(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(FixedIterationLoop.OSR_RESULT, target.call(2 * osrThreshold)); } @@ -283,7 +284,7 @@ public void testStackTraceUsesOSRFrame() { FrameDescriptor frameDescriptor = new FrameDescriptor(); CheckStackWalkFrame osrNode = new CheckStackWalkFrame(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); osrNode.callTarget = target; // set the call target so stack walking can use it Assert.assertEquals(FixedIterationLoop.OSR_RESULT, target.call(2 * osrThreshold)); } @@ -297,7 +298,7 @@ public void testStackTraceUsesNewestOSRFrame() { FrameDescriptor frameDescriptor = new FrameDescriptor(); CheckStackWalkFrameNested osrNode = new CheckStackWalkFrameNested(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); osrNode.callTarget = target; // set the call target so stack walking can use it Assert.assertEquals(FixedIterationLoop.OSR_RESULT, target.call(3 * osrThreshold)); Assert.assertTrue(osrNode.hasDeoptimizedYet); @@ -314,9 +315,9 @@ public void testGetCallerFrameSkipsOSR() { FrameDescriptor frameDescriptor = new FrameDescriptor(); CheckGetCallerFrameSkipsOSR osrNode = new CheckGetCallerFrameSkipsOSR(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); RootNode caller = new CheckGetCallerFrameSkipsOSR.Caller(target); - OptimizedCallTarget callerTarget = (OptimizedCallTarget) runtime.createCallTarget(caller); + OptimizedCallTarget callerTarget = (OptimizedCallTarget) caller.getCallTarget(); osrNode.caller = callerTarget; Assert.assertEquals(FixedIterationLoop.OSR_RESULT, callerTarget.call(osrThreshold + 1)); } @@ -328,7 +329,7 @@ public void testGetCallerFrameSkipsOSR() { public void testFrameTransfer() { FrameDescriptor frameDescriptor = new FrameDescriptor(); RootNode rootNode = new Program(new FrameTransferringNode(frameDescriptor), frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(42, target.call()); } @@ -340,7 +341,7 @@ public void testFrameTransfer() { public void testFrameTransferWithTagUpdate() { FrameDescriptor frameDescriptor = new FrameDescriptor(); RootNode rootNode = new Program(new FrameTransferringNodeWithTagUpdate(frameDescriptor), frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(42, target.call()); } @@ -357,7 +358,7 @@ public void testFrameTransferWithUninitializedSlots() { // use a non-null default value to make sure it gets copied properly. FrameDescriptor frameDescriptor = new FrameDescriptor(new Object()); RootNode rootNode = new Program(new FrameTransferringNodeWithUninitializedSlots(frameDescriptor), frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(42, target.call()); } @@ -370,7 +371,7 @@ public void testFrameChanges() { FrameDescriptor frameDescriptor = new FrameDescriptor(); FrameChangingNode osrNode = new FrameChangingNode(frameDescriptor); RootNode rootNode = new Program(osrNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(42, target.call()); Assert.assertEquals(2, osrNode.osrCount); } @@ -411,7 +412,7 @@ public void testOSRInBytecodeLoop() { FrameDescriptor frameDescriptor = new FrameDescriptor(); BytecodeNode bytecodeNode = new BytecodeNode(3, frameDescriptor, tripleInput1); RootNode rootNode = new Program(bytecodeNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); // note: requires an extra iteration due to an awkward interaction with enterprise loop // peeling. Assert.assertEquals(3 * (osrThreshold + 2), target.call(osrThreshold + 2, 0)); @@ -428,7 +429,7 @@ public void testNoOSRInBytecodeLoop() { FrameDescriptor frameDescriptor = new FrameDescriptor(); BytecodeNode bytecodeNode = new BytecodeNode(3, frameDescriptor, tripleInput1); RootNode rootNode = new Program(bytecodeNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(3 * osrThreshold, target.call(osrThreshold, 0)); Assert.assertFalse(bytecodeNode.compiled); BytecodeOSRMetadata osrMetadata = (BytecodeOSRMetadata) bytecodeNode.getOSRMetadata(); @@ -443,7 +444,7 @@ public void testOSRInBytecodeOuterLoop() { FrameDescriptor frameDescriptor = new FrameDescriptor(); BytecodeNode bytecodeNode = new BytecodeNode(4, frameDescriptor, multiplyInputs); RootNode rootNode = new Program(bytecodeNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(2 * osrThreshold, target.call(osrThreshold, 2)); Assert.assertTrue(bytecodeNode.compiled); BytecodeOSRMetadata osrMetadata = (BytecodeOSRMetadata) bytecodeNode.getOSRMetadata(); @@ -461,7 +462,7 @@ public void testOSRInBytecodeInnerLoop() { FrameDescriptor frameDescriptor = new FrameDescriptor(); BytecodeNode bytecodeNode = new BytecodeNode(4, frameDescriptor, multiplyInputs); RootNode rootNode = new Program(bytecodeNode, frameDescriptor); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals(2 * (osrThreshold - 1), target.call(2, osrThreshold - 1)); Assert.assertTrue(bytecodeNode.compiled); BytecodeOSRMetadata osrMetadata = (BytecodeOSRMetadata) bytecodeNode.getOSRMetadata(); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CastExactPartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CastExactPartialEvaluationTest.java index da874e7c0376..e73ac3aab0cd 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CastExactPartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CastExactPartialEvaluationTest.java @@ -38,7 +38,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; @@ -105,7 +104,7 @@ public void byteBufferAccessIndex() { private void testCommon(AbstractTestNode testNode, String testName) { FrameDescriptor fd = new FrameDescriptor(); RootNode rootNode = new RootTestNode(fd, testName, testNode); - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); + RootCallTarget callTarget = rootNode.getCallTarget(); Assert.assertEquals(42, callTarget.call(newBuffer())); assertPartialEvalNoInvokes(callTarget, new Object[]{newBuffer()}); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ClearFrameSlotTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ClearFrameSlotTest.java index b14bd96d0c03..e97abe151e3e 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ClearFrameSlotTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ClearFrameSlotTest.java @@ -49,7 +49,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -283,7 +282,7 @@ private void doTest(Supplier rootProvider, Consumer g setupContext(Context.newBuilder().option("engine.ForceFrameLivenessAnalysis", "true")); } RootNode rootNode = rootProvider.get(); - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); + RootCallTarget callTarget = rootNode.getCallTarget(); StructuredGraph graph = null; try { callTarget.call(args); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CodeInvalidationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CodeInvalidationTest.java index 5facd40e2448..e873da6858f6 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CodeInvalidationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CodeInvalidationTest.java @@ -258,7 +258,7 @@ public void testInvalidation() throws IOException, InterruptedException { protected synchronized CallTarget parse(ParsingRequest request) { com.oracle.truffle.api.source.Source source = request.getSource(); if (target == null) { - target = Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + target = new RootNode(languageInstance) { @Node.Child private volatile BaseNode child = testedCode; @@ -272,7 +272,7 @@ public SourceSection getSourceSection() { return source.createSection(1); } - }); + }.getCallTarget(); } return target; } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CompilationMemoryTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CompilationMemoryTest.java index 2e89039c992b..ae66ac8af5fb 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CompilationMemoryTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CompilationMemoryTest.java @@ -24,17 +24,18 @@ */ package org.graalvm.compiler.truffle.test; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.api.test.GCUtils; import java.lang.ref.Reference; import java.lang.ref.WeakReference; + import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.test.GCUtils; + public class CompilationMemoryTest extends TestWithPolyglotOptions { @Before @@ -45,7 +46,7 @@ public void setUp() { @Test public void testFieldsFreedAfterCompilation() { TestObject expected = new TestObject(); - OptimizedCallTarget callTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(expected)); + OptimizedCallTarget callTarget = (OptimizedCallTarget) RootNode.createConstantNode(expected).getCallTarget(); Assert.assertEquals(expected, callTarget.call()); Assert.assertEquals(expected, callTarget.call()); Assert.assertTrue(callTarget.isValid()); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CompilerLoggingTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CompilerLoggingTest.java index 82af56ac3f6c..4b50d97c98e6 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CompilerLoggingTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/CompilerLoggingTest.java @@ -54,7 +54,7 @@ public void testLogging() throws IOException { TestListener listener = new TestListener(); try { runtime.addListener(listener); - OptimizedCallTarget compilable = (OptimizedCallTarget) runtime.createCallTarget(RootNode.createConstantNode(true)); + OptimizedCallTarget compilable = (OptimizedCallTarget) RootNode.createConstantNode(true).getCallTarget(); compilable.call(); String logContent = new String(logOut.toByteArray()); String expected = String.format(FORMAT_SUCCESS + "%s%s%n", compilable.getName(), MESSAGE_TO_STREAM, MESSAGE_TO_TTY); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ControlFlowExceptionPartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ControlFlowExceptionPartialEvaluationTest.java index 3ead4bbf2d4a..ee2f908b3d76 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ControlFlowExceptionPartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ControlFlowExceptionPartialEvaluationTest.java @@ -67,7 +67,7 @@ public void catchControlFlowExceptionWithLoopExplosion() { @Test public void catchControlFlowExceptionFromCall() { setupContext(Context.newBuilder().allowExperimentalOptions(true).option("engine.Inlining", "true").build()); - CallTarget callTarget = Truffle.getRuntime().createCallTarget(new RootTestNode(new FrameDescriptor(), "throwControlFlowException", new ThrowControlFlowExceptionTestNode())); + CallTarget callTarget = new RootTestNode(new FrameDescriptor(), "throwControlFlowException", new ThrowControlFlowExceptionTestNode()).getCallTarget(); AbstractTestNode result = new CatchControlFlowExceptionTestNode(new CallTestNode(callTarget)); assertPartialEvalEquals(ControlFlowExceptionPartialEvaluationTest::constant42, new RootTestNode(new FrameDescriptor(), "catchControlFlowExceptionFromCall", result)); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/DFAPartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/DFAPartialEvaluationTest.java index e666a0c63902..b64a65cd8dfd 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/DFAPartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/DFAPartialEvaluationTest.java @@ -31,7 +31,6 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; @@ -302,7 +301,7 @@ private RootNode createRootNode(int initialState, DFAStateNode[] states) { } private static void assertMatches(RootNode program, String input) { - Object result = Truffle.getRuntime().createCallTarget(program).call(input); + Object result = program.getCallTarget().call(input); Assert.assertEquals(Boolean.TRUE, result); } @@ -312,7 +311,7 @@ public static boolean constantTrue() { private void assertPartialEvalEqualsAndRunsCorrect(RootNode program, String input) { assertMatches(program, input); - final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(program); + final OptimizedCallTarget compilable = (OptimizedCallTarget) program.getCallTarget(); partialEval(compilable, new Object[]{input}, getCompilationId(compilable)); // fail on Exceptions only for now } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java index de58af75ee45..1a3c2d8214f4 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EncodedGraphCacheTest.java @@ -124,9 +124,8 @@ private static boolean encodedGraphCacheContains(TruffleCompilerImpl compiler, R @SuppressWarnings("try") private static OptimizedCallTarget compileAST(RootNode rootNode) { - GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); - DebugContext debug = new DebugContext.Builder(runtime.getGraalOptions(OptionValues.class)).build(); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); + DebugContext debug = new DebugContext.Builder(GraalTruffleRuntime.getRuntime().getGraalOptions(OptionValues.class)).build(); try (DebugContext.Scope s = debug.scope("EncodedGraphCacheTest")) { CompilationIdentifier compilationId = getTruffleCompilerFromRuntime(target).createCompilationIdentifier(target); getTruffleCompilerFromRuntime(target).compileAST(target.getOptionValues(), debug, target, compilationId, null, null); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EngineModeTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EngineModeTest.java index 07d44f0ecfe0..5c46f8ca7f53 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EngineModeTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/EngineModeTest.java @@ -63,7 +63,7 @@ private static void compileAndAssertLatency(OptimizedCallTarget target) { @Test public void testLatencyFirstTierOnly() { setupContext(MODE, LATENCY); - OptimizedCallTarget target = (OptimizedCallTarget) GraalTruffleRuntime.getRuntime().createCallTarget(new RootNode(null) { + OptimizedCallTarget target = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { if (GraalCompilerDirectives.hasNextTier()) { @@ -71,7 +71,7 @@ public Object execute(VirtualFrame frame) { } return null; } - }); + }.getCallTarget(); compileAndAssertLatency(target); } @@ -82,7 +82,7 @@ public void testLatencyNoSplitting() { AbstractSplittingStrategyTest.SplitCountingListener listener = new AbstractSplittingStrategyTest.SplitCountingListener(); try { runtime.addListener(listener); - OptimizedCallTarget inner = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + OptimizedCallTarget inner = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { reportPolymorphicSpecialize(); @@ -93,11 +93,11 @@ public Object execute(VirtualFrame frame) { public boolean isCloningAllowed() { return true; } - }); + }.getCallTarget(); DirectCallNode directCallNode = runtime.createDirectCallNode(inner); DirectCallNode directCallNode2 = runtime.createDirectCallNode(inner); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + OptimizedCallTarget target = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { directCallNode.call(); @@ -109,7 +109,7 @@ public Object execute(VirtualFrame frame) { public boolean isCloningAllowed() { return true; } - }); + }.getCallTarget(); compileAndAssertLatency(target); Assert.assertEquals("Should not be splitting in latency mode", 0, listener.splitCount); } finally { @@ -121,7 +121,7 @@ public boolean isCloningAllowed() { public void testLatencyNoInlining() { setupContext(MODE, LATENCY, "engine.CompileOnly", ROOT); GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget inner = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + OptimizedCallTarget inner = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { if (CompilerDirectives.inCompiledCode()) { @@ -139,11 +139,11 @@ private void fail() { public boolean isCloningAllowed() { return true; } - }); + }.getCallTarget(); DirectCallNode directCallNode = runtime.createDirectCallNode(inner); DirectCallNode directCallNode2 = runtime.createDirectCallNode(inner); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + OptimizedCallTarget target = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { directCallNode.call(); @@ -155,7 +155,7 @@ public Object execute(VirtualFrame frame) { public String getName() { return ROOT; } - }); + }.getCallTarget(); compileAndAssertLatency(target); Assert.assertNull(directCallNode.getClonedCallTarget()); Assert.assertNull(directCallNode2.getClonedCallTarget()); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ExceptionActionTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ExceptionActionTest.java index 093a99157218..c871d856ad5a 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ExceptionActionTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ExceptionActionTest.java @@ -24,12 +24,6 @@ */ package org.graalvm.compiler.truffle.test; -import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.OptimizationFailedException; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.frame.FrameDescriptor; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.RootNode; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -39,10 +33,11 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.Supplier; -import java.util.regex.Pattern; import java.util.logging.FileHandler; import java.util.logging.SimpleFormatter; +import java.util.regex.Pattern; import java.util.stream.Collectors; + import org.graalvm.compiler.core.GraalCompilerOptions; import org.graalvm.compiler.test.SubprocessUtil; import org.graalvm.compiler.truffle.common.TruffleCompilerRuntime; @@ -50,9 +45,15 @@ import org.graalvm.compiler.truffle.test.nodes.AbstractTestNode; import org.graalvm.compiler.truffle.test.nodes.RootTestNode; import org.graalvm.polyglot.Context; -import org.junit.Test; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Test; + +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.OptimizationFailedException; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.RootNode; public class ExceptionActionTest extends TestWithPolyglotOptions { @@ -66,7 +67,7 @@ public class ExceptionActionTest extends TestWithPolyglotOptions { @BeforeClass public static void setUp() { - Truffle.getRuntime().createCallTarget(createPermanentBailoutNode()).call(); + createPermanentBailoutNode().getCallTarget().call(); } @Test @@ -190,7 +191,7 @@ private void executeForked(Consumer verifier, Supplier r verifier.accept(log); } else { setupContext(contextOptions); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(rootNodeFactory.get()); + OptimizedCallTarget target = (OptimizedCallTarget) rootNodeFactory.get().getCallTarget(); try { target.call(); } catch (RuntimeException e) { diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ExplodeLoopBlockDuplicationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ExplodeLoopBlockDuplicationTest.java index e92ed4a54ef7..e151aff045ae 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ExplodeLoopBlockDuplicationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ExplodeLoopBlockDuplicationTest.java @@ -29,7 +29,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.UnsupportedSpecializationException; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; @@ -45,7 +44,7 @@ public class ExplodeLoopBlockDuplicationTest extends TestWithSynchronousCompilin */ @Test public void testBlockDuplication() { - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(new ObjectCacheTestRootNode()); + OptimizedCallTarget target = (OptimizedCallTarget) new ObjectCacheTestRootNode().getCallTarget(); AbstractType value1 = new ConcreteType1(); AbstractType value2 = new ConcreteType2(); target.call(value1); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/FlushEngineQueueTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/FlushEngineQueueTest.java index 7d53b3ef5e43..5e7c00cf9bec 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/FlushEngineQueueTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/FlushEngineQueueTest.java @@ -26,7 +26,6 @@ import static org.junit.Assert.assertNotEquals; -import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.polyglot.Context; import org.junit.Test; @@ -78,7 +77,7 @@ public void testTargetsDequeuedOnClose() { } private static OptimizedCallTarget createConstantCallTarget(int i) { - return (OptimizedCallTarget) GraalTruffleRuntime.getRuntime().createCallTarget(new RootNode(null) { + return (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { @@ -94,7 +93,7 @@ public String getName() { public String toString() { return getName(); } - }); + }.getCallTarget(); } } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java index 72f119187fae..fb13b5d17f4a 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java @@ -56,7 +56,7 @@ public final class GraalTruffleRuntimeListenerTest extends TestWithPolyglotOptio public void testCompilationSuccess() { setupContext("engine.CompileImmediately", "true", "engine.BackgroundCompilation", "false"); GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget compilable = (OptimizedCallTarget) runtime.createCallTarget(RootNode.createConstantNode(true)); + OptimizedCallTarget compilable = (OptimizedCallTarget) RootNode.createConstantNode(true).getCallTarget(); TestListener listener = new TestListener(compilable); try { runtime.addListener(listener); @@ -76,7 +76,7 @@ public void testCompilationSuccess() { public void testCompilationFailure() { setupContext("engine.CompileImmediately", "true", "engine.BackgroundCompilation", "false"); GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget compilable = (OptimizedCallTarget) runtime.createCallTarget(createFailureNode()); + OptimizedCallTarget compilable = (OptimizedCallTarget) createFailureNode().getCallTarget(); TestListener listener = new TestListener(compilable); try { runtime.addListener(listener); @@ -98,7 +98,7 @@ public void write(int b) throws IOException { } }).allowExperimentalOptions(true).option("engine.CompileImmediately", "true").option("engine.BackgroundCompilation", "false").option("engine.CompilationFailureAction", "Diagnose")); GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget compilable = (OptimizedCallTarget) runtime.createCallTarget(createFailureNode()); + OptimizedCallTarget compilable = (OptimizedCallTarget) createFailureNode().getCallTarget(); TestListener listener = new TestListener(compilable); try { runtime.addListener(listener); @@ -121,7 +121,7 @@ public void testBlockCompilation() { "engine.BackgroundCompilation", "false", "engine.PartialBlockCompilationSize", "1"); GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget compilable = (OptimizedCallTarget) runtime.createCallTarget(createBlocks()); + OptimizedCallTarget compilable = (OptimizedCallTarget) createBlocks().getCallTarget(); compilable.computeBlockCompilations(); TestListener listener = new TestListener(compilable); try { @@ -159,7 +159,7 @@ public void testBlockCompilationLargeBlocks() { "engine.PartialBlockCompilationSize", "1", "engine.PartialBlockMaximumSize", "0"); GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget compilable = (OptimizedCallTarget) runtime.createCallTarget(createBlocks()); + OptimizedCallTarget compilable = (OptimizedCallTarget) createBlocks().getCallTarget(); compilable.computeBlockCompilations(); TestListener listener = new TestListener(compilable); try { @@ -198,7 +198,7 @@ public void testBlockCompilationMaximumGraalNodeCount() { children[i] = new ExpensiveTestNode(); } BlockNode block = BlockNode.create(children, new NodeExecutor()); - OptimizedCallTarget compilable = (OptimizedCallTarget) runtime.createCallTarget(new TestRootNode(block)); + OptimizedCallTarget compilable = (OptimizedCallTarget) new TestRootNode(block).getCallTarget(); TestListener listener = new TestListener(compilable); try { runtime.addListener(listener); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/IndirectCallSiteTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/IndirectCallSiteTest.java index fd96927fa482..29c5f3aab5ec 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/IndirectCallSiteTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/IndirectCallSiteTest.java @@ -55,19 +55,19 @@ public void before() { @Test public void testIndirectCallNodeDoesNotDeopOnFirstCall() { final Object[] noArguments = new Object[0]; - final OptimizedCallTarget innerTarget = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + final OptimizedCallTarget innerTarget = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return null; } - }); - final OptimizedCallTarget uninitializedInnerTarget = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + }.getCallTarget(); + final OptimizedCallTarget uninitializedInnerTarget = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return null; } - }); - final OptimizedCallTarget outerTarget = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + }.getCallTarget(); + final OptimizedCallTarget outerTarget = (OptimizedCallTarget) new RootNode(null) { @Child OptimizedIndirectCallNode indirectCallNode = (OptimizedIndirectCallNode) runtime.createIndirectCallNode(); @Override @@ -78,7 +78,7 @@ public Object execute(VirtualFrame frame) { return indirectCallNode.call(uninitializedInnerTarget, noArguments); } } - }); + }.getCallTarget(); final int compilationThreshold = outerTarget.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); for (int i = 0; i < compilationThreshold; i++) { outerTarget.call(noArguments); @@ -206,11 +206,11 @@ void assertNotDeoptimized(OptimizedCallTarget target) { */ @Test public void testIndirectCallNodeDoesNotDeoptOnTypeChangeWithInlining1() { - final OptimizedCallTarget toInterpreterOnString = (OptimizedCallTarget) runtime.createCallTarget(new WritesToGlobalState()); + final OptimizedCallTarget toInterpreterOnString = (OptimizedCallTarget) new WritesToGlobalState().getCallTarget(); final Object[] directArguments = new Object[]{1}; - final OptimizedCallTarget directCall = (OptimizedCallTarget) runtime.createCallTarget(new DirectlyCallsTargetWithArguments(toInterpreterOnString, directArguments)); - final OptimizedCallTarget noOp = (OptimizedCallTarget) runtime.createCallTarget(new DummyTarget()); - final OptimizedCallTarget indirectCall = (OptimizedCallTarget) runtime.createCallTarget(new IndirectCallTargetFromArgument()); + final OptimizedCallTarget directCall = (OptimizedCallTarget) new DirectlyCallsTargetWithArguments(toInterpreterOnString, directArguments).getCallTarget(); + final OptimizedCallTarget noOp = (OptimizedCallTarget) new DummyTarget().getCallTarget(); + final OptimizedCallTarget indirectCall = (OptimizedCallTarget) new IndirectCallTargetFromArgument().getCallTarget(); final int compilationThreshold = toInterpreterOnString.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); @@ -248,10 +248,10 @@ public void testIndirectCallNodeDoesNotDeoptOnTypeChangeWithInlining1() { @Test public void testIndirectCallDoesNotDeoptInliningDirectCaller() { - final OptimizedCallTarget callee = (OptimizedCallTarget) runtime.createCallTarget(RootNode.createConstantNode(0)); + final OptimizedCallTarget callee = (OptimizedCallTarget) RootNode.createConstantNode(0).getCallTarget(); final Object[] directArguments = new Object[]{"direct arg"}; - final OptimizedCallTarget directCall = (OptimizedCallTarget) runtime.createCallTarget(new DirectlyCallsTargetWithArguments(callee, directArguments)); - final OptimizedCallTarget indirectCall = (OptimizedCallTarget) runtime.createCallTarget(new IndirectCallTargetFromArgument()); + final OptimizedCallTarget directCall = (OptimizedCallTarget) new DirectlyCallsTargetWithArguments(callee, directArguments).getCallTarget(); + final OptimizedCallTarget indirectCall = (OptimizedCallTarget) new IndirectCallTargetFromArgument().getCallTarget(); final int compilationThreshold = callee.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); try (DeoptInvalidateListener directListener = new DeoptInvalidateListener(runtime, directCall)) { @@ -278,10 +278,10 @@ public void testIndirectCallDoesNotDeoptInliningDirectCaller() { public void testIndirectCallDoesNotDeoptNotInliningDirectCaller() { setupContext("engine.MultiTier", "false", "engine.Inlining", "false"); - final OptimizedCallTarget callee = (OptimizedCallTarget) runtime.createCallTarget(RootNode.createConstantNode(0)); + final OptimizedCallTarget callee = (OptimizedCallTarget) RootNode.createConstantNode(0).getCallTarget(); final Object[] directArguments = new Object[]{"direct arg"}; - final OptimizedCallTarget directCall = (OptimizedCallTarget) runtime.createCallTarget(new DirectlyCallsTargetWithArguments(callee, directArguments)); - final OptimizedCallTarget indirectCall = (OptimizedCallTarget) runtime.createCallTarget(new IndirectCallTargetFromArgument()); + final OptimizedCallTarget directCall = (OptimizedCallTarget) new DirectlyCallsTargetWithArguments(callee, directArguments).getCallTarget(); + final OptimizedCallTarget indirectCall = (OptimizedCallTarget) new IndirectCallTargetFromArgument().getCallTarget(); final int compilationThreshold = callee.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); try (DeoptInvalidateListener directListener = new DeoptInvalidateListener(runtime, directCall)) { @@ -305,10 +305,10 @@ public void testIndirectCallDoesNotDeoptNotInliningDirectCaller() { @Test public void testIndirectCallDoesNotDeoptCallee() { - final OptimizedCallTarget callee = (OptimizedCallTarget) runtime.createCallTarget(RootNode.createConstantNode(0)); + final OptimizedCallTarget callee = (OptimizedCallTarget) RootNode.createConstantNode(0).getCallTarget(); final Object[] directArguments = new Object[]{"direct arg"}; - final OptimizedCallTarget directCall = (OptimizedCallTarget) runtime.createCallTarget(new DirectlyCallsTargetWithArguments(callee, directArguments)); - final OptimizedCallTarget indirectCall = (OptimizedCallTarget) runtime.createCallTarget(new IndirectCallTargetFromArgument()); + final OptimizedCallTarget directCall = (OptimizedCallTarget) new DirectlyCallsTargetWithArguments(callee, directArguments).getCallTarget(); + final OptimizedCallTarget indirectCall = (OptimizedCallTarget) new IndirectCallTargetFromArgument().getCallTarget(); final int compilationThreshold = callee.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); try (DeoptInvalidateListener calleeListener = new DeoptInvalidateListener(runtime, callee)) { diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LanguageContextFreedTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LanguageContextFreedTest.java index 5f7f9b3c46d4..a8fb5989cf32 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LanguageContextFreedTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LanguageContextFreedTest.java @@ -40,11 +40,9 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.ContextLocal; import com.oracle.truffle.api.ContextThreadLocal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.ContextPolicy; import com.oracle.truffle.api.TruffleLanguage.Registration; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.test.GCUtils; @@ -154,8 +152,7 @@ protected LanguageContext createContext(Env env) { @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - TruffleRuntime runtime = Truffle.getRuntime(); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(this) { + OptimizedCallTarget target = (OptimizedCallTarget) new RootNode(this) { @SuppressWarnings("unchecked") @Override @@ -163,7 +160,7 @@ public Object execute(VirtualFrame frame) { getContextReference0().get(this).currentTarget = (OptimizedCallTarget) getCallTarget(); return true; } - }); + }.getCallTarget(); getContextReference0().get(null).currentTarget = target; assertEquals(COMPILATION_THRESHOLD, (int) target.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold)); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LazyClassLoadingTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LazyClassLoadingTest.java index b5d77628b72b..ecb63059fb76 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LazyClassLoadingTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LazyClassLoadingTest.java @@ -55,7 +55,7 @@ import org.junit.Assert; import org.junit.Assume; import org.junit.Test; -import com.oracle.truffle.api.Truffle; + import com.oracle.truffle.api.nodes.RootNode; import jdk.vm.ci.runtime.JVMCICompilerFactory; @@ -90,7 +90,7 @@ private static Class forNameOrNull(String name) { @Test public void testClassLoading() throws IOException, InterruptedException { setupContext(); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(0)); + OptimizedCallTarget target = (OptimizedCallTarget) RootNode.createConstantNode(0).getCallTarget(); Assume.assumeFalse(target.getOptionValue(CompileImmediately)); List vmCommandLine = getVMCommandLine(); Assume.assumeFalse("Explicitly enables JVMCI compiler", vmCommandLine.contains("-XX:+UseJVMCINativeLibrary") || vmCommandLine.contains("-XX:+UseJVMCICompiler")); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LibrarySplittingStrategyTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LibrarySplittingStrategyTest.java index 917c3d2f6bcf..878f5d629b08 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LibrarySplittingStrategyTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LibrarySplittingStrategyTest.java @@ -58,9 +58,9 @@ public void boostBudget() { @Test public void testCachedLibWithValue() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(LibrarySplittingStrategyTestFactory.CachesLibOnValueNodeGen.create( - new ReturnsFirstArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + LibrarySplittingStrategyTestFactory.CachesLibOnValueNodeGen.create( + new ReturnsFirstArgumentNode())).getCallTarget(); Object[] first = new Object[]{1}; Object[] second = new Object[]{"2"}; testSplitsDirectCallsHelper(callTarget, first, second); @@ -68,10 +68,9 @@ public void testCachedLibWithValue() { @Test public void testCachedLibWithValueExclude() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode( - LibrarySplittingStrategyTestFactory.CachesLibOnValueNodeExcludeNodeGen.create( - new ReturnsFirstArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + LibrarySplittingStrategyTestFactory.CachesLibOnValueNodeExcludeNodeGen.create( + new ReturnsFirstArgumentNode())).getCallTarget(); Object[] first = new Object[]{1}; Object[] second = new Object[]{"2"}; testDoesNotSplitDirectCallHelper(callTarget, first, second); @@ -79,10 +78,9 @@ public void testCachedLibWithValueExclude() { @Test public void testExportedMessage() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode( - LibrarySplittingStrategyTestFactory.SplitReadPropertyNodeGen.create( - new ReturnsFirstArgumentNode(), new ReturnsSecondArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + LibrarySplittingStrategyTestFactory.SplitReadPropertyNodeGen.create( + new ReturnsFirstArgumentNode(), new ReturnsSecondArgumentNode())).getCallTarget(); Object[] first = new Object[]{newInstance(), "a"}; Object[] second = new Object[]{newInstance(), "b"}; testSplitsDirectCallsHelper(callTarget, first, second); @@ -90,10 +88,9 @@ public void testExportedMessage() { @Test public void testExportedMessageWithExcludedSpecialisation() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode( - LibrarySplittingStrategyTestFactory.SplitReadPropertyNodeGen.create( - new ReturnsFirstArgumentNode(), new ReturnsSecondArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + LibrarySplittingStrategyTestFactory.SplitReadPropertyNodeGen.create( + new ReturnsFirstArgumentNode(), new ReturnsSecondArgumentNode())).getCallTarget(); Object[] first = new Object[]{newInstance(), SplittingObjectType.ReadMember.CACHED_NAME}; Object[] second = new Object[]{newInstance(), "b"}; testDoesNotSplitDirectCallHelper(callTarget, first, second); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodeOSRTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodeOSRTest.java index 1e39f6bbdde0..f2840e095a75 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodeOSRTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodeOSRTest.java @@ -121,7 +121,7 @@ public void testOSRStackFrame() { FrameSlot iterationSlot = desc.addFrameSlot("iteration", FrameSlotKind.Int); CheckStackWalkBody loop = new CheckStackWalkBody(osrThreshold * 2, desc, iterationSlot); TestLoopRootNode rootNode = new TestLoopRootNode(loop, desc, iterationSlot); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); target.call(ARGUMENTS); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java index 7d909a7789f4..3796130670fc 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/LoopNodePartialEvaluationTest.java @@ -30,8 +30,8 @@ import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.ProfileData.ProfileSource; -import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.polyglot.Context; import org.junit.Assert; @@ -98,7 +98,7 @@ public void testLoopConditionProfile() { setupContext(Context.newBuilder().allowExperimentalOptions(true).option("engine.CompileImmediately", "false").option("engine.BackgroundCompilation", "false").build()); TestLoopRootNode repeatRootNode = new TestLoopRootNode(new RepeatNTimesNode(9)); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(repeatRootNode); + OptimizedCallTarget target = (OptimizedCallTarget) repeatRootNode.getCallTarget(); StructuredGraph graph = partialEval(target, new Object[0]); Stream ifWithInjectedProfile = graph.getNodes().filter(IfNode.class).stream().filter(i -> i.getProfileData().getProfileSource() == ProfileSource.INJECTED); @@ -120,7 +120,7 @@ public void testPrepareLoopForAOT() { setupContext(Context.newBuilder().allowExperimentalOptions(true).option("engine.CompileImmediately", "true").option("engine.BackgroundCompilation", "false").build()); TestLoopRootNode repeatRootNode = new TestLoopRootNode(new RepeatNTimesNode(9)); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(repeatRootNode); + OptimizedCallTarget target = (OptimizedCallTarget) repeatRootNode.getCallTarget(); target.prepareForAOT(); StructuredGraph graph = partialEval(target, new Object[0]); @@ -257,7 +257,7 @@ public void testPropagateInjectedProfile(boolean twoEnds, boolean trueContinue) setupContext(Context.newBuilder().allowExperimentalOptions(true).option("engine.CompileImmediately", "false").option("engine.BackgroundCompilation", "false").build()); RootNode rootNode = new TestPropagateInjectedProfileRootNode(new TestRepeatingNode(9, twoEnds, trueContinue)); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); StructuredGraph graph = partialEval(target, new Object[0]); Stream ifWithInjectedProfile = graph.getNodes().filter(IfNode.class).stream().filter(i -> i.getProfileData().getProfileSource() == ProfileSource.INJECTED); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MaterializedFrameTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MaterializedFrameTest.java index caf71ddd7176..a51f3d938b8c 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MaterializedFrameTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MaterializedFrameTest.java @@ -41,7 +41,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -81,7 +80,7 @@ public Object execute(VirtualFrame frame) { @Test public void getFrameSlotKind() { RootNode rootNode = createRootNode(); - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); + RootCallTarget callTarget = rootNode.getCallTarget(); StructuredGraph graph = partialEval((OptimizedCallTarget) callTarget, new Object[]{}, getCompilationId(callTarget)); NodeIterable calls = graph.getNodes().filter(MethodCallTargetNode.class); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MergeExplodeProxyTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MergeExplodeProxyTest.java index a11e030b259e..f4eea426ef41 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MergeExplodeProxyTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MergeExplodeProxyTest.java @@ -37,7 +37,6 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.FrameSlotTypeException; @@ -211,7 +210,7 @@ public void testLoopControlVariableProxy() { /* 12: */Bytecode.POP, /* 13: */Bytecode.RETURN}; - CallTarget callee = Truffle.getRuntime().createCallTarget(new LoopControlVariableProxy("simpleLoopProgram", bytecodes, 1, 3)); + CallTarget callee = new LoopControlVariableProxy("simpleLoopProgram", bytecodes, 1, 3).getCallTarget(); callee.call(); callee.call(); callee.call(); @@ -394,13 +393,13 @@ public void test01() { /* 12: */Bytecode.POP, /* 13: */Bytecode.RETURN}; - CallTarget callee = Truffle.getRuntime().createCallTarget(new WrongLoopExitMerge("mergedLoopExitProgram", bytecodes, 1, 3)); + CallTarget callee = new WrongLoopExitMerge("mergedLoopExitProgram", bytecodes, 1, 3).getCallTarget(); callee.call(); callee.call(); callee.call(); callee.call(); - CallTarget caller = Truffle.getRuntime().createCallTarget(new Caller(callee)); + CallTarget caller = new Caller(callee).getCallTarget(); caller.call(); caller.call(); caller.call(); @@ -432,7 +431,7 @@ public void test01Caller() { /* 12: */Bytecode.POP, /* 13: */Bytecode.RETURN}; - CallTarget callee = Truffle.getRuntime().createCallTarget(new WrongLoopExitMerge("mergedLoopExitProgram", bytecodes, 1, 3)); + CallTarget callee = new WrongLoopExitMerge("mergedLoopExitProgram", bytecodes, 1, 3).getCallTarget(); callee.call(); callee.call(); callee.call(); @@ -653,8 +652,7 @@ public void testSameValueProxy() { /* 23: */Bytecode.POP, /* 24: */Bytecode.RETURN}; - CallTarget callee = Truffle.getRuntime().createCallTarget( - new ProxySameValueOnce("proxyAtStateProgram", bytecodes, 0, 6)); + CallTarget callee = new ProxySameValueOnce("proxyAtStateProgram", bytecodes, 0, 6).getCallTarget(); ProxySameValueOnce.SideEffect = -1; callee.call(); ProxySameValueOnce.SideEffect = 0; @@ -883,8 +881,7 @@ public void testNoneLiveLoopExitProxy() { /* 23: */Bytecode.POP, /* 24: */Bytecode.RETURN}; - CallTarget callee = Truffle.getRuntime().createCallTarget( - new NoneLiveNoProxyTest("proxyAtStateProgram", bytecodes, 0, 6)); + CallTarget callee = new NoneLiveNoProxyTest("proxyAtStateProgram", bytecodes, 0, 6).getCallTarget(); ProxySameValueOnce.SideEffect = -1; callee.call(); ProxySameValueOnce.SideEffect = 0; diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MultiTierCompilationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MultiTierCompilationTest.java index fe4276adc33f..b8a3fca01e10 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MultiTierCompilationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/MultiTierCompilationTest.java @@ -24,14 +24,12 @@ */ package org.graalvm.compiler.truffle.test; -import static org.graalvm.compiler.truffle.options.PolyglotCompilerOptions.LastTierCompilationThreshold; import static org.graalvm.compiler.truffle.options.PolyglotCompilerOptions.FirstTierCompilationThreshold; +import static org.graalvm.compiler.truffle.options.PolyglotCompilerOptions.LastTierCompilationThreshold; -import com.oracle.truffle.api.nodes.LoopNode; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.nodes.RepeatingNode; import org.graalvm.compiler.truffle.runtime.GraalCompilerDirectives; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; +import org.graalvm.polyglot.Context; import org.junit.Assert; import org.junit.Test; @@ -40,8 +38,10 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.api.nodes.LoopNode; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RepeatingNode; import com.oracle.truffle.api.nodes.RootNode; -import org.graalvm.polyglot.Context; public class MultiTierCompilationTest extends PartialEvaluationTest { @@ -187,8 +187,8 @@ public void testDefault() { "true").option("engine.FirstTierInliningPolicy", "None").option("engine.Splitting", "false").option("engine.FirstTierCompilationThreshold", "100").option( "engine.LastTierCompilationThreshold", "1000").build()); - OptimizedCallTarget calleeTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(new MultiTierCalleeNode()); - OptimizedCallTarget multiTierTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(new MultiTierRootNode(calleeTarget)); + OptimizedCallTarget calleeTarget = (OptimizedCallTarget) new MultiTierCalleeNode().getCallTarget(); + OptimizedCallTarget multiTierTarget = (OptimizedCallTarget) new MultiTierRootNode(calleeTarget).getCallTarget(); final int firstTierCompilationThreshold = calleeTarget.getOptionValue(FirstTierCompilationThreshold); final int compilationThreshold = calleeTarget.getOptionValue(LastTierCompilationThreshold); @@ -214,8 +214,8 @@ public void testFirstTierInlining() { "true").option("engine.FirstTierInliningPolicy", "Default").option("engine.Splitting", "false").option("engine.FirstTierCompilationThreshold", "100").option( "engine.LastTierCompilationThreshold", "1000").build()); - OptimizedCallTarget calleeTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(new MultiTierCalleeNode()); - OptimizedCallTarget multiTierTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(new MultiTierRootNode(calleeTarget)); + OptimizedCallTarget calleeTarget = (OptimizedCallTarget) new MultiTierCalleeNode().getCallTarget(); + OptimizedCallTarget multiTierTarget = (OptimizedCallTarget) new MultiTierRootNode(calleeTarget).getCallTarget(); final int firstTierCompilationThreshold = calleeTarget.getOptionValue(FirstTierCompilationThreshold); final int compilationThreshold = calleeTarget.getOptionValue(LastTierCompilationThreshold); @@ -237,10 +237,10 @@ public void testWhenCalleeCompiledFirst() { "true").option("engine.FirstTierInliningPolicy", "None").option("engine.Splitting", "false").option("engine.FirstTierCompilationThreshold", "100").option( "engine.LastTierCompilationThreshold", "1000").build()); - OptimizedCallTarget calleeTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(new MultiTierCalleeNode()); + OptimizedCallTarget calleeTarget = (OptimizedCallTarget) new MultiTierCalleeNode().getCallTarget(); final int firstTierCompilationThreshold = calleeTarget.getOptionValue(FirstTierCompilationThreshold); final int compilationThreshold = calleeTarget.getOptionValue(LastTierCompilationThreshold); - OptimizedCallTarget multiTierTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(new MultiTierWithFrequentCalleeRootNode(calleeTarget, firstTierCompilationThreshold)); + OptimizedCallTarget multiTierTarget = (OptimizedCallTarget) new MultiTierWithFrequentCalleeRootNode(calleeTarget, firstTierCompilationThreshold).getCallTarget(); Assert.assertEquals("root:interpreter", multiTierTarget.call()); for (int i = 0; i < firstTierCompilationThreshold - 2; i++) { @@ -275,7 +275,7 @@ public void testLoop() { MultiTierLoopBodyNode body = new MultiTierLoopBodyNode(firstThreshold); final MultiTierWithLoopRootNode rootNode = new MultiTierWithLoopRootNode(body); - OptimizedCallTarget rootTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(rootNode); + OptimizedCallTarget rootTarget = (OptimizedCallTarget) rootNode.getCallTarget(); Assert.assertEquals("break:interpreter", rootTarget.call()); Assert.assertEquals("break:first-tier", rootTarget.call()); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/NodeLimitTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/NodeLimitTest.java index e335eb5b8564..2a233f943dbf 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/NodeLimitTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/NodeLimitTest.java @@ -39,7 +39,6 @@ import org.junit.Test; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.RootNode; @@ -53,7 +52,7 @@ public void before() { } private static OptimizedCallTarget dummyTarget() { - return (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + return (OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget(); } @Test @@ -94,7 +93,7 @@ public Integer apply(Integer integer) { }; } }; - partialEval((OptimizedCallTarget) Truffle.getRuntime().createCallTarget(rootNode), new Object[]{}, CompilationIdentifier.INVALID_COMPILATION_ID); + partialEval((OptimizedCallTarget) rootNode.getCallTarget(), new Object[]{}, CompilationIdentifier.INVALID_COMPILATION_ID); } private static class TestRootNode extends RootNode { @@ -141,7 +140,7 @@ private void expectAllOK(Supplier rootNodeFactory) { } private int getBaselineGraphNodeCount(RootNode rootNode) { - final OptimizedCallTarget baselineGraphTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(rootNode); + final OptimizedCallTarget baselineGraphTarget = (OptimizedCallTarget) rootNode.getCallTarget(); final StructuredGraph baselineGraph = partialEval(baselineGraphTarget, new Object[]{}, getCompilationId(baselineGraphTarget)); return baselineGraph.getNodeCount(); } @@ -149,7 +148,7 @@ private int getBaselineGraphNodeCount(RootNode rootNode) { @SuppressWarnings("try") private void peRootNode(int nodeLimit, Supplier rootNodeFactory) { setupContext(Context.newBuilder().allowAllAccess(true).allowExperimentalOptions(true).option("engine.MaximumGraalNodeCount", Integer.toString(nodeLimit)).build()); - RootCallTarget target = Truffle.getRuntime().createCallTarget(rootNodeFactory.get()); + RootCallTarget target = rootNodeFactory.get().getCallTarget(); final Object[] arguments = {1}; partialEval((OptimizedCallTarget) target, arguments, getCompilationId(target)); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/NodeSplittingStrategyTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/NodeSplittingStrategyTest.java index 3b7960d35118..e1a74b9f3eec 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/NodeSplittingStrategyTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/NodeSplittingStrategyTest.java @@ -24,13 +24,13 @@ */ package org.graalvm.compiler.truffle.test; -import com.oracle.truffle.api.CallTarget; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.compiler.truffle.runtime.OptimizedDirectCallNode; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.dsl.Cached; @@ -124,7 +124,7 @@ protected static Object doIndirect(RootCallTarget target) { static class TwoDummiesAndAnotherNode extends SplittingTestNode { int counter; - RootCallTarget dummy = runtime.createCallTarget(new DummyRootNode()); + RootCallTarget dummy = new DummyRootNode().getCallTarget(); @Override public Object execute(VirtualFrame frame) { @@ -132,7 +132,7 @@ public Object execute(VirtualFrame frame) { counter++; } else { counter = 0; - dummy = runtime.createCallTarget(new DummyRootNode()); + dummy = new DummyRootNode().getCallTarget(); } return dummy; } @@ -140,26 +140,24 @@ public Object execute(VirtualFrame frame) { @Test public void testSplitsDirectCalls() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.HasInlineCacheNodeGen.create(new ReturnsFirstArgumentNode()))); - Object[] first = new Object[]{runtime.createCallTarget(new DummyRootNode())}; - Object[] second = new Object[]{runtime.createCallTarget(new DummyRootNode())}; + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode(NodeSplittingStrategyTestFactory.HasInlineCacheNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); + Object[] first = new Object[]{new DummyRootNode().getCallTarget()}; + Object[] second = new Object[]{new DummyRootNode().getCallTarget()}; testSplitsDirectCallsHelper(callTarget, first, second); - callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroNodeGen.create(new ReturnsFirstArgumentNode()))); + callTarget = (OptimizedCallTarget) new SplittingTestRootNode(NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); // two callers for a target are needed testSplitsDirectCallsHelper(callTarget, new Object[]{1}, new Object[]{0}); } @Test public void testDoesNotSplitsDirectCalls() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget(new SplittingTestRootNode( - NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroButClassIsExcludedNodeGen.create(new ReturnsFirstArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroButClassIsExcludedNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); testDoesNotSplitDirectCallHelper(callTarget, new Object[]{1}, new Object[]{0}); - callTarget = (OptimizedCallTarget) runtime.createCallTarget(new SplittingTestRootNode( - NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroButSpecializationIsExcludedNodeGen.create(new ReturnsFirstArgumentNode()))); + callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroButSpecializationIsExcludedNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); testDoesNotSplitDirectCallHelper(callTarget, new Object[]{1}, new Object[]{0}); } @@ -188,19 +186,18 @@ public Object execute(VirtualFrame frame) { @Test public void testSplitPropagatesThrongSoleCallers() { - OptimizedCallTarget turnsPolymorphic = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroNodeGen.create(new ReturnsFirstArgumentNode()))); + OptimizedCallTarget turnsPolymorphic = (OptimizedCallTarget) new SplittingTestRootNode( + NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); testPropagatesThroughSoleCallers(turnsPolymorphic, new Object[]{1}, new Object[]{0}); - turnsPolymorphic = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.HasInlineCacheNodeGen.create(new ReturnsFirstArgumentNode()))); - Object[] first = new Object[]{runtime.createCallTarget(new DummyRootNode())}; - Object[] second = new Object[]{runtime.createCallTarget(new DummyRootNode())}; + turnsPolymorphic = (OptimizedCallTarget) new SplittingTestRootNode(NodeSplittingStrategyTestFactory.HasInlineCacheNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); + Object[] first = new Object[]{new DummyRootNode().getCallTarget()}; + Object[] second = new Object[]{new DummyRootNode().getCallTarget()}; testPropagatesThroughSoleCallers(turnsPolymorphic, first, second); } private void testPropagatesThroughSoleCallers(OptimizedCallTarget turnsPolymorphic, Object[] firstArgs, Object[] secondArgs) { - final OptimizedCallTarget callsInner = (OptimizedCallTarget) runtime.createCallTarget(new CallsInnerNode(turnsPolymorphic)); - final OptimizedCallTarget callsCallsInner = (OptimizedCallTarget) runtime.createCallTarget(new CallsInnerNode(callsInner)); + final OptimizedCallTarget callsInner = (OptimizedCallTarget) new CallsInnerNode(turnsPolymorphic).getCallTarget(); + final OptimizedCallTarget callsCallsInner = (OptimizedCallTarget) new CallsInnerNode(callsInner).getCallTarget(); // two callers for a target are needed runtime.createDirectCallNode(callsCallsInner); final DirectCallNode directCallNode = runtime.createDirectCallNode(callsCallsInner); @@ -236,9 +233,9 @@ private void testPropagatesThroughSoleCallers(OptimizedCallTarget turnsPolymorph @Test public void testNoSplitsDirectCallsBecauseFirstExecution() { - final OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget(new SplittableRootNode() { - @Child private OptimizedDirectCallNode callNode = (OptimizedDirectCallNode) runtime.createDirectCallNode(runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroNodeGen.create(new ReturnsFirstArgumentNode())))); + final OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittableRootNode() { + @Child private OptimizedDirectCallNode callNode = (OptimizedDirectCallNode) runtime.createDirectCallNode( + new SplittingTestRootNode(NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget()); @Override public Object execute(VirtualFrame frame) { @@ -250,7 +247,7 @@ public Object execute(VirtualFrame frame) { callNode.call(second); return null; } - }); + }.getCallTarget(); // Multiple call nodes runtime.createDirectCallNode(callTarget); runtime.createDirectCallNode(callTarget); @@ -262,9 +259,9 @@ public Object execute(VirtualFrame frame) { @Test public void testIncreaseInPolymorphism() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroNodeGen.create(new ReturnsFirstArgumentNode()))); - final RootCallTarget outerTarget = runtime.createCallTarget(new CallsInnerNode(callTarget)); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + NodeSplittingStrategyTestFactory.TurnsPolymorphicOnZeroNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); + final RootCallTarget outerTarget = new CallsInnerNode(callTarget).getCallTarget(); Object[] firstArgs = new Object[]{1}; outerTarget.call(firstArgs); Assert.assertFalse("Target needs split before the node went polymorphic", getNeedsSplit(callTarget)); @@ -322,8 +319,7 @@ public Object execute(VirtualFrame frame) { @Test public void testSoloTarget() { final ExposesReportPolymorphicSpecializeRootNode rootNode = new ExposesReportPolymorphicSpecializeRootNode(); - final RootCallTarget callTarget = runtime.createCallTarget(rootNode); - callTarget.call(noArguments); + rootNode.getCallTarget().call(noArguments); rootNode.report(); } @@ -349,10 +345,10 @@ public boolean isCloningAllowed() { @Test public void testSplitsCalledAfterSplit() { final CallableOnlyOnceRootNode rootNode = new CallableOnlyOnceRootNode(); - final RootCallTarget reportsPolymorphism = runtime.createCallTarget(rootNode); + final RootCallTarget reportsPolymorphism = rootNode.getCallTarget(); reportsPolymorphism.call(noArguments); - final RootCallTarget callsInner1 = runtime.createCallTarget(new CallsInnerNode(reportsPolymorphism)); - final RootCallTarget callsInner2 = runtime.createCallTarget(new CallsInnerNode(reportsPolymorphism)); + final RootCallTarget callsInner1 = new CallsInnerNode(reportsPolymorphism).getCallTarget(); + final RootCallTarget callsInner2 = new CallsInnerNode(reportsPolymorphism).getCallTarget(); // make sure the runtime has seen these calls callsInner1.call(noArguments); callsInner2.call(noArguments); @@ -380,8 +376,7 @@ protected static Object doIndirect(int val) { @Test public void testMegamorpic() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.MegamorpicNodeGen.create(new ReturnsFirstArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode(NodeSplittingStrategyTestFactory.MegamorpicNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); int[] args = {1, 2, 3, 4, 5}; testMegamorphicHelper(callTarget, args); } @@ -434,8 +429,8 @@ protected static Object doIndirect(int val) { @Test public void testTwoMegamorpicSpec1() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.TwoMegamorpicSpecNodeGen.create(new ReturnsFirstArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + NodeSplittingStrategyTestFactory.TwoMegamorpicSpecNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); // activates the first spec 2 times than the second (megamorphic) int[] args = {1, 2, 3, 4, 5}; testMegamorphicHelper(callTarget, args); @@ -443,8 +438,8 @@ public void testTwoMegamorpicSpec1() { @Test public void testTwoMegamorpicSpec2() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.TwoMegamorpicSpecNodeGen.create(new ReturnsFirstArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + NodeSplittingStrategyTestFactory.TwoMegamorpicSpecNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); // activates the first spec 2 times than the last (megamorphic) int[] args = {1, 2, 4, 5, 6}; testMegamorphicHelper(callTarget, args); @@ -467,8 +462,8 @@ protected static Object doIndirect(int val) { @Test public void testPolymorphicInPolyAndMegamorpic() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.PolymorphicAndMegamorpicNodeGen.create(new ReturnsFirstArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + NodeSplittingStrategyTestFactory.PolymorphicAndMegamorpicNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); // activates the first spec 2 times than the last (megamorphic) int[] args = {1, 2, 3, 4}; final DirectCallNode callNode1 = runtime.createDirectCallNode(callTarget); @@ -492,8 +487,8 @@ public void testPolymorphicInPolyAndMegamorpic() { @Test public void testMegamorphicInPolyAndMegamorpic() { - OptimizedCallTarget callTarget = (OptimizedCallTarget) runtime.createCallTarget( - new SplittingTestRootNode(NodeSplittingStrategyTestFactory.PolymorphicAndMegamorpicNodeGen.create(new ReturnsFirstArgumentNode()))); + OptimizedCallTarget callTarget = (OptimizedCallTarget) new SplittingTestRootNode( + NodeSplittingStrategyTestFactory.PolymorphicAndMegamorpicNodeGen.create(new ReturnsFirstArgumentNode())).getCallTarget(); // activates the first spec 2 times than the last (megamorphic) int[] args = {1, 0, 3, 4}; final DirectCallNode callNode1 = runtime.createDirectCallNode(callTarget); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OSRCancelTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OSRCancelTest.java index c8928519a099..59633b1b2fcf 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OSRCancelTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OSRCancelTest.java @@ -107,7 +107,7 @@ protected Env createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Child TestInstrumentableNode loop = new TestLoopNode(); @@ -116,7 +116,7 @@ public Object execute(VirtualFrame frame) { loop.execute(frame); return ""; } - }); + }.getCallTarget(); } } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ObjectsRequireNonNullPartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ObjectsRequireNonNullPartialEvaluationTest.java index 61f2e5d846b7..f3c3ca4d4005 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ObjectsRequireNonNullPartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ObjectsRequireNonNullPartialEvaluationTest.java @@ -24,6 +24,8 @@ */ package org.graalvm.compiler.truffle.test; +import java.util.Objects; + import org.graalvm.compiler.truffle.test.ObjectsRequireNonNullPartialEvaluationTest.TestClass.InnerClass; import org.graalvm.compiler.truffle.test.nodes.AbstractTestNode; import org.graalvm.compiler.truffle.test.nodes.RootTestNode; @@ -31,12 +33,8 @@ import org.junit.Test; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.RootNode; - -import java.util.Objects; public class ObjectsRequireNonNullPartialEvaluationTest extends PartialEvaluationTest { @@ -78,8 +76,7 @@ public void testNull() { private void testCommon(AbstractTestNode testNode, String testName, Object arg) { FrameDescriptor fd = new FrameDescriptor(); - RootNode rootNode = new RootTestNode(fd, testName, testNode); - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); + RootCallTarget callTarget = new RootTestNode(fd, testName, testNode).getCallTarget(); Assert.assertEquals(42, callTarget.call(arg)); assertPartialEvalNoInvokes(callTarget, new Object[]{arg}); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedBlockNodeTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedBlockNodeTest.java index 67fcc6961b86..d43fcc3e7886 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedBlockNodeTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedBlockNodeTest.java @@ -602,7 +602,7 @@ private static OptimizedBlockNode createBlock(int blockSize, int de private static OptimizedCallTarget createTest(BlockNode block) { TestRootNode root = new TestRootNode(block, "Block[" + block.getElements().length + "]"); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); + OptimizedCallTarget target = (OptimizedCallTarget) root.getCallTarget(); root.accept(new NodeVisitor() { @Override public boolean visit(Node node) { diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedCallTargetTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedCallTargetTest.java index c8dfd0165cbc..d845d3957f9b 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedCallTargetTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedCallTargetTest.java @@ -107,7 +107,7 @@ public void testCompilationHeuristics() { testInvalidationCounterCompiled = 0; testInvalidationCounterInterpreted = 0; doInvalidate = false; - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + OptimizedCallTarget target = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { if (CompilerDirectives.inInterpreter()) { @@ -121,7 +121,7 @@ public Object execute(VirtualFrame frame) { } return null; } - }); + }.getCallTarget(); final int compilationThreshold = target.getOptionValue(PolyglotCompilerOptions.LastTierCompilationThreshold); final int reprofileCount = target.getOptionValue(PolyglotCompilerOptions.ReplaceReprofileCount); assertTrue(compilationThreshold >= 2); @@ -187,7 +187,7 @@ public void testRewriteAssumption() { final int compilationThreshold = 20; setupContext("engine.Inlining", "true", "engine.SingleTierCompilationThreshold", String.valueOf(compilationThreshold), "engine.MultiTier", "false"); - OptimizedCallTarget innermostCallTarget = (OptimizedCallTarget) runtime.createCallTarget(new RootTestNode(new FrameDescriptor(), testName + 0, new AbstractTestNode() { + OptimizedCallTarget innermostCallTarget = (OptimizedCallTarget) new RootTestNode(new FrameDescriptor(), testName + 0, new AbstractTestNode() { @Child private AbstractTestNode child = new ConstantTestNode(42); @Child private AbstractTestNode dummy = new ConstantTestNode(17); @@ -200,12 +200,12 @@ public int execute(VirtualFrame frame) { } return child.execute(frame); } - })); + }).getCallTarget(); assertEquals(compilationThreshold, (int) innermostCallTarget.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold)); OptimizedCallTarget ct = innermostCallTarget; - ct = (OptimizedCallTarget) runtime.createCallTarget(new RootTestNode(new FrameDescriptor(), testName + 1, new CallTestNode(ct))); - ct = (OptimizedCallTarget) runtime.createCallTarget(new RootTestNode(new FrameDescriptor(), testName + 2, new CallTestNode(ct))); + ct = (OptimizedCallTarget) new RootTestNode(new FrameDescriptor(), testName + 1, new CallTestNode(ct)).getCallTarget(); + ct = (OptimizedCallTarget) new RootTestNode(new FrameDescriptor(), testName + 2, new CallTestNode(ct)).getCallTarget(); final OptimizedCallTarget outermostCallTarget = ct; assertNull("assumption is initially null", getRewriteAssumption(innermostCallTarget)); @@ -264,14 +264,14 @@ public void testCompileOnly1() { // test single include setupContext("engine.CompileOnly", "foobar", "engine.MultiTier", "false"); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new NamedRootNode("foobar")); + OptimizedCallTarget target = (OptimizedCallTarget) new NamedRootNode("foobar").getCallTarget(); final int compilationThreshold = target.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); for (int i = 0; i < compilationThreshold; i++) { assertNotCompiled(target); target.call(); } assertCompiled(target); - target = (OptimizedCallTarget) runtime.createCallTarget(new NamedRootNode("baz")); + target = (OptimizedCallTarget) new NamedRootNode("baz").getCallTarget(); for (int i = 0; i < compilationThreshold; i++) { assertNotCompiled(target); target.call(); @@ -283,14 +283,14 @@ public void testCompileOnly1() { public void testCompileOnly2() { // test single exclude setupContext("engine.CompileOnly", "~foobar", "engine.MultiTier", "false"); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new NamedRootNode("foobar")); + OptimizedCallTarget target = (OptimizedCallTarget) new NamedRootNode("foobar").getCallTarget(); final int compilationThreshold = target.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); for (int i = 0; i < compilationThreshold; i++) { assertNotCompiled(target); target.call(); } assertNotCompiled(target); - target = (OptimizedCallTarget) runtime.createCallTarget(new NamedRootNode("baz")); + target = (OptimizedCallTarget) new NamedRootNode("baz").getCallTarget(); for (int i = 0; i < compilationThreshold; i++) { assertNotCompiled(target); target.call(); @@ -302,14 +302,14 @@ public void testCompileOnly2() { public void testCompileOnly3() { // test two includes/excludes setupContext("engine.CompileOnly", "foo,baz", "engine.MultiTier", "false"); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new NamedRootNode("foobar")); + OptimizedCallTarget target = (OptimizedCallTarget) new NamedRootNode("foobar").getCallTarget(); final int compilationThreshold = target.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); for (int i = 0; i < compilationThreshold; i++) { assertNotCompiled(target); target.call(); } assertCompiled(target); - target = (OptimizedCallTarget) runtime.createCallTarget(new NamedRootNode("baz")); + target = (OptimizedCallTarget) new NamedRootNode("baz").getCallTarget(); for (int i = 0; i < compilationThreshold; i++) { assertNotCompiled(target); target.call(); @@ -336,10 +336,10 @@ public boolean executeRepeating(VirtualFrame frame) { public void testCompileOnly4() { // OSR should not trigger for compile-only includes setupContext("engine.CompileOnly", "foobar"); - OptimizedCallTarget constant = (OptimizedCallTarget) runtime.createCallTarget(RootNode.createConstantNode(42)); + OptimizedCallTarget constant = (OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget(); final OSRRepeatingNode repeating = new OSRRepeatingNode(constant.getOptionValue(PolyglotCompilerOptions.OSRCompilationThreshold)); final LoopNode loop = runtime.createLoopNode(repeating); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new NamedRootNode("foobar") { + OptimizedCallTarget target = (OptimizedCallTarget) new NamedRootNode("foobar") { @Child LoopNode loopChild = loop; @@ -349,7 +349,7 @@ public Object execute(VirtualFrame frame) { return super.execute(frame); } - }); + }.getCallTarget(); target.call(); OptimizedCallTarget osrTarget = findOSRTarget(loop); if (osrTarget != null) { @@ -367,7 +367,7 @@ public void testCompilation() { private void testCompilationImpl(Boolean compileOptionValue, boolean expectedCompiled) { String[] options = compileOptionValue == null ? new String[]{"engine.MultiTier", "false"} : new String[]{"engine.Compilation", compileOptionValue.toString(), "engine.MultiTier", "false"}; setupContext(options); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new NamedRootNode("foobar")); + OptimizedCallTarget target = (OptimizedCallTarget) new NamedRootNode("foobar").getCallTarget(); final int compilationThreshold = target.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); for (int i = 0; i < compilationThreshold; i++) { assertNotCompiled(target); @@ -399,10 +399,10 @@ private static OptimizedCallTarget findOSRTarget(Node loopNode) { public void testCompileOnly5() { // OSR should trigger if compile-only with excludes setupContext("engine.CompileOnly", "~foobar"); - OptimizedCallTarget constant = (OptimizedCallTarget) runtime.createCallTarget(RootNode.createConstantNode(42)); + OptimizedCallTarget constant = (OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget(); final OSRRepeatingNode repeating = new OSRRepeatingNode(constant.getOptionValue(PolyglotCompilerOptions.OSRCompilationThreshold)); final LoopNode loop = runtime.createLoopNode(repeating); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(new NamedRootNode("foobar") { + OptimizedCallTarget target = (OptimizedCallTarget) new NamedRootNode("foobar") { @Child LoopNode loopChild = loop; @@ -412,7 +412,7 @@ public Object execute(VirtualFrame frame) { return super.execute(frame); } - }); + }.getCallTarget(); target.call(); OptimizedCallTarget osrTarget = findOSRTarget(loop); assertCompiled(osrTarget); @@ -430,7 +430,7 @@ public void testInCompilationRootDirective() { int[] innerMethod = {0}; int[] innerBoundary = {0}; - final OptimizedCallTarget innerTarget = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + final OptimizedCallTarget innerTarget = (OptimizedCallTarget) new RootNode(null) { @Override public String toString() { @@ -462,8 +462,8 @@ void innerBoundary() { innerBoundary[0] = 1; } } - }); - final OptimizedCallTarget outerTarget = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + }.getCallTarget(); + final OptimizedCallTarget outerTarget = (OptimizedCallTarget) new RootNode(null) { @Override public String toString() { @@ -497,7 +497,7 @@ void outerBoundary() { outerBoundary[0]++; } } - }); + }.getCallTarget(); final int compilationThreshold = outerTarget.getOptionValue(PolyglotCompilerOptions.LastTierCompilationThreshold); for (int i = 0; i < compilationThreshold; i++) { outerTarget.call(); @@ -520,8 +520,8 @@ void outerBoundary() { @Test public void testManyArguments() { setupContext("engine.CompileImmediately", Boolean.TRUE.toString()); - CallTarget fortyTwo = runtime.createCallTarget(new RootTestNode(new FrameDescriptor(), "42", new ConstantTestNode(42))); - OptimizedCallTarget ct = (OptimizedCallTarget) runtime.createCallTarget(new RootTestNode(new FrameDescriptor(), "caller", new CallTestNode(fortyTwo))); + CallTarget fortyTwo = new RootTestNode(new FrameDescriptor(), "42", new ConstantTestNode(42)).getCallTarget(); + OptimizedCallTarget ct = (OptimizedCallTarget) new RootTestNode(new FrameDescriptor(), "caller", new CallTestNode(fortyTwo)).getCallTarget(); for (int i = 0; i < 3; i++) { ct.call(IntStream.range(0, 100000).mapToObj(Integer::valueOf).toArray()); } @@ -533,8 +533,8 @@ public void testNoArgumentTypeSpeculation() { setupContext("engine.CompileImmediately", Boolean.TRUE.toString(), "engine.CompilationFailureAction", "Throw", "engine.BackgroundCompilation", Boolean.FALSE.toString(), "engine.ArgumentTypeSpeculation", Boolean.FALSE.toString()); - CallTarget fortyTwo = runtime.createCallTarget(new RootTestNode(new FrameDescriptor(), "42", new ConstantTestNode(42))); - OptimizedCallTarget ct = (OptimizedCallTarget) runtime.createCallTarget(new RootTestNode(new FrameDescriptor(), "caller", new CallTestNode(fortyTwo))); + CallTarget fortyTwo = new RootTestNode(new FrameDescriptor(), "42", new ConstantTestNode(42)).getCallTarget(); + OptimizedCallTarget ct = (OptimizedCallTarget) new RootTestNode(new FrameDescriptor(), "caller", new CallTestNode(fortyTwo)).getCallTarget(); for (int i = 0; i < 3; i++) { ct.call(IntStream.range(0, 20).mapToObj(Integer::valueOf).toArray()); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedOSRLoopNodeTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedOSRLoopNodeTest.java index 7f34a7a5bcdf..b91c8542f042 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedOSRLoopNodeTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedOSRLoopNodeTest.java @@ -87,10 +87,10 @@ public static void doBefore() { // ensure that all classes are properly loaded int defaultThreshold = OSRCompilationThreshold.getDefaultValue(); TestRootNode rootNode = new TestRootNode(defaultThreshold, DEFAULT, new TestRepeatingNode()); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); target.call(1); rootNode = new TestRootNode(defaultThreshold, CONFIGURED, new TestRepeatingNode()); - target = runtime.createCallTarget(rootNode); + target = rootNode.getCallTarget(); target.call(1); } @@ -98,7 +98,7 @@ public static void doBefore() { @Override public void before() { setupContext("engine.MultiTier", "false"); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(0)); + OptimizedCallTarget target = (OptimizedCallTarget) RootNode.createConstantNode(0).getCallTarget(); osrThreshold = target.getOptionValue(OSRCompilationThreshold); } @@ -108,7 +108,7 @@ public void before() { @Theory public void testOSRSingleInvocation(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new TestRepeatingNode()); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); target.call(osrThreshold + 1); assertCompiled(rootNode.getOSRTarget()); target.call(2); @@ -120,7 +120,7 @@ public void testOSRSingleInvocation(OSRLoopFactory factory) { public void testNoInliningForLatency(OSRLoopFactory factory) { setupContext("engine.MultiTier", "false", "engine.Mode", "latency"); TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new CallsTargetRepeatingNode( - (OptimizedDirectCallNode) runtime.createDirectCallNode(runtime.createCallTarget(new RootNode(null) { + (OptimizedDirectCallNode) runtime.createDirectCallNode(new RootNode(null) { @Override public Object execute(VirtualFrame frame) { if (CompilerDirectives.inCompiledCode() && !CompilerDirectives.inCompilationRoot()) { @@ -128,8 +128,8 @@ public Object execute(VirtualFrame frame) { } return 42; } - })))); - CallTarget target = runtime.createCallTarget(rootNode); + }.getCallTarget()))); + CallTarget target = rootNode.getCallTarget(); target.call(osrThreshold + 1); assertCompiled(rootNode.getOSRTarget()); } @@ -139,7 +139,7 @@ public Object execute(VirtualFrame frame) { public void testOSRAndRewriteDoesNotSuppressTargetCompilation(OSRLoopFactory factory) { setupContext("engine.SingleTierCompilationThreshold", "3"); TestRootNodeWithReplacement rootNode = new TestRootNodeWithReplacement(osrThreshold, factory, new TestRepeatingNode()); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); target.call(osrThreshold + 1); assertCompiled(rootNode.getOSRTarget()); assertNotCompiled(target); @@ -175,7 +175,7 @@ public boolean executeRepeating(VirtualFrame frame) { } TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new TransferToInterpreterTestRepeatingNode()); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); target.call(osrThreshold + 1); try { // Invalidation is asynchronous. @@ -192,7 +192,7 @@ public boolean executeRepeating(VirtualFrame frame) { @Theory public void testNonOSR(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new TestRepeatingNode()); - runtime.createCallTarget(rootNode).call(osrThreshold); + rootNode.getCallTarget().call(osrThreshold); assertNotCompiled(rootNode.getOSRTarget()); } @@ -251,7 +251,7 @@ public Object execute(VirtualFrame frame) { @Theory public void testNoInvalidationWithoutFirstExecution(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new TestRepeatingNode()); - RootCallTarget target = runtime.createCallTarget(rootNode); + RootCallTarget target = rootNode.getCallTarget(); rootNode.forceOSR(); assertCompiled(rootNode.getOSRTarget()); target.call(1); // should not invalidate OSR @@ -302,7 +302,7 @@ public void testExternalInvalidations(OSRLoopFactory factory) { public void testInternalInvalidations(OSRLoopFactory factory) { TestRepeatingNode repeating = new TestRepeatingNode(); TestRootNode rootNode = new TestRootNode(osrThreshold, factory, repeating); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); target.call(osrThreshold + 1); target.resetCompilationProfile(); assertCompiled(rootNode.getOSRTarget()); @@ -321,7 +321,7 @@ public void testInternalInvalidations(OSRLoopFactory factory) { public void testOuterInvalidationTriggersOSR(OSRLoopFactory factory) { TestRepeatingNode repeating = new TestRepeatingNode(); TestRootNode rootNode = new TestRootNode(osrThreshold, factory, repeating); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); // compile inner target.call(osrThreshold + 1); @@ -366,7 +366,7 @@ public void testOuterInvalidationTriggersOSR(OSRLoopFactory factory) { @Theory public void testNoOSRAfterMinInvocationThreshold(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new TestRepeatingNode()); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); int i; for (i = 0; i < target.getOptionValue(MinInvokeThreshold); i++) { target.call(0); @@ -382,7 +382,7 @@ public void testNoOSRAfterMinInvocationThreshold(OSRLoopFactory factory) { @Theory public void testOSRMinInvocationThresholdPropagateLoopCounts(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new TestRepeatingNode()); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); int thresholdForOsr = this.osrThreshold; int truffleMinInvokes = target.getOptionValue(MinInvokeThreshold); @@ -429,7 +429,7 @@ public void testThreadSafety(OSRLoopFactory factory) { @Theory public void testTwoLoopsSilblings(OSRLoopFactory factory) { TwoSilblingLoopNodesTest rootNode = new TwoSilblingLoopNodesTest(osrThreshold, factory, new TestRepeatingNode(), new TestRepeatingNode()); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); target.call(osrThreshold + 1, 1); waitForCompiled(rootNode.getOSRTarget()); waitForCompiled(rootNode.getOSRTarget2()); @@ -474,7 +474,7 @@ public void testTwoLoopsParentChild1(OSRLoopFactory factory) { return null; }); TestRootNode rootNode = new TestRootNode(osrThreshold, factory, childLoop); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); target.call(1, osrThreshold); assertCompiled(rootNode.getOSRTarget()); @@ -488,7 +488,7 @@ public void testTwoLoopsParentChild2(OSRLoopFactory factory) { return null; }); TestRootNode rootNode = new TestRootNode(osrThreshold, factory, childLoop); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); target.call(1, osrThreshold + 1); assertCompiled(rootNode.getOSRTarget()); @@ -534,32 +534,32 @@ public boolean executeRepeating(VirtualFrame frame) { @Theory public void testCustomLoopContributingToOSR1(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new CustomInnerLoopRepeatingNode()); - runtime.createCallTarget(rootNode).call(10, osrThreshold / 10 - 1); // triggers + rootNode.getCallTarget().call(10, osrThreshold / 10 - 1); // triggers assertNotCompiled(rootNode.getOSRTarget()); - runtime.createCallTarget(rootNode).call(10, osrThreshold / 10); // triggers + rootNode.getCallTarget().call(10, osrThreshold / 10); // triggers assertCompiled(rootNode.getOSRTarget()); } @Theory public void testCustomLoopContributingToOSR2(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new CustomInnerLoopRepeatingNode()); - runtime.createCallTarget(rootNode).call(1, osrThreshold - 1); + rootNode.getCallTarget().call(1, osrThreshold - 1); assertNotCompiled(rootNode.getOSRTarget()); - runtime.createCallTarget(rootNode).call(1, osrThreshold); + rootNode.getCallTarget().call(1, osrThreshold); assertCompiled(rootNode.getOSRTarget()); } @Theory public void testCustomLoopContributingToOSR3(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new CustomInnerLoopRepeatingNode()); - runtime.createCallTarget(rootNode).call(2, osrThreshold / 2); + rootNode.getCallTarget().call(2, osrThreshold / 2); assertCompiled(rootNode.getOSRTarget()); } @Theory public void testCustomLoopContributingToOSR4(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new CustomInnerLoopRepeatingNode()); - runtime.createCallTarget(rootNode).call(2, osrThreshold / 2 - 1); + rootNode.getCallTarget().call(2, osrThreshold / 2 - 1); assertNotCompiled(rootNode.getOSRTarget()); } @@ -592,7 +592,7 @@ public boolean executeRepeating(VirtualFrame frame) { @Theory public void testStackTraceDoesNotShowOSR(OSRLoopFactory factory) { TestRootNode rootNode = new TestRootNode(osrThreshold, factory, new TestOSRStackTrace()); - CallTarget target = runtime.createCallTarget(rootNode); + CallTarget target = rootNode.getCallTarget(); target.call(1); rootNode.forceOSR(); assertCompiled(rootNode.getOSRTarget()); @@ -608,7 +608,7 @@ public void testStackTraceDoesNotShowOSR(OSRLoopFactory factory) { public void testStackFrameNodes(OSRLoopFactory factory) { TestOSRStackTraceFromAbove testOSRStackTrace = new TestOSRStackTraceFromAbove(); TestRootNode rootNode = new TestRootNode(osrThreshold, factory, testOSRStackTrace); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); rootNode.forceOSR(); target.call(1); } @@ -663,7 +663,7 @@ public Object execute(VirtualFrame frame) { return null; } }; - callNode = runtime.createDirectCallNode(runtime.createCallTarget(root)); + callNode = runtime.createDirectCallNode(root.getCallTarget()); adoptChildren(); callNode.call(new Object[]{}); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OverrideOptionsTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OverrideOptionsTest.java index 9aec32e8fa0c..9bbab932c46b 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OverrideOptionsTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OverrideOptionsTest.java @@ -33,7 +33,6 @@ import org.junit.Assert; import org.junit.Test; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.RootNode; public class OverrideOptionsTest extends TruffleCompilerImplTest { @@ -43,7 +42,7 @@ public class OverrideOptionsTest extends TruffleCompilerImplTest { public void testOverrideOptionsUsingContext() { setupContext(Context.newBuilder().allowAllAccess(true).allowExperimentalOptions(true).option("engine.BackgroundCompilation", Boolean.FALSE.toString()).option("engine.CompileImmediately", Boolean.TRUE.toString()).build()); - OptimizedCallTarget callTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + OptimizedCallTarget callTarget = (OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget(); OptionValues values = TruffleCompilerImpl.getOptionsForCompiler(GraalTruffleRuntime.getOptionsForCompiler(callTarget)); Assert.assertEquals(false, values.get(PolyglotCompilerOptions.BackgroundCompilation)); Assert.assertEquals(true, values.get(PolyglotCompilerOptions.CompileImmediately)); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PartialEvaluationTest.java index 979ed8df577b..106d63a22a00 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PartialEvaluationTest.java @@ -54,7 +54,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ControlFlowException; import com.oracle.truffle.api.nodes.RootNode; @@ -92,7 +91,7 @@ protected final CompilationIdentifier getCompilationId(final RootCallTarget comp } protected OptimizedCallTarget compileHelper(String methodName, RootNode root, Object[] arguments) { - final OptimizedCallTarget compilable = (OptimizedCallTarget) (Truffle.getRuntime()).createCallTarget(root); + final OptimizedCallTarget compilable = (OptimizedCallTarget) root.getCallTarget(); CompilationIdentifier compilationId = getCompilationId(compilable); StructuredGraph graph = partialEval(compilable, arguments, compilationId); this.lastCompilationResult = getTruffleCompiler(compilable).compilePEGraph(graph, methodName, null, compilable, asCompilationRequest(compilationId), null, @@ -120,8 +119,8 @@ protected OptimizedCallTarget assertPartialEvalEquals(RootNode expected, RootNod } protected OptimizedCallTarget assertPartialEvalEquals(RootNode expected, RootNode actual, Object[] arguments, boolean checkConstants) { - final OptimizedCallTarget expectedTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(expected); - final OptimizedCallTarget actualTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(actual); + final OptimizedCallTarget expectedTarget = (OptimizedCallTarget) expected.getCallTarget(); + final OptimizedCallTarget actualTarget = (OptimizedCallTarget) actual.getCallTarget(); BailoutException lastBailout = null; for (int i = 0; i < 10; i++) { @@ -184,8 +183,7 @@ protected void assertPartialEvalNoInvokes(RootNode root) { } protected void assertPartialEvalNoInvokes(RootNode root, Object[] arguments) { - CallTarget callTarget = Truffle.getRuntime().createCallTarget(root); - assertPartialEvalNoInvokes(callTarget, arguments); + assertPartialEvalNoInvokes(root.getCallTarget(), arguments); } protected void assertPartialEvalNoInvokes(CallTarget callTarget, Object[] arguments) { @@ -196,7 +194,7 @@ protected void assertPartialEvalNoInvokes(CallTarget callTarget, Object[] argume } protected StructuredGraph partialEval(RootNode root, Object... arguments) { - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); + OptimizedCallTarget target = (OptimizedCallTarget) root.getCallTarget(); return partialEval(target, arguments); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PerformanceWarningTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PerformanceWarningTest.java index 7dba5e5cac36..957582b08762 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PerformanceWarningTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PerformanceWarningTest.java @@ -130,9 +130,8 @@ private void testHelper(RootNode rootNode, boolean expectException, String... ou // Compile and capture output to logger's stream. boolean seenException = false; try { - GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); - DebugContext debug = new Builder(runtime.getGraalOptions(OptionValues.class)).build(); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); + DebugContext debug = new Builder(GraalTruffleRuntime.getRuntime().getGraalOptions(OptionValues.class)).build(); try (DebugCloseable d = debug.disableIntercept(); DebugContext.Scope s = debug.scope("PerformanceWarningTest")) { final OptimizedCallTarget compilable = target; CompilationIdentifier compilationId = getTruffleCompiler(target).createCompilationIdentifier(compilable); @@ -444,13 +443,12 @@ protected class TrivialCallsInnerNode extends RootNode { public TrivialCallsInnerNode() { super(null); - final GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - this.callNode = (OptimizedDirectCallNode) runtime.createDirectCallNode(runtime.createCallTarget(new RootNode(null) { + this.callNode = (OptimizedDirectCallNode) GraalTruffleRuntime.getRuntime().createDirectCallNode(new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return 0; } - })); + }.getCallTarget()); } @Override diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PhiStampInferencePartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PhiStampInferencePartialEvaluationTest.java index 07f9c201afcb..36beeed03a5a 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PhiStampInferencePartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PhiStampInferencePartialEvaluationTest.java @@ -31,7 +31,6 @@ import org.junit.Test; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; @@ -48,7 +47,7 @@ public void ifPhiStamp() { FrameDescriptor fd = new FrameDescriptor(); AbstractTestNode result = new IfPhiStampTestNode(); RootNode rootNode = new RootTestNode(fd, "ifPhiStamp", result); - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); + RootCallTarget callTarget = rootNode.getCallTarget(); callTarget.call(new Object[]{true}); callTarget.call(new Object[]{false}); new D().get(); // ensure method cannot be statically bound without receiver type info diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PolyglotEngineOptionsTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PolyglotEngineOptionsTest.java index c101fb443c2f..f485882432f9 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PolyglotEngineOptionsTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PolyglotEngineOptionsTest.java @@ -33,7 +33,6 @@ import org.junit.Assert; import org.junit.Test; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.sl.runtime.SLContext; import com.oracle.truffle.sl.runtime.SLFunction; @@ -54,7 +53,7 @@ public void testCompilationThreshold() { Assert.assertEquals(2, SLFunction.INLINE_CACHE_SIZE); // doWhile must run isolated and should not affect other compilation thresholds - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + OptimizedCallTarget target = (OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget(); Runnable doWhile = () -> testCompilationThreshold(50, "50", null); testCompilationThreshold(42, "42", doWhile); // test default value testCompilationThreshold(target.getOptionValue(PolyglotCompilerOptions.LastTierCompilationThreshold), null, doWhile); @@ -69,7 +68,7 @@ public void testPolyglotCompilerOptionsAreUsed() { "engine.Inlining", "false", // "engine.Splitting", "false", // "engine.Mode", "latency"); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + OptimizedCallTarget target = (OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget(); Assert.assertEquals(27, (int) target.getOptionValue(PolyglotCompilerOptions.LastTierCompilationThreshold)); Assert.assertEquals(true, target.getOptionValue(PolyglotCompilerOptions.TraceCompilation)); Assert.assertEquals(true, target.getOptionValue(PolyglotCompilerOptions.TraceCompilationDetails)); @@ -83,7 +82,7 @@ public void testEngineModeLatency() { Assert.assertEquals(OptionStability.STABLE, Engine.create().getOptions().get("engine.Mode").getStability()); setupContext("engine.Mode", "latency"); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + OptimizedCallTarget target = (OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget(); Assert.assertEquals(PolyglotCompilerOptions.EngineModeEnum.LATENCY, target.getOptionValue(PolyglotCompilerOptions.Mode)); Assert.assertEquals(true, target.engine.inlining); Assert.assertEquals(false, target.engine.splitting); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/RewriteDuringCompilationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/RewriteDuringCompilationTest.java index 8300eef3a54d..c047c8935d72 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/RewriteDuringCompilationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/RewriteDuringCompilationTest.java @@ -221,7 +221,7 @@ private void testCompilation(BaseNode testedCode, LoopNode loopNode, DetectInval protected synchronized CallTarget parse(ParsingRequest request) throws Exception { com.oracle.truffle.api.source.Source source = request.getSource(); if (target == null) { - target = Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + target = new RootNode(languageInstance) { @Node.Child private volatile BaseNode child = testedCode; @@ -235,7 +235,7 @@ public SourceSection getSourceSection() { return source.createSection(1); } - }); + }.getCallTarget(); } return target; } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ThreadsActivationCompilationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ThreadsActivationCompilationTest.java index eedef1736e4b..c50416c0c9ee 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ThreadsActivationCompilationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ThreadsActivationCompilationTest.java @@ -83,7 +83,7 @@ public void onEnterThread(TruffleContext c) { compiledEnter.set(Boolean.FALSE); compiledLeave.set(Boolean.FALSE); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(new RootNode(null) { + OptimizedCallTarget target = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { TruffleContext tc = (TruffleContext) frame.getArguments()[0]; @@ -104,7 +104,7 @@ public Object execute(VirtualFrame frame) { } return null; } - }); + }.getCallTarget(); TruffleContext tc = LanguageContext.get(null).getEnv().getContext(); singleContext.invalidate(); target.call(tc); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TraceCompilationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TraceCompilationTest.java index 11073a2a1eb8..b1b700712501 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TraceCompilationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TraceCompilationTest.java @@ -24,11 +24,6 @@ */ package org.graalvm.compiler.truffle.test; -import com.oracle.truffle.api.Assumption; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.frame.FrameDescriptor; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.RootNode; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; @@ -47,6 +42,7 @@ import java.util.logging.LogRecord; import java.util.regex.Pattern; import java.util.stream.Collectors; + import org.graalvm.compiler.test.SubprocessUtil; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.compiler.truffle.test.nodes.AbstractTestNode; @@ -55,6 +51,12 @@ import org.junit.Assert; import org.junit.Test; +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.RootNode; + public class TraceCompilationTest extends TestWithPolyglotOptions { private static final String CONFIGURED_PROPERTY = ExceptionActionTest.class.getSimpleName() + ".configured"; @@ -130,7 +132,7 @@ public void testNoEngineTracingOn() throws Exception { PrintStream origSystemErr = System.err; ByteArrayOutputStream rawStdErr = new ByteArrayOutputStream(); System.setErr(new PrintStream(rawStdErr, true, "UTF-8")); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(10)); + OptimizedCallTarget target = (OptimizedCallTarget) RootNode.createConstantNode(10).getCallTarget(); target.call(); System.setErr(origSystemErr); String strStdErr = rawStdErr.toString("UTF-8"); @@ -249,10 +251,10 @@ private void testHelper(Supplier rootProvider, Map add } TestHandler handler = builder.build(); setupContext(newContextBuilder(additionalOptions, handler)); - OptimizedCallTarget warmUpTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(rootProvider.get()); + OptimizedCallTarget warmUpTarget = (OptimizedCallTarget) rootProvider.get().getCallTarget(); warmUpTarget.call(); handler.start(); - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(rootProvider.get()); + OptimizedCallTarget target = (OptimizedCallTarget) rootProvider.get().getCallTarget(); target.call(); handler.assertLogs(); return null; diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TransferToInterpreterTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TransferToInterpreterTest.java index 43de7e5ab98a..9901472094a1 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TransferToInterpreterTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TransferToInterpreterTest.java @@ -53,7 +53,7 @@ public void setup() { public void test() { RootNode rootNode = new TestRootNode(); GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget target = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + OptimizedCallTarget target = (OptimizedCallTarget) rootNode.getCallTarget(); target.call(0); Assert.assertFalse(target.isValid()); final OptimizedCallTarget compilable = target; diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java index 1bc7432aa743..6307b305fdd3 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java @@ -95,7 +95,7 @@ public void onCompilationStarted(OptimizedCallTarget target, int tier) { setupContext("engine.InvalidationReprofileCount", "0", "engine.MultiTier", "false"); DeoptCountingExceptionOverBoundaryRootNode rootNode = new DeoptCountingExceptionOverBoundaryRootNode(); - final OptimizedCallTarget outerTarget = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + final OptimizedCallTarget outerTarget = (OptimizedCallTarget) rootNode.getCallTarget(); final int compilationThreshold = outerTarget.getOptionValue(SingleTierCompilationThreshold); for (int i = 0; i < compilationThreshold; i++) { @@ -159,7 +159,7 @@ public void throwExceptionBoundary() { } DeoptCountingExceptionOverBoundaryRootNode rootNode = new DeoptCountingExceptionOverBoundaryRootNode(); - final OptimizedCallTarget outerTarget = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + final OptimizedCallTarget outerTarget = (OptimizedCallTarget) rootNode.getCallTarget(); final int compilationThreshold = outerTarget.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); for (int i = 0; i < compilationThreshold; i++) { outerTarget.call(); @@ -208,7 +208,7 @@ public void throwExceptionBoundary() { } DeoptCountingExceptionOverBoundaryRootNode rootNode = new DeoptCountingExceptionOverBoundaryRootNode(); - final OptimizedCallTarget outerTarget = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + final OptimizedCallTarget outerTarget = (OptimizedCallTarget) rootNode.getCallTarget(); final int compilationThreshold = outerTarget.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); final int invalidationReprofileCount = outerTarget.getOptionValue(PolyglotCompilerOptions.InvalidationReprofileCount); @@ -278,7 +278,7 @@ public void throwExceptionBoundary() { } DeoptCountingExceptionOverBoundaryRootNode rootNode = new DeoptCountingExceptionOverBoundaryRootNode(); - final OptimizedCallTarget outerTarget = (OptimizedCallTarget) runtime.createCallTarget(rootNode); + final OptimizedCallTarget outerTarget = (OptimizedCallTarget) rootNode.getCallTarget(); final int compilationThreshold = outerTarget.getOptionValue(PolyglotCompilerOptions.SingleTierCompilationThreshold); for (int i = 0; i < compilationThreshold; i++) { try { diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryInliningTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryInliningTest.java index bbc694251992..05b207125e46 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryInliningTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryInliningTest.java @@ -34,17 +34,10 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; public class TruffleBoundaryInliningTest extends PartialEvaluationTest { - private TruffleRuntime runtime; - - public TruffleBoundaryInliningTest() { - this.runtime = Truffle.getRuntime(); - } private static RootNode createRootNodeAllowInline() { return new RootNode(null) { @@ -78,10 +71,10 @@ void testMethod() { private void runTest() { RootNode n1 = createRootNodeAllowInline(); - RootCallTarget c1 = runtime.createCallTarget(n1); + RootCallTarget c1 = n1.getCallTarget(); StructuredGraph allowInline = partialEval((OptimizedCallTarget) c1, new Object[]{}, getCompilationId(c1)); RootNode n2 = createRootNodeNoInline(); - RootCallTarget c2 = runtime.createCallTarget(n2); + RootCallTarget c2 = n2.getCallTarget(); StructuredGraph noInline = partialEval((OptimizedCallTarget) c2, new Object[]{}, getCompilationId(c2)); checkHasTestMethod(allowInline); checkHasTestMethod(noInline); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleCompilerImplTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleCompilerImplTest.java index e4649441b876..d5e6354a9901 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleCompilerImplTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleCompilerImplTest.java @@ -37,7 +37,6 @@ import org.junit.Assume; import org.junit.Before; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleOptions; import com.oracle.truffle.api.nodes.RootNode; @@ -59,8 +58,7 @@ protected TruffleCompilerImplTest() { @Before public void onlyWhiteBox() { if (TruffleOptions.AOT) { - GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - TruffleCompiler compiler = runtime.getTruffleCompiler((OptimizedCallTarget) runtime.createCallTarget(RootNode.createConstantNode(42))); + TruffleCompiler compiler = GraalTruffleRuntime.getRuntime().getTruffleCompiler((OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget()); Assume.assumeTrue("cannot get whitebox interface to Truffle compiler", compiler instanceof TruffleCompilerImpl); this.truffleCompiler = (TruffleCompilerImpl) compiler; } @@ -75,7 +73,7 @@ protected final TruffleCompilerImpl getTruffleCompiler(OptimizedCallTarget callT @Override protected CompilationIdentifier createCompilationId() { - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(42)); + OptimizedCallTarget target = (OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget(); return getTruffleCompiler(target).createCompilationIdentifier(target); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleDirectCallNodeTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleDirectCallNodeTest.java index 0bde080447b0..09d82acfb3fc 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleDirectCallNodeTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleDirectCallNodeTest.java @@ -49,7 +49,7 @@ public boolean isCloningAllowed() { return true; } }; - final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); + final CallTarget callTarget = rootNode.getCallTarget(); final DirectCallNode callNode = Truffle.getRuntime().createDirectCallNode(callTarget); assertTrue(callNode.isCallTargetCloningAllowed()); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleExceptionPartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleExceptionPartialEvaluationTest.java index a55b440f0ba1..e912b979dfa6 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleExceptionPartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleExceptionPartialEvaluationTest.java @@ -78,14 +78,14 @@ static RootTestNode createCallerChain(int framesAbove, int framesBelow, NodeFact AbstractTestNode calleeNode = factory.createThrowNode(-1, true); RootTestNode calleeRoot = new RootTestNode(fd, "testTruffleException", calleeNode); for (int i = 0; i < framesAbove; i++) { - AbstractTestNode call = new CallTestNode(Truffle.getRuntime().createCallTarget(calleeRoot)); + AbstractTestNode call = new CallTestNode(calleeRoot.getCallTarget()); calleeRoot = new RootTestNode(fd, "testTruffleException", call); } - AbstractTestNode callerNode = new CallTestNode(Truffle.getRuntime().createCallTarget(calleeRoot)); + AbstractTestNode callerNode = new CallTestNode(calleeRoot.getCallTarget()); AbstractTestNode catchNode = factory.createCatchNode(callerNode); RootTestNode callerRoot = new RootTestNode(fd, "testTruffleException", catchNode); for (int i = 0; i < framesBelow; i++) { - AbstractTestNode call = new CallTestNode(Truffle.getRuntime().createCallTarget(callerRoot)); + AbstractTestNode call = new CallTestNode(callerRoot.getCallTarget()); callerRoot = new RootTestNode(fd, "testTruffleException", call); } return callerRoot; diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleReturnBoxedParameterTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleReturnBoxedParameterTest.java index 81e2a11d4a27..21edbeb5be44 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleReturnBoxedParameterTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleReturnBoxedParameterTest.java @@ -30,7 +30,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.compiler.truffle.test.TruffleReturnBoxedParameterTestFactory.IntNodeFactory; import org.junit.Test; @@ -142,7 +141,7 @@ static E createNode(NodeFactory factory, boolean prefixCons @Test public void testBox() throws Throwable { TestRootNode node = createRoot(IntNodeFactory.getInstance()); - OptimizedCallTarget callTarget = (OptimizedCallTarget) GraalTruffleRuntime.getRuntime().createCallTarget(node); + OptimizedCallTarget callTarget = (OptimizedCallTarget) node.getCallTarget(); StructuredGraph g = partialEval(callTarget, new Object[]{1}); compile(callTarget, g); // no box foreign call to allocation snippet after box optimization diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleToTruffleCallExceptionHandlerTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleToTruffleCallExceptionHandlerTest.java index 3a37bd9050cf..8b67c1b2d5c4 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleToTruffleCallExceptionHandlerTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleToTruffleCallExceptionHandlerTest.java @@ -47,7 +47,7 @@ public class TruffleToTruffleCallExceptionHandlerTest extends PartialEvaluationT private static final class Compilables { - final OptimizedCallTarget calleeNoException = (OptimizedCallTarget) GraalTruffleRuntime.getRuntime().createCallTarget(new RootNode(null) { + final OptimizedCallTarget calleeNoException = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { return null; @@ -57,9 +57,9 @@ public Object execute(VirtualFrame frame) { public String toString() { return "CALLEE_NO_EXCEPTION"; } - }); + }.getCallTarget(); - final OptimizedCallTarget callerNoException = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + final OptimizedCallTarget callerNoException = (OptimizedCallTarget) new RootNode(null) { @Child protected DirectCallNode callNode = runtime.createDirectCallNode(calleeNoException); @@ -73,9 +73,9 @@ public Object execute(VirtualFrame frame) { public String toString() { return "CALLER_NO_EXCEPTION"; } - }); + }.getCallTarget(); - final OptimizedCallTarget calleeWithException = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + final OptimizedCallTarget calleeWithException = (OptimizedCallTarget) new RootNode(null) { @Override public Object execute(VirtualFrame frame) { throw new RuntimeException(); @@ -85,9 +85,9 @@ public Object execute(VirtualFrame frame) { public String toString() { return "CALLEE_EXCEPTION"; } - }); + }.getCallTarget(); - final OptimizedCallTarget callerWithException = (OptimizedCallTarget) runtime.createCallTarget(new RootNode(null) { + final OptimizedCallTarget callerWithException = (OptimizedCallTarget) new RootNode(null) { @Child protected DirectCallNode callNode = runtime.createDirectCallNode(calleeWithException); @@ -101,7 +101,7 @@ public Object execute(VirtualFrame frame) { public String toString() { return "CALLER_EXCEPTION"; } - }); + }.getCallTarget(); } @Test diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/UnrollLoopBlockDuplicationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/UnrollLoopBlockDuplicationTest.java index 2b890f7faba4..91508729a46f 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/UnrollLoopBlockDuplicationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/UnrollLoopBlockDuplicationTest.java @@ -29,7 +29,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.UnsupportedSpecializationException; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; @@ -45,7 +44,7 @@ public class UnrollLoopBlockDuplicationTest extends TestWithSynchronousCompiling */ @Test public void testBlockDuplication() { - OptimizedCallTarget target = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(new ObjectCacheTestRootNode()); + OptimizedCallTarget target = (OptimizedCallTarget) new ObjectCacheTestRootNode().getCallTarget(); AbstractType value1 = new ConcreteType1(); AbstractType value2 = new ConcreteType2(); target.call(value1); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/inlining/InlineOnlyTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/inlining/InlineOnlyTest.java index 04e1a4042688..007d7fd36fbd 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/inlining/InlineOnlyTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/inlining/InlineOnlyTest.java @@ -34,7 +34,6 @@ import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.RootNode; @@ -80,8 +79,7 @@ public static class ExcludePatternTestLanguage extends ProxyLanguage { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - final TruffleRuntime runtime = Truffle.getRuntime(); - final RootCallTarget rootCallTarget = runtime.createCallTarget(new RootNode(this) { + final RootCallTarget rootCallTarget = new RootNode(this) { @Override public String toString() { @@ -98,10 +96,10 @@ public Object execute(VirtualFrame frame) { public String getName() { return METHOD_EXCLUDED_FROM_INLINING; } - }); - return runtime.createCallTarget(new RootNode(this) { + }.getCallTarget(); + return new RootNode(this) { - @Child DirectCallNode callNode = runtime.createDirectCallNode(rootCallTarget); + @Child DirectCallNode callNode = Truffle.getRuntime().createDirectCallNode(rootCallTarget); @Override public String toString() { @@ -117,7 +115,7 @@ public String getName() { public Object execute(VirtualFrame frame) { return callNode.call(); } - }); + }.getCallTarget(); } } @@ -128,8 +126,7 @@ public static class InlineSelectedMethodsTestLanguage extends ProxyLanguage { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - final TruffleRuntime runtime = Truffle.getRuntime(); - final RootCallTarget rootCallTarget = runtime.createCallTarget(new RootNode(this) { + final RootCallTarget rootCallTarget = new RootNode(this) { @Override public String toString() { @@ -153,10 +150,10 @@ private void assertFalse(boolean inCompilationRoot) { public String getName() { return METHOD_INLINED; } - }); - return runtime.createCallTarget(new RootNode(this) { + }.getCallTarget(); + return new RootNode(this) { - @Child DirectCallNode callNode = runtime.createDirectCallNode(rootCallTarget); + @Child DirectCallNode callNode = Truffle.getRuntime().createDirectCallNode(rootCallTarget); @Override public String toString() { @@ -172,7 +169,7 @@ public String getName() { public Object execute(VirtualFrame frame) { return callNode.call(); } - }); + }.getCallTarget(); } } } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/inlining/InliningTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/inlining/InliningTest.java index f8269c684480..f4cfe1d567f7 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/inlining/InliningTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/inlining/InliningTest.java @@ -32,7 +32,6 @@ import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.TruffleRuntime; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.RootNode; @@ -71,8 +70,7 @@ public static class InliningTestLanguage extends ProxyLanguage { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - final TruffleRuntime runtime = Truffle.getRuntime(); - final RootCallTarget mustNotInline = runtime.createCallTarget(new RootNode(this) { + final RootCallTarget mustNotInline = new RootNode(this) { @Override public String toString() { @@ -84,10 +82,10 @@ public Object execute(VirtualFrame frame) { CompilerDirectives.bailout("This node should not be inlined"); return 42; } - }); - return runtime.createCallTarget(new RootNode(this) { + }.getCallTarget(); + return new RootNode(this) { - @Child DirectCallNode callNode = runtime.createDirectCallNode(mustNotInline); + @Child DirectCallNode callNode = Truffle.getRuntime().createDirectCallNode(mustNotInline); @Override public String toString() { @@ -103,7 +101,7 @@ public String getName() { public Object execute(VirtualFrame frame) { return callNode.call(); } - }); + }.getCallTarget(); } } } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/libgraal/JNIExceptionWrapperTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/libgraal/JNIExceptionWrapperTest.java index 2a9429f5a632..3b12a9715dd7 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/libgraal/JNIExceptionWrapperTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/libgraal/JNIExceptionWrapperTest.java @@ -90,7 +90,7 @@ private static List makeSilent(List vmArgs) { private void testMergedStackTraceImpl() throws Exception { setupContext("engine.CompilationExceptionsAreThrown", Boolean.TRUE.toString(), "engine.CompilationExceptionsAreFatal", Boolean.FALSE.toString()); GraalTruffleRuntime runtime = GraalTruffleRuntime.getRuntime(); - OptimizedCallTarget compilable = (OptimizedCallTarget) runtime.createCallTarget(RootNode.createConstantNode(42)); + OptimizedCallTarget compilable = (OptimizedCallTarget) RootNode.createConstantNode(42).getCallTarget(); TruffleCompiler compiler = runtime.getTruffleCompiler(compilable); try (TruffleCompilation compilation = compiler.openCompilation(compilable)) { try (TruffleDebugContext debug = compiler.openDebugContext(GraalTruffleRuntime.getOptionsForCompiler(compilable), compilation)) { From d1ecd9edf431795103e6746e54bb7173c2437235 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 27 Sep 2021 13:55:58 +0200 Subject: [PATCH 186/681] Avoid createCallTarget() in Espresso. --- .../oracle/truffle/espresso/EspressoLanguage.java | 7 +++---- .../src/com/oracle/truffle/espresso/impl/Method.java | 12 ++++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java index b6f055f118d4..61166a8a1951 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java @@ -32,7 +32,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Registration; import com.oracle.truffle.api.instrumentation.ProvidedTags; @@ -180,15 +179,15 @@ protected CallTarget parse(final ParsingRequest request) throws Exception { String contents = request.getSource().getCharacters().toString(); if (DestroyVMNode.EVAL_NAME.equals(contents)) { RootNode node = new DestroyVMNode(this); - return Truffle.getRuntime().createCallTarget(node); + return node.getCallTarget(); } if (ExitCodeNode.EVAL_NAME.equals(contents)) { RootNode node = new ExitCodeNode(this); - return Truffle.getRuntime().createCallTarget(node); + return node.getCallTarget(); } if (GetBindingsNode.EVAL_NAME.equals(contents)) { RootNode node = new GetBindingsNode(this); - return Truffle.getRuntime().createCallTarget(node); + return node.getCallTarget(); } throw new UnsupportedOperationException("Unsupported operation. Use the language bindings to load classes e.g. context.getBindings(\"" + ID + "\").getMember(\"java.lang.Integer\")"); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java index b6b86f7830cc..e28d1e17354b 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java @@ -460,7 +460,7 @@ private CallTarget lookupLibJavaCallTarget() { // Look in libjava TruffleObject nativeMethod = lookupAndBind(getVM().getJavaLibrary(), mangledName); if (nativeMethod != null) { - return Truffle.getRuntime().createCallTarget(EspressoRootNode.create(null, new NativeMethodNode(nativeMethod, getMethodVersion()))); + return EspressoRootNode.create(null, new NativeMethodNode(nativeMethod, getMethodVersion())).getCallTarget(); } } } @@ -473,7 +473,7 @@ private CallTarget lookupAgents() { String mangledName = Mangle.mangleMethod(this, withSignature); TruffleObject nativeMethod = getContext().bindToAgent(this, mangledName); if (nativeMethod != null) { - return Truffle.getRuntime().createCallTarget(EspressoRootNode.create(null, new NativeMethodNode(nativeMethod, getMethodVersion()))); + return EspressoRootNode.create(null, new NativeMethodNode(nativeMethod, getMethodVersion())).getCallTarget(); } } return null; @@ -499,7 +499,7 @@ private CallTarget lookupJniCallTarget(Method findNative, boolean fullSignature) } TruffleObject symbol = getVM().getFunction(handle); TruffleObject nativeMethod = bind(symbol); - return Truffle.getRuntime().createCallTarget(EspressoRootNode.create(null, new NativeMethodNode(nativeMethod, this.getMethodVersion()))); + return EspressoRootNode.create(null, new NativeMethodNode(nativeMethod, this.getMethodVersion())).getCallTarget(); } public boolean isConstructor() { @@ -975,7 +975,7 @@ public Method forceSplit() { Method result = new Method(this, getCodeAttribute()); FrameDescriptor frameDescriptor = new FrameDescriptor(); EspressoRootNode root = EspressoRootNode.create(frameDescriptor, new BytecodeNode(result.getMethodVersion(), frameDescriptor)); - result.getMethodVersion().callTarget = Truffle.getRuntime().createCallTarget(root); + result.getMethodVersion().callTarget = root.getCallTarget(); return result; } @@ -1362,7 +1362,7 @@ private CallTarget getCallTarget(boolean initKlass) { */ EspressoRootNode redirectedMethod = getSubstitutions().get(getMethod()); if (redirectedMethod != null) { - callTarget = Truffle.getRuntime().createCallTarget(redirectedMethod); + callTarget = redirectedMethod.getCallTarget(); return callTarget; } @@ -1416,7 +1416,7 @@ private CallTarget findCallTarget() { } FrameDescriptor frameDescriptor = new FrameDescriptor(); EspressoRootNode rootNode = EspressoRootNode.create(frameDescriptor, new BytecodeNode(this, frameDescriptor)); - target = Truffle.getRuntime().createCallTarget(rootNode); + target = rootNode.getCallTarget(); } return target; } From 3e85ffdc5594f30329955779943315536714e80e Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 27 Sep 2021 13:56:05 +0200 Subject: [PATCH 187/681] Avoid createCallTarget() in Sulong. --- .../runtime/NFIContextExtension.java | 4 +-- .../oracle/truffle/llvm/nfi/SulongNFI.java | 9 +++--- .../factories/BasicIntrinsicsProvider.java | 2 +- .../parser/factories/BasicNodeFactory.java | 12 ++++---- .../parser/LazyToTruffleConverterImpl.java | 29 ++++++++++--------- .../llvm/runtime/LLVMFunctionCode.java | 6 ++-- .../truffle/llvm/runtime/LLVMLanguage.java | 8 ++--- .../truffle/llvm/runtime/SulongLibrary.java | 10 +++---- .../llvm/runtime/debug/LLDBSupport.java | 4 +-- .../interop/LLVMTruffleDecorateFunction.java | 3 +- .../com/oracle/truffle/llvm/ParserDriver.java | 12 ++++---- .../initialization/InitializeModuleNode.java | 2 +- .../llvm/tests/interop/nfi/NFIAPITest.java | 3 +- 13 files changed, 48 insertions(+), 56 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.nativemode/src/com/oracle/truffle/llvm/nativemode/runtime/NFIContextExtension.java b/sulong/projects/com.oracle.truffle.llvm.nativemode/src/com/oracle/truffle/llvm/nativemode/runtime/NFIContextExtension.java index b2a89f6f8433..d1ca8bb0d266 100644 --- a/sulong/projects/com.oracle.truffle.llvm.nativemode/src/com/oracle/truffle/llvm/nativemode/runtime/NFIContextExtension.java +++ b/sulong/projects/com.oracle.truffle.llvm.nativemode/src/com/oracle/truffle/llvm/nativemode/runtime/NFIContextExtension.java @@ -40,7 +40,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.dsl.Specialization; @@ -285,8 +284,7 @@ public CallTarget createNativeWrapperFactory(LLVMFunctionCode code) { */ try { Source signatureSource = signatureSourceCache.getSignatureSource(code.getLLVMFunction().getType()); - RootNode root = CreateClosureNodeGen.create(LLVMLanguage.get(null), signatureSource, new LLVMNativeWrapper(code)); - return Truffle.getRuntime().createCallTarget(root); + return CreateClosureNodeGen.create(LLVMLanguage.get(null), signatureSource, new LLVMNativeWrapper(code)).getCallTarget(); } catch (UnsupportedNativeTypeException ex) { // ignore, fall back to tagged id return null; diff --git a/sulong/projects/com.oracle.truffle.llvm.nfi/src/com/oracle/truffle/llvm/nfi/SulongNFI.java b/sulong/projects/com.oracle.truffle.llvm.nfi/src/com/oracle/truffle/llvm/nfi/SulongNFI.java index 30f19e63ff4d..fcb7d56569b5 100644 --- a/sulong/projects/com.oracle.truffle.llvm.nfi/src/com/oracle/truffle/llvm/nfi/SulongNFI.java +++ b/sulong/projects/com.oracle.truffle.llvm.nfi/src/com/oracle/truffle/llvm/nfi/SulongNFI.java @@ -34,7 +34,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.ContextPolicy; @@ -127,7 +126,7 @@ Object createSignatureBuilder() { } private static CallTarget wrap(SulongNFI nfi, CallTarget target) { - return Truffle.getRuntime().createCallTarget(new RootNode(nfi) { + return new RootNode(nfi) { @Child DirectCallNode call = DirectCallNode.create(target); @@ -136,18 +135,18 @@ public Object execute(VirtualFrame frame) { Object ret = call.call(); return new SulongNFILibrary(ret); } - }); + }.getCallTarget(); } @Override protected CallTarget parse(ParsingRequest request) { - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public Object execute(VirtualFrame frame) { throw CompilerDirectives.shouldNotReachHere("illegal access to internal language"); } - }); + }.getCallTarget(); } @Override diff --git a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicIntrinsicsProvider.java b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicIntrinsicsProvider.java index 75449d2e00be..86831cba6710 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicIntrinsicsProvider.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicIntrinsicsProvider.java @@ -212,7 +212,7 @@ protected LLVMTypedIntrinsicFactory getFactory(String name) { } private RootCallTarget wrap(String functionName, LLVMExpressionNode node) { - return LLVMLanguage.createCallTarget(LLVMIntrinsicExpressionNodeGen.create(language, functionName, node)); + return LLVMIntrinsicExpressionNodeGen.create(language, functionName, node).getCallTarget(); } protected final LLVMLanguage language; diff --git a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java index aac96d172e97..b915ecfb201e 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java @@ -100,6 +100,7 @@ import com.oracle.truffle.llvm.runtime.nodes.control.LLVMLoopNode; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVM80BitFloatRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMAddressRetNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMArrayRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMDoubleRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMFloatRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMI16RetNodeGen; @@ -109,7 +110,6 @@ import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMI8RetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMIVarBitRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMStructRetNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMArrayRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMVectorRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMVoidReturnNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMSwitchNode; @@ -163,14 +163,14 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMArithmeticFactory.LLVMArithmeticWithOverflowNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMArithmeticFactory.LLVMSimpleArithmeticPrimitiveNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceAddNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceMulNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceAndNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceMulNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceOrNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceXorNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceUnsignedMaxNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceSignedMaxNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceUnsignedMinNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceSignedMinNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceUnsignedMaxNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceUnsignedMinNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceXorNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountLeadingZeroesNodeFactory.CountLeadingZeroesI16NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountLeadingZeroesNodeFactory.CountLeadingZeroesI32NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountLeadingZeroesNodeFactory.CountLeadingZeroesI64NodeGen; @@ -1211,7 +1211,7 @@ public LLVMExpressionNode createInlineAssemblerExpression(String asmExpression, } catch (AsmParseException e) { assemblyRoot = getLazyUnsupportedInlineRootNode(asmExpression, e); } - LLVMIRFunction function = new LLVMIRFunction(LLVMLanguage.createCallTarget(assemblyRoot), null); + LLVMIRFunction function = new LLVMIRFunction(assemblyRoot.getCallTarget(), null); LLVMFunction functionDetail = LLVMFunction.create("", function, new FunctionType(MetaType.UNKNOWN, 0, false), IDGenerater.INVALID_ID, LLVMSymbol.INVALID_INDEX, false, assemblyRoot.getName(), false); // The function descriptor for the inline assembly does not require a language. diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LazyToTruffleConverterImpl.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LazyToTruffleConverterImpl.java index 49c653564259..6e8467f9a43a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LazyToTruffleConverterImpl.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LazyToTruffleConverterImpl.java @@ -29,6 +29,20 @@ */ package com.oracle.truffle.llvm.parser; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import org.graalvm.options.OptionValues; + import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.frame.FrameDescriptor; @@ -84,19 +98,6 @@ import com.oracle.truffle.llvm.runtime.types.StructureType; import com.oracle.truffle.llvm.runtime.types.Type; import com.oracle.truffle.llvm.runtime.types.symbols.SSAValue; -import org.graalvm.options.OptionValues; - -import java.io.PrintWriter; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; public class LazyToTruffleConverterImpl implements LazyToTruffleConverter { @@ -245,7 +246,7 @@ private RootCallTarget generateCallTarget() { System.out.println(); } - return LLVMLanguage.createCallTarget(rootNode); + return rootNode.getCallTarget(); } private HashSet getDebugValues() { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMFunctionCode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMFunctionCode.java index bcf206e2a211..f867b16e930c 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMFunctionCode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMFunctionCode.java @@ -120,7 +120,7 @@ private CallTarget createNativeWrapperFactory(NativeContextExtension nativeExt) if (ret == null) { // either no native access, or signature is unsupported // fall back to tagged id - ret = Truffle.getRuntime().createCallTarget(new TagSulongFunctionPointerNode(this)); + ret = new TagSulongFunctionPointerNode(this).getCallTarget(); } return ret; } @@ -451,7 +451,7 @@ private void initForeignCallTarget() { foreignCall = LLVMForeignFunctionCallNode.create(language, this, interopType, sourceType); } - foreignFunctionCallTarget = LLVMLanguage.createCallTarget(foreignCall); + foreignFunctionCallTarget = foreignCall.getCallTarget(); } } @@ -478,7 +478,7 @@ private void initForeignConstructorCallTarget() { LLVMInteropType.Structured structured = ((LLVMInteropType.Value) extractedType).baseType; LLVMForeignCallNode foreignCall = LLVMForeignConstructorCallNode.create( language, this, interopType, sourceType, structured); - foreignConstructorCallTarget = LLVMLanguage.createCallTarget(foreignCall); + foreignConstructorCallTarget = foreignCall.getCallTarget(); } } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java index 3da578924125..f5932df8e4b6 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java @@ -474,7 +474,7 @@ public LLVMFunctionCode getStartFunctionCode() { protected void initFreeGlobalBlocks(NodeFactory nodeFactory) { // lazily initialized, this is not necessary if there are no global blocks allocated if (freeGlobalBlocks == null) { - freeGlobalBlocks = LLVMLanguage.createCallTarget(new FreeGlobalsNode(this, nodeFactory)); + freeGlobalBlocks = new FreeGlobalsNode(this, nodeFactory).getCallTarget(); } } @@ -612,11 +612,7 @@ protected void initializeMultipleContexts() { singleContextAssumption.invalidate(); } - public static RootCallTarget createCallTarget(RootNode rootNode) { - return Truffle.getRuntime().createCallTarget(rootNode); - } - public RootCallTarget createCachedCallTarget(Class key, Function create) { - return cachedCallTargets.computeIfAbsent(key, k -> createCallTarget(create.apply(LLVMLanguage.this))); + return cachedCallTargets.computeIfAbsent(key, k -> create.apply(LLVMLanguage.this).getCallTarget()); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/SulongLibrary.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/SulongLibrary.java index 178cdcc49fb1..6a3caee411c3 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/SulongLibrary.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/SulongLibrary.java @@ -29,6 +29,10 @@ */ package com.oracle.truffle.llvm.runtime; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Objects; + import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -59,10 +63,6 @@ import com.oracle.truffle.llvm.runtime.nodes.func.LLVMGlobalRootNode; import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Objects; - /** * Object that is returned when a bitcode library is parsed. */ @@ -107,7 +107,7 @@ private CallTarget createCallTarget() { RootCallTarget startCallTarget = language.getStartFunctionCode().getLLVMIRFunctionSlowPath(); Path applicationPath = Paths.get(mainFunction.getStringPath()); RootNode rootNode = new LLVMGlobalRootNode(language, new FrameDescriptor(), mainFunction, startCallTarget, Objects.toString(applicationPath, "")); - return LLVMLanguage.createCallTarget(rootNode); + return rootNode.getCallTarget(); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/LLDBSupport.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/LLDBSupport.java index 8ef3eaa90a5f..8a87f41f76eb 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/LLDBSupport.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/LLDBSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. * * All rights reserved. * @@ -74,7 +74,7 @@ public Object execute(VirtualFrame frame) { public CallTarget getLoadFunction(Type loadType) { CallTarget ret = loadFunctionCache.get(loadType); if (ret == null) { - ret = LLVMLanguage.createCallTarget(new LoadRootNode(this, loadType)); + ret = new LoadRootNode(this, loadType).getCallTarget(); loadFunctionCache.put(loadType, ret); } return ret; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMTruffleDecorateFunction.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMTruffleDecorateFunction.java index 1b6fdb8f2011..c265369b0602 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMTruffleDecorateFunction.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMTruffleDecorateFunction.java @@ -48,7 +48,6 @@ import com.oracle.truffle.llvm.runtime.LLVMFunctionCode; import com.oracle.truffle.llvm.runtime.LLVMFunctionCode.LLVMIRFunction; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; -import com.oracle.truffle.llvm.runtime.LLVMLanguage; import com.oracle.truffle.llvm.runtime.LLVMSymbol; import com.oracle.truffle.llvm.runtime.except.LLVMPolyglotException; import com.oracle.truffle.llvm.runtime.library.internal.LLVMAsForeignLibrary; @@ -195,7 +194,7 @@ private Object decorateForeign(Object function, LLVMFunctionDescriptor wrapperFu } private static Object registerRoot(String path, FunctionType newFunctionType, DecoratedRoot decoratedRoot) { - LLVMIRFunction function = new LLVMIRFunction(LLVMLanguage.createCallTarget(decoratedRoot), null); + LLVMIRFunction function = new LLVMIRFunction(decoratedRoot.getCallTarget(), null); LLVMFunction functionDetail = LLVMFunction.create("", function, newFunctionType, IDGenerater.INVALID_ID, LLVMSymbol.INVALID_INDEX, false, path, false); LLVMFunctionDescriptor wrappedFunction = new LLVMFunctionDescriptor(functionDetail, new LLVMFunctionCode(functionDetail)); return LLVMManagedPointer.create(wrappedFunction); diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/ParserDriver.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/ParserDriver.java index 3d30685c95a6..ae6b4fc62845 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/ParserDriver.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/ParserDriver.java @@ -151,7 +151,7 @@ private CallTarget parseWithDependencies(Source source, ByteSequence bytes) { TruffleFile file = createNativeTruffleFile(source.getName(), source.getPath()); // An empty call target is returned for native libraries. if (file == null) { - return LLVMLanguage.createCallTarget(RootNode.createConstantNode(0)); + return RootNode.createConstantNode(0).getCallTarget(); } return createNativeLibraryCallTarget(file); } @@ -543,12 +543,12 @@ private static void addExternalSymbolsToScopes(LLVMParserResult parserResult) { */ private CallTarget createLibraryCallTarget(String name, LLVMParserResult parserResult, Source source) { if (context.getEnv().getOptions().get(SulongEngineOption.PARSE_ONLY)) { - return LLVMLanguage.createCallTarget(RootNode.createConstantNode(0)); + return RootNode.createConstantNode(0).getCallTarget(); } else { // check if the functions should be resolved eagerly or lazily. boolean lazyParsing = context.getEnv().getOptions().get(SulongEngineOption.LAZY_PARSING) && !context.getEnv().getOptions().get(SulongEngineOption.AOTCacheStore); LoadModulesNode loadModules = LoadModulesNode.create(name, parserResult, lazyParsing, context.isInternalLibraryFile(parserResult.getRuntime().getFile()), dependencies, source, language); - return LLVMLanguage.createCallTarget(loadModules); + return loadModules.getCallTarget(); } } @@ -559,11 +559,11 @@ private CallTarget createLibraryCallTarget(String name, LLVMParserResult parserR */ private CallTarget createNativeLibraryCallTarget(TruffleFile file) { if (context.getEnv().getOptions().get(SulongEngineOption.PARSE_ONLY)) { - return LLVMLanguage.createCallTarget(RootNode.createConstantNode(0)); + return RootNode.createConstantNode(0).getCallTarget(); } else { - // check if the functions should be resolved eagerly or lazyly. + // check if the functions should be resolved eagerly or lazily. LoadNativeNode loadNative = LoadNativeNode.create(new FrameDescriptor(), language, file); - return LLVMLanguage.createCallTarget(loadNative); + return loadNative.getCallTarget(); } } } diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/initialization/InitializeModuleNode.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/initialization/InitializeModuleNode.java index a07b04598b4a..293e017b1410 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/initialization/InitializeModuleNode.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/initialization/InitializeModuleNode.java @@ -112,7 +112,7 @@ public static RootCallTarget createDestructor(LLVMParserResult parserResult, Str FrameDescriptor frameDescriptor = new FrameDescriptor(); LLVMStatementRootNode root = new LLVMStatementRootNode(language, StaticInitsNodeGen.create(destructors, "fini", moduleName), frameDescriptor, parserResult.getRuntime().getNodeFactory().createStackAccess(frameDescriptor)); - return LLVMLanguage.createCallTarget(root); + return root.getCallTarget(); } else { return null; } diff --git a/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/nfi/NFIAPITest.java b/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/nfi/NFIAPITest.java index 03840f0bd173..3b43f7298c7b 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/nfi/NFIAPITest.java +++ b/sulong/tests/com.oracle.truffle.llvm.tests/src/com/oracle/truffle/llvm/tests/interop/nfi/NFIAPITest.java @@ -40,7 +40,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -68,7 +67,7 @@ public static void initialize() { } private static CallTarget lookupAndBind() { - return Truffle.getRuntime().createCallTarget(new LookupAndBindNode()); + return new LookupAndBindNode().getCallTarget(); } private static Object loadLibrary(String lib, String filename) { From 7936aac26958d0d3ce43fee456a6ce867d2eb622 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 27 Sep 2021 13:56:16 +0200 Subject: [PATCH 188/681] Avoid createCallTarget() in tools. --- .../LazyAccessInspectDebugLegacyTest.java | 5 ++- .../test/LazyAccessInspectDebugTest.java | 5 ++- .../test/NotReadableValuesLegacyTest.java | 5 ++- .../test/NotReadableValuesTest.java | 5 ++- .../tools/coverage/test/CoverageTest.java | 7 ++-- .../tools/profiler/test/MemoryTracerTest.java | 5 ++- .../profiler/test/NoTagSamplingTest.java | 3 +- .../insight/test/InsightContextTest.java | 35 ++++++++++--------- .../insight/test/InsightObjectFactory.java | 5 ++- 9 files changed, 35 insertions(+), 40 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/LazyAccessInspectDebugLegacyTest.java b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/LazyAccessInspectDebugLegacyTest.java index 0390307f171d..89fbff5410a7 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/LazyAccessInspectDebugLegacyTest.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/LazyAccessInspectDebugLegacyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -34,7 +34,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -185,7 +184,7 @@ static class ReadWithSideEffectsLanguage extends ProxyLanguage { @Override protected final CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, request.getSource())); + return new TestRootNode(languageInstance, request.getSource()).getCallTarget(); } @Override diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/LazyAccessInspectDebugTest.java b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/LazyAccessInspectDebugTest.java index 95a8506c3cf7..4a0bfe770014 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/LazyAccessInspectDebugTest.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/LazyAccessInspectDebugTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -33,7 +33,6 @@ import org.graalvm.polyglot.Source; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; @@ -184,7 +183,7 @@ static class ReadWithSideEffectsLanguage extends ProxyLanguage { @Override protected final CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, request.getSource())); + return new TestRootNode(languageInstance, request.getSource()).getCallTarget(); } @Override diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/NotReadableValuesLegacyTest.java b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/NotReadableValuesLegacyTest.java index bc1236cb5ccd..2e1e97cedc41 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/NotReadableValuesLegacyTest.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/NotReadableValuesLegacyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -35,7 +35,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.GenerateWrapper; @@ -130,7 +129,7 @@ static class NotReadableValuesLanguage extends ProxyLanguage { @Override protected final CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, request.getSource())); + return new TestRootNode(languageInstance, request.getSource()).getCallTarget(); } @Override diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/NotReadableValuesTest.java b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/NotReadableValuesTest.java index a0cbf8097825..2a55f9661f34 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/NotReadableValuesTest.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/NotReadableValuesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -34,7 +34,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.GenerateWrapper; @@ -128,7 +127,7 @@ static class NotReadableValuesLanguage extends ProxyLanguage { @Override protected final CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new TestRootNode(languageInstance, request.getSource())); + return new TestRootNode(languageInstance, request.getSource()).getCallTarget(); } @Override diff --git a/tools/src/com.oracle.truffle.tools.coverage.test/src/com/oracle/truffle/tools/coverage/test/CoverageTest.java b/tools/src/com.oracle.truffle.tools.coverage.test/src/com/oracle/truffle/tools/coverage/test/CoverageTest.java index aae847e00480..c9ca8da41167 100644 --- a/tools/src/com.oracle.truffle.tools.coverage.test/src/com/oracle/truffle/tools/coverage/test/CoverageTest.java +++ b/tools/src/com.oracle.truffle.tools.coverage.test/src/com/oracle/truffle/tools/coverage/test/CoverageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -40,7 +40,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.GenerateWrapper; @@ -245,14 +244,14 @@ public static class RootAndStatementInDifferentSources extends ProxyLanguage { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Child SuperclassNode child = new TestRootNode(new TestStatementNode()); @Override public Object execute(VirtualFrame frame) { return child.execute(frame); } - }); + }.getCallTarget(); } @GenerateWrapper diff --git a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/MemoryTracerTest.java b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/MemoryTracerTest.java index 83e40dc31196..09bae3becbec 100644 --- a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/MemoryTracerTest.java +++ b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/MemoryTracerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -33,7 +33,6 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.AllocationReporter; @@ -315,7 +314,7 @@ public Object execute(VirtualFrame frame) { protected CallTarget parse(ParsingRequest request) { final ADRARootNode rootNode = new ADRARootNode(this); rootNode.setSection(request.getSource().createSection(1)); - return Truffle.getRuntime().createCallTarget(rootNode); + return rootNode.getCallTarget(); } @Override diff --git a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java index 1168305ab185..755a20734e9f 100644 --- a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java +++ b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java @@ -34,7 +34,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleSafepoint; import com.oracle.truffle.api.frame.VirtualFrame; @@ -97,7 +96,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { } private RootCallTarget newTarget() { - return Truffle.getRuntime().createCallTarget(new LILRootNode(this)); + return new LILRootNode(this).getCallTarget(); } } } diff --git a/tools/src/org.graalvm.tools.insight.test/src/org/graalvm/tools/insight/test/InsightContextTest.java b/tools/src/org.graalvm.tools.insight.test/src/org/graalvm/tools/insight/test/InsightContextTest.java index f700bcb95a14..f2bdf329d9a4 100644 --- a/tools/src/org.graalvm.tools.insight.test/src/org/graalvm/tools/insight/test/InsightContextTest.java +++ b/tools/src/org.graalvm.tools.insight.test/src/org/graalvm/tools/insight/test/InsightContextTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -24,34 +24,37 @@ */ package org.graalvm.tools.insight.test; -import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.TruffleContext; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.instrumentation.test.InstrumentationTestLanguage; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.nodes.NodeUtil; -import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.api.test.GCUtils; -import com.oracle.truffle.api.test.polyglot.ProxyLanguage; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.Function; + import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; import org.graalvm.tools.insight.Insight; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; import org.junit.Before; import org.junit.Test; +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.TruffleContext; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.instrumentation.test.InstrumentationTestLanguage; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.NodeUtil; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.test.GCUtils; +import com.oracle.truffle.api.test.polyglot.ProxyLanguage; + public class InsightContextTest { public static final class InsightTestLanguage extends ProxyLanguage { int parsingCounter; @@ -77,7 +80,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { int idx = request.getArgumentNames().indexOf("insight"); assertNotEquals("insight is an argument", -1, idx); - return Truffle.getRuntime().createCallTarget(new ParsingNode(idx)); + return new ParsingNode(idx).getCallTarget(); } class ParsingNode extends RootNode { diff --git a/tools/src/org.graalvm.tools.insight.test/src/org/graalvm/tools/insight/test/InsightObjectFactory.java b/tools/src/org.graalvm.tools.insight.test/src/org/graalvm/tools/insight/test/InsightObjectFactory.java index 6539a3af0412..4f7f523d4e45 100644 --- a/tools/src/org.graalvm.tools.insight.test/src/org/graalvm/tools/insight/test/InsightObjectFactory.java +++ b/tools/src/org.graalvm.tools.insight.test/src/org/graalvm/tools/insight/test/InsightObjectFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -25,7 +25,6 @@ package org.graalvm.tools.insight.test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.GenerateWrapper; @@ -86,7 +85,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { final Source source = request.getSource(); String scriptName = source.getName(); final AgentRootNode root = new AgentRootNode(ProxyLanguage.get(null), this, scriptName, source, request.getArgumentNames()); - return Truffle.getRuntime().createCallTarget(root); + return root.getCallTarget(); } public static Value readInsight(Context context, Object[] interopValue) throws Exception { From 9dcf122e643368e727131dba60f322edd5a7977e Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 27 Sep 2021 13:56:25 +0200 Subject: [PATCH 189/681] Avoid createCallTarget() in vm. --- .../src/org/graalvm/polybench/micro/Parser.java | 3 +-- .../src/org/graalvm/polybench/micro/nodes/SetupRootNode.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/vm/src/org.graalvm.polybench.micro/src/org/graalvm/polybench/micro/Parser.java b/vm/src/org.graalvm.polybench.micro/src/org/graalvm/polybench/micro/Parser.java index 7f5bff1907da..993183a6811b 100644 --- a/vm/src/org.graalvm.polybench.micro/src/org/graalvm/polybench/micro/Parser.java +++ b/vm/src/org.graalvm.polybench.micro/src/org/graalvm/polybench/micro/Parser.java @@ -25,7 +25,6 @@ package org.graalvm.polybench.micro; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.source.Source; import org.graalvm.polybench.micro.expr.EvalExpression; import org.graalvm.polybench.micro.expr.EvalExpressionNodeGen; @@ -85,7 +84,7 @@ CallTarget parseEverything(MicrobenchLanguage language) throws IOException { Microbench spec = parseMicrobenchStatement(); SetupRootNode setupNode = SetupRootNodeGen.create(language, spec, preparedState); - return Truffle.getRuntime().createCallTarget(setupNode); + return setupNode.getCallTarget(); } void parseDeclarations() throws IOException { diff --git a/vm/src/org.graalvm.polybench.micro/src/org/graalvm/polybench/micro/nodes/SetupRootNode.java b/vm/src/org.graalvm.polybench.micro/src/org/graalvm/polybench/micro/nodes/SetupRootNode.java index 58cacbeab094..17ebb3877079 100644 --- a/vm/src/org.graalvm.polybench.micro/src/org/graalvm/polybench/micro/nodes/SetupRootNode.java +++ b/vm/src/org.graalvm.polybench.micro/src/org/graalvm/polybench/micro/nodes/SetupRootNode.java @@ -26,7 +26,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; @@ -52,7 +51,7 @@ public SetupRootNode(MicrobenchLanguage language, Microbench spec, Expression[] super(language); MicrobenchRootNode workloadRoot = new MicrobenchRootNode(language, spec); - this.workload = Truffle.getRuntime().createCallTarget(workloadRoot); + this.workload = workloadRoot.getCallTarget(); this.prepare = prepare; this.spec = spec; } From 65b34cc7e53b2470eb05ae022ff9da9371ec8e82 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Mon, 27 Sep 2021 16:20:48 +0300 Subject: [PATCH 190/681] Forward more mx args for GraalVMConfig None-config --- substratevm/mx.substratevm/mx_substratevm.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 2e5dc90cb77f..4e92dffe8675 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -45,6 +45,7 @@ import mx_gate import mx_unittest import mx_sdk_vm +import mx_sdk_vm_impl import mx_javamodules import mx_subst import mx_substratevm_benchmark # pylint: disable=unused-import @@ -176,6 +177,14 @@ def _run_graalvm_cmd(cmd_args, config, nonZeroIsFatal=True, out=None, err=None, primary_suite_dir = config.primary_suite_dir else: config_args = [] + if not mx_sdk_vm_impl._jlink_libraries(): + config_args += ['--no-jlinking'] + native_images = mx_sdk_vm_impl._parse_cmd_arg('native_images') + if native_images: + config_args += ['--native-images=' + ','.join(native_images)] + components = mx_sdk_vm_impl._components_include_list() + if components: + config_args += ['--components=' + ','.join(c.name for c in components)] dynamic_imports = [x for x, _ in mx.get_dynamic_imports()] if dynamic_imports: config_args += ['--dynamicimports', ','.join(dynamic_imports)] From 72e63be1d9aaa0ee7205fd4cac56a6586627a276 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Tue, 28 Sep 2021 12:35:20 +0300 Subject: [PATCH 191/681] Remove duplicate _jlink_libraries from mx_compiler.py --- compiler/mx.compiler/mx_compiler.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 48d016eb2f30..f3fb32bb8dd1 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -1149,9 +1149,6 @@ def _zipadd(arc, filename, arcname): arc.close() -def _jlink_libraries(): - return not (mx.get_opts().no_jlinking or mx.env_var_to_bool('NO_JLINKING')) - def makegraaljdk_cli(args): """make a JDK with Graal as the default top level JIT""" parser = ArgumentParser(prog='mx makegraaljdk') @@ -1321,7 +1318,7 @@ def _copy_file(src, dst): vendor_info = {'vendor-version' : vm_name} # Setting dedup_legal_notices=False avoids due to license files conflicting # when switching JAVA_HOME from an OpenJDK to an OracleJDK or vice versa between executions. - if _jlink_libraries(): + if mx_sdk_vm_impl._jlink_libraries(): jlink_new_jdk(jdk, tmp_dst_jdk_dir, module_dists, ignore_dists=[], root_module_names=root_module_names, vendor_info=vendor_info, dedup_legal_notices=False) if export_truffle: jmd = as_java_module(_graal_config().dists_dict['truffle:TRUFFLE_API'], jdk) From 6c77c83334eaf11566f0e8ec625562a10d9896dc Mon Sep 17 00:00:00 2001 From: "thomas.garcia" Date: Tue, 28 Sep 2021 13:42:46 +0200 Subject: [PATCH 192/681] Remove empty 8 and 11 projects --- espresso/mx.espresso/suite.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/espresso/mx.espresso/suite.py b/espresso/mx.espresso/suite.py index 211446bf9dbd..11d11e1368ed 100644 --- a/espresso/mx.espresso/suite.py +++ b/espresso/mx.espresso/suite.py @@ -121,25 +121,6 @@ "checkPackagePrefix": False, # java.lang.ref.PublicFinalReference }, - "com.oracle.truffle.espresso.jdk8": { - "subDir": "src", - "sourceDirs": ["src"], - "overlayTarget": "com.oracle.truffle.espresso", - "checkPackagePrefix": "false", - "checkstyle": "com.oracle.truffle.espresso", - "javaCompliance": "8", - }, - - "com.oracle.truffle.espresso.jdk11": { - "subDir": "src", - "sourceDirs": ["src"], - "overlayTarget": "com.oracle.truffle.espresso", - "checkPackagePrefix": "false", - "multiReleaseJarVersion": "11", - "checkstyle": "com.oracle.truffle.espresso", - "javaCompliance": "11+", - }, - "com.oracle.truffle.espresso.jdk17": { "subDir": "src", "sourceDirs": ["src"], From 7f43d1a2433a555c7109e0efaf761b21903e4f27 Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Tue, 28 Sep 2021 14:26:50 +0200 Subject: [PATCH 193/681] Fixing AIOOB from GlobalRegistry.ensureExternalGlobalCapacity(). --- .../org.graalvm.wasm/src/org/graalvm/wasm/GlobalRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/GlobalRegistry.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/GlobalRegistry.java index 7e18e43c1238..a657cadb60c4 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/GlobalRegistry.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/GlobalRegistry.java @@ -88,7 +88,7 @@ private void ensureGlobalCapacity() { private void ensureExternalGlobalCapacity() { if (externalGlobalCount == externalGlobals.length) { final WasmGlobal[] nExternalGlobals = new WasmGlobal[externalGlobals.length * 2]; - System.arraycopy(externalGlobals, 0, nExternalGlobals, 0, nExternalGlobals.length); + System.arraycopy(externalGlobals, 0, nExternalGlobals, 0, externalGlobals.length); externalGlobals = nExternalGlobals; } } From ca1492fbed8d54738738910d20ef5aeecf340e20 Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Tue, 28 Sep 2021 14:27:47 +0200 Subject: [PATCH 194/681] Adding a regression test with an import of many globals. --- .../org/graalvm/wasm/test/WasmJsApiSuite.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java index 8402ff021c44..1e639acbae3d 100644 --- a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java +++ b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java @@ -1295,6 +1295,67 @@ private static void runValidationValid(byte[] data) throws IOException { }); } + @Test + public void testImportManyGlobals() throws IOException, InterruptedException { + String importManyGlobalsWat = "(module\n" + + "(global $global0 (import \"globals\" \"global0\") i32)\n" + + "(global $global1 (import \"globals\" \"global1\") i32)\n" + + "(global $global2 (import \"globals\" \"global2\") i32)\n" + + "(global $global3 (import \"globals\" \"global3\") i32)\n" + + "(global $global4 (import \"globals\" \"global4\") i32)\n" + + "(global $global5 (import \"globals\" \"global5\") i32)\n" + + "(global $global6 (import \"globals\" \"global6\") i32)\n" + + "(global $global7 (import \"globals\" \"global7\") i32)\n" + + "(global $global8 (import \"globals\" \"global8\") i32)\n" + + "(func (export \"sum\") (result i32)\n" + + " get_global $global0\n" + + " get_global $global1\n" + + " i32.add\n" + + " get_global $global2\n" + + " i32.add\n" + + " get_global $global3\n" + + " i32.add\n" + + " get_global $global4\n" + + " i32.add\n" + + " get_global $global5\n" + + " i32.add\n" + + " get_global $global6\n" + + " i32.add\n" + + " get_global $global7\n" + + " i32.add\n" + + " get_global $global8\n" + + " i32.add\n" + + ")\n" + + ")"; + byte[] importManyGlobalsBytes = compileWat("importManyGlobals", importManyGlobalsWat); + runTest(context -> { + WebAssembly wasm = new WebAssembly(context); + Dictionary importObject = Dictionary.create(new Object[]{ + "globals", Dictionary.create(new Object[]{ + "global0", WebAssembly.globalAlloc(ValueType.i32, false, 1), + "global1", WebAssembly.globalAlloc(ValueType.i32, false, 2), + "global2", WebAssembly.globalAlloc(ValueType.i32, false, 3), + "global3", WebAssembly.globalAlloc(ValueType.i32, false, 4), + "global4", WebAssembly.globalAlloc(ValueType.i32, false, 5), + "global5", WebAssembly.globalAlloc(ValueType.i32, false, 6), + "global6", WebAssembly.globalAlloc(ValueType.i32, false, 7), + "global7", WebAssembly.globalAlloc(ValueType.i32, false, 8), + "global8", WebAssembly.globalAlloc(ValueType.i32, false, 9), + }), + }); + WasmInstance instance = moduleInstantiate(wasm, importManyGlobalsBytes, importObject); + try { + InteropLibrary lib = InteropLibrary.getUncached(); + Object sum = lib.execute(WebAssembly.instanceExport(instance, "sum")); + int intSum = lib.asInt(sum); + Assert.assertEquals("Incorrect sum of imported globals", 45, intSum); + } catch (InteropException e) { + throw new RuntimeException(e); + } + }); + + } + private static void runTest(Consumer testCase) throws IOException { final Context.Builder contextBuilder = Context.newBuilder(WasmLanguage.ID); contextBuilder.option("wasm.Builtins", "testutil:testutil"); From badb93d6c498eba04c178ff9661fe190d0710fb5 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Tue, 28 Sep 2021 16:17:06 +0200 Subject: [PATCH 195/681] Do not close env output. --- .../coverage/impl/CoverageInstrument.java | 29 +++++++------- .../tools/profiler/impl/CPUSamplerCLI.java | 35 +++++++++-------- .../tools/profiler/impl/CPUTracerCLI.java | 38 +++++++++---------- 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.coverage/src/com/oracle/truffle/tools/coverage/impl/CoverageInstrument.java b/tools/src/com.oracle.truffle.tools.coverage/src/com/oracle/truffle/tools/coverage/impl/CoverageInstrument.java index 7004aff88633..498e837e6323 100644 --- a/tools/src/com.oracle.truffle.tools.coverage/src/com/oracle/truffle/tools/coverage/impl/CoverageInstrument.java +++ b/tools/src/com.oracle.truffle.tools.coverage/src/com/oracle/truffle/tools/coverage/impl/CoverageInstrument.java @@ -174,21 +174,20 @@ protected void onDispose(Env env) { SourceCoverage[] coverage = tracker.getCoverage(); final OptionValues options = env.getOptions(); final boolean strictLines = StrictLines.getValue(options); - try (PrintStream out = chooseOutputStream(env, OUTPUT_FILE)) { - switch (OUTPUT.getValue(options)) { - case HISTOGRAM: - new CoverageCLI(out, coverage, strictLines).printHistogramOutput(); - break; - case DETAILED: - new CoverageCLI(out, coverage, strictLines).printLinesOutput(); - break; - case JSON: - new JSONPrinter(out, coverage).print(); - break; - case LCOV: - new LCOVPrinter(out, coverage, strictLines).print(); - break; - } + PrintStream out = chooseOutputStream(env, OUTPUT_FILE); + switch (OUTPUT.getValue(options)) { + case HISTOGRAM: + new CoverageCLI(out, coverage, strictLines).printHistogramOutput(); + break; + case DETAILED: + new CoverageCLI(out, coverage, strictLines).printLinesOutput(); + break; + case JSON: + new JSONPrinter(out, coverage).print(); + break; + case LCOV: + new LCOVPrinter(out, coverage, strictLines).print(); + break; } tracker.close(); } diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java index 372083b60e12..6b023b5a30e7 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java @@ -166,24 +166,23 @@ public CPUSampler.Mode apply(String s) { static final OptionKey SAMPLE_CONTEXT_INITIALIZATION = new OptionKey<>(false); static void handleOutput(TruffleInstrument.Env env, CPUSampler sampler) { - try (PrintStream out = chooseOutputStream(env, OUTPUT_FILE)) { - Map data = sampler.getData(); - OptionValues options = env.getOptions(); - switch (options.get(OUTPUT)) { - case HISTOGRAM: - printWarnings(sampler, out); - printSamplingHistogram(out, options, data); - break; - case CALLTREE: - printWarnings(sampler, out); - printSamplingCallTree(out, options, data); - break; - case JSON: - printSamplingJson(out, options, data); - break; - case FLAMEGRAPH: - SVGSamplerOutput.printSamplingFlameGraph(out, data); - } + PrintStream out = chooseOutputStream(env, OUTPUT_FILE); + Map data = sampler.getData(); + OptionValues options = env.getOptions(); + switch (options.get(OUTPUT)) { + case HISTOGRAM: + printWarnings(sampler, out); + printSamplingHistogram(out, options, data); + break; + case CALLTREE: + printWarnings(sampler, out); + printSamplingCallTree(out, options, data); + break; + case JSON: + printSamplingJson(out, options, data); + break; + case FLAMEGRAPH: + SVGSamplerOutput.printSamplingFlameGraph(out, data); } } diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUTracerCLI.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUTracerCLI.java index a99c46da250c..447004c9472c 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUTracerCLI.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUTracerCLI.java @@ -24,16 +24,6 @@ */ package com.oracle.truffle.tools.profiler.impl; -import com.oracle.truffle.api.Option; -import com.oracle.truffle.api.instrumentation.TruffleInstrument; -import com.oracle.truffle.tools.profiler.CPUTracer; -import com.oracle.truffle.tools.utils.json.JSONArray; -import com.oracle.truffle.tools.utils.json.JSONObject; -import org.graalvm.options.OptionCategory; -import org.graalvm.options.OptionKey; -import org.graalvm.options.OptionStability; -import org.graalvm.options.OptionType; - import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; @@ -41,6 +31,17 @@ import java.util.List; import java.util.function.Function; +import org.graalvm.options.OptionCategory; +import org.graalvm.options.OptionKey; +import org.graalvm.options.OptionStability; +import org.graalvm.options.OptionType; + +import com.oracle.truffle.api.Option; +import com.oracle.truffle.api.instrumentation.TruffleInstrument; +import com.oracle.truffle.tools.profiler.CPUTracer; +import com.oracle.truffle.tools.utils.json.JSONArray; +import com.oracle.truffle.tools.utils.json.JSONObject; + @Option.Group(CPUTracerInstrument.ID) class CPUTracerCLI extends ProfilerCLI { @@ -95,15 +96,14 @@ public Output apply(String s) { static final OptionKey OUTPUT_FILE = new OptionKey<>(""); public static void handleOutput(TruffleInstrument.Env env, CPUTracer tracer) { - try (PrintStream out = chooseOutputStream(env, OUTPUT_FILE)) { - switch (env.getOptions().get(OUTPUT)) { - case HISTOGRAM: - printTracerHistogram(out, tracer); - break; - case JSON: - printTracerJson(out, tracer); - break; - } + PrintStream out = chooseOutputStream(env, OUTPUT_FILE); + switch (env.getOptions().get(OUTPUT)) { + case HISTOGRAM: + printTracerHistogram(out, tracer); + break; + case JSON: + printTracerJson(out, tracer); + break; } } From a8557fcc83296d92ed4210c64371e18fbb91a12f Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 28 Sep 2021 15:28:40 +0100 Subject: [PATCH 196/681] Fix to String format for source location. --- .../oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index 4a26747fd3b6..3019af47072f 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -841,7 +841,7 @@ private String drawSample(double y, JSONObject sample) { double totalPercent = 100.0 * total / sampleCount; title.append(String.format("Self samples: %d (%.2f%%)\n", interpreted + compiled, percent)); title.append(String.format("total samples: %d (%.2f%%)\n", total, totalPercent)); - title.append(String.format("Source location: %s\n", owner.sourceHash.get(sample.getInt("f")), sample.getInt("fl"))); + title.append(String.format("Source location: %s:%d\n", owner.sourceNames.get(sample.getInt("f")), sample.getInt("fl"))); groupAttrs.put("title", escape(title.toString())); output.append(startGroup(groupAttrs)); From 75f68c4c3d907ca3da6bfffd6fe4983410302ae4 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Tue, 28 Sep 2021 15:34:10 +0200 Subject: [PATCH 197/681] Simplify test for GR-32346. --- .../api/test/polyglot/HostAccessTest.java | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostAccessTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostAccessTest.java index 3fe80e7e8946..79337beeb3c2 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostAccessTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostAccessTest.java @@ -77,8 +77,6 @@ import org.graalvm.polyglot.PolyglotException; import org.graalvm.polyglot.TypeLiteral; import org.graalvm.polyglot.Value; -import org.graalvm.polyglot.impl.AbstractPolyglotImpl; -import org.graalvm.polyglot.impl.AbstractPolyglotImpl.APIAccess; import org.graalvm.polyglot.proxy.ProxyArray; import org.graalvm.polyglot.proxy.ProxyExecutable; import org.graalvm.polyglot.proxy.ProxyObject; @@ -417,45 +415,23 @@ public void testBufferAccessDisabled() { */ @Test public void testBuilderCannotChangeMembersAndTargetMappingsOfHostAccess() throws Exception { - APIAccess apiAccess = findAPIAccess(); - // Set up hostAccess Builder builder = HostAccess.newBuilder(); - Field okField = OK.class.getField("value"); - Field banField = Ban.class.getField("value"); - builder.allowAccess(okField); - builder.targetTypeMapping(Integer.class, Integer.class, null, (v) -> 42); + builder.allowAccess(OK.class.getField("value")); + builder.targetTypeMapping(Value.class, String.class, (v) -> v.isString(), (v) -> "foo"); HostAccess hostAccess = builder.build(); - List targetMappings = apiAccess.getTargetMappings(hostAccess); - - // Verify hostAccess - assertTrue(apiAccess.allowsAccess(hostAccess, okField)); - assertFalse(apiAccess.allowsAccess(hostAccess, banField)); - assertEquals(1, targetMappings.size()); // Try to change members or targetMappings through child builder Builder childBuilder = HostAccess.newBuilder(hostAccess); - childBuilder.allowAccess(banField); - childBuilder.targetTypeMapping(Integer.class, Character.class, null, (v) -> (char) 42); - HostAccess childHostAccess = childBuilder.build(); - List childTargetMappings = apiAccess.getTargetMappings(childHostAccess); - - // Verify childHostAccess - assertTrue(apiAccess.allowsAccess(childHostAccess, okField)); - assertTrue(apiAccess.allowsAccess(childHostAccess, banField)); - assertEquals(2, childTargetMappings.size()); + childBuilder.allowAccess(Ban.class.getField("value")); + childBuilder.targetTypeMapping(Value.class, Integer.class, null, (v) -> 42); // Ensure hostAccess has not been altered by child builder - assertTrue(apiAccess.allowsAccess(hostAccess, okField)); - assertFalse(apiAccess.allowsAccess(hostAccess, banField)); - assertEquals(1, targetMappings.size()); - assertNotSame(targetMappings, childTargetMappings); - } - - APIAccess findAPIAccess() throws ReflectiveOperationException { - Method getImplMethod = Engine.class.getDeclaredMethod("getImpl"); - getImplMethod.setAccessible(true); - return ((AbstractPolyglotImpl) getImplMethod.invoke(null)).getAPIAccess(); + try (Context c = Context.newBuilder().allowHostAccess(hostAccess).build()) { + assertAccess(c); + assertEquals("foo", c.asValue("a string").as(String.class)); + assertEquals(123, (int) c.asValue(123).as(Integer.class)); + } } @Test From 8fc80490e1461714467a942a943d9402036250a5 Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Mon, 20 Sep 2021 15:25:44 +0200 Subject: [PATCH 198/681] Transform (-a)*(-b) into a*b. --- .../compiler/core/test/MulNegateTest.java | 49 +++++++++++++++++++ .../graalvm/compiler/nodes/calc/MulNode.java | 10 +++- 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java new file mode 100644 index 000000000000..2a6af5ba25c4 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 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 org.graalvm.compiler.core.test; + +import org.graalvm.compiler.nodes.calc.NegateNode; +import org.junit.Test; + +public class MulNegateTest extends GraalCompilerTest { + + public static int mulInt(int x, int y) { + return -x * -y; + } + + @Test + public void testInt() { + assertTrue(getFinalGraph("mulInt").getNodes().filter(NegateNode.class).count() == 0); + } + + public static float mulFlt(float x, float y) { + return -x * -y; + } + + @Test + public void testFloat() { + assertTrue(getFinalGraph("mulFlt").getNodes().filter(NegateNode.class).count() == 0); + } +} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java index 46e6137b0aac..0ac7500ea8e8 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java @@ -32,13 +32,13 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable.BinaryCommutative; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.Canonicalizable.BinaryCommutative; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import jdk.vm.ci.code.CodeUtil; @@ -90,6 +90,12 @@ public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode for // if this fails we only swap return new MulNode(forY, forX); } + + // convert "(-a)*(-b)" into "a*b" + if (forX instanceof NegateNode && forY instanceof NegateNode) { + return new MulNode(((NegateNode) forX).getValue(), ((NegateNode) forY).getValue()).maybeCommuteInputs(); + } + BinaryOp op = getOp(forX, forY); NodeView view = NodeView.from(tool); return canonical(this, op, stamp(view), forX, forY, view); From fd726d43a3f055a59278694a886c5e3e532f9414 Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Tue, 28 Sep 2021 18:48:12 +0200 Subject: [PATCH 199/681] Update MulNegateTest. --- .../compiler/core/test/MulNegateTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java index 2a6af5ba25c4..d6bcfeedbf02 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java @@ -29,6 +29,8 @@ public class MulNegateTest extends GraalCompilerTest { + public static final int[] INT_TEST_CASES = {0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE}; + public static int mulInt(int x, int y) { return -x * -y; } @@ -36,8 +38,17 @@ public static int mulInt(int x, int y) { @Test public void testInt() { assertTrue(getFinalGraph("mulInt").getNodes().filter(NegateNode.class).count() == 0); + + for (int i : INT_TEST_CASES) { + for (int j : INT_TEST_CASES) { + test("mulInt", i, j); + } + } } + public static final float[] FLOAT_TEST_CASES = {0.0f, -0.0f, 1.0f, -1.0f, Float.MIN_VALUE, Float.MIN_NORMAL, + Float.MAX_VALUE, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Float.NaN}; + public static float mulFlt(float x, float y) { return -x * -y; } @@ -45,5 +56,11 @@ public static float mulFlt(float x, float y) { @Test public void testFloat() { assertTrue(getFinalGraph("mulFlt").getNodes().filter(NegateNode.class).count() == 0); + + for (float i : FLOAT_TEST_CASES) { + for (float j : FLOAT_TEST_CASES) { + test("mulFlt", i, j); + } + } } } From c98d9ae8ebedb174c5a74af6f1786bc095a24b44 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 21 Sep 2021 22:49:57 -0700 Subject: [PATCH 200/681] Clean-up executor. Analysis initialization task can be run in the same thread, --- .../src/com/oracle/graal/pointsto/api/HostVM.java | 5 +---- .../com/oracle/graal/pointsto/meta/AnalysisType.java | 2 +- .../com/oracle/svm/hosted/HostedConfiguration.java | 12 ++++++------ .../com/oracle/svm/hosted/NativeImageGenerator.java | 6 +++--- .../src/com/oracle/svm/hosted/SVMHost.java | 12 ++---------- 5 files changed, 13 insertions(+), 24 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java index 018926e0f324..4b9e8f035a51 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java @@ -26,9 +26,7 @@ import java.lang.reflect.AnnotatedElement; import java.util.Optional; -import java.util.concurrent.ForkJoinPool; -import com.oracle.graal.pointsto.BigBang; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -38,6 +36,7 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; +import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; @@ -55,8 +54,6 @@ public interface HostVM { OptionValues options(); - ForkJoinPool executor(); - boolean isRelocatedPointer(Object originalObject); void clearInThread(); 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 b670d5248c6f..3d5b37141f7b 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 @@ -462,7 +462,7 @@ private void markReachable() { */ registerAsAllocated(null); } - universe.hostVM.executor().execute(initializationTask); + ensureInitialized(); } } 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 d4d8a5a844e9..406c6e8ca7d8 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,16 +31,15 @@ import java.util.Set; import java.util.concurrent.ForkJoinPool; -import com.oracle.graal.pointsto.BigBang; -import com.oracle.svm.core.util.VMError; -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; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.OptionValues; 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; @@ -54,6 +53,8 @@ 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; @@ -67,7 +68,6 @@ import com.oracle.svm.hosted.substitute.UnsafeAutomaticSubstitutionProcessor; import jdk.vm.ci.meta.JavaKind; -import org.graalvm.nativeimage.Platform; public class HostedConfiguration { @@ -132,9 +132,9 @@ public static ObjectLayout createObjectLayout(JavaKind referenceKind) { return new ObjectLayout(target, referenceSize, objectAlignment, hubOffset, firstFieldOffset, arrayLengthOffset, arrayBaseOffset, identityHashCodeOffset); } - public SVMHost createHostVM(OptionValues options, ForkJoinPool buildExecutor, ClassLoader classLoader, ClassInitializationSupport classInitializationSupport, + public SVMHost createHostVM(OptionValues options, ClassLoader classLoader, ClassInitializationSupport classInitializationSupport, UnsafeAutomaticSubstitutionProcessor automaticSubstitutions, Platform platform) { - return new SVMHost(options, buildExecutor, classLoader, classInitializationSupport, automaticSubstitutions, platform); + return new SVMHost(options, classLoader, classInitializationSupport, automaticSubstitutions, platform); } public CompileQueue createCompileQueue(DebugContext debug, FeatureHandler featureHandler, HostedUniverse hostedUniverse, 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 ff3fea8a9152..b50974e7d045 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 @@ -841,7 +841,7 @@ private void setupNativeImage(String imageName, OptionValues options, Map additionalSubstitutions, ForkJoinPool buildExecutor) { + ClassInitializationSupport classInitializationSupport, List additionalSubstitutions) { UnsafeAutomaticSubstitutionProcessor automaticSubstitutions = createAutomaticUnsafeSubstitutions(originalSnippetReflection, annotationSubstitutions); SubstitutionProcessor aSubstitutions = createAnalysisSubstitutionProcessor(originalMetaAccess, originalSnippetReflection, cEnumProcessor, automaticSubstitutions, annotationSubstitutions, additionalSubstitutions); - SVMHost hostVM = HostedConfiguration.instance().createHostVM(options, buildExecutor, loader.getClassLoader(), classInitializationSupport, automaticSubstitutions, loader.platform); + SVMHost hostVM = HostedConfiguration.instance().createHostVM(options, loader.getClassLoader(), classInitializationSupport, automaticSubstitutions, loader.platform); automaticSubstitutions.init(loader, originalMetaAccess); AnalysisPolicy analysisPolicy = PointstoOptions.AllocationSiteSensitiveHeap.getValue(options) ? new BytecodeSensitiveAnalysisPolicy(options) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index 083e3b7fdf51..c7416f4be096 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -43,10 +43,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ForkJoinPool; import java.util.function.BiConsumer; -import com.oracle.graal.pointsto.BigBang; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.MethodFilter; @@ -69,6 +67,7 @@ import org.graalvm.nativeimage.hosted.Feature.DuringAnalysisAccess; import org.graalvm.util.GuardedAnnotationAccess; +import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.api.PointstoOptions; @@ -125,7 +124,6 @@ public class SVMHost implements HostVM { private final Map> forbiddenTypes; private final Platform platform; private final OptionValues options; - private final ForkJoinPool executor; private final ClassLoader classLoader; private final ClassInitializationSupport classInitializationSupport; private final HostedStringDeduplication stringTable; @@ -149,10 +147,9 @@ public class SVMHost implements HostVM { private static final Method getNestHostMethod = JavaVersionUtil.JAVA_SPEC >= 11 ? ReflectionUtil.lookupMethod(Class.class, "getNestHost") : null; - public SVMHost(OptionValues options, ForkJoinPool executor, ClassLoader classLoader, ClassInitializationSupport classInitializationSupport, + public SVMHost(OptionValues options, ClassLoader classLoader, ClassInitializationSupport classInitializationSupport, UnsafeAutomaticSubstitutionProcessor automaticSubstitutions, Platform platform) { this.options = options; - this.executor = executor; this.classLoader = classLoader; this.classInitializationSupport = classInitializationSupport; this.stringTable = HostedStringDeduplication.singleton(); @@ -211,11 +208,6 @@ public OptionValues options() { return options; } - @Override - public ForkJoinPool executor() { - return executor; - } - @Override public Instance createGraphBuilderPhase(HostedProviders providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { return new AnalysisGraphBuilderPhase(providers, graphBuilderConfig, optimisticOpts, initialIntrinsicContext, providers.getWordTypes()); From 89ae8f909de4d6eb14a13fcd0ed7cb229eff3b0f Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Wed, 22 Sep 2021 21:27:56 -0700 Subject: [PATCH 201/681] Guarantee that only the main thread posts tasks before start. --- .../com/oracle/graal/pointsto/util/CompletionExecutor.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java index 01d9cda71f3a..1618213cb93a 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java @@ -70,6 +70,7 @@ private enum State { private BigBang bb; private Timing timing; private Object vmConfig; + private final Thread startingThread; public interface Timing { long getPrintIntervalNanos(); @@ -91,6 +92,7 @@ public CompletionExecutor(BigBang bb, ForkJoinPool forkJoin, Runnable heartbeatC postedOperations = new LongAdder(); completedOperations = new LongAdder(); postedBeforeStart = new ArrayList<>(); + startingThread = Thread.currentThread(); } public void init() { @@ -142,6 +144,11 @@ public void execute(DebugContextRunnable command) { case UNUSED: throw JVMCIError.shouldNotReachHere(); case BEFORE_START: + /* + * The postedBeforeStart list is not thread safe. Make sure that it is only updated + * from the same thread that created the executor. + */ + assert Thread.currentThread() == startingThread; postedBeforeStart.add(command); break; case STARTED: From 5b287ed060d7f643e91d72007839019d65eb5484 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 21 Sep 2021 23:17:23 -0700 Subject: [PATCH 202/681] Improve encapsulation. --- .../pointsto/util/CompletionExecutor.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java index 1618213cb93a..0f48c2eff19a 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java @@ -62,12 +62,12 @@ private enum State { private final LongAdder postedOperations; private final LongAdder completedOperations; private final List postedBeforeStart; - private volatile CopyOnWriteArrayList exceptions = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList exceptions = new CopyOnWriteArrayList<>(); - public ExecutorService executorService; + private ExecutorService executorService; private final Runnable heartbeatCallback; - private BigBang bb; + private final BigBang bb; private Timing timing; private Object vmConfig; private final Thread startingThread; @@ -174,14 +174,14 @@ public void execute(DebugContextRunnable command) { } } - public void executeService(DebugContextRunnable command) { + private void executeService(DebugContextRunnable command) { executorService.execute(() -> { executeCommand(command); }); } @SuppressWarnings("try") - public void executeCommand(DebugContextRunnable command) { + private void executeCommand(DebugContextRunnable command) { bb.getHostVM().installInThread(vmConfig); long startTime = 0L; if (timing != null) { @@ -289,10 +289,6 @@ public boolean isStarted() { return state.get() == State.STARTED; } - public ExecutorService getExecutorService() { - return executorService; - } - public int parallelism() { if (executorService instanceof ForkJoinPool) { return ((ForkJoinPool) executorService).getParallelism(); @@ -307,6 +303,10 @@ public int poolSize() { return 1; } + public ExecutorService getExecutorService() { + return executorService; + } + public void setExecutorService(ExecutorService executorService) { this.executorService = executorService; } From 1df971d9abd3a2d5a21907cd5398aaee2af7822c Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Wed, 22 Sep 2021 12:34:22 -0700 Subject: [PATCH 203/681] Refactor NativeImagePointsToAnalysis class. This is not a functional change, just moves code around to make it easier to integrate the new heap scanning. --- .../svm/graal/hosted/GraalObjectReplacer.java | 10 +- .../svm/hosted/NativeImageGenerator.java | 3 +- .../hosted/analysis/AnnotationsProcessor.java | 109 +++++ .../analysis/DynamicHubInitializer.java | 383 ++++++++++++++++ .../analysis/NativeImagePointsToAnalysis.java | 415 +----------------- 5 files changed, 506 insertions(+), 414 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/AnnotationsProcessor.java create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalObjectReplacer.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalObjectReplacer.java index bc178efa1188..76dcd99d9580 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalObjectReplacer.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalObjectReplacer.java @@ -64,7 +64,7 @@ import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.ameta.AnalysisConstantFieldProvider; import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; -import com.oracle.svm.hosted.analysis.NativeImagePointsToAnalysis; +import com.oracle.svm.hosted.analysis.AnnotationsProcessor; import com.oracle.svm.hosted.meta.HostedConstantFieldProvider; import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedMethod; @@ -217,7 +217,7 @@ public synchronized SubstrateMethod createMethod(ResolvedJavaMethod original) { * Annotations are updated in every analysis iteration, but this is a starting point. It * also ensures that all types used by annotations are created eagerly. */ - sMethod.setAnnotationsEncoding(NativeImagePointsToAnalysis.encodeAnnotations(aMetaAccess, aMethod.getAnnotations(), aMethod.getDeclaredAnnotations(), null)); + sMethod.setAnnotationsEncoding(AnnotationsProcessor.encodeAnnotations(aMetaAccess, aMethod.getAnnotations(), aMethod.getDeclaredAnnotations(), null)); } return sMethod; } @@ -251,7 +251,7 @@ public synchronized SubstrateField createField(ResolvedJavaField original) { * Annotations are updated in every analysis iteration, but this is a starting point. It * also ensures that all types used by annotations are created eagerly. */ - sField.setAnnotationsEncoding(NativeImagePointsToAnalysis.encodeAnnotations(aMetaAccess, aField.getAnnotations(), aField.getDeclaredAnnotations(), null)); + sField.setAnnotationsEncoding(AnnotationsProcessor.encodeAnnotations(aMetaAccess, aField.getAnnotations(), aField.getDeclaredAnnotations(), null)); } return sField; } @@ -378,13 +378,13 @@ public boolean updateDataDuringAnalysis(AnalysisMetaAccess metaAccess) { } for (Map.Entry entry : methods.entrySet()) { - if (entry.getValue().setAnnotationsEncoding(NativeImagePointsToAnalysis.encodeAnnotations(metaAccess, entry.getKey().getAnnotations(), entry.getKey().getDeclaredAnnotations(), + if (entry.getValue().setAnnotationsEncoding(AnnotationsProcessor.encodeAnnotations(metaAccess, entry.getKey().getAnnotations(), entry.getKey().getDeclaredAnnotations(), entry.getValue().getAnnotationsEncoding()))) { result = true; } } for (Map.Entry entry : fields.entrySet()) { - if (entry.getValue().setAnnotationsEncoding(NativeImagePointsToAnalysis.encodeAnnotations(metaAccess, entry.getKey().getAnnotations(), entry.getKey().getDeclaredAnnotations(), + if (entry.getValue().setAnnotationsEncoding(AnnotationsProcessor.encodeAnnotations(metaAccess, entry.getKey().getAnnotations(), entry.getKey().getDeclaredAnnotations(), entry.getValue().getAnnotationsEncoding()))) { result = true; } 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 b50974e7d045..a8e2aab61753 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 @@ -59,6 +59,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +import com.oracle.svm.hosted.analysis.SubstrateUnsupportedFeatures; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Pair; import org.graalvm.compiler.api.replacements.Fold; @@ -1032,7 +1033,7 @@ 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()); - return new NativeImagePointsToAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback); + return new NativeImagePointsToAnalysis(options, aUniverse, aProviders, annotationSubstitutionProcessor, analysisExecutor, heartbeatCallback, new SubstrateUnsupportedFeatures()); } @SuppressWarnings("try") diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/AnnotationsProcessor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/AnnotationsProcessor.java new file mode 100644 index 000000000000..4358e8ca8eeb --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/AnnotationsProcessor.java @@ -0,0 +1,109 @@ +/* + * 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.analysis; + +import java.lang.annotation.Annotation; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.util.AnalysisError; +import com.oracle.svm.core.hub.AnnotationsEncoding; + +public class AnnotationsProcessor { + + 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(); + } + + 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; + } + +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java new file mode 100644 index 000000000000..7919db92785d --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java @@ -0,0 +1,383 @@ +/* + * 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.analysis; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.MalformedParameterizedTypeException; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; +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.AnalysisType; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.svm.core.hub.AnnotatedSuperInfo; +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 jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaType; + +public class DynamicHubInitializer { + + private final SVMHost hostVM; + private final AnalysisUniverse universe; + private final AnalysisMetaAccess metaAccess; + private final UnsupportedFeatures unsupportedFeatures; + private final ConstantReflectionProvider constantReflection; + + private final Map genericInterfacesMap; + private final Map annotatedInterfacesMap; + private final Map interfacesEncodings; + + public DynamicHubInitializer(AnalysisUniverse universe, AnalysisMetaAccess metaAccess, + UnsupportedFeatures unsupportedFeatures, ConstantReflectionProvider constantReflection) { + this.hostVM = (SVMHost) universe.hostVM(); + this.universe = universe; + this.metaAccess = metaAccess; + this.unsupportedFeatures = unsupportedFeatures; + this.constantReflection = constantReflection; + + this.genericInterfacesMap = new ConcurrentHashMap<>(); + this.annotatedInterfacesMap = new ConcurrentHashMap<>(); + this.interfacesEncodings = new ConcurrentHashMap<>(); + } + + public void initializeMetaData(AnalysisType type) { + assert type.isReachable(); + DynamicHub hub = hostVM.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(hostVM.dynamicHub(enclosingType)); + } + } catch (UnsupportedFeatureException ex) { + unsupportedFeatures.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(AnnotationsProcessor.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 (hostVM.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(constantReflection.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 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 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() { + DynamicHub[] hubs = new DynamicHub[aInterfaces.length]; + for (int i = 0; i < hubs.length; i++) { + hubs[i] = hostVM.dynamicHub(aInterfaces[i]); + } + return hubs; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof InterfacesEncodingKey && Arrays.equals(aInterfaces, ((InterfacesEncodingKey) obj).aInterfaces); + } + + @Override + public int hashCode() { + return Arrays.hashCode(aInterfaces); + } + } + + /** + * Fill array returned by Class.getInterfaces(). + */ + private void fillInterfaces(AnalysisType type, DynamicHub hub) { + AnalysisType[] aInterfaces = type.getInterfaces(); + if (aInterfaces.length == 0) { + hub.setInterfacesEncoding(null); + } else if (aInterfaces.length == 1) { + hub.setInterfacesEncoding(hostVM.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 InterfacesEncodingKey(aInterfaces), InterfacesEncodingKey::createHubs)); + } + } + +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java index 58a4f50240b4..5aa4d03db3d4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java @@ -28,56 +28,40 @@ import static com.oracle.svm.hosted.NativeImageOptions.MaxReachableTypes; import static jdk.vm.ci.common.JVMCIError.shouldNotReachHere; -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.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.concurrent.ForkJoinPool; import java.util.regex.Pattern; -import java.util.stream.Collectors; -import com.oracle.svm.hosted.HostedConfiguration; import org.graalvm.compiler.core.common.SuppressSVMWarnings; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.options.OptionValues; import org.graalvm.word.WordBase; -import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.ObjectScanner; import com.oracle.graal.pointsto.ObjectScanner.ScanReason; -import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; +import com.oracle.graal.pointsto.PointsToAnalysis; +import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; import com.oracle.graal.pointsto.flow.MethodTypeFlow; import com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder; import com.oracle.graal.pointsto.flow.TypeFlow; 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; import com.oracle.graal.pointsto.reports.CallTreePrinter; -import com.oracle.graal.pointsto.util.AnalysisError.TypeNotFoundError; 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.core.util.UserError; +import com.oracle.svm.hosted.HostedConfiguration; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor; @@ -88,17 +72,14 @@ public class NativeImagePointsToAnalysis extends PointsToAnalysis implements Inflation { private Set handledUnknownValueFields; - private Map genericInterfacesMap; - private Map annotatedInterfacesMap; - private Map interfacesEncodings; private final Pattern illegalCalleesPattern; private final Pattern targetCallersPattern; private final AnnotationSubstitutionProcessor annotationSubstitutionProcessor; + private final DynamicHubInitializer dynamicHubInitializer; public NativeImagePointsToAnalysis(OptionValues options, AnalysisUniverse universe, HostedProviders providers, AnnotationSubstitutionProcessor annotationSubstitutionProcessor, - ForkJoinPool executor, - Runnable heartbeatCallback) { + ForkJoinPool executor, Runnable heartbeatCallback, UnsupportedFeatures unsupportedFeatures) { super(options, universe, providers, universe.hostVM(), executor, heartbeatCallback, new SubstrateUnsupportedFeatures(), SubstrateOptions.parseOnce()); this.annotationSubstitutionProcessor = annotationSubstitutionProcessor; @@ -109,9 +90,7 @@ public NativeImagePointsToAnalysis(OptionValues options, AnalysisUniverse univer illegalCalleesPattern = buildPrefixMatchPattern(illegalCallees); handledUnknownValueFields = new HashSet<>(); - genericInterfacesMap = new HashMap<>(); - annotatedInterfacesMap = new HashMap<>(); - interfacesEncodings = new HashMap<>(); + dynamicHubInitializer = new DynamicHubInitializer(universe, metaAccess, unsupportedFeatures, providers.getConstantReflection()); } @Override @@ -122,7 +101,7 @@ public MethodTypeFlowBuilder createMethodTypeFlowBuilder(PointsToAnalysis bb, Me @Override protected void checkObjectGraph(ObjectScanner objectScanner) { 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)); @@ -133,107 +112,10 @@ public SVMHost getHostVM() { return (SVMHost) hostVM; } - private 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); - } - } - } - } - @Override public void cleanupAfterAnalysis() { super.cleanupAfterAnalysis(); handledUnknownValueFields = null; - genericInterfacesMap = null; - annotatedInterfacesMap = null; - interfacesEncodings = null; } @Override @@ -255,220 +137,6 @@ public AnnotationSubstitutionProcessor getAnnotationSubstitutionProcessor() { return annotationSubstitutionProcessor; } - 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 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 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 InterfacesEncodingKey && Arrays.equals(aInterfaces, ((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 InterfacesEncodingKey(aInterfaces), InterfacesEncodingKey::createHubs)); - } - } - private void scanHub(ObjectScanner objectScanner, AnalysisType type) { SVMHost svmHost = (SVMHost) hostVM; JavaConstant hubConstant = SubstrateObjectConstant.forObject(svmHost.dynamicHub(type)); @@ -596,75 +264,6 @@ 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 (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(); From e30a5b148d7d957a766b1ddf60e4414523da6bf4 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 28 Sep 2021 20:35:45 +0200 Subject: [PATCH 204/681] First version of Class Hierarchy Oracle API --- .../hierarchy/ClassHierarchyOracle.java | 59 +++++++++++++++++++ .../hierarchy/LeafTypeAssumption.java | 34 +++++++++++ 2 files changed, 93 insertions(+) create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/LeafTypeAssumption.java diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java new file mode 100644 index 000000000000..934585f00ec1 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java @@ -0,0 +1,59 @@ +/* + * 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. + * + * 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.truffle.espresso.analysis.hierarchy; + +import com.oracle.truffle.espresso.impl.ObjectKlass; +import com.oracle.truffle.espresso.runtime.EspressoContext; + +/** + * {@code ClassHierarchyOracle} provides information about class hierarchy in the guest code, + * evolving as new classes are loaded. The oracle is safe, i.e. its answers never cause incorrect + * optimizations, but not necessarily precise (e.g. may not detect an effectively leaf type). + *

+ * The oracle is only valid within an {@link EspressoContext}. + */ +public interface ClassHierarchyOracle { + /** + * Must be called to initialize {@link ObjectKlass#leafTypeAssumption} of {@code newKlass}. + * + * @param newKlass -- newly created class + * @return the assumption, indicating whether the class is a leaf in class hierarchy. + */ + LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass); + + /** + * Must be called when {@code newKlass} is initialized. Communicates to the oracle that + * instances of this class might exist, which changes the class hierarchy. + * + * @param newKlass -- newly initialized class + */ + void onClassInit(ObjectKlass newKlass); + + /** + * @return the assumption, valid iff {@code klass} is a leaf in class hierarchy. Automatically + * invalidated in {@link #onClassInit(ObjectKlass)} when a child of {@code klass} is + * initialized. + */ + LeafTypeAssumption isLeafClass(ObjectKlass klass); +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/LeafTypeAssumption.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/LeafTypeAssumption.java new file mode 100644 index 000000000000..4b579587386d --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/LeafTypeAssumption.java @@ -0,0 +1,34 @@ +/* + * 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. + * + * 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.truffle.espresso.analysis.hierarchy; + +import com.oracle.truffle.api.Assumption; + +/** + * A wrapper around {@link Assumption}. Ensures that class hierarchy assumptions are managed + * exclusively by {@link ClassHierarchyOracle}. + */ +public interface LeafTypeAssumption { + Assumption getAssumption(); +} From a6052642650e1197cbdd09d996d664fe5cacce4e Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 28 Sep 2021 20:38:16 +0200 Subject: [PATCH 205/681] Create a simplistic class hierarchy oracle This oracle marks final and only final classes as leaf. Introduce leafTypeAssumption in ObjectKlass and use the oracle to initialize it. Keep an instance of oracle in the espresso context. --- .../hierarchy/NoOpClassHierarchyOracle.java | 77 +++++++++++++++++++ .../truffle/espresso/impl/ObjectKlass.java | 16 ++++ .../espresso/runtime/EspressoContext.java | 8 ++ 3 files changed, 101 insertions(+) create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java new file mode 100644 index 000000000000..a355d80aab6d --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java @@ -0,0 +1,77 @@ +/* + * 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. + * + * 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.truffle.espresso.analysis.hierarchy; + +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.espresso.impl.ObjectKlass; + +/** + * An implementation of {@link ClassHierarchyOracle} which simply checks {@code final} modifier of a + * class. + */ +public class NoOpClassHierarchyOracle implements ClassHierarchyOracle { + protected static class LeafTypeAssumptionImpl implements LeafTypeAssumption { + private final Assumption underlying; + + private LeafTypeAssumptionImpl(String assumptionName) { + underlying = Truffle.getRuntime().createAssumption(assumptionName); + } + + LeafTypeAssumptionImpl(ObjectKlass klass) { + this(klass.getNameAsString() + " is a leaf type"); + } + + protected static LeafTypeAssumptionImpl createAndInvalidate(String name) { + LeafTypeAssumptionImpl instance = new LeafTypeAssumptionImpl(name); + instance.getAssumption().invalidate(); + return instance; + } + + @Override + public Assumption getAssumption() { + return underlying; + } + } + + protected static final LeafTypeAssumption FinalIsAlwaysLeaf = new LeafTypeAssumptionImpl("final class is always a CHA leaf"); + protected static final LeafTypeAssumption NotLeaf = LeafTypeAssumptionImpl.createAndInvalidate("invalid"); + + @Override + public LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass) { + if (newKlass.isFinalFlagSet()) { + return FinalIsAlwaysLeaf; + } + return NotLeaf; + } + + @Override + public void onClassInit(ObjectKlass newKlass) { + } + + @Override + public LeafTypeAssumption isLeafClass(ObjectKlass klass) { + return klass.getLeafTypeAssumption(); + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java index 4fbc1d1c4d23..8cae9b3c347a 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java @@ -46,6 +46,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.espresso.analysis.hierarchy.LeafTypeAssumption; +import com.oracle.truffle.espresso.analysis.hierarchy.ClassHierarchyOracle; import com.oracle.truffle.espresso.classfile.ConstantPool; import com.oracle.truffle.espresso.classfile.RuntimeConstantPool; import com.oracle.truffle.espresso.classfile.attributes.ConstantValueAttribute; @@ -141,6 +143,8 @@ public final class ObjectKlass extends Klass { private final StaticObject definingClassLoader; + private final LeafTypeAssumption leafTypeAssumption; + public Attribute getAttribute(Symbol attrName) { return getLinkedKlass().getAttribute(attrName); } @@ -229,6 +233,7 @@ public ObjectKlass(EspressoContext context, LinkedKlass linkedKlass, ObjectKlass initSelfReferenceInPool(); } + this.leafTypeAssumption = getContext().getClassHierarchyOracle().createAssumptionForClass(this); this.initState = LOADED; assert verifyTables(); } @@ -390,6 +395,7 @@ private void actualInit() { throw e; } checkErroneousInitialization(); + getContext().getClassHierarchyOracle().onClassInit(this); initState = INITIALIZED; assert isInitialized(); } @@ -1399,6 +1405,16 @@ public void removeByRedefinition() { } } + /** + * @return the assumption, indicating if this class is a leaf in class hierarchy. This + * assumption must only be used by {@link ClassHierarchyOracle}, other users must use + * {@link ClassHierarchyOracle#isLeafClass(ObjectKlass)}. The assumption is stored in + * ObjectKlass for easy mapping between classes and corresponding assumptions. + */ + public LeafTypeAssumption getLeafTypeAssumption() { + return leafTypeAssumption; + } + public final class KlassVersion { final Assumption assumption; final RuntimeConstantPool pool; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java index 70771e74d2e5..23257795d668 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java @@ -66,6 +66,8 @@ import com.oracle.truffle.espresso.EspressoLanguage; import com.oracle.truffle.espresso.EspressoOptions; import com.oracle.truffle.espresso.FinalizationSupport; +import com.oracle.truffle.espresso.analysis.hierarchy.ClassHierarchyOracle; +import com.oracle.truffle.espresso.analysis.hierarchy.NoOpClassHierarchyOracle; import com.oracle.truffle.espresso.descriptors.Names; import com.oracle.truffle.espresso.descriptors.Signatures; import com.oracle.truffle.espresso.descriptors.Symbol; @@ -129,6 +131,7 @@ public final class EspressoContext { private final ClassRegistries registries; private final Substitutions substitutions; private final MethodHandleIntrinsics methodHandleIntrinsics; + private final ClassHierarchyOracle classHierarchyOracle; // endregion Runtime // region Helpers @@ -293,6 +296,7 @@ public EspressoContext(TruffleLanguage.Env env, EspressoLanguage language) { this.vmArguments = buildVmArguments(); this.jdwpContext = new JDWPContextImpl(this); + this.classHierarchyOracle = new NoOpClassHierarchyOracle(); } private static Set knownSingleThreadedLanguages(TruffleLanguage.Env env) { @@ -1016,4 +1020,8 @@ public void rerunclinit(ObjectKlass oldKlass) { public static EspressoContext get(Node node) { return REFERENCE.get(node); } + + public ClassHierarchyOracle getClassHierarchyOracle() { + return classHierarchyOracle; + } } From b2387e2c95c89d05a7a2f55f9335423869c7b1ed Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 28 Sep 2021 20:43:32 +0200 Subject: [PATCH 206/681] Create a class hierarchy oracle which keeps track of currently leaf classes --- .../DefaultClassHierarchyOracle.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java new file mode 100644 index 000000000000..152092b223cd --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java @@ -0,0 +1,59 @@ +/* + * 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. + * + * 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.truffle.espresso.analysis.hierarchy; + +import com.oracle.truffle.espresso.impl.ObjectKlass; + +/** + * Computes the classes that are effectively final by keeping track of currently loaded classes. To + * compute currently leaf classes, it creates {@link ObjectKlass#leafTypeAssumption} in the + * {@link ObjectKlass} constructor and invalidates it when a descendant of this class is + * initialized. + */ +public class DefaultClassHierarchyOracle extends NoOpClassHierarchyOracle implements ClassHierarchyOracle { + @Override + public LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass) { + if (newKlass.isFinalFlagSet()) { + return FinalIsAlwaysLeaf; + } + if (newKlass.isAbstract() || newKlass.isInterface()) { + return NotLeaf; + } + return new LeafTypeAssumptionImpl(newKlass); + } + + /** + * Marks all ancestors of {@code newClass} as non-leaf. + * + * @param newClass -- newly initialized class. + */ + @Override + public void onClassInit(ObjectKlass newClass) { + ObjectKlass currentParent = newClass.getSuperKlass(); + while (currentParent.getLeafTypeAssumption().getAssumption().isValid()) { + currentParent.getLeafTypeAssumption().getAssumption().invalidate(); + currentParent = currentParent.getSuperKlass(); + } + } +} From f75cdc2c00e0cbc286e70f5e3721434f26c12541 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 28 Sep 2021 20:44:11 +0200 Subject: [PATCH 207/681] Use class hierarchy oracle to optimize instanceof check --- .../espresso/nodes/bytecodes/InstanceOf.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InstanceOf.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InstanceOf.java index c618635b0c69..f6aaa7710323 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InstanceOf.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InstanceOf.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.espresso.nodes.bytecodes; +import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateUncached; @@ -221,12 +222,23 @@ boolean doFallback(Klass maybeSubtype) { abstract static class ConstantClass extends InstanceOf { private final ObjectKlass superType; + protected final Assumption superTypeIsLeaf; ConstantClass(ObjectKlass superType) { this.superType = superType; + this.superTypeIsLeaf = EspressoContext.get(this).getClassHierarchyOracle().isLeafClass(this.superType).getAssumption(); } - @Specialization + /** + * If {@code superType} is a leaf type, {@code maybeSubtype} is a subtype of + * {@code superType} iff it is equal to {@code superType}. + */ + @Specialization(assumptions = "superTypeIsLeaf") + public boolean doLeaf(ObjectKlass maybeSubtype) { + return superType == maybeSubtype; + } + + @Specialization(guards = "!superTypeIsLeaf.isValid()") public boolean doObjectKlass(ObjectKlass maybeSubtype) { return superType == maybeSubtype || superType.checkOrdinaryClassSubclassing(maybeSubtype); } From 35e00f0b5b094f8398dc5abaa131f38ae1d69f61 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 28 Sep 2021 20:45:49 +0200 Subject: [PATCH 208/681] Rename isLeaf method of Klass to hasNoSubtypes to avoid confusion with CHA oracle's method --- .../src/com/oracle/truffle/espresso/impl/Klass.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java index ccb341aa9b16..7c5c3cbfa91b 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java @@ -742,7 +742,7 @@ public final boolean isPrimitive() { * The setting of the final bit for types is a bit confusing since arrays are marked as final. * This method provides a semantically equivalent test that appropriate for types. */ - public boolean isLeaf() { + public boolean hasNoSubtypes() { return getElementalType().isFinalFlagSet(); } From 38ca47f6273385daf6d32800cdc5f664ca471614 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 28 Sep 2021 21:02:23 +0200 Subject: [PATCH 209/681] Update docs of CHA oracles: avoid referring to private field of ObjectKlass --- .../espresso/analysis/hierarchy/ClassHierarchyOracle.java | 2 +- .../analysis/hierarchy/DefaultClassHierarchyOracle.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java index 934585f00ec1..384aa24312d2 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java @@ -35,7 +35,7 @@ */ public interface ClassHierarchyOracle { /** - * Must be called to initialize {@link ObjectKlass#leafTypeAssumption} of {@code newKlass}. + * Must be called to initialize {@code leafTypeAssumption} of {@code newKlass}. * * @param newKlass -- newly created class * @return the assumption, indicating whether the class is a leaf in class hierarchy. diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java index 152092b223cd..4c56c048f3ba 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java @@ -27,9 +27,8 @@ /** * Computes the classes that are effectively final by keeping track of currently loaded classes. To - * compute currently leaf classes, it creates {@link ObjectKlass#leafTypeAssumption} in the - * {@link ObjectKlass} constructor and invalidates it when a descendant of this class is - * initialized. + * compute currently leaf classes, it creates {@code leafTypeAssumption} in the {@link ObjectKlass} + * constructor and invalidates it when a descendant of this class is initialized. */ public class DefaultClassHierarchyOracle extends NoOpClassHierarchyOracle implements ClassHierarchyOracle { @Override From fcd86719ce1add1705cd16dfad9607068d886d93 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 28 Sep 2021 21:33:12 +0200 Subject: [PATCH 210/681] Create a single instance of always invalid LeafTypeAssumption instead of providing a method --- .../analysis/hierarchy/NoOpClassHierarchyOracle.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java index a355d80aab6d..aad597b94058 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java @@ -34,6 +34,10 @@ public class NoOpClassHierarchyOracle implements ClassHierarchyOracle { protected static class LeafTypeAssumptionImpl implements LeafTypeAssumption { private final Assumption underlying; + static final LeafTypeAssumption AlwaysInvalid = new LeafTypeAssumptionImpl("invalid"); + static { + AlwaysInvalid.getAssumption().invalidate(); + } private LeafTypeAssumptionImpl(String assumptionName) { underlying = Truffle.getRuntime().createAssumption(assumptionName); @@ -43,12 +47,6 @@ private LeafTypeAssumptionImpl(String assumptionName) { this(klass.getNameAsString() + " is a leaf type"); } - protected static LeafTypeAssumptionImpl createAndInvalidate(String name) { - LeafTypeAssumptionImpl instance = new LeafTypeAssumptionImpl(name); - instance.getAssumption().invalidate(); - return instance; - } - @Override public Assumption getAssumption() { return underlying; @@ -56,7 +54,7 @@ public Assumption getAssumption() { } protected static final LeafTypeAssumption FinalIsAlwaysLeaf = new LeafTypeAssumptionImpl("final class is always a CHA leaf"); - protected static final LeafTypeAssumption NotLeaf = LeafTypeAssumptionImpl.createAndInvalidate("invalid"); + protected static final LeafTypeAssumption NotLeaf = LeafTypeAssumptionImpl.AlwaysInvalid; @Override public LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass) { From 024dff077841db766d74efed2cad61f19a71ea7b Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 28 Sep 2021 14:22:15 -0700 Subject: [PATCH 211/681] Compute AnalysisType.subTypes continuously, as the universe expands. --- .../graal/pointsto/meta/AnalysisType.java | 34 +++++++++-- .../graal/pointsto/meta/AnalysisUniverse.java | 57 +++++-------------- .../com/oracle/svm/hosted/FeatureImpl.java | 5 +- .../svm/hosted/NativeImageGenerator.java | 5 +- 4 files changed, 50 insertions(+), 51 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 3d5b37141f7b..3e48a52596eb 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 @@ -103,9 +103,8 @@ public class AnalysisType implements WrappedJavaType, OriginalClassProvider, Com */ private volatile ConcurrentHashMap> unsafeAccessedFields; - private static final AnalysisType[] EMPTY_ARRAY = {}; - - AnalysisType[] subTypes; + /** Immediate subtypes and this type itself. */ + private final Set subTypes; AnalysisType superClass; private final int id; @@ -143,7 +142,7 @@ public class AnalysisType implements WrappedJavaType, OriginalClassProvider, Com private final AnalysisType[] interfaces; /* isArray is an expensive operation so we eagerly compute it */ - private boolean isArray; + private final boolean isArray; private final int dimension; @@ -181,10 +180,24 @@ public enum UsageKind { */ } - subTypes = EMPTY_ARRAY; /* Ensure the super types as well as the component type (for arrays) is created too. */ superClass = universe.lookup(wrapped.getSuperclass()); interfaces = convertTypes(wrapped.getInterfaces()); + + subTypes = ConcurrentHashMap.newKeySet(); + addSubType(this); + + /* Build subtypes. */ + if (superClass != null) { + superClass.addSubType(this); + } + if (isInterface() && interfaces.length == 0) { + objectType.addSubType(this); + } + for (AnalysisType interf : interfaces) { + interf.addSubType(this); + } + if (isArray()) { this.componentType = universe.lookup(wrapped.getComponentType()); int dim = 0; @@ -787,6 +800,15 @@ public ResolvedJavaType getSingleImplementor() { return this; } + /** Get the immediate subtypes, including this type itself. */ + public Set getSubTypes() { + return subTypes; + } + + private void addSubType(AnalysisType subType) { + this.subTypes.add(subType); + } + @Override public AnalysisType findLeastCommonAncestor(ResolvedJavaType otherType) { ResolvedJavaType subst = universe.substitutions.resolve(((AnalysisType) otherType).wrapped); @@ -813,7 +835,7 @@ public ResolvedJavaType getElementalType() { } public boolean hasSubTypes() { - return subTypes != null ? subTypes.length > 0 : false; + return subTypes.size() > 0; } @Override 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 3131af28bfa6..49637e572588 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 @@ -28,7 +28,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; @@ -161,7 +160,6 @@ public boolean sealed() { public void setAnalysisDataValid(boolean dataIsValid) { if (dataIsValid) { - buildSubTypes(); collectMethodImplementations(); } analysisDataValid = dataIsValid; @@ -574,35 +572,6 @@ public Object replaceObject(Object source) { return destination; } - public void buildSubTypes() { - Map> allSubTypes = new HashMap<>(); - AnalysisType objectType = null; - for (AnalysisType type : getTypes()) { - allSubTypes.put(type, new HashSet<>()); - if (type.isInstanceClass() && type.getSuperclass() == null) { - objectType = type; - } - } - assert objectType != null; - - for (AnalysisType type : getTypes()) { - if (type.getSuperclass() != null) { - allSubTypes.get(type.getSuperclass()).add(type); - } - if (type.isInterface() && type.getInterfaces().length == 0) { - allSubTypes.get(objectType).add(type); - } - for (AnalysisType interf : type.getInterfaces()) { - allSubTypes.get(interf).add(type); - } - } - - for (AnalysisType type : getTypes()) { - Set subTypesSet = allSubTypes.get(type); - type.subTypes = subTypesSet.toArray(new AnalysisType[subTypesSet.size()]); - } - } - private void collectMethodImplementations() { for (AnalysisMethod method : methods.values()) { @@ -629,9 +598,12 @@ public static Set getMethodImplementations(BigBang bb, AnalysisM } private static boolean collectMethodImplementations(AnalysisMethod method, AnalysisType holder, Set implementations, boolean includeInlinedMethods) { - assert holder.subTypes != null : holder; boolean holderOrSubtypeInstantiated = holder.isInstantiated(); - for (AnalysisType subClass : holder.subTypes) { + for (AnalysisType subClass : holder.getSubTypes()) { + if (subClass.equals(holder)) { + /* Subtypes include the holder type itself. The holder is processed below. */ + continue; + } holderOrSubtypeInstantiated |= collectMethodImplementations(method, subClass, implementations, includeInlinedMethods); } @@ -654,21 +626,22 @@ private static boolean collectMethodImplementations(AnalysisMethod method, Analy return holderOrSubtypeInstantiated; } - public static Set getSubtypes(AnalysisType baseType) { - LinkedHashSet result = new LinkedHashSet<>(); - result.add(baseType); + /** + * Collect and returns *all* subtypes of this type, not only the immediate subtypes. The + * immediate sub-types are updated continuously as the universe is expanded and can be accessed + * using {@link AnalysisType#getSubTypes()}. + */ + public static Set getAllSubtypes(AnalysisType baseType) { + HashSet result = new HashSet<>(); collectSubtypes(baseType, result); return result; } private static void collectSubtypes(AnalysisType baseType, Set result) { - assert baseType.subTypes != null : baseType; - for (AnalysisType subType : baseType.subTypes) { - if (result.contains(subType)) { - continue; + for (AnalysisType subType : baseType.getSubTypes()) { + if (result.add(subType)) { + collectSubtypes(subType, result); } - result.add(subType); - collectSubtypes(subType, result); } } 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 f1bf9e8e0ad8..f2ca7753b5c2 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 @@ -35,6 +35,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Deque; +import java.util.HashSet; import java.util.IdentityHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -227,11 +228,11 @@ public boolean isReachable(AnalysisMethod method) { public Set> reachableSubtypes(Class baseClass) { return reachableSubtypes(getMetaAccess().lookupJavaType(baseClass)).stream() - .map(AnalysisType::getJavaClass).collect(Collectors.toCollection(LinkedHashSet::new)); + .map(AnalysisType::getJavaClass).collect(Collectors.toCollection(HashSet::new)); } Set reachableSubtypes(AnalysisType baseType) { - Set result = AnalysisUniverse.getSubtypes(baseType); + Set result = AnalysisUniverse.getAllSubtypes(baseType); result.removeIf(t -> !isReachable(t)); return result; } 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 a8e2aab61753..5ef607941bab 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 @@ -59,7 +59,6 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -import com.oracle.svm.hosted.analysis.SubstrateUnsupportedFeatures; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Pair; import org.graalvm.compiler.api.replacements.Fold; @@ -226,6 +225,7 @@ import com.oracle.svm.hosted.analysis.Inflation; import com.oracle.svm.hosted.analysis.NativeImagePointsToAnalysis; import com.oracle.svm.hosted.analysis.SVMAnalysisMetaAccess; +import com.oracle.svm.hosted.analysis.SubstrateUnsupportedFeatures; import com.oracle.svm.hosted.annotation.AnnotationSupport; import com.oracle.svm.hosted.c.CAnnotationProcessorCache; import com.oracle.svm.hosted.c.CConstantValueSupportImpl; @@ -845,6 +845,9 @@ private void setupNativeImage(String imageName, OptionValues options, Map Date: Wed, 22 Sep 2021 15:39:02 -0700 Subject: [PATCH 212/681] Extract ObjectScanningObserver interface. --- .../graal/pointsto/AnalysisObjectScanner.java | 102 +------------ .../AnalysisObjectScanningObserver.java | 139 ++++++++++++++++++ .../oracle/graal/pointsto/ObjectScanner.java | 55 ++----- .../pointsto/ObjectScanningObserver.java | 75 ++++++++++ .../reports/AnalysisHeapHistogramPrinter.java | 65 ++++---- .../pointsto/reports/ObjectTreePrinter.java | 132 +++++++++-------- 6 files changed, 333 insertions(+), 235 deletions(-) create mode 100644 substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanningObserver.java create mode 100644 substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanningObserver.java diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanner.java index f7ab722b8ca1..2f1d0f066323 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanner.java @@ -24,111 +24,11 @@ */ package com.oracle.graal.pointsto; -import com.oracle.graal.pointsto.flow.ArrayElementsTypeFlow; -import com.oracle.graal.pointsto.flow.FieldTypeFlow; -import com.oracle.graal.pointsto.flow.context.object.AnalysisObject; -import com.oracle.graal.pointsto.meta.AnalysisField; -import com.oracle.graal.pointsto.meta.AnalysisType; -import com.oracle.graal.pointsto.typestate.TypeState; import com.oracle.graal.pointsto.util.CompletionExecutor; -import jdk.vm.ci.meta.JavaConstant; - public class AnalysisObjectScanner extends ObjectScanner { public AnalysisObjectScanner(BigBang bb, CompletionExecutor executor, ReusableSet scannedObjects) { - super(bb, executor, scannedObjects); - } - - @Override - public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { - if (!field.isWritten()) { - field.registerAsWritten(null); - } - } - - @Override - public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { - FieldTypeFlow fieldTypeFlow = getFieldTypeFlow(field, receiver); - if (!fieldTypeFlow.getState().canBeNull()) { - /* Signal that the field can contain null. */ - fieldTypeFlow.addState(getAnalysis(), TypeState.forNull()); - } - } - - @Override - public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { - PointsToAnalysis analysis = getAnalysis(); - AnalysisType fieldType = analysis.getMetaAccess().lookupJavaType(analysis.getSnippetReflectionProvider().asObject(Object.class, fieldValue).getClass()); - assert fieldType.isInstantiated() : fieldType; - - /* Add the constant value object to the field's type flow. */ - FieldTypeFlow fieldTypeFlow = getFieldTypeFlow(field, receiver); - AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(analysis, fieldValue, fieldType); - if (!fieldTypeFlow.getState().containsObject(constantObject)) { - /* Add the new constant to the field's flow state. */ - TypeState constantTypeState = TypeState.forNonNullObject(analysis, constantObject); - fieldTypeFlow.addState(analysis, constantTypeState); - } - } - - /** Get the field type flow give a receiver. */ - private FieldTypeFlow getFieldTypeFlow(AnalysisField field, JavaConstant receiver) { - /* The field type flow is used to track the constant field value. */ - if (field.isStatic()) { - /* If the field is static it comes from the originalRoots. */ - return field.getStaticFieldFlow(); - } else { - /* - * The field comes from a constant scan, thus it's type flow is mapped to the unique - * constant object. - */ - PointsToAnalysis analysis = getAnalysis(); - AnalysisType receiverType = analysis.getMetaAccess().lookupJavaType(analysis.getSnippetReflectionProvider().asObject(Object.class, receiver).getClass()); - AnalysisObject constantReceiverObj = analysis.analysisPolicy().createConstantObject(analysis, receiver, receiverType); - return constantReceiverObj.getInstanceFieldFlow(analysis, field, true); - } - } - - @Override - public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex) { - ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType); - if (!arrayObjElementsFlow.getState().canBeNull()) { - /* Signal that the constant array can contain null. */ - arrayObjElementsFlow.addState(getAnalysis(), TypeState.forNull()); - } - } - - @Override - public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex) { - assert elementType.isInstantiated() : elementType; - ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType); - PointsToAnalysis analysis = getAnalysis(); - AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(analysis, elementConstant, elementType); - if (!arrayObjElementsFlow.getState().containsObject(constantObject)) { - /* Add the constant element to the constant's array type flow. */ - TypeState elementTypeState = TypeState.forNonNullObject(analysis, constantObject); - arrayObjElementsFlow.addState(analysis, elementTypeState); - } - } - - /** Get the array elements flow given its type and the array constant. */ - private ArrayElementsTypeFlow getArrayElementsFlow(JavaConstant array, AnalysisType arrayType) { - PointsToAnalysis analysis = getAnalysis(); - AnalysisObject arrayObjConstant = analysis.analysisPolicy().createConstantObject(analysis, array, arrayType); - return arrayObjConstant.getArrayElementsFlow(analysis, true); - } - - @Override - protected void forScannedConstant(JavaConstant value, ScanReason reason) { - PointsToAnalysis analysis = getAnalysis(); - Object valueObj = analysis.getSnippetReflectionProvider().asObject(Object.class, value); - AnalysisType type = bb.getMetaAccess().lookupJavaType(valueObj.getClass()); - - type.registerAsInHeap(); - } - - private PointsToAnalysis getAnalysis() { - return ((PointsToAnalysis) bb); + super(bb, executor, scannedObjects, new AnalysisObjectScanningObserver(bb)); } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanningObserver.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanningObserver.java new file mode 100644 index 000000000000..f07d0707c0f4 --- /dev/null +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanningObserver.java @@ -0,0 +1,139 @@ +/* + * 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.flow.ArrayElementsTypeFlow; +import com.oracle.graal.pointsto.flow.FieldTypeFlow; +import com.oracle.graal.pointsto.flow.context.object.AnalysisObject; +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.typestate.TypeState; + +import jdk.vm.ci.meta.JavaConstant; + +class AnalysisObjectScanningObserver implements ObjectScanningObserver { + + private final BigBang bb; + + AnalysisObjectScanningObserver(BigBang bb) { + this.bb = bb; + } + + @Override + public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + if (!field.isWritten()) { + field.registerAsWritten(null); + } + } + + @Override + public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { + FieldTypeFlow fieldTypeFlow = getFieldTypeFlow(field, receiver); + if (!fieldTypeFlow.getState().canBeNull()) { + /* Signal that the field can contain null. */ + fieldTypeFlow.addState(getAnalysis(), TypeState.forNull()); + } + } + + @Override + public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + PointsToAnalysis analysis = getAnalysis(); + AnalysisType fieldType = analysis.getMetaAccess().lookupJavaType(analysis.getSnippetReflectionProvider().asObject(Object.class, fieldValue).getClass()); + assert fieldType.isInstantiated() : fieldType; + + /* Add the constant value object to the field's type flow. */ + FieldTypeFlow fieldTypeFlow = getFieldTypeFlow(field, receiver); + AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(analysis, fieldValue, fieldType); + if (!fieldTypeFlow.getState().containsObject(constantObject)) { + /* Add the new constant to the field's flow state. */ + TypeState constantTypeState = TypeState.forNonNullObject(analysis, constantObject); + fieldTypeFlow.addState(analysis, constantTypeState); + } + } + + /** + * Get the field type flow give a receiver. + */ + private FieldTypeFlow getFieldTypeFlow(AnalysisField field, JavaConstant receiver) { + /* The field type flow is used to track the constant field value. */ + if (field.isStatic()) { + /* If the field is static it comes from the originalRoots. */ + return field.getStaticFieldFlow(); + } else { + /* + * The field comes from a constant scan, thus it's type flow is mapped to the unique + * constant object. + */ + PointsToAnalysis analysis = getAnalysis(); + AnalysisType receiverType = analysis.getMetaAccess().lookupJavaType(analysis.getSnippetReflectionProvider().asObject(Object.class, receiver).getClass()); + AnalysisObject constantReceiverObj = analysis.analysisPolicy().createConstantObject(analysis, receiver, receiverType); + return constantReceiverObj.getInstanceFieldFlow(analysis, field, true); + } + } + + @Override + public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex) { + ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType); + if (!arrayObjElementsFlow.getState().canBeNull()) { + /* Signal that the constant array can contain null. */ + arrayObjElementsFlow.addState(getAnalysis(), TypeState.forNull()); + } + } + + @Override + public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex) { + assert elementType.isInstantiated() : elementType; + ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType); + PointsToAnalysis analysis = getAnalysis(); + AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(analysis, elementConstant, elementType); + if (!arrayObjElementsFlow.getState().containsObject(constantObject)) { + /* Add the constant element to the constant's array type flow. */ + TypeState elementTypeState = TypeState.forNonNullObject(analysis, constantObject); + arrayObjElementsFlow.addState(analysis, elementTypeState); + } + } + + /** + * Get the array elements flow given its type and the array constant. + */ + private ArrayElementsTypeFlow getArrayElementsFlow(JavaConstant array, AnalysisType arrayType) { + PointsToAnalysis analysis = getAnalysis(); + AnalysisObject arrayObjConstant = analysis.analysisPolicy().createConstantObject(analysis, array, arrayType); + return arrayObjConstant.getArrayElementsFlow(analysis, true); + } + + @Override + public void forScannedConstant(JavaConstant value, ObjectScanner.ScanReason reason) { + PointsToAnalysis analysis = getAnalysis(); + Object valueObj = analysis.getSnippetReflectionProvider().asObject(Object.class, value); + AnalysisType type = bb.getMetaAccess().lookupJavaType(valueObj.getClass()); + + type.registerAsInHeap(); + } + + private PointsToAnalysis getAnalysis() { + return ((PointsToAnalysis) bb); + } +} diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java index b633afcb2b81..ffd701706cde 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java @@ -60,9 +60,11 @@ public abstract class ObjectScanner { private final ReusableSet scannedObjects; private final CompletionExecutor executor; private final Deque worklist; + private final ObjectScanningObserver scanningObserver; - public ObjectScanner(BigBang bb, CompletionExecutor executor, ReusableSet scannedObjects) { + public ObjectScanner(BigBang bb, CompletionExecutor executor, ReusableSet scannedObjects, ObjectScanningObserver scanningObserver) { this.bb = bb; + this.scanningObserver = scanningObserver; if (executor != null) { this.executor = executor; this.worklist = null; @@ -117,27 +119,6 @@ private void scanEmbeddedRoot(JavaConstant root, BytecodePosition position) { } } - /* - * When scanning a field there are three possible cases: the field value is a relocated pointer, - * the field value is null or the field value is non-null. The method {@link - * ObjectScanner#scanField(AnalysisField, JavaConstant, Object)} will call the appropriated - * method during scanning. - */ - - /** - * Hook for relocated pointer scanned field value. - * - * For relocated pointers the value is only known at runtime after methods are relocated, which - * is pretty much the same as a field written at runtime: we do not have a constant value. - */ - public abstract void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue); - - /** Hook for scanned null field value. */ - public abstract void forNullFieldValue(JavaConstant receiver, AnalysisField field); - - /** Hook for scanned non-null field value. */ - public abstract void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue); - /** * Scans the value of a root field. * @@ -168,14 +149,14 @@ protected final void scanField(AnalysisField field, JavaConstant receiver, Workl } if (fieldValue.getJavaKind() == JavaKind.Object && bb.getHostVM().isRelocatedPointer(constantAsObject(bb, fieldValue))) { - forRelocatedPointerFieldValue(receiver, field, fieldValue); + scanningObserver.forRelocatedPointerFieldValue(receiver, field, fieldValue); } else if (fieldValue.isNull()) { - forNullFieldValue(receiver, field); + scanningObserver.forNullFieldValue(receiver, field); } else if (fieldValue.getJavaKind() == JavaKind.Object) { /* Scan the field value. */ scanConstant(fieldValue, reason, previous); /* Process the field value. */ - forNonNullFieldValue(receiver, field, fieldValue); + scanningObserver.forNonNullFieldValue(receiver, field, fieldValue); } } catch (UnsupportedFeatureException ex) { @@ -183,18 +164,6 @@ protected final void scanField(AnalysisField field, JavaConstant receiver, Workl } } - /* - * When scanning array elements there are two possible cases: the element value is either null - * or the field value is non-null. The method {@link ObjectScanner#scanArray(JavaConstant, - * Object)} will call the appropriated method during scanning. - */ - - /** Hook for scanned null element value. */ - public abstract void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex); - - /** Hook for scanned non-null element value. */ - public abstract void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex); - /** * Scans constant arrays, one element at the time. * @@ -213,7 +182,7 @@ protected final void scanArray(JavaConstant array, WorklistEntry previous) { Object e = arrayObject[idx]; try { if (e == null) { - forNullArrayElement(array, arrayType, idx); + scanningObserver.forNullArrayElement(array, arrayType, idx); } else { Object element = bb.getUniverse().replaceObject(e); JavaConstant elementConstant = bb.getSnippetReflectionProvider().forObject(element); @@ -222,7 +191,7 @@ protected final void scanArray(JavaConstant array, WorklistEntry previous) { /* Scan the array element. */ scanConstant(elementConstant, reason, previous); /* Process the array element. */ - forNonNullArrayElement(array, arrayType, elementConstant, elementType, idx); + scanningObserver.forNonNullArrayElement(array, arrayType, elementConstant, elementType, idx); } } catch (UnsupportedFeatureException ex) { unsupportedFeature(arrayType.toJavaName(true), ex.getMessage(), reason, previous); @@ -230,12 +199,6 @@ protected final void scanArray(JavaConstant array, WorklistEntry previous) { } } - /** - * Hook for scanned constant. The subclasses can provide additional processing for the scanned - * constants. - */ - protected abstract void forScannedConstant(JavaConstant scannedValue, ScanReason reason); - public final void scanConstant(JavaConstant value, ScanReason reason) { scanConstant(value, reason, null); } @@ -251,7 +214,7 @@ public final void scanConstant(JavaConstant value, ScanReason reason, WorklistEn } if (scannedObjects.putAndAcquire(valueObj) == null) { try { - forScannedConstant(value, reason); + scanningObserver.forScannedConstant(value, reason); } finally { scannedObjects.release(valueObj); WorklistEntry worklistEntry = new WorklistEntry(previous, value, reason); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanningObserver.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanningObserver.java new file mode 100644 index 000000000000..9101fa4ab148 --- /dev/null +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanningObserver.java @@ -0,0 +1,75 @@ +/* + * 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.ObjectScanner.ScanReason; +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisType; + +import jdk.vm.ci.meta.JavaConstant; + +/** + * This interface contains hooks for constant scanning events. + * + * When scanning a field there are three possible cases: the field value is a relocated pointer, the + * field value is null or the field value is non-null. When scanning array elements there are two + * possible cases: the element value is either null or the field value is non-null. The implementers + * of this API will call the appropriate method during scanning. + */ +public interface ObjectScanningObserver { + + /** + * Hook for relocated pointer scanned field value. + *

+ * For relocated pointers the value is only known at runtime after methods are relocated, which + * is pretty much the same as a field written at runtime: we do not have a constant value. + */ + void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue); + + /** + * Hook for scanned null field value. + */ + void forNullFieldValue(JavaConstant receiver, AnalysisField field); + + /** + * Hook for scanned non-null field value. + */ + void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue); + + /** + * Hook for scanned null element value. + */ + void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int elementIndex); + + /** + * Hook for scanned non-null element value. + */ + void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex); + + /** + * Hook for scanned constant. + */ + void forScannedConstant(JavaConstant scannedValue, ScanReason reason); +} diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisHeapHistogramPrinter.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisHeapHistogramPrinter.java index 56a28c6cba81..c9b855de77cf 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisHeapHistogramPrinter.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisHeapHistogramPrinter.java @@ -35,6 +35,7 @@ import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.ObjectScanner; +import com.oracle.graal.pointsto.ObjectScanningObserver; import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisType; @@ -54,12 +55,13 @@ private static void doPrint(PrintWriter out, BigBang bb) { System.out.println("Exhaustive heap scanning is disabled. The analysis heap histogram will not contain all instances of types: " + types); System.out.println("Exhaustive heap scanning can be turned on using -H:+ExhaustiveHeapScan."); } - AnalysisHeapHistogramPrinter printer = new AnalysisHeapHistogramPrinter(bb); + Map histogram = new HashMap<>(); + AnalysisHeapHistogramPrinter printer = new AnalysisHeapHistogramPrinter(bb, histogram); printer.scanBootImageHeapRoots(fieldComparator, positionComparator); - printer.printHistogram(out); + printHistogram(out, histogram); } - private void printHistogram(PrintWriter out) { + private static void printHistogram(PrintWriter out, Map histogram) { out.println("Heap histogram"); out.format("%8s %s %n", "Count", "Class"); @@ -67,36 +69,45 @@ private void printHistogram(PrintWriter out) { .forEach(entry -> out.format("%8d %8s %n", entry.getValue(), entry.getKey().toJavaName())); } - private final Map histogram = new HashMap<>(); - - private AnalysisHeapHistogramPrinter(BigBang bb) { - super(bb, null, new ReusableSet()); + private AnalysisHeapHistogramPrinter(BigBang bb, Map histogram) { + super(bb, null, new ReusableSet(), new ScanningObserver(bb, histogram)); } - @Override - protected void forScannedConstant(JavaConstant scannedValue, ScanReason reason) { - AnalysisType type = constantType(bb, scannedValue); - int count = histogram.getOrDefault(type, 0); - histogram.put(type, count + 1); - } + private static final class ScanningObserver implements ObjectScanningObserver { - @Override - public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { - } + private final BigBang bb; + private final Map histogram; - @Override - public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { - } + private ScanningObserver(BigBang bb, Map histogram) { + this.bb = bb; + this.histogram = histogram; + } - @Override - public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { - } + @Override + public void forScannedConstant(JavaConstant scannedValue, ScanReason reason) { + AnalysisType type = constantType(bb, scannedValue); + int count = histogram.getOrDefault(type, 0); + histogram.put(type, count + 1); + } - @Override - public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int index) { - } + @Override + public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + } + + @Override + public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { + } + + @Override + public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + } + + @Override + public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int index) { + } - @Override - public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int index) { + @Override + public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int index) { + } } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/ObjectTreePrinter.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/ObjectTreePrinter.java index 08257afbc071..fafe5d3364ec 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/ObjectTreePrinter.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/ObjectTreePrinter.java @@ -47,6 +47,7 @@ import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.ObjectScanner; +import com.oracle.graal.pointsto.ObjectScanningObserver; import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisType; @@ -70,9 +71,11 @@ private static void doPrint(PrintWriter out, BigBang bb) { System.out.println("Exhaustive heap scanning is disabled. The object tree will not contain all instances of types: " + types); System.out.println("Exhaustive heap scanning can be turned on using -H:+ExhaustiveHeapScan."); } - ObjectTreePrinter printer = new ObjectTreePrinter(bb); + /* Use linked hash map for predictable iteration order. */ + Map constantToNode = new LinkedHashMap<>(); + ObjectTreePrinter printer = new ObjectTreePrinter(bb, constantToNode); printer.scanBootImageHeapRoots(fieldComparator, positionComparator); - printer.printTypeHierarchy(out); + printer.printTypeHierarchy(out, constantToNode); } static class RootSource { @@ -285,7 +288,6 @@ public boolean matches(String input) { "com.ibm.icu.util.ULocale.nameCache*", "com.oracle.svm.core.option.RuntimeOptionsSupportImpl.set(String, Object)"}; - private final Map constantToNode; private final SimpleMatcher suppressTypeMatcher; private final SimpleMatcher expandTypeMatcher; private final SimpleMatcher defaultSuppressTypeMatcher; @@ -293,11 +295,8 @@ public boolean matches(String input) { private final SimpleMatcher expandRootMatcher; private final SimpleMatcher defaultSuppressRootMatcher; - private ObjectTreePrinter(BigBang bb) { - super(bb, null, new ReusableSet()); - - /* Use linked hash map for predictable iteration order. */ - this.constantToNode = new LinkedHashMap<>(); + private ObjectTreePrinter(BigBang bb, Map constantToNode) { + super(bb, null, new ReusableSet(), new ScanningObserver(bb, constantToNode)); OptionValues options = bb.getOptions(); @@ -310,76 +309,87 @@ private ObjectTreePrinter(BigBang bb) { this.defaultSuppressRootMatcher = new SimpleMatcher(suppressRootsDefault); } - @Override - public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { - } + private static final class ScanningObserver implements ObjectScanningObserver { - @Override - public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { - if (receiver == null) { - // static field - return; - } + private final BigBang bb; + private final Map constantToNode; - assert constantToNode.containsKey(receiver); + private ScanningObserver(BigBang bb, Map constantToNode) { + this.bb = bb; + this.constantToNode = constantToNode; + } - ObjectNode receiverNode = (ObjectNode) constantToNode.get(receiver); - receiverNode.addField(field, ObjectNodeBase.forNull()); - } + @Override + public void forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + } - @Override - public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { + @Override + public void forNullFieldValue(JavaConstant receiver, AnalysisField field) { + if (receiver == null) { + // static field + return; + } - if (receiver == null) { - // static field - return; - } + assert constantToNode.containsKey(receiver); - if (constantToNode.containsKey(receiver) && constantToNode.containsKey(fieldValue)) { ObjectNode receiverNode = (ObjectNode) constantToNode.get(receiver); - ObjectNodeBase valueNode = constantToNode.get(fieldValue); - receiverNode.addField(field, valueNode); + receiverNode.addField(field, ObjectNodeBase.forNull()); } - } - @Override - public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int index) { - assert constantToNode.containsKey(array); + @Override + public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) { - ArrayObjectNode arrayNode = (ArrayObjectNode) constantToNode.get(array); - arrayNode.addElement(index, ObjectNodeBase.forNull()); - } + if (receiver == null) { + // static field + return; + } + + if (constantToNode.containsKey(receiver) && constantToNode.containsKey(fieldValue)) { + ObjectNode receiverNode = (ObjectNode) constantToNode.get(receiver); + ObjectNodeBase valueNode = constantToNode.get(fieldValue); + receiverNode.addField(field, valueNode); + } + } + + @Override + public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int index) { + assert constantToNode.containsKey(array); - @Override - public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int index) { - if (constantToNode.containsKey(array) && constantToNode.containsKey(elementConstant)) { ArrayObjectNode arrayNode = (ArrayObjectNode) constantToNode.get(array); - ObjectNodeBase valueNode = constantToNode.get(elementConstant); - arrayNode.addElement(index, valueNode); + arrayNode.addElement(index, ObjectNodeBase.forNull()); } - } - @Override - protected void forScannedConstant(JavaConstant scannedValue, ScanReason reason) { - JVMCIError.guarantee(scannedValue != null, "scannedValue is null"); - constantToNode.computeIfAbsent(scannedValue, c -> { - ObjectNodeBase node; - if (reason instanceof FieldScan) { - ResolvedJavaField field = ((FieldScan) reason).getField(); - if (field.isStatic()) { - node = ObjectNodeBase.fromConstant(bb, scannedValue, new RootSource(field)); + @Override + public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int index) { + if (constantToNode.containsKey(array) && constantToNode.containsKey(elementConstant)) { + ArrayObjectNode arrayNode = (ArrayObjectNode) constantToNode.get(array); + ObjectNodeBase valueNode = constantToNode.get(elementConstant); + arrayNode.addElement(index, valueNode); + } + } + + @Override + public void forScannedConstant(JavaConstant scannedValue, ScanReason reason) { + JVMCIError.guarantee(scannedValue != null, "scannedValue is null"); + constantToNode.computeIfAbsent(scannedValue, c -> { + ObjectNodeBase node; + if (reason instanceof FieldScan) { + ResolvedJavaField field = ((FieldScan) reason).getField(); + if (field.isStatic()) { + node = ObjectNodeBase.fromConstant(bb, scannedValue, new RootSource(field)); + } else { + node = ObjectNodeBase.fromConstant(bb, scannedValue); + } + } else if (reason instanceof MethodScan) { + ResolvedJavaMethod method = ((MethodScan) reason).getMethod(); + node = ObjectNodeBase.fromConstant(bb, scannedValue, new RootSource(method)); } else { node = ObjectNodeBase.fromConstant(bb, scannedValue); } - } else if (reason instanceof MethodScan) { - ResolvedJavaMethod method = ((MethodScan) reason).getMethod(); - node = ObjectNodeBase.fromConstant(bb, scannedValue, new RootSource(method)); - } else { - node = ObjectNodeBase.fromConstant(bb, scannedValue); - } - return node; - }); + return node; + }); + } } static String constantAsString(BigBang bb, JavaConstant constant) { @@ -453,7 +463,7 @@ private boolean suppressRoot(RootSource source) { return false; } - private void printTypeHierarchy(PrintWriter out) { + private void printTypeHierarchy(PrintWriter out, Map constantToNode) { out.println("Heap roots"); Iterator iterator = constantToNode.values().stream().filter(n -> n.isRoot()).iterator(); while (iterator.hasNext()) { From 895687d0d2b3d5ae1f9316879355553b17eabcad Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Wed, 29 Sep 2021 09:15:29 +0200 Subject: [PATCH 213/681] move sending class prepare events to when classes are actually prepared according to spec --- .../oracle/truffle/espresso/impl/ObjectKlass.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java index 4fbc1d1c4d23..482fe9c8ad6d 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java @@ -343,12 +343,6 @@ private void actualInit() { } initState = INITIALIZING; try { - if (getContext().isMainThreadCreated()) { - if (getContext().shouldReportVMEvents()) { - prepareThread = getContext().getGuestThreadFromHost(Thread.currentThread()); - getContext().reportClassPrepared(this, prepareThread); - } - } if (!isInterface()) { /* * Next, if C is a class rather than an interface, then let SC be its superclass @@ -460,6 +454,12 @@ private void prepare() { } } initState = PREPARED; + if (getContext().isMainThreadCreated()) { + if (getContext().shouldReportVMEvents()) { + prepareThread = getContext().getGuestThreadFromHost(Thread.currentThread()); + getContext().reportClassPrepared(this, prepareThread); + } + } } } } From 19cc06b2e34a67ded925e95a630a052b08e7762c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Tue, 28 Sep 2021 12:28:21 +0200 Subject: [PATCH 214/681] Remove obsolete JLineFeature --- .../svm/thirdparty/jline/JLineFeature.java | 143 ------------------ 1 file changed, 143 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.thirdparty/src/com/oracle/svm/thirdparty/jline/JLineFeature.java diff --git a/substratevm/src/com.oracle.svm.thirdparty/src/com/oracle/svm/thirdparty/jline/JLineFeature.java b/substratevm/src/com.oracle.svm.thirdparty/src/com/oracle/svm/thirdparty/jline/JLineFeature.java deleted file mode 100644 index 85894c981ced..000000000000 --- a/substratevm/src/com.oracle.svm.thirdparty/src/com/oracle/svm/thirdparty/jline/JLineFeature.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2019, 2019, 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.thirdparty.jline; - -// Checkstyle: allow reflection - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Stream; - -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.hosted.Feature; -import org.graalvm.nativeimage.hosted.RuntimeClassInitialization; -import org.graalvm.nativeimage.hosted.RuntimeReflection; - -import com.oracle.svm.core.annotate.AutomaticFeature; -import com.oracle.svm.core.jdk.Resources; -import com.oracle.svm.core.jni.JNIRuntimeAccess; -import com.oracle.svm.util.ReflectionUtil; - -@AutomaticFeature -final class JLineFeature implements Feature { - - /** List of the classes that access the JNI library. */ - private static final List JNI_CLASS_NAMES = Arrays.asList( - "org.fusesource.jansi.internal.CLibrary", - "org.fusesource.jansi.internal.CLibrary$WinSize", - "org.fusesource.jansi.internal.CLibrary$Termios", - "org.fusesource.jansi.internal.Kernel32", - "org.fusesource.jansi.internal.Kernel32$SMALL_RECT", - "org.fusesource.jansi.internal.Kernel32$COORD", - "org.fusesource.jansi.internal.Kernel32$CONSOLE_SCREEN_BUFFER_INFO", - "org.fusesource.jansi.internal.Kernel32$CHAR_INFO", - "org.fusesource.jansi.internal.Kernel32$KEY_EVENT_RECORD", - "org.fusesource.jansi.internal.Kernel32$MOUSE_EVENT_RECORD", - "org.fusesource.jansi.internal.Kernel32$WINDOW_BUFFER_SIZE_RECORD", - "org.fusesource.jansi.internal.Kernel32$FOCUS_EVENT_RECORD", - "org.fusesource.jansi.internal.Kernel32$MENU_EVENT_RECORD", - "org.fusesource.jansi.internal.Kernel32$INPUT_RECORD"); - - /** - * Other classes that need to be initialized at run time because they reference the JNI classes - * and/or have static state that depends on run time state. - */ - private static final List RUNTIME_INIT_CLASS_NAMES = Arrays.asList( - "org.fusesource.jansi.AnsiConsole", - "org.fusesource.jansi.WindowsAnsiOutputStream", - "org.fusesource.jansi.WindowsAnsiProcessor"); - - Class terminalFactoryClass; - - @Override - public boolean isInConfiguration(IsInConfigurationAccess access) { - terminalFactoryClass = access.findClassByName("jline.TerminalFactory"); - /* Feature is only active when JLine is on the classpath. */ - return terminalFactoryClass != null; - } - - @Override - public void duringSetup(DuringSetupAccess access) { - if (Platform.includedIn(Platform.WINDOWS.class)) { - Stream.concat(JNI_CLASS_NAMES.stream(), RUNTIME_INIT_CLASS_NAMES.stream()) - .map(access::findClassByName) - .filter(Objects::nonNull) - .forEach(RuntimeClassInitialization::initializeAtRunTime); - } - } - - @Override - public void beforeAnalysis(BeforeAnalysisAccess access) { - Object[] createMethods = Arrays.stream(terminalFactoryClass.getDeclaredMethods()) - .filter(m -> Modifier.isStatic(m.getModifiers()) && m.getName().equals("create")) - .toArray(); - access.registerReachabilityHandler(JLineFeature::registerTerminalConstructor, createMethods); - - if (Platform.includedIn(Platform.WINDOWS.class)) { - /* - * Each listed class has a native method named "init" that initializes all declared - * fields of the class using JNI. So when the "init" method gets reachable (which means - * the class initializer got reachable), we need to register all fields for JNI access. - */ - JNI_CLASS_NAMES.stream() - .map(access::findClassByName) - .filter(Objects::nonNull) - .map(jniClass -> ReflectionUtil.lookupMethod(jniClass, "init")) - .forEach(initMethod -> access.registerReachabilityHandler(a -> registerJNIFields(initMethod), initMethod)); - } - } - - private static void registerTerminalConstructor(DuringAnalysisAccess access) { - /* - * TerminalFactory.create methods instantiate the actual Terminal implementation class via - * reflection. We cannot automatically constant fold which class is going to be used, so we - * register the default for each platform. If the user manually overrides the default - * implementation class, they also need to provide a reflection configuration for that - * class. - */ - Class terminalClass = access.findClassByName(Platform.includedIn(Platform.WINDOWS.class) ? "jline.AnsiWindowsTerminal" : "jline.UnixTerminal"); - if (terminalClass != null) { - RuntimeReflection.register(terminalClass); - RuntimeReflection.register(terminalClass.getDeclaredConstructors()); - } - } - - private AtomicBoolean resourceRegistered = new AtomicBoolean(); - - private void registerJNIFields(Method initMethod) { - Class jniClass = initMethod.getDeclaringClass(); - JNIRuntimeAccess.register(jniClass.getDeclaredFields()); - - if (!resourceRegistered.getAndSet(true)) { - /* The native library that is included as a resource in the .jar file. */ - String resource = "META-INF/native/windows64/jansi.dll"; - Resources.registerResource(resource, jniClass.getClassLoader().getResourceAsStream(resource)); - } - } -} From 3d16b0bf6827a321bd7723b5195252e0bc924fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Wed, 29 Sep 2021 09:31:31 +0200 Subject: [PATCH 215/681] Add to changelog --- substratevm/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/CHANGELOG.md b/substratevm/CHANGELOG.md index 5a799f92a3d2..5823faf69b22 100644 --- a/substratevm/CHANGELOG.md +++ b/substratevm/CHANGELOG.md @@ -5,5 +5,6 @@ This changelog summarizes major changes to Native Image, developed under the cod ## Version 22.0.0 * (GR-33930) Decouple HostedOptionParser setup from classpath/modulepath scanning (use ServiceLoader for collecting options). * (GR-33504) Implement --add-reads for native-image and fix --add-opens error handling. +* (GR-33983) Remove obsolete com.oracle.svm.thirdparty.jline.JLineFeature from substratevm:LIBRARY_SUPPORT. ## Version 21.3.0
 From 36a68415d6243438df93764f1fff51bee60c7b76 Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Wed, 29 Sep 2021 11:02:55 +0200 Subject: [PATCH 216/681] add member checks to invoke method commands in jdwp --- .../truffle/espresso/jdwp/impl/JDWP.java | 26 +++++++++++++++++++ .../espresso/runtime/JDWPContextImpl.java | 10 +++++++ 2 files changed, 36 insertions(+) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java index 818fc245701c..ba6a26c0d1c6 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java @@ -1075,6 +1075,22 @@ static CommandResult createReply(Packet packet, DebuggerController controller, D return new CommandResult(reply); } + // check that method is member of the class type or a super class + KlassRef declaringKlass = method.getDeclaringKlass(); + KlassRef checkedKlass = klass; + boolean isMember = false; + while (checkedKlass != null) { + if (checkedKlass == declaringKlass) { + isMember = true; + break; + } + checkedKlass = checkedKlass.getSuperClass(); + } + if (!isMember) { + reply.errorCode(ErrorCodes.INVALID_METHODID); + return new CommandResult(reply); + } + LOGGER.fine(() -> "trying to invoke static method: " + method.getNameAsString()); int arguments = input.readInt(); @@ -1257,6 +1273,11 @@ static CommandResult createReply(Packet packet, DebuggerController controller, D return new CommandResult(reply); } + if (method.getDeclaringKlass() != itf) { + reply.errorCode(ErrorCodes.INVALID_METHODID); + return new CommandResult(reply); + } + LOGGER.fine(() -> "trying to invoke interface method: " + method.getNameAsString()); int arguments = input.readInt(); @@ -1764,6 +1785,11 @@ static CommandResult createReply(Packet packet, DebuggerController controller, D return new CommandResult(reply); } + if (!context.isMemberOf(callee, method.getDeclaringKlass())) { + reply.errorCode(ErrorCodes.INVALID_METHODID); + return new CommandResult(reply); + } + LOGGER.fine("trying to invoke method: " + method.getNameAsString()); int invocationOptions = input.readInt(); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java index 63721330524f..5d9ad20ae91c 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java @@ -711,6 +711,16 @@ public Node getInstrumentableNode(RootNode rootNode) { return rootNode; } + @Override + public boolean isMemberOf(Object guestObject, KlassRef klass) { + if (guestObject instanceof StaticObject) { + StaticObject staticObject = (StaticObject) guestObject; + return klass.isAssignable(staticObject.getKlass()); + } else { + return false; + } + } + public void rerunclinit(ObjectKlass oldKlass) { classInitializerActions.add(new ReloadingAction(oldKlass)); } From 28422d89bc5bb5d76d697450fefc4711af6a1dec Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Wed, 29 Sep 2021 11:03:30 +0200 Subject: [PATCH 217/681] missing file from previous commit --- .../com/oracle/truffle/espresso/jdwp/api/JDWPContext.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java index bf50a832b036..e5f3aa2f2cb5 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java @@ -497,4 +497,12 @@ public interface JDWPContext { * @return the instrumentable delegate node */ Node getInstrumentableNode(RootNode rootNode); + + /** + * Tests if the guest object is a member of the klass. + * @param guestObject the guest object + * @param klass the class + * @return true is guest object is a member of the klass + */ + boolean isMemberOf(Object guestObject, KlassRef klass); } From b39703608a60c484f15b0853b577c745fad3a58a Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Wed, 29 Sep 2021 11:57:31 +0200 Subject: [PATCH 218/681] Handle recursion correctly for total samples and call tree depth. --- .../tools/profiler/impl/CPUSamplerCLI.java | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java index 372083b60e12..72219bb7706a 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java @@ -383,12 +383,12 @@ private static final class SamplingHistogram { this.showTiers = options.get(ShowTiers); this.samplePeriod = options.get(SAMPLE_PERIOD); this.samplesTaken = data.getSamples(); - Map perThreadSourceLocationPayloads = new HashMap<>(); + Map perThreadSourceLocationPayloads = new HashMap<>(); for (Thread thread : data.getThreadData().keySet()) { perThreadSourceLocationPayloads.put(thread, computeSourceLocationPayloads(data.getThreadData().get(thread))); } maybeSummarizeThreads(perThreadSourceLocationPayloads); - for (Map.Entry threadEntry : perThreadSourceLocationPayloads.entrySet()) { + for (Map.Entry threadEntry : perThreadSourceLocationPayloads.entrySet()) { histogram.put(threadEntry.getKey(), histogramEntries(threadEntry)); } sortedTiers = sortedArray(tiers); @@ -397,19 +397,21 @@ private static final class SamplingHistogram { this.format = titleAndFormat[1]; } - private ArrayList histogramEntries(Map.Entry threadEntry) { + private ArrayList histogramEntries(Map.Entry threadEntry) { ArrayList histogramEntries = new ArrayList<>(); - for (Map.Entry> sourceLocationEntry : threadEntry.getValue().locations.entrySet()) { + for (Map.Entry>> sourceLocationEntry : threadEntry.getValue().locations.entrySet()) { histogramEntries.add(histogramEntry(sourceLocationEntry)); } histogramEntries.sort((o1, o2) -> Integer.compare(o2.totalSelfSamples, o1.totalSelfSamples)); return histogramEntries; } - private OutputEntry histogramEntry(Map.Entry> sourceLocationEntry) { - OutputEntry outputEntry = new OutputEntry(sourceLocationEntry.getKey()); - maxNameLength = Math.max(maxNameLength, sourceLocationEntry.getKey().getRootName().length()); - for (CPUSampler.Payload payload : sourceLocationEntry.getValue()) { + private OutputEntry histogramEntry(Map.Entry>> sourceLocationEntry) { + SourceLocation location = sourceLocationEntry.getKey(); + OutputEntry outputEntry = new OutputEntry(location); + maxNameLength = Math.max(maxNameLength, location.getRootName().length()); + for (ProfilerNode node : sourceLocationEntry.getValue()) { + CPUSampler.Payload payload = node.getPayload(); for (int i = 0; i < payload.getNumberOfTiers(); i++) { int selfHitCountsValue = payload.getTierSelfCount(i); outputEntry.totalSelfSamples += selfHitCountsValue; @@ -420,7 +422,11 @@ private OutputEntry histogramEntry(Map.Entry node : sourceLocationEntry.getValue()) { + if (node.isRecursive()) { + continue; + } + CPUSampler.Payload payload = node.getPayload(); for (int i = 0; i < payload.getNumberOfTiers(); i++) { int hitCountsValue = payload.getTierTotalCount(i); outputEntry.totalSamples += hitCountsValue; @@ -434,11 +440,11 @@ private OutputEntry histogramEntry(Map.Entry perThreadSourceLocationPayloads) { + private void maybeSummarizeThreads(Map perThreadSourceLocationPayloads) { if (summariseThreads) { - SourceLocationPayloads summary = new SourceLocationPayloads(new HashMap<>()); - for (SourceLocationPayloads sourceLocationPayloads : perThreadSourceLocationPayloads.values()) { - for (Map.Entry> entry : sourceLocationPayloads.locations.entrySet()) { + SourceLocationNodes summary = new SourceLocationNodes(new HashMap<>()); + for (SourceLocationNodes sourceLocationNodes : perThreadSourceLocationPayloads.values()) { + for (Map.Entry>> entry : sourceLocationNodes.locations.entrySet()) { summary.locations.computeIfAbsent(entry.getKey(), s -> new ArrayList<>()).addAll(entry.getValue()); } } @@ -447,22 +453,16 @@ private void maybeSummarizeThreads(Map perThread } } - private static SourceLocationPayloads computeSourceLocationPayloads(Collection> profilerNodes) { - Map> histogram = new HashMap<>(); + private static SourceLocationNodes computeSourceLocationPayloads(Collection> profilerNodes) { + Map>> histogram = new HashMap<>(); computeSourceLocationPayloadsImpl(profilerNodes, histogram); - return new SourceLocationPayloads(histogram); + return new SourceLocationNodes(histogram); } - private static void computeSourceLocationPayloadsImpl(Collection> children, Map> histogram) { + private static void computeSourceLocationPayloadsImpl(Collection> children, Map>> histogram) { for (ProfilerNode treeNode : children) { - List nodes = histogram.computeIfAbsent(new SourceLocation(treeNode.getSourceSection(), treeNode.getRootName()), - new Function>() { - @Override - public List apply(SourceLocation s) { - return new ArrayList<>(); - } - }); - nodes.add(treeNode.getPayload()); + List> nodes = histogram.computeIfAbsent(new SourceLocation(treeNode.getSourceSection(), treeNode.getRootName()), s -> new ArrayList<>()); + nodes.add(treeNode); computeSourceLocationPayloadsImpl(treeNode.getChildren(), histogram); } } @@ -486,10 +486,10 @@ void print(PrintStream out) { } } - private static final class SourceLocationPayloads { - final Map> locations; + private static final class SourceLocationNodes { + final Map>> locations; - SourceLocationPayloads(Map> locations) { + SourceLocationNodes(Map>> locations) { this.locations = locations; } } @@ -601,7 +601,9 @@ private void calculateMaxValuesRec(ProfilerNode node, int de maxNameLength = Math.max(maxNameLength, node.getRootName().length() + depth); tiers.add(node.getPayload().getNumberOfTiers() - 1); for (ProfilerNode child : node.getChildren()) { - calculateMaxValuesRec(child, depth + 1); + if (!child.isRecursive()) { + calculateMaxValuesRec(child, depth + 1); + } } } From 7fbb7fa3fca884a36b46ea68c0f41a4a0c60ab30 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Wed, 29 Sep 2021 12:10:42 +0200 Subject: [PATCH 219/681] In CHA oracle, stop walking the parent hierarchy on null (parent of jlObject) --- .../analysis/hierarchy/DefaultClassHierarchyOracle.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java index 4c56c048f3ba..09cf21c0ab2c 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java @@ -50,7 +50,7 @@ public LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass) { @Override public void onClassInit(ObjectKlass newClass) { ObjectKlass currentParent = newClass.getSuperKlass(); - while (currentParent.getLeafTypeAssumption().getAssumption().isValid()) { + while (currentParent != null && currentParent.getLeafTypeAssumption().getAssumption().isValid()) { currentParent.getLeafTypeAssumption().getAssumption().invalidate(); currentParent = currentParent.getSuperKlass(); } From ad460e2804264f2def82164dba8d44e0950e5196 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 27 Sep 2021 13:56:32 +0200 Subject: [PATCH 220/681] Avoid createCallTarget() in GraalWasm. --- .../src/org/graalvm/wasm/test/WasmJsApiSuite.java | 13 ++++++------- .../src/org/graalvm/wasm/WasmInstantiator.java | 6 ++---- .../src/org/graalvm/wasm/WasmLanguage.java | 5 ++--- .../org/graalvm/wasm/predefined/BuiltinModule.java | 5 +---- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java index 8402ff021c44..80f2abe8dfdb 100644 --- a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java +++ b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java @@ -78,7 +78,6 @@ import org.graalvm.wasm.utils.Assert; import org.junit.Test; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; @@ -203,12 +202,12 @@ public void testInstantiateWithImportTable() throws IOException { }), }); WebAssembly.tableWrite(table, 0, new WasmFunctionInstance(context, null, - Truffle.getRuntime().createCallTarget(new RootNode(context.language()) { + new RootNode(context.language()) { @Override public Object execute(VirtualFrame frame) { return 210; } - }))); + }.getCallTarget())); final WasmInstance instance = moduleInstantiate(wasm, binaryWithTableImport, importObject); try { final Object callFirst = WebAssembly.instanceExport(instance, "callFirst"); @@ -355,12 +354,12 @@ public void testExportTableTwice() throws IOException, InterruptedException { final InteropLibrary lib = InteropLibrary.getUncached(); try { final Object f = new WasmFunctionInstance(context, null, - Truffle.getRuntime().createCallTarget(new RootNode(context.language()) { + new RootNode(context.language()) { @Override public Object execute(VirtualFrame frame) { return 42; } - })); + }.getCallTarget()); final Object writeTable = wasm.readMember("table_write"); final Object readTable = wasm.readMember("table_read"); final Object a = WebAssembly.instanceExport(instance, "a"); @@ -641,12 +640,12 @@ public void testTableInstanceOutOfBoundsSet() throws IOException { final WasmFunctionInstance functionInstance = new WasmFunctionInstance( null, null, - Truffle.getRuntime().createCallTarget(new RootNode(WasmContext.get(null).language()) { + new RootNode(WasmContext.get(null).language()) { @Override public Object execute(VirtualFrame frame) { return 42; } - })); + }.getCallTarget()); // We should be able to set element 1. try { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmInstantiator.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmInstantiator.java index 2c171ba0d913..0a0897b7a1f0 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmInstantiator.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmInstantiator.java @@ -42,7 +42,6 @@ package org.graalvm.wasm; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.Node; import org.graalvm.wasm.exception.Failure; @@ -61,7 +60,7 @@ import java.util.List; /** - * Creates wasm instances by converting parser nodes into truffle nodes. + * Creates wasm instances by converting parser nodes into Truffle nodes. */ public class WasmInstantiator { private static final int MIN_DEFAULT_STACK_SIZE = 1_000_000; @@ -145,8 +144,7 @@ private void instantiateCodeEntry(WasmInstance instance, CodeEntry codeEntry) { * nodes {@see TruffleRuntime#createDirectCallNode} during translation. */ WasmRootNode rootNode = new WasmRootNode(language, instance, wasmCodeEntry); - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); - instance.setTarget(codeEntry.getFunctionIndex(), callTarget); + instance.setTarget(codeEntry.getFunctionIndex(), rootNode.getCallTarget()); /* * Set the code entry local variables (which contain the parameters and the locals). */ diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmLanguage.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmLanguage.java index d3c4d7c6e947..e6c7b103dfa8 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmLanguage.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmLanguage.java @@ -48,7 +48,6 @@ import org.graalvm.wasm.memory.WasmMemory; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; @@ -83,12 +82,12 @@ protected CallTarget parse(ParsingRequest request) { final byte[] data = source.getBytes().toByteArray(); final WasmModule module = WasmContext.readModule(moduleName, data, null, source); final WasmInstance instance = context.readInstance(module); - return Truffle.getRuntime().createCallTarget(new RootNode(this) { + return new RootNode(this) { @Override public WasmInstance execute(VirtualFrame frame) { return instance; } - }); + }.getCallTarget(); } @Override diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/BuiltinModule.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/BuiltinModule.java index e20a5ecfcb60..ceaec515c2f5 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/BuiltinModule.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/BuiltinModule.java @@ -41,8 +41,6 @@ package org.graalvm.wasm.predefined; import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.RootNode; import org.graalvm.wasm.Assert; import org.graalvm.wasm.ReferenceTypes; @@ -99,8 +97,7 @@ protected void defineFunction(WasmInstance instance, String name, byte[] paramTy // since predefined modules have a relatively small size. final int typeIdx = instance.symbolTable().allocateFunctionType(paramTypes, retTypes); final WasmFunction function = instance.symbolTable().declareExportedFunction(typeIdx, name); - RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); - instance.setTarget(function.index(), callTarget); + instance.setTarget(function.index(), rootNode.getCallTarget()); } protected int defineExternalGlobal(WasmInstance instance, String globalName, WasmGlobal global) { From 3d62974abf247ca95d331e4ee27d7ee885a9daef Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Wed, 29 Sep 2021 15:58:22 +0200 Subject: [PATCH 221/681] Docuement why we are using unsafeCast --- .../staticobject/ArrayBasedStaticShape.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java b/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java index 3c6cde4010af..a240bf156881 100644 --- a/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java +++ b/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java @@ -94,11 +94,33 @@ Object getStorage(Object obj, boolean primitive) { } else { assert checkShape(receiverObject); } + /* + * The safety of the unsafeCasts below is based on the fact that those 2 fields are final, + * initialized in the constructor: + * + * * the object array is exactly an Object[] (see + * ArrayBasedShapeGenerator.addStorageConstructors) + * + * * the byte[] is exact because there are no byte[] subclasses + * + * * the fields are final (see ArrayBasedShapeGenerator.generateStorage) + * + * * Any access of these fields after the constructor must remain after the final fields are + * stored (because of the barrier at the end of the constructor for final fields) and thus + * must see the initialized, non-null array of the correct type. + * + * * This getStorage access is not reachable inside the constructor (see the code of the + * constructor). + */ if (primitive) { Object storage = UNSAFE.getObject(receiverObject, (long) propertyLayout.generator.getByteArrayOffset()); + assert storage != null; + assert storage.getClass() == byte[].class; return SomAccessor.RUNTIME.unsafeCast(storage, byte[].class, true, true, true); } else { Object storage = UNSAFE.getObject(receiverObject, (long) propertyLayout.generator.getObjectArrayOffset()); + assert storage != null; + assert storage.getClass() == Object[].class; return SomAccessor.RUNTIME.unsafeCast(storage, Object[].class, true, true, true); } } From d3a4fefc1e90f0fcc78128f59b73b503a493fc2d Mon Sep 17 00:00:00 2001 From: Florian Huemer Date: Fri, 13 Aug 2021 10:17:05 +0200 Subject: [PATCH 222/681] Implemented Non-trapping Float-to-Int Conversion. --- wasm/ci_common/common.jsonnet | 2 +- .../org/graalvm/wasm/test/WasmFileSuite.java | 7 ++ .../graalvm/wasm/test/WasmTestProperties.java | 54 ++++++++ .../suites/arithmetic/Integer32Suite.java | 58 ++++++++- .../suites/arithmetic/Integer64Suite.java | 54 +++++++- .../src/org/graalvm/wasm/BinaryParser.java | 45 ++++++- .../src/org/graalvm/wasm/WasmContext.java | 12 +- .../org/graalvm/wasm/WasmContextOptions.java | 97 +++++++++++++++ .../src/org/graalvm/wasm/WasmLanguage.java | 2 +- .../src/org/graalvm/wasm/WasmOptions.java | 5 + .../graalvm/wasm/constants/Instructions.java | 11 ++ .../org/graalvm/wasm/nodes/WasmBlockNode.java | 115 ++++++++++++++++++ 12 files changed, 454 insertions(+), 8 deletions(-) create mode 100644 wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmTestProperties.java create mode 100644 wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContextOptions.java diff --git a/wasm/ci_common/common.jsonnet b/wasm/ci_common/common.jsonnet index 6a6123217c50..6204bb4cb8da 100644 --- a/wasm/ci_common/common.jsonnet +++ b/wasm/ci_common/common.jsonnet @@ -93,7 +93,7 @@ local graal_suite_root = root_ci.graal_suite_root; wabt: { downloads+: { - WABT_DIR: {name: 'wabt', version: '1.0.12', platformspecific: true}, + WABT_DIR: {name: 'wabt', version: '1.0.23', platformspecific: true}, }, }, diff --git a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmFileSuite.java b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmFileSuite.java index eb25c99a8ffa..67d19d5f0739 100644 --- a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmFileSuite.java +++ b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmFileSuite.java @@ -51,6 +51,7 @@ import org.graalvm.wasm.WasmContext; import org.graalvm.wasm.WasmFunctionInstance; import org.graalvm.wasm.WasmInstance; +import org.graalvm.wasm.WasmOptions; import org.graalvm.wasm.WasmLanguage; import org.graalvm.wasm.memory.WasmMemory; import org.graalvm.wasm.test.options.WasmTestOptions; @@ -296,6 +297,12 @@ private WasmTestStatus runTestCase(WasmCase testCase) { contextBuilder.arguments(WasmLanguage.ID, prepend(commandLineArgs.split(" "), "")); } + final String saturatingFloatToIntProperty = "wasm." + WasmOptions.SATURATING_FLOAT_TO_INT_NAME; + final String saturatingFloatToIntValue = testCase.options().getProperty(saturatingFloatToIntProperty); + if (saturatingFloatToIntValue != null) { + contextBuilder.option(saturatingFloatToIntProperty, saturatingFloatToIntValue); + } + final String envString = testCase.options().getProperty("env"); if (envString != null) { for (String var : envString.split(" ")) { diff --git a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmTestProperties.java b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmTestProperties.java new file mode 100644 index 000000000000..f715f6ebd55b --- /dev/null +++ b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmTestProperties.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.graalvm.wasm.test; + +import java.util.Properties; + +public class WasmTestProperties { + public static Properties create(String... properties) { + Properties p = new Properties(); + for (String property : properties) { + p.setProperty(property, "true"); + } + return p; + } +} diff --git a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/arithmetic/Integer32Suite.java b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/arithmetic/Integer32Suite.java index 0659a782e89d..b0e81a2acea0 100644 --- a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/arithmetic/Integer32Suite.java +++ b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/arithmetic/Integer32Suite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -43,7 +43,9 @@ import java.io.IOException; import java.util.Arrays; import java.util.Collection; +import java.util.Properties; +import org.graalvm.wasm.test.WasmTestProperties; import org.graalvm.wasm.utils.cases.WasmCase; import org.graalvm.wasm.utils.cases.WasmStringCase; import org.junit.Test; @@ -51,6 +53,8 @@ import org.graalvm.wasm.test.WasmFileSuite; public class Integer32Suite extends WasmFileSuite { + private final Properties saturatingFloatToIntProperties = WasmTestProperties.create("wasm.saturating-float-to-int"); + private WasmStringCase[] testCases = { WasmCase.create("CONST_SMALL", WasmCase.expected(42), "(module (func (export \"_main\") (result i32) i32.const 42))"), @@ -176,6 +180,58 @@ public class Integer32Suite extends WasmFileSuite { "(module (func (export \"_main\") (result i32) i32.const -3 i32.const 1 i32.rotr))"), WasmCase.create("WRAP_I64", WasmCase.expected(-1794634296), "(module (func (export \"_main\") (result i32) i64.const 2500333000 i32.wrap_i64))"), + WasmCase.create("TRUNC_SAT_F32_S_NAN", WasmCase.expected(0), + "(module (func (export \"_main\") (result i32) f32.const nan i32.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_INF", WasmCase.expected(Integer.MAX_VALUE), + "(module (func (export \"_main\") (result i32) f32.const inf i32.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_NEG_INF", WasmCase.expected(Integer.MIN_VALUE), + "(module (func (export \"_main\") (result i32) f32.const inf f32.neg i32.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_OVERFLOW", WasmCase.expected(Integer.MAX_VALUE), + "(module (func (export \"_main\") (result i32) f32.const 3.4028235E38 i32.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_UNDERFLOW", WasmCase.expected(Integer.MIN_VALUE), + "(module (func (export \"_main\") (result i32) f32.const -3.4028235E38 i32.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_VALID", WasmCase.expected(1), + "(module (func (export \"_main\") (result i32) f32.const 1.532 i32.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_NAN", WasmCase.expected(0), + "(module (func (export \"_main\") (result i32) f32.const nan i32.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_INF", WasmCase.expected(0xffff_ffff), + "(module (func (export \"_main\") (result i32) f32.const inf i32.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_NEG_INF", WasmCase.expected(0), + "(module (func (export \"_main\") (result i32) f32.const inf f32.neg i32.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_OVERFLOW", WasmCase.expected(0xffff_ffff), + "(module (func (export \"_main\") (result i32) f32.const 3.4028235E38 i32.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_INT_OVERFLOW", WasmCase.expected(0xffff_ffff), + "(module (func (export \"_main\") (result i32) f32.const 4.294967296E9 i32.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_NEG", WasmCase.expected(0), + "(module (func (export \"_main\") (result i32) f32.const -1.235 i32.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_VALID", WasmCase.expected(1), + "(module (func (export \"_main\") (result i32) f32.const 1.532 i32.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_NAN", WasmCase.expected(0), + "(module (func (export \"_main\") (result i32) f64.const nan i32.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_INF", WasmCase.expected(Integer.MAX_VALUE), + "(module (func (export \"_main\") (result i32) f64.const inf i32.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_NEG_INF", WasmCase.expected(Integer.MIN_VALUE), + "(module (func (export \"_main\") (result i32) f64.const inf f64.neg i32.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_OVERFLOW", WasmCase.expected(Integer.MAX_VALUE), + "(module (func (export \"_main\") (result i32) f64.const 1.79769E308 i32.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_UNDERFLOW", WasmCase.expected(Integer.MIN_VALUE), + "(module (func (export \"_main\") (result i32) f64.const -1.79769E308 i32.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_VALID", WasmCase.expected(1), + "(module (func (export \"_main\") (result i32) f64.const 1.532 i32.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_NAN", WasmCase.expected(0), + "(module (func (export \"_main\") (result i32) f64.const nan i32.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_INF", WasmCase.expected(0xffff_ffff), + "(module (func (export \"_main\") (result i32) f64.const inf i32.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_NEG_INF", WasmCase.expected(0), + "(module (func (export \"_main\") (result i32) f64.const inf f64.neg i32.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_OVERFLOW", WasmCase.expected(0xffff_ffff), + "(module (func (export \"_main\") (result i32) f64.const 1.7976931348623157E308 i32.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_INT_OVERFLOW", WasmCase.expected(0xffff_ffff), + "(module (func (export \"_main\") (result i32) f64.const 4.294967296E9 i32.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_NEG", WasmCase.expected(0), + "(module (func (export \"_main\") (result i32) f64.const -1.235 i32.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_VALID", WasmCase.expected(1), + "(module (func (export \"_main\") (result i32) f64.const 1.532 i32.trunc_sat_f64_u))", saturatingFloatToIntProperties), }; @Override diff --git a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/arithmetic/Integer64Suite.java b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/arithmetic/Integer64Suite.java index fa039070bea0..0dca848cce5b 100644 --- a/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/arithmetic/Integer64Suite.java +++ b/wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/arithmetic/Integer64Suite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -43,7 +43,9 @@ import java.io.IOException; import java.util.Arrays; import java.util.Collection; +import java.util.Properties; +import org.graalvm.wasm.test.WasmTestProperties; import org.graalvm.wasm.utils.cases.WasmCase; import org.graalvm.wasm.utils.cases.WasmStringCase; import org.junit.Test; @@ -51,6 +53,8 @@ import org.graalvm.wasm.test.WasmFileSuite; public class Integer64Suite extends WasmFileSuite { + private final Properties saturatingFloatToIntProperties = WasmTestProperties.create("wasm.saturating-float-to-int"); + private WasmStringCase[] testCases = { WasmCase.create("CONST_SMALL", WasmCase.expected(42L), "(module (func (export \"_main\") (result i64) i64.const 42))"), @@ -176,6 +180,54 @@ public class Integer64Suite extends WasmFileSuite { "(module (func (export \"_main\") (result i64) i64.const -2 i64.const 1 i64.rotl))"), WasmCase.create("ROTATE_RIGHT", WasmCase.expected(-2L), "(module (func (export \"_main\") (result i64) i64.const -3 i64.const 1 i64.rotr))"), + WasmCase.create("TRUNC_SAT_F32_S_NAN", WasmCase.expected(0L), + "(module (func (export \"_main\") (result i64) f32.const nan i64.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_INF", WasmCase.expected(Long.MAX_VALUE), + "(module (func (export \"_main\") (result i64) f32.const inf i64.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_NEG_INF", WasmCase.expected(Long.MIN_VALUE), + "(module (func (export \"_main\") (result i64) f32.const inf f32.neg i64.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_OVERFLOW", WasmCase.expected(Long.MAX_VALUE), + "(module (func (export \"_main\") (result i64) f32.const 3.4028235E38 i64.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_UNDERFLOW", WasmCase.expected(Long.MIN_VALUE), + "(module (func (export \"_main\") (result i64) f32.const -3.4028235E38 i64.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_S_VALID", WasmCase.expected(1L), + "(module (func (export \"_main\") (result i64) f32.const 1.532 i64.trunc_sat_f32_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_NAN", WasmCase.expected(0L), + "(module (func (export \"_main\") (result i64) f32.const nan i64.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_INF", WasmCase.expected(0xffff_ffff_ffff_ffffL), + "(module (func (export \"_main\") (result i64) f32.const inf i64.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_NEG_INF", WasmCase.expected(0L), + "(module (func (export \"_main\") (result i64) f32.const inf f32.neg i64.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_OVERFLOW", WasmCase.expected(0xffff_ffff_ffff_ffffL), + "(module (func (export \"_main\") (result i64) f32.const 3.4028235E38 i64.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_NEG", WasmCase.expected(0L), + "(module (func (export \"_main\") (result i64) f32.const -1.235 i64.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F32_U_VALID", WasmCase.expected(1L), + "(module (func (export \"_main\") (result i64) f32.const 1.532 i64.trunc_sat_f32_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_NAN", WasmCase.expected(0L), + "(module (func (export \"_main\") (result i64) f64.const nan i64.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_INF", WasmCase.expected(Long.MAX_VALUE), + "(module (func (export \"_main\") (result i64) f64.const inf i64.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_NEG_INF", WasmCase.expected(Long.MIN_VALUE), + "(module (func (export \"_main\") (result i64) f64.const inf f64.neg i64.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_OVERFLOW", WasmCase.expected(Long.MAX_VALUE), + "(module (func (export \"_main\") (result i64) f64.const 1.79769E308 i64.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_UNDERFLOW", WasmCase.expected(Long.MIN_VALUE), + "(module (func (export \"_main\") (result i64) f64.const -1.79769E308 i64.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_S_VALID", WasmCase.expected(1L), + "(module (func (export \"_main\") (result i64) f64.const 1.532 i64.trunc_sat_f64_s))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_NAN", WasmCase.expected(0L), + "(module (func (export \"_main\") (result i64) f64.const nan i64.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_INF", WasmCase.expected(0xffff_ffff_ffff_ffffL), + "(module (func (export \"_main\") (result i64) f64.const inf i64.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_NEG_INF", WasmCase.expected(0L), + "(module (func (export \"_main\") (result i64) f64.const inf f64.neg i64.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_OVERFLOW", WasmCase.expected(0xffff_ffff_ffff_ffffL), + "(module (func (export \"_main\") (result i64) f64.const 1.7976931348623157E308 i64.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_NEG", WasmCase.expected(0L), + "(module (func (export \"_main\") (result i64) f64.const -1.235 i64.trunc_sat_f64_u))", saturatingFloatToIntProperties), + WasmCase.create("TRUNC_SAT_F64_U_VALID", WasmCase.expected(1L), + "(module (func (export \"_main\") (result i64) f64.const 1.532 i64.trunc_sat_f64_u))", saturatingFloatToIntProperties), }; @Override diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/BinaryParser.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/BinaryParser.java index b4fc18b94951..a07bd9d1711c 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/BinaryParser.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/BinaryParser.java @@ -95,12 +95,14 @@ public class BinaryParser extends BinaryStreamParser { private static final int VERSION = 0x00000001; private final WasmModule module; + private final WasmContext wasmContext; private final int[] limitsResult; @CompilerDirectives.TruffleBoundary - public BinaryParser(WasmModule module) { + public BinaryParser(WasmModule module, WasmContext context) { super(module.data()); this.module = module; + this.wasmContext = context; this.limitsResult = new int[2]; } @@ -961,12 +963,53 @@ private void readNumericInstructions(ValidationState state, int opcode) { state.popChecked(I64_TYPE); state.push(F64_TYPE); break; + case Instructions.MISC: + int miscOpcode = read1() & 0xFF; + switch (miscOpcode) { + case Instructions.I32_TRUNC_SAT_F32_S: + case Instructions.I32_TRUNC_SAT_F32_U: + checkSaturatingFloatToIntSupport(miscOpcode); + state.popChecked(F32_TYPE); + state.push(I32_TYPE); + break; + case Instructions.I32_TRUNC_SAT_F64_S: + case Instructions.I32_TRUNC_SAT_F64_U: + checkSaturatingFloatToIntSupport(miscOpcode); + state.popChecked(F64_TYPE); + state.push(I32_TYPE); + break; + case Instructions.I64_TRUNC_SAT_F32_S: + case Instructions.I64_TRUNC_SAT_F32_U: + checkSaturatingFloatToIntSupport(miscOpcode); + state.popChecked(F32_TYPE); + state.push(I64_TYPE); + break; + case Instructions.I64_TRUNC_SAT_F64_S: + case Instructions.I64_TRUNC_SAT_F64_U: + checkSaturatingFloatToIntSupport(miscOpcode); + state.popChecked(F64_TYPE); + state.push(I64_TYPE); + break; + default: + fail(Failure.UNSPECIFIED_MALFORMED, "Unknown opcode: 0xFC 0x%02x", miscOpcode); + } + break; default: fail(Failure.UNSPECIFIED_MALFORMED, "Unknown opcode: 0x%02x", opcode); break; } } + private static void checkContextOption(boolean option, String message, Object... args) { + if (!option) { + fail(Failure.UNSPECIFIED_MALFORMED, message, args); + } + } + + private void checkSaturatingFloatToIntSupport(int opcode) { + checkContextOption(wasmContext.getContextOptions().isSaturatingFloatToInt(), "Saturating float-to-int conversion is not enabled (opcode: 0xFC 0x%02x)", opcode); + } + private void store(ValidationState state, byte type, int n) { assertTrue(module.symbolTable().memoryExists(), Failure.UNKNOWN_MEMORY); diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContext.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContext.java index b47d3c16cc58..1c8d61e777bc 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContext.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContext.java @@ -67,6 +67,7 @@ public final class WasmContext { private final Map moduleInstances; private int moduleNameCount; private final FdManager filesManager; + private final WasmContextOptions contextOptions; public WasmContext(Env env, WasmLanguage language) { this.env = env; @@ -80,6 +81,7 @@ public WasmContext(Env env, WasmLanguage language) { this.linker = new Linker(); this.moduleNameCount = 0; this.filesManager = new FdManager(env); + this.contextOptions = WasmContextOptions.fromOptionValues(env.getOptions()); instantiateBuiltinInstances(); } @@ -167,9 +169,9 @@ public WasmModule readModule(byte[] data, ModuleLimits moduleLimits) { return readModule(moduleName, data, moduleLimits, source); } - public static WasmModule readModule(String moduleName, byte[] data, ModuleLimits moduleLimits, Source source) { + public WasmModule readModule(String moduleName, byte[] data, ModuleLimits moduleLimits, Source source) { final WasmModule module = WasmModule.create(moduleName, data, moduleLimits, source); - final BinaryParser reader = new BinaryParser(module); + final BinaryParser reader = new BinaryParser(module, this); reader.readModule(); return module; } @@ -188,7 +190,7 @@ public void reinitInstance(WasmInstance instance, boolean reinitMemory) { // Note: this is not a complete and correct instantiation as defined in // https://webassembly.github.io/spec/core/exec/modules.html#instantiation // For testing only. - final BinaryParser reader = new BinaryParser(instance.module()); + final BinaryParser reader = new BinaryParser(instance.module(), this); reader.resetGlobalState(this, instance); if (reinitMemory) { reader.resetMemoryState(this, instance); @@ -200,6 +202,10 @@ public void reinitInstance(WasmInstance instance, boolean reinitMemory) { } } + public WasmContextOptions getContextOptions() { + return this.contextOptions; + } + private static final ContextReference REFERENCE = ContextReference.create(WasmLanguage.class); public static WasmContext get(Node node) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContextOptions.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContextOptions.java new file mode 100644 index 000000000000..73aeb506e864 --- /dev/null +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContextOptions.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.graalvm.wasm; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import org.graalvm.options.OptionKey; +import org.graalvm.options.OptionValues; + +public class WasmContextOptions { + @CompilationFinal private boolean saturatingFloatToInt; + @CompilationFinal private OptionValues optionValues; + + WasmContextOptions(OptionValues optionValues) { + this.optionValues = optionValues; + setOptionValues(); + } + + public static WasmContextOptions fromOptionValues(OptionValues optionValues) { + return new WasmContextOptions(optionValues); + } + + private void setOptionValues() { + this.saturatingFloatToInt = readBooleanOption(WasmOptions.SATURATING_FLOAT_TO_INT); + } + + private boolean readBooleanOption(OptionKey key) { + return key.getValue(optionValues); + } + + public boolean isSaturatingFloatToInt() { + return saturatingFloatToInt; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 53 * hash + (this.saturatingFloatToInt ? 1 : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final WasmContextOptions other = (WasmContextOptions) obj; + if (this.saturatingFloatToInt != other.saturatingFloatToInt) { + return false; + } + return true; + } +} diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmLanguage.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmLanguage.java index d3c4d7c6e947..2f3aebf820cc 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmLanguage.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmLanguage.java @@ -81,7 +81,7 @@ protected CallTarget parse(ParsingRequest request) { isFirst = false; final Source source = request.getSource(); final byte[] data = source.getBytes().toByteArray(); - final WasmModule module = WasmContext.readModule(moduleName, data, null, source); + final WasmModule module = context.readModule(moduleName, data, null, source); final WasmInstance instance = context.readInstance(module); return Truffle.getRuntime().createCallTarget(new RootNode(this) { @Override diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java index 3b04481485b5..3dd29f28f6c1 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java @@ -73,4 +73,9 @@ public enum ConstantsStorePolicy { @Option(help = "Use sun.misc.Unsafe-based memory.", category = OptionCategory.EXPERT, stability = OptionStability.EXPERIMENTAL)// public static final OptionKey UseUnsafeMemory = new OptionKey<>(false); + + // WASM Context Options + public static final String SATURATING_FLOAT_TO_INT_NAME = "saturating-float-to-int"; + @Option(name = SATURATING_FLOAT_TO_INT_NAME, help = "Use saturating-float-to-int conversion", category = OptionCategory.EXPERT, stability = OptionStability.EXPERIMENTAL) // + public static final OptionKey SATURATING_FLOAT_TO_INT = new OptionKey<>(false); } diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/constants/Instructions.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/constants/Instructions.java index d8ef39e6e350..8883f0e582de 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/constants/Instructions.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/constants/Instructions.java @@ -235,6 +235,17 @@ public final class Instructions { public static final int F32_REINTERPRET_I32 = 0xBE; public static final int F64_REINTERPRET_I64 = 0xBF; + public static final int MISC = 0xFC; + + public static final int I32_TRUNC_SAT_F32_S = 0x00; + public static final int I32_TRUNC_SAT_F32_U = 0x01; + public static final int I32_TRUNC_SAT_F64_S = 0x02; + public static final int I32_TRUNC_SAT_F64_U = 0x03; + public static final int I64_TRUNC_SAT_F32_S = 0x04; + public static final int I64_TRUNC_SAT_F32_U = 0x05; + public static final int I64_TRUNC_SAT_F64_S = 0x06; + public static final int I64_TRUNC_SAT_F64_U = 0x07; + private static String[] decodingTable = new String[256]; private Instructions() { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/nodes/WasmBlockNode.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/nodes/WasmBlockNode.java index 8f140d01b5e4..f71ef9484848 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/nodes/WasmBlockNode.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/nodes/WasmBlockNode.java @@ -153,6 +153,10 @@ import static org.graalvm.wasm.constants.Instructions.I32_TRUNC_F32_U; import static org.graalvm.wasm.constants.Instructions.I32_TRUNC_F64_S; import static org.graalvm.wasm.constants.Instructions.I32_TRUNC_F64_U; +import static org.graalvm.wasm.constants.Instructions.I32_TRUNC_SAT_F32_S; +import static org.graalvm.wasm.constants.Instructions.I32_TRUNC_SAT_F32_U; +import static org.graalvm.wasm.constants.Instructions.I32_TRUNC_SAT_F64_S; +import static org.graalvm.wasm.constants.Instructions.I32_TRUNC_SAT_F64_U; import static org.graalvm.wasm.constants.Instructions.I32_WRAP_I64; import static org.graalvm.wasm.constants.Instructions.I32_XOR; import static org.graalvm.wasm.constants.Instructions.I64_ADD; @@ -202,6 +206,10 @@ import static org.graalvm.wasm.constants.Instructions.I64_TRUNC_F32_U; import static org.graalvm.wasm.constants.Instructions.I64_TRUNC_F64_S; import static org.graalvm.wasm.constants.Instructions.I64_TRUNC_F64_U; +import static org.graalvm.wasm.constants.Instructions.I64_TRUNC_SAT_F32_S; +import static org.graalvm.wasm.constants.Instructions.I64_TRUNC_SAT_F32_U; +import static org.graalvm.wasm.constants.Instructions.I64_TRUNC_SAT_F64_S; +import static org.graalvm.wasm.constants.Instructions.I64_TRUNC_SAT_F64_U; import static org.graalvm.wasm.constants.Instructions.I64_XOR; import static org.graalvm.wasm.constants.Instructions.IF; import static org.graalvm.wasm.constants.Instructions.LOCAL_GET; @@ -210,6 +218,7 @@ import static org.graalvm.wasm.constants.Instructions.LOOP; import static org.graalvm.wasm.constants.Instructions.MEMORY_GROW; import static org.graalvm.wasm.constants.Instructions.MEMORY_SIZE; +import static org.graalvm.wasm.constants.Instructions.MISC; import static org.graalvm.wasm.constants.Instructions.NOP; import static org.graalvm.wasm.constants.Instructions.RETURN; import static org.graalvm.wasm.constants.Instructions.SELECT; @@ -1398,6 +1407,40 @@ public int execute(WasmContext context, VirtualFrame frame, long[] stacklocals) // and interpreted appropriately upon access), we don't need to do anything // for these instructions. break; + case MISC: + byte miscByteOpcode = BinaryStreamParser.rawPeek1(data, offset); + int miscOpcode = miscByteOpcode & 0xFF; + offset++; + CompilerAsserts.partialEvaluationConstant(offset); + switch (miscOpcode) { + case I32_TRUNC_SAT_F32_S: + i32_trunc_sat_f32_s(stacklocals, stackPointer); + break; + case I32_TRUNC_SAT_F32_U: + i32_trunc_sat_f32_u(stacklocals, stackPointer); + break; + case I32_TRUNC_SAT_F64_S: + i32_trunc_sat_f64_s(stacklocals, stackPointer); + break; + case I32_TRUNC_SAT_F64_U: + i32_trunc_sat_f64_u(stacklocals, stackPointer); + break; + case I64_TRUNC_SAT_F32_S: + i64_trunc_sat_f32_s(stacklocals, stackPointer); + break; + case I64_TRUNC_SAT_F32_U: + i64_trunc_sat_f32_u(stacklocals, stackPointer); + break; + case I64_TRUNC_SAT_F64_S: + i64_trunc_sat_f64_s(stacklocals, stackPointer); + break; + case I64_TRUNC_SAT_F64_U: + i64_trunc_sat_f64_u(stacklocals, stackPointer); + break; + default: + throw CompilerDirectives.shouldNotReachHere(); + } + break; default: throw CompilerDirectives.shouldNotReachHere(); } @@ -2772,6 +2815,44 @@ private void i32_trunc_f64_u(long[] stack, int stackPointer) { pushInt(stack, stackPointer - 1, result); } + private void i32_trunc_sat_f32_s(long[] stack, int stackPointer) { + final float x = popAsFloat(stack, stackPointer - 1); + final int result = (int) ExactMath.truncate(x); + pushInt(stack, stackPointer - 1, result); + } + + private void i32_trunc_sat_f32_u(long[] stack, int stackPointer) { + final float x = popAsFloat(stack, stackPointer - 1); + final int result; + if (Float.isNaN(x) || x < MIN_FLOAT_TRUNCATABLE_TO_U_INT) { + result = 0; + } else if (x > MAX_FLOAT_TRUNCATABLE_TO_U_INT) { + result = 0xffff_ffff; + } else { + result = (int) WasmMath.truncFloatToUnsignedLong(x); + } + pushInt(stack, stackPointer - 1, result); + } + + private void i32_trunc_sat_f64_s(long[] stack, int stackPointer) { + final double x = popAsDouble(stack, stackPointer - 1); + final int result = (int) ExactMath.truncate(x); + pushInt(stack, stackPointer - 1, result); + } + + private void i32_trunc_sat_f64_u(long[] stack, int stackPointer) { + final double x = popAsDouble(stack, stackPointer - 1); + final int result; + if (Double.isNaN(x) || x < MIN_DOUBLE_TRUNCATABLE_TO_U_INT) { + result = 0; + } else if (x > MAX_DOUBLE_TRUNCATABLE_TO_U_INT) { + result = 0xffff_ffff; + } else { + result = (int) WasmMath.truncDoubleToUnsignedLong(x); + } + pushInt(stack, stackPointer - 1, result); + } + private void i64_extend_i32_s(long[] stack, int stackPointer) { int x = popInt(stack, stackPointer - 1); long result = x; @@ -2836,6 +2917,40 @@ private void i64_trunc_f64_u(long[] stack, int stackPointer) { push(stack, stackPointer - 1, result); } + private void i64_trunc_sat_f32_s(long[] stack, int stackPointer) { + final float x = popAsFloat(stack, stackPointer - 1); + final long result = (long) ExactMath.truncate(x); + push(stack, stackPointer - 1, result); + } + + private void i64_trunc_sat_f32_u(long[] stack, int stackPointer) { + final float x = popAsFloat(stack, stackPointer - 1); + final long result; + if (Float.isNaN(x) || x < MIN_FLOAT_TRUNCATABLE_TO_U_LONG) { + result = 0; + } else { + result = WasmMath.truncFloatToUnsignedLong(x); + } + push(stack, stackPointer - 1, result); + } + + private void i64_trunc_sat_f64_s(long[] stack, int stackPointer) { + final double x = popAsDouble(stack, stackPointer - 1); + final long result = (long) ExactMath.truncate(x); + push(stack, stackPointer - 1, result); + } + + private void i64_trunc_sat_f64_u(long[] stack, int stackPointer) { + final double x = popAsDouble(stack, stackPointer - 1); + final long result; + if (Double.isNaN(x) || x < MIN_DOUBLE_TRUNCATABLE_TO_U_LONG) { + result = 0; + } else { + result = WasmMath.truncDoubleToUnsignedLong(x); + } + push(stack, stackPointer - 1, result); + } + private void f32_convert_i32_s(long[] stack, int stackPointer) { final int x = popInt(stack, stackPointer - 1); final float result = x; From 77886d9c3b893de8002bd1137e29de2080343ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Wed, 29 Sep 2021 18:45:14 +0200 Subject: [PATCH 223/681] Build native-image with -H:+UseReferenceHandlerThread to ensure synchronized (files) blocks in ZipFile.Source#release and ZipFile.Source#get are indeed mutually exclusive. --- .../com.oracle.substratevm/svm-driver/native-image.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.driver/resources/META-INF/native-image/com.oracle.substratevm/svm-driver/native-image.properties b/substratevm/src/com.oracle.svm.driver/resources/META-INF/native-image/com.oracle.substratevm/svm-driver/native-image.properties index a3883325fe9c..f9acfcc2f4c8 100644 --- a/substratevm/src/com.oracle.svm.driver/resources/META-INF/native-image/com.oracle.substratevm/svm-driver/native-image.properties +++ b/substratevm/src/com.oracle.svm.driver/resources/META-INF/native-image/com.oracle.substratevm/svm-driver/native-image.properties @@ -1,2 +1,2 @@ ImageName = native-image -Args = -H:-ParseRuntimeOptions --initialize-at-build-time=com.oracle.svm.driver +Args = -H:+UseReferenceHandlerThread -H:-ParseRuntimeOptions --initialize-at-build-time=com.oracle.svm.driver From 94966712ee286f5a799edb2463a8e62483a2bbe3 Mon Sep 17 00:00:00 2001 From: Jirka Marsik Date: Tue, 31 Aug 2021 15:01:30 +0200 Subject: [PATCH 224/681] Update TRegex's Unicode data to current draft of version 14 --- .../charset/UnicodeGeneralCategories.java | 432 +-- .../regex/charset/UnicodePropertyData.java | 2444 +++++++++-------- .../regex/tregex/parser/CaseFoldTable.java | 51 +- .../parser/flavors/RubyCaseFoldingData.java | 40 + .../tools/run_scripts.sh | 2 +- 5 files changed, 1583 insertions(+), 1386 deletions(-) diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodeGeneralCategories.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodeGeneralCategories.java index 07e0ecfedea2..543aba39e64a 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodeGeneralCategories.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodeGeneralCategories.java @@ -62,52 +62,53 @@ static CodePointSet getGeneralCategory(String name) { 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002119, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x00212d, 0x00212f, 0x002134, 0x002139, 0x002139, 0x00213c, 0x00213f, - 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002183, 0x002184, 0x002c00, 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002c7b, 0x002c7e, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, - 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x00a640, 0x00a66d, 0x00a680, 0x00a69b, 0x00a722, 0x00a76f, 0x00a771, 0x00a787, 0x00a78b, 0x00a78e, - 0x00a790, 0x00a7bf, 0x00a7c2, 0x00a7ca, 0x00a7f5, 0x00a7f6, 0x00a7fa, 0x00a7fa, 0x00ab30, 0x00ab5a, 0x00ab60, 0x00ab68, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, - 0x00fb17, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, 0x010400, 0x01044f, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x0118a0, 0x0118df, - 0x016e40, 0x016e7f, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, - 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, - 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, - 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01e900, 0x01e943)); + 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002183, 0x002184, 0x002c00, 0x002c7b, 0x002c7e, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, + 0x002d27, 0x002d2d, 0x002d2d, 0x00a640, 0x00a66d, 0x00a680, 0x00a69b, 0x00a722, 0x00a76f, 0x00a771, 0x00a787, 0x00a78b, 0x00a78e, 0x00a790, 0x00a7ca, 0x00a7d0, 0x00a7d1, + 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, 0x00a7f5, 0x00a7f6, 0x00a7fa, 0x00a7fa, 0x00ab30, 0x00ab5a, 0x00ab60, 0x00ab68, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, + 0x00fb17, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, 0x010400, 0x01044f, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, + 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x0118a0, 0x0118df, 0x016e40, + 0x016e7f, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, + 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, + 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, + 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01df00, 0x01df09, 0x01df0b, 0x01df1e, 0x01e900, 0x01e943)); GENERAL_CATEGORIES.put("gc=L", CodePointSet.createNoDedup(0x000041, 0x00005a, 0x000061, 0x00007a, 0x0000aa, 0x0000aa, 0x0000b5, 0x0000b5, 0x0000ba, 0x0000ba, 0x0000c0, 0x0000d6, 0x0000d8, 0x0000f6, 0x0000f8, 0x0002c1, 0x0002c6, 0x0002d1, 0x0002e0, 0x0002e4, 0x0002ec, 0x0002ec, 0x0002ee, 0x0002ee, 0x000370, 0x000374, 0x000376, 0x000377, 0x00037a, 0x00037d, 0x00037f, 0x00037f, 0x000386, 0x000386, 0x000388, 0x00038a, 0x00038c, 0x00038c, 0x00038e, 0x0003a1, 0x0003a3, 0x0003f5, 0x0003f7, 0x000481, 0x00048a, 0x00052f, 0x000531, 0x000556, 0x000559, 0x000559, 0x000560, 0x000588, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f2, 0x000620, 0x00064a, 0x00066e, 0x00066f, 0x000671, 0x0006d3, 0x0006d5, 0x0006d5, 0x0006e5, 0x0006e6, 0x0006ee, 0x0006ef, 0x0006fa, 0x0006fc, 0x0006ff, 0x0006ff, 0x000710, 0x000710, 0x000712, 0x00072f, 0x00074d, 0x0007a5, 0x0007b1, 0x0007b1, 0x0007ca, 0x0007ea, 0x0007f4, 0x0007f5, 0x0007fa, 0x0007fa, 0x000800, 0x000815, 0x00081a, 0x00081a, 0x000824, 0x000824, 0x000828, 0x000828, 0x000840, 0x000858, 0x000860, 0x00086a, - 0x0008a0, 0x0008b4, 0x0008b6, 0x0008c7, 0x000904, 0x000939, 0x00093d, 0x00093d, 0x000950, 0x000950, 0x000958, 0x000961, 0x000971, 0x000980, 0x000985, 0x00098c, 0x00098f, - 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009bd, 0x0009ce, 0x0009ce, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e1, - 0x0009f0, 0x0009f1, 0x0009fc, 0x0009fc, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, 0x000a38, - 0x000a39, 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a72, 0x000a74, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, 0x000ab3, - 0x000ab5, 0x000ab9, 0x000abd, 0x000abd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae1, 0x000af9, 0x000af9, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, 0x000b2a, - 0x000b30, 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b3d, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b61, 0x000b71, 0x000b71, 0x000b83, 0x000b83, 0x000b85, 0x000b8a, - 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bd0, - 0x000bd0, 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c58, 0x000c5a, 0x000c60, 0x000c61, 0x000c80, 0x000c80, - 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbd, 0x000cde, 0x000cde, 0x000ce0, 0x000ce1, 0x000cf1, - 0x000cf2, 0x000d04, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d4e, 0x000d4e, 0x000d54, 0x000d56, 0x000d5f, 0x000d61, 0x000d7a, 0x000d7f, - 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000e01, 0x000e30, 0x000e32, 0x000e33, 0x000e40, 0x000e46, 0x000e81, - 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb3, 0x000ebd, 0x000ebd, 0x000ec0, 0x000ec4, - 0x000ec6, 0x000ec6, 0x000edc, 0x000edf, 0x000f00, 0x000f00, 0x000f40, 0x000f47, 0x000f49, 0x000f6c, 0x000f88, 0x000f8c, 0x001000, 0x00102a, 0x00103f, 0x00103f, 0x001050, - 0x001055, 0x00105a, 0x00105d, 0x001061, 0x001061, 0x001065, 0x001066, 0x00106e, 0x001070, 0x001075, 0x001081, 0x00108e, 0x00108e, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, - 0x0010cd, 0x0010cd, 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, - 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, - 0x001318, 0x00135a, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, 0x0016a0, 0x0016ea, 0x0016f1, - 0x0016f8, 0x001700, 0x00170c, 0x00170e, 0x001711, 0x001720, 0x001731, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001780, 0x0017b3, 0x0017d7, 0x0017d7, - 0x0017dc, 0x0017dc, 0x001820, 0x001878, 0x001880, 0x001884, 0x001887, 0x0018a8, 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001950, 0x00196d, 0x001970, - 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x001a00, 0x001a16, 0x001a20, 0x001a54, 0x001aa7, 0x001aa7, 0x001b05, 0x001b33, 0x001b45, 0x001b4b, 0x001b83, 0x001ba0, - 0x001bae, 0x001baf, 0x001bba, 0x001be5, 0x001c00, 0x001c23, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cbf, 0x001ce9, - 0x001cec, 0x001cee, 0x001cf3, 0x001cf5, 0x001cf6, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, 0x001e00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, - 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, - 0x001fc4, 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002071, 0x002071, 0x00207f, 0x00207f, - 0x002090, 0x00209c, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002119, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, - 0x002128, 0x00212a, 0x00212d, 0x00212f, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002183, 0x002184, 0x002c00, 0x002c2e, 0x002c30, 0x002c5e, - 0x002c60, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d6f, 0x002d80, - 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, - 0x002e2f, 0x002e2f, 0x003005, 0x003006, 0x003031, 0x003035, 0x00303b, 0x00303c, 0x003041, 0x003096, 0x00309d, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, - 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, 0x009ffc, 0x00a000, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, - 0x00a610, 0x00a61f, 0x00a62a, 0x00a62b, 0x00a640, 0x00a66e, 0x00a67f, 0x00a69d, 0x00a6a0, 0x00a6e5, 0x00a717, 0x00a71f, 0x00a722, 0x00a788, 0x00a78b, 0x00a7bf, 0x00a7c2, - 0x00a7ca, 0x00a7f5, 0x00a801, 0x00a803, 0x00a805, 0x00a807, 0x00a80a, 0x00a80c, 0x00a822, 0x00a840, 0x00a873, 0x00a882, 0x00a8b3, 0x00a8f2, 0x00a8f7, 0x00a8fb, 0x00a8fb, + 0x000870, 0x000887, 0x000889, 0x00088e, 0x0008a0, 0x0008c9, 0x000904, 0x000939, 0x00093d, 0x00093d, 0x000950, 0x000950, 0x000958, 0x000961, 0x000971, 0x000980, 0x000985, + 0x00098c, 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009bd, 0x0009ce, 0x0009ce, 0x0009dc, 0x0009dd, + 0x0009df, 0x0009e1, 0x0009f0, 0x0009f1, 0x0009fc, 0x0009fc, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, + 0x000a36, 0x000a38, 0x000a39, 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a72, 0x000a74, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, + 0x000ab2, 0x000ab3, 0x000ab5, 0x000ab9, 0x000abd, 0x000abd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae1, 0x000af9, 0x000af9, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, + 0x000b28, 0x000b2a, 0x000b30, 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b3d, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b61, 0x000b71, 0x000b71, 0x000b83, 0x000b83, + 0x000b85, 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, + 0x000bb9, 0x000bd0, 0x000bd0, 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, + 0x000c60, 0x000c61, 0x000c80, 0x000c80, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbd, 0x000cdd, + 0x000cde, 0x000ce0, 0x000ce1, 0x000cf1, 0x000cf2, 0x000d04, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d4e, 0x000d4e, 0x000d54, 0x000d56, + 0x000d5f, 0x000d61, 0x000d7a, 0x000d7f, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000e01, 0x000e30, 0x000e32, + 0x000e33, 0x000e40, 0x000e46, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb3, + 0x000ebd, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000edc, 0x000edf, 0x000f00, 0x000f00, 0x000f40, 0x000f47, 0x000f49, 0x000f6c, 0x000f88, 0x000f8c, 0x001000, + 0x00102a, 0x00103f, 0x00103f, 0x001050, 0x001055, 0x00105a, 0x00105d, 0x001061, 0x001061, 0x001065, 0x001066, 0x00106e, 0x001070, 0x001075, 0x001081, 0x00108e, 0x00108e, + 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, + 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, + 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, + 0x00169a, 0x0016a0, 0x0016ea, 0x0016f1, 0x0016f8, 0x001700, 0x001711, 0x00171f, 0x001731, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001780, 0x0017b3, + 0x0017d7, 0x0017d7, 0x0017dc, 0x0017dc, 0x001820, 0x001878, 0x001880, 0x001884, 0x001887, 0x0018a8, 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001950, + 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x001a00, 0x001a16, 0x001a20, 0x001a54, 0x001aa7, 0x001aa7, 0x001b05, 0x001b33, 0x001b45, 0x001b4c, + 0x001b83, 0x001ba0, 0x001bae, 0x001baf, 0x001bba, 0x001be5, 0x001c00, 0x001c23, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, + 0x001cbf, 0x001ce9, 0x001cec, 0x001cee, 0x001cf3, 0x001cf5, 0x001cf6, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, 0x001e00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, + 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, + 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002071, 0x002071, + 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002119, 0x00211d, 0x002124, 0x002124, 0x002126, + 0x002126, 0x002128, 0x002128, 0x00212a, 0x00212d, 0x00212f, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002183, 0x002184, 0x002c00, 0x002ce4, + 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d6f, 0x002d80, 0x002d96, 0x002da0, + 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x002e2f, 0x002e2f, + 0x003005, 0x003006, 0x003031, 0x003035, 0x00303b, 0x00303c, 0x003041, 0x003096, 0x00309d, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, 0x00312f, 0x003131, + 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a61f, 0x00a62a, 0x00a62b, + 0x00a640, 0x00a66e, 0x00a67f, 0x00a69d, 0x00a6a0, 0x00a6e5, 0x00a717, 0x00a71f, 0x00a722, 0x00a788, 0x00a78b, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, + 0x00a7d9, 0x00a7f2, 0x00a801, 0x00a803, 0x00a805, 0x00a807, 0x00a80a, 0x00a80c, 0x00a822, 0x00a840, 0x00a873, 0x00a882, 0x00a8b3, 0x00a8f2, 0x00a8f7, 0x00a8fb, 0x00a8fb, 0x00a8fd, 0x00a8fe, 0x00a90a, 0x00a925, 0x00a930, 0x00a946, 0x00a960, 0x00a97c, 0x00a984, 0x00a9b2, 0x00a9cf, 0x00a9cf, 0x00a9e0, 0x00a9e4, 0x00a9e6, 0x00a9ef, 0x00a9fa, 0x00a9fe, 0x00aa00, 0x00aa28, 0x00aa40, 0x00aa42, 0x00aa44, 0x00aa4b, 0x00aa60, 0x00aa76, 0x00aa7a, 0x00aa7a, 0x00aa7e, 0x00aaaf, 0x00aab1, 0x00aab1, 0x00aab5, 0x00aab6, 0x00aab9, 0x00aabd, 0x00aac0, 0x00aac0, 0x00aac2, 0x00aac2, 0x00aadb, 0x00aadd, 0x00aae0, 0x00aaea, 0x00aaf2, 0x00aaf4, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, @@ -117,68 +118,72 @@ static CodePointSet getGeneralCategory(String name) { 0x00fe76, 0x00fefc, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, 0x00ff66, 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, 0x01003c, 0x01003d, 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x010300, 0x01031f, 0x01032d, 0x010340, 0x010342, 0x010349, 0x010350, 0x010375, 0x010380, 0x01039d, 0x0103a0, 0x0103c3, 0x0103c8, 0x0103cf, 0x010400, 0x01049d, 0x0104b0, - 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010800, 0x010805, 0x010808, 0x010808, - 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x010900, - 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a00, 0x010a10, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a60, 0x010a7c, - 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae4, 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, - 0x010cb2, 0x010cc0, 0x010cf2, 0x010d00, 0x010d23, 0x010e80, 0x010ea9, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f45, 0x010fb0, 0x010fc4, - 0x010fe0, 0x010ff6, 0x011003, 0x011037, 0x011083, 0x0110af, 0x0110d0, 0x0110e8, 0x011103, 0x011126, 0x011144, 0x011144, 0x011147, 0x011147, 0x011150, 0x011172, 0x011176, - 0x011176, 0x011183, 0x0111b2, 0x0111c1, 0x0111c4, 0x0111da, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x01122b, 0x011280, 0x011286, 0x011288, 0x011288, - 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112de, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, - 0x011333, 0x011335, 0x011339, 0x01133d, 0x01133d, 0x011350, 0x011350, 0x01135d, 0x011361, 0x011400, 0x011434, 0x011447, 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114af, - 0x0114c4, 0x0114c5, 0x0114c7, 0x0114c7, 0x011580, 0x0115ae, 0x0115d8, 0x0115db, 0x011600, 0x01162f, 0x011644, 0x011644, 0x011680, 0x0116aa, 0x0116b8, 0x0116b8, 0x011700, - 0x01171a, 0x011800, 0x01182b, 0x0118a0, 0x0118df, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x01192f, 0x01193f, 0x01193f, - 0x011941, 0x011941, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d0, 0x0119e1, 0x0119e1, 0x0119e3, 0x0119e3, 0x011a00, 0x011a00, 0x011a0b, 0x011a32, 0x011a3a, 0x011a3a, 0x011a50, - 0x011a50, 0x011a5c, 0x011a89, 0x011a9d, 0x011a9d, 0x011ac0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c2e, 0x011c40, 0x011c40, 0x011c72, 0x011c8f, 0x011d00, 0x011d06, - 0x011d08, 0x011d09, 0x011d0b, 0x011d30, 0x011d46, 0x011d46, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d89, 0x011d98, 0x011d98, 0x011ee0, 0x011ef2, 0x011fb0, - 0x011fb0, 0x012000, 0x012399, 0x012480, 0x012543, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, + 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, + 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, + 0x0107ba, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, + 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a00, 0x010a10, 0x010a13, 0x010a15, + 0x010a17, 0x010a19, 0x010a35, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae4, 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, + 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010d00, 0x010d23, 0x010e80, 0x010ea9, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, + 0x010f27, 0x010f30, 0x010f45, 0x010f70, 0x010f81, 0x010fb0, 0x010fc4, 0x010fe0, 0x010ff6, 0x011003, 0x011037, 0x011071, 0x011072, 0x011075, 0x011075, 0x011083, 0x0110af, + 0x0110d0, 0x0110e8, 0x011103, 0x011126, 0x011144, 0x011144, 0x011147, 0x011147, 0x011150, 0x011172, 0x011176, 0x011176, 0x011183, 0x0111b2, 0x0111c1, 0x0111c4, 0x0111da, + 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x01122b, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, + 0x0112b0, 0x0112de, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133d, 0x01133d, 0x011350, + 0x011350, 0x01135d, 0x011361, 0x011400, 0x011434, 0x011447, 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114af, 0x0114c4, 0x0114c5, 0x0114c7, 0x0114c7, 0x011580, 0x0115ae, + 0x0115d8, 0x0115db, 0x011600, 0x01162f, 0x011644, 0x011644, 0x011680, 0x0116aa, 0x0116b8, 0x0116b8, 0x011700, 0x01171a, 0x011740, 0x011746, 0x011800, 0x01182b, 0x0118a0, + 0x0118df, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x01192f, 0x01193f, 0x01193f, 0x011941, 0x011941, 0x0119a0, 0x0119a7, + 0x0119aa, 0x0119d0, 0x0119e1, 0x0119e1, 0x0119e3, 0x0119e3, 0x011a00, 0x011a00, 0x011a0b, 0x011a32, 0x011a3a, 0x011a3a, 0x011a50, 0x011a50, 0x011a5c, 0x011a89, 0x011a9d, + 0x011a9d, 0x011ab0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c2e, 0x011c40, 0x011c40, 0x011c72, 0x011c8f, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d30, + 0x011d46, 0x011d46, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d89, 0x011d98, 0x011d98, 0x011ee0, 0x011ef2, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012480, + 0x012543, 0x012f90, 0x012ff0, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016a70, 0x016abe, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, 0x016b40, 0x016b43, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e7f, 0x016f00, 0x016f4a, 0x016f50, 0x016f50, 0x016f93, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, - 0x016fe3, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b11e, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, - 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, - 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, - 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, - 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01e100, 0x01e12c, - 0x01e137, 0x01e13d, 0x01e14e, 0x01e14e, 0x01e2c0, 0x01e2eb, 0x01e800, 0x01e8c4, 0x01e900, 0x01e943, 0x01e94b, 0x01e94b, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, - 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, - 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, - 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, - 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, - 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); + 0x016fe3, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01b000, 0x01b122, 0x01b150, 0x01b152, + 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, + 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, + 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, + 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, + 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01df00, 0x01df1e, 0x01e100, 0x01e12c, 0x01e137, 0x01e13d, 0x01e14e, 0x01e14e, 0x01e290, 0x01e2ad, 0x01e2c0, 0x01e2eb, 0x01e7e0, + 0x01e7e6, 0x01e7e8, 0x01e7eb, 0x01e7ed, 0x01e7ee, 0x01e7f0, 0x01e7fe, 0x01e800, 0x01e8c4, 0x01e900, 0x01e943, 0x01e94b, 0x01e94b, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, + 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, + 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, + 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, + 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, + 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); GENERAL_CATEGORIES.put("gc=M", CodePointSet.createNoDedup(0x000300, 0x00036f, 0x000483, 0x000489, 0x000591, 0x0005bd, 0x0005bf, 0x0005bf, 0x0005c1, 0x0005c2, 0x0005c4, 0x0005c5, 0x0005c7, 0x0005c7, 0x000610, 0x00061a, 0x00064b, 0x00065f, 0x000670, 0x000670, 0x0006d6, 0x0006dc, 0x0006df, 0x0006e4, 0x0006e7, 0x0006e8, 0x0006ea, 0x0006ed, 0x000711, 0x000711, 0x000730, 0x00074a, 0x0007a6, 0x0007b0, 0x0007eb, 0x0007f3, 0x0007fd, 0x0007fd, 0x000816, 0x000819, 0x00081b, 0x000823, 0x000825, 0x000827, 0x000829, 0x00082d, 0x000859, - 0x00085b, 0x0008d3, 0x0008e1, 0x0008e3, 0x000903, 0x00093a, 0x00093c, 0x00093e, 0x00094f, 0x000951, 0x000957, 0x000962, 0x000963, 0x000981, 0x000983, 0x0009bc, 0x0009bc, - 0x0009be, 0x0009c4, 0x0009c7, 0x0009c8, 0x0009cb, 0x0009cd, 0x0009d7, 0x0009d7, 0x0009e2, 0x0009e3, 0x0009fe, 0x0009fe, 0x000a01, 0x000a03, 0x000a3c, 0x000a3c, 0x000a3e, - 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4d, 0x000a51, 0x000a51, 0x000a70, 0x000a71, 0x000a75, 0x000a75, 0x000a81, 0x000a83, 0x000abc, 0x000abc, 0x000abe, 0x000ac5, - 0x000ac7, 0x000ac9, 0x000acb, 0x000acd, 0x000ae2, 0x000ae3, 0x000afa, 0x000aff, 0x000b01, 0x000b03, 0x000b3c, 0x000b3c, 0x000b3e, 0x000b44, 0x000b47, 0x000b48, 0x000b4b, - 0x000b4d, 0x000b55, 0x000b57, 0x000b62, 0x000b63, 0x000b82, 0x000b82, 0x000bbe, 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcd, 0x000bd7, 0x000bd7, 0x000c00, 0x000c04, - 0x000c3e, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c62, 0x000c63, 0x000c81, 0x000c83, 0x000cbc, 0x000cbc, 0x000cbe, 0x000cc4, 0x000cc6, - 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000ce2, 0x000ce3, 0x000d00, 0x000d03, 0x000d3b, 0x000d3c, 0x000d3e, 0x000d44, 0x000d46, 0x000d48, 0x000d4a, 0x000d4d, - 0x000d57, 0x000d57, 0x000d62, 0x000d63, 0x000d81, 0x000d83, 0x000dca, 0x000dca, 0x000dcf, 0x000dd4, 0x000dd6, 0x000dd6, 0x000dd8, 0x000ddf, 0x000df2, 0x000df3, 0x000e31, - 0x000e31, 0x000e34, 0x000e3a, 0x000e47, 0x000e4e, 0x000eb1, 0x000eb1, 0x000eb4, 0x000ebc, 0x000ec8, 0x000ecd, 0x000f18, 0x000f19, 0x000f35, 0x000f35, 0x000f37, 0x000f37, - 0x000f39, 0x000f39, 0x000f3e, 0x000f3f, 0x000f71, 0x000f84, 0x000f86, 0x000f87, 0x000f8d, 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x00102b, 0x00103e, 0x001056, - 0x001059, 0x00105e, 0x001060, 0x001062, 0x001064, 0x001067, 0x00106d, 0x001071, 0x001074, 0x001082, 0x00108d, 0x00108f, 0x00108f, 0x00109a, 0x00109d, 0x00135d, 0x00135f, - 0x001712, 0x001714, 0x001732, 0x001734, 0x001752, 0x001753, 0x001772, 0x001773, 0x0017b4, 0x0017d3, 0x0017dd, 0x0017dd, 0x00180b, 0x00180d, 0x001885, 0x001886, 0x0018a9, - 0x0018a9, 0x001920, 0x00192b, 0x001930, 0x00193b, 0x001a17, 0x001a1b, 0x001a55, 0x001a5e, 0x001a60, 0x001a7c, 0x001a7f, 0x001a7f, 0x001ab0, 0x001ac0, 0x001b00, 0x001b04, - 0x001b34, 0x001b44, 0x001b6b, 0x001b73, 0x001b80, 0x001b82, 0x001ba1, 0x001bad, 0x001be6, 0x001bf3, 0x001c24, 0x001c37, 0x001cd0, 0x001cd2, 0x001cd4, 0x001ce8, 0x001ced, - 0x001ced, 0x001cf4, 0x001cf4, 0x001cf7, 0x001cf9, 0x001dc0, 0x001df9, 0x001dfb, 0x001dff, 0x0020d0, 0x0020f0, 0x002cef, 0x002cf1, 0x002d7f, 0x002d7f, 0x002de0, 0x002dff, - 0x00302a, 0x00302f, 0x003099, 0x00309a, 0x00a66f, 0x00a672, 0x00a674, 0x00a67d, 0x00a69e, 0x00a69f, 0x00a6f0, 0x00a6f1, 0x00a802, 0x00a802, 0x00a806, 0x00a806, 0x00a80b, - 0x00a80b, 0x00a823, 0x00a827, 0x00a82c, 0x00a82c, 0x00a880, 0x00a881, 0x00a8b4, 0x00a8c5, 0x00a8e0, 0x00a8f1, 0x00a8ff, 0x00a8ff, 0x00a926, 0x00a92d, 0x00a947, 0x00a953, - 0x00a980, 0x00a983, 0x00a9b3, 0x00a9c0, 0x00a9e5, 0x00a9e5, 0x00aa29, 0x00aa36, 0x00aa43, 0x00aa43, 0x00aa4c, 0x00aa4d, 0x00aa7b, 0x00aa7d, 0x00aab0, 0x00aab0, 0x00aab2, - 0x00aab4, 0x00aab7, 0x00aab8, 0x00aabe, 0x00aabf, 0x00aac1, 0x00aac1, 0x00aaeb, 0x00aaef, 0x00aaf5, 0x00aaf6, 0x00abe3, 0x00abea, 0x00abec, 0x00abed, 0x00fb1e, 0x00fb1e, - 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2f, 0x0101fd, 0x0101fd, 0x0102e0, 0x0102e0, 0x010376, 0x01037a, 0x010a01, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a0f, 0x010a38, - 0x010a3a, 0x010a3f, 0x010a3f, 0x010ae5, 0x010ae6, 0x010d24, 0x010d27, 0x010eab, 0x010eac, 0x010f46, 0x010f50, 0x011000, 0x011002, 0x011038, 0x011046, 0x01107f, 0x011082, - 0x0110b0, 0x0110ba, 0x011100, 0x011102, 0x011127, 0x011134, 0x011145, 0x011146, 0x011173, 0x011173, 0x011180, 0x011182, 0x0111b3, 0x0111c0, 0x0111c9, 0x0111cc, 0x0111ce, - 0x0111cf, 0x01122c, 0x011237, 0x01123e, 0x01123e, 0x0112df, 0x0112ea, 0x011300, 0x011303, 0x01133b, 0x01133c, 0x01133e, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, - 0x011357, 0x011357, 0x011362, 0x011363, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011435, 0x011446, 0x01145e, 0x01145e, 0x0114b0, 0x0114c3, 0x0115af, 0x0115b5, 0x0115b8, - 0x0115c0, 0x0115dc, 0x0115dd, 0x011630, 0x011640, 0x0116ab, 0x0116b7, 0x01171d, 0x01172b, 0x01182c, 0x01183a, 0x011930, 0x011935, 0x011937, 0x011938, 0x01193b, 0x01193e, - 0x011940, 0x011940, 0x011942, 0x011943, 0x0119d1, 0x0119d7, 0x0119da, 0x0119e0, 0x0119e4, 0x0119e4, 0x011a01, 0x011a0a, 0x011a33, 0x011a39, 0x011a3b, 0x011a3e, 0x011a47, - 0x011a47, 0x011a51, 0x011a5b, 0x011a8a, 0x011a99, 0x011c2f, 0x011c36, 0x011c38, 0x011c3f, 0x011c92, 0x011ca7, 0x011ca9, 0x011cb6, 0x011d31, 0x011d36, 0x011d3a, 0x011d3a, - 0x011d3c, 0x011d3d, 0x011d3f, 0x011d45, 0x011d47, 0x011d47, 0x011d8a, 0x011d8e, 0x011d90, 0x011d91, 0x011d93, 0x011d97, 0x011ef3, 0x011ef6, 0x016af0, 0x016af4, 0x016b30, - 0x016b36, 0x016f4f, 0x016f4f, 0x016f51, 0x016f87, 0x016f8f, 0x016f92, 0x016fe4, 0x016fe4, 0x016ff0, 0x016ff1, 0x01bc9d, 0x01bc9e, 0x01d165, 0x01d169, 0x01d16d, 0x01d172, - 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, 0x01d244, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, 0x01da75, 0x01da75, 0x01da84, 0x01da84, 0x01da9b, - 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e130, 0x01e136, 0x01e2ec, 0x01e2ef, - 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e94a, 0x0e0100, 0x0e01ef)); + 0x00085b, 0x000898, 0x00089f, 0x0008ca, 0x0008e1, 0x0008e3, 0x000903, 0x00093a, 0x00093c, 0x00093e, 0x00094f, 0x000951, 0x000957, 0x000962, 0x000963, 0x000981, 0x000983, + 0x0009bc, 0x0009bc, 0x0009be, 0x0009c4, 0x0009c7, 0x0009c8, 0x0009cb, 0x0009cd, 0x0009d7, 0x0009d7, 0x0009e2, 0x0009e3, 0x0009fe, 0x0009fe, 0x000a01, 0x000a03, 0x000a3c, + 0x000a3c, 0x000a3e, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4d, 0x000a51, 0x000a51, 0x000a70, 0x000a71, 0x000a75, 0x000a75, 0x000a81, 0x000a83, 0x000abc, 0x000abc, + 0x000abe, 0x000ac5, 0x000ac7, 0x000ac9, 0x000acb, 0x000acd, 0x000ae2, 0x000ae3, 0x000afa, 0x000aff, 0x000b01, 0x000b03, 0x000b3c, 0x000b3c, 0x000b3e, 0x000b44, 0x000b47, + 0x000b48, 0x000b4b, 0x000b4d, 0x000b55, 0x000b57, 0x000b62, 0x000b63, 0x000b82, 0x000b82, 0x000bbe, 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcd, 0x000bd7, 0x000bd7, + 0x000c00, 0x000c04, 0x000c3c, 0x000c3c, 0x000c3e, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c62, 0x000c63, 0x000c81, 0x000c83, 0x000cbc, + 0x000cbc, 0x000cbe, 0x000cc4, 0x000cc6, 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000ce2, 0x000ce3, 0x000d00, 0x000d03, 0x000d3b, 0x000d3c, 0x000d3e, 0x000d44, + 0x000d46, 0x000d48, 0x000d4a, 0x000d4d, 0x000d57, 0x000d57, 0x000d62, 0x000d63, 0x000d81, 0x000d83, 0x000dca, 0x000dca, 0x000dcf, 0x000dd4, 0x000dd6, 0x000dd6, 0x000dd8, + 0x000ddf, 0x000df2, 0x000df3, 0x000e31, 0x000e31, 0x000e34, 0x000e3a, 0x000e47, 0x000e4e, 0x000eb1, 0x000eb1, 0x000eb4, 0x000ebc, 0x000ec8, 0x000ecd, 0x000f18, 0x000f19, + 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f3e, 0x000f3f, 0x000f71, 0x000f84, 0x000f86, 0x000f87, 0x000f8d, 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, + 0x000fc6, 0x00102b, 0x00103e, 0x001056, 0x001059, 0x00105e, 0x001060, 0x001062, 0x001064, 0x001067, 0x00106d, 0x001071, 0x001074, 0x001082, 0x00108d, 0x00108f, 0x00108f, + 0x00109a, 0x00109d, 0x00135d, 0x00135f, 0x001712, 0x001715, 0x001732, 0x001734, 0x001752, 0x001753, 0x001772, 0x001773, 0x0017b4, 0x0017d3, 0x0017dd, 0x0017dd, 0x00180b, + 0x00180d, 0x00180f, 0x00180f, 0x001885, 0x001886, 0x0018a9, 0x0018a9, 0x001920, 0x00192b, 0x001930, 0x00193b, 0x001a17, 0x001a1b, 0x001a55, 0x001a5e, 0x001a60, 0x001a7c, + 0x001a7f, 0x001a7f, 0x001ab0, 0x001ace, 0x001b00, 0x001b04, 0x001b34, 0x001b44, 0x001b6b, 0x001b73, 0x001b80, 0x001b82, 0x001ba1, 0x001bad, 0x001be6, 0x001bf3, 0x001c24, + 0x001c37, 0x001cd0, 0x001cd2, 0x001cd4, 0x001ce8, 0x001ced, 0x001ced, 0x001cf4, 0x001cf4, 0x001cf7, 0x001cf9, 0x001dc0, 0x001dff, 0x0020d0, 0x0020f0, 0x002cef, 0x002cf1, + 0x002d7f, 0x002d7f, 0x002de0, 0x002dff, 0x00302a, 0x00302f, 0x003099, 0x00309a, 0x00a66f, 0x00a672, 0x00a674, 0x00a67d, 0x00a69e, 0x00a69f, 0x00a6f0, 0x00a6f1, 0x00a802, + 0x00a802, 0x00a806, 0x00a806, 0x00a80b, 0x00a80b, 0x00a823, 0x00a827, 0x00a82c, 0x00a82c, 0x00a880, 0x00a881, 0x00a8b4, 0x00a8c5, 0x00a8e0, 0x00a8f1, 0x00a8ff, 0x00a8ff, + 0x00a926, 0x00a92d, 0x00a947, 0x00a953, 0x00a980, 0x00a983, 0x00a9b3, 0x00a9c0, 0x00a9e5, 0x00a9e5, 0x00aa29, 0x00aa36, 0x00aa43, 0x00aa43, 0x00aa4c, 0x00aa4d, 0x00aa7b, + 0x00aa7d, 0x00aab0, 0x00aab0, 0x00aab2, 0x00aab4, 0x00aab7, 0x00aab8, 0x00aabe, 0x00aabf, 0x00aac1, 0x00aac1, 0x00aaeb, 0x00aaef, 0x00aaf5, 0x00aaf6, 0x00abe3, 0x00abea, + 0x00abec, 0x00abed, 0x00fb1e, 0x00fb1e, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2f, 0x0101fd, 0x0101fd, 0x0102e0, 0x0102e0, 0x010376, 0x01037a, 0x010a01, 0x010a03, 0x010a05, + 0x010a06, 0x010a0c, 0x010a0f, 0x010a38, 0x010a3a, 0x010a3f, 0x010a3f, 0x010ae5, 0x010ae6, 0x010d24, 0x010d27, 0x010eab, 0x010eac, 0x010f46, 0x010f50, 0x010f82, 0x010f85, + 0x011000, 0x011002, 0x011038, 0x011046, 0x011070, 0x011070, 0x011073, 0x011074, 0x01107f, 0x011082, 0x0110b0, 0x0110ba, 0x0110c2, 0x0110c2, 0x011100, 0x011102, 0x011127, + 0x011134, 0x011145, 0x011146, 0x011173, 0x011173, 0x011180, 0x011182, 0x0111b3, 0x0111c0, 0x0111c9, 0x0111cc, 0x0111ce, 0x0111cf, 0x01122c, 0x011237, 0x01123e, 0x01123e, + 0x0112df, 0x0112ea, 0x011300, 0x011303, 0x01133b, 0x01133c, 0x01133e, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, 0x011357, 0x011357, 0x011362, 0x011363, 0x011366, + 0x01136c, 0x011370, 0x011374, 0x011435, 0x011446, 0x01145e, 0x01145e, 0x0114b0, 0x0114c3, 0x0115af, 0x0115b5, 0x0115b8, 0x0115c0, 0x0115dc, 0x0115dd, 0x011630, 0x011640, + 0x0116ab, 0x0116b7, 0x01171d, 0x01172b, 0x01182c, 0x01183a, 0x011930, 0x011935, 0x011937, 0x011938, 0x01193b, 0x01193e, 0x011940, 0x011940, 0x011942, 0x011943, 0x0119d1, + 0x0119d7, 0x0119da, 0x0119e0, 0x0119e4, 0x0119e4, 0x011a01, 0x011a0a, 0x011a33, 0x011a39, 0x011a3b, 0x011a3e, 0x011a47, 0x011a47, 0x011a51, 0x011a5b, 0x011a8a, 0x011a99, + 0x011c2f, 0x011c36, 0x011c38, 0x011c3f, 0x011c92, 0x011ca7, 0x011ca9, 0x011cb6, 0x011d31, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d45, 0x011d47, + 0x011d47, 0x011d8a, 0x011d8e, 0x011d90, 0x011d91, 0x011d93, 0x011d97, 0x011ef3, 0x011ef6, 0x016af0, 0x016af4, 0x016b30, 0x016b36, 0x016f4f, 0x016f4f, 0x016f51, 0x016f87, + 0x016f8f, 0x016f92, 0x016fe4, 0x016fe4, 0x016ff0, 0x016ff1, 0x01bc9d, 0x01bc9e, 0x01cf00, 0x01cf2d, 0x01cf30, 0x01cf46, 0x01d165, 0x01d169, 0x01d16d, 0x01d172, 0x01d17b, + 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, 0x01d244, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, 0x01da75, 0x01da75, 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, + 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e130, 0x01e136, 0x01e2ae, 0x01e2ae, 0x01e2ec, + 0x01e2ef, 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e94a, 0x0e0100, 0x0e01ef)); GENERAL_CATEGORIES.put("gc=N", CodePointSet.createNoDedup(0x000030, 0x000039, 0x0000b2, 0x0000b3, 0x0000b9, 0x0000b9, 0x0000bc, 0x0000be, 0x000660, 0x000669, 0x0006f0, 0x0006f9, 0x0007c0, 0x0007c9, 0x000966, 0x00096f, 0x0009e6, 0x0009ef, 0x0009f4, 0x0009f9, 0x000a66, 0x000a6f, 0x000ae6, 0x000aef, 0x000b66, 0x000b6f, 0x000b72, 0x000b77, 0x000be6, 0x000bf2, 0x000c66, 0x000c6f, 0x000c78, 0x000c7e, 0x000ce6, 0x000cef, 0x000d58, 0x000d5e, 0x000d66, 0x000d78, 0x000de6, 0x000def, 0x000e50, 0x000e59, 0x000ed0, 0x000ed9, 0x000f20, @@ -192,76 +197,77 @@ static CodePointSet getGeneralCategory(String name) { 0x0109d2, 0x0109ff, 0x010a40, 0x010a48, 0x010a7d, 0x010a7e, 0x010a9d, 0x010a9f, 0x010aeb, 0x010aef, 0x010b58, 0x010b5f, 0x010b78, 0x010b7f, 0x010ba9, 0x010baf, 0x010cfa, 0x010cff, 0x010d30, 0x010d39, 0x010e60, 0x010e7e, 0x010f1d, 0x010f26, 0x010f51, 0x010f54, 0x010fc5, 0x010fcb, 0x011052, 0x01106f, 0x0110f0, 0x0110f9, 0x011136, 0x01113f, 0x0111d0, 0x0111d9, 0x0111e1, 0x0111f4, 0x0112f0, 0x0112f9, 0x011450, 0x011459, 0x0114d0, 0x0114d9, 0x011650, 0x011659, 0x0116c0, 0x0116c9, 0x011730, 0x01173b, 0x0118e0, - 0x0118f2, 0x011950, 0x011959, 0x011c50, 0x011c6c, 0x011d50, 0x011d59, 0x011da0, 0x011da9, 0x011fc0, 0x011fd4, 0x012400, 0x01246e, 0x016a60, 0x016a69, 0x016b50, 0x016b59, - 0x016b5b, 0x016b61, 0x016e80, 0x016e96, 0x01d2e0, 0x01d2f3, 0x01d360, 0x01d378, 0x01d7ce, 0x01d7ff, 0x01e140, 0x01e149, 0x01e2f0, 0x01e2f9, 0x01e8c7, 0x01e8cf, 0x01e950, - 0x01e959, 0x01ec71, 0x01ecab, 0x01ecad, 0x01ecaf, 0x01ecb1, 0x01ecb4, 0x01ed01, 0x01ed2d, 0x01ed2f, 0x01ed3d, 0x01f100, 0x01f10c, 0x01fbf0, 0x01fbf9)); + 0x0118f2, 0x011950, 0x011959, 0x011c50, 0x011c6c, 0x011d50, 0x011d59, 0x011da0, 0x011da9, 0x011fc0, 0x011fd4, 0x012400, 0x01246e, 0x016a60, 0x016a69, 0x016ac0, 0x016ac9, + 0x016b50, 0x016b59, 0x016b5b, 0x016b61, 0x016e80, 0x016e96, 0x01d2e0, 0x01d2f3, 0x01d360, 0x01d378, 0x01d7ce, 0x01d7ff, 0x01e140, 0x01e149, 0x01e2f0, 0x01e2f9, 0x01e8c7, + 0x01e8cf, 0x01e950, 0x01e959, 0x01ec71, 0x01ecab, 0x01ecad, 0x01ecaf, 0x01ecb1, 0x01ecb4, 0x01ed01, 0x01ed2d, 0x01ed2f, 0x01ed3d, 0x01f100, 0x01f10c, 0x01fbf0, 0x01fbf9)); GENERAL_CATEGORIES.put("gc=P", CodePointSet.createNoDedup(0x000021, 0x000023, 0x000025, 0x00002a, 0x00002c, 0x00002f, 0x00003a, 0x00003b, 0x00003f, 0x000040, 0x00005b, 0x00005d, 0x00005f, 0x00005f, 0x00007b, 0x00007b, 0x00007d, 0x00007d, 0x0000a1, 0x0000a1, 0x0000a7, 0x0000a7, 0x0000ab, 0x0000ab, 0x0000b6, 0x0000b7, 0x0000bb, 0x0000bb, 0x0000bf, 0x0000bf, 0x00037e, 0x00037e, 0x000387, 0x000387, 0x00055a, 0x00055f, 0x000589, 0x00058a, 0x0005be, 0x0005be, 0x0005c0, 0x0005c0, 0x0005c3, 0x0005c3, 0x0005c6, 0x0005c6, 0x0005f3, - 0x0005f4, 0x000609, 0x00060a, 0x00060c, 0x00060d, 0x00061b, 0x00061b, 0x00061e, 0x00061f, 0x00066a, 0x00066d, 0x0006d4, 0x0006d4, 0x000700, 0x00070d, 0x0007f7, 0x0007f9, + 0x0005f4, 0x000609, 0x00060a, 0x00060c, 0x00060d, 0x00061b, 0x00061b, 0x00061d, 0x00061f, 0x00066a, 0x00066d, 0x0006d4, 0x0006d4, 0x000700, 0x00070d, 0x0007f7, 0x0007f9, 0x000830, 0x00083e, 0x00085e, 0x00085e, 0x000964, 0x000965, 0x000970, 0x000970, 0x0009fd, 0x0009fd, 0x000a76, 0x000a76, 0x000af0, 0x000af0, 0x000c77, 0x000c77, 0x000c84, 0x000c84, 0x000df4, 0x000df4, 0x000e4f, 0x000e4f, 0x000e5a, 0x000e5b, 0x000f04, 0x000f12, 0x000f14, 0x000f14, 0x000f3a, 0x000f3d, 0x000f85, 0x000f85, 0x000fd0, 0x000fd4, 0x000fd9, 0x000fda, 0x00104a, 0x00104f, 0x0010fb, 0x0010fb, 0x001360, 0x001368, 0x001400, 0x001400, 0x00166e, 0x00166e, 0x00169b, 0x00169c, 0x0016eb, 0x0016ed, 0x001735, 0x001736, 0x0017d4, 0x0017d6, 0x0017d8, 0x0017da, 0x001800, 0x00180a, 0x001944, 0x001945, 0x001a1e, 0x001a1f, 0x001aa0, 0x001aa6, 0x001aa8, 0x001aad, 0x001b5a, 0x001b60, - 0x001bfc, 0x001bff, 0x001c3b, 0x001c3f, 0x001c7e, 0x001c7f, 0x001cc0, 0x001cc7, 0x001cd3, 0x001cd3, 0x002010, 0x002027, 0x002030, 0x002043, 0x002045, 0x002051, 0x002053, - 0x00205e, 0x00207d, 0x00207e, 0x00208d, 0x00208e, 0x002308, 0x00230b, 0x002329, 0x00232a, 0x002768, 0x002775, 0x0027c5, 0x0027c6, 0x0027e6, 0x0027ef, 0x002983, 0x002998, - 0x0029d8, 0x0029db, 0x0029fc, 0x0029fd, 0x002cf9, 0x002cfc, 0x002cfe, 0x002cff, 0x002d70, 0x002d70, 0x002e00, 0x002e2e, 0x002e30, 0x002e4f, 0x002e52, 0x002e52, 0x003001, - 0x003003, 0x003008, 0x003011, 0x003014, 0x00301f, 0x003030, 0x003030, 0x00303d, 0x00303d, 0x0030a0, 0x0030a0, 0x0030fb, 0x0030fb, 0x00a4fe, 0x00a4ff, 0x00a60d, 0x00a60f, - 0x00a673, 0x00a673, 0x00a67e, 0x00a67e, 0x00a6f2, 0x00a6f7, 0x00a874, 0x00a877, 0x00a8ce, 0x00a8cf, 0x00a8f8, 0x00a8fa, 0x00a8fc, 0x00a8fc, 0x00a92e, 0x00a92f, 0x00a95f, - 0x00a95f, 0x00a9c1, 0x00a9cd, 0x00a9de, 0x00a9df, 0x00aa5c, 0x00aa5f, 0x00aade, 0x00aadf, 0x00aaf0, 0x00aaf1, 0x00abeb, 0x00abeb, 0x00fd3e, 0x00fd3f, 0x00fe10, 0x00fe19, - 0x00fe30, 0x00fe52, 0x00fe54, 0x00fe61, 0x00fe63, 0x00fe63, 0x00fe68, 0x00fe68, 0x00fe6a, 0x00fe6b, 0x00ff01, 0x00ff03, 0x00ff05, 0x00ff0a, 0x00ff0c, 0x00ff0f, 0x00ff1a, - 0x00ff1b, 0x00ff1f, 0x00ff20, 0x00ff3b, 0x00ff3d, 0x00ff3f, 0x00ff3f, 0x00ff5b, 0x00ff5b, 0x00ff5d, 0x00ff5d, 0x00ff5f, 0x00ff65, 0x010100, 0x010102, 0x01039f, 0x01039f, - 0x0103d0, 0x0103d0, 0x01056f, 0x01056f, 0x010857, 0x010857, 0x01091f, 0x01091f, 0x01093f, 0x01093f, 0x010a50, 0x010a58, 0x010a7f, 0x010a7f, 0x010af0, 0x010af6, 0x010b39, - 0x010b3f, 0x010b99, 0x010b9c, 0x010ead, 0x010ead, 0x010f55, 0x010f59, 0x011047, 0x01104d, 0x0110bb, 0x0110bc, 0x0110be, 0x0110c1, 0x011140, 0x011143, 0x011174, 0x011175, - 0x0111c5, 0x0111c8, 0x0111cd, 0x0111cd, 0x0111db, 0x0111db, 0x0111dd, 0x0111df, 0x011238, 0x01123d, 0x0112a9, 0x0112a9, 0x01144b, 0x01144f, 0x01145a, 0x01145b, 0x01145d, - 0x01145d, 0x0114c6, 0x0114c6, 0x0115c1, 0x0115d7, 0x011641, 0x011643, 0x011660, 0x01166c, 0x01173c, 0x01173e, 0x01183b, 0x01183b, 0x011944, 0x011946, 0x0119e2, 0x0119e2, - 0x011a3f, 0x011a46, 0x011a9a, 0x011a9c, 0x011a9e, 0x011aa2, 0x011c41, 0x011c45, 0x011c70, 0x011c71, 0x011ef7, 0x011ef8, 0x011fff, 0x011fff, 0x012470, 0x012474, 0x016a6e, - 0x016a6f, 0x016af5, 0x016af5, 0x016b37, 0x016b3b, 0x016b44, 0x016b44, 0x016e97, 0x016e9a, 0x016fe2, 0x016fe2, 0x01bc9f, 0x01bc9f, 0x01da87, 0x01da8b, 0x01e95e, 0x01e95f)); + 0x001b7d, 0x001b7e, 0x001bfc, 0x001bff, 0x001c3b, 0x001c3f, 0x001c7e, 0x001c7f, 0x001cc0, 0x001cc7, 0x001cd3, 0x001cd3, 0x002010, 0x002027, 0x002030, 0x002043, 0x002045, + 0x002051, 0x002053, 0x00205e, 0x00207d, 0x00207e, 0x00208d, 0x00208e, 0x002308, 0x00230b, 0x002329, 0x00232a, 0x002768, 0x002775, 0x0027c5, 0x0027c6, 0x0027e6, 0x0027ef, + 0x002983, 0x002998, 0x0029d8, 0x0029db, 0x0029fc, 0x0029fd, 0x002cf9, 0x002cfc, 0x002cfe, 0x002cff, 0x002d70, 0x002d70, 0x002e00, 0x002e2e, 0x002e30, 0x002e4f, 0x002e52, + 0x002e5d, 0x003001, 0x003003, 0x003008, 0x003011, 0x003014, 0x00301f, 0x003030, 0x003030, 0x00303d, 0x00303d, 0x0030a0, 0x0030a0, 0x0030fb, 0x0030fb, 0x00a4fe, 0x00a4ff, + 0x00a60d, 0x00a60f, 0x00a673, 0x00a673, 0x00a67e, 0x00a67e, 0x00a6f2, 0x00a6f7, 0x00a874, 0x00a877, 0x00a8ce, 0x00a8cf, 0x00a8f8, 0x00a8fa, 0x00a8fc, 0x00a8fc, 0x00a92e, + 0x00a92f, 0x00a95f, 0x00a95f, 0x00a9c1, 0x00a9cd, 0x00a9de, 0x00a9df, 0x00aa5c, 0x00aa5f, 0x00aade, 0x00aadf, 0x00aaf0, 0x00aaf1, 0x00abeb, 0x00abeb, 0x00fd3e, 0x00fd3f, + 0x00fe10, 0x00fe19, 0x00fe30, 0x00fe52, 0x00fe54, 0x00fe61, 0x00fe63, 0x00fe63, 0x00fe68, 0x00fe68, 0x00fe6a, 0x00fe6b, 0x00ff01, 0x00ff03, 0x00ff05, 0x00ff0a, 0x00ff0c, + 0x00ff0f, 0x00ff1a, 0x00ff1b, 0x00ff1f, 0x00ff20, 0x00ff3b, 0x00ff3d, 0x00ff3f, 0x00ff3f, 0x00ff5b, 0x00ff5b, 0x00ff5d, 0x00ff5d, 0x00ff5f, 0x00ff65, 0x010100, 0x010102, + 0x01039f, 0x01039f, 0x0103d0, 0x0103d0, 0x01056f, 0x01056f, 0x010857, 0x010857, 0x01091f, 0x01091f, 0x01093f, 0x01093f, 0x010a50, 0x010a58, 0x010a7f, 0x010a7f, 0x010af0, + 0x010af6, 0x010b39, 0x010b3f, 0x010b99, 0x010b9c, 0x010ead, 0x010ead, 0x010f55, 0x010f59, 0x010f86, 0x010f89, 0x011047, 0x01104d, 0x0110bb, 0x0110bc, 0x0110be, 0x0110c1, + 0x011140, 0x011143, 0x011174, 0x011175, 0x0111c5, 0x0111c8, 0x0111cd, 0x0111cd, 0x0111db, 0x0111db, 0x0111dd, 0x0111df, 0x011238, 0x01123d, 0x0112a9, 0x0112a9, 0x01144b, + 0x01144f, 0x01145a, 0x01145b, 0x01145d, 0x01145d, 0x0114c6, 0x0114c6, 0x0115c1, 0x0115d7, 0x011641, 0x011643, 0x011660, 0x01166c, 0x0116b9, 0x0116b9, 0x01173c, 0x01173e, + 0x01183b, 0x01183b, 0x011944, 0x011946, 0x0119e2, 0x0119e2, 0x011a3f, 0x011a46, 0x011a9a, 0x011a9c, 0x011a9e, 0x011aa2, 0x011c41, 0x011c45, 0x011c70, 0x011c71, 0x011ef7, + 0x011ef8, 0x011fff, 0x011fff, 0x012470, 0x012474, 0x012ff1, 0x012ff2, 0x016a6e, 0x016a6f, 0x016af5, 0x016af5, 0x016b37, 0x016b3b, 0x016b44, 0x016b44, 0x016e97, 0x016e9a, + 0x016fe2, 0x016fe2, 0x01bc9f, 0x01bc9f, 0x01da87, 0x01da8b, 0x01e95e, 0x01e95f)); GENERAL_CATEGORIES.put("gc=S", CodePointSet.createNoDedup(0x000024, 0x000024, 0x00002b, 0x00002b, 0x00003c, 0x00003e, 0x00005e, 0x00005e, 0x000060, 0x000060, 0x00007c, 0x00007c, 0x00007e, 0x00007e, 0x0000a2, 0x0000a6, 0x0000a8, 0x0000a9, 0x0000ac, 0x0000ac, 0x0000ae, 0x0000b1, 0x0000b4, 0x0000b4, 0x0000b8, 0x0000b8, 0x0000d7, 0x0000d7, 0x0000f7, 0x0000f7, 0x0002c2, 0x0002c5, 0x0002d2, 0x0002df, 0x0002e5, 0x0002eb, 0x0002ed, 0x0002ed, 0x0002ef, 0x0002ff, 0x000375, 0x000375, 0x000384, 0x000385, 0x0003f6, 0x0003f6, 0x000482, 0x000482, 0x00058d, 0x00058f, 0x000606, 0x000608, 0x00060b, 0x00060b, 0x00060e, 0x00060f, 0x0006de, 0x0006de, 0x0006e9, 0x0006e9, 0x0006fd, 0x0006fe, 0x0007f6, 0x0007f6, - 0x0007fe, 0x0007ff, 0x0009f2, 0x0009f3, 0x0009fa, 0x0009fb, 0x000af1, 0x000af1, 0x000b70, 0x000b70, 0x000bf3, 0x000bfa, 0x000c7f, 0x000c7f, 0x000d4f, 0x000d4f, 0x000d79, - 0x000d79, 0x000e3f, 0x000e3f, 0x000f01, 0x000f03, 0x000f13, 0x000f13, 0x000f15, 0x000f17, 0x000f1a, 0x000f1f, 0x000f34, 0x000f34, 0x000f36, 0x000f36, 0x000f38, 0x000f38, - 0x000fbe, 0x000fc5, 0x000fc7, 0x000fcc, 0x000fce, 0x000fcf, 0x000fd5, 0x000fd8, 0x00109e, 0x00109f, 0x001390, 0x001399, 0x00166d, 0x00166d, 0x0017db, 0x0017db, 0x001940, - 0x001940, 0x0019de, 0x0019ff, 0x001b61, 0x001b6a, 0x001b74, 0x001b7c, 0x001fbd, 0x001fbd, 0x001fbf, 0x001fc1, 0x001fcd, 0x001fcf, 0x001fdd, 0x001fdf, 0x001fed, 0x001fef, - 0x001ffd, 0x001ffe, 0x002044, 0x002044, 0x002052, 0x002052, 0x00207a, 0x00207c, 0x00208a, 0x00208c, 0x0020a0, 0x0020bf, 0x002100, 0x002101, 0x002103, 0x002106, 0x002108, - 0x002109, 0x002114, 0x002114, 0x002116, 0x002118, 0x00211e, 0x002123, 0x002125, 0x002125, 0x002127, 0x002127, 0x002129, 0x002129, 0x00212e, 0x00212e, 0x00213a, 0x00213b, - 0x002140, 0x002144, 0x00214a, 0x00214d, 0x00214f, 0x00214f, 0x00218a, 0x00218b, 0x002190, 0x002307, 0x00230c, 0x002328, 0x00232b, 0x002426, 0x002440, 0x00244a, 0x00249c, - 0x0024e9, 0x002500, 0x002767, 0x002794, 0x0027c4, 0x0027c7, 0x0027e5, 0x0027f0, 0x002982, 0x002999, 0x0029d7, 0x0029dc, 0x0029fb, 0x0029fe, 0x002b73, 0x002b76, 0x002b95, - 0x002b97, 0x002bff, 0x002ce5, 0x002cea, 0x002e50, 0x002e51, 0x002e80, 0x002e99, 0x002e9b, 0x002ef3, 0x002f00, 0x002fd5, 0x002ff0, 0x002ffb, 0x003004, 0x003004, 0x003012, - 0x003013, 0x003020, 0x003020, 0x003036, 0x003037, 0x00303e, 0x00303f, 0x00309b, 0x00309c, 0x003190, 0x003191, 0x003196, 0x00319f, 0x0031c0, 0x0031e3, 0x003200, 0x00321e, - 0x00322a, 0x003247, 0x003250, 0x003250, 0x003260, 0x00327f, 0x00328a, 0x0032b0, 0x0032c0, 0x0033ff, 0x004dc0, 0x004dff, 0x00a490, 0x00a4c6, 0x00a700, 0x00a716, 0x00a720, - 0x00a721, 0x00a789, 0x00a78a, 0x00a828, 0x00a82b, 0x00a836, 0x00a839, 0x00aa77, 0x00aa79, 0x00ab5b, 0x00ab5b, 0x00ab6a, 0x00ab6b, 0x00fb29, 0x00fb29, 0x00fbb2, 0x00fbc1, - 0x00fdfc, 0x00fdfd, 0x00fe62, 0x00fe62, 0x00fe64, 0x00fe66, 0x00fe69, 0x00fe69, 0x00ff04, 0x00ff04, 0x00ff0b, 0x00ff0b, 0x00ff1c, 0x00ff1e, 0x00ff3e, 0x00ff3e, 0x00ff40, - 0x00ff40, 0x00ff5c, 0x00ff5c, 0x00ff5e, 0x00ff5e, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, 0x00fffc, 0x00fffd, 0x010137, 0x01013f, 0x010179, 0x010189, 0x01018c, 0x01018e, - 0x010190, 0x01019c, 0x0101a0, 0x0101a0, 0x0101d0, 0x0101fc, 0x010877, 0x010878, 0x010ac8, 0x010ac8, 0x01173f, 0x01173f, 0x011fd5, 0x011ff1, 0x016b3c, 0x016b3f, 0x016b45, - 0x016b45, 0x01bc9c, 0x01bc9c, 0x01d000, 0x01d0f5, 0x01d100, 0x01d126, 0x01d129, 0x01d164, 0x01d16a, 0x01d16c, 0x01d183, 0x01d184, 0x01d18c, 0x01d1a9, 0x01d1ae, 0x01d1e8, - 0x01d200, 0x01d241, 0x01d245, 0x01d245, 0x01d300, 0x01d356, 0x01d6c1, 0x01d6c1, 0x01d6db, 0x01d6db, 0x01d6fb, 0x01d6fb, 0x01d715, 0x01d715, 0x01d735, 0x01d735, 0x01d74f, - 0x01d74f, 0x01d76f, 0x01d76f, 0x01d789, 0x01d789, 0x01d7a9, 0x01d7a9, 0x01d7c3, 0x01d7c3, 0x01d800, 0x01d9ff, 0x01da37, 0x01da3a, 0x01da6d, 0x01da74, 0x01da76, 0x01da83, - 0x01da85, 0x01da86, 0x01e14f, 0x01e14f, 0x01e2ff, 0x01e2ff, 0x01ecac, 0x01ecac, 0x01ecb0, 0x01ecb0, 0x01ed2e, 0x01ed2e, 0x01eef0, 0x01eef1, 0x01f000, 0x01f02b, 0x01f030, - 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, 0x01f10d, 0x01f1ad, 0x01f1e6, 0x01f202, 0x01f210, 0x01f23b, 0x01f240, 0x01f248, - 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6e0, 0x01f6ec, 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, 0x01f7e0, 0x01f7eb, 0x01f800, - 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01f978, 0x01f97a, 0x01f9cb, 0x01f9cd, 0x01fa53, - 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7a, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faa8, 0x01fab0, 0x01fab6, 0x01fac0, 0x01fac2, 0x01fad0, 0x01fad6, 0x01fb00, - 0x01fb92, 0x01fb94, 0x01fbca)); + 0x0007fe, 0x0007ff, 0x000888, 0x000888, 0x0009f2, 0x0009f3, 0x0009fa, 0x0009fb, 0x000af1, 0x000af1, 0x000b70, 0x000b70, 0x000bf3, 0x000bfa, 0x000c7f, 0x000c7f, 0x000d4f, + 0x000d4f, 0x000d79, 0x000d79, 0x000e3f, 0x000e3f, 0x000f01, 0x000f03, 0x000f13, 0x000f13, 0x000f15, 0x000f17, 0x000f1a, 0x000f1f, 0x000f34, 0x000f34, 0x000f36, 0x000f36, + 0x000f38, 0x000f38, 0x000fbe, 0x000fc5, 0x000fc7, 0x000fcc, 0x000fce, 0x000fcf, 0x000fd5, 0x000fd8, 0x00109e, 0x00109f, 0x001390, 0x001399, 0x00166d, 0x00166d, 0x0017db, + 0x0017db, 0x001940, 0x001940, 0x0019de, 0x0019ff, 0x001b61, 0x001b6a, 0x001b74, 0x001b7c, 0x001fbd, 0x001fbd, 0x001fbf, 0x001fc1, 0x001fcd, 0x001fcf, 0x001fdd, 0x001fdf, + 0x001fed, 0x001fef, 0x001ffd, 0x001ffe, 0x002044, 0x002044, 0x002052, 0x002052, 0x00207a, 0x00207c, 0x00208a, 0x00208c, 0x0020a0, 0x0020c0, 0x002100, 0x002101, 0x002103, + 0x002106, 0x002108, 0x002109, 0x002114, 0x002114, 0x002116, 0x002118, 0x00211e, 0x002123, 0x002125, 0x002125, 0x002127, 0x002127, 0x002129, 0x002129, 0x00212e, 0x00212e, + 0x00213a, 0x00213b, 0x002140, 0x002144, 0x00214a, 0x00214d, 0x00214f, 0x00214f, 0x00218a, 0x00218b, 0x002190, 0x002307, 0x00230c, 0x002328, 0x00232b, 0x002426, 0x002440, + 0x00244a, 0x00249c, 0x0024e9, 0x002500, 0x002767, 0x002794, 0x0027c4, 0x0027c7, 0x0027e5, 0x0027f0, 0x002982, 0x002999, 0x0029d7, 0x0029dc, 0x0029fb, 0x0029fe, 0x002b73, + 0x002b76, 0x002b95, 0x002b97, 0x002bff, 0x002ce5, 0x002cea, 0x002e50, 0x002e51, 0x002e80, 0x002e99, 0x002e9b, 0x002ef3, 0x002f00, 0x002fd5, 0x002ff0, 0x002ffb, 0x003004, + 0x003004, 0x003012, 0x003013, 0x003020, 0x003020, 0x003036, 0x003037, 0x00303e, 0x00303f, 0x00309b, 0x00309c, 0x003190, 0x003191, 0x003196, 0x00319f, 0x0031c0, 0x0031e3, + 0x003200, 0x00321e, 0x00322a, 0x003247, 0x003250, 0x003250, 0x003260, 0x00327f, 0x00328a, 0x0032b0, 0x0032c0, 0x0033ff, 0x004dc0, 0x004dff, 0x00a490, 0x00a4c6, 0x00a700, + 0x00a716, 0x00a720, 0x00a721, 0x00a789, 0x00a78a, 0x00a828, 0x00a82b, 0x00a836, 0x00a839, 0x00aa77, 0x00aa79, 0x00ab5b, 0x00ab5b, 0x00ab6a, 0x00ab6b, 0x00fb29, 0x00fb29, + 0x00fbb2, 0x00fbc2, 0x00fd40, 0x00fd4f, 0x00fdcf, 0x00fdcf, 0x00fdfc, 0x00fdff, 0x00fe62, 0x00fe62, 0x00fe64, 0x00fe66, 0x00fe69, 0x00fe69, 0x00ff04, 0x00ff04, 0x00ff0b, + 0x00ff0b, 0x00ff1c, 0x00ff1e, 0x00ff3e, 0x00ff3e, 0x00ff40, 0x00ff40, 0x00ff5c, 0x00ff5c, 0x00ff5e, 0x00ff5e, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, 0x00fffc, 0x00fffd, + 0x010137, 0x01013f, 0x010179, 0x010189, 0x01018c, 0x01018e, 0x010190, 0x01019c, 0x0101a0, 0x0101a0, 0x0101d0, 0x0101fc, 0x010877, 0x010878, 0x010ac8, 0x010ac8, 0x01173f, + 0x01173f, 0x011fd5, 0x011ff1, 0x016b3c, 0x016b3f, 0x016b45, 0x016b45, 0x01bc9c, 0x01bc9c, 0x01cf50, 0x01cfc3, 0x01d000, 0x01d0f5, 0x01d100, 0x01d126, 0x01d129, 0x01d164, + 0x01d16a, 0x01d16c, 0x01d183, 0x01d184, 0x01d18c, 0x01d1a9, 0x01d1ae, 0x01d1ea, 0x01d200, 0x01d241, 0x01d245, 0x01d245, 0x01d300, 0x01d356, 0x01d6c1, 0x01d6c1, 0x01d6db, + 0x01d6db, 0x01d6fb, 0x01d6fb, 0x01d715, 0x01d715, 0x01d735, 0x01d735, 0x01d74f, 0x01d74f, 0x01d76f, 0x01d76f, 0x01d789, 0x01d789, 0x01d7a9, 0x01d7a9, 0x01d7c3, 0x01d7c3, + 0x01d800, 0x01d9ff, 0x01da37, 0x01da3a, 0x01da6d, 0x01da74, 0x01da76, 0x01da83, 0x01da85, 0x01da86, 0x01e14f, 0x01e14f, 0x01e2ff, 0x01e2ff, 0x01ecac, 0x01ecac, 0x01ecb0, + 0x01ecb0, 0x01ed2e, 0x01ed2e, 0x01eef0, 0x01eef1, 0x01f000, 0x01f02b, 0x01f030, 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, + 0x01f10d, 0x01f1ad, 0x01f1e6, 0x01f202, 0x01f210, 0x01f23b, 0x01f240, 0x01f248, 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6dd, 0x01f6ec, 0x01f6f0, + 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, 0x01f7e0, 0x01f7eb, 0x01f7f0, 0x01f7f0, 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, + 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01fa53, 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7c, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faac, 0x01fab0, + 0x01faba, 0x01fac0, 0x01fac5, 0x01fad0, 0x01fad9, 0x01fae0, 0x01fae7, 0x01faf0, 0x01faf6, 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca)); GENERAL_CATEGORIES.put("gc=Z", CodePointSet.createNoDedup(0x000020, 0x000020, 0x0000a0, 0x0000a0, 0x001680, 0x001680, 0x002000, 0x00200a, 0x002028, 0x002029, 0x00202f, 0x00202f, 0x00205f, 0x00205f, 0x003000, 0x003000)); GENERAL_CATEGORIES.put("gc=C", CodePointSet.createNoDedup(0x000000, 0x00001f, 0x00007f, 0x00009f, 0x0000ad, 0x0000ad, 0x000378, 0x000379, 0x000380, 0x000383, 0x00038b, 0x00038b, 0x00038d, 0x00038d, 0x0003a2, 0x0003a2, 0x000530, 0x000530, 0x000557, 0x000558, 0x00058b, 0x00058c, 0x000590, 0x000590, 0x0005c8, 0x0005cf, 0x0005eb, 0x0005ee, 0x0005f5, 0x000605, - 0x00061c, 0x00061d, 0x0006dd, 0x0006dd, 0x00070e, 0x00070f, 0x00074b, 0x00074c, 0x0007b2, 0x0007bf, 0x0007fb, 0x0007fc, 0x00082e, 0x00082f, 0x00083f, 0x00083f, 0x00085c, - 0x00085d, 0x00085f, 0x00085f, 0x00086b, 0x00089f, 0x0008b5, 0x0008b5, 0x0008c8, 0x0008d2, 0x0008e2, 0x0008e2, 0x000984, 0x000984, 0x00098d, 0x00098e, 0x000991, 0x000992, - 0x0009a9, 0x0009a9, 0x0009b1, 0x0009b1, 0x0009b3, 0x0009b5, 0x0009ba, 0x0009bb, 0x0009c5, 0x0009c6, 0x0009c9, 0x0009ca, 0x0009cf, 0x0009d6, 0x0009d8, 0x0009db, 0x0009de, - 0x0009de, 0x0009e4, 0x0009e5, 0x0009ff, 0x000a00, 0x000a04, 0x000a04, 0x000a0b, 0x000a0e, 0x000a11, 0x000a12, 0x000a29, 0x000a29, 0x000a31, 0x000a31, 0x000a34, 0x000a34, - 0x000a37, 0x000a37, 0x000a3a, 0x000a3b, 0x000a3d, 0x000a3d, 0x000a43, 0x000a46, 0x000a49, 0x000a4a, 0x000a4e, 0x000a50, 0x000a52, 0x000a58, 0x000a5d, 0x000a5d, 0x000a5f, - 0x000a65, 0x000a77, 0x000a80, 0x000a84, 0x000a84, 0x000a8e, 0x000a8e, 0x000a92, 0x000a92, 0x000aa9, 0x000aa9, 0x000ab1, 0x000ab1, 0x000ab4, 0x000ab4, 0x000aba, 0x000abb, - 0x000ac6, 0x000ac6, 0x000aca, 0x000aca, 0x000ace, 0x000acf, 0x000ad1, 0x000adf, 0x000ae4, 0x000ae5, 0x000af2, 0x000af8, 0x000b00, 0x000b00, 0x000b04, 0x000b04, 0x000b0d, - 0x000b0e, 0x000b11, 0x000b12, 0x000b29, 0x000b29, 0x000b31, 0x000b31, 0x000b34, 0x000b34, 0x000b3a, 0x000b3b, 0x000b45, 0x000b46, 0x000b49, 0x000b4a, 0x000b4e, 0x000b54, - 0x000b58, 0x000b5b, 0x000b5e, 0x000b5e, 0x000b64, 0x000b65, 0x000b78, 0x000b81, 0x000b84, 0x000b84, 0x000b8b, 0x000b8d, 0x000b91, 0x000b91, 0x000b96, 0x000b98, 0x000b9b, - 0x000b9b, 0x000b9d, 0x000b9d, 0x000ba0, 0x000ba2, 0x000ba5, 0x000ba7, 0x000bab, 0x000bad, 0x000bba, 0x000bbd, 0x000bc3, 0x000bc5, 0x000bc9, 0x000bc9, 0x000bce, 0x000bcf, - 0x000bd1, 0x000bd6, 0x000bd8, 0x000be5, 0x000bfb, 0x000bff, 0x000c0d, 0x000c0d, 0x000c11, 0x000c11, 0x000c29, 0x000c29, 0x000c3a, 0x000c3c, 0x000c45, 0x000c45, 0x000c49, - 0x000c49, 0x000c4e, 0x000c54, 0x000c57, 0x000c57, 0x000c5b, 0x000c5f, 0x000c64, 0x000c65, 0x000c70, 0x000c76, 0x000c8d, 0x000c8d, 0x000c91, 0x000c91, 0x000ca9, 0x000ca9, - 0x000cb4, 0x000cb4, 0x000cba, 0x000cbb, 0x000cc5, 0x000cc5, 0x000cc9, 0x000cc9, 0x000cce, 0x000cd4, 0x000cd7, 0x000cdd, 0x000cdf, 0x000cdf, 0x000ce4, 0x000ce5, 0x000cf0, + 0x00061c, 0x00061c, 0x0006dd, 0x0006dd, 0x00070e, 0x00070f, 0x00074b, 0x00074c, 0x0007b2, 0x0007bf, 0x0007fb, 0x0007fc, 0x00082e, 0x00082f, 0x00083f, 0x00083f, 0x00085c, + 0x00085d, 0x00085f, 0x00085f, 0x00086b, 0x00086f, 0x00088f, 0x000897, 0x0008e2, 0x0008e2, 0x000984, 0x000984, 0x00098d, 0x00098e, 0x000991, 0x000992, 0x0009a9, 0x0009a9, + 0x0009b1, 0x0009b1, 0x0009b3, 0x0009b5, 0x0009ba, 0x0009bb, 0x0009c5, 0x0009c6, 0x0009c9, 0x0009ca, 0x0009cf, 0x0009d6, 0x0009d8, 0x0009db, 0x0009de, 0x0009de, 0x0009e4, + 0x0009e5, 0x0009ff, 0x000a00, 0x000a04, 0x000a04, 0x000a0b, 0x000a0e, 0x000a11, 0x000a12, 0x000a29, 0x000a29, 0x000a31, 0x000a31, 0x000a34, 0x000a34, 0x000a37, 0x000a37, + 0x000a3a, 0x000a3b, 0x000a3d, 0x000a3d, 0x000a43, 0x000a46, 0x000a49, 0x000a4a, 0x000a4e, 0x000a50, 0x000a52, 0x000a58, 0x000a5d, 0x000a5d, 0x000a5f, 0x000a65, 0x000a77, + 0x000a80, 0x000a84, 0x000a84, 0x000a8e, 0x000a8e, 0x000a92, 0x000a92, 0x000aa9, 0x000aa9, 0x000ab1, 0x000ab1, 0x000ab4, 0x000ab4, 0x000aba, 0x000abb, 0x000ac6, 0x000ac6, + 0x000aca, 0x000aca, 0x000ace, 0x000acf, 0x000ad1, 0x000adf, 0x000ae4, 0x000ae5, 0x000af2, 0x000af8, 0x000b00, 0x000b00, 0x000b04, 0x000b04, 0x000b0d, 0x000b0e, 0x000b11, + 0x000b12, 0x000b29, 0x000b29, 0x000b31, 0x000b31, 0x000b34, 0x000b34, 0x000b3a, 0x000b3b, 0x000b45, 0x000b46, 0x000b49, 0x000b4a, 0x000b4e, 0x000b54, 0x000b58, 0x000b5b, + 0x000b5e, 0x000b5e, 0x000b64, 0x000b65, 0x000b78, 0x000b81, 0x000b84, 0x000b84, 0x000b8b, 0x000b8d, 0x000b91, 0x000b91, 0x000b96, 0x000b98, 0x000b9b, 0x000b9b, 0x000b9d, + 0x000b9d, 0x000ba0, 0x000ba2, 0x000ba5, 0x000ba7, 0x000bab, 0x000bad, 0x000bba, 0x000bbd, 0x000bc3, 0x000bc5, 0x000bc9, 0x000bc9, 0x000bce, 0x000bcf, 0x000bd1, 0x000bd6, + 0x000bd8, 0x000be5, 0x000bfb, 0x000bff, 0x000c0d, 0x000c0d, 0x000c11, 0x000c11, 0x000c29, 0x000c29, 0x000c3a, 0x000c3b, 0x000c45, 0x000c45, 0x000c49, 0x000c49, 0x000c4e, + 0x000c54, 0x000c57, 0x000c57, 0x000c5b, 0x000c5c, 0x000c5e, 0x000c5f, 0x000c64, 0x000c65, 0x000c70, 0x000c76, 0x000c8d, 0x000c8d, 0x000c91, 0x000c91, 0x000ca9, 0x000ca9, + 0x000cb4, 0x000cb4, 0x000cba, 0x000cbb, 0x000cc5, 0x000cc5, 0x000cc9, 0x000cc9, 0x000cce, 0x000cd4, 0x000cd7, 0x000cdc, 0x000cdf, 0x000cdf, 0x000ce4, 0x000ce5, 0x000cf0, 0x000cf0, 0x000cf3, 0x000cff, 0x000d0d, 0x000d0d, 0x000d11, 0x000d11, 0x000d45, 0x000d45, 0x000d49, 0x000d49, 0x000d50, 0x000d53, 0x000d64, 0x000d65, 0x000d80, 0x000d80, 0x000d84, 0x000d84, 0x000d97, 0x000d99, 0x000db2, 0x000db2, 0x000dbc, 0x000dbc, 0x000dbe, 0x000dbf, 0x000dc7, 0x000dc9, 0x000dcb, 0x000dce, 0x000dd5, 0x000dd5, 0x000dd7, 0x000dd7, 0x000de0, 0x000de5, 0x000df0, 0x000df1, 0x000df5, 0x000e00, 0x000e3b, 0x000e3e, 0x000e5c, 0x000e80, 0x000e83, 0x000e83, 0x000e85, 0x000e85, 0x000e8b, 0x000e8b, @@ -269,64 +275,66 @@ static CodePointSet getGeneralCategory(String name) { 0x000f48, 0x000f6d, 0x000f70, 0x000f98, 0x000f98, 0x000fbd, 0x000fbd, 0x000fcd, 0x000fcd, 0x000fdb, 0x000fff, 0x0010c6, 0x0010c6, 0x0010c8, 0x0010cc, 0x0010ce, 0x0010cf, 0x001249, 0x001249, 0x00124e, 0x00124f, 0x001257, 0x001257, 0x001259, 0x001259, 0x00125e, 0x00125f, 0x001289, 0x001289, 0x00128e, 0x00128f, 0x0012b1, 0x0012b1, 0x0012b6, 0x0012b7, 0x0012bf, 0x0012bf, 0x0012c1, 0x0012c1, 0x0012c6, 0x0012c7, 0x0012d7, 0x0012d7, 0x001311, 0x001311, 0x001316, 0x001317, 0x00135b, 0x00135c, 0x00137d, 0x00137f, - 0x00139a, 0x00139f, 0x0013f6, 0x0013f7, 0x0013fe, 0x0013ff, 0x00169d, 0x00169f, 0x0016f9, 0x0016ff, 0x00170d, 0x00170d, 0x001715, 0x00171f, 0x001737, 0x00173f, 0x001754, - 0x00175f, 0x00176d, 0x00176d, 0x001771, 0x001771, 0x001774, 0x00177f, 0x0017de, 0x0017df, 0x0017ea, 0x0017ef, 0x0017fa, 0x0017ff, 0x00180e, 0x00180f, 0x00181a, 0x00181f, - 0x001879, 0x00187f, 0x0018ab, 0x0018af, 0x0018f6, 0x0018ff, 0x00191f, 0x00191f, 0x00192c, 0x00192f, 0x00193c, 0x00193f, 0x001941, 0x001943, 0x00196e, 0x00196f, 0x001975, - 0x00197f, 0x0019ac, 0x0019af, 0x0019ca, 0x0019cf, 0x0019db, 0x0019dd, 0x001a1c, 0x001a1d, 0x001a5f, 0x001a5f, 0x001a7d, 0x001a7e, 0x001a8a, 0x001a8f, 0x001a9a, 0x001a9f, - 0x001aae, 0x001aaf, 0x001ac1, 0x001aff, 0x001b4c, 0x001b4f, 0x001b7d, 0x001b7f, 0x001bf4, 0x001bfb, 0x001c38, 0x001c3a, 0x001c4a, 0x001c4c, 0x001c89, 0x001c8f, 0x001cbb, - 0x001cbc, 0x001cc8, 0x001ccf, 0x001cfb, 0x001cff, 0x001dfa, 0x001dfa, 0x001f16, 0x001f17, 0x001f1e, 0x001f1f, 0x001f46, 0x001f47, 0x001f4e, 0x001f4f, 0x001f58, 0x001f58, - 0x001f5a, 0x001f5a, 0x001f5c, 0x001f5c, 0x001f5e, 0x001f5e, 0x001f7e, 0x001f7f, 0x001fb5, 0x001fb5, 0x001fc5, 0x001fc5, 0x001fd4, 0x001fd5, 0x001fdc, 0x001fdc, 0x001ff0, - 0x001ff1, 0x001ff5, 0x001ff5, 0x001fff, 0x001fff, 0x00200b, 0x00200f, 0x00202a, 0x00202e, 0x002060, 0x00206f, 0x002072, 0x002073, 0x00208f, 0x00208f, 0x00209d, 0x00209f, - 0x0020c0, 0x0020cf, 0x0020f1, 0x0020ff, 0x00218c, 0x00218f, 0x002427, 0x00243f, 0x00244b, 0x00245f, 0x002b74, 0x002b75, 0x002b96, 0x002b96, 0x002c2f, 0x002c2f, 0x002c5f, - 0x002c5f, 0x002cf4, 0x002cf8, 0x002d26, 0x002d26, 0x002d28, 0x002d2c, 0x002d2e, 0x002d2f, 0x002d68, 0x002d6e, 0x002d71, 0x002d7e, 0x002d97, 0x002d9f, 0x002da7, 0x002da7, - 0x002daf, 0x002daf, 0x002db7, 0x002db7, 0x002dbf, 0x002dbf, 0x002dc7, 0x002dc7, 0x002dcf, 0x002dcf, 0x002dd7, 0x002dd7, 0x002ddf, 0x002ddf, 0x002e53, 0x002e7f, 0x002e9a, - 0x002e9a, 0x002ef4, 0x002eff, 0x002fd6, 0x002fef, 0x002ffc, 0x002fff, 0x003040, 0x003040, 0x003097, 0x003098, 0x003100, 0x003104, 0x003130, 0x003130, 0x00318f, 0x00318f, - 0x0031e4, 0x0031ef, 0x00321f, 0x00321f, 0x009ffd, 0x009fff, 0x00a48d, 0x00a48f, 0x00a4c7, 0x00a4cf, 0x00a62c, 0x00a63f, 0x00a6f8, 0x00a6ff, 0x00a7c0, 0x00a7c1, 0x00a7cb, - 0x00a7f4, 0x00a82d, 0x00a82f, 0x00a83a, 0x00a83f, 0x00a878, 0x00a87f, 0x00a8c6, 0x00a8cd, 0x00a8da, 0x00a8df, 0x00a954, 0x00a95e, 0x00a97d, 0x00a97f, 0x00a9ce, 0x00a9ce, - 0x00a9da, 0x00a9dd, 0x00a9ff, 0x00a9ff, 0x00aa37, 0x00aa3f, 0x00aa4e, 0x00aa4f, 0x00aa5a, 0x00aa5b, 0x00aac3, 0x00aada, 0x00aaf7, 0x00ab00, 0x00ab07, 0x00ab08, 0x00ab0f, - 0x00ab10, 0x00ab17, 0x00ab1f, 0x00ab27, 0x00ab27, 0x00ab2f, 0x00ab2f, 0x00ab6c, 0x00ab6f, 0x00abee, 0x00abef, 0x00abfa, 0x00abff, 0x00d7a4, 0x00d7af, 0x00d7c7, 0x00d7ca, - 0x00d7fc, 0x00f8ff, 0x00fa6e, 0x00fa6f, 0x00fada, 0x00faff, 0x00fb07, 0x00fb12, 0x00fb18, 0x00fb1c, 0x00fb37, 0x00fb37, 0x00fb3d, 0x00fb3d, 0x00fb3f, 0x00fb3f, 0x00fb42, - 0x00fb42, 0x00fb45, 0x00fb45, 0x00fbc2, 0x00fbd2, 0x00fd40, 0x00fd4f, 0x00fd90, 0x00fd91, 0x00fdc8, 0x00fdef, 0x00fdfe, 0x00fdff, 0x00fe1a, 0x00fe1f, 0x00fe53, 0x00fe53, - 0x00fe67, 0x00fe67, 0x00fe6c, 0x00fe6f, 0x00fe75, 0x00fe75, 0x00fefd, 0x00ff00, 0x00ffbf, 0x00ffc1, 0x00ffc8, 0x00ffc9, 0x00ffd0, 0x00ffd1, 0x00ffd8, 0x00ffd9, 0x00ffdd, - 0x00ffdf, 0x00ffe7, 0x00ffe7, 0x00ffef, 0x00fffb, 0x00fffe, 0x00ffff, 0x01000c, 0x01000c, 0x010027, 0x010027, 0x01003b, 0x01003b, 0x01003e, 0x01003e, 0x01004e, 0x01004f, - 0x01005e, 0x01007f, 0x0100fb, 0x0100ff, 0x010103, 0x010106, 0x010134, 0x010136, 0x01018f, 0x01018f, 0x01019d, 0x01019f, 0x0101a1, 0x0101cf, 0x0101fe, 0x01027f, 0x01029d, - 0x01029f, 0x0102d1, 0x0102df, 0x0102fc, 0x0102ff, 0x010324, 0x01032c, 0x01034b, 0x01034f, 0x01037b, 0x01037f, 0x01039e, 0x01039e, 0x0103c4, 0x0103c7, 0x0103d6, 0x0103ff, - 0x01049e, 0x01049f, 0x0104aa, 0x0104af, 0x0104d4, 0x0104d7, 0x0104fc, 0x0104ff, 0x010528, 0x01052f, 0x010564, 0x01056e, 0x010570, 0x0105ff, 0x010737, 0x01073f, 0x010756, - 0x01075f, 0x010768, 0x0107ff, 0x010806, 0x010807, 0x010809, 0x010809, 0x010836, 0x010836, 0x010839, 0x01083b, 0x01083d, 0x01083e, 0x010856, 0x010856, 0x01089f, 0x0108a6, - 0x0108b0, 0x0108df, 0x0108f3, 0x0108f3, 0x0108f6, 0x0108fa, 0x01091c, 0x01091e, 0x01093a, 0x01093e, 0x010940, 0x01097f, 0x0109b8, 0x0109bb, 0x0109d0, 0x0109d1, 0x010a04, - 0x010a04, 0x010a07, 0x010a0b, 0x010a14, 0x010a14, 0x010a18, 0x010a18, 0x010a36, 0x010a37, 0x010a3b, 0x010a3e, 0x010a49, 0x010a4f, 0x010a59, 0x010a5f, 0x010aa0, 0x010abf, - 0x010ae7, 0x010aea, 0x010af7, 0x010aff, 0x010b36, 0x010b38, 0x010b56, 0x010b57, 0x010b73, 0x010b77, 0x010b92, 0x010b98, 0x010b9d, 0x010ba8, 0x010bb0, 0x010bff, 0x010c49, - 0x010c7f, 0x010cb3, 0x010cbf, 0x010cf3, 0x010cf9, 0x010d28, 0x010d2f, 0x010d3a, 0x010e5f, 0x010e7f, 0x010e7f, 0x010eaa, 0x010eaa, 0x010eae, 0x010eaf, 0x010eb2, 0x010eff, - 0x010f28, 0x010f2f, 0x010f5a, 0x010faf, 0x010fcc, 0x010fdf, 0x010ff7, 0x010fff, 0x01104e, 0x011051, 0x011070, 0x01107e, 0x0110bd, 0x0110bd, 0x0110c2, 0x0110cf, 0x0110e9, - 0x0110ef, 0x0110fa, 0x0110ff, 0x011135, 0x011135, 0x011148, 0x01114f, 0x011177, 0x01117f, 0x0111e0, 0x0111e0, 0x0111f5, 0x0111ff, 0x011212, 0x011212, 0x01123f, 0x01127f, - 0x011287, 0x011287, 0x011289, 0x011289, 0x01128e, 0x01128e, 0x01129e, 0x01129e, 0x0112aa, 0x0112af, 0x0112eb, 0x0112ef, 0x0112fa, 0x0112ff, 0x011304, 0x011304, 0x01130d, - 0x01130e, 0x011311, 0x011312, 0x011329, 0x011329, 0x011331, 0x011331, 0x011334, 0x011334, 0x01133a, 0x01133a, 0x011345, 0x011346, 0x011349, 0x01134a, 0x01134e, 0x01134f, - 0x011351, 0x011356, 0x011358, 0x01135c, 0x011364, 0x011365, 0x01136d, 0x01136f, 0x011375, 0x0113ff, 0x01145c, 0x01145c, 0x011462, 0x01147f, 0x0114c8, 0x0114cf, 0x0114da, - 0x01157f, 0x0115b6, 0x0115b7, 0x0115de, 0x0115ff, 0x011645, 0x01164f, 0x01165a, 0x01165f, 0x01166d, 0x01167f, 0x0116b9, 0x0116bf, 0x0116ca, 0x0116ff, 0x01171b, 0x01171c, - 0x01172c, 0x01172f, 0x011740, 0x0117ff, 0x01183c, 0x01189f, 0x0118f3, 0x0118fe, 0x011907, 0x011908, 0x01190a, 0x01190b, 0x011914, 0x011914, 0x011917, 0x011917, 0x011936, - 0x011936, 0x011939, 0x01193a, 0x011947, 0x01194f, 0x01195a, 0x01199f, 0x0119a8, 0x0119a9, 0x0119d8, 0x0119d9, 0x0119e5, 0x0119ff, 0x011a48, 0x011a4f, 0x011aa3, 0x011abf, - 0x011af9, 0x011bff, 0x011c09, 0x011c09, 0x011c37, 0x011c37, 0x011c46, 0x011c4f, 0x011c6d, 0x011c6f, 0x011c90, 0x011c91, 0x011ca8, 0x011ca8, 0x011cb7, 0x011cff, 0x011d07, - 0x011d07, 0x011d0a, 0x011d0a, 0x011d37, 0x011d39, 0x011d3b, 0x011d3b, 0x011d3e, 0x011d3e, 0x011d48, 0x011d4f, 0x011d5a, 0x011d5f, 0x011d66, 0x011d66, 0x011d69, 0x011d69, - 0x011d8f, 0x011d8f, 0x011d92, 0x011d92, 0x011d99, 0x011d9f, 0x011daa, 0x011edf, 0x011ef9, 0x011faf, 0x011fb1, 0x011fbf, 0x011ff2, 0x011ffe, 0x01239a, 0x0123ff, 0x01246f, - 0x01246f, 0x012475, 0x01247f, 0x012544, 0x012fff, 0x01342f, 0x0143ff, 0x014647, 0x0167ff, 0x016a39, 0x016a3f, 0x016a5f, 0x016a5f, 0x016a6a, 0x016a6d, 0x016a70, 0x016acf, - 0x016aee, 0x016aef, 0x016af6, 0x016aff, 0x016b46, 0x016b4f, 0x016b5a, 0x016b5a, 0x016b62, 0x016b62, 0x016b78, 0x016b7c, 0x016b90, 0x016e3f, 0x016e9b, 0x016eff, 0x016f4b, - 0x016f4e, 0x016f88, 0x016f8e, 0x016fa0, 0x016fdf, 0x016fe5, 0x016fef, 0x016ff2, 0x016fff, 0x0187f8, 0x0187ff, 0x018cd6, 0x018cff, 0x018d09, 0x01afff, 0x01b11f, 0x01b14f, - 0x01b153, 0x01b163, 0x01b168, 0x01b16f, 0x01b2fc, 0x01bbff, 0x01bc6b, 0x01bc6f, 0x01bc7d, 0x01bc7f, 0x01bc89, 0x01bc8f, 0x01bc9a, 0x01bc9b, 0x01bca0, 0x01cfff, 0x01d0f6, - 0x01d0ff, 0x01d127, 0x01d128, 0x01d173, 0x01d17a, 0x01d1e9, 0x01d1ff, 0x01d246, 0x01d2df, 0x01d2f4, 0x01d2ff, 0x01d357, 0x01d35f, 0x01d379, 0x01d3ff, 0x01d455, 0x01d455, - 0x01d49d, 0x01d49d, 0x01d4a0, 0x01d4a1, 0x01d4a3, 0x01d4a4, 0x01d4a7, 0x01d4a8, 0x01d4ad, 0x01d4ad, 0x01d4ba, 0x01d4ba, 0x01d4bc, 0x01d4bc, 0x01d4c4, 0x01d4c4, 0x01d506, - 0x01d506, 0x01d50b, 0x01d50c, 0x01d515, 0x01d515, 0x01d51d, 0x01d51d, 0x01d53a, 0x01d53a, 0x01d53f, 0x01d53f, 0x01d545, 0x01d545, 0x01d547, 0x01d549, 0x01d551, 0x01d551, - 0x01d6a6, 0x01d6a7, 0x01d7cc, 0x01d7cd, 0x01da8c, 0x01da9a, 0x01daa0, 0x01daa0, 0x01dab0, 0x01dfff, 0x01e007, 0x01e007, 0x01e019, 0x01e01a, 0x01e022, 0x01e022, 0x01e025, - 0x01e025, 0x01e02b, 0x01e0ff, 0x01e12d, 0x01e12f, 0x01e13e, 0x01e13f, 0x01e14a, 0x01e14d, 0x01e150, 0x01e2bf, 0x01e2fa, 0x01e2fe, 0x01e300, 0x01e7ff, 0x01e8c5, 0x01e8c6, - 0x01e8d7, 0x01e8ff, 0x01e94c, 0x01e94f, 0x01e95a, 0x01e95d, 0x01e960, 0x01ec70, 0x01ecb5, 0x01ed00, 0x01ed3e, 0x01edff, 0x01ee04, 0x01ee04, 0x01ee20, 0x01ee20, 0x01ee23, - 0x01ee23, 0x01ee25, 0x01ee26, 0x01ee28, 0x01ee28, 0x01ee33, 0x01ee33, 0x01ee38, 0x01ee38, 0x01ee3a, 0x01ee3a, 0x01ee3c, 0x01ee41, 0x01ee43, 0x01ee46, 0x01ee48, 0x01ee48, - 0x01ee4a, 0x01ee4a, 0x01ee4c, 0x01ee4c, 0x01ee50, 0x01ee50, 0x01ee53, 0x01ee53, 0x01ee55, 0x01ee56, 0x01ee58, 0x01ee58, 0x01ee5a, 0x01ee5a, 0x01ee5c, 0x01ee5c, 0x01ee5e, - 0x01ee5e, 0x01ee60, 0x01ee60, 0x01ee63, 0x01ee63, 0x01ee65, 0x01ee66, 0x01ee6b, 0x01ee6b, 0x01ee73, 0x01ee73, 0x01ee78, 0x01ee78, 0x01ee7d, 0x01ee7d, 0x01ee7f, 0x01ee7f, - 0x01ee8a, 0x01ee8a, 0x01ee9c, 0x01eea0, 0x01eea4, 0x01eea4, 0x01eeaa, 0x01eeaa, 0x01eebc, 0x01eeef, 0x01eef2, 0x01efff, 0x01f02c, 0x01f02f, 0x01f094, 0x01f09f, 0x01f0af, - 0x01f0b0, 0x01f0c0, 0x01f0c0, 0x01f0d0, 0x01f0d0, 0x01f0f6, 0x01f0ff, 0x01f1ae, 0x01f1e5, 0x01f203, 0x01f20f, 0x01f23c, 0x01f23f, 0x01f249, 0x01f24f, 0x01f252, 0x01f25f, - 0x01f266, 0x01f2ff, 0x01f6d8, 0x01f6df, 0x01f6ed, 0x01f6ef, 0x01f6fd, 0x01f6ff, 0x01f774, 0x01f77f, 0x01f7d9, 0x01f7df, 0x01f7ec, 0x01f7ff, 0x01f80c, 0x01f80f, 0x01f848, - 0x01f84f, 0x01f85a, 0x01f85f, 0x01f888, 0x01f88f, 0x01f8ae, 0x01f8af, 0x01f8b2, 0x01f8ff, 0x01f979, 0x01f979, 0x01f9cc, 0x01f9cc, 0x01fa54, 0x01fa5f, 0x01fa6e, 0x01fa6f, - 0x01fa75, 0x01fa77, 0x01fa7b, 0x01fa7f, 0x01fa87, 0x01fa8f, 0x01faa9, 0x01faaf, 0x01fab7, 0x01fabf, 0x01fac3, 0x01facf, 0x01fad7, 0x01faff, 0x01fb93, 0x01fb93, 0x01fbcb, - 0x01fbef, 0x01fbfa, 0x01ffff, 0x02a6de, 0x02a6ff, 0x02b735, 0x02b73f, 0x02b81e, 0x02b81f, 0x02cea2, 0x02ceaf, 0x02ebe1, 0x02f7ff, 0x02fa1e, 0x02ffff, 0x03134b, 0x0e00ff, - 0x0e01f0, 0x10ffff)); + 0x00139a, 0x00139f, 0x0013f6, 0x0013f7, 0x0013fe, 0x0013ff, 0x00169d, 0x00169f, 0x0016f9, 0x0016ff, 0x001716, 0x00171e, 0x001737, 0x00173f, 0x001754, 0x00175f, 0x00176d, + 0x00176d, 0x001771, 0x001771, 0x001774, 0x00177f, 0x0017de, 0x0017df, 0x0017ea, 0x0017ef, 0x0017fa, 0x0017ff, 0x00180e, 0x00180e, 0x00181a, 0x00181f, 0x001879, 0x00187f, + 0x0018ab, 0x0018af, 0x0018f6, 0x0018ff, 0x00191f, 0x00191f, 0x00192c, 0x00192f, 0x00193c, 0x00193f, 0x001941, 0x001943, 0x00196e, 0x00196f, 0x001975, 0x00197f, 0x0019ac, + 0x0019af, 0x0019ca, 0x0019cf, 0x0019db, 0x0019dd, 0x001a1c, 0x001a1d, 0x001a5f, 0x001a5f, 0x001a7d, 0x001a7e, 0x001a8a, 0x001a8f, 0x001a9a, 0x001a9f, 0x001aae, 0x001aaf, + 0x001acf, 0x001aff, 0x001b4d, 0x001b4f, 0x001b7f, 0x001b7f, 0x001bf4, 0x001bfb, 0x001c38, 0x001c3a, 0x001c4a, 0x001c4c, 0x001c89, 0x001c8f, 0x001cbb, 0x001cbc, 0x001cc8, + 0x001ccf, 0x001cfb, 0x001cff, 0x001f16, 0x001f17, 0x001f1e, 0x001f1f, 0x001f46, 0x001f47, 0x001f4e, 0x001f4f, 0x001f58, 0x001f58, 0x001f5a, 0x001f5a, 0x001f5c, 0x001f5c, + 0x001f5e, 0x001f5e, 0x001f7e, 0x001f7f, 0x001fb5, 0x001fb5, 0x001fc5, 0x001fc5, 0x001fd4, 0x001fd5, 0x001fdc, 0x001fdc, 0x001ff0, 0x001ff1, 0x001ff5, 0x001ff5, 0x001fff, + 0x001fff, 0x00200b, 0x00200f, 0x00202a, 0x00202e, 0x002060, 0x00206f, 0x002072, 0x002073, 0x00208f, 0x00208f, 0x00209d, 0x00209f, 0x0020c1, 0x0020cf, 0x0020f1, 0x0020ff, + 0x00218c, 0x00218f, 0x002427, 0x00243f, 0x00244b, 0x00245f, 0x002b74, 0x002b75, 0x002b96, 0x002b96, 0x002cf4, 0x002cf8, 0x002d26, 0x002d26, 0x002d28, 0x002d2c, 0x002d2e, + 0x002d2f, 0x002d68, 0x002d6e, 0x002d71, 0x002d7e, 0x002d97, 0x002d9f, 0x002da7, 0x002da7, 0x002daf, 0x002daf, 0x002db7, 0x002db7, 0x002dbf, 0x002dbf, 0x002dc7, 0x002dc7, + 0x002dcf, 0x002dcf, 0x002dd7, 0x002dd7, 0x002ddf, 0x002ddf, 0x002e5e, 0x002e7f, 0x002e9a, 0x002e9a, 0x002ef4, 0x002eff, 0x002fd6, 0x002fef, 0x002ffc, 0x002fff, 0x003040, + 0x003040, 0x003097, 0x003098, 0x003100, 0x003104, 0x003130, 0x003130, 0x00318f, 0x00318f, 0x0031e4, 0x0031ef, 0x00321f, 0x00321f, 0x00a48d, 0x00a48f, 0x00a4c7, 0x00a4cf, + 0x00a62c, 0x00a63f, 0x00a6f8, 0x00a6ff, 0x00a7cb, 0x00a7cf, 0x00a7d2, 0x00a7d2, 0x00a7d4, 0x00a7d4, 0x00a7da, 0x00a7f1, 0x00a82d, 0x00a82f, 0x00a83a, 0x00a83f, 0x00a878, + 0x00a87f, 0x00a8c6, 0x00a8cd, 0x00a8da, 0x00a8df, 0x00a954, 0x00a95e, 0x00a97d, 0x00a97f, 0x00a9ce, 0x00a9ce, 0x00a9da, 0x00a9dd, 0x00a9ff, 0x00a9ff, 0x00aa37, 0x00aa3f, + 0x00aa4e, 0x00aa4f, 0x00aa5a, 0x00aa5b, 0x00aac3, 0x00aada, 0x00aaf7, 0x00ab00, 0x00ab07, 0x00ab08, 0x00ab0f, 0x00ab10, 0x00ab17, 0x00ab1f, 0x00ab27, 0x00ab27, 0x00ab2f, + 0x00ab2f, 0x00ab6c, 0x00ab6f, 0x00abee, 0x00abef, 0x00abfa, 0x00abff, 0x00d7a4, 0x00d7af, 0x00d7c7, 0x00d7ca, 0x00d7fc, 0x00f8ff, 0x00fa6e, 0x00fa6f, 0x00fada, 0x00faff, + 0x00fb07, 0x00fb12, 0x00fb18, 0x00fb1c, 0x00fb37, 0x00fb37, 0x00fb3d, 0x00fb3d, 0x00fb3f, 0x00fb3f, 0x00fb42, 0x00fb42, 0x00fb45, 0x00fb45, 0x00fbc3, 0x00fbd2, 0x00fd90, + 0x00fd91, 0x00fdc8, 0x00fdce, 0x00fdd0, 0x00fdef, 0x00fe1a, 0x00fe1f, 0x00fe53, 0x00fe53, 0x00fe67, 0x00fe67, 0x00fe6c, 0x00fe6f, 0x00fe75, 0x00fe75, 0x00fefd, 0x00ff00, + 0x00ffbf, 0x00ffc1, 0x00ffc8, 0x00ffc9, 0x00ffd0, 0x00ffd1, 0x00ffd8, 0x00ffd9, 0x00ffdd, 0x00ffdf, 0x00ffe7, 0x00ffe7, 0x00ffef, 0x00fffb, 0x00fffe, 0x00ffff, 0x01000c, + 0x01000c, 0x010027, 0x010027, 0x01003b, 0x01003b, 0x01003e, 0x01003e, 0x01004e, 0x01004f, 0x01005e, 0x01007f, 0x0100fb, 0x0100ff, 0x010103, 0x010106, 0x010134, 0x010136, + 0x01018f, 0x01018f, 0x01019d, 0x01019f, 0x0101a1, 0x0101cf, 0x0101fe, 0x01027f, 0x01029d, 0x01029f, 0x0102d1, 0x0102df, 0x0102fc, 0x0102ff, 0x010324, 0x01032c, 0x01034b, + 0x01034f, 0x01037b, 0x01037f, 0x01039e, 0x01039e, 0x0103c4, 0x0103c7, 0x0103d6, 0x0103ff, 0x01049e, 0x01049f, 0x0104aa, 0x0104af, 0x0104d4, 0x0104d7, 0x0104fc, 0x0104ff, + 0x010528, 0x01052f, 0x010564, 0x01056e, 0x01057b, 0x01057b, 0x01058b, 0x01058b, 0x010593, 0x010593, 0x010596, 0x010596, 0x0105a2, 0x0105a2, 0x0105b2, 0x0105b2, 0x0105ba, + 0x0105ba, 0x0105bd, 0x0105ff, 0x010737, 0x01073f, 0x010756, 0x01075f, 0x010768, 0x01077f, 0x010786, 0x010786, 0x0107b1, 0x0107b1, 0x0107bb, 0x0107ff, 0x010806, 0x010807, + 0x010809, 0x010809, 0x010836, 0x010836, 0x010839, 0x01083b, 0x01083d, 0x01083e, 0x010856, 0x010856, 0x01089f, 0x0108a6, 0x0108b0, 0x0108df, 0x0108f3, 0x0108f3, 0x0108f6, + 0x0108fa, 0x01091c, 0x01091e, 0x01093a, 0x01093e, 0x010940, 0x01097f, 0x0109b8, 0x0109bb, 0x0109d0, 0x0109d1, 0x010a04, 0x010a04, 0x010a07, 0x010a0b, 0x010a14, 0x010a14, + 0x010a18, 0x010a18, 0x010a36, 0x010a37, 0x010a3b, 0x010a3e, 0x010a49, 0x010a4f, 0x010a59, 0x010a5f, 0x010aa0, 0x010abf, 0x010ae7, 0x010aea, 0x010af7, 0x010aff, 0x010b36, + 0x010b38, 0x010b56, 0x010b57, 0x010b73, 0x010b77, 0x010b92, 0x010b98, 0x010b9d, 0x010ba8, 0x010bb0, 0x010bff, 0x010c49, 0x010c7f, 0x010cb3, 0x010cbf, 0x010cf3, 0x010cf9, + 0x010d28, 0x010d2f, 0x010d3a, 0x010e5f, 0x010e7f, 0x010e7f, 0x010eaa, 0x010eaa, 0x010eae, 0x010eaf, 0x010eb2, 0x010eff, 0x010f28, 0x010f2f, 0x010f5a, 0x010f6f, 0x010f8a, + 0x010faf, 0x010fcc, 0x010fdf, 0x010ff7, 0x010fff, 0x01104e, 0x011051, 0x011076, 0x01107e, 0x0110bd, 0x0110bd, 0x0110c3, 0x0110cf, 0x0110e9, 0x0110ef, 0x0110fa, 0x0110ff, + 0x011135, 0x011135, 0x011148, 0x01114f, 0x011177, 0x01117f, 0x0111e0, 0x0111e0, 0x0111f5, 0x0111ff, 0x011212, 0x011212, 0x01123f, 0x01127f, 0x011287, 0x011287, 0x011289, + 0x011289, 0x01128e, 0x01128e, 0x01129e, 0x01129e, 0x0112aa, 0x0112af, 0x0112eb, 0x0112ef, 0x0112fa, 0x0112ff, 0x011304, 0x011304, 0x01130d, 0x01130e, 0x011311, 0x011312, + 0x011329, 0x011329, 0x011331, 0x011331, 0x011334, 0x011334, 0x01133a, 0x01133a, 0x011345, 0x011346, 0x011349, 0x01134a, 0x01134e, 0x01134f, 0x011351, 0x011356, 0x011358, + 0x01135c, 0x011364, 0x011365, 0x01136d, 0x01136f, 0x011375, 0x0113ff, 0x01145c, 0x01145c, 0x011462, 0x01147f, 0x0114c8, 0x0114cf, 0x0114da, 0x01157f, 0x0115b6, 0x0115b7, + 0x0115de, 0x0115ff, 0x011645, 0x01164f, 0x01165a, 0x01165f, 0x01166d, 0x01167f, 0x0116ba, 0x0116bf, 0x0116ca, 0x0116ff, 0x01171b, 0x01171c, 0x01172c, 0x01172f, 0x011747, + 0x0117ff, 0x01183c, 0x01189f, 0x0118f3, 0x0118fe, 0x011907, 0x011908, 0x01190a, 0x01190b, 0x011914, 0x011914, 0x011917, 0x011917, 0x011936, 0x011936, 0x011939, 0x01193a, + 0x011947, 0x01194f, 0x01195a, 0x01199f, 0x0119a8, 0x0119a9, 0x0119d8, 0x0119d9, 0x0119e5, 0x0119ff, 0x011a48, 0x011a4f, 0x011aa3, 0x011aaf, 0x011af9, 0x011bff, 0x011c09, + 0x011c09, 0x011c37, 0x011c37, 0x011c46, 0x011c4f, 0x011c6d, 0x011c6f, 0x011c90, 0x011c91, 0x011ca8, 0x011ca8, 0x011cb7, 0x011cff, 0x011d07, 0x011d07, 0x011d0a, 0x011d0a, + 0x011d37, 0x011d39, 0x011d3b, 0x011d3b, 0x011d3e, 0x011d3e, 0x011d48, 0x011d4f, 0x011d5a, 0x011d5f, 0x011d66, 0x011d66, 0x011d69, 0x011d69, 0x011d8f, 0x011d8f, 0x011d92, + 0x011d92, 0x011d99, 0x011d9f, 0x011daa, 0x011edf, 0x011ef9, 0x011faf, 0x011fb1, 0x011fbf, 0x011ff2, 0x011ffe, 0x01239a, 0x0123ff, 0x01246f, 0x01246f, 0x012475, 0x01247f, + 0x012544, 0x012f8f, 0x012ff3, 0x012fff, 0x01342f, 0x0143ff, 0x014647, 0x0167ff, 0x016a39, 0x016a3f, 0x016a5f, 0x016a5f, 0x016a6a, 0x016a6d, 0x016abf, 0x016abf, 0x016aca, + 0x016acf, 0x016aee, 0x016aef, 0x016af6, 0x016aff, 0x016b46, 0x016b4f, 0x016b5a, 0x016b5a, 0x016b62, 0x016b62, 0x016b78, 0x016b7c, 0x016b90, 0x016e3f, 0x016e9b, 0x016eff, + 0x016f4b, 0x016f4e, 0x016f88, 0x016f8e, 0x016fa0, 0x016fdf, 0x016fe5, 0x016fef, 0x016ff2, 0x016fff, 0x0187f8, 0x0187ff, 0x018cd6, 0x018cff, 0x018d09, 0x01afef, 0x01aff4, + 0x01aff4, 0x01affc, 0x01affc, 0x01afff, 0x01afff, 0x01b123, 0x01b14f, 0x01b153, 0x01b163, 0x01b168, 0x01b16f, 0x01b2fc, 0x01bbff, 0x01bc6b, 0x01bc6f, 0x01bc7d, 0x01bc7f, + 0x01bc89, 0x01bc8f, 0x01bc9a, 0x01bc9b, 0x01bca0, 0x01ceff, 0x01cf2e, 0x01cf2f, 0x01cf47, 0x01cf4f, 0x01cfc4, 0x01cfff, 0x01d0f6, 0x01d0ff, 0x01d127, 0x01d128, 0x01d173, + 0x01d17a, 0x01d1eb, 0x01d1ff, 0x01d246, 0x01d2df, 0x01d2f4, 0x01d2ff, 0x01d357, 0x01d35f, 0x01d379, 0x01d3ff, 0x01d455, 0x01d455, 0x01d49d, 0x01d49d, 0x01d4a0, 0x01d4a1, + 0x01d4a3, 0x01d4a4, 0x01d4a7, 0x01d4a8, 0x01d4ad, 0x01d4ad, 0x01d4ba, 0x01d4ba, 0x01d4bc, 0x01d4bc, 0x01d4c4, 0x01d4c4, 0x01d506, 0x01d506, 0x01d50b, 0x01d50c, 0x01d515, + 0x01d515, 0x01d51d, 0x01d51d, 0x01d53a, 0x01d53a, 0x01d53f, 0x01d53f, 0x01d545, 0x01d545, 0x01d547, 0x01d549, 0x01d551, 0x01d551, 0x01d6a6, 0x01d6a7, 0x01d7cc, 0x01d7cd, + 0x01da8c, 0x01da9a, 0x01daa0, 0x01daa0, 0x01dab0, 0x01deff, 0x01df1f, 0x01dfff, 0x01e007, 0x01e007, 0x01e019, 0x01e01a, 0x01e022, 0x01e022, 0x01e025, 0x01e025, 0x01e02b, + 0x01e0ff, 0x01e12d, 0x01e12f, 0x01e13e, 0x01e13f, 0x01e14a, 0x01e14d, 0x01e150, 0x01e28f, 0x01e2af, 0x01e2bf, 0x01e2fa, 0x01e2fe, 0x01e300, 0x01e7df, 0x01e7e7, 0x01e7e7, + 0x01e7ec, 0x01e7ec, 0x01e7ef, 0x01e7ef, 0x01e7ff, 0x01e7ff, 0x01e8c5, 0x01e8c6, 0x01e8d7, 0x01e8ff, 0x01e94c, 0x01e94f, 0x01e95a, 0x01e95d, 0x01e960, 0x01ec70, 0x01ecb5, + 0x01ed00, 0x01ed3e, 0x01edff, 0x01ee04, 0x01ee04, 0x01ee20, 0x01ee20, 0x01ee23, 0x01ee23, 0x01ee25, 0x01ee26, 0x01ee28, 0x01ee28, 0x01ee33, 0x01ee33, 0x01ee38, 0x01ee38, + 0x01ee3a, 0x01ee3a, 0x01ee3c, 0x01ee41, 0x01ee43, 0x01ee46, 0x01ee48, 0x01ee48, 0x01ee4a, 0x01ee4a, 0x01ee4c, 0x01ee4c, 0x01ee50, 0x01ee50, 0x01ee53, 0x01ee53, 0x01ee55, + 0x01ee56, 0x01ee58, 0x01ee58, 0x01ee5a, 0x01ee5a, 0x01ee5c, 0x01ee5c, 0x01ee5e, 0x01ee5e, 0x01ee60, 0x01ee60, 0x01ee63, 0x01ee63, 0x01ee65, 0x01ee66, 0x01ee6b, 0x01ee6b, + 0x01ee73, 0x01ee73, 0x01ee78, 0x01ee78, 0x01ee7d, 0x01ee7d, 0x01ee7f, 0x01ee7f, 0x01ee8a, 0x01ee8a, 0x01ee9c, 0x01eea0, 0x01eea4, 0x01eea4, 0x01eeaa, 0x01eeaa, 0x01eebc, + 0x01eeef, 0x01eef2, 0x01efff, 0x01f02c, 0x01f02f, 0x01f094, 0x01f09f, 0x01f0af, 0x01f0b0, 0x01f0c0, 0x01f0c0, 0x01f0d0, 0x01f0d0, 0x01f0f6, 0x01f0ff, 0x01f1ae, 0x01f1e5, + 0x01f203, 0x01f20f, 0x01f23c, 0x01f23f, 0x01f249, 0x01f24f, 0x01f252, 0x01f25f, 0x01f266, 0x01f2ff, 0x01f6d8, 0x01f6dc, 0x01f6ed, 0x01f6ef, 0x01f6fd, 0x01f6ff, 0x01f774, + 0x01f77f, 0x01f7d9, 0x01f7df, 0x01f7ec, 0x01f7ef, 0x01f7f1, 0x01f7ff, 0x01f80c, 0x01f80f, 0x01f848, 0x01f84f, 0x01f85a, 0x01f85f, 0x01f888, 0x01f88f, 0x01f8ae, 0x01f8af, + 0x01f8b2, 0x01f8ff, 0x01fa54, 0x01fa5f, 0x01fa6e, 0x01fa6f, 0x01fa75, 0x01fa77, 0x01fa7d, 0x01fa7f, 0x01fa87, 0x01fa8f, 0x01faad, 0x01faaf, 0x01fabb, 0x01fabf, 0x01fac6, + 0x01facf, 0x01fada, 0x01fadf, 0x01fae8, 0x01faef, 0x01faf7, 0x01faff, 0x01fb93, 0x01fb93, 0x01fbcb, 0x01fbef, 0x01fbfa, 0x01ffff, 0x02a6e0, 0x02a6ff, 0x02b739, 0x02b73f, + 0x02b81e, 0x02b81f, 0x02cea2, 0x02ceaf, 0x02ebe1, 0x02f7ff, 0x02fa1e, 0x02ffff, 0x03134b, 0x0e00ff, 0x0e01f0, 0x10ffff)); } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodePropertyData.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodePropertyData.java index 79af63ece906..d86acfc89730 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodePropertyData.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodePropertyData.java @@ -47,18 +47,15 @@ import org.graalvm.collections.EconomicMap; -import com.oracle.truffle.api.CompilerDirectives; - class UnicodePropertyData { static final EconomicMap PROPERTY_ALIASES = EconomicMap.create(105); static final EconomicMap GENERAL_CATEGORY_ALIASES = EconomicMap.create(80); - static final EconomicMap SCRIPT_ALIASES = EconomicMap.create(312); - private static final EconomicMap SET_ENCODINGS = EconomicMap.create(397); + static final EconomicMap SCRIPT_ALIASES = EconomicMap.create(321); + private static final EconomicMap SET_ENCODINGS = EconomicMap.create(407); public static CodePointSet retrieveProperty(String propertySpec) { if (!SET_ENCODINGS.containsKey(propertySpec)) { - CompilerDirectives.transferToInterpreterAndInvalidate(); throw new IllegalArgumentException("Unsupported Unicode character property escape"); } return SET_ENCODINGS.get(propertySpec); @@ -301,9 +298,11 @@ public static CodePointSet retrieveProperty(String propertySpec) { SCRIPT_ALIASES.put("Common", "Zyyy"); SCRIPT_ALIASES.put("Copt", "Copt"); SCRIPT_ALIASES.put("Coptic", "Copt"); + SCRIPT_ALIASES.put("Cpmn", "Cpmn"); SCRIPT_ALIASES.put("Cprt", "Cprt"); SCRIPT_ALIASES.put("Cuneiform", "Xsux"); SCRIPT_ALIASES.put("Cypriot", "Cprt"); + SCRIPT_ALIASES.put("Cypro_Minoan", "Cpmn"); SCRIPT_ALIASES.put("Cyrillic", "Cyrl"); SCRIPT_ALIASES.put("Cyrl", "Cyrl"); SCRIPT_ALIASES.put("Deseret", "Dsrt"); @@ -459,6 +458,7 @@ public static CodePointSet retrieveProperty(String propertySpec) { SCRIPT_ALIASES.put("Old_Sogdian", "Sogo"); SCRIPT_ALIASES.put("Old_South_Arabian", "Sarb"); SCRIPT_ALIASES.put("Old_Turkic", "Orkh"); + SCRIPT_ALIASES.put("Old_Uyghur", "Ougr"); SCRIPT_ALIASES.put("Oriya", "Orya"); SCRIPT_ALIASES.put("Orkh", "Orkh"); SCRIPT_ALIASES.put("Orya", "Orya"); @@ -466,6 +466,7 @@ public static CodePointSet retrieveProperty(String propertySpec) { SCRIPT_ALIASES.put("Osge", "Osge"); SCRIPT_ALIASES.put("Osma", "Osma"); SCRIPT_ALIASES.put("Osmanya", "Osma"); + SCRIPT_ALIASES.put("Ougr", "Ougr"); SCRIPT_ALIASES.put("Pahawh_Hmong", "Hmng"); SCRIPT_ALIASES.put("Palm", "Palm"); SCRIPT_ALIASES.put("Palmyrene", "Palm"); @@ -530,6 +531,7 @@ public static CodePointSet retrieveProperty(String propertySpec) { SCRIPT_ALIASES.put("Tamil", "Taml"); SCRIPT_ALIASES.put("Taml", "Taml"); SCRIPT_ALIASES.put("Tang", "Tang"); + SCRIPT_ALIASES.put("Tangsa", "Tnsa"); SCRIPT_ALIASES.put("Tangut", "Tang"); SCRIPT_ALIASES.put("Tavt", "Tavt"); SCRIPT_ALIASES.put("Telu", "Telu"); @@ -544,11 +546,15 @@ public static CodePointSet retrieveProperty(String propertySpec) { SCRIPT_ALIASES.put("Tifinagh", "Tfng"); SCRIPT_ALIASES.put("Tirh", "Tirh"); SCRIPT_ALIASES.put("Tirhuta", "Tirh"); + SCRIPT_ALIASES.put("Tnsa", "Tnsa"); + SCRIPT_ALIASES.put("Toto", "Toto"); SCRIPT_ALIASES.put("Ugar", "Ugar"); SCRIPT_ALIASES.put("Ugaritic", "Ugar"); SCRIPT_ALIASES.put("Unknown", "Zzzz"); SCRIPT_ALIASES.put("Vai", "Vaii"); SCRIPT_ALIASES.put("Vaii", "Vaii"); + SCRIPT_ALIASES.put("Vith", "Vith"); + SCRIPT_ALIASES.put("Vithkuqi", "Vith"); SCRIPT_ALIASES.put("Wancho", "Wcho"); SCRIPT_ALIASES.put("Wara", "Wara"); SCRIPT_ALIASES.put("Warang_Citi", "Wara"); @@ -673,6 +679,7 @@ public static CodePointSet retrieveProperty(String propertySpec) { populateSC_CHER(); populateSC_CHRS(); populateSC_COPT(); + populateSC_CPMN(); populateSC_CPRT(); populateSC_CYRL(); populateSC_DEVA(); @@ -751,6 +758,7 @@ public static CodePointSet retrieveProperty(String propertySpec) { populateSC_ORYA(); populateSC_OSGE(); populateSC_OSMA(); + populateSC_OUGR(); populateSC_PALM(); populateSC_PAUC(); populateSC_PERM(); @@ -793,8 +801,11 @@ public static CodePointSet retrieveProperty(String propertySpec) { populateSC_THAI(); populateSC_TIBT(); populateSC_TIRH(); + populateSC_TNSA(); + populateSC_TOTO(); populateSC_UGAR(); populateSC_VAII(); + populateSC_VITH(); populateSC_WARA(); populateSC_WCHO(); populateSC_XPEO(); @@ -830,6 +841,7 @@ public static CodePointSet retrieveProperty(String propertySpec) { populateSCX_CHER(); populateSCX_CHRS(); populateSCX_COPT(); + populateSCX_CPMN(); populateSCX_CPRT(); populateSCX_CYRL(); populateSCX_DEVA(); @@ -908,6 +920,7 @@ public static CodePointSet retrieveProperty(String propertySpec) { populateSCX_ORYA(); populateSCX_OSGE(); populateSCX_OSMA(); + populateSCX_OUGR(); populateSCX_PALM(); populateSCX_PAUC(); populateSCX_PERM(); @@ -950,8 +963,11 @@ public static CodePointSet retrieveProperty(String propertySpec) { populateSCX_THAI(); populateSCX_TIBT(); populateSCX_TIRH(); + populateSCX_TNSA(); + populateSCX_TOTO(); populateSCX_UGAR(); populateSCX_VAII(); + populateSCX_VITH(); populateSCX_WARA(); populateSCX_WCHO(); populateSCX_XPEO(); @@ -979,82 +995,86 @@ private static void populateALPHA() { 0x00052f, 0x000531, 0x000556, 0x000559, 0x000559, 0x000560, 0x000588, 0x0005b0, 0x0005bd, 0x0005bf, 0x0005bf, 0x0005c1, 0x0005c2, 0x0005c4, 0x0005c5, 0x0005c7, 0x0005c7, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f2, 0x000610, 0x00061a, 0x000620, 0x000657, 0x000659, 0x00065f, 0x00066e, 0x0006d3, 0x0006d5, 0x0006dc, 0x0006e1, 0x0006e8, 0x0006ed, 0x0006ef, 0x0006fa, 0x0006fc, 0x0006ff, 0x0006ff, 0x000710, 0x00073f, 0x00074d, 0x0007b1, 0x0007ca, 0x0007ea, 0x0007f4, 0x0007f5, 0x0007fa, 0x0007fa, 0x000800, 0x000817, - 0x00081a, 0x00082c, 0x000840, 0x000858, 0x000860, 0x00086a, 0x0008a0, 0x0008b4, 0x0008b6, 0x0008c7, 0x0008d4, 0x0008df, 0x0008e3, 0x0008e9, 0x0008f0, 0x00093b, 0x00093d, - 0x00094c, 0x00094e, 0x000950, 0x000955, 0x000963, 0x000971, 0x000983, 0x000985, 0x00098c, 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, - 0x0009b6, 0x0009b9, 0x0009bd, 0x0009c4, 0x0009c7, 0x0009c8, 0x0009cb, 0x0009cc, 0x0009ce, 0x0009ce, 0x0009d7, 0x0009d7, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e3, 0x0009f0, - 0x0009f1, 0x0009fc, 0x0009fc, 0x000a01, 0x000a03, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, - 0x000a38, 0x000a39, 0x000a3e, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4c, 0x000a51, 0x000a51, 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a70, 0x000a75, 0x000a81, - 0x000a83, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, 0x000ab3, 0x000ab5, 0x000ab9, 0x000abd, 0x000ac5, 0x000ac7, 0x000ac9, - 0x000acb, 0x000acc, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae3, 0x000af9, 0x000afc, 0x000b01, 0x000b03, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, 0x000b2a, - 0x000b30, 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b44, 0x000b47, 0x000b48, 0x000b4b, 0x000b4c, 0x000b56, 0x000b57, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b63, - 0x000b71, 0x000b71, 0x000b82, 0x000b83, 0x000b85, 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, - 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bbe, 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcc, 0x000bd0, 0x000bd0, 0x000bd7, 0x000bd7, 0x000c00, 0x000c03, - 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4c, 0x000c55, 0x000c56, 0x000c58, - 0x000c5a, 0x000c60, 0x000c63, 0x000c80, 0x000c83, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cc4, - 0x000cc6, 0x000cc8, 0x000cca, 0x000ccc, 0x000cd5, 0x000cd6, 0x000cde, 0x000cde, 0x000ce0, 0x000ce3, 0x000cf1, 0x000cf2, 0x000d00, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, - 0x000d3a, 0x000d3d, 0x000d44, 0x000d46, 0x000d48, 0x000d4a, 0x000d4c, 0x000d4e, 0x000d4e, 0x000d54, 0x000d57, 0x000d5f, 0x000d63, 0x000d7a, 0x000d7f, 0x000d81, 0x000d83, - 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000dcf, 0x000dd4, 0x000dd6, 0x000dd6, 0x000dd8, 0x000ddf, 0x000df2, - 0x000df3, 0x000e01, 0x000e3a, 0x000e40, 0x000e46, 0x000e4d, 0x000e4d, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, - 0x000ea7, 0x000eb9, 0x000ebb, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000ecd, 0x000ecd, 0x000edc, 0x000edf, 0x000f00, 0x000f00, 0x000f40, 0x000f47, 0x000f49, - 0x000f6c, 0x000f71, 0x000f81, 0x000f88, 0x000f97, 0x000f99, 0x000fbc, 0x001000, 0x001036, 0x001038, 0x001038, 0x00103b, 0x00103f, 0x001050, 0x00108f, 0x00109a, 0x00109d, - 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, - 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, - 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, - 0x00169a, 0x0016a0, 0x0016ea, 0x0016ee, 0x0016f8, 0x001700, 0x00170c, 0x00170e, 0x001713, 0x001720, 0x001733, 0x001740, 0x001753, 0x001760, 0x00176c, 0x00176e, 0x001770, - 0x001772, 0x001773, 0x001780, 0x0017b3, 0x0017b6, 0x0017c8, 0x0017d7, 0x0017d7, 0x0017dc, 0x0017dc, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, - 0x00191e, 0x001920, 0x00192b, 0x001930, 0x001938, 0x001950, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x001a00, 0x001a1b, 0x001a20, 0x001a5e, - 0x001a61, 0x001a74, 0x001aa7, 0x001aa7, 0x001abf, 0x001ac0, 0x001b00, 0x001b33, 0x001b35, 0x001b43, 0x001b45, 0x001b4b, 0x001b80, 0x001ba9, 0x001bac, 0x001baf, 0x001bba, - 0x001be5, 0x001be7, 0x001bf1, 0x001c00, 0x001c36, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cbf, 0x001ce9, 0x001cec, - 0x001cee, 0x001cf3, 0x001cf5, 0x001cf6, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, 0x001de7, 0x001df4, 0x001e00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, - 0x001f4d, 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, - 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002071, 0x002071, 0x00207f, - 0x00207f, 0x002090, 0x00209c, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002119, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, - 0x002128, 0x002128, 0x00212a, 0x00212d, 0x00212f, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x0024b6, 0x0024e9, 0x002c00, - 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, + 0x00081a, 0x00082c, 0x000840, 0x000858, 0x000860, 0x00086a, 0x000870, 0x000887, 0x000889, 0x00088e, 0x0008a0, 0x0008c9, 0x0008d4, 0x0008df, 0x0008e3, 0x0008e9, 0x0008f0, + 0x00093b, 0x00093d, 0x00094c, 0x00094e, 0x000950, 0x000955, 0x000963, 0x000971, 0x000983, 0x000985, 0x00098c, 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, + 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009c4, 0x0009c7, 0x0009c8, 0x0009cb, 0x0009cc, 0x0009ce, 0x0009ce, 0x0009d7, 0x0009d7, 0x0009dc, 0x0009dd, 0x0009df, + 0x0009e3, 0x0009f0, 0x0009f1, 0x0009fc, 0x0009fc, 0x000a01, 0x000a03, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, + 0x000a35, 0x000a36, 0x000a38, 0x000a39, 0x000a3e, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4c, 0x000a51, 0x000a51, 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a70, + 0x000a75, 0x000a81, 0x000a83, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, 0x000ab3, 0x000ab5, 0x000ab9, 0x000abd, 0x000ac5, + 0x000ac7, 0x000ac9, 0x000acb, 0x000acc, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae3, 0x000af9, 0x000afc, 0x000b01, 0x000b03, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, + 0x000b28, 0x000b2a, 0x000b30, 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b44, 0x000b47, 0x000b48, 0x000b4b, 0x000b4c, 0x000b56, 0x000b57, 0x000b5c, 0x000b5d, + 0x000b5f, 0x000b63, 0x000b71, 0x000b71, 0x000b82, 0x000b83, 0x000b85, 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, + 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bbe, 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcc, 0x000bd0, 0x000bd0, 0x000bd7, 0x000bd7, + 0x000c00, 0x000c03, 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4c, 0x000c55, + 0x000c56, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, 0x000c60, 0x000c63, 0x000c80, 0x000c83, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, + 0x000cb5, 0x000cb9, 0x000cbd, 0x000cc4, 0x000cc6, 0x000cc8, 0x000cca, 0x000ccc, 0x000cd5, 0x000cd6, 0x000cdd, 0x000cde, 0x000ce0, 0x000ce3, 0x000cf1, 0x000cf2, 0x000d00, + 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d44, 0x000d46, 0x000d48, 0x000d4a, 0x000d4c, 0x000d4e, 0x000d4e, 0x000d54, 0x000d57, 0x000d5f, 0x000d63, + 0x000d7a, 0x000d7f, 0x000d81, 0x000d83, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000dcf, 0x000dd4, 0x000dd6, + 0x000dd6, 0x000dd8, 0x000ddf, 0x000df2, 0x000df3, 0x000e01, 0x000e3a, 0x000e40, 0x000e46, 0x000e4d, 0x000e4d, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, + 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb9, 0x000ebb, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000ecd, 0x000ecd, 0x000edc, 0x000edf, 0x000f00, + 0x000f00, 0x000f40, 0x000f47, 0x000f49, 0x000f6c, 0x000f71, 0x000f81, 0x000f88, 0x000f97, 0x000f99, 0x000fbc, 0x001000, 0x001036, 0x001038, 0x001038, 0x00103b, 0x00103f, + 0x001050, 0x00108f, 0x00109a, 0x00109d, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, + 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, + 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, + 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, 0x0016a0, 0x0016ea, 0x0016ee, 0x0016f8, 0x001700, 0x001713, 0x00171f, 0x001733, 0x001740, 0x001753, 0x001760, 0x00176c, + 0x00176e, 0x001770, 0x001772, 0x001773, 0x001780, 0x0017b3, 0x0017b6, 0x0017c8, 0x0017d7, 0x0017d7, 0x0017dc, 0x0017dc, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x0018b0, + 0x0018f5, 0x001900, 0x00191e, 0x001920, 0x00192b, 0x001930, 0x001938, 0x001950, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x001a00, 0x001a1b, + 0x001a20, 0x001a5e, 0x001a61, 0x001a74, 0x001aa7, 0x001aa7, 0x001abf, 0x001ac0, 0x001acc, 0x001ace, 0x001b00, 0x001b33, 0x001b35, 0x001b43, 0x001b45, 0x001b4c, 0x001b80, + 0x001ba9, 0x001bac, 0x001baf, 0x001bba, 0x001be5, 0x001be7, 0x001bf1, 0x001c00, 0x001c36, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, + 0x001cbd, 0x001cbf, 0x001ce9, 0x001cec, 0x001cee, 0x001cf3, 0x001cf5, 0x001cf6, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, 0x001de7, 0x001df4, 0x001e00, 0x001f15, 0x001f18, + 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, + 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, + 0x001ffc, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002119, 0x00211d, + 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x00212d, 0x00212f, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, + 0x002188, 0x0024b6, 0x0024e9, 0x002c00, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d6f, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x002de0, 0x002dff, 0x002e2f, 0x002e2f, 0x003005, 0x003007, 0x003021, 0x003029, 0x003031, 0x003035, 0x003038, 0x00303c, 0x003041, 0x003096, 0x00309d, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, - 0x009ffc, 0x00a000, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a61f, 0x00a62a, 0x00a62b, 0x00a640, 0x00a66e, 0x00a674, 0x00a67b, 0x00a67f, 0x00a6ef, - 0x00a717, 0x00a71f, 0x00a722, 0x00a788, 0x00a78b, 0x00a7bf, 0x00a7c2, 0x00a7ca, 0x00a7f5, 0x00a805, 0x00a807, 0x00a827, 0x00a840, 0x00a873, 0x00a880, 0x00a8c3, 0x00a8c5, - 0x00a8c5, 0x00a8f2, 0x00a8f7, 0x00a8fb, 0x00a8fb, 0x00a8fd, 0x00a8ff, 0x00a90a, 0x00a92a, 0x00a930, 0x00a952, 0x00a960, 0x00a97c, 0x00a980, 0x00a9b2, 0x00a9b4, 0x00a9bf, - 0x00a9cf, 0x00a9cf, 0x00a9e0, 0x00a9ef, 0x00a9fa, 0x00a9fe, 0x00aa00, 0x00aa36, 0x00aa40, 0x00aa4d, 0x00aa60, 0x00aa76, 0x00aa7a, 0x00aabe, 0x00aac0, 0x00aac0, 0x00aac2, - 0x00aac2, 0x00aadb, 0x00aadd, 0x00aae0, 0x00aaef, 0x00aaf2, 0x00aaf5, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, 0x00ab2e, - 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab69, 0x00ab70, 0x00abea, 0x00ac00, 0x00d7a3, 0x00d7b0, 0x00d7c6, 0x00d7cb, 0x00d7fb, 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x00fb00, - 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb28, 0x00fb2a, 0x00fb36, 0x00fb38, 0x00fb3c, 0x00fb3e, 0x00fb3e, 0x00fb40, 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbb1, - 0x00fbd3, 0x00fd3d, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdfb, 0x00fe70, 0x00fe74, 0x00fe76, 0x00fefc, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, 0x00ff66, - 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, 0x01003c, 0x01003d, - 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010140, 0x010174, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x010300, 0x01031f, 0x01032d, 0x01034a, 0x010350, - 0x01037a, 0x010380, 0x01039d, 0x0103a0, 0x0103c3, 0x0103c8, 0x0103cf, 0x0103d1, 0x0103d5, 0x010400, 0x01049d, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, - 0x010530, 0x010563, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, - 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, - 0x0109be, 0x0109bf, 0x010a00, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, - 0x010ac7, 0x010ac9, 0x010ae4, 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, - 0x010d00, 0x010d27, 0x010e80, 0x010ea9, 0x010eab, 0x010eac, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f45, 0x010fb0, 0x010fc4, 0x010fe0, - 0x010ff6, 0x011000, 0x011045, 0x011082, 0x0110b8, 0x0110d0, 0x0110e8, 0x011100, 0x011132, 0x011144, 0x011147, 0x011150, 0x011172, 0x011176, 0x011176, 0x011180, 0x0111bf, - 0x0111c1, 0x0111c4, 0x0111ce, 0x0111cf, 0x0111da, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x011234, 0x011237, 0x011237, 0x01123e, 0x01123e, 0x011280, - 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112e8, 0x011300, 0x011303, 0x011305, 0x01130c, 0x01130f, 0x011310, - 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133d, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134c, 0x011350, 0x011350, 0x011357, - 0x011357, 0x01135d, 0x011363, 0x011400, 0x011441, 0x011443, 0x011445, 0x011447, 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114c1, 0x0114c4, 0x0114c5, 0x0114c7, 0x0114c7, - 0x011580, 0x0115b5, 0x0115b8, 0x0115be, 0x0115d8, 0x0115dd, 0x011600, 0x01163e, 0x011640, 0x011640, 0x011644, 0x011644, 0x011680, 0x0116b5, 0x0116b8, 0x0116b8, 0x011700, - 0x01171a, 0x01171d, 0x01172a, 0x011800, 0x011838, 0x0118a0, 0x0118df, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x011935, - 0x011937, 0x011938, 0x01193b, 0x01193c, 0x01193f, 0x011942, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d7, 0x0119da, 0x0119df, 0x0119e1, 0x0119e1, 0x0119e3, 0x0119e4, 0x011a00, - 0x011a32, 0x011a35, 0x011a3e, 0x011a50, 0x011a97, 0x011a9d, 0x011a9d, 0x011ac0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c36, 0x011c38, 0x011c3e, 0x011c40, 0x011c40, - 0x011c72, 0x011c8f, 0x011c92, 0x011ca7, 0x011ca9, 0x011cb6, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, - 0x011d41, 0x011d43, 0x011d43, 0x011d46, 0x011d47, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d8e, 0x011d90, 0x011d91, 0x011d93, 0x011d96, 0x011d98, 0x011d98, - 0x011ee0, 0x011ef6, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012400, 0x01246e, 0x012480, 0x012543, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, - 0x016a5e, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, 0x016b40, 0x016b43, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e7f, 0x016f00, 0x016f4a, 0x016f4f, 0x016f87, - 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe3, 0x016ff0, 0x016ff1, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b11e, 0x01b150, - 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01bc9e, 0x01bc9e, 0x01d400, 0x01d454, - 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, - 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, - 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, - 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, - 0x01e100, 0x01e12c, 0x01e137, 0x01e13d, 0x01e14e, 0x01e14e, 0x01e2c0, 0x01e2eb, 0x01e800, 0x01e8c4, 0x01e900, 0x01e943, 0x01e947, 0x01e947, 0x01e94b, 0x01e94b, 0x01ee00, - 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, - 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, - 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, - 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x01f130, 0x01f149, 0x01f150, - 0x01f169, 0x01f170, 0x01f189, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); + 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a61f, 0x00a62a, 0x00a62b, 0x00a640, 0x00a66e, 0x00a674, 0x00a67b, 0x00a67f, 0x00a6ef, 0x00a717, 0x00a71f, + 0x00a722, 0x00a788, 0x00a78b, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, 0x00a7f2, 0x00a805, 0x00a807, 0x00a827, 0x00a840, 0x00a873, 0x00a880, + 0x00a8c3, 0x00a8c5, 0x00a8c5, 0x00a8f2, 0x00a8f7, 0x00a8fb, 0x00a8fb, 0x00a8fd, 0x00a8ff, 0x00a90a, 0x00a92a, 0x00a930, 0x00a952, 0x00a960, 0x00a97c, 0x00a980, 0x00a9b2, + 0x00a9b4, 0x00a9bf, 0x00a9cf, 0x00a9cf, 0x00a9e0, 0x00a9ef, 0x00a9fa, 0x00a9fe, 0x00aa00, 0x00aa36, 0x00aa40, 0x00aa4d, 0x00aa60, 0x00aa76, 0x00aa7a, 0x00aabe, 0x00aac0, + 0x00aac0, 0x00aac2, 0x00aac2, 0x00aadb, 0x00aadd, 0x00aae0, 0x00aaef, 0x00aaf2, 0x00aaf5, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, + 0x00ab28, 0x00ab2e, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab69, 0x00ab70, 0x00abea, 0x00ac00, 0x00d7a3, 0x00d7b0, 0x00d7c6, 0x00d7cb, 0x00d7fb, 0x00f900, 0x00fa6d, 0x00fa70, + 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb28, 0x00fb2a, 0x00fb36, 0x00fb38, 0x00fb3c, 0x00fb3e, 0x00fb3e, 0x00fb40, 0x00fb41, 0x00fb43, 0x00fb44, + 0x00fb46, 0x00fbb1, 0x00fbd3, 0x00fd3d, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdfb, 0x00fe70, 0x00fe74, 0x00fe76, 0x00fefc, 0x00ff21, 0x00ff3a, 0x00ff41, + 0x00ff5a, 0x00ff66, 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, + 0x01003c, 0x01003d, 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010140, 0x010174, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x010300, 0x01031f, 0x01032d, + 0x01034a, 0x010350, 0x01037a, 0x010380, 0x01039d, 0x0103a0, 0x0103c3, 0x0103c8, 0x0103cf, 0x0103d1, 0x0103d5, 0x010400, 0x01049d, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, + 0x010500, 0x010527, 0x010530, 0x010563, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, + 0x0105b9, 0x0105bb, 0x0105bc, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x010800, 0x010805, + 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, + 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a13, 0x010a15, 0x010a17, + 0x010a19, 0x010a35, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae4, 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, + 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010d00, 0x010d27, 0x010e80, 0x010ea9, 0x010eab, 0x010eac, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, + 0x010f27, 0x010f27, 0x010f30, 0x010f45, 0x010f70, 0x010f81, 0x010fb0, 0x010fc4, 0x010fe0, 0x010ff6, 0x011000, 0x011045, 0x011071, 0x011075, 0x011082, 0x0110b8, 0x0110c2, + 0x0110c2, 0x0110d0, 0x0110e8, 0x011100, 0x011132, 0x011144, 0x011147, 0x011150, 0x011172, 0x011176, 0x011176, 0x011180, 0x0111bf, 0x0111c1, 0x0111c4, 0x0111ce, 0x0111cf, + 0x0111da, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x011234, 0x011237, 0x011237, 0x01123e, 0x01123e, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, + 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112e8, 0x011300, 0x011303, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, + 0x011332, 0x011333, 0x011335, 0x011339, 0x01133d, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134c, 0x011350, 0x011350, 0x011357, 0x011357, 0x01135d, 0x011363, 0x011400, + 0x011441, 0x011443, 0x011445, 0x011447, 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114c1, 0x0114c4, 0x0114c5, 0x0114c7, 0x0114c7, 0x011580, 0x0115b5, 0x0115b8, 0x0115be, + 0x0115d8, 0x0115dd, 0x011600, 0x01163e, 0x011640, 0x011640, 0x011644, 0x011644, 0x011680, 0x0116b5, 0x0116b8, 0x0116b8, 0x011700, 0x01171a, 0x01171d, 0x01172a, 0x011740, + 0x011746, 0x011800, 0x011838, 0x0118a0, 0x0118df, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x011935, 0x011937, 0x011938, + 0x01193b, 0x01193c, 0x01193f, 0x011942, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d7, 0x0119da, 0x0119df, 0x0119e1, 0x0119e1, 0x0119e3, 0x0119e4, 0x011a00, 0x011a32, 0x011a35, + 0x011a3e, 0x011a50, 0x011a97, 0x011a9d, 0x011a9d, 0x011ab0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c36, 0x011c38, 0x011c3e, 0x011c40, 0x011c40, 0x011c72, 0x011c8f, + 0x011c92, 0x011ca7, 0x011ca9, 0x011cb6, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d41, 0x011d43, + 0x011d43, 0x011d46, 0x011d47, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d8e, 0x011d90, 0x011d91, 0x011d93, 0x011d96, 0x011d98, 0x011d98, 0x011ee0, 0x011ef6, + 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012400, 0x01246e, 0x012480, 0x012543, 0x012f90, 0x012ff0, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, + 0x016a5e, 0x016a70, 0x016abe, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, 0x016b40, 0x016b43, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e7f, 0x016f00, 0x016f4a, + 0x016f4f, 0x016f87, 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe3, 0x016ff0, 0x016ff1, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01aff0, + 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01b000, 0x01b122, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, + 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01bc9e, 0x01bc9e, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, + 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, + 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, + 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01df00, 0x01df1e, + 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e100, 0x01e12c, 0x01e137, 0x01e13d, 0x01e14e, 0x01e14e, 0x01e290, + 0x01e2ad, 0x01e2c0, 0x01e2eb, 0x01e7e0, 0x01e7e6, 0x01e7e8, 0x01e7eb, 0x01e7ed, 0x01e7ee, 0x01e7f0, 0x01e7fe, 0x01e800, 0x01e8c4, 0x01e900, 0x01e943, 0x01e947, 0x01e947, + 0x01e94b, 0x01e94b, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, + 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, + 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, + 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, + 0x01f130, 0x01f149, 0x01f150, 0x01f169, 0x01f170, 0x01f189, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, + 0x02fa1d, 0x030000, 0x03134a)); } private static void populateANY() { @@ -1063,20 +1083,20 @@ private static void populateANY() { private static void populateASSIGNED() { SET_ENCODINGS.put("Assigned", CodePointSet.createNoDedup(0x000000, 0x000377, 0x00037a, 0x00037f, 0x000384, 0x00038a, 0x00038c, 0x00038c, 0x00038e, 0x0003a1, 0x0003a3, 0x00052f, 0x000531, - 0x000556, 0x000559, 0x00058a, 0x00058d, 0x00058f, 0x000591, 0x0005c7, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f4, 0x000600, 0x00061c, 0x00061e, 0x00070d, 0x00070f, 0x00074a, - 0x00074d, 0x0007b1, 0x0007c0, 0x0007fa, 0x0007fd, 0x00082d, 0x000830, 0x00083e, 0x000840, 0x00085b, 0x00085e, 0x00085e, 0x000860, 0x00086a, 0x0008a0, 0x0008b4, 0x0008b6, - 0x0008c7, 0x0008d3, 0x000983, 0x000985, 0x00098c, 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bc, 0x0009c4, - 0x0009c7, 0x0009c8, 0x0009cb, 0x0009ce, 0x0009d7, 0x0009d7, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e3, 0x0009e6, 0x0009fe, 0x000a01, 0x000a03, 0x000a05, 0x000a0a, 0x000a0f, - 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, 0x000a38, 0x000a39, 0x000a3c, 0x000a3c, 0x000a3e, 0x000a42, 0x000a47, 0x000a48, - 0x000a4b, 0x000a4d, 0x000a51, 0x000a51, 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a66, 0x000a76, 0x000a81, 0x000a83, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, - 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, 0x000ab3, 0x000ab5, 0x000ab9, 0x000abc, 0x000ac5, 0x000ac7, 0x000ac9, 0x000acb, 0x000acd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae3, - 0x000ae6, 0x000af1, 0x000af9, 0x000aff, 0x000b01, 0x000b03, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, 0x000b2a, 0x000b30, 0x000b32, 0x000b33, 0x000b35, - 0x000b39, 0x000b3c, 0x000b44, 0x000b47, 0x000b48, 0x000b4b, 0x000b4d, 0x000b55, 0x000b57, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b63, 0x000b66, 0x000b77, 0x000b82, 0x000b83, - 0x000b85, 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, - 0x000bb9, 0x000bbe, 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcd, 0x000bd0, 0x000bd0, 0x000bd7, 0x000bd7, 0x000be6, 0x000bfa, 0x000c00, 0x000c0c, 0x000c0e, 0x000c10, - 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c60, 0x000c63, 0x000c66, + 0x000556, 0x000559, 0x00058a, 0x00058d, 0x00058f, 0x000591, 0x0005c7, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f4, 0x000600, 0x00070d, 0x00070f, 0x00074a, 0x00074d, 0x0007b1, + 0x0007c0, 0x0007fa, 0x0007fd, 0x00082d, 0x000830, 0x00083e, 0x000840, 0x00085b, 0x00085e, 0x00085e, 0x000860, 0x00086a, 0x000870, 0x00088e, 0x000890, 0x000891, 0x000898, + 0x000983, 0x000985, 0x00098c, 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bc, 0x0009c4, 0x0009c7, 0x0009c8, + 0x0009cb, 0x0009ce, 0x0009d7, 0x0009d7, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e3, 0x0009e6, 0x0009fe, 0x000a01, 0x000a03, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, + 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, 0x000a38, 0x000a39, 0x000a3c, 0x000a3c, 0x000a3e, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4d, + 0x000a51, 0x000a51, 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a66, 0x000a76, 0x000a81, 0x000a83, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, + 0x000ab0, 0x000ab2, 0x000ab3, 0x000ab5, 0x000ab9, 0x000abc, 0x000ac5, 0x000ac7, 0x000ac9, 0x000acb, 0x000acd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae3, 0x000ae6, 0x000af1, + 0x000af9, 0x000aff, 0x000b01, 0x000b03, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, 0x000b2a, 0x000b30, 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3c, + 0x000b44, 0x000b47, 0x000b48, 0x000b4b, 0x000b4d, 0x000b55, 0x000b57, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b63, 0x000b66, 0x000b77, 0x000b82, 0x000b83, 0x000b85, 0x000b8a, + 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bbe, + 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcd, 0x000bd0, 0x000bd0, 0x000bd7, 0x000bd7, 0x000be6, 0x000bfa, 0x000c00, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, + 0x000c2a, 0x000c39, 0x000c3c, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, 0x000c60, 0x000c63, 0x000c66, 0x000c6f, 0x000c77, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbc, 0x000cc4, 0x000cc6, 0x000cc8, 0x000cca, 0x000ccd, - 0x000cd5, 0x000cd6, 0x000cde, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x000d00, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d44, 0x000d46, + 0x000cd5, 0x000cd6, 0x000cdd, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x000d00, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d44, 0x000d46, 0x000d48, 0x000d4a, 0x000d4f, 0x000d54, 0x000d63, 0x000d66, 0x000d7f, 0x000d81, 0x000d83, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000dca, 0x000dca, 0x000dcf, 0x000dd4, 0x000dd6, 0x000dd6, 0x000dd8, 0x000ddf, 0x000de6, 0x000def, 0x000df2, 0x000df4, 0x000e01, 0x000e3a, 0x000e3f, 0x000e5b, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, @@ -1084,64 +1104,67 @@ private static void populateASSIGNED() { 0x000fda, 0x001000, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x00135d, 0x00137c, 0x001380, 0x001399, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001400, 0x00169c, 0x0016a0, 0x0016f8, - 0x001700, 0x00170c, 0x00170e, 0x001714, 0x001720, 0x001736, 0x001740, 0x001753, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001772, 0x001773, 0x001780, 0x0017dd, 0x0017e0, - 0x0017e9, 0x0017f0, 0x0017f9, 0x001800, 0x00180e, 0x001810, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001920, 0x00192b, - 0x001930, 0x00193b, 0x001940, 0x001940, 0x001944, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x0019d0, 0x0019da, 0x0019de, 0x001a1b, 0x001a1e, - 0x001a5e, 0x001a60, 0x001a7c, 0x001a7f, 0x001a89, 0x001a90, 0x001a99, 0x001aa0, 0x001aad, 0x001ab0, 0x001ac0, 0x001b00, 0x001b4b, 0x001b50, 0x001b7c, 0x001b80, 0x001bf3, - 0x001bfc, 0x001c37, 0x001c3b, 0x001c49, 0x001c4d, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cc7, 0x001cd0, 0x001cfa, 0x001d00, 0x001df9, 0x001dfb, 0x001f15, 0x001f18, - 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, - 0x001fb6, 0x001fc4, 0x001fc6, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fdd, 0x001fef, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffe, 0x002000, 0x002064, 0x002066, 0x002071, 0x002074, - 0x00208e, 0x002090, 0x00209c, 0x0020a0, 0x0020bf, 0x0020d0, 0x0020f0, 0x002100, 0x00218b, 0x002190, 0x002426, 0x002440, 0x00244a, 0x002460, 0x002b73, 0x002b76, 0x002b95, - 0x002b97, 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002cf3, 0x002cf9, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d70, 0x002d7f, - 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, - 0x002de0, 0x002e52, 0x002e80, 0x002e99, 0x002e9b, 0x002ef3, 0x002f00, 0x002fd5, 0x002ff0, 0x002ffb, 0x003000, 0x00303f, 0x003041, 0x003096, 0x003099, 0x0030ff, 0x003105, - 0x00312f, 0x003131, 0x00318e, 0x003190, 0x0031e3, 0x0031f0, 0x00321e, 0x003220, 0x009ffc, 0x00a000, 0x00a48c, 0x00a490, 0x00a4c6, 0x00a4d0, 0x00a62b, 0x00a640, 0x00a6f7, - 0x00a700, 0x00a7bf, 0x00a7c2, 0x00a7ca, 0x00a7f5, 0x00a82c, 0x00a830, 0x00a839, 0x00a840, 0x00a877, 0x00a880, 0x00a8c5, 0x00a8ce, 0x00a8d9, 0x00a8e0, 0x00a953, 0x00a95f, - 0x00a97c, 0x00a980, 0x00a9cd, 0x00a9cf, 0x00a9d9, 0x00a9de, 0x00a9fe, 0x00aa00, 0x00aa36, 0x00aa40, 0x00aa4d, 0x00aa50, 0x00aa59, 0x00aa5c, 0x00aac2, 0x00aadb, 0x00aaf6, - 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, 0x00ab2e, 0x00ab30, 0x00ab6b, 0x00ab70, 0x00abed, 0x00abf0, 0x00abf9, 0x00ac00, - 0x00d7a3, 0x00d7b0, 0x00d7c6, 0x00d7cb, 0x00d7fb, 0x00d800, 0x00fa6d, 0x00fa70, 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb36, 0x00fb38, 0x00fb3c, - 0x00fb3e, 0x00fb3e, 0x00fb40, 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbc1, 0x00fbd3, 0x00fd3f, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdfd, 0x00fe00, - 0x00fe19, 0x00fe20, 0x00fe52, 0x00fe54, 0x00fe66, 0x00fe68, 0x00fe6b, 0x00fe70, 0x00fe74, 0x00fe76, 0x00fefc, 0x00feff, 0x00feff, 0x00ff01, 0x00ffbe, 0x00ffc2, 0x00ffc7, - 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, 0x00fff9, 0x00fffd, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, - 0x01003a, 0x01003c, 0x01003d, 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010100, 0x010102, 0x010107, 0x010133, 0x010137, 0x01018e, 0x010190, 0x01019c, - 0x0101a0, 0x0101a0, 0x0101d0, 0x0101fd, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x0102e0, 0x0102fb, 0x010300, 0x010323, 0x01032d, 0x01034a, 0x010350, 0x01037a, 0x010380, - 0x01039d, 0x01039f, 0x0103c3, 0x0103c8, 0x0103d5, 0x010400, 0x01049d, 0x0104a0, 0x0104a9, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, - 0x01056f, 0x01056f, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, - 0x01083c, 0x01083f, 0x010855, 0x010857, 0x01089e, 0x0108a7, 0x0108af, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x0108fb, 0x01091b, 0x01091f, 0x010939, 0x01093f, 0x01093f, - 0x010980, 0x0109b7, 0x0109bc, 0x0109cf, 0x0109d2, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a38, 0x010a3a, 0x010a3f, - 0x010a48, 0x010a50, 0x010a58, 0x010a60, 0x010a9f, 0x010ac0, 0x010ae6, 0x010aeb, 0x010af6, 0x010b00, 0x010b35, 0x010b39, 0x010b55, 0x010b58, 0x010b72, 0x010b78, 0x010b91, - 0x010b99, 0x010b9c, 0x010ba9, 0x010baf, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010cfa, 0x010d27, 0x010d30, 0x010d39, 0x010e60, 0x010e7e, 0x010e80, - 0x010ea9, 0x010eab, 0x010ead, 0x010eb0, 0x010eb1, 0x010f00, 0x010f27, 0x010f30, 0x010f59, 0x010fb0, 0x010fcb, 0x010fe0, 0x010ff6, 0x011000, 0x01104d, 0x011052, 0x01106f, - 0x01107f, 0x0110c1, 0x0110cd, 0x0110cd, 0x0110d0, 0x0110e8, 0x0110f0, 0x0110f9, 0x011100, 0x011134, 0x011136, 0x011147, 0x011150, 0x011176, 0x011180, 0x0111df, 0x0111e1, - 0x0111f4, 0x011200, 0x011211, 0x011213, 0x01123e, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a9, 0x0112b0, 0x0112ea, - 0x0112f0, 0x0112f9, 0x011300, 0x011303, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133b, - 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, 0x011350, 0x011350, 0x011357, 0x011357, 0x01135d, 0x011363, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011400, 0x01145b, - 0x01145d, 0x011461, 0x011480, 0x0114c7, 0x0114d0, 0x0114d9, 0x011580, 0x0115b5, 0x0115b8, 0x0115dd, 0x011600, 0x011644, 0x011650, 0x011659, 0x011660, 0x01166c, 0x011680, - 0x0116b8, 0x0116c0, 0x0116c9, 0x011700, 0x01171a, 0x01171d, 0x01172b, 0x011730, 0x01173f, 0x011800, 0x01183b, 0x0118a0, 0x0118f2, 0x0118ff, 0x011906, 0x011909, 0x011909, - 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x011935, 0x011937, 0x011938, 0x01193b, 0x011946, 0x011950, 0x011959, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d7, 0x0119da, - 0x0119e4, 0x011a00, 0x011a47, 0x011a50, 0x011aa2, 0x011ac0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c36, 0x011c38, 0x011c45, 0x011c50, 0x011c6c, 0x011c70, 0x011c8f, - 0x011c92, 0x011ca7, 0x011ca9, 0x011cb6, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d47, 0x011d50, - 0x011d59, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d8e, 0x011d90, 0x011d91, 0x011d93, 0x011d98, 0x011da0, 0x011da9, 0x011ee0, 0x011ef8, 0x011fb0, 0x011fb0, - 0x011fc0, 0x011ff1, 0x011fff, 0x012399, 0x012400, 0x01246e, 0x012470, 0x012474, 0x012480, 0x012543, 0x013000, 0x01342e, 0x013430, 0x013438, 0x014400, 0x014646, 0x016800, - 0x016a38, 0x016a40, 0x016a5e, 0x016a60, 0x016a69, 0x016a6e, 0x016a6f, 0x016ad0, 0x016aed, 0x016af0, 0x016af5, 0x016b00, 0x016b45, 0x016b50, 0x016b59, 0x016b5b, 0x016b61, - 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e9a, 0x016f00, 0x016f4a, 0x016f4f, 0x016f87, 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe4, 0x016ff0, 0x016ff1, 0x017000, - 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b11e, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, - 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01bc9c, 0x01bca3, 0x01d000, 0x01d0f5, 0x01d100, 0x01d126, 0x01d129, 0x01d1e8, 0x01d200, 0x01d245, 0x01d2e0, 0x01d2f3, 0x01d300, - 0x01d356, 0x01d360, 0x01d378, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, - 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, - 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d7cb, 0x01d7ce, 0x01da8b, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, - 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e100, 0x01e12c, 0x01e130, 0x01e13d, 0x01e140, 0x01e149, 0x01e14e, 0x01e14f, 0x01e2c0, - 0x01e2f9, 0x01e2ff, 0x01e2ff, 0x01e800, 0x01e8c4, 0x01e8c7, 0x01e8d6, 0x01e900, 0x01e94b, 0x01e950, 0x01e959, 0x01e95e, 0x01e95f, 0x01ec71, 0x01ecb4, 0x01ed01, 0x01ed3d, - 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, - 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, - 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, - 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x01eef0, 0x01eef1, - 0x01f000, 0x01f02b, 0x01f030, 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, 0x01f100, 0x01f1ad, 0x01f1e6, 0x01f202, 0x01f210, - 0x01f23b, 0x01f240, 0x01f248, 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6e0, 0x01f6ec, 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, - 0x01f7e0, 0x01f7eb, 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01f978, 0x01f97a, - 0x01f9cb, 0x01f9cd, 0x01fa53, 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7a, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faa8, 0x01fab0, 0x01fab6, 0x01fac0, 0x01fac2, - 0x01fad0, 0x01fad6, 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca, 0x01fbf0, 0x01fbf9, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, - 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a, 0x0e0001, 0x0e0001, 0x0e0020, 0x0e007f, 0x0e0100, 0x0e01ef, 0x0f0000, 0x0ffffd, 0x100000, 0x10fffd)); + 0x001700, 0x001715, 0x00171f, 0x001736, 0x001740, 0x001753, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001772, 0x001773, 0x001780, 0x0017dd, 0x0017e0, 0x0017e9, 0x0017f0, + 0x0017f9, 0x001800, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001920, 0x00192b, 0x001930, 0x00193b, 0x001940, 0x001940, + 0x001944, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x0019d0, 0x0019da, 0x0019de, 0x001a1b, 0x001a1e, 0x001a5e, 0x001a60, 0x001a7c, 0x001a7f, + 0x001a89, 0x001a90, 0x001a99, 0x001aa0, 0x001aad, 0x001ab0, 0x001ace, 0x001b00, 0x001b4c, 0x001b50, 0x001b7e, 0x001b80, 0x001bf3, 0x001bfc, 0x001c37, 0x001c3b, 0x001c49, + 0x001c4d, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cc7, 0x001cd0, 0x001cfa, 0x001d00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, + 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fc4, 0x001fc6, 0x001fd3, 0x001fd6, 0x001fdb, + 0x001fdd, 0x001fef, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffe, 0x002000, 0x002064, 0x002066, 0x002071, 0x002074, 0x00208e, 0x002090, 0x00209c, 0x0020a0, 0x0020c0, 0x0020d0, + 0x0020f0, 0x002100, 0x00218b, 0x002190, 0x002426, 0x002440, 0x00244a, 0x002460, 0x002b73, 0x002b76, 0x002b95, 0x002b97, 0x002cf3, 0x002cf9, 0x002d25, 0x002d27, 0x002d27, + 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d70, 0x002d7f, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, + 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x002de0, 0x002e5d, 0x002e80, 0x002e99, 0x002e9b, 0x002ef3, 0x002f00, 0x002fd5, 0x002ff0, 0x002ffb, + 0x003000, 0x00303f, 0x003041, 0x003096, 0x003099, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x003190, 0x0031e3, 0x0031f0, 0x00321e, 0x003220, 0x00a48c, 0x00a490, + 0x00a4c6, 0x00a4d0, 0x00a62b, 0x00a640, 0x00a6f7, 0x00a700, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, 0x00a7f2, 0x00a82c, 0x00a830, 0x00a839, + 0x00a840, 0x00a877, 0x00a880, 0x00a8c5, 0x00a8ce, 0x00a8d9, 0x00a8e0, 0x00a953, 0x00a95f, 0x00a97c, 0x00a980, 0x00a9cd, 0x00a9cf, 0x00a9d9, 0x00a9de, 0x00a9fe, 0x00aa00, + 0x00aa36, 0x00aa40, 0x00aa4d, 0x00aa50, 0x00aa59, 0x00aa5c, 0x00aac2, 0x00aadb, 0x00aaf6, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, + 0x00ab28, 0x00ab2e, 0x00ab30, 0x00ab6b, 0x00ab70, 0x00abed, 0x00abf0, 0x00abf9, 0x00ac00, 0x00d7a3, 0x00d7b0, 0x00d7c6, 0x00d7cb, 0x00d7fb, 0x00d800, 0x00fa6d, 0x00fa70, + 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb36, 0x00fb38, 0x00fb3c, 0x00fb3e, 0x00fb3e, 0x00fb40, 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbc2, + 0x00fbd3, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdcf, 0x00fdcf, 0x00fdf0, 0x00fe19, 0x00fe20, 0x00fe52, 0x00fe54, 0x00fe66, 0x00fe68, 0x00fe6b, 0x00fe70, 0x00fe74, 0x00fe76, + 0x00fefc, 0x00feff, 0x00feff, 0x00ff01, 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, + 0x00fff9, 0x00fffd, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, 0x01003c, 0x01003d, 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010100, + 0x010102, 0x010107, 0x010133, 0x010137, 0x01018e, 0x010190, 0x01019c, 0x0101a0, 0x0101a0, 0x0101d0, 0x0101fd, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x0102e0, 0x0102fb, + 0x010300, 0x010323, 0x01032d, 0x01034a, 0x010350, 0x01037a, 0x010380, 0x01039d, 0x01039f, 0x0103c3, 0x0103c8, 0x0103d5, 0x010400, 0x01049d, 0x0104a0, 0x0104a9, 0x0104b0, + 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x01056f, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, + 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, + 0x0107ba, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010857, 0x01089e, 0x0108a7, 0x0108af, + 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x0108fb, 0x01091b, 0x01091f, 0x010939, 0x01093f, 0x01093f, 0x010980, 0x0109b7, 0x0109bc, 0x0109cf, 0x0109d2, 0x010a03, 0x010a05, + 0x010a06, 0x010a0c, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a38, 0x010a3a, 0x010a3f, 0x010a48, 0x010a50, 0x010a58, 0x010a60, 0x010a9f, 0x010ac0, 0x010ae6, + 0x010aeb, 0x010af6, 0x010b00, 0x010b35, 0x010b39, 0x010b55, 0x010b58, 0x010b72, 0x010b78, 0x010b91, 0x010b99, 0x010b9c, 0x010ba9, 0x010baf, 0x010c00, 0x010c48, 0x010c80, + 0x010cb2, 0x010cc0, 0x010cf2, 0x010cfa, 0x010d27, 0x010d30, 0x010d39, 0x010e60, 0x010e7e, 0x010e80, 0x010ea9, 0x010eab, 0x010ead, 0x010eb0, 0x010eb1, 0x010f00, 0x010f27, + 0x010f30, 0x010f59, 0x010f70, 0x010f89, 0x010fb0, 0x010fcb, 0x010fe0, 0x010ff6, 0x011000, 0x01104d, 0x011052, 0x011075, 0x01107f, 0x0110c2, 0x0110cd, 0x0110cd, 0x0110d0, + 0x0110e8, 0x0110f0, 0x0110f9, 0x011100, 0x011134, 0x011136, 0x011147, 0x011150, 0x011176, 0x011180, 0x0111df, 0x0111e1, 0x0111f4, 0x011200, 0x011211, 0x011213, 0x01123e, + 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a9, 0x0112b0, 0x0112ea, 0x0112f0, 0x0112f9, 0x011300, 0x011303, 0x011305, + 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133b, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, + 0x011350, 0x011350, 0x011357, 0x011357, 0x01135d, 0x011363, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011400, 0x01145b, 0x01145d, 0x011461, 0x011480, 0x0114c7, 0x0114d0, + 0x0114d9, 0x011580, 0x0115b5, 0x0115b8, 0x0115dd, 0x011600, 0x011644, 0x011650, 0x011659, 0x011660, 0x01166c, 0x011680, 0x0116b9, 0x0116c0, 0x0116c9, 0x011700, 0x01171a, + 0x01171d, 0x01172b, 0x011730, 0x011746, 0x011800, 0x01183b, 0x0118a0, 0x0118f2, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, + 0x011935, 0x011937, 0x011938, 0x01193b, 0x011946, 0x011950, 0x011959, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d7, 0x0119da, 0x0119e4, 0x011a00, 0x011a47, 0x011a50, 0x011aa2, + 0x011ab0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c36, 0x011c38, 0x011c45, 0x011c50, 0x011c6c, 0x011c70, 0x011c8f, 0x011c92, 0x011ca7, 0x011ca9, 0x011cb6, 0x011d00, + 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d47, 0x011d50, 0x011d59, 0x011d60, 0x011d65, 0x011d67, 0x011d68, + 0x011d6a, 0x011d8e, 0x011d90, 0x011d91, 0x011d93, 0x011d98, 0x011da0, 0x011da9, 0x011ee0, 0x011ef8, 0x011fb0, 0x011fb0, 0x011fc0, 0x011ff1, 0x011fff, 0x012399, 0x012400, + 0x01246e, 0x012470, 0x012474, 0x012480, 0x012543, 0x012f90, 0x012ff2, 0x013000, 0x01342e, 0x013430, 0x013438, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, + 0x016a60, 0x016a69, 0x016a6e, 0x016abe, 0x016ac0, 0x016ac9, 0x016ad0, 0x016aed, 0x016af0, 0x016af5, 0x016b00, 0x016b45, 0x016b50, 0x016b59, 0x016b5b, 0x016b61, 0x016b63, + 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e9a, 0x016f00, 0x016f4a, 0x016f4f, 0x016f87, 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe4, 0x016ff0, 0x016ff1, 0x017000, 0x0187f7, + 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01b000, 0x01b122, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, + 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01bc9c, 0x01bca3, 0x01cf00, 0x01cf2d, 0x01cf30, 0x01cf46, 0x01cf50, 0x01cfc3, + 0x01d000, 0x01d0f5, 0x01d100, 0x01d126, 0x01d129, 0x01d1ea, 0x01d200, 0x01d245, 0x01d2e0, 0x01d2f3, 0x01d300, 0x01d356, 0x01d360, 0x01d378, 0x01d400, 0x01d454, 0x01d456, + 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, + 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, + 0x01d6a5, 0x01d6a8, 0x01d7cb, 0x01d7ce, 0x01da8b, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01df00, 0x01df1e, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, + 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e100, 0x01e12c, 0x01e130, 0x01e13d, 0x01e140, 0x01e149, 0x01e14e, 0x01e14f, 0x01e290, 0x01e2ae, 0x01e2c0, 0x01e2f9, 0x01e2ff, + 0x01e2ff, 0x01e7e0, 0x01e7e6, 0x01e7e8, 0x01e7eb, 0x01e7ed, 0x01e7ee, 0x01e7f0, 0x01e7fe, 0x01e800, 0x01e8c4, 0x01e8c7, 0x01e8d6, 0x01e900, 0x01e94b, 0x01e950, 0x01e959, + 0x01e95e, 0x01e95f, 0x01ec71, 0x01ecb4, 0x01ed01, 0x01ed3d, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, + 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, + 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, + 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, + 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x01eef0, 0x01eef1, 0x01f000, 0x01f02b, 0x01f030, 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, + 0x01f0f5, 0x01f100, 0x01f1ad, 0x01f1e6, 0x01f202, 0x01f210, 0x01f23b, 0x01f240, 0x01f248, 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6dd, 0x01f6ec, + 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, 0x01f7e0, 0x01f7eb, 0x01f7f0, 0x01f7f0, 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, + 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01fa53, 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7c, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faac, + 0x01fab0, 0x01faba, 0x01fac0, 0x01fac5, 0x01fad0, 0x01fad9, 0x01fae0, 0x01fae7, 0x01faf0, 0x01faf6, 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca, 0x01fbf0, 0x01fbf9, 0x020000, + 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a, 0x0e0001, 0x0e0001, 0x0e0020, 0x0e007f, + 0x0e0100, 0x0e01ef, 0x0f0000, 0x0ffffd, 0x100000, 0x10fffd)); } private static void populateBIDI_C() { @@ -1160,9 +1183,9 @@ private static void populateBIDI_M() { 0x002a0a, 0x002a1c, 0x002a1e, 0x002a21, 0x002a24, 0x002a24, 0x002a26, 0x002a26, 0x002a29, 0x002a29, 0x002a2b, 0x002a2e, 0x002a34, 0x002a35, 0x002a3c, 0x002a3e, 0x002a57, 0x002a58, 0x002a64, 0x002a65, 0x002a6a, 0x002a6d, 0x002a6f, 0x002a70, 0x002a73, 0x002a74, 0x002a79, 0x002aa3, 0x002aa6, 0x002aad, 0x002aaf, 0x002ad6, 0x002adc, 0x002adc, 0x002ade, 0x002ade, 0x002ae2, 0x002ae6, 0x002aec, 0x002aee, 0x002af3, 0x002af3, 0x002af7, 0x002afb, 0x002afd, 0x002afd, 0x002bfe, 0x002bfe, 0x002e02, 0x002e05, 0x002e09, - 0x002e0a, 0x002e0c, 0x002e0d, 0x002e1c, 0x002e1d, 0x002e20, 0x002e29, 0x003008, 0x003011, 0x003014, 0x00301b, 0x00fe59, 0x00fe5e, 0x00fe64, 0x00fe65, 0x00ff08, 0x00ff09, - 0x00ff1c, 0x00ff1c, 0x00ff1e, 0x00ff1e, 0x00ff3b, 0x00ff3b, 0x00ff3d, 0x00ff3d, 0x00ff5b, 0x00ff5b, 0x00ff5d, 0x00ff5d, 0x00ff5f, 0x00ff60, 0x00ff62, 0x00ff63, 0x01d6db, - 0x01d6db, 0x01d715, 0x01d715, 0x01d74f, 0x01d74f, 0x01d789, 0x01d789, 0x01d7c3, 0x01d7c3)); + 0x002e0a, 0x002e0c, 0x002e0d, 0x002e1c, 0x002e1d, 0x002e20, 0x002e29, 0x002e55, 0x002e5c, 0x003008, 0x003011, 0x003014, 0x00301b, 0x00fe59, 0x00fe5e, 0x00fe64, 0x00fe65, + 0x00ff08, 0x00ff09, 0x00ff1c, 0x00ff1c, 0x00ff1e, 0x00ff1e, 0x00ff3b, 0x00ff3b, 0x00ff3d, 0x00ff3d, 0x00ff5b, 0x00ff5b, 0x00ff5d, 0x00ff5d, 0x00ff5f, 0x00ff60, 0x00ff62, + 0x00ff63, 0x01d6db, 0x01d6db, 0x01d715, 0x01d715, 0x01d74f, 0x01d74f, 0x01d789, 0x01d789, 0x01d7c3, 0x01d7c3)); } private static void populateCI() { @@ -1171,49 +1194,51 @@ private static void populateCI() { 0x000489, 0x000559, 0x000559, 0x00055f, 0x00055f, 0x000591, 0x0005bd, 0x0005bf, 0x0005bf, 0x0005c1, 0x0005c2, 0x0005c4, 0x0005c5, 0x0005c7, 0x0005c7, 0x0005f4, 0x0005f4, 0x000600, 0x000605, 0x000610, 0x00061a, 0x00061c, 0x00061c, 0x000640, 0x000640, 0x00064b, 0x00065f, 0x000670, 0x000670, 0x0006d6, 0x0006dd, 0x0006df, 0x0006e8, 0x0006ea, 0x0006ed, 0x00070f, 0x00070f, 0x000711, 0x000711, 0x000730, 0x00074a, 0x0007a6, 0x0007b0, 0x0007eb, 0x0007f5, 0x0007fa, 0x0007fa, 0x0007fd, 0x0007fd, 0x000816, 0x00082d, - 0x000859, 0x00085b, 0x0008d3, 0x000902, 0x00093a, 0x00093a, 0x00093c, 0x00093c, 0x000941, 0x000948, 0x00094d, 0x00094d, 0x000951, 0x000957, 0x000962, 0x000963, 0x000971, - 0x000971, 0x000981, 0x000981, 0x0009bc, 0x0009bc, 0x0009c1, 0x0009c4, 0x0009cd, 0x0009cd, 0x0009e2, 0x0009e3, 0x0009fe, 0x0009fe, 0x000a01, 0x000a02, 0x000a3c, 0x000a3c, - 0x000a41, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4d, 0x000a51, 0x000a51, 0x000a70, 0x000a71, 0x000a75, 0x000a75, 0x000a81, 0x000a82, 0x000abc, 0x000abc, 0x000ac1, - 0x000ac5, 0x000ac7, 0x000ac8, 0x000acd, 0x000acd, 0x000ae2, 0x000ae3, 0x000afa, 0x000aff, 0x000b01, 0x000b01, 0x000b3c, 0x000b3c, 0x000b3f, 0x000b3f, 0x000b41, 0x000b44, - 0x000b4d, 0x000b4d, 0x000b55, 0x000b56, 0x000b62, 0x000b63, 0x000b82, 0x000b82, 0x000bc0, 0x000bc0, 0x000bcd, 0x000bcd, 0x000c00, 0x000c00, 0x000c04, 0x000c04, 0x000c3e, - 0x000c40, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c62, 0x000c63, 0x000c81, 0x000c81, 0x000cbc, 0x000cbc, 0x000cbf, 0x000cbf, 0x000cc6, 0x000cc6, - 0x000ccc, 0x000ccd, 0x000ce2, 0x000ce3, 0x000d00, 0x000d01, 0x000d3b, 0x000d3c, 0x000d41, 0x000d44, 0x000d4d, 0x000d4d, 0x000d62, 0x000d63, 0x000d81, 0x000d81, 0x000dca, - 0x000dca, 0x000dd2, 0x000dd4, 0x000dd6, 0x000dd6, 0x000e31, 0x000e31, 0x000e34, 0x000e3a, 0x000e46, 0x000e4e, 0x000eb1, 0x000eb1, 0x000eb4, 0x000ebc, 0x000ec6, 0x000ec6, - 0x000ec8, 0x000ecd, 0x000f18, 0x000f19, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f71, 0x000f7e, 0x000f80, 0x000f84, 0x000f86, 0x000f87, 0x000f8d, - 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x00102d, 0x001030, 0x001032, 0x001037, 0x001039, 0x00103a, 0x00103d, 0x00103e, 0x001058, 0x001059, 0x00105e, 0x001060, - 0x001071, 0x001074, 0x001082, 0x001082, 0x001085, 0x001086, 0x00108d, 0x00108d, 0x00109d, 0x00109d, 0x0010fc, 0x0010fc, 0x00135d, 0x00135f, 0x001712, 0x001714, 0x001732, - 0x001734, 0x001752, 0x001753, 0x001772, 0x001773, 0x0017b4, 0x0017b5, 0x0017b7, 0x0017bd, 0x0017c6, 0x0017c6, 0x0017c9, 0x0017d3, 0x0017d7, 0x0017d7, 0x0017dd, 0x0017dd, - 0x00180b, 0x00180e, 0x001843, 0x001843, 0x001885, 0x001886, 0x0018a9, 0x0018a9, 0x001920, 0x001922, 0x001927, 0x001928, 0x001932, 0x001932, 0x001939, 0x00193b, 0x001a17, - 0x001a18, 0x001a1b, 0x001a1b, 0x001a56, 0x001a56, 0x001a58, 0x001a5e, 0x001a60, 0x001a60, 0x001a62, 0x001a62, 0x001a65, 0x001a6c, 0x001a73, 0x001a7c, 0x001a7f, 0x001a7f, - 0x001aa7, 0x001aa7, 0x001ab0, 0x001ac0, 0x001b00, 0x001b03, 0x001b34, 0x001b34, 0x001b36, 0x001b3a, 0x001b3c, 0x001b3c, 0x001b42, 0x001b42, 0x001b6b, 0x001b73, 0x001b80, - 0x001b81, 0x001ba2, 0x001ba5, 0x001ba8, 0x001ba9, 0x001bab, 0x001bad, 0x001be6, 0x001be6, 0x001be8, 0x001be9, 0x001bed, 0x001bed, 0x001bef, 0x001bf1, 0x001c2c, 0x001c33, - 0x001c36, 0x001c37, 0x001c78, 0x001c7d, 0x001cd0, 0x001cd2, 0x001cd4, 0x001ce0, 0x001ce2, 0x001ce8, 0x001ced, 0x001ced, 0x001cf4, 0x001cf4, 0x001cf8, 0x001cf9, 0x001d2c, - 0x001d6a, 0x001d78, 0x001d78, 0x001d9b, 0x001df9, 0x001dfb, 0x001dff, 0x001fbd, 0x001fbd, 0x001fbf, 0x001fc1, 0x001fcd, 0x001fcf, 0x001fdd, 0x001fdf, 0x001fed, 0x001fef, - 0x001ffd, 0x001ffe, 0x00200b, 0x00200f, 0x002018, 0x002019, 0x002024, 0x002024, 0x002027, 0x002027, 0x00202a, 0x00202e, 0x002060, 0x002064, 0x002066, 0x00206f, 0x002071, - 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x0020d0, 0x0020f0, 0x002c7c, 0x002c7d, 0x002cef, 0x002cf1, 0x002d6f, 0x002d6f, 0x002d7f, 0x002d7f, 0x002de0, 0x002dff, - 0x002e2f, 0x002e2f, 0x003005, 0x003005, 0x00302a, 0x00302d, 0x003031, 0x003035, 0x00303b, 0x00303b, 0x003099, 0x00309e, 0x0030fc, 0x0030fe, 0x00a015, 0x00a015, 0x00a4f8, - 0x00a4fd, 0x00a60c, 0x00a60c, 0x00a66f, 0x00a672, 0x00a674, 0x00a67d, 0x00a67f, 0x00a67f, 0x00a69c, 0x00a69f, 0x00a6f0, 0x00a6f1, 0x00a700, 0x00a721, 0x00a770, 0x00a770, - 0x00a788, 0x00a78a, 0x00a7f8, 0x00a7f9, 0x00a802, 0x00a802, 0x00a806, 0x00a806, 0x00a80b, 0x00a80b, 0x00a825, 0x00a826, 0x00a82c, 0x00a82c, 0x00a8c4, 0x00a8c5, 0x00a8e0, - 0x00a8f1, 0x00a8ff, 0x00a8ff, 0x00a926, 0x00a92d, 0x00a947, 0x00a951, 0x00a980, 0x00a982, 0x00a9b3, 0x00a9b3, 0x00a9b6, 0x00a9b9, 0x00a9bc, 0x00a9bd, 0x00a9cf, 0x00a9cf, - 0x00a9e5, 0x00a9e6, 0x00aa29, 0x00aa2e, 0x00aa31, 0x00aa32, 0x00aa35, 0x00aa36, 0x00aa43, 0x00aa43, 0x00aa4c, 0x00aa4c, 0x00aa70, 0x00aa70, 0x00aa7c, 0x00aa7c, 0x00aab0, - 0x00aab0, 0x00aab2, 0x00aab4, 0x00aab7, 0x00aab8, 0x00aabe, 0x00aabf, 0x00aac1, 0x00aac1, 0x00aadd, 0x00aadd, 0x00aaec, 0x00aaed, 0x00aaf3, 0x00aaf4, 0x00aaf6, 0x00aaf6, - 0x00ab5b, 0x00ab5f, 0x00ab69, 0x00ab6b, 0x00abe5, 0x00abe5, 0x00abe8, 0x00abe8, 0x00abed, 0x00abed, 0x00fb1e, 0x00fb1e, 0x00fbb2, 0x00fbc1, 0x00fe00, 0x00fe0f, 0x00fe13, - 0x00fe13, 0x00fe20, 0x00fe2f, 0x00fe52, 0x00fe52, 0x00fe55, 0x00fe55, 0x00feff, 0x00feff, 0x00ff07, 0x00ff07, 0x00ff0e, 0x00ff0e, 0x00ff1a, 0x00ff1a, 0x00ff3e, 0x00ff3e, - 0x00ff40, 0x00ff40, 0x00ff70, 0x00ff70, 0x00ff9e, 0x00ff9f, 0x00ffe3, 0x00ffe3, 0x00fff9, 0x00fffb, 0x0101fd, 0x0101fd, 0x0102e0, 0x0102e0, 0x010376, 0x01037a, 0x010a01, - 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a0f, 0x010a38, 0x010a3a, 0x010a3f, 0x010a3f, 0x010ae5, 0x010ae6, 0x010d24, 0x010d27, 0x010eab, 0x010eac, 0x010f46, 0x010f50, - 0x011001, 0x011001, 0x011038, 0x011046, 0x01107f, 0x011081, 0x0110b3, 0x0110b6, 0x0110b9, 0x0110ba, 0x0110bd, 0x0110bd, 0x0110cd, 0x0110cd, 0x011100, 0x011102, 0x011127, - 0x01112b, 0x01112d, 0x011134, 0x011173, 0x011173, 0x011180, 0x011181, 0x0111b6, 0x0111be, 0x0111c9, 0x0111cc, 0x0111cf, 0x0111cf, 0x01122f, 0x011231, 0x011234, 0x011234, - 0x011236, 0x011237, 0x01123e, 0x01123e, 0x0112df, 0x0112df, 0x0112e3, 0x0112ea, 0x011300, 0x011301, 0x01133b, 0x01133c, 0x011340, 0x011340, 0x011366, 0x01136c, 0x011370, - 0x011374, 0x011438, 0x01143f, 0x011442, 0x011444, 0x011446, 0x011446, 0x01145e, 0x01145e, 0x0114b3, 0x0114b8, 0x0114ba, 0x0114ba, 0x0114bf, 0x0114c0, 0x0114c2, 0x0114c3, - 0x0115b2, 0x0115b5, 0x0115bc, 0x0115bd, 0x0115bf, 0x0115c0, 0x0115dc, 0x0115dd, 0x011633, 0x01163a, 0x01163d, 0x01163d, 0x01163f, 0x011640, 0x0116ab, 0x0116ab, 0x0116ad, - 0x0116ad, 0x0116b0, 0x0116b5, 0x0116b7, 0x0116b7, 0x01171d, 0x01171f, 0x011722, 0x011725, 0x011727, 0x01172b, 0x01182f, 0x011837, 0x011839, 0x01183a, 0x01193b, 0x01193c, - 0x01193e, 0x01193e, 0x011943, 0x011943, 0x0119d4, 0x0119d7, 0x0119da, 0x0119db, 0x0119e0, 0x0119e0, 0x011a01, 0x011a0a, 0x011a33, 0x011a38, 0x011a3b, 0x011a3e, 0x011a47, - 0x011a47, 0x011a51, 0x011a56, 0x011a59, 0x011a5b, 0x011a8a, 0x011a96, 0x011a98, 0x011a99, 0x011c30, 0x011c36, 0x011c38, 0x011c3d, 0x011c3f, 0x011c3f, 0x011c92, 0x011ca7, - 0x011caa, 0x011cb0, 0x011cb2, 0x011cb3, 0x011cb5, 0x011cb6, 0x011d31, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d45, 0x011d47, 0x011d47, 0x011d90, - 0x011d91, 0x011d95, 0x011d95, 0x011d97, 0x011d97, 0x011ef3, 0x011ef4, 0x013430, 0x013438, 0x016af0, 0x016af4, 0x016b30, 0x016b36, 0x016b40, 0x016b43, 0x016f4f, 0x016f4f, - 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe4, 0x01bc9d, 0x01bc9e, 0x01bca0, 0x01bca3, 0x01d167, 0x01d169, 0x01d173, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, - 0x01d1ad, 0x01d242, 0x01d244, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, 0x01da75, 0x01da75, 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, - 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e130, 0x01e13d, 0x01e2ec, 0x01e2ef, 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e94b, 0x01f3fb, + 0x000859, 0x00085b, 0x000888, 0x000888, 0x000890, 0x000891, 0x000898, 0x00089f, 0x0008c9, 0x000902, 0x00093a, 0x00093a, 0x00093c, 0x00093c, 0x000941, 0x000948, 0x00094d, + 0x00094d, 0x000951, 0x000957, 0x000962, 0x000963, 0x000971, 0x000971, 0x000981, 0x000981, 0x0009bc, 0x0009bc, 0x0009c1, 0x0009c4, 0x0009cd, 0x0009cd, 0x0009e2, 0x0009e3, + 0x0009fe, 0x0009fe, 0x000a01, 0x000a02, 0x000a3c, 0x000a3c, 0x000a41, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4d, 0x000a51, 0x000a51, 0x000a70, 0x000a71, 0x000a75, + 0x000a75, 0x000a81, 0x000a82, 0x000abc, 0x000abc, 0x000ac1, 0x000ac5, 0x000ac7, 0x000ac8, 0x000acd, 0x000acd, 0x000ae2, 0x000ae3, 0x000afa, 0x000aff, 0x000b01, 0x000b01, + 0x000b3c, 0x000b3c, 0x000b3f, 0x000b3f, 0x000b41, 0x000b44, 0x000b4d, 0x000b4d, 0x000b55, 0x000b56, 0x000b62, 0x000b63, 0x000b82, 0x000b82, 0x000bc0, 0x000bc0, 0x000bcd, + 0x000bcd, 0x000c00, 0x000c00, 0x000c04, 0x000c04, 0x000c3c, 0x000c3c, 0x000c3e, 0x000c40, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c62, 0x000c63, + 0x000c81, 0x000c81, 0x000cbc, 0x000cbc, 0x000cbf, 0x000cbf, 0x000cc6, 0x000cc6, 0x000ccc, 0x000ccd, 0x000ce2, 0x000ce3, 0x000d00, 0x000d01, 0x000d3b, 0x000d3c, 0x000d41, + 0x000d44, 0x000d4d, 0x000d4d, 0x000d62, 0x000d63, 0x000d81, 0x000d81, 0x000dca, 0x000dca, 0x000dd2, 0x000dd4, 0x000dd6, 0x000dd6, 0x000e31, 0x000e31, 0x000e34, 0x000e3a, + 0x000e46, 0x000e4e, 0x000eb1, 0x000eb1, 0x000eb4, 0x000ebc, 0x000ec6, 0x000ec6, 0x000ec8, 0x000ecd, 0x000f18, 0x000f19, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, + 0x000f39, 0x000f71, 0x000f7e, 0x000f80, 0x000f84, 0x000f86, 0x000f87, 0x000f8d, 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x00102d, 0x001030, 0x001032, 0x001037, + 0x001039, 0x00103a, 0x00103d, 0x00103e, 0x001058, 0x001059, 0x00105e, 0x001060, 0x001071, 0x001074, 0x001082, 0x001082, 0x001085, 0x001086, 0x00108d, 0x00108d, 0x00109d, + 0x00109d, 0x0010fc, 0x0010fc, 0x00135d, 0x00135f, 0x001712, 0x001714, 0x001732, 0x001733, 0x001752, 0x001753, 0x001772, 0x001773, 0x0017b4, 0x0017b5, 0x0017b7, 0x0017bd, + 0x0017c6, 0x0017c6, 0x0017c9, 0x0017d3, 0x0017d7, 0x0017d7, 0x0017dd, 0x0017dd, 0x00180b, 0x00180f, 0x001843, 0x001843, 0x001885, 0x001886, 0x0018a9, 0x0018a9, 0x001920, + 0x001922, 0x001927, 0x001928, 0x001932, 0x001932, 0x001939, 0x00193b, 0x001a17, 0x001a18, 0x001a1b, 0x001a1b, 0x001a56, 0x001a56, 0x001a58, 0x001a5e, 0x001a60, 0x001a60, + 0x001a62, 0x001a62, 0x001a65, 0x001a6c, 0x001a73, 0x001a7c, 0x001a7f, 0x001a7f, 0x001aa7, 0x001aa7, 0x001ab0, 0x001ace, 0x001b00, 0x001b03, 0x001b34, 0x001b34, 0x001b36, + 0x001b3a, 0x001b3c, 0x001b3c, 0x001b42, 0x001b42, 0x001b6b, 0x001b73, 0x001b80, 0x001b81, 0x001ba2, 0x001ba5, 0x001ba8, 0x001ba9, 0x001bab, 0x001bad, 0x001be6, 0x001be6, + 0x001be8, 0x001be9, 0x001bed, 0x001bed, 0x001bef, 0x001bf1, 0x001c2c, 0x001c33, 0x001c36, 0x001c37, 0x001c78, 0x001c7d, 0x001cd0, 0x001cd2, 0x001cd4, 0x001ce0, 0x001ce2, + 0x001ce8, 0x001ced, 0x001ced, 0x001cf4, 0x001cf4, 0x001cf8, 0x001cf9, 0x001d2c, 0x001d6a, 0x001d78, 0x001d78, 0x001d9b, 0x001dff, 0x001fbd, 0x001fbd, 0x001fbf, 0x001fc1, + 0x001fcd, 0x001fcf, 0x001fdd, 0x001fdf, 0x001fed, 0x001fef, 0x001ffd, 0x001ffe, 0x00200b, 0x00200f, 0x002018, 0x002019, 0x002024, 0x002024, 0x002027, 0x002027, 0x00202a, + 0x00202e, 0x002060, 0x002064, 0x002066, 0x00206f, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x0020d0, 0x0020f0, 0x002c7c, 0x002c7d, 0x002cef, 0x002cf1, + 0x002d6f, 0x002d6f, 0x002d7f, 0x002d7f, 0x002de0, 0x002dff, 0x002e2f, 0x002e2f, 0x003005, 0x003005, 0x00302a, 0x00302d, 0x003031, 0x003035, 0x00303b, 0x00303b, 0x003099, + 0x00309e, 0x0030fc, 0x0030fe, 0x00a015, 0x00a015, 0x00a4f8, 0x00a4fd, 0x00a60c, 0x00a60c, 0x00a66f, 0x00a672, 0x00a674, 0x00a67d, 0x00a67f, 0x00a67f, 0x00a69c, 0x00a69f, + 0x00a6f0, 0x00a6f1, 0x00a700, 0x00a721, 0x00a770, 0x00a770, 0x00a788, 0x00a78a, 0x00a7f2, 0x00a7f4, 0x00a7f8, 0x00a7f9, 0x00a802, 0x00a802, 0x00a806, 0x00a806, 0x00a80b, + 0x00a80b, 0x00a825, 0x00a826, 0x00a82c, 0x00a82c, 0x00a8c4, 0x00a8c5, 0x00a8e0, 0x00a8f1, 0x00a8ff, 0x00a8ff, 0x00a926, 0x00a92d, 0x00a947, 0x00a951, 0x00a980, 0x00a982, + 0x00a9b3, 0x00a9b3, 0x00a9b6, 0x00a9b9, 0x00a9bc, 0x00a9bd, 0x00a9cf, 0x00a9cf, 0x00a9e5, 0x00a9e6, 0x00aa29, 0x00aa2e, 0x00aa31, 0x00aa32, 0x00aa35, 0x00aa36, 0x00aa43, + 0x00aa43, 0x00aa4c, 0x00aa4c, 0x00aa70, 0x00aa70, 0x00aa7c, 0x00aa7c, 0x00aab0, 0x00aab0, 0x00aab2, 0x00aab4, 0x00aab7, 0x00aab8, 0x00aabe, 0x00aabf, 0x00aac1, 0x00aac1, + 0x00aadd, 0x00aadd, 0x00aaec, 0x00aaed, 0x00aaf3, 0x00aaf4, 0x00aaf6, 0x00aaf6, 0x00ab5b, 0x00ab5f, 0x00ab69, 0x00ab6b, 0x00abe5, 0x00abe5, 0x00abe8, 0x00abe8, 0x00abed, + 0x00abed, 0x00fb1e, 0x00fb1e, 0x00fbb2, 0x00fbc2, 0x00fe00, 0x00fe0f, 0x00fe13, 0x00fe13, 0x00fe20, 0x00fe2f, 0x00fe52, 0x00fe52, 0x00fe55, 0x00fe55, 0x00feff, 0x00feff, + 0x00ff07, 0x00ff07, 0x00ff0e, 0x00ff0e, 0x00ff1a, 0x00ff1a, 0x00ff3e, 0x00ff3e, 0x00ff40, 0x00ff40, 0x00ff70, 0x00ff70, 0x00ff9e, 0x00ff9f, 0x00ffe3, 0x00ffe3, 0x00fff9, + 0x00fffb, 0x0101fd, 0x0101fd, 0x0102e0, 0x0102e0, 0x010376, 0x01037a, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x010a01, 0x010a03, 0x010a05, 0x010a06, + 0x010a0c, 0x010a0f, 0x010a38, 0x010a3a, 0x010a3f, 0x010a3f, 0x010ae5, 0x010ae6, 0x010d24, 0x010d27, 0x010eab, 0x010eac, 0x010f46, 0x010f50, 0x010f82, 0x010f85, 0x011001, + 0x011001, 0x011038, 0x011046, 0x011070, 0x011070, 0x011073, 0x011074, 0x01107f, 0x011081, 0x0110b3, 0x0110b6, 0x0110b9, 0x0110ba, 0x0110bd, 0x0110bd, 0x0110c2, 0x0110c2, + 0x0110cd, 0x0110cd, 0x011100, 0x011102, 0x011127, 0x01112b, 0x01112d, 0x011134, 0x011173, 0x011173, 0x011180, 0x011181, 0x0111b6, 0x0111be, 0x0111c9, 0x0111cc, 0x0111cf, + 0x0111cf, 0x01122f, 0x011231, 0x011234, 0x011234, 0x011236, 0x011237, 0x01123e, 0x01123e, 0x0112df, 0x0112df, 0x0112e3, 0x0112ea, 0x011300, 0x011301, 0x01133b, 0x01133c, + 0x011340, 0x011340, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011438, 0x01143f, 0x011442, 0x011444, 0x011446, 0x011446, 0x01145e, 0x01145e, 0x0114b3, 0x0114b8, 0x0114ba, + 0x0114ba, 0x0114bf, 0x0114c0, 0x0114c2, 0x0114c3, 0x0115b2, 0x0115b5, 0x0115bc, 0x0115bd, 0x0115bf, 0x0115c0, 0x0115dc, 0x0115dd, 0x011633, 0x01163a, 0x01163d, 0x01163d, + 0x01163f, 0x011640, 0x0116ab, 0x0116ab, 0x0116ad, 0x0116ad, 0x0116b0, 0x0116b5, 0x0116b7, 0x0116b7, 0x01171d, 0x01171f, 0x011722, 0x011725, 0x011727, 0x01172b, 0x01182f, + 0x011837, 0x011839, 0x01183a, 0x01193b, 0x01193c, 0x01193e, 0x01193e, 0x011943, 0x011943, 0x0119d4, 0x0119d7, 0x0119da, 0x0119db, 0x0119e0, 0x0119e0, 0x011a01, 0x011a0a, + 0x011a33, 0x011a38, 0x011a3b, 0x011a3e, 0x011a47, 0x011a47, 0x011a51, 0x011a56, 0x011a59, 0x011a5b, 0x011a8a, 0x011a96, 0x011a98, 0x011a99, 0x011c30, 0x011c36, 0x011c38, + 0x011c3d, 0x011c3f, 0x011c3f, 0x011c92, 0x011ca7, 0x011caa, 0x011cb0, 0x011cb2, 0x011cb3, 0x011cb5, 0x011cb6, 0x011d31, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, + 0x011d3f, 0x011d45, 0x011d47, 0x011d47, 0x011d90, 0x011d91, 0x011d95, 0x011d95, 0x011d97, 0x011d97, 0x011ef3, 0x011ef4, 0x013430, 0x013438, 0x016af0, 0x016af4, 0x016b30, + 0x016b36, 0x016b40, 0x016b43, 0x016f4f, 0x016f4f, 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe4, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, + 0x01bc9d, 0x01bc9e, 0x01bca0, 0x01bca3, 0x01cf00, 0x01cf2d, 0x01cf30, 0x01cf46, 0x01d167, 0x01d169, 0x01d173, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, + 0x01d244, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, 0x01da75, 0x01da75, 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, 0x01e008, 0x01e018, + 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e130, 0x01e13d, 0x01e2ae, 0x01e2ae, 0x01e2ec, 0x01e2ef, 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e94b, 0x01f3fb, 0x01f3ff, 0x0e0001, 0x0e0001, 0x0e0020, 0x0e007f, 0x0e0100, 0x0e01ef)); } @@ -1269,7 +1294,7 @@ private static void populateCWCF() { 0x001ef8, 0x001efa, 0x001efa, 0x001efc, 0x001efc, 0x001efe, 0x001efe, 0x001f08, 0x001f0f, 0x001f18, 0x001f1d, 0x001f28, 0x001f2f, 0x001f38, 0x001f3f, 0x001f48, 0x001f4d, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f5f, 0x001f68, 0x001f6f, 0x001f80, 0x001faf, 0x001fb2, 0x001fb4, 0x001fb7, 0x001fbc, 0x001fc2, 0x001fc4, 0x001fc7, 0x001fcc, 0x001fd8, 0x001fdb, 0x001fe8, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff7, 0x001ffc, 0x002126, 0x002126, 0x00212a, 0x00212b, 0x002132, 0x002132, - 0x002160, 0x00216f, 0x002183, 0x002183, 0x0024b6, 0x0024cf, 0x002c00, 0x002c2e, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, 0x002c69, 0x002c69, 0x002c6b, + 0x002160, 0x00216f, 0x002183, 0x002183, 0x0024b6, 0x0024cf, 0x002c00, 0x002c2f, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, 0x002c69, 0x002c69, 0x002c6b, 0x002c6b, 0x002c6d, 0x002c70, 0x002c72, 0x002c72, 0x002c75, 0x002c75, 0x002c7e, 0x002c80, 0x002c82, 0x002c82, 0x002c84, 0x002c84, 0x002c86, 0x002c86, 0x002c88, 0x002c88, 0x002c8a, 0x002c8a, 0x002c8c, 0x002c8c, 0x002c8e, 0x002c8e, 0x002c90, 0x002c90, 0x002c92, 0x002c92, 0x002c94, 0x002c94, 0x002c96, 0x002c96, 0x002c98, 0x002c98, 0x002c9a, 0x002c9a, 0x002c9c, 0x002c9c, 0x002c9e, 0x002c9e, 0x002ca0, 0x002ca0, 0x002ca2, 0x002ca2, 0x002ca4, 0x002ca4, 0x002ca6, 0x002ca6, 0x002ca8, 0x002ca8, 0x002caa, 0x002caa, @@ -1288,9 +1313,10 @@ private static void populateCWCF() { 0x00a768, 0x00a768, 0x00a76a, 0x00a76a, 0x00a76c, 0x00a76c, 0x00a76e, 0x00a76e, 0x00a779, 0x00a779, 0x00a77b, 0x00a77b, 0x00a77d, 0x00a77e, 0x00a780, 0x00a780, 0x00a782, 0x00a782, 0x00a784, 0x00a784, 0x00a786, 0x00a786, 0x00a78b, 0x00a78b, 0x00a78d, 0x00a78d, 0x00a790, 0x00a790, 0x00a792, 0x00a792, 0x00a796, 0x00a796, 0x00a798, 0x00a798, 0x00a79a, 0x00a79a, 0x00a79c, 0x00a79c, 0x00a79e, 0x00a79e, 0x00a7a0, 0x00a7a0, 0x00a7a2, 0x00a7a2, 0x00a7a4, 0x00a7a4, 0x00a7a6, 0x00a7a6, 0x00a7a8, 0x00a7a8, 0x00a7aa, - 0x00a7ae, 0x00a7b0, 0x00a7b4, 0x00a7b6, 0x00a7b6, 0x00a7b8, 0x00a7b8, 0x00a7ba, 0x00a7ba, 0x00a7bc, 0x00a7bc, 0x00a7be, 0x00a7be, 0x00a7c2, 0x00a7c2, 0x00a7c4, 0x00a7c7, - 0x00a7c9, 0x00a7c9, 0x00a7f5, 0x00a7f5, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff21, 0x00ff3a, 0x010400, 0x010427, 0x0104b0, 0x0104d3, 0x010c80, - 0x010cb2, 0x0118a0, 0x0118bf, 0x016e40, 0x016e5f, 0x01e900, 0x01e921)); + 0x00a7ae, 0x00a7b0, 0x00a7b4, 0x00a7b6, 0x00a7b6, 0x00a7b8, 0x00a7b8, 0x00a7ba, 0x00a7ba, 0x00a7bc, 0x00a7bc, 0x00a7be, 0x00a7be, 0x00a7c0, 0x00a7c0, 0x00a7c2, 0x00a7c2, + 0x00a7c4, 0x00a7c7, 0x00a7c9, 0x00a7c9, 0x00a7d0, 0x00a7d0, 0x00a7d6, 0x00a7d6, 0x00a7d8, 0x00a7d8, 0x00a7f5, 0x00a7f5, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, + 0x00fb17, 0x00ff21, 0x00ff3a, 0x010400, 0x010427, 0x0104b0, 0x0104d3, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010c80, 0x010cb2, + 0x0118a0, 0x0118bf, 0x016e40, 0x016e5f, 0x01e900, 0x01e921)); } private static void populateCWCM() { @@ -1304,11 +1330,12 @@ private static void populateCWCM() { 0x001d7d, 0x001d7d, 0x001d8e, 0x001d8e, 0x001e00, 0x001e9b, 0x001e9e, 0x001e9e, 0x001ea0, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002126, 0x002126, 0x00212a, 0x00212b, 0x002132, - 0x002132, 0x00214e, 0x00214e, 0x002160, 0x00217f, 0x002183, 0x002184, 0x0024b6, 0x0024e9, 0x002c00, 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002c70, 0x002c72, 0x002c73, - 0x002c75, 0x002c76, 0x002c7e, 0x002ce3, 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x00a640, 0x00a66d, 0x00a680, - 0x00a69b, 0x00a722, 0x00a72f, 0x00a732, 0x00a76f, 0x00a779, 0x00a787, 0x00a78b, 0x00a78d, 0x00a790, 0x00a794, 0x00a796, 0x00a7ae, 0x00a7b0, 0x00a7bf, 0x00a7c2, 0x00a7ca, - 0x00a7f5, 0x00a7f6, 0x00ab53, 0x00ab53, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, 0x010400, 0x01044f, 0x0104b0, - 0x0104d3, 0x0104d8, 0x0104fb, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x0118a0, 0x0118df, 0x016e40, 0x016e7f, 0x01e900, 0x01e943)); + 0x002132, 0x00214e, 0x00214e, 0x002160, 0x00217f, 0x002183, 0x002184, 0x0024b6, 0x0024e9, 0x002c00, 0x002c70, 0x002c72, 0x002c73, 0x002c75, 0x002c76, 0x002c7e, 0x002ce3, + 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x00a640, 0x00a66d, 0x00a680, 0x00a69b, 0x00a722, 0x00a72f, 0x00a732, + 0x00a76f, 0x00a779, 0x00a787, 0x00a78b, 0x00a78d, 0x00a790, 0x00a794, 0x00a796, 0x00a7ae, 0x00a7b0, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d6, 0x00a7d9, 0x00a7f5, 0x00a7f6, + 0x00ab53, 0x00ab53, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, 0x010400, 0x01044f, 0x0104b0, 0x0104d3, 0x0104d8, + 0x0104fb, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, + 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x0118a0, 0x0118df, 0x016e40, 0x016e7f, 0x01e900, 0x01e943)); } private static void populateCWKCF() { @@ -1349,7 +1376,7 @@ private static void populateCWKCF() { 0x0009dc, 0x0009dd, 0x0009df, 0x0009df, 0x000a33, 0x000a33, 0x000a36, 0x000a36, 0x000a59, 0x000a5b, 0x000a5e, 0x000a5e, 0x000b5c, 0x000b5d, 0x000e33, 0x000e33, 0x000eb3, 0x000eb3, 0x000edc, 0x000edd, 0x000f0c, 0x000f0c, 0x000f43, 0x000f43, 0x000f4d, 0x000f4d, 0x000f52, 0x000f52, 0x000f57, 0x000f57, 0x000f5c, 0x000f5c, 0x000f69, 0x000f69, 0x000f73, 0x000f73, 0x000f75, 0x000f79, 0x000f81, 0x000f81, 0x000f93, 0x000f93, 0x000f9d, 0x000f9d, 0x000fa2, 0x000fa2, 0x000fa7, 0x000fa7, 0x000fac, 0x000fac, 0x000fb9, - 0x000fb9, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010fc, 0x0010fc, 0x00115f, 0x001160, 0x0013f8, 0x0013fd, 0x0017b4, 0x0017b5, 0x00180b, 0x00180e, + 0x000fb9, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010fc, 0x0010fc, 0x00115f, 0x001160, 0x0013f8, 0x0013fd, 0x0017b4, 0x0017b5, 0x00180b, 0x00180f, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cbf, 0x001d2c, 0x001d2e, 0x001d30, 0x001d3a, 0x001d3c, 0x001d4d, 0x001d4f, 0x001d6a, 0x001d78, 0x001d78, 0x001d9b, 0x001dbf, 0x001e00, 0x001e00, 0x001e02, 0x001e02, 0x001e04, 0x001e04, 0x001e06, 0x001e06, 0x001e08, 0x001e08, 0x001e0a, 0x001e0a, 0x001e0c, 0x001e0c, 0x001e0e, 0x001e0e, 0x001e10, 0x001e10, 0x001e12, 0x001e12, 0x001e14, 0x001e14, 0x001e16, 0x001e16, 0x001e18, 0x001e18, 0x001e1a, 0x001e1a, 0x001e1c, 0x001e1c, 0x001e1e, 0x001e1e, 0x001e20, @@ -1373,7 +1400,7 @@ private static void populateCWKCF() { 0x00203e, 0x00203e, 0x002047, 0x002049, 0x002057, 0x002057, 0x00205f, 0x002071, 0x002074, 0x00208e, 0x002090, 0x00209c, 0x0020a8, 0x0020a8, 0x002100, 0x002103, 0x002105, 0x002107, 0x002109, 0x002113, 0x002115, 0x002116, 0x002119, 0x00211d, 0x002120, 0x002122, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x00212d, 0x00212f, 0x002139, 0x00213b, 0x002140, 0x002145, 0x002149, 0x002150, 0x00217f, 0x002183, 0x002183, 0x002189, 0x002189, 0x00222c, 0x00222d, 0x00222f, 0x002230, 0x002329, - 0x00232a, 0x002460, 0x0024ea, 0x002a0c, 0x002a0c, 0x002a74, 0x002a76, 0x002adc, 0x002adc, 0x002c00, 0x002c2e, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, + 0x00232a, 0x002460, 0x0024ea, 0x002a0c, 0x002a0c, 0x002a74, 0x002a76, 0x002adc, 0x002adc, 0x002c00, 0x002c2f, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, 0x002c69, 0x002c69, 0x002c6b, 0x002c6b, 0x002c6d, 0x002c70, 0x002c72, 0x002c72, 0x002c75, 0x002c75, 0x002c7c, 0x002c80, 0x002c82, 0x002c82, 0x002c84, 0x002c84, 0x002c86, 0x002c86, 0x002c88, 0x002c88, 0x002c8a, 0x002c8a, 0x002c8c, 0x002c8c, 0x002c8e, 0x002c8e, 0x002c90, 0x002c90, 0x002c92, 0x002c92, 0x002c94, 0x002c94, 0x002c96, 0x002c96, 0x002c98, 0x002c98, 0x002c9a, 0x002c9a, 0x002c9c, 0x002c9c, 0x002c9e, 0x002c9e, 0x002ca0, 0x002ca0, 0x002ca2, 0x002ca2, 0x002ca4, 0x002ca4, 0x002ca6, 0x002ca6, 0x002ca8, @@ -1395,21 +1422,22 @@ private static void populateCWKCF() { 0x00a77d, 0x00a77e, 0x00a780, 0x00a780, 0x00a782, 0x00a782, 0x00a784, 0x00a784, 0x00a786, 0x00a786, 0x00a78b, 0x00a78b, 0x00a78d, 0x00a78d, 0x00a790, 0x00a790, 0x00a792, 0x00a792, 0x00a796, 0x00a796, 0x00a798, 0x00a798, 0x00a79a, 0x00a79a, 0x00a79c, 0x00a79c, 0x00a79e, 0x00a79e, 0x00a7a0, 0x00a7a0, 0x00a7a2, 0x00a7a2, 0x00a7a4, 0x00a7a4, 0x00a7a6, 0x00a7a6, 0x00a7a8, 0x00a7a8, 0x00a7aa, 0x00a7ae, 0x00a7b0, 0x00a7b4, 0x00a7b6, 0x00a7b6, 0x00a7b8, 0x00a7b8, 0x00a7ba, 0x00a7ba, 0x00a7bc, 0x00a7bc, 0x00a7be, - 0x00a7be, 0x00a7c2, 0x00a7c2, 0x00a7c4, 0x00a7c7, 0x00a7c9, 0x00a7c9, 0x00a7f5, 0x00a7f5, 0x00a7f8, 0x00a7f9, 0x00ab5c, 0x00ab5f, 0x00ab69, 0x00ab69, 0x00ab70, 0x00abbf, - 0x00f900, 0x00fa0d, 0x00fa10, 0x00fa10, 0x00fa12, 0x00fa12, 0x00fa15, 0x00fa1e, 0x00fa20, 0x00fa20, 0x00fa22, 0x00fa22, 0x00fa25, 0x00fa26, 0x00fa2a, 0x00fa6d, 0x00fa70, - 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb1d, 0x00fb1f, 0x00fb36, 0x00fb38, 0x00fb3c, 0x00fb3e, 0x00fb3e, 0x00fb40, 0x00fb41, 0x00fb43, 0x00fb44, - 0x00fb46, 0x00fbb1, 0x00fbd3, 0x00fd3d, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdfc, 0x00fe00, 0x00fe19, 0x00fe30, 0x00fe44, 0x00fe47, 0x00fe52, 0x00fe54, - 0x00fe66, 0x00fe68, 0x00fe6b, 0x00fe70, 0x00fe72, 0x00fe74, 0x00fe74, 0x00fe76, 0x00fefc, 0x00feff, 0x00feff, 0x00ff01, 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, - 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, 0x00fff0, 0x00fff8, 0x010400, 0x010427, 0x0104b0, 0x0104d3, 0x010c80, 0x010cb2, 0x0118a0, - 0x0118bf, 0x016e40, 0x016e5f, 0x01bca0, 0x01bca3, 0x01d15e, 0x01d164, 0x01d173, 0x01d17a, 0x01d1bb, 0x01d1c0, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, - 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, - 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d7cb, - 0x01d7ce, 0x01d7ff, 0x01e900, 0x01e921, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, - 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, - 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, - 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, - 0x01eeab, 0x01eebb, 0x01f100, 0x01f10a, 0x01f110, 0x01f12e, 0x01f130, 0x01f14f, 0x01f16a, 0x01f16c, 0x01f190, 0x01f190, 0x01f200, 0x01f202, 0x01f210, 0x01f23b, 0x01f240, - 0x01f248, 0x01f250, 0x01f251, 0x01fbf0, 0x01fbf9, 0x02f800, 0x02fa1d, 0x0e0000, 0x0e0fff)); + 0x00a7be, 0x00a7c0, 0x00a7c0, 0x00a7c2, 0x00a7c2, 0x00a7c4, 0x00a7c7, 0x00a7c9, 0x00a7c9, 0x00a7d0, 0x00a7d0, 0x00a7d6, 0x00a7d6, 0x00a7d8, 0x00a7d8, 0x00a7f2, 0x00a7f5, + 0x00a7f8, 0x00a7f9, 0x00ab5c, 0x00ab5f, 0x00ab69, 0x00ab69, 0x00ab70, 0x00abbf, 0x00f900, 0x00fa0d, 0x00fa10, 0x00fa10, 0x00fa12, 0x00fa12, 0x00fa15, 0x00fa1e, 0x00fa20, + 0x00fa20, 0x00fa22, 0x00fa22, 0x00fa25, 0x00fa26, 0x00fa2a, 0x00fa6d, 0x00fa70, 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb1d, 0x00fb1f, 0x00fb36, + 0x00fb38, 0x00fb3c, 0x00fb3e, 0x00fb3e, 0x00fb40, 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbb1, 0x00fbd3, 0x00fd3d, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, + 0x00fdfc, 0x00fe00, 0x00fe19, 0x00fe30, 0x00fe44, 0x00fe47, 0x00fe52, 0x00fe54, 0x00fe66, 0x00fe68, 0x00fe6b, 0x00fe70, 0x00fe72, 0x00fe74, 0x00fe74, 0x00fe76, 0x00fefc, + 0x00feff, 0x00feff, 0x00ff01, 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, 0x00fff0, + 0x00fff8, 0x010400, 0x010427, 0x0104b0, 0x0104d3, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010781, 0x010785, 0x010787, 0x0107b0, + 0x0107b2, 0x0107ba, 0x010c80, 0x010cb2, 0x0118a0, 0x0118bf, 0x016e40, 0x016e5f, 0x01bca0, 0x01bca3, 0x01d15e, 0x01d164, 0x01d173, 0x01d17a, 0x01d1bb, 0x01d1c0, 0x01d400, + 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, + 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, + 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d7cb, 0x01d7ce, 0x01d7ff, 0x01e900, 0x01e921, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, + 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, + 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, + 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, + 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x01f100, 0x01f10a, 0x01f110, 0x01f12e, 0x01f130, 0x01f14f, 0x01f16a, 0x01f16c, 0x01f190, 0x01f190, + 0x01f200, 0x01f202, 0x01f210, 0x01f23b, 0x01f240, 0x01f248, 0x01f250, 0x01f251, 0x01fbf0, 0x01fbf9, 0x02f800, 0x02fa1d, 0x0e0000, 0x0e0fff)); } private static void populateCWL() { @@ -1463,7 +1491,7 @@ private static void populateCWL() { 0x001efa, 0x001efa, 0x001efc, 0x001efc, 0x001efe, 0x001efe, 0x001f08, 0x001f0f, 0x001f18, 0x001f1d, 0x001f28, 0x001f2f, 0x001f38, 0x001f3f, 0x001f48, 0x001f4d, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f5f, 0x001f68, 0x001f6f, 0x001f88, 0x001f8f, 0x001f98, 0x001f9f, 0x001fa8, 0x001faf, 0x001fb8, 0x001fbc, 0x001fc8, 0x001fcc, 0x001fd8, 0x001fdb, 0x001fe8, 0x001fec, 0x001ff8, 0x001ffc, 0x002126, 0x002126, 0x00212a, 0x00212b, 0x002132, 0x002132, 0x002160, 0x00216f, 0x002183, - 0x002183, 0x0024b6, 0x0024cf, 0x002c00, 0x002c2e, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, 0x002c69, 0x002c69, 0x002c6b, 0x002c6b, 0x002c6d, 0x002c70, + 0x002183, 0x0024b6, 0x0024cf, 0x002c00, 0x002c2f, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, 0x002c69, 0x002c69, 0x002c6b, 0x002c6b, 0x002c6d, 0x002c70, 0x002c72, 0x002c72, 0x002c75, 0x002c75, 0x002c7e, 0x002c80, 0x002c82, 0x002c82, 0x002c84, 0x002c84, 0x002c86, 0x002c86, 0x002c88, 0x002c88, 0x002c8a, 0x002c8a, 0x002c8c, 0x002c8c, 0x002c8e, 0x002c8e, 0x002c90, 0x002c90, 0x002c92, 0x002c92, 0x002c94, 0x002c94, 0x002c96, 0x002c96, 0x002c98, 0x002c98, 0x002c9a, 0x002c9a, 0x002c9c, 0x002c9c, 0x002c9e, 0x002c9e, 0x002ca0, 0x002ca0, 0x002ca2, 0x002ca2, 0x002ca4, 0x002ca4, 0x002ca6, 0x002ca6, 0x002ca8, 0x002ca8, 0x002caa, 0x002caa, 0x002cac, 0x002cac, 0x002cae, @@ -1482,8 +1510,9 @@ private static void populateCWL() { 0x00a76a, 0x00a76c, 0x00a76c, 0x00a76e, 0x00a76e, 0x00a779, 0x00a779, 0x00a77b, 0x00a77b, 0x00a77d, 0x00a77e, 0x00a780, 0x00a780, 0x00a782, 0x00a782, 0x00a784, 0x00a784, 0x00a786, 0x00a786, 0x00a78b, 0x00a78b, 0x00a78d, 0x00a78d, 0x00a790, 0x00a790, 0x00a792, 0x00a792, 0x00a796, 0x00a796, 0x00a798, 0x00a798, 0x00a79a, 0x00a79a, 0x00a79c, 0x00a79c, 0x00a79e, 0x00a79e, 0x00a7a0, 0x00a7a0, 0x00a7a2, 0x00a7a2, 0x00a7a4, 0x00a7a4, 0x00a7a6, 0x00a7a6, 0x00a7a8, 0x00a7a8, 0x00a7aa, 0x00a7ae, 0x00a7b0, 0x00a7b4, - 0x00a7b6, 0x00a7b6, 0x00a7b8, 0x00a7b8, 0x00a7ba, 0x00a7ba, 0x00a7bc, 0x00a7bc, 0x00a7be, 0x00a7be, 0x00a7c2, 0x00a7c2, 0x00a7c4, 0x00a7c7, 0x00a7c9, 0x00a7c9, 0x00a7f5, - 0x00a7f5, 0x00ff21, 0x00ff3a, 0x010400, 0x010427, 0x0104b0, 0x0104d3, 0x010c80, 0x010cb2, 0x0118a0, 0x0118bf, 0x016e40, 0x016e5f, 0x01e900, 0x01e921)); + 0x00a7b6, 0x00a7b6, 0x00a7b8, 0x00a7b8, 0x00a7ba, 0x00a7ba, 0x00a7bc, 0x00a7bc, 0x00a7be, 0x00a7be, 0x00a7c0, 0x00a7c0, 0x00a7c2, 0x00a7c2, 0x00a7c4, 0x00a7c7, 0x00a7c9, + 0x00a7c9, 0x00a7d0, 0x00a7d0, 0x00a7d6, 0x00a7d6, 0x00a7d8, 0x00a7d8, 0x00a7f5, 0x00a7f5, 0x00ff21, 0x00ff3a, 0x010400, 0x010427, 0x0104b0, 0x0104d3, 0x010570, 0x01057a, + 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010c80, 0x010cb2, 0x0118a0, 0x0118bf, 0x016e40, 0x016e5f, 0x01e900, 0x01e921)); } private static void populateCWT() { @@ -1538,7 +1567,7 @@ private static void populateCWT() { 0x001ef1, 0x001ef3, 0x001ef3, 0x001ef5, 0x001ef5, 0x001ef7, 0x001ef7, 0x001ef9, 0x001ef9, 0x001efb, 0x001efb, 0x001efd, 0x001efd, 0x001eff, 0x001f07, 0x001f10, 0x001f15, 0x001f20, 0x001f27, 0x001f30, 0x001f37, 0x001f40, 0x001f45, 0x001f50, 0x001f57, 0x001f60, 0x001f67, 0x001f70, 0x001f7d, 0x001f80, 0x001f87, 0x001f90, 0x001f97, 0x001fa0, 0x001fa7, 0x001fb0, 0x001fb4, 0x001fb6, 0x001fb7, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fc7, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fd7, 0x001fe0, 0x001fe7, - 0x001ff2, 0x001ff4, 0x001ff6, 0x001ff7, 0x00214e, 0x00214e, 0x002170, 0x00217f, 0x002184, 0x002184, 0x0024d0, 0x0024e9, 0x002c30, 0x002c5e, 0x002c61, 0x002c61, 0x002c65, + 0x001ff2, 0x001ff4, 0x001ff6, 0x001ff7, 0x00214e, 0x00214e, 0x002170, 0x00217f, 0x002184, 0x002184, 0x0024d0, 0x0024e9, 0x002c30, 0x002c5f, 0x002c61, 0x002c61, 0x002c65, 0x002c66, 0x002c68, 0x002c68, 0x002c6a, 0x002c6a, 0x002c6c, 0x002c6c, 0x002c73, 0x002c73, 0x002c76, 0x002c76, 0x002c81, 0x002c81, 0x002c83, 0x002c83, 0x002c85, 0x002c85, 0x002c87, 0x002c87, 0x002c89, 0x002c89, 0x002c8b, 0x002c8b, 0x002c8d, 0x002c8d, 0x002c8f, 0x002c8f, 0x002c91, 0x002c91, 0x002c93, 0x002c93, 0x002c95, 0x002c95, 0x002c97, 0x002c97, 0x002c99, 0x002c99, 0x002c9b, 0x002c9b, 0x002c9d, 0x002c9d, 0x002c9f, 0x002c9f, 0x002ca1, 0x002ca1, 0x002ca3, 0x002ca3, 0x002ca5, 0x002ca5, 0x002ca7, 0x002ca7, @@ -1558,8 +1587,9 @@ private static void populateCWT() { 0x00a76f, 0x00a77a, 0x00a77a, 0x00a77c, 0x00a77c, 0x00a77f, 0x00a77f, 0x00a781, 0x00a781, 0x00a783, 0x00a783, 0x00a785, 0x00a785, 0x00a787, 0x00a787, 0x00a78c, 0x00a78c, 0x00a791, 0x00a791, 0x00a793, 0x00a794, 0x00a797, 0x00a797, 0x00a799, 0x00a799, 0x00a79b, 0x00a79b, 0x00a79d, 0x00a79d, 0x00a79f, 0x00a79f, 0x00a7a1, 0x00a7a1, 0x00a7a3, 0x00a7a3, 0x00a7a5, 0x00a7a5, 0x00a7a7, 0x00a7a7, 0x00a7a9, 0x00a7a9, 0x00a7b5, 0x00a7b5, 0x00a7b7, 0x00a7b7, 0x00a7b9, 0x00a7b9, 0x00a7bb, 0x00a7bb, 0x00a7bd, 0x00a7bd, - 0x00a7bf, 0x00a7bf, 0x00a7c3, 0x00a7c3, 0x00a7c8, 0x00a7c8, 0x00a7ca, 0x00a7ca, 0x00a7f6, 0x00a7f6, 0x00ab53, 0x00ab53, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, - 0x00fb17, 0x00ff41, 0x00ff5a, 0x010428, 0x01044f, 0x0104d8, 0x0104fb, 0x010cc0, 0x010cf2, 0x0118c0, 0x0118df, 0x016e60, 0x016e7f, 0x01e922, 0x01e943)); + 0x00a7bf, 0x00a7bf, 0x00a7c1, 0x00a7c1, 0x00a7c3, 0x00a7c3, 0x00a7c8, 0x00a7c8, 0x00a7ca, 0x00a7ca, 0x00a7d1, 0x00a7d1, 0x00a7d7, 0x00a7d7, 0x00a7d9, 0x00a7d9, 0x00a7f6, + 0x00a7f6, 0x00ab53, 0x00ab53, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff41, 0x00ff5a, 0x010428, 0x01044f, 0x0104d8, 0x0104fb, 0x010597, 0x0105a1, + 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010cc0, 0x010cf2, 0x0118c0, 0x0118df, 0x016e60, 0x016e7f, 0x01e922, 0x01e943)); } private static void populateCWU() { @@ -1614,7 +1644,7 @@ private static void populateCWU() { 0x001eef, 0x001ef1, 0x001ef1, 0x001ef3, 0x001ef3, 0x001ef5, 0x001ef5, 0x001ef7, 0x001ef7, 0x001ef9, 0x001ef9, 0x001efb, 0x001efb, 0x001efd, 0x001efd, 0x001eff, 0x001f07, 0x001f10, 0x001f15, 0x001f20, 0x001f27, 0x001f30, 0x001f37, 0x001f40, 0x001f45, 0x001f50, 0x001f57, 0x001f60, 0x001f67, 0x001f70, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fb7, 0x001fbc, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fc7, 0x001fcc, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fd7, 0x001fe0, 0x001fe7, - 0x001ff2, 0x001ff4, 0x001ff6, 0x001ff7, 0x001ffc, 0x001ffc, 0x00214e, 0x00214e, 0x002170, 0x00217f, 0x002184, 0x002184, 0x0024d0, 0x0024e9, 0x002c30, 0x002c5e, 0x002c61, + 0x001ff2, 0x001ff4, 0x001ff6, 0x001ff7, 0x001ffc, 0x001ffc, 0x00214e, 0x00214e, 0x002170, 0x00217f, 0x002184, 0x002184, 0x0024d0, 0x0024e9, 0x002c30, 0x002c5f, 0x002c61, 0x002c61, 0x002c65, 0x002c66, 0x002c68, 0x002c68, 0x002c6a, 0x002c6a, 0x002c6c, 0x002c6c, 0x002c73, 0x002c73, 0x002c76, 0x002c76, 0x002c81, 0x002c81, 0x002c83, 0x002c83, 0x002c85, 0x002c85, 0x002c87, 0x002c87, 0x002c89, 0x002c89, 0x002c8b, 0x002c8b, 0x002c8d, 0x002c8d, 0x002c8f, 0x002c8f, 0x002c91, 0x002c91, 0x002c93, 0x002c93, 0x002c95, 0x002c95, 0x002c97, 0x002c97, 0x002c99, 0x002c99, 0x002c9b, 0x002c9b, 0x002c9d, 0x002c9d, 0x002c9f, 0x002c9f, 0x002ca1, 0x002ca1, 0x002ca3, 0x002ca3, 0x002ca5, 0x002ca5, @@ -1634,8 +1664,9 @@ private static void populateCWU() { 0x00a76d, 0x00a76f, 0x00a76f, 0x00a77a, 0x00a77a, 0x00a77c, 0x00a77c, 0x00a77f, 0x00a77f, 0x00a781, 0x00a781, 0x00a783, 0x00a783, 0x00a785, 0x00a785, 0x00a787, 0x00a787, 0x00a78c, 0x00a78c, 0x00a791, 0x00a791, 0x00a793, 0x00a794, 0x00a797, 0x00a797, 0x00a799, 0x00a799, 0x00a79b, 0x00a79b, 0x00a79d, 0x00a79d, 0x00a79f, 0x00a79f, 0x00a7a1, 0x00a7a1, 0x00a7a3, 0x00a7a3, 0x00a7a5, 0x00a7a5, 0x00a7a7, 0x00a7a7, 0x00a7a9, 0x00a7a9, 0x00a7b5, 0x00a7b5, 0x00a7b7, 0x00a7b7, 0x00a7b9, 0x00a7b9, 0x00a7bb, 0x00a7bb, - 0x00a7bd, 0x00a7bd, 0x00a7bf, 0x00a7bf, 0x00a7c3, 0x00a7c3, 0x00a7c8, 0x00a7c8, 0x00a7ca, 0x00a7ca, 0x00a7f6, 0x00a7f6, 0x00ab53, 0x00ab53, 0x00ab70, 0x00abbf, 0x00fb00, - 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff41, 0x00ff5a, 0x010428, 0x01044f, 0x0104d8, 0x0104fb, 0x010cc0, 0x010cf2, 0x0118c0, 0x0118df, 0x016e60, 0x016e7f, 0x01e922, 0x01e943)); + 0x00a7bd, 0x00a7bd, 0x00a7bf, 0x00a7bf, 0x00a7c1, 0x00a7c1, 0x00a7c3, 0x00a7c3, 0x00a7c8, 0x00a7c8, 0x00a7ca, 0x00a7ca, 0x00a7d1, 0x00a7d1, 0x00a7d7, 0x00a7d7, 0x00a7d9, + 0x00a7d9, 0x00a7f6, 0x00a7f6, 0x00ab53, 0x00ab53, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff41, 0x00ff5a, 0x010428, 0x01044f, 0x0104d8, 0x0104fb, + 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010cc0, 0x010cf2, 0x0118c0, 0x0118df, 0x016e60, 0x016e7f, 0x01e922, 0x01e943)); } private static void populateCASED() { @@ -1648,19 +1679,20 @@ private static void populateCASED() { 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002119, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x00212d, 0x00212f, 0x002134, 0x002139, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, - 0x00217f, 0x002183, 0x002184, 0x0024b6, 0x0024e9, 0x002c00, 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, 0x002d25, - 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x00a640, 0x00a66d, 0x00a680, 0x00a69d, 0x00a722, 0x00a787, 0x00a78b, 0x00a78e, 0x00a790, 0x00a7bf, 0x00a7c2, 0x00a7ca, 0x00a7f5, + 0x00217f, 0x002183, 0x002184, 0x0024b6, 0x0024e9, 0x002c00, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, + 0x00a640, 0x00a66d, 0x00a680, 0x00a69d, 0x00a722, 0x00a787, 0x00a78b, 0x00a78e, 0x00a790, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, 0x00a7f5, 0x00a7f6, 0x00a7f8, 0x00a7fa, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab68, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, - 0x010400, 0x01044f, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x0118a0, 0x0118df, 0x016e40, 0x016e7f, 0x01d400, 0x01d454, 0x01d456, - 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, - 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, - 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, - 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01e900, 0x01e943, 0x01f130, 0x01f149, 0x01f150, 0x01f169, 0x01f170, 0x01f189)); + 0x010400, 0x01044f, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, + 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x0118a0, 0x0118df, 0x016e40, 0x016e7f, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, + 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, + 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, + 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, + 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01df00, 0x01df09, 0x01df0b, 0x01df1e, 0x01e900, 0x01e943, 0x01f130, 0x01f149, 0x01f150, 0x01f169, 0x01f170, 0x01f189)); } private static void populateDI() { SET_ENCODINGS.put("DI", - CodePointSet.createNoDedup(0x0000ad, 0x0000ad, 0x00034f, 0x00034f, 0x00061c, 0x00061c, 0x00115f, 0x001160, 0x0017b4, 0x0017b5, 0x00180b, 0x00180e, 0x00200b, 0x00200f, 0x00202a, + CodePointSet.createNoDedup(0x0000ad, 0x0000ad, 0x00034f, 0x00034f, 0x00061c, 0x00061c, 0x00115f, 0x001160, 0x0017b4, 0x0017b5, 0x00180b, 0x00180f, 0x00200b, 0x00200f, 0x00202a, 0x00202e, 0x002060, 0x00206f, 0x003164, 0x003164, 0x00fe00, 0x00fe0f, 0x00feff, 0x00feff, 0x00ffa0, 0x00ffa0, 0x00fff0, 0x00fff8, 0x01bca0, 0x01bca3, 0x01d173, 0x01d17a, 0x0e0000, 0x0e0fff)); } @@ -1668,8 +1700,8 @@ private static void populateDI() { private static void populateDASH() { SET_ENCODINGS.put("Dash", CodePointSet.createNoDedup(0x00002d, 0x00002d, 0x00058a, 0x00058a, 0x0005be, 0x0005be, 0x001400, 0x001400, 0x001806, 0x001806, 0x002010, 0x002015, 0x002053, 0x002053, 0x00207b, - 0x00207b, 0x00208b, 0x00208b, 0x002212, 0x002212, 0x002e17, 0x002e17, 0x002e1a, 0x002e1a, 0x002e3a, 0x002e3b, 0x002e40, 0x002e40, 0x00301c, 0x00301c, 0x003030, - 0x003030, 0x0030a0, 0x0030a0, 0x00fe31, 0x00fe32, 0x00fe58, 0x00fe58, 0x00fe63, 0x00fe63, 0x00ff0d, 0x00ff0d, 0x010ead, 0x010ead)); + 0x00207b, 0x00208b, 0x00208b, 0x002212, 0x002212, 0x002e17, 0x002e17, 0x002e1a, 0x002e1a, 0x002e3a, 0x002e3b, 0x002e40, 0x002e40, 0x002e5d, 0x002e5d, 0x00301c, + 0x00301c, 0x003030, 0x003030, 0x0030a0, 0x0030a0, 0x00fe31, 0x00fe32, 0x00fe58, 0x00fe58, 0x00fe63, 0x00fe63, 0x00ff0d, 0x00ff0d, 0x010ead, 0x010ead)); } private static void populateDEP() { @@ -1681,33 +1713,34 @@ private static void populateDIA() { SET_ENCODINGS.put("Dia", CodePointSet.createNoDedup(0x00005e, 0x00005e, 0x000060, 0x000060, 0x0000a8, 0x0000a8, 0x0000af, 0x0000af, 0x0000b4, 0x0000b4, 0x0000b7, 0x0000b8, 0x0002b0, 0x00034e, 0x000350, 0x000357, 0x00035d, 0x000362, 0x000374, 0x000375, 0x00037a, 0x00037a, 0x000384, 0x000385, 0x000483, 0x000487, 0x000559, 0x000559, 0x000591, 0x0005a1, 0x0005a3, 0x0005bd, 0x0005bf, 0x0005bf, 0x0005c1, 0x0005c2, 0x0005c4, 0x0005c4, 0x00064b, 0x000652, 0x000657, 0x000658, 0x0006df, 0x0006e0, 0x0006e5, 0x0006e6, 0x0006ea, 0x0006ec, - 0x000730, 0x00074a, 0x0007a6, 0x0007b0, 0x0007eb, 0x0007f5, 0x000818, 0x000819, 0x0008e3, 0x0008fe, 0x00093c, 0x00093c, 0x00094d, 0x00094d, 0x000951, 0x000954, 0x000971, - 0x000971, 0x0009bc, 0x0009bc, 0x0009cd, 0x0009cd, 0x000a3c, 0x000a3c, 0x000a4d, 0x000a4d, 0x000abc, 0x000abc, 0x000acd, 0x000acd, 0x000afd, 0x000aff, 0x000b3c, 0x000b3c, - 0x000b4d, 0x000b4d, 0x000b55, 0x000b55, 0x000bcd, 0x000bcd, 0x000c4d, 0x000c4d, 0x000cbc, 0x000cbc, 0x000ccd, 0x000ccd, 0x000d3b, 0x000d3c, 0x000d4d, 0x000d4d, 0x000dca, - 0x000dca, 0x000e47, 0x000e4c, 0x000e4e, 0x000e4e, 0x000eba, 0x000eba, 0x000ec8, 0x000ecc, 0x000f18, 0x000f19, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, - 0x000f3e, 0x000f3f, 0x000f82, 0x000f84, 0x000f86, 0x000f87, 0x000fc6, 0x000fc6, 0x001037, 0x001037, 0x001039, 0x00103a, 0x001063, 0x001064, 0x001069, 0x00106d, 0x001087, - 0x00108d, 0x00108f, 0x00108f, 0x00109a, 0x00109b, 0x00135d, 0x00135f, 0x0017c9, 0x0017d3, 0x0017dd, 0x0017dd, 0x001939, 0x00193b, 0x001a75, 0x001a7c, 0x001a7f, 0x001a7f, - 0x001ab0, 0x001abd, 0x001b34, 0x001b34, 0x001b44, 0x001b44, 0x001b6b, 0x001b73, 0x001baa, 0x001bab, 0x001c36, 0x001c37, 0x001c78, 0x001c7d, 0x001cd0, 0x001ce8, 0x001ced, - 0x001ced, 0x001cf4, 0x001cf4, 0x001cf7, 0x001cf9, 0x001d2c, 0x001d6a, 0x001dc4, 0x001dcf, 0x001df5, 0x001df9, 0x001dfd, 0x001dff, 0x001fbd, 0x001fbd, 0x001fbf, 0x001fc1, - 0x001fcd, 0x001fcf, 0x001fdd, 0x001fdf, 0x001fed, 0x001fef, 0x001ffd, 0x001ffe, 0x002cef, 0x002cf1, 0x002e2f, 0x002e2f, 0x00302a, 0x00302f, 0x003099, 0x00309c, 0x0030fc, - 0x0030fc, 0x00a66f, 0x00a66f, 0x00a67c, 0x00a67d, 0x00a67f, 0x00a67f, 0x00a69c, 0x00a69d, 0x00a6f0, 0x00a6f1, 0x00a700, 0x00a721, 0x00a788, 0x00a78a, 0x00a7f8, 0x00a7f9, - 0x00a8c4, 0x00a8c4, 0x00a8e0, 0x00a8f1, 0x00a92b, 0x00a92e, 0x00a953, 0x00a953, 0x00a9b3, 0x00a9b3, 0x00a9c0, 0x00a9c0, 0x00a9e5, 0x00a9e5, 0x00aa7b, 0x00aa7d, 0x00aabf, - 0x00aac2, 0x00aaf6, 0x00aaf6, 0x00ab5b, 0x00ab5f, 0x00ab69, 0x00ab6b, 0x00abec, 0x00abed, 0x00fb1e, 0x00fb1e, 0x00fe20, 0x00fe2f, 0x00ff3e, 0x00ff3e, 0x00ff40, 0x00ff40, - 0x00ff70, 0x00ff70, 0x00ff9e, 0x00ff9f, 0x00ffe3, 0x00ffe3, 0x0102e0, 0x0102e0, 0x010ae5, 0x010ae6, 0x010d22, 0x010d27, 0x010f46, 0x010f50, 0x0110b9, 0x0110ba, 0x011133, - 0x011134, 0x011173, 0x011173, 0x0111c0, 0x0111c0, 0x0111ca, 0x0111cc, 0x011235, 0x011236, 0x0112e9, 0x0112ea, 0x01133c, 0x01133c, 0x01134d, 0x01134d, 0x011366, 0x01136c, - 0x011370, 0x011374, 0x011442, 0x011442, 0x011446, 0x011446, 0x0114c2, 0x0114c3, 0x0115bf, 0x0115c0, 0x01163f, 0x01163f, 0x0116b6, 0x0116b7, 0x01172b, 0x01172b, 0x011839, - 0x01183a, 0x01193d, 0x01193e, 0x011943, 0x011943, 0x0119e0, 0x0119e0, 0x011a34, 0x011a34, 0x011a47, 0x011a47, 0x011a99, 0x011a99, 0x011c3f, 0x011c3f, 0x011d42, 0x011d42, - 0x011d44, 0x011d45, 0x011d97, 0x011d97, 0x016af0, 0x016af4, 0x016b30, 0x016b36, 0x016f8f, 0x016f9f, 0x016ff0, 0x016ff1, 0x01d167, 0x01d169, 0x01d16d, 0x01d172, 0x01d17b, - 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01e130, 0x01e136, 0x01e2ec, 0x01e2ef, 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e946, 0x01e948, 0x01e94a)); + 0x000730, 0x00074a, 0x0007a6, 0x0007b0, 0x0007eb, 0x0007f5, 0x000818, 0x000819, 0x000898, 0x00089f, 0x0008c9, 0x0008d2, 0x0008e3, 0x0008fe, 0x00093c, 0x00093c, 0x00094d, + 0x00094d, 0x000951, 0x000954, 0x000971, 0x000971, 0x0009bc, 0x0009bc, 0x0009cd, 0x0009cd, 0x000a3c, 0x000a3c, 0x000a4d, 0x000a4d, 0x000abc, 0x000abc, 0x000acd, 0x000acd, + 0x000afd, 0x000aff, 0x000b3c, 0x000b3c, 0x000b4d, 0x000b4d, 0x000b55, 0x000b55, 0x000bcd, 0x000bcd, 0x000c3c, 0x000c3c, 0x000c4d, 0x000c4d, 0x000cbc, 0x000cbc, 0x000ccd, + 0x000ccd, 0x000d3b, 0x000d3c, 0x000d4d, 0x000d4d, 0x000dca, 0x000dca, 0x000e47, 0x000e4c, 0x000e4e, 0x000e4e, 0x000eba, 0x000eba, 0x000ec8, 0x000ecc, 0x000f18, 0x000f19, + 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f3e, 0x000f3f, 0x000f82, 0x000f84, 0x000f86, 0x000f87, 0x000fc6, 0x000fc6, 0x001037, 0x001037, 0x001039, + 0x00103a, 0x001063, 0x001064, 0x001069, 0x00106d, 0x001087, 0x00108d, 0x00108f, 0x00108f, 0x00109a, 0x00109b, 0x00135d, 0x00135f, 0x001714, 0x001715, 0x0017c9, 0x0017d3, + 0x0017dd, 0x0017dd, 0x001939, 0x00193b, 0x001a75, 0x001a7c, 0x001a7f, 0x001a7f, 0x001ab0, 0x001abe, 0x001ac1, 0x001acb, 0x001b34, 0x001b34, 0x001b44, 0x001b44, 0x001b6b, + 0x001b73, 0x001baa, 0x001bab, 0x001c36, 0x001c37, 0x001c78, 0x001c7d, 0x001cd0, 0x001ce8, 0x001ced, 0x001ced, 0x001cf4, 0x001cf4, 0x001cf7, 0x001cf9, 0x001d2c, 0x001d6a, + 0x001dc4, 0x001dcf, 0x001df5, 0x001dff, 0x001fbd, 0x001fbd, 0x001fbf, 0x001fc1, 0x001fcd, 0x001fcf, 0x001fdd, 0x001fdf, 0x001fed, 0x001fef, 0x001ffd, 0x001ffe, 0x002cef, + 0x002cf1, 0x002e2f, 0x002e2f, 0x00302a, 0x00302f, 0x003099, 0x00309c, 0x0030fc, 0x0030fc, 0x00a66f, 0x00a66f, 0x00a67c, 0x00a67d, 0x00a67f, 0x00a67f, 0x00a69c, 0x00a69d, + 0x00a6f0, 0x00a6f1, 0x00a700, 0x00a721, 0x00a788, 0x00a78a, 0x00a7f8, 0x00a7f9, 0x00a8c4, 0x00a8c4, 0x00a8e0, 0x00a8f1, 0x00a92b, 0x00a92e, 0x00a953, 0x00a953, 0x00a9b3, + 0x00a9b3, 0x00a9c0, 0x00a9c0, 0x00a9e5, 0x00a9e5, 0x00aa7b, 0x00aa7d, 0x00aabf, 0x00aac2, 0x00aaf6, 0x00aaf6, 0x00ab5b, 0x00ab5f, 0x00ab69, 0x00ab6b, 0x00abec, 0x00abed, + 0x00fb1e, 0x00fb1e, 0x00fe20, 0x00fe2f, 0x00ff3e, 0x00ff3e, 0x00ff40, 0x00ff40, 0x00ff70, 0x00ff70, 0x00ff9e, 0x00ff9f, 0x00ffe3, 0x00ffe3, 0x0102e0, 0x0102e0, 0x010780, + 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x010ae5, 0x010ae6, 0x010d22, 0x010d27, 0x010f46, 0x010f50, 0x010f82, 0x010f85, 0x011046, 0x011046, 0x011070, 0x011070, + 0x0110b9, 0x0110ba, 0x011133, 0x011134, 0x011173, 0x011173, 0x0111c0, 0x0111c0, 0x0111ca, 0x0111cc, 0x011235, 0x011236, 0x0112e9, 0x0112ea, 0x01133c, 0x01133c, 0x01134d, + 0x01134d, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011442, 0x011442, 0x011446, 0x011446, 0x0114c2, 0x0114c3, 0x0115bf, 0x0115c0, 0x01163f, 0x01163f, 0x0116b6, 0x0116b7, + 0x01172b, 0x01172b, 0x011839, 0x01183a, 0x01193d, 0x01193e, 0x011943, 0x011943, 0x0119e0, 0x0119e0, 0x011a34, 0x011a34, 0x011a47, 0x011a47, 0x011a99, 0x011a99, 0x011c3f, + 0x011c3f, 0x011d42, 0x011d42, 0x011d44, 0x011d45, 0x011d97, 0x011d97, 0x016af0, 0x016af4, 0x016b30, 0x016b36, 0x016f8f, 0x016f9f, 0x016ff0, 0x016ff1, 0x01aff0, 0x01aff3, + 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01cf00, 0x01cf2d, 0x01cf30, 0x01cf46, 0x01d167, 0x01d169, 0x01d16d, 0x01d172, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, + 0x01d1ad, 0x01e130, 0x01e136, 0x01e2ae, 0x01e2ae, 0x01e2ec, 0x01e2ef, 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e946, 0x01e948, 0x01e94a)); } private static void populateEBASE() { - SET_ENCODINGS.put("EBase", - CodePointSet.createNoDedup(0x00261d, 0x00261d, 0x0026f9, 0x0026f9, 0x00270a, 0x00270d, 0x01f385, 0x01f385, 0x01f3c2, 0x01f3c4, 0x01f3c7, 0x01f3c7, 0x01f3ca, 0x01f3cc, 0x01f442, - 0x01f443, 0x01f446, 0x01f450, 0x01f466, 0x01f478, 0x01f47c, 0x01f47c, 0x01f481, 0x01f483, 0x01f485, 0x01f487, 0x01f48f, 0x01f48f, 0x01f491, 0x01f491, 0x01f4aa, - 0x01f4aa, 0x01f574, 0x01f575, 0x01f57a, 0x01f57a, 0x01f590, 0x01f590, 0x01f595, 0x01f596, 0x01f645, 0x01f647, 0x01f64b, 0x01f64f, 0x01f6a3, 0x01f6a3, 0x01f6b4, - 0x01f6b6, 0x01f6c0, 0x01f6c0, 0x01f6cc, 0x01f6cc, 0x01f90c, 0x01f90c, 0x01f90f, 0x01f90f, 0x01f918, 0x01f91f, 0x01f926, 0x01f926, 0x01f930, 0x01f939, 0x01f93c, - 0x01f93e, 0x01f977, 0x01f977, 0x01f9b5, 0x01f9b6, 0x01f9b8, 0x01f9b9, 0x01f9bb, 0x01f9bb, 0x01f9cd, 0x01f9cf, 0x01f9d1, 0x01f9dd)); + SET_ENCODINGS.put("EBase", CodePointSet.createNoDedup(0x00261d, 0x00261d, 0x0026f9, 0x0026f9, 0x00270a, 0x00270d, 0x01f385, 0x01f385, 0x01f3c2, 0x01f3c4, 0x01f3c7, 0x01f3c7, 0x01f3ca, + 0x01f3cc, 0x01f442, 0x01f443, 0x01f446, 0x01f450, 0x01f466, 0x01f478, 0x01f47c, 0x01f47c, 0x01f481, 0x01f483, 0x01f485, 0x01f487, 0x01f48f, 0x01f48f, 0x01f491, 0x01f491, + 0x01f4aa, 0x01f4aa, 0x01f574, 0x01f575, 0x01f57a, 0x01f57a, 0x01f590, 0x01f590, 0x01f595, 0x01f596, 0x01f645, 0x01f647, 0x01f64b, 0x01f64f, 0x01f6a3, 0x01f6a3, 0x01f6b4, + 0x01f6b6, 0x01f6c0, 0x01f6c0, 0x01f6cc, 0x01f6cc, 0x01f90c, 0x01f90c, 0x01f90f, 0x01f90f, 0x01f918, 0x01f91f, 0x01f926, 0x01f926, 0x01f930, 0x01f939, 0x01f93c, 0x01f93e, + 0x01f977, 0x01f977, 0x01f9b5, 0x01f9b6, 0x01f9b8, 0x01f9b9, 0x01f9bb, 0x01f9bb, 0x01f9cd, 0x01f9cf, 0x01f9d1, 0x01f9dd, 0x01fac3, 0x01fac5, 0x01faf0, 0x01faf6)); } private static void populateECOMP() { @@ -1728,8 +1761,8 @@ private static void populateEPRES() { 0x01f22f, 0x01f232, 0x01f236, 0x01f238, 0x01f23a, 0x01f250, 0x01f251, 0x01f300, 0x01f320, 0x01f32d, 0x01f335, 0x01f337, 0x01f37c, 0x01f37e, 0x01f393, 0x01f3a0, 0x01f3ca, 0x01f3cf, 0x01f3d3, 0x01f3e0, 0x01f3f0, 0x01f3f4, 0x01f3f4, 0x01f3f8, 0x01f43e, 0x01f440, 0x01f440, 0x01f442, 0x01f4fc, 0x01f4ff, 0x01f53d, 0x01f54b, 0x01f54e, 0x01f550, 0x01f567, 0x01f57a, 0x01f57a, 0x01f595, 0x01f596, 0x01f5a4, 0x01f5a4, 0x01f5fb, 0x01f64f, 0x01f680, 0x01f6c5, 0x01f6cc, 0x01f6cc, 0x01f6d0, 0x01f6d2, 0x01f6d5, 0x01f6d7, - 0x01f6eb, 0x01f6ec, 0x01f6f4, 0x01f6fc, 0x01f7e0, 0x01f7eb, 0x01f90c, 0x01f93a, 0x01f93c, 0x01f945, 0x01f947, 0x01f978, 0x01f97a, 0x01f9cb, 0x01f9cd, 0x01f9ff, 0x01fa70, - 0x01fa74, 0x01fa78, 0x01fa7a, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faa8, 0x01fab0, 0x01fab6, 0x01fac0, 0x01fac2, 0x01fad0, 0x01fad6)); + 0x01f6dd, 0x01f6df, 0x01f6eb, 0x01f6ec, 0x01f6f4, 0x01f6fc, 0x01f7e0, 0x01f7eb, 0x01f7f0, 0x01f7f0, 0x01f90c, 0x01f93a, 0x01f93c, 0x01f945, 0x01f947, 0x01f9ff, 0x01fa70, + 0x01fa74, 0x01fa78, 0x01fa7c, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faac, 0x01fab0, 0x01faba, 0x01fac0, 0x01fac5, 0x01fad0, 0x01fad9, 0x01fae0, 0x01fae7, 0x01faf0, 0x01faf6)); } private static void populateEMOJI() { @@ -1749,16 +1782,18 @@ private static void populateEMOJI() { 0x01f4fd, 0x01f4ff, 0x01f53d, 0x01f549, 0x01f54e, 0x01f550, 0x01f567, 0x01f56f, 0x01f570, 0x01f573, 0x01f57a, 0x01f587, 0x01f587, 0x01f58a, 0x01f58d, 0x01f590, 0x01f590, 0x01f595, 0x01f596, 0x01f5a4, 0x01f5a5, 0x01f5a8, 0x01f5a8, 0x01f5b1, 0x01f5b2, 0x01f5bc, 0x01f5bc, 0x01f5c2, 0x01f5c4, 0x01f5d1, 0x01f5d3, 0x01f5dc, 0x01f5de, 0x01f5e1, 0x01f5e1, 0x01f5e3, 0x01f5e3, 0x01f5e8, 0x01f5e8, 0x01f5ef, 0x01f5ef, 0x01f5f3, 0x01f5f3, 0x01f5fa, 0x01f64f, 0x01f680, 0x01f6c5, 0x01f6cb, 0x01f6d2, 0x01f6d5, 0x01f6d7, - 0x01f6e0, 0x01f6e5, 0x01f6e9, 0x01f6e9, 0x01f6eb, 0x01f6ec, 0x01f6f0, 0x01f6f0, 0x01f6f3, 0x01f6fc, 0x01f7e0, 0x01f7eb, 0x01f90c, 0x01f93a, 0x01f93c, 0x01f945, 0x01f947, - 0x01f978, 0x01f97a, 0x01f9cb, 0x01f9cd, 0x01f9ff, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7a, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faa8, 0x01fab0, 0x01fab6, 0x01fac0, 0x01fac2, - 0x01fad0, 0x01fad6)); + 0x01f6dd, 0x01f6e5, 0x01f6e9, 0x01f6e9, 0x01f6eb, 0x01f6ec, 0x01f6f0, 0x01f6f0, 0x01f6f3, 0x01f6fc, 0x01f7e0, 0x01f7eb, 0x01f7f0, 0x01f7f0, 0x01f90c, 0x01f93a, 0x01f93c, + 0x01f945, 0x01f947, 0x01f9ff, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7c, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faac, 0x01fab0, 0x01faba, 0x01fac0, 0x01fac5, 0x01fad0, 0x01fad9, + 0x01fae0, 0x01fae7, 0x01faf0, 0x01faf6)); } private static void populateEXT() { - SET_ENCODINGS.put("Ext", CodePointSet.createNoDedup(0x0000b7, 0x0000b7, 0x0002d0, 0x0002d1, 0x000640, 0x000640, 0x0007fa, 0x0007fa, 0x000b55, 0x000b55, 0x000e46, 0x000e46, 0x000ec6, 0x000ec6, - 0x00180a, 0x00180a, 0x001843, 0x001843, 0x001aa7, 0x001aa7, 0x001c36, 0x001c36, 0x001c7b, 0x001c7b, 0x003005, 0x003005, 0x003031, 0x003035, 0x00309d, 0x00309e, 0x0030fc, - 0x0030fe, 0x00a015, 0x00a015, 0x00a60c, 0x00a60c, 0x00a9cf, 0x00a9cf, 0x00a9e6, 0x00a9e6, 0x00aa70, 0x00aa70, 0x00aadd, 0x00aadd, 0x00aaf3, 0x00aaf4, 0x00ff70, 0x00ff70, - 0x01135d, 0x01135d, 0x0115c6, 0x0115c8, 0x011a98, 0x011a98, 0x016b42, 0x016b43, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe3, 0x01e13c, 0x01e13d, 0x01e944, 0x01e946)); + SET_ENCODINGS.put("Ext", + CodePointSet.createNoDedup(0x0000b7, 0x0000b7, 0x0002d0, 0x0002d1, 0x000640, 0x000640, 0x0007fa, 0x0007fa, 0x000b55, 0x000b55, 0x000e46, 0x000e46, 0x000ec6, 0x000ec6, 0x00180a, + 0x00180a, 0x001843, 0x001843, 0x001aa7, 0x001aa7, 0x001c36, 0x001c36, 0x001c7b, 0x001c7b, 0x003005, 0x003005, 0x003031, 0x003035, 0x00309d, 0x00309e, 0x0030fc, + 0x0030fe, 0x00a015, 0x00a015, 0x00a60c, 0x00a60c, 0x00a9cf, 0x00a9cf, 0x00a9e6, 0x00a9e6, 0x00aa70, 0x00aa70, 0x00aadd, 0x00aadd, 0x00aaf3, 0x00aaf4, 0x00ff70, + 0x00ff70, 0x010781, 0x010782, 0x01135d, 0x01135d, 0x0115c6, 0x0115c8, 0x011a98, 0x011a98, 0x016b42, 0x016b43, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe3, 0x01e13c, + 0x01e13d, 0x01e944, 0x01e946)); } private static void populateEXTPICT() { @@ -1778,10 +1813,10 @@ private static void populateEXTPICT() { private static void populateGR_BASE() { SET_ENCODINGS.put("Gr_Base", CodePointSet.createNoDedup(0x000020, 0x00007e, 0x0000a0, 0x0000ac, 0x0000ae, 0x0002ff, 0x000370, 0x000377, 0x00037a, 0x00037f, 0x000384, 0x00038a, 0x00038c, 0x00038c, 0x00038e, 0x0003a1, 0x0003a3, 0x000482, 0x00048a, 0x00052f, 0x000531, 0x000556, 0x000559, 0x00058a, 0x00058d, 0x00058f, 0x0005be, 0x0005be, 0x0005c0, 0x0005c0, - 0x0005c3, 0x0005c3, 0x0005c6, 0x0005c6, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f4, 0x000606, 0x00060f, 0x00061b, 0x00061b, 0x00061e, 0x00064a, 0x000660, 0x00066f, 0x000671, + 0x0005c3, 0x0005c3, 0x0005c6, 0x0005c6, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f4, 0x000606, 0x00060f, 0x00061b, 0x00061b, 0x00061d, 0x00064a, 0x000660, 0x00066f, 0x000671, 0x0006d5, 0x0006de, 0x0006de, 0x0006e5, 0x0006e6, 0x0006e9, 0x0006e9, 0x0006ee, 0x00070d, 0x000710, 0x000710, 0x000712, 0x00072f, 0x00074d, 0x0007a5, 0x0007b1, 0x0007b1, 0x0007c0, 0x0007ea, 0x0007f4, 0x0007fa, 0x0007fe, 0x000815, 0x00081a, 0x00081a, 0x000824, 0x000824, 0x000828, 0x000828, 0x000830, 0x00083e, 0x000840, 0x000858, 0x00085e, - 0x00085e, 0x000860, 0x00086a, 0x0008a0, 0x0008b4, 0x0008b6, 0x0008c7, 0x000903, 0x000939, 0x00093b, 0x00093b, 0x00093d, 0x000940, 0x000949, 0x00094c, 0x00094e, 0x000950, + 0x00085e, 0x000860, 0x00086a, 0x000870, 0x00088e, 0x0008a0, 0x0008c9, 0x000903, 0x000939, 0x00093b, 0x00093b, 0x00093d, 0x000940, 0x000949, 0x00094c, 0x00094e, 0x000950, 0x000958, 0x000961, 0x000964, 0x000980, 0x000982, 0x000983, 0x000985, 0x00098c, 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009bd, 0x0009bf, 0x0009c0, 0x0009c7, 0x0009c8, 0x0009cb, 0x0009cc, 0x0009ce, 0x0009ce, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e1, 0x0009e6, 0x0009fd, 0x000a03, 0x000a03, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, 0x000a38, 0x000a39, 0x000a3e, @@ -1791,134 +1826,138 @@ private static void populateGR_BASE() { 0x000b35, 0x000b39, 0x000b3d, 0x000b3d, 0x000b40, 0x000b40, 0x000b47, 0x000b48, 0x000b4b, 0x000b4c, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b61, 0x000b66, 0x000b77, 0x000b83, 0x000b83, 0x000b85, 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bbf, 0x000bbf, 0x000bc1, 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcc, 0x000bd0, 0x000bd0, 0x000be6, 0x000bfa, 0x000c01, 0x000c03, 0x000c05, - 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c41, 0x000c44, 0x000c58, 0x000c5a, 0x000c60, 0x000c61, 0x000c66, 0x000c6f, - 0x000c77, 0x000c80, 0x000c82, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbe, 0x000cc0, 0x000cc1, 0x000cc3, - 0x000cc4, 0x000cc7, 0x000cc8, 0x000cca, 0x000ccb, 0x000cde, 0x000cde, 0x000ce0, 0x000ce1, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x000d02, 0x000d0c, 0x000d0e, 0x000d10, - 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d3f, 0x000d40, 0x000d46, 0x000d48, 0x000d4a, 0x000d4c, 0x000d4e, 0x000d4f, 0x000d54, 0x000d56, 0x000d58, 0x000d61, 0x000d66, - 0x000d7f, 0x000d82, 0x000d83, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000dd0, 0x000dd1, 0x000dd8, 0x000dde, - 0x000de6, 0x000def, 0x000df2, 0x000df4, 0x000e01, 0x000e30, 0x000e32, 0x000e33, 0x000e3f, 0x000e46, 0x000e4f, 0x000e5b, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, - 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb3, 0x000ebd, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000ed0, 0x000ed9, - 0x000edc, 0x000edf, 0x000f00, 0x000f17, 0x000f1a, 0x000f34, 0x000f36, 0x000f36, 0x000f38, 0x000f38, 0x000f3a, 0x000f47, 0x000f49, 0x000f6c, 0x000f7f, 0x000f7f, 0x000f85, - 0x000f85, 0x000f88, 0x000f8c, 0x000fbe, 0x000fc5, 0x000fc7, 0x000fcc, 0x000fce, 0x000fda, 0x001000, 0x00102c, 0x001031, 0x001031, 0x001038, 0x001038, 0x00103b, 0x00103c, - 0x00103f, 0x001057, 0x00105a, 0x00105d, 0x001061, 0x001070, 0x001075, 0x001081, 0x001083, 0x001084, 0x001087, 0x00108c, 0x00108e, 0x00109c, 0x00109e, 0x0010c5, 0x0010c7, - 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, - 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, - 0x00135a, 0x001360, 0x00137c, 0x001380, 0x001399, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001400, 0x00169c, 0x0016a0, 0x0016f8, 0x001700, 0x00170c, 0x00170e, 0x001711, - 0x001720, 0x001731, 0x001735, 0x001736, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001780, 0x0017b3, 0x0017b6, 0x0017b6, 0x0017be, 0x0017c5, 0x0017c7, - 0x0017c8, 0x0017d4, 0x0017dc, 0x0017e0, 0x0017e9, 0x0017f0, 0x0017f9, 0x001800, 0x00180a, 0x001810, 0x001819, 0x001820, 0x001878, 0x001880, 0x001884, 0x001887, 0x0018a8, - 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001923, 0x001926, 0x001929, 0x00192b, 0x001930, 0x001931, 0x001933, 0x001938, 0x001940, 0x001940, 0x001944, - 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x0019d0, 0x0019da, 0x0019de, 0x001a16, 0x001a19, 0x001a1a, 0x001a1e, 0x001a55, 0x001a57, 0x001a57, - 0x001a61, 0x001a61, 0x001a63, 0x001a64, 0x001a6d, 0x001a72, 0x001a80, 0x001a89, 0x001a90, 0x001a99, 0x001aa0, 0x001aad, 0x001b04, 0x001b33, 0x001b3b, 0x001b3b, 0x001b3d, - 0x001b41, 0x001b43, 0x001b4b, 0x001b50, 0x001b6a, 0x001b74, 0x001b7c, 0x001b82, 0x001ba1, 0x001ba6, 0x001ba7, 0x001baa, 0x001baa, 0x001bae, 0x001be5, 0x001be7, 0x001be7, - 0x001bea, 0x001bec, 0x001bee, 0x001bee, 0x001bf2, 0x001bf3, 0x001bfc, 0x001c2b, 0x001c34, 0x001c35, 0x001c3b, 0x001c49, 0x001c4d, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, - 0x001cc7, 0x001cd3, 0x001cd3, 0x001ce1, 0x001ce1, 0x001ce9, 0x001cec, 0x001cee, 0x001cf3, 0x001cf5, 0x001cf7, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, 0x001e00, 0x001f15, - 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, - 0x001fb4, 0x001fb6, 0x001fc4, 0x001fc6, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fdd, 0x001fef, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffe, 0x002000, 0x00200a, 0x002010, 0x002027, - 0x00202f, 0x00205f, 0x002070, 0x002071, 0x002074, 0x00208e, 0x002090, 0x00209c, 0x0020a0, 0x0020bf, 0x002100, 0x00218b, 0x002190, 0x002426, 0x002440, 0x00244a, 0x002460, - 0x002b73, 0x002b76, 0x002b95, 0x002b97, 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002cee, 0x002cf2, 0x002cf3, 0x002cf9, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, - 0x002d30, 0x002d67, 0x002d6f, 0x002d70, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, - 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x002e00, 0x002e52, 0x002e80, 0x002e99, 0x002e9b, 0x002ef3, 0x002f00, 0x002fd5, 0x002ff0, 0x002ffb, 0x003000, 0x003029, - 0x003030, 0x00303f, 0x003041, 0x003096, 0x00309b, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x003190, 0x0031e3, 0x0031f0, 0x00321e, 0x003220, 0x009ffc, 0x00a000, - 0x00a48c, 0x00a490, 0x00a4c6, 0x00a4d0, 0x00a62b, 0x00a640, 0x00a66e, 0x00a673, 0x00a673, 0x00a67e, 0x00a69d, 0x00a6a0, 0x00a6ef, 0x00a6f2, 0x00a6f7, 0x00a700, 0x00a7bf, - 0x00a7c2, 0x00a7ca, 0x00a7f5, 0x00a801, 0x00a803, 0x00a805, 0x00a807, 0x00a80a, 0x00a80c, 0x00a824, 0x00a827, 0x00a82b, 0x00a830, 0x00a839, 0x00a840, 0x00a877, 0x00a880, + 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c41, 0x000c44, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, 0x000c60, 0x000c61, + 0x000c66, 0x000c6f, 0x000c77, 0x000c80, 0x000c82, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbe, 0x000cc0, + 0x000cc1, 0x000cc3, 0x000cc4, 0x000cc7, 0x000cc8, 0x000cca, 0x000ccb, 0x000cdd, 0x000cde, 0x000ce0, 0x000ce1, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x000d02, 0x000d0c, + 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d3f, 0x000d40, 0x000d46, 0x000d48, 0x000d4a, 0x000d4c, 0x000d4e, 0x000d4f, 0x000d54, 0x000d56, 0x000d58, + 0x000d61, 0x000d66, 0x000d7f, 0x000d82, 0x000d83, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000dd0, 0x000dd1, + 0x000dd8, 0x000dde, 0x000de6, 0x000def, 0x000df2, 0x000df4, 0x000e01, 0x000e30, 0x000e32, 0x000e33, 0x000e3f, 0x000e46, 0x000e4f, 0x000e5b, 0x000e81, 0x000e82, 0x000e84, + 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb3, 0x000ebd, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, + 0x000ed0, 0x000ed9, 0x000edc, 0x000edf, 0x000f00, 0x000f17, 0x000f1a, 0x000f34, 0x000f36, 0x000f36, 0x000f38, 0x000f38, 0x000f3a, 0x000f47, 0x000f49, 0x000f6c, 0x000f7f, + 0x000f7f, 0x000f85, 0x000f85, 0x000f88, 0x000f8c, 0x000fbe, 0x000fc5, 0x000fc7, 0x000fcc, 0x000fce, 0x000fda, 0x001000, 0x00102c, 0x001031, 0x001031, 0x001038, 0x001038, + 0x00103b, 0x00103c, 0x00103f, 0x001057, 0x00105a, 0x00105d, 0x001061, 0x001070, 0x001075, 0x001081, 0x001083, 0x001084, 0x001087, 0x00108c, 0x00108e, 0x00109c, 0x00109e, + 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, + 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, + 0x001315, 0x001318, 0x00135a, 0x001360, 0x00137c, 0x001380, 0x001399, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001400, 0x00169c, 0x0016a0, 0x0016f8, 0x001700, 0x001711, + 0x001715, 0x001715, 0x00171f, 0x001731, 0x001734, 0x001736, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001780, 0x0017b3, 0x0017b6, 0x0017b6, 0x0017be, + 0x0017c5, 0x0017c7, 0x0017c8, 0x0017d4, 0x0017dc, 0x0017e0, 0x0017e9, 0x0017f0, 0x0017f9, 0x001800, 0x00180a, 0x001810, 0x001819, 0x001820, 0x001878, 0x001880, 0x001884, + 0x001887, 0x0018a8, 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001923, 0x001926, 0x001929, 0x00192b, 0x001930, 0x001931, 0x001933, 0x001938, 0x001940, + 0x001940, 0x001944, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x0019d0, 0x0019da, 0x0019de, 0x001a16, 0x001a19, 0x001a1a, 0x001a1e, 0x001a55, + 0x001a57, 0x001a57, 0x001a61, 0x001a61, 0x001a63, 0x001a64, 0x001a6d, 0x001a72, 0x001a80, 0x001a89, 0x001a90, 0x001a99, 0x001aa0, 0x001aad, 0x001b04, 0x001b33, 0x001b3b, + 0x001b3b, 0x001b3d, 0x001b41, 0x001b43, 0x001b4c, 0x001b50, 0x001b6a, 0x001b74, 0x001b7e, 0x001b82, 0x001ba1, 0x001ba6, 0x001ba7, 0x001baa, 0x001baa, 0x001bae, 0x001be5, + 0x001be7, 0x001be7, 0x001bea, 0x001bec, 0x001bee, 0x001bee, 0x001bf2, 0x001bf3, 0x001bfc, 0x001c2b, 0x001c34, 0x001c35, 0x001c3b, 0x001c49, 0x001c4d, 0x001c88, 0x001c90, + 0x001cba, 0x001cbd, 0x001cc7, 0x001cd3, 0x001cd3, 0x001ce1, 0x001ce1, 0x001ce9, 0x001cec, 0x001cee, 0x001cf3, 0x001cf5, 0x001cf7, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, + 0x001e00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, + 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fc4, 0x001fc6, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fdd, 0x001fef, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffe, 0x002000, 0x00200a, + 0x002010, 0x002027, 0x00202f, 0x00205f, 0x002070, 0x002071, 0x002074, 0x00208e, 0x002090, 0x00209c, 0x0020a0, 0x0020c0, 0x002100, 0x00218b, 0x002190, 0x002426, 0x002440, + 0x00244a, 0x002460, 0x002b73, 0x002b76, 0x002b95, 0x002b97, 0x002cee, 0x002cf2, 0x002cf3, 0x002cf9, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, + 0x002d6f, 0x002d70, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, + 0x002dd6, 0x002dd8, 0x002dde, 0x002e00, 0x002e5d, 0x002e80, 0x002e99, 0x002e9b, 0x002ef3, 0x002f00, 0x002fd5, 0x002ff0, 0x002ffb, 0x003000, 0x003029, 0x003030, 0x00303f, + 0x003041, 0x003096, 0x00309b, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x003190, 0x0031e3, 0x0031f0, 0x00321e, 0x003220, 0x00a48c, 0x00a490, 0x00a4c6, 0x00a4d0, + 0x00a62b, 0x00a640, 0x00a66e, 0x00a673, 0x00a673, 0x00a67e, 0x00a69d, 0x00a6a0, 0x00a6ef, 0x00a6f2, 0x00a6f7, 0x00a700, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, + 0x00a7d5, 0x00a7d9, 0x00a7f2, 0x00a801, 0x00a803, 0x00a805, 0x00a807, 0x00a80a, 0x00a80c, 0x00a824, 0x00a827, 0x00a82b, 0x00a830, 0x00a839, 0x00a840, 0x00a877, 0x00a880, 0x00a8c3, 0x00a8ce, 0x00a8d9, 0x00a8f2, 0x00a8fe, 0x00a900, 0x00a925, 0x00a92e, 0x00a946, 0x00a952, 0x00a953, 0x00a95f, 0x00a97c, 0x00a983, 0x00a9b2, 0x00a9b4, 0x00a9b5, 0x00a9ba, 0x00a9bb, 0x00a9be, 0x00a9cd, 0x00a9cf, 0x00a9d9, 0x00a9de, 0x00a9e4, 0x00a9e6, 0x00a9fe, 0x00aa00, 0x00aa28, 0x00aa2f, 0x00aa30, 0x00aa33, 0x00aa34, 0x00aa40, 0x00aa42, 0x00aa44, 0x00aa4b, 0x00aa4d, 0x00aa4d, 0x00aa50, 0x00aa59, 0x00aa5c, 0x00aa7b, 0x00aa7d, 0x00aaaf, 0x00aab1, 0x00aab1, 0x00aab5, 0x00aab6, 0x00aab9, 0x00aabd, 0x00aac0, 0x00aac0, 0x00aac2, 0x00aac2, 0x00aadb, 0x00aaeb, 0x00aaee, 0x00aaf5, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, 0x00ab2e, 0x00ab30, 0x00ab6b, 0x00ab70, 0x00abe4, 0x00abe6, 0x00abe7, 0x00abe9, 0x00abec, 0x00abf0, 0x00abf9, 0x00ac00, 0x00d7a3, 0x00d7b0, 0x00d7c6, 0x00d7cb, 0x00d7fb, 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb1d, 0x00fb1f, 0x00fb36, 0x00fb38, 0x00fb3c, 0x00fb3e, 0x00fb3e, 0x00fb40, - 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbc1, 0x00fbd3, 0x00fd3f, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdfd, 0x00fe10, 0x00fe19, 0x00fe30, 0x00fe52, + 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbc2, 0x00fbd3, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdcf, 0x00fdcf, 0x00fdf0, 0x00fdff, 0x00fe10, 0x00fe19, 0x00fe30, 0x00fe52, 0x00fe54, 0x00fe66, 0x00fe68, 0x00fe6b, 0x00fe70, 0x00fe74, 0x00fe76, 0x00fefc, 0x00ff01, 0x00ff9d, 0x00ffa0, 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, 0x00fffc, 0x00fffd, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, 0x01003c, 0x01003d, 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010100, 0x010102, 0x010107, 0x010133, 0x010137, 0x01018e, 0x010190, 0x01019c, 0x0101a0, 0x0101a0, 0x0101d0, 0x0101fc, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x0102e1, 0x0102fb, 0x010300, 0x010323, 0x01032d, 0x01034a, 0x010350, 0x010375, 0x010380, 0x01039d, 0x01039f, 0x0103c3, - 0x0103c8, 0x0103d5, 0x010400, 0x01049d, 0x0104a0, 0x0104a9, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x01056f, 0x01056f, 0x010600, - 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, - 0x010857, 0x01089e, 0x0108a7, 0x0108af, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x0108fb, 0x01091b, 0x01091f, 0x010939, 0x01093f, 0x01093f, 0x010980, 0x0109b7, 0x0109bc, - 0x0109cf, 0x0109d2, 0x010a00, 0x010a10, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a40, 0x010a48, 0x010a50, 0x010a58, 0x010a60, 0x010a9f, 0x010ac0, 0x010ae4, - 0x010aeb, 0x010af6, 0x010b00, 0x010b35, 0x010b39, 0x010b55, 0x010b58, 0x010b72, 0x010b78, 0x010b91, 0x010b99, 0x010b9c, 0x010ba9, 0x010baf, 0x010c00, 0x010c48, 0x010c80, - 0x010cb2, 0x010cc0, 0x010cf2, 0x010cfa, 0x010d23, 0x010d30, 0x010d39, 0x010e60, 0x010e7e, 0x010e80, 0x010ea9, 0x010ead, 0x010ead, 0x010eb0, 0x010eb1, 0x010f00, 0x010f27, - 0x010f30, 0x010f45, 0x010f51, 0x010f59, 0x010fb0, 0x010fcb, 0x010fe0, 0x010ff6, 0x011000, 0x011000, 0x011002, 0x011037, 0x011047, 0x01104d, 0x011052, 0x01106f, 0x011082, - 0x0110b2, 0x0110b7, 0x0110b8, 0x0110bb, 0x0110bc, 0x0110be, 0x0110c1, 0x0110d0, 0x0110e8, 0x0110f0, 0x0110f9, 0x011103, 0x011126, 0x01112c, 0x01112c, 0x011136, 0x011147, - 0x011150, 0x011172, 0x011174, 0x011176, 0x011182, 0x0111b5, 0x0111bf, 0x0111c8, 0x0111cd, 0x0111ce, 0x0111d0, 0x0111df, 0x0111e1, 0x0111f4, 0x011200, 0x011211, 0x011213, - 0x01122e, 0x011232, 0x011233, 0x011235, 0x011235, 0x011238, 0x01123d, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a9, - 0x0112b0, 0x0112de, 0x0112e0, 0x0112e2, 0x0112f0, 0x0112f9, 0x011302, 0x011303, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, - 0x011333, 0x011335, 0x011339, 0x01133d, 0x01133d, 0x01133f, 0x01133f, 0x011341, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, 0x011350, 0x011350, 0x01135d, 0x011363, - 0x011400, 0x011437, 0x011440, 0x011441, 0x011445, 0x011445, 0x011447, 0x01145b, 0x01145d, 0x01145d, 0x01145f, 0x011461, 0x011480, 0x0114af, 0x0114b1, 0x0114b2, 0x0114b9, - 0x0114b9, 0x0114bb, 0x0114bc, 0x0114be, 0x0114be, 0x0114c1, 0x0114c1, 0x0114c4, 0x0114c7, 0x0114d0, 0x0114d9, 0x011580, 0x0115ae, 0x0115b0, 0x0115b1, 0x0115b8, 0x0115bb, - 0x0115be, 0x0115be, 0x0115c1, 0x0115db, 0x011600, 0x011632, 0x01163b, 0x01163c, 0x01163e, 0x01163e, 0x011641, 0x011644, 0x011650, 0x011659, 0x011660, 0x01166c, 0x011680, - 0x0116aa, 0x0116ac, 0x0116ac, 0x0116ae, 0x0116af, 0x0116b6, 0x0116b6, 0x0116b8, 0x0116b8, 0x0116c0, 0x0116c9, 0x011700, 0x01171a, 0x011720, 0x011721, 0x011726, 0x011726, - 0x011730, 0x01173f, 0x011800, 0x01182e, 0x011838, 0x011838, 0x01183b, 0x01183b, 0x0118a0, 0x0118f2, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, - 0x011916, 0x011918, 0x01192f, 0x011931, 0x011935, 0x011937, 0x011938, 0x01193d, 0x01193d, 0x01193f, 0x011942, 0x011944, 0x011946, 0x011950, 0x011959, 0x0119a0, 0x0119a7, - 0x0119aa, 0x0119d3, 0x0119dc, 0x0119df, 0x0119e1, 0x0119e4, 0x011a00, 0x011a00, 0x011a0b, 0x011a32, 0x011a39, 0x011a3a, 0x011a3f, 0x011a46, 0x011a50, 0x011a50, 0x011a57, - 0x011a58, 0x011a5c, 0x011a89, 0x011a97, 0x011a97, 0x011a9a, 0x011aa2, 0x011ac0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c2f, 0x011c3e, 0x011c3e, 0x011c40, 0x011c45, - 0x011c50, 0x011c6c, 0x011c70, 0x011c8f, 0x011ca9, 0x011ca9, 0x011cb1, 0x011cb1, 0x011cb4, 0x011cb4, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d30, 0x011d46, - 0x011d46, 0x011d50, 0x011d59, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d8e, 0x011d93, 0x011d94, 0x011d96, 0x011d96, 0x011d98, 0x011d98, 0x011da0, 0x011da9, - 0x011ee0, 0x011ef2, 0x011ef5, 0x011ef8, 0x011fb0, 0x011fb0, 0x011fc0, 0x011ff1, 0x011fff, 0x012399, 0x012400, 0x01246e, 0x012470, 0x012474, 0x012480, 0x012543, 0x013000, - 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016a60, 0x016a69, 0x016a6e, 0x016a6f, 0x016ad0, 0x016aed, 0x016af5, 0x016af5, 0x016b00, 0x016b2f, - 0x016b37, 0x016b45, 0x016b50, 0x016b59, 0x016b5b, 0x016b61, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e9a, 0x016f00, 0x016f4a, 0x016f50, 0x016f87, 0x016f93, - 0x016f9f, 0x016fe0, 0x016fe3, 0x016ff0, 0x016ff1, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b11e, 0x01b150, 0x01b152, 0x01b164, 0x01b167, - 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01bc9c, 0x01bc9c, 0x01bc9f, 0x01bc9f, 0x01d000, 0x01d0f5, 0x01d100, - 0x01d126, 0x01d129, 0x01d164, 0x01d166, 0x01d166, 0x01d16a, 0x01d16d, 0x01d183, 0x01d184, 0x01d18c, 0x01d1a9, 0x01d1ae, 0x01d1e8, 0x01d200, 0x01d241, 0x01d245, 0x01d245, - 0x01d2e0, 0x01d2f3, 0x01d300, 0x01d356, 0x01d360, 0x01d378, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, - 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, - 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d7cb, 0x01d7ce, 0x01d9ff, 0x01da37, 0x01da3a, 0x01da6d, - 0x01da74, 0x01da76, 0x01da83, 0x01da85, 0x01da8b, 0x01e100, 0x01e12c, 0x01e137, 0x01e13d, 0x01e140, 0x01e149, 0x01e14e, 0x01e14f, 0x01e2c0, 0x01e2eb, 0x01e2f0, 0x01e2f9, - 0x01e2ff, 0x01e2ff, 0x01e800, 0x01e8c4, 0x01e8c7, 0x01e8cf, 0x01e900, 0x01e943, 0x01e94b, 0x01e94b, 0x01e950, 0x01e959, 0x01e95e, 0x01e95f, 0x01ec71, 0x01ecb4, 0x01ed01, - 0x01ed3d, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, - 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, - 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, - 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x01eef0, - 0x01eef1, 0x01f000, 0x01f02b, 0x01f030, 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, 0x01f100, 0x01f1ad, 0x01f1e6, 0x01f202, - 0x01f210, 0x01f23b, 0x01f240, 0x01f248, 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6e0, 0x01f6ec, 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, - 0x01f7d8, 0x01f7e0, 0x01f7eb, 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01f978, - 0x01f97a, 0x01f9cb, 0x01f9cd, 0x01fa53, 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7a, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faa8, 0x01fab0, 0x01fab6, 0x01fac0, - 0x01fac2, 0x01fad0, 0x01fad6, 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca, 0x01fbf0, 0x01fbf9, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, - 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); + 0x0103c8, 0x0103d5, 0x010400, 0x01049d, 0x0104a0, 0x0104a9, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x01056f, 0x01057a, 0x01057c, + 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010600, 0x010736, 0x010740, 0x010755, + 0x010760, 0x010767, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, + 0x01083c, 0x01083f, 0x010855, 0x010857, 0x01089e, 0x0108a7, 0x0108af, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x0108fb, 0x01091b, 0x01091f, 0x010939, 0x01093f, 0x01093f, + 0x010980, 0x0109b7, 0x0109bc, 0x0109cf, 0x0109d2, 0x010a00, 0x010a10, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a40, 0x010a48, 0x010a50, 0x010a58, 0x010a60, + 0x010a9f, 0x010ac0, 0x010ae4, 0x010aeb, 0x010af6, 0x010b00, 0x010b35, 0x010b39, 0x010b55, 0x010b58, 0x010b72, 0x010b78, 0x010b91, 0x010b99, 0x010b9c, 0x010ba9, 0x010baf, + 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010cfa, 0x010d23, 0x010d30, 0x010d39, 0x010e60, 0x010e7e, 0x010e80, 0x010ea9, 0x010ead, 0x010ead, 0x010eb0, + 0x010eb1, 0x010f00, 0x010f27, 0x010f30, 0x010f45, 0x010f51, 0x010f59, 0x010f70, 0x010f81, 0x010f86, 0x010f89, 0x010fb0, 0x010fcb, 0x010fe0, 0x010ff6, 0x011000, 0x011000, + 0x011002, 0x011037, 0x011047, 0x01104d, 0x011052, 0x01106f, 0x011071, 0x011072, 0x011075, 0x011075, 0x011082, 0x0110b2, 0x0110b7, 0x0110b8, 0x0110bb, 0x0110bc, 0x0110be, + 0x0110c1, 0x0110d0, 0x0110e8, 0x0110f0, 0x0110f9, 0x011103, 0x011126, 0x01112c, 0x01112c, 0x011136, 0x011147, 0x011150, 0x011172, 0x011174, 0x011176, 0x011182, 0x0111b5, + 0x0111bf, 0x0111c8, 0x0111cd, 0x0111ce, 0x0111d0, 0x0111df, 0x0111e1, 0x0111f4, 0x011200, 0x011211, 0x011213, 0x01122e, 0x011232, 0x011233, 0x011235, 0x011235, 0x011238, + 0x01123d, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a9, 0x0112b0, 0x0112de, 0x0112e0, 0x0112e2, 0x0112f0, 0x0112f9, + 0x011302, 0x011303, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133d, 0x01133d, 0x01133f, + 0x01133f, 0x011341, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, 0x011350, 0x011350, 0x01135d, 0x011363, 0x011400, 0x011437, 0x011440, 0x011441, 0x011445, 0x011445, + 0x011447, 0x01145b, 0x01145d, 0x01145d, 0x01145f, 0x011461, 0x011480, 0x0114af, 0x0114b1, 0x0114b2, 0x0114b9, 0x0114b9, 0x0114bb, 0x0114bc, 0x0114be, 0x0114be, 0x0114c1, + 0x0114c1, 0x0114c4, 0x0114c7, 0x0114d0, 0x0114d9, 0x011580, 0x0115ae, 0x0115b0, 0x0115b1, 0x0115b8, 0x0115bb, 0x0115be, 0x0115be, 0x0115c1, 0x0115db, 0x011600, 0x011632, + 0x01163b, 0x01163c, 0x01163e, 0x01163e, 0x011641, 0x011644, 0x011650, 0x011659, 0x011660, 0x01166c, 0x011680, 0x0116aa, 0x0116ac, 0x0116ac, 0x0116ae, 0x0116af, 0x0116b6, + 0x0116b6, 0x0116b8, 0x0116b9, 0x0116c0, 0x0116c9, 0x011700, 0x01171a, 0x011720, 0x011721, 0x011726, 0x011726, 0x011730, 0x011746, 0x011800, 0x01182e, 0x011838, 0x011838, + 0x01183b, 0x01183b, 0x0118a0, 0x0118f2, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x01192f, 0x011931, 0x011935, 0x011937, + 0x011938, 0x01193d, 0x01193d, 0x01193f, 0x011942, 0x011944, 0x011946, 0x011950, 0x011959, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d3, 0x0119dc, 0x0119df, 0x0119e1, 0x0119e4, + 0x011a00, 0x011a00, 0x011a0b, 0x011a32, 0x011a39, 0x011a3a, 0x011a3f, 0x011a46, 0x011a50, 0x011a50, 0x011a57, 0x011a58, 0x011a5c, 0x011a89, 0x011a97, 0x011a97, 0x011a9a, + 0x011aa2, 0x011ab0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c2f, 0x011c3e, 0x011c3e, 0x011c40, 0x011c45, 0x011c50, 0x011c6c, 0x011c70, 0x011c8f, 0x011ca9, 0x011ca9, + 0x011cb1, 0x011cb1, 0x011cb4, 0x011cb4, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d30, 0x011d46, 0x011d46, 0x011d50, 0x011d59, 0x011d60, 0x011d65, 0x011d67, + 0x011d68, 0x011d6a, 0x011d8e, 0x011d93, 0x011d94, 0x011d96, 0x011d96, 0x011d98, 0x011d98, 0x011da0, 0x011da9, 0x011ee0, 0x011ef2, 0x011ef5, 0x011ef8, 0x011fb0, 0x011fb0, + 0x011fc0, 0x011ff1, 0x011fff, 0x012399, 0x012400, 0x01246e, 0x012470, 0x012474, 0x012480, 0x012543, 0x012f90, 0x012ff2, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, + 0x016a38, 0x016a40, 0x016a5e, 0x016a60, 0x016a69, 0x016a6e, 0x016abe, 0x016ac0, 0x016ac9, 0x016ad0, 0x016aed, 0x016af5, 0x016af5, 0x016b00, 0x016b2f, 0x016b37, 0x016b45, + 0x016b50, 0x016b59, 0x016b5b, 0x016b61, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e9a, 0x016f00, 0x016f4a, 0x016f50, 0x016f87, 0x016f93, 0x016f9f, 0x016fe0, + 0x016fe3, 0x016ff0, 0x016ff1, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01b000, 0x01b122, + 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01bc9c, 0x01bc9c, 0x01bc9f, + 0x01bc9f, 0x01cf50, 0x01cfc3, 0x01d000, 0x01d0f5, 0x01d100, 0x01d126, 0x01d129, 0x01d164, 0x01d166, 0x01d166, 0x01d16a, 0x01d16d, 0x01d183, 0x01d184, 0x01d18c, 0x01d1a9, + 0x01d1ae, 0x01d1ea, 0x01d200, 0x01d241, 0x01d245, 0x01d245, 0x01d2e0, 0x01d2f3, 0x01d300, 0x01d356, 0x01d360, 0x01d378, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, + 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, + 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, + 0x01d7cb, 0x01d7ce, 0x01d9ff, 0x01da37, 0x01da3a, 0x01da6d, 0x01da74, 0x01da76, 0x01da83, 0x01da85, 0x01da8b, 0x01df00, 0x01df1e, 0x01e100, 0x01e12c, 0x01e137, 0x01e13d, + 0x01e140, 0x01e149, 0x01e14e, 0x01e14f, 0x01e290, 0x01e2ad, 0x01e2c0, 0x01e2eb, 0x01e2f0, 0x01e2f9, 0x01e2ff, 0x01e2ff, 0x01e7e0, 0x01e7e6, 0x01e7e8, 0x01e7eb, 0x01e7ed, + 0x01e7ee, 0x01e7f0, 0x01e7fe, 0x01e800, 0x01e8c4, 0x01e8c7, 0x01e8cf, 0x01e900, 0x01e943, 0x01e94b, 0x01e94b, 0x01e950, 0x01e959, 0x01e95e, 0x01e95f, 0x01ec71, 0x01ecb4, + 0x01ed01, 0x01ed3d, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, + 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, + 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, + 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, + 0x01eef0, 0x01eef1, 0x01f000, 0x01f02b, 0x01f030, 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, 0x01f100, 0x01f1ad, 0x01f1e6, + 0x01f202, 0x01f210, 0x01f23b, 0x01f240, 0x01f248, 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6dd, 0x01f6ec, 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, + 0x01f780, 0x01f7d8, 0x01f7e0, 0x01f7eb, 0x01f7f0, 0x01f7f0, 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, + 0x01f8b1, 0x01f900, 0x01fa53, 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7c, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faac, 0x01fab0, 0x01faba, 0x01fac0, 0x01fac5, + 0x01fad0, 0x01fad9, 0x01fae0, 0x01fae7, 0x01faf0, 0x01faf6, 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca, 0x01fbf0, 0x01fbf9, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, + 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); } private static void populateGR_EXT() { SET_ENCODINGS.put("Gr_Ext", CodePointSet.createNoDedup(0x000300, 0x00036f, 0x000483, 0x000489, 0x000591, 0x0005bd, 0x0005bf, 0x0005bf, 0x0005c1, 0x0005c2, 0x0005c4, 0x0005c5, 0x0005c7, 0x0005c7, 0x000610, 0x00061a, 0x00064b, 0x00065f, 0x000670, 0x000670, 0x0006d6, 0x0006dc, 0x0006df, 0x0006e4, 0x0006e7, 0x0006e8, 0x0006ea, 0x0006ed, 0x000711, 0x000711, 0x000730, 0x00074a, 0x0007a6, 0x0007b0, 0x0007eb, 0x0007f3, 0x0007fd, 0x0007fd, 0x000816, 0x000819, 0x00081b, 0x000823, 0x000825, 0x000827, 0x000829, 0x00082d, 0x000859, - 0x00085b, 0x0008d3, 0x0008e1, 0x0008e3, 0x000902, 0x00093a, 0x00093a, 0x00093c, 0x00093c, 0x000941, 0x000948, 0x00094d, 0x00094d, 0x000951, 0x000957, 0x000962, 0x000963, - 0x000981, 0x000981, 0x0009bc, 0x0009bc, 0x0009be, 0x0009be, 0x0009c1, 0x0009c4, 0x0009cd, 0x0009cd, 0x0009d7, 0x0009d7, 0x0009e2, 0x0009e3, 0x0009fe, 0x0009fe, 0x000a01, - 0x000a02, 0x000a3c, 0x000a3c, 0x000a41, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4d, 0x000a51, 0x000a51, 0x000a70, 0x000a71, 0x000a75, 0x000a75, 0x000a81, 0x000a82, - 0x000abc, 0x000abc, 0x000ac1, 0x000ac5, 0x000ac7, 0x000ac8, 0x000acd, 0x000acd, 0x000ae2, 0x000ae3, 0x000afa, 0x000aff, 0x000b01, 0x000b01, 0x000b3c, 0x000b3c, 0x000b3e, - 0x000b3f, 0x000b41, 0x000b44, 0x000b4d, 0x000b4d, 0x000b55, 0x000b57, 0x000b62, 0x000b63, 0x000b82, 0x000b82, 0x000bbe, 0x000bbe, 0x000bc0, 0x000bc0, 0x000bcd, 0x000bcd, - 0x000bd7, 0x000bd7, 0x000c00, 0x000c00, 0x000c04, 0x000c04, 0x000c3e, 0x000c40, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c62, 0x000c63, 0x000c81, - 0x000c81, 0x000cbc, 0x000cbc, 0x000cbf, 0x000cbf, 0x000cc2, 0x000cc2, 0x000cc6, 0x000cc6, 0x000ccc, 0x000ccd, 0x000cd5, 0x000cd6, 0x000ce2, 0x000ce3, 0x000d00, 0x000d01, - 0x000d3b, 0x000d3c, 0x000d3e, 0x000d3e, 0x000d41, 0x000d44, 0x000d4d, 0x000d4d, 0x000d57, 0x000d57, 0x000d62, 0x000d63, 0x000d81, 0x000d81, 0x000dca, 0x000dca, 0x000dcf, - 0x000dcf, 0x000dd2, 0x000dd4, 0x000dd6, 0x000dd6, 0x000ddf, 0x000ddf, 0x000e31, 0x000e31, 0x000e34, 0x000e3a, 0x000e47, 0x000e4e, 0x000eb1, 0x000eb1, 0x000eb4, 0x000ebc, - 0x000ec8, 0x000ecd, 0x000f18, 0x000f19, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f71, 0x000f7e, 0x000f80, 0x000f84, 0x000f86, 0x000f87, 0x000f8d, - 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x00102d, 0x001030, 0x001032, 0x001037, 0x001039, 0x00103a, 0x00103d, 0x00103e, 0x001058, 0x001059, 0x00105e, 0x001060, - 0x001071, 0x001074, 0x001082, 0x001082, 0x001085, 0x001086, 0x00108d, 0x00108d, 0x00109d, 0x00109d, 0x00135d, 0x00135f, 0x001712, 0x001714, 0x001732, 0x001734, 0x001752, - 0x001753, 0x001772, 0x001773, 0x0017b4, 0x0017b5, 0x0017b7, 0x0017bd, 0x0017c6, 0x0017c6, 0x0017c9, 0x0017d3, 0x0017dd, 0x0017dd, 0x00180b, 0x00180d, 0x001885, 0x001886, - 0x0018a9, 0x0018a9, 0x001920, 0x001922, 0x001927, 0x001928, 0x001932, 0x001932, 0x001939, 0x00193b, 0x001a17, 0x001a18, 0x001a1b, 0x001a1b, 0x001a56, 0x001a56, 0x001a58, - 0x001a5e, 0x001a60, 0x001a60, 0x001a62, 0x001a62, 0x001a65, 0x001a6c, 0x001a73, 0x001a7c, 0x001a7f, 0x001a7f, 0x001ab0, 0x001ac0, 0x001b00, 0x001b03, 0x001b34, 0x001b3a, - 0x001b3c, 0x001b3c, 0x001b42, 0x001b42, 0x001b6b, 0x001b73, 0x001b80, 0x001b81, 0x001ba2, 0x001ba5, 0x001ba8, 0x001ba9, 0x001bab, 0x001bad, 0x001be6, 0x001be6, 0x001be8, - 0x001be9, 0x001bed, 0x001bed, 0x001bef, 0x001bf1, 0x001c2c, 0x001c33, 0x001c36, 0x001c37, 0x001cd0, 0x001cd2, 0x001cd4, 0x001ce0, 0x001ce2, 0x001ce8, 0x001ced, 0x001ced, - 0x001cf4, 0x001cf4, 0x001cf8, 0x001cf9, 0x001dc0, 0x001df9, 0x001dfb, 0x001dff, 0x00200c, 0x00200c, 0x0020d0, 0x0020f0, 0x002cef, 0x002cf1, 0x002d7f, 0x002d7f, 0x002de0, - 0x002dff, 0x00302a, 0x00302f, 0x003099, 0x00309a, 0x00a66f, 0x00a672, 0x00a674, 0x00a67d, 0x00a69e, 0x00a69f, 0x00a6f0, 0x00a6f1, 0x00a802, 0x00a802, 0x00a806, 0x00a806, - 0x00a80b, 0x00a80b, 0x00a825, 0x00a826, 0x00a82c, 0x00a82c, 0x00a8c4, 0x00a8c5, 0x00a8e0, 0x00a8f1, 0x00a8ff, 0x00a8ff, 0x00a926, 0x00a92d, 0x00a947, 0x00a951, 0x00a980, - 0x00a982, 0x00a9b3, 0x00a9b3, 0x00a9b6, 0x00a9b9, 0x00a9bc, 0x00a9bd, 0x00a9e5, 0x00a9e5, 0x00aa29, 0x00aa2e, 0x00aa31, 0x00aa32, 0x00aa35, 0x00aa36, 0x00aa43, 0x00aa43, - 0x00aa4c, 0x00aa4c, 0x00aa7c, 0x00aa7c, 0x00aab0, 0x00aab0, 0x00aab2, 0x00aab4, 0x00aab7, 0x00aab8, 0x00aabe, 0x00aabf, 0x00aac1, 0x00aac1, 0x00aaec, 0x00aaed, 0x00aaf6, - 0x00aaf6, 0x00abe5, 0x00abe5, 0x00abe8, 0x00abe8, 0x00abed, 0x00abed, 0x00fb1e, 0x00fb1e, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2f, 0x00ff9e, 0x00ff9f, 0x0101fd, 0x0101fd, - 0x0102e0, 0x0102e0, 0x010376, 0x01037a, 0x010a01, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a0f, 0x010a38, 0x010a3a, 0x010a3f, 0x010a3f, 0x010ae5, 0x010ae6, 0x010d24, - 0x010d27, 0x010eab, 0x010eac, 0x010f46, 0x010f50, 0x011001, 0x011001, 0x011038, 0x011046, 0x01107f, 0x011081, 0x0110b3, 0x0110b6, 0x0110b9, 0x0110ba, 0x011100, 0x011102, - 0x011127, 0x01112b, 0x01112d, 0x011134, 0x011173, 0x011173, 0x011180, 0x011181, 0x0111b6, 0x0111be, 0x0111c9, 0x0111cc, 0x0111cf, 0x0111cf, 0x01122f, 0x011231, 0x011234, - 0x011234, 0x011236, 0x011237, 0x01123e, 0x01123e, 0x0112df, 0x0112df, 0x0112e3, 0x0112ea, 0x011300, 0x011301, 0x01133b, 0x01133c, 0x01133e, 0x01133e, 0x011340, 0x011340, - 0x011357, 0x011357, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011438, 0x01143f, 0x011442, 0x011444, 0x011446, 0x011446, 0x01145e, 0x01145e, 0x0114b0, 0x0114b0, 0x0114b3, - 0x0114b8, 0x0114ba, 0x0114ba, 0x0114bd, 0x0114bd, 0x0114bf, 0x0114c0, 0x0114c2, 0x0114c3, 0x0115af, 0x0115af, 0x0115b2, 0x0115b5, 0x0115bc, 0x0115bd, 0x0115bf, 0x0115c0, - 0x0115dc, 0x0115dd, 0x011633, 0x01163a, 0x01163d, 0x01163d, 0x01163f, 0x011640, 0x0116ab, 0x0116ab, 0x0116ad, 0x0116ad, 0x0116b0, 0x0116b5, 0x0116b7, 0x0116b7, 0x01171d, - 0x01171f, 0x011722, 0x011725, 0x011727, 0x01172b, 0x01182f, 0x011837, 0x011839, 0x01183a, 0x011930, 0x011930, 0x01193b, 0x01193c, 0x01193e, 0x01193e, 0x011943, 0x011943, - 0x0119d4, 0x0119d7, 0x0119da, 0x0119db, 0x0119e0, 0x0119e0, 0x011a01, 0x011a0a, 0x011a33, 0x011a38, 0x011a3b, 0x011a3e, 0x011a47, 0x011a47, 0x011a51, 0x011a56, 0x011a59, - 0x011a5b, 0x011a8a, 0x011a96, 0x011a98, 0x011a99, 0x011c30, 0x011c36, 0x011c38, 0x011c3d, 0x011c3f, 0x011c3f, 0x011c92, 0x011ca7, 0x011caa, 0x011cb0, 0x011cb2, 0x011cb3, - 0x011cb5, 0x011cb6, 0x011d31, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d45, 0x011d47, 0x011d47, 0x011d90, 0x011d91, 0x011d95, 0x011d95, 0x011d97, - 0x011d97, 0x011ef3, 0x011ef4, 0x016af0, 0x016af4, 0x016b30, 0x016b36, 0x016f4f, 0x016f4f, 0x016f8f, 0x016f92, 0x016fe4, 0x016fe4, 0x01bc9d, 0x01bc9e, 0x01d165, 0x01d165, - 0x01d167, 0x01d169, 0x01d16e, 0x01d172, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, 0x01d244, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, 0x01da75, - 0x01da75, 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, - 0x01e130, 0x01e136, 0x01e2ec, 0x01e2ef, 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e94a, 0x0e0020, 0x0e007f, 0x0e0100, 0x0e01ef)); + 0x00085b, 0x000898, 0x00089f, 0x0008ca, 0x0008e1, 0x0008e3, 0x000902, 0x00093a, 0x00093a, 0x00093c, 0x00093c, 0x000941, 0x000948, 0x00094d, 0x00094d, 0x000951, 0x000957, + 0x000962, 0x000963, 0x000981, 0x000981, 0x0009bc, 0x0009bc, 0x0009be, 0x0009be, 0x0009c1, 0x0009c4, 0x0009cd, 0x0009cd, 0x0009d7, 0x0009d7, 0x0009e2, 0x0009e3, 0x0009fe, + 0x0009fe, 0x000a01, 0x000a02, 0x000a3c, 0x000a3c, 0x000a41, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4d, 0x000a51, 0x000a51, 0x000a70, 0x000a71, 0x000a75, 0x000a75, + 0x000a81, 0x000a82, 0x000abc, 0x000abc, 0x000ac1, 0x000ac5, 0x000ac7, 0x000ac8, 0x000acd, 0x000acd, 0x000ae2, 0x000ae3, 0x000afa, 0x000aff, 0x000b01, 0x000b01, 0x000b3c, + 0x000b3c, 0x000b3e, 0x000b3f, 0x000b41, 0x000b44, 0x000b4d, 0x000b4d, 0x000b55, 0x000b57, 0x000b62, 0x000b63, 0x000b82, 0x000b82, 0x000bbe, 0x000bbe, 0x000bc0, 0x000bc0, + 0x000bcd, 0x000bcd, 0x000bd7, 0x000bd7, 0x000c00, 0x000c00, 0x000c04, 0x000c04, 0x000c3c, 0x000c3c, 0x000c3e, 0x000c40, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, + 0x000c56, 0x000c62, 0x000c63, 0x000c81, 0x000c81, 0x000cbc, 0x000cbc, 0x000cbf, 0x000cbf, 0x000cc2, 0x000cc2, 0x000cc6, 0x000cc6, 0x000ccc, 0x000ccd, 0x000cd5, 0x000cd6, + 0x000ce2, 0x000ce3, 0x000d00, 0x000d01, 0x000d3b, 0x000d3c, 0x000d3e, 0x000d3e, 0x000d41, 0x000d44, 0x000d4d, 0x000d4d, 0x000d57, 0x000d57, 0x000d62, 0x000d63, 0x000d81, + 0x000d81, 0x000dca, 0x000dca, 0x000dcf, 0x000dcf, 0x000dd2, 0x000dd4, 0x000dd6, 0x000dd6, 0x000ddf, 0x000ddf, 0x000e31, 0x000e31, 0x000e34, 0x000e3a, 0x000e47, 0x000e4e, + 0x000eb1, 0x000eb1, 0x000eb4, 0x000ebc, 0x000ec8, 0x000ecd, 0x000f18, 0x000f19, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f71, 0x000f7e, 0x000f80, + 0x000f84, 0x000f86, 0x000f87, 0x000f8d, 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x00102d, 0x001030, 0x001032, 0x001037, 0x001039, 0x00103a, 0x00103d, 0x00103e, + 0x001058, 0x001059, 0x00105e, 0x001060, 0x001071, 0x001074, 0x001082, 0x001082, 0x001085, 0x001086, 0x00108d, 0x00108d, 0x00109d, 0x00109d, 0x00135d, 0x00135f, 0x001712, + 0x001714, 0x001732, 0x001733, 0x001752, 0x001753, 0x001772, 0x001773, 0x0017b4, 0x0017b5, 0x0017b7, 0x0017bd, 0x0017c6, 0x0017c6, 0x0017c9, 0x0017d3, 0x0017dd, 0x0017dd, + 0x00180b, 0x00180d, 0x00180f, 0x00180f, 0x001885, 0x001886, 0x0018a9, 0x0018a9, 0x001920, 0x001922, 0x001927, 0x001928, 0x001932, 0x001932, 0x001939, 0x00193b, 0x001a17, + 0x001a18, 0x001a1b, 0x001a1b, 0x001a56, 0x001a56, 0x001a58, 0x001a5e, 0x001a60, 0x001a60, 0x001a62, 0x001a62, 0x001a65, 0x001a6c, 0x001a73, 0x001a7c, 0x001a7f, 0x001a7f, + 0x001ab0, 0x001ace, 0x001b00, 0x001b03, 0x001b34, 0x001b3a, 0x001b3c, 0x001b3c, 0x001b42, 0x001b42, 0x001b6b, 0x001b73, 0x001b80, 0x001b81, 0x001ba2, 0x001ba5, 0x001ba8, + 0x001ba9, 0x001bab, 0x001bad, 0x001be6, 0x001be6, 0x001be8, 0x001be9, 0x001bed, 0x001bed, 0x001bef, 0x001bf1, 0x001c2c, 0x001c33, 0x001c36, 0x001c37, 0x001cd0, 0x001cd2, + 0x001cd4, 0x001ce0, 0x001ce2, 0x001ce8, 0x001ced, 0x001ced, 0x001cf4, 0x001cf4, 0x001cf8, 0x001cf9, 0x001dc0, 0x001dff, 0x00200c, 0x00200c, 0x0020d0, 0x0020f0, 0x002cef, + 0x002cf1, 0x002d7f, 0x002d7f, 0x002de0, 0x002dff, 0x00302a, 0x00302f, 0x003099, 0x00309a, 0x00a66f, 0x00a672, 0x00a674, 0x00a67d, 0x00a69e, 0x00a69f, 0x00a6f0, 0x00a6f1, + 0x00a802, 0x00a802, 0x00a806, 0x00a806, 0x00a80b, 0x00a80b, 0x00a825, 0x00a826, 0x00a82c, 0x00a82c, 0x00a8c4, 0x00a8c5, 0x00a8e0, 0x00a8f1, 0x00a8ff, 0x00a8ff, 0x00a926, + 0x00a92d, 0x00a947, 0x00a951, 0x00a980, 0x00a982, 0x00a9b3, 0x00a9b3, 0x00a9b6, 0x00a9b9, 0x00a9bc, 0x00a9bd, 0x00a9e5, 0x00a9e5, 0x00aa29, 0x00aa2e, 0x00aa31, 0x00aa32, + 0x00aa35, 0x00aa36, 0x00aa43, 0x00aa43, 0x00aa4c, 0x00aa4c, 0x00aa7c, 0x00aa7c, 0x00aab0, 0x00aab0, 0x00aab2, 0x00aab4, 0x00aab7, 0x00aab8, 0x00aabe, 0x00aabf, 0x00aac1, + 0x00aac1, 0x00aaec, 0x00aaed, 0x00aaf6, 0x00aaf6, 0x00abe5, 0x00abe5, 0x00abe8, 0x00abe8, 0x00abed, 0x00abed, 0x00fb1e, 0x00fb1e, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2f, + 0x00ff9e, 0x00ff9f, 0x0101fd, 0x0101fd, 0x0102e0, 0x0102e0, 0x010376, 0x01037a, 0x010a01, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a0f, 0x010a38, 0x010a3a, 0x010a3f, + 0x010a3f, 0x010ae5, 0x010ae6, 0x010d24, 0x010d27, 0x010eab, 0x010eac, 0x010f46, 0x010f50, 0x010f82, 0x010f85, 0x011001, 0x011001, 0x011038, 0x011046, 0x011070, 0x011070, + 0x011073, 0x011074, 0x01107f, 0x011081, 0x0110b3, 0x0110b6, 0x0110b9, 0x0110ba, 0x0110c2, 0x0110c2, 0x011100, 0x011102, 0x011127, 0x01112b, 0x01112d, 0x011134, 0x011173, + 0x011173, 0x011180, 0x011181, 0x0111b6, 0x0111be, 0x0111c9, 0x0111cc, 0x0111cf, 0x0111cf, 0x01122f, 0x011231, 0x011234, 0x011234, 0x011236, 0x011237, 0x01123e, 0x01123e, + 0x0112df, 0x0112df, 0x0112e3, 0x0112ea, 0x011300, 0x011301, 0x01133b, 0x01133c, 0x01133e, 0x01133e, 0x011340, 0x011340, 0x011357, 0x011357, 0x011366, 0x01136c, 0x011370, + 0x011374, 0x011438, 0x01143f, 0x011442, 0x011444, 0x011446, 0x011446, 0x01145e, 0x01145e, 0x0114b0, 0x0114b0, 0x0114b3, 0x0114b8, 0x0114ba, 0x0114ba, 0x0114bd, 0x0114bd, + 0x0114bf, 0x0114c0, 0x0114c2, 0x0114c3, 0x0115af, 0x0115af, 0x0115b2, 0x0115b5, 0x0115bc, 0x0115bd, 0x0115bf, 0x0115c0, 0x0115dc, 0x0115dd, 0x011633, 0x01163a, 0x01163d, + 0x01163d, 0x01163f, 0x011640, 0x0116ab, 0x0116ab, 0x0116ad, 0x0116ad, 0x0116b0, 0x0116b5, 0x0116b7, 0x0116b7, 0x01171d, 0x01171f, 0x011722, 0x011725, 0x011727, 0x01172b, + 0x01182f, 0x011837, 0x011839, 0x01183a, 0x011930, 0x011930, 0x01193b, 0x01193c, 0x01193e, 0x01193e, 0x011943, 0x011943, 0x0119d4, 0x0119d7, 0x0119da, 0x0119db, 0x0119e0, + 0x0119e0, 0x011a01, 0x011a0a, 0x011a33, 0x011a38, 0x011a3b, 0x011a3e, 0x011a47, 0x011a47, 0x011a51, 0x011a56, 0x011a59, 0x011a5b, 0x011a8a, 0x011a96, 0x011a98, 0x011a99, + 0x011c30, 0x011c36, 0x011c38, 0x011c3d, 0x011c3f, 0x011c3f, 0x011c92, 0x011ca7, 0x011caa, 0x011cb0, 0x011cb2, 0x011cb3, 0x011cb5, 0x011cb6, 0x011d31, 0x011d36, 0x011d3a, + 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d45, 0x011d47, 0x011d47, 0x011d90, 0x011d91, 0x011d95, 0x011d95, 0x011d97, 0x011d97, 0x011ef3, 0x011ef4, 0x016af0, 0x016af4, + 0x016b30, 0x016b36, 0x016f4f, 0x016f4f, 0x016f8f, 0x016f92, 0x016fe4, 0x016fe4, 0x01bc9d, 0x01bc9e, 0x01cf00, 0x01cf2d, 0x01cf30, 0x01cf46, 0x01d165, 0x01d165, 0x01d167, + 0x01d169, 0x01d16e, 0x01d172, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, 0x01d244, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, 0x01da75, 0x01da75, + 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e130, + 0x01e136, 0x01e2ae, 0x01e2ae, 0x01e2ec, 0x01e2ef, 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e94a, 0x0e0020, 0x0e007f, 0x0e0100, 0x0e01ef)); } private static void populateHEX() { @@ -1932,7 +1971,7 @@ private static void populateIDC() { 0x000483, 0x000487, 0x00048a, 0x00052f, 0x000531, 0x000556, 0x000559, 0x000559, 0x000560, 0x000588, 0x000591, 0x0005bd, 0x0005bf, 0x0005bf, 0x0005c1, 0x0005c2, 0x0005c4, 0x0005c5, 0x0005c7, 0x0005c7, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f2, 0x000610, 0x00061a, 0x000620, 0x000669, 0x00066e, 0x0006d3, 0x0006d5, 0x0006dc, 0x0006df, 0x0006e8, 0x0006ea, 0x0006fc, 0x0006ff, 0x0006ff, 0x000710, 0x00074a, 0x00074d, 0x0007b1, 0x0007c0, 0x0007f5, 0x0007fa, 0x0007fa, 0x0007fd, 0x0007fd, 0x000800, 0x00082d, 0x000840, - 0x00085b, 0x000860, 0x00086a, 0x0008a0, 0x0008b4, 0x0008b6, 0x0008c7, 0x0008d3, 0x0008e1, 0x0008e3, 0x000963, 0x000966, 0x00096f, 0x000971, 0x000983, 0x000985, 0x00098c, + 0x00085b, 0x000860, 0x00086a, 0x000870, 0x000887, 0x000889, 0x00088e, 0x000898, 0x0008e1, 0x0008e3, 0x000963, 0x000966, 0x00096f, 0x000971, 0x000983, 0x000985, 0x00098c, 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bc, 0x0009c4, 0x0009c7, 0x0009c8, 0x0009cb, 0x0009ce, 0x0009d7, 0x0009d7, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e3, 0x0009e6, 0x0009f1, 0x0009fc, 0x0009fc, 0x0009fe, 0x0009fe, 0x000a01, 0x000a03, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, 0x000a38, 0x000a39, 0x000a3c, 0x000a3c, 0x000a3e, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, @@ -1942,77 +1981,80 @@ private static void populateIDC() { 0x000b3c, 0x000b44, 0x000b47, 0x000b48, 0x000b4b, 0x000b4d, 0x000b55, 0x000b57, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b63, 0x000b66, 0x000b6f, 0x000b71, 0x000b71, 0x000b82, 0x000b83, 0x000b85, 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bbe, 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcd, 0x000bd0, 0x000bd0, 0x000bd7, 0x000bd7, 0x000be6, 0x000bef, 0x000c00, 0x000c0c, 0x000c0e, - 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c60, 0x000c63, - 0x000c66, 0x000c6f, 0x000c80, 0x000c83, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbc, 0x000cc4, 0x000cc6, - 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000cde, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x000d00, 0x000d0c, 0x000d0e, 0x000d10, - 0x000d12, 0x000d44, 0x000d46, 0x000d48, 0x000d4a, 0x000d4e, 0x000d54, 0x000d57, 0x000d5f, 0x000d63, 0x000d66, 0x000d6f, 0x000d7a, 0x000d7f, 0x000d81, 0x000d83, 0x000d85, - 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000dca, 0x000dca, 0x000dcf, 0x000dd4, 0x000dd6, 0x000dd6, 0x000dd8, 0x000ddf, - 0x000de6, 0x000def, 0x000df2, 0x000df3, 0x000e01, 0x000e3a, 0x000e40, 0x000e4e, 0x000e50, 0x000e59, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, - 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000ec8, 0x000ecd, 0x000ed0, 0x000ed9, 0x000edc, 0x000edf, 0x000f00, 0x000f00, - 0x000f18, 0x000f19, 0x000f20, 0x000f29, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f3e, 0x000f47, 0x000f49, 0x000f6c, 0x000f71, 0x000f84, 0x000f86, - 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x001000, 0x001049, 0x001050, 0x00109d, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x0010fa, - 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, - 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x00135d, 0x00135f, - 0x001369, 0x001371, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, 0x0016a0, 0x0016ea, 0x0016ee, - 0x0016f8, 0x001700, 0x00170c, 0x00170e, 0x001714, 0x001720, 0x001734, 0x001740, 0x001753, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001772, 0x001773, 0x001780, 0x0017d3, - 0x0017d7, 0x0017d7, 0x0017dc, 0x0017dd, 0x0017e0, 0x0017e9, 0x00180b, 0x00180d, 0x001810, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, + 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3c, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, + 0x000c60, 0x000c63, 0x000c66, 0x000c6f, 0x000c80, 0x000c83, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbc, + 0x000cc4, 0x000cc6, 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000cdd, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x000d00, 0x000d0c, + 0x000d0e, 0x000d10, 0x000d12, 0x000d44, 0x000d46, 0x000d48, 0x000d4a, 0x000d4e, 0x000d54, 0x000d57, 0x000d5f, 0x000d63, 0x000d66, 0x000d6f, 0x000d7a, 0x000d7f, 0x000d81, + 0x000d83, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000dca, 0x000dca, 0x000dcf, 0x000dd4, 0x000dd6, 0x000dd6, + 0x000dd8, 0x000ddf, 0x000de6, 0x000def, 0x000df2, 0x000df3, 0x000e01, 0x000e3a, 0x000e40, 0x000e4e, 0x000e50, 0x000e59, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, + 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000ec8, 0x000ecd, 0x000ed0, 0x000ed9, 0x000edc, 0x000edf, + 0x000f00, 0x000f00, 0x000f18, 0x000f19, 0x000f20, 0x000f29, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f3e, 0x000f47, 0x000f49, 0x000f6c, 0x000f71, + 0x000f84, 0x000f86, 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x001000, 0x001049, 0x001050, 0x00109d, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, + 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, + 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, + 0x00135d, 0x00135f, 0x001369, 0x001371, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, 0x0016a0, + 0x0016ea, 0x0016ee, 0x0016f8, 0x001700, 0x001715, 0x00171f, 0x001734, 0x001740, 0x001753, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001772, 0x001773, 0x001780, 0x0017d3, + 0x0017d7, 0x0017d7, 0x0017dc, 0x0017dd, 0x0017e0, 0x0017e9, 0x00180b, 0x00180d, 0x00180f, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001920, 0x00192b, 0x001930, 0x00193b, 0x001946, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x0019d0, 0x0019da, 0x001a00, 0x001a1b, - 0x001a20, 0x001a5e, 0x001a60, 0x001a7c, 0x001a7f, 0x001a89, 0x001a90, 0x001a99, 0x001aa7, 0x001aa7, 0x001ab0, 0x001abd, 0x001abf, 0x001ac0, 0x001b00, 0x001b4b, 0x001b50, + 0x001a20, 0x001a5e, 0x001a60, 0x001a7c, 0x001a7f, 0x001a89, 0x001a90, 0x001a99, 0x001aa7, 0x001aa7, 0x001ab0, 0x001abd, 0x001abf, 0x001ace, 0x001b00, 0x001b4c, 0x001b50, 0x001b59, 0x001b6b, 0x001b73, 0x001b80, 0x001bf3, 0x001c00, 0x001c37, 0x001c40, 0x001c49, 0x001c4d, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cbf, - 0x001cd0, 0x001cd2, 0x001cd4, 0x001cfa, 0x001d00, 0x001df9, 0x001dfb, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, - 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, - 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x00203f, 0x002040, 0x002054, 0x002054, 0x002071, 0x002071, 0x00207f, - 0x00207f, 0x002090, 0x00209c, 0x0020d0, 0x0020dc, 0x0020e1, 0x0020e1, 0x0020e5, 0x0020f0, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, - 0x002118, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, - 0x002188, 0x002c00, 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002ce4, 0x002ceb, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, - 0x002d6f, 0x002d6f, 0x002d7f, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, - 0x002dd6, 0x002dd8, 0x002dde, 0x002de0, 0x002dff, 0x003005, 0x003007, 0x003021, 0x00302f, 0x003031, 0x003035, 0x003038, 0x00303c, 0x003041, 0x003096, 0x003099, 0x00309f, - 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, 0x009ffc, 0x00a000, - 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a62b, 0x00a640, 0x00a66f, 0x00a674, 0x00a67d, 0x00a67f, 0x00a6f1, 0x00a717, 0x00a71f, 0x00a722, 0x00a788, - 0x00a78b, 0x00a7bf, 0x00a7c2, 0x00a7ca, 0x00a7f5, 0x00a827, 0x00a82c, 0x00a82c, 0x00a840, 0x00a873, 0x00a880, 0x00a8c5, 0x00a8d0, 0x00a8d9, 0x00a8e0, 0x00a8f7, 0x00a8fb, - 0x00a8fb, 0x00a8fd, 0x00a92d, 0x00a930, 0x00a953, 0x00a960, 0x00a97c, 0x00a980, 0x00a9c0, 0x00a9cf, 0x00a9d9, 0x00a9e0, 0x00a9fe, 0x00aa00, 0x00aa36, 0x00aa40, 0x00aa4d, - 0x00aa50, 0x00aa59, 0x00aa60, 0x00aa76, 0x00aa7a, 0x00aac2, 0x00aadb, 0x00aadd, 0x00aae0, 0x00aaef, 0x00aaf2, 0x00aaf6, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, - 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, 0x00ab2e, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab69, 0x00ab70, 0x00abea, 0x00abec, 0x00abed, 0x00abf0, 0x00abf9, 0x00ac00, 0x00d7a3, - 0x00d7b0, 0x00d7c6, 0x00d7cb, 0x00d7fb, 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb28, 0x00fb2a, 0x00fb36, 0x00fb38, - 0x00fb3c, 0x00fb3e, 0x00fb3e, 0x00fb40, 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbb1, 0x00fbd3, 0x00fd3d, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdfb, - 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2f, 0x00fe33, 0x00fe34, 0x00fe4d, 0x00fe4f, 0x00fe70, 0x00fe74, 0x00fe76, 0x00fefc, 0x00ff10, 0x00ff19, 0x00ff21, 0x00ff3a, 0x00ff3f, - 0x00ff3f, 0x00ff41, 0x00ff5a, 0x00ff66, 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x010000, 0x01000b, 0x01000d, 0x010026, - 0x010028, 0x01003a, 0x01003c, 0x01003d, 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010140, 0x010174, 0x0101fd, 0x0101fd, 0x010280, 0x01029c, 0x0102a0, - 0x0102d0, 0x0102e0, 0x0102e0, 0x010300, 0x01031f, 0x01032d, 0x01034a, 0x010350, 0x01037a, 0x010380, 0x01039d, 0x0103a0, 0x0103c3, 0x0103c8, 0x0103cf, 0x0103d1, 0x0103d5, - 0x010400, 0x01049d, 0x0104a0, 0x0104a9, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, - 0x010767, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, - 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, - 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a38, 0x010a3a, 0x010a3f, 0x010a3f, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae6, - 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010d00, 0x010d27, 0x010d30, - 0x010d39, 0x010e80, 0x010ea9, 0x010eab, 0x010eac, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f50, 0x010fb0, 0x010fc4, 0x010fe0, 0x010ff6, - 0x011000, 0x011046, 0x011066, 0x01106f, 0x01107f, 0x0110ba, 0x0110d0, 0x0110e8, 0x0110f0, 0x0110f9, 0x011100, 0x011134, 0x011136, 0x01113f, 0x011144, 0x011147, 0x011150, - 0x011173, 0x011176, 0x011176, 0x011180, 0x0111c4, 0x0111c9, 0x0111cc, 0x0111ce, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x011237, 0x01123e, 0x01123e, - 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112ea, 0x0112f0, 0x0112f9, 0x011300, 0x011303, 0x011305, - 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133b, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, - 0x011350, 0x011350, 0x011357, 0x011357, 0x01135d, 0x011363, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011400, 0x01144a, 0x011450, 0x011459, 0x01145e, 0x011461, 0x011480, - 0x0114c5, 0x0114c7, 0x0114c7, 0x0114d0, 0x0114d9, 0x011580, 0x0115b5, 0x0115b8, 0x0115c0, 0x0115d8, 0x0115dd, 0x011600, 0x011640, 0x011644, 0x011644, 0x011650, 0x011659, - 0x011680, 0x0116b8, 0x0116c0, 0x0116c9, 0x011700, 0x01171a, 0x01171d, 0x01172b, 0x011730, 0x011739, 0x011800, 0x01183a, 0x0118a0, 0x0118e9, 0x0118ff, 0x011906, 0x011909, - 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x011935, 0x011937, 0x011938, 0x01193b, 0x011943, 0x011950, 0x011959, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d7, - 0x0119da, 0x0119e1, 0x0119e3, 0x0119e4, 0x011a00, 0x011a3e, 0x011a47, 0x011a47, 0x011a50, 0x011a99, 0x011a9d, 0x011a9d, 0x011ac0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, - 0x011c36, 0x011c38, 0x011c40, 0x011c50, 0x011c59, 0x011c72, 0x011c8f, 0x011c92, 0x011ca7, 0x011ca9, 0x011cb6, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d36, - 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d47, 0x011d50, 0x011d59, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d8e, 0x011d90, 0x011d91, 0x011d93, - 0x011d98, 0x011da0, 0x011da9, 0x011ee0, 0x011ef6, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012400, 0x01246e, 0x012480, 0x012543, 0x013000, 0x01342e, 0x014400, 0x014646, - 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016a60, 0x016a69, 0x016ad0, 0x016aed, 0x016af0, 0x016af4, 0x016b00, 0x016b36, 0x016b40, 0x016b43, 0x016b50, 0x016b59, 0x016b63, - 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e7f, 0x016f00, 0x016f4a, 0x016f4f, 0x016f87, 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe4, 0x016ff0, 0x016ff1, - 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b11e, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, - 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01bc9d, 0x01bc9e, 0x01d165, 0x01d169, 0x01d16d, 0x01d172, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, - 0x01d242, 0x01d244, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, - 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, - 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, - 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01d7ce, 0x01d7ff, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, - 0x01da75, 0x01da75, 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, - 0x01e02a, 0x01e100, 0x01e12c, 0x01e130, 0x01e13d, 0x01e140, 0x01e149, 0x01e14e, 0x01e14e, 0x01e2c0, 0x01e2f9, 0x01e800, 0x01e8c4, 0x01e8d0, 0x01e8d6, 0x01e900, 0x01e94b, - 0x01e950, 0x01e959, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, - 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, - 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, - 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, - 0x01fbf0, 0x01fbf9, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a, 0x0e0100, - 0x0e01ef)); + 0x001cd0, 0x001cd2, 0x001cd4, 0x001cfa, 0x001d00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, + 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, + 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x00203f, 0x002040, 0x002054, 0x002054, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, + 0x00209c, 0x0020d0, 0x0020dc, 0x0020e1, 0x0020e1, 0x0020e5, 0x0020f0, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002118, 0x00211d, + 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c00, + 0x002ce4, 0x002ceb, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d6f, 0x002d7f, 0x002d96, 0x002da0, 0x002da6, + 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x002de0, 0x002dff, 0x003005, + 0x003007, 0x003021, 0x00302f, 0x003031, 0x003035, 0x003038, 0x00303c, 0x003041, 0x003096, 0x003099, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, 0x00312f, + 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a62b, 0x00a640, + 0x00a66f, 0x00a674, 0x00a67d, 0x00a67f, 0x00a6f1, 0x00a717, 0x00a71f, 0x00a722, 0x00a788, 0x00a78b, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, + 0x00a7f2, 0x00a827, 0x00a82c, 0x00a82c, 0x00a840, 0x00a873, 0x00a880, 0x00a8c5, 0x00a8d0, 0x00a8d9, 0x00a8e0, 0x00a8f7, 0x00a8fb, 0x00a8fb, 0x00a8fd, 0x00a92d, 0x00a930, + 0x00a953, 0x00a960, 0x00a97c, 0x00a980, 0x00a9c0, 0x00a9cf, 0x00a9d9, 0x00a9e0, 0x00a9fe, 0x00aa00, 0x00aa36, 0x00aa40, 0x00aa4d, 0x00aa50, 0x00aa59, 0x00aa60, 0x00aa76, + 0x00aa7a, 0x00aac2, 0x00aadb, 0x00aadd, 0x00aae0, 0x00aaef, 0x00aaf2, 0x00aaf6, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, + 0x00ab2e, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab69, 0x00ab70, 0x00abea, 0x00abec, 0x00abed, 0x00abf0, 0x00abf9, 0x00ac00, 0x00d7a3, 0x00d7b0, 0x00d7c6, 0x00d7cb, 0x00d7fb, + 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb28, 0x00fb2a, 0x00fb36, 0x00fb38, 0x00fb3c, 0x00fb3e, 0x00fb3e, 0x00fb40, + 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbb1, 0x00fbd3, 0x00fd3d, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdfb, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2f, + 0x00fe33, 0x00fe34, 0x00fe4d, 0x00fe4f, 0x00fe70, 0x00fe74, 0x00fe76, 0x00fefc, 0x00ff10, 0x00ff19, 0x00ff21, 0x00ff3a, 0x00ff3f, 0x00ff3f, 0x00ff41, 0x00ff5a, 0x00ff66, + 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, 0x01003c, 0x01003d, + 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010140, 0x010174, 0x0101fd, 0x0101fd, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x0102e0, 0x0102e0, 0x010300, + 0x01031f, 0x01032d, 0x01034a, 0x010350, 0x01037a, 0x010380, 0x01039d, 0x0103a0, 0x0103c3, 0x0103c8, 0x0103cf, 0x0103d1, 0x0103d5, 0x010400, 0x01049d, 0x0104a0, 0x0104a9, + 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, + 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010780, 0x010785, 0x010787, 0x0107b0, + 0x0107b2, 0x0107ba, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, + 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a03, 0x010a05, 0x010a06, + 0x010a0c, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a38, 0x010a3a, 0x010a3f, 0x010a3f, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, + 0x010ae6, 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010d00, 0x010d27, + 0x010d30, 0x010d39, 0x010e80, 0x010ea9, 0x010eab, 0x010eac, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f50, 0x010f70, 0x010f85, 0x010fb0, + 0x010fc4, 0x010fe0, 0x010ff6, 0x011000, 0x011046, 0x011066, 0x011075, 0x01107f, 0x0110ba, 0x0110c2, 0x0110c2, 0x0110d0, 0x0110e8, 0x0110f0, 0x0110f9, 0x011100, 0x011134, + 0x011136, 0x01113f, 0x011144, 0x011147, 0x011150, 0x011173, 0x011176, 0x011176, 0x011180, 0x0111c4, 0x0111c9, 0x0111cc, 0x0111ce, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, + 0x011211, 0x011213, 0x011237, 0x01123e, 0x01123e, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112ea, + 0x0112f0, 0x0112f9, 0x011300, 0x011303, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133b, + 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, 0x011350, 0x011350, 0x011357, 0x011357, 0x01135d, 0x011363, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011400, 0x01144a, + 0x011450, 0x011459, 0x01145e, 0x011461, 0x011480, 0x0114c5, 0x0114c7, 0x0114c7, 0x0114d0, 0x0114d9, 0x011580, 0x0115b5, 0x0115b8, 0x0115c0, 0x0115d8, 0x0115dd, 0x011600, + 0x011640, 0x011644, 0x011644, 0x011650, 0x011659, 0x011680, 0x0116b8, 0x0116c0, 0x0116c9, 0x011700, 0x01171a, 0x01171d, 0x01172b, 0x011730, 0x011739, 0x011740, 0x011746, + 0x011800, 0x01183a, 0x0118a0, 0x0118e9, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x011935, 0x011937, 0x011938, 0x01193b, + 0x011943, 0x011950, 0x011959, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d7, 0x0119da, 0x0119e1, 0x0119e3, 0x0119e4, 0x011a00, 0x011a3e, 0x011a47, 0x011a47, 0x011a50, 0x011a99, + 0x011a9d, 0x011a9d, 0x011ab0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c36, 0x011c38, 0x011c40, 0x011c50, 0x011c59, 0x011c72, 0x011c8f, 0x011c92, 0x011ca7, 0x011ca9, + 0x011cb6, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d47, 0x011d50, 0x011d59, 0x011d60, 0x011d65, + 0x011d67, 0x011d68, 0x011d6a, 0x011d8e, 0x011d90, 0x011d91, 0x011d93, 0x011d98, 0x011da0, 0x011da9, 0x011ee0, 0x011ef6, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012400, + 0x01246e, 0x012480, 0x012543, 0x012f90, 0x012ff0, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016a60, 0x016a69, 0x016a70, 0x016abe, + 0x016ac0, 0x016ac9, 0x016ad0, 0x016aed, 0x016af0, 0x016af4, 0x016b00, 0x016b36, 0x016b40, 0x016b43, 0x016b50, 0x016b59, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, + 0x016e7f, 0x016f00, 0x016f4a, 0x016f4f, 0x016f87, 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe4, 0x016ff0, 0x016ff1, 0x017000, 0x0187f7, 0x018800, 0x018cd5, + 0x018d00, 0x018d08, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01b000, 0x01b122, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, + 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01bc9d, 0x01bc9e, 0x01cf00, 0x01cf2d, 0x01cf30, 0x01cf46, 0x01d165, 0x01d169, 0x01d16d, 0x01d172, + 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, 0x01d244, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, + 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, + 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, + 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, + 0x01d7ce, 0x01d7ff, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, 0x01da75, 0x01da75, 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01df00, 0x01df1e, 0x01e000, + 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e100, 0x01e12c, 0x01e130, 0x01e13d, 0x01e140, 0x01e149, 0x01e14e, 0x01e14e, + 0x01e290, 0x01e2ae, 0x01e2c0, 0x01e2f9, 0x01e7e0, 0x01e7e6, 0x01e7e8, 0x01e7eb, 0x01e7ed, 0x01e7ee, 0x01e7f0, 0x01e7fe, 0x01e800, 0x01e8c4, 0x01e8d0, 0x01e8d6, 0x01e900, + 0x01e94b, 0x01e950, 0x01e959, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, + 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, + 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, + 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, + 0x01eebb, 0x01fbf0, 0x01fbf9, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a, + 0x0e0100, 0x0e01ef)); } private static void populateIDS() { @@ -2021,38 +2063,38 @@ private static void populateIDS() { 0x00037f, 0x000386, 0x000386, 0x000388, 0x00038a, 0x00038c, 0x00038c, 0x00038e, 0x0003a1, 0x0003a3, 0x0003f5, 0x0003f7, 0x000481, 0x00048a, 0x00052f, 0x000531, 0x000556, 0x000559, 0x000559, 0x000560, 0x000588, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f2, 0x000620, 0x00064a, 0x00066e, 0x00066f, 0x000671, 0x0006d3, 0x0006d5, 0x0006d5, 0x0006e5, 0x0006e6, 0x0006ee, 0x0006ef, 0x0006fa, 0x0006fc, 0x0006ff, 0x0006ff, 0x000710, 0x000710, 0x000712, 0x00072f, 0x00074d, 0x0007a5, 0x0007b1, 0x0007b1, 0x0007ca, 0x0007ea, - 0x0007f4, 0x0007f5, 0x0007fa, 0x0007fa, 0x000800, 0x000815, 0x00081a, 0x00081a, 0x000824, 0x000824, 0x000828, 0x000828, 0x000840, 0x000858, 0x000860, 0x00086a, 0x0008a0, - 0x0008b4, 0x0008b6, 0x0008c7, 0x000904, 0x000939, 0x00093d, 0x00093d, 0x000950, 0x000950, 0x000958, 0x000961, 0x000971, 0x000980, 0x000985, 0x00098c, 0x00098f, 0x000990, - 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009bd, 0x0009ce, 0x0009ce, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e1, 0x0009f0, - 0x0009f1, 0x0009fc, 0x0009fc, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, 0x000a38, 0x000a39, - 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a72, 0x000a74, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, 0x000ab3, 0x000ab5, - 0x000ab9, 0x000abd, 0x000abd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae1, 0x000af9, 0x000af9, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, 0x000b2a, 0x000b30, - 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b3d, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b61, 0x000b71, 0x000b71, 0x000b83, 0x000b83, 0x000b85, 0x000b8a, 0x000b8e, - 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bd0, 0x000bd0, - 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c58, 0x000c5a, 0x000c60, 0x000c61, 0x000c80, 0x000c80, 0x000c85, - 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbd, 0x000cde, 0x000cde, 0x000ce0, 0x000ce1, 0x000cf1, 0x000cf2, - 0x000d04, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d4e, 0x000d4e, 0x000d54, 0x000d56, 0x000d5f, 0x000d61, 0x000d7a, 0x000d7f, 0x000d85, - 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000e01, 0x000e30, 0x000e32, 0x000e33, 0x000e40, 0x000e46, 0x000e81, 0x000e82, - 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb3, 0x000ebd, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, - 0x000ec6, 0x000edc, 0x000edf, 0x000f00, 0x000f00, 0x000f40, 0x000f47, 0x000f49, 0x000f6c, 0x000f88, 0x000f8c, 0x001000, 0x00102a, 0x00103f, 0x00103f, 0x001050, 0x001055, - 0x00105a, 0x00105d, 0x001061, 0x001061, 0x001065, 0x001066, 0x00106e, 0x001070, 0x001075, 0x001081, 0x00108e, 0x00108e, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, - 0x0010cd, 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, - 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, - 0x00135a, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, 0x0016a0, 0x0016ea, 0x0016ee, 0x0016f8, - 0x001700, 0x00170c, 0x00170e, 0x001711, 0x001720, 0x001731, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001780, 0x0017b3, 0x0017d7, 0x0017d7, 0x0017dc, - 0x0017dc, 0x001820, 0x001878, 0x001880, 0x0018a8, 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001950, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, - 0x0019b0, 0x0019c9, 0x001a00, 0x001a16, 0x001a20, 0x001a54, 0x001aa7, 0x001aa7, 0x001b05, 0x001b33, 0x001b45, 0x001b4b, 0x001b83, 0x001ba0, 0x001bae, 0x001baf, 0x001bba, - 0x001be5, 0x001c00, 0x001c23, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cbf, 0x001ce9, 0x001cec, 0x001cee, 0x001cf3, - 0x001cf5, 0x001cf6, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, 0x001e00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, - 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, - 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x002102, - 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002118, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x002139, - 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c00, 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, - 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d6f, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, - 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x003005, 0x003007, 0x003021, 0x003029, 0x003031, - 0x003035, 0x003038, 0x00303c, 0x003041, 0x003096, 0x00309b, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, - 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, 0x009ffc, 0x00a000, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a61f, 0x00a62a, 0x00a62b, 0x00a640, - 0x00a66e, 0x00a67f, 0x00a69d, 0x00a6a0, 0x00a6ef, 0x00a717, 0x00a71f, 0x00a722, 0x00a788, 0x00a78b, 0x00a7bf, 0x00a7c2, 0x00a7ca, 0x00a7f5, 0x00a801, 0x00a803, 0x00a805, + 0x0007f4, 0x0007f5, 0x0007fa, 0x0007fa, 0x000800, 0x000815, 0x00081a, 0x00081a, 0x000824, 0x000824, 0x000828, 0x000828, 0x000840, 0x000858, 0x000860, 0x00086a, 0x000870, + 0x000887, 0x000889, 0x00088e, 0x0008a0, 0x0008c9, 0x000904, 0x000939, 0x00093d, 0x00093d, 0x000950, 0x000950, 0x000958, 0x000961, 0x000971, 0x000980, 0x000985, 0x00098c, + 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009bd, 0x0009ce, 0x0009ce, 0x0009dc, 0x0009dd, 0x0009df, + 0x0009e1, 0x0009f0, 0x0009f1, 0x0009fc, 0x0009fc, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, + 0x000a38, 0x000a39, 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a72, 0x000a74, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, + 0x000ab3, 0x000ab5, 0x000ab9, 0x000abd, 0x000abd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae1, 0x000af9, 0x000af9, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, + 0x000b2a, 0x000b30, 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b3d, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b61, 0x000b71, 0x000b71, 0x000b83, 0x000b83, 0x000b85, + 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, + 0x000bd0, 0x000bd0, 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, 0x000c60, + 0x000c61, 0x000c80, 0x000c80, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbd, 0x000cdd, 0x000cde, + 0x000ce0, 0x000ce1, 0x000cf1, 0x000cf2, 0x000d04, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d4e, 0x000d4e, 0x000d54, 0x000d56, 0x000d5f, + 0x000d61, 0x000d7a, 0x000d7f, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000e01, 0x000e30, 0x000e32, 0x000e33, + 0x000e40, 0x000e46, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb3, 0x000ebd, + 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000edc, 0x000edf, 0x000f00, 0x000f00, 0x000f40, 0x000f47, 0x000f49, 0x000f6c, 0x000f88, 0x000f8c, 0x001000, 0x00102a, + 0x00103f, 0x00103f, 0x001050, 0x001055, 0x00105a, 0x00105d, 0x001061, 0x001061, 0x001065, 0x001066, 0x00106e, 0x001070, 0x001075, 0x001081, 0x00108e, 0x00108e, 0x0010a0, + 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, + 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, + 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, + 0x0016a0, 0x0016ea, 0x0016ee, 0x0016f8, 0x001700, 0x001711, 0x00171f, 0x001731, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001780, 0x0017b3, 0x0017d7, + 0x0017d7, 0x0017dc, 0x0017dc, 0x001820, 0x001878, 0x001880, 0x0018a8, 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001950, 0x00196d, 0x001970, 0x001974, + 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x001a00, 0x001a16, 0x001a20, 0x001a54, 0x001aa7, 0x001aa7, 0x001b05, 0x001b33, 0x001b45, 0x001b4c, 0x001b83, 0x001ba0, 0x001bae, + 0x001baf, 0x001bba, 0x001be5, 0x001c00, 0x001c23, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cbf, 0x001ce9, 0x001cec, + 0x001cee, 0x001cf3, 0x001cf5, 0x001cf6, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, 0x001e00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, + 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, + 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, + 0x00209c, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002118, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, + 0x00212a, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c00, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, + 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d6f, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, + 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x003005, 0x003007, 0x003021, 0x003029, 0x003031, 0x003035, 0x003038, + 0x00303c, 0x003041, 0x003096, 0x00309b, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, + 0x003400, 0x004dbf, 0x004e00, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a61f, 0x00a62a, 0x00a62b, 0x00a640, 0x00a66e, 0x00a67f, 0x00a69d, 0x00a6a0, + 0x00a6ef, 0x00a717, 0x00a71f, 0x00a722, 0x00a788, 0x00a78b, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, 0x00a7f2, 0x00a801, 0x00a803, 0x00a805, 0x00a807, 0x00a80a, 0x00a80c, 0x00a822, 0x00a840, 0x00a873, 0x00a882, 0x00a8b3, 0x00a8f2, 0x00a8f7, 0x00a8fb, 0x00a8fb, 0x00a8fd, 0x00a8fe, 0x00a90a, 0x00a925, 0x00a930, 0x00a946, 0x00a960, 0x00a97c, 0x00a984, 0x00a9b2, 0x00a9cf, 0x00a9cf, 0x00a9e0, 0x00a9e4, 0x00a9e6, 0x00a9ef, 0x00a9fa, 0x00a9fe, 0x00aa00, 0x00aa28, 0x00aa40, 0x00aa42, 0x00aa44, 0x00aa4b, 0x00aa60, 0x00aa76, 0x00aa7a, 0x00aa7a, 0x00aa7e, 0x00aaaf, 0x00aab1, 0x00aab1, 0x00aab5, 0x00aab6, 0x00aab9, 0x00aabd, 0x00aac0, 0x00aac0, 0x00aac2, @@ -2063,33 +2105,36 @@ private static void populateIDS() { 0x00ff5a, 0x00ff66, 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, 0x01003c, 0x01003d, 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010140, 0x010174, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x010300, 0x01031f, 0x01032d, 0x01034a, 0x010350, 0x010375, 0x010380, 0x01039d, 0x0103a0, 0x0103c3, 0x0103c8, 0x0103cf, 0x0103d1, 0x0103d5, 0x010400, 0x01049d, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, - 0x010500, 0x010527, 0x010530, 0x010563, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, - 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, - 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a00, 0x010a10, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, - 0x010ac7, 0x010ac9, 0x010ae4, 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, - 0x010d00, 0x010d23, 0x010e80, 0x010ea9, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f45, 0x010fb0, 0x010fc4, 0x010fe0, 0x010ff6, 0x011003, - 0x011037, 0x011083, 0x0110af, 0x0110d0, 0x0110e8, 0x011103, 0x011126, 0x011144, 0x011144, 0x011147, 0x011147, 0x011150, 0x011172, 0x011176, 0x011176, 0x011183, 0x0111b2, - 0x0111c1, 0x0111c4, 0x0111da, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x01122b, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, - 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112de, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, - 0x01133d, 0x01133d, 0x011350, 0x011350, 0x01135d, 0x011361, 0x011400, 0x011434, 0x011447, 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114af, 0x0114c4, 0x0114c5, 0x0114c7, - 0x0114c7, 0x011580, 0x0115ae, 0x0115d8, 0x0115db, 0x011600, 0x01162f, 0x011644, 0x011644, 0x011680, 0x0116aa, 0x0116b8, 0x0116b8, 0x011700, 0x01171a, 0x011800, 0x01182b, - 0x0118a0, 0x0118df, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x01192f, 0x01193f, 0x01193f, 0x011941, 0x011941, 0x0119a0, - 0x0119a7, 0x0119aa, 0x0119d0, 0x0119e1, 0x0119e1, 0x0119e3, 0x0119e3, 0x011a00, 0x011a00, 0x011a0b, 0x011a32, 0x011a3a, 0x011a3a, 0x011a50, 0x011a50, 0x011a5c, 0x011a89, - 0x011a9d, 0x011a9d, 0x011ac0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c2e, 0x011c40, 0x011c40, 0x011c72, 0x011c8f, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, - 0x011d30, 0x011d46, 0x011d46, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d89, 0x011d98, 0x011d98, 0x011ee0, 0x011ef2, 0x011fb0, 0x011fb0, 0x012000, 0x012399, - 0x012400, 0x01246e, 0x012480, 0x012543, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, 0x016b40, + 0x010500, 0x010527, 0x010530, 0x010563, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, + 0x0105b9, 0x0105bb, 0x0105bc, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x010800, 0x010805, + 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, + 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a00, 0x010a10, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, + 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae4, 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, + 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010d00, 0x010d23, 0x010e80, 0x010ea9, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f45, + 0x010f70, 0x010f81, 0x010fb0, 0x010fc4, 0x010fe0, 0x010ff6, 0x011003, 0x011037, 0x011071, 0x011072, 0x011075, 0x011075, 0x011083, 0x0110af, 0x0110d0, 0x0110e8, 0x011103, + 0x011126, 0x011144, 0x011144, 0x011147, 0x011147, 0x011150, 0x011172, 0x011176, 0x011176, 0x011183, 0x0111b2, 0x0111c1, 0x0111c4, 0x0111da, 0x0111da, 0x0111dc, 0x0111dc, + 0x011200, 0x011211, 0x011213, 0x01122b, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112de, 0x011305, + 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133d, 0x01133d, 0x011350, 0x011350, 0x01135d, 0x011361, + 0x011400, 0x011434, 0x011447, 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114af, 0x0114c4, 0x0114c5, 0x0114c7, 0x0114c7, 0x011580, 0x0115ae, 0x0115d8, 0x0115db, 0x011600, + 0x01162f, 0x011644, 0x011644, 0x011680, 0x0116aa, 0x0116b8, 0x0116b8, 0x011700, 0x01171a, 0x011740, 0x011746, 0x011800, 0x01182b, 0x0118a0, 0x0118df, 0x0118ff, 0x011906, + 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x01192f, 0x01193f, 0x01193f, 0x011941, 0x011941, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d0, 0x0119e1, + 0x0119e1, 0x0119e3, 0x0119e3, 0x011a00, 0x011a00, 0x011a0b, 0x011a32, 0x011a3a, 0x011a3a, 0x011a50, 0x011a50, 0x011a5c, 0x011a89, 0x011a9d, 0x011a9d, 0x011ab0, 0x011af8, + 0x011c00, 0x011c08, 0x011c0a, 0x011c2e, 0x011c40, 0x011c40, 0x011c72, 0x011c8f, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d30, 0x011d46, 0x011d46, 0x011d60, + 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d89, 0x011d98, 0x011d98, 0x011ee0, 0x011ef2, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012400, 0x01246e, 0x012480, 0x012543, + 0x012f90, 0x012ff0, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016a70, 0x016abe, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, 0x016b40, 0x016b43, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e7f, 0x016f00, 0x016f4a, 0x016f50, 0x016f50, 0x016f93, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe3, - 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b11e, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, - 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, - 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, - 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, - 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01e100, 0x01e12c, 0x01e137, - 0x01e13d, 0x01e14e, 0x01e14e, 0x01e2c0, 0x01e2eb, 0x01e800, 0x01e8c4, 0x01e900, 0x01e943, 0x01e94b, 0x01e94b, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, - 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, - 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, - 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, - 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, - 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); + 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01b000, 0x01b122, 0x01b150, 0x01b152, 0x01b164, + 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, + 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, + 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, + 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, + 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01df00, 0x01df1e, 0x01e100, 0x01e12c, 0x01e137, 0x01e13d, 0x01e14e, 0x01e14e, 0x01e290, 0x01e2ad, 0x01e2c0, 0x01e2eb, 0x01e7e0, 0x01e7e6, + 0x01e7e8, 0x01e7eb, 0x01e7ed, 0x01e7ee, 0x01e7f0, 0x01e7fe, 0x01e800, 0x01e8c4, 0x01e900, 0x01e943, 0x01e94b, 0x01e94b, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, + 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, + 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, + 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, + 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, 0x02b820, + 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); } private static void populateIDSB() { @@ -2102,8 +2147,8 @@ private static void populateIDST() { private static void populateIDEO() { SET_ENCODINGS.put("Ideo", - CodePointSet.createNoDedup(0x003006, 0x003007, 0x003021, 0x003029, 0x003038, 0x00303a, 0x003400, 0x004dbf, 0x004e00, 0x009ffc, 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x016fe4, - 0x016fe4, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b170, 0x01b2fb, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, + CodePointSet.createNoDedup(0x003006, 0x003007, 0x003021, 0x003029, 0x003038, 0x00303a, 0x003400, 0x004dbf, 0x004e00, 0x009fff, 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x016fe4, + 0x016fe4, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b170, 0x01b2fb, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); } @@ -2168,7 +2213,7 @@ private static void populateLOWER() { 0x001f30, 0x001f37, 0x001f40, 0x001f45, 0x001f50, 0x001f57, 0x001f60, 0x001f67, 0x001f70, 0x001f7d, 0x001f80, 0x001f87, 0x001f90, 0x001f97, 0x001fa0, 0x001fa7, 0x001fb0, 0x001fb4, 0x001fb6, 0x001fb7, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fc7, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fd7, 0x001fe0, 0x001fe7, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ff7, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x00210a, 0x00210a, 0x00210e, 0x00210f, 0x002113, 0x002113, 0x00212f, 0x00212f, 0x002134, - 0x002134, 0x002139, 0x002139, 0x00213c, 0x00213d, 0x002146, 0x002149, 0x00214e, 0x00214e, 0x002170, 0x00217f, 0x002184, 0x002184, 0x0024d0, 0x0024e9, 0x002c30, 0x002c5e, + 0x002134, 0x002139, 0x002139, 0x00213c, 0x00213d, 0x002146, 0x002149, 0x00214e, 0x00214e, 0x002170, 0x00217f, 0x002184, 0x002184, 0x0024d0, 0x0024e9, 0x002c30, 0x002c5f, 0x002c61, 0x002c61, 0x002c65, 0x002c66, 0x002c68, 0x002c68, 0x002c6a, 0x002c6a, 0x002c6c, 0x002c6c, 0x002c71, 0x002c71, 0x002c73, 0x002c74, 0x002c76, 0x002c7d, 0x002c81, 0x002c81, 0x002c83, 0x002c83, 0x002c85, 0x002c85, 0x002c87, 0x002c87, 0x002c89, 0x002c89, 0x002c8b, 0x002c8b, 0x002c8d, 0x002c8d, 0x002c8f, 0x002c8f, 0x002c91, 0x002c91, 0x002c93, 0x002c93, 0x002c95, 0x002c95, 0x002c97, 0x002c97, 0x002c99, 0x002c99, 0x002c9b, 0x002c9b, 0x002c9d, 0x002c9d, 0x002c9f, 0x002c9f, 0x002ca1, 0x002ca1, 0x002ca3, @@ -2188,12 +2233,14 @@ private static void populateLOWER() { 0x00a76b, 0x00a76b, 0x00a76d, 0x00a76d, 0x00a76f, 0x00a778, 0x00a77a, 0x00a77a, 0x00a77c, 0x00a77c, 0x00a77f, 0x00a77f, 0x00a781, 0x00a781, 0x00a783, 0x00a783, 0x00a785, 0x00a785, 0x00a787, 0x00a787, 0x00a78c, 0x00a78c, 0x00a78e, 0x00a78e, 0x00a791, 0x00a791, 0x00a793, 0x00a795, 0x00a797, 0x00a797, 0x00a799, 0x00a799, 0x00a79b, 0x00a79b, 0x00a79d, 0x00a79d, 0x00a79f, 0x00a79f, 0x00a7a1, 0x00a7a1, 0x00a7a3, 0x00a7a3, 0x00a7a5, 0x00a7a5, 0x00a7a7, 0x00a7a7, 0x00a7a9, 0x00a7a9, 0x00a7af, 0x00a7af, 0x00a7b5, - 0x00a7b5, 0x00a7b7, 0x00a7b7, 0x00a7b9, 0x00a7b9, 0x00a7bb, 0x00a7bb, 0x00a7bd, 0x00a7bd, 0x00a7bf, 0x00a7bf, 0x00a7c3, 0x00a7c3, 0x00a7c8, 0x00a7c8, 0x00a7ca, 0x00a7ca, - 0x00a7f6, 0x00a7f6, 0x00a7f8, 0x00a7fa, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab68, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff41, 0x00ff5a, 0x010428, - 0x01044f, 0x0104d8, 0x0104fb, 0x010cc0, 0x010cf2, 0x0118c0, 0x0118df, 0x016e60, 0x016e7f, 0x01d41a, 0x01d433, 0x01d44e, 0x01d454, 0x01d456, 0x01d467, 0x01d482, 0x01d49b, - 0x01d4b6, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d4cf, 0x01d4ea, 0x01d503, 0x01d51e, 0x01d537, 0x01d552, 0x01d56b, 0x01d586, 0x01d59f, 0x01d5ba, - 0x01d5d3, 0x01d5ee, 0x01d607, 0x01d622, 0x01d63b, 0x01d656, 0x01d66f, 0x01d68a, 0x01d6a5, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6e1, 0x01d6fc, 0x01d714, 0x01d716, 0x01d71b, - 0x01d736, 0x01d74e, 0x01d750, 0x01d755, 0x01d770, 0x01d788, 0x01d78a, 0x01d78f, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7c9, 0x01d7cb, 0x01d7cb, 0x01e922, 0x01e943)); + 0x00a7b5, 0x00a7b7, 0x00a7b7, 0x00a7b9, 0x00a7b9, 0x00a7bb, 0x00a7bb, 0x00a7bd, 0x00a7bd, 0x00a7bf, 0x00a7bf, 0x00a7c1, 0x00a7c1, 0x00a7c3, 0x00a7c3, 0x00a7c8, 0x00a7c8, + 0x00a7ca, 0x00a7ca, 0x00a7d1, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d5, 0x00a7d7, 0x00a7d7, 0x00a7d9, 0x00a7d9, 0x00a7f6, 0x00a7f6, 0x00a7f8, 0x00a7fa, 0x00ab30, + 0x00ab5a, 0x00ab5c, 0x00ab68, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff41, 0x00ff5a, 0x010428, 0x01044f, 0x0104d8, 0x0104fb, 0x010597, 0x0105a1, + 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010cc0, 0x010cf2, 0x0118c0, 0x0118df, 0x016e60, 0x016e7f, 0x01d41a, 0x01d433, 0x01d44e, 0x01d454, 0x01d456, + 0x01d467, 0x01d482, 0x01d49b, 0x01d4b6, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d4cf, 0x01d4ea, 0x01d503, 0x01d51e, 0x01d537, 0x01d552, 0x01d56b, + 0x01d586, 0x01d59f, 0x01d5ba, 0x01d5d3, 0x01d5ee, 0x01d607, 0x01d622, 0x01d63b, 0x01d656, 0x01d66f, 0x01d68a, 0x01d6a5, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6e1, 0x01d6fc, + 0x01d714, 0x01d716, 0x01d71b, 0x01d736, 0x01d74e, 0x01d750, 0x01d755, 0x01d770, 0x01d788, 0x01d78a, 0x01d78f, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7c9, 0x01d7cb, 0x01d7cb, + 0x01df00, 0x01df09, 0x01df0b, 0x01df1e, 0x01e922, 0x01e943)); } private static void populateMATH() { @@ -2249,46 +2296,45 @@ private static void populateRADICAL() { } private static void populateSD() { - SET_ENCODINGS.put("SD", - CodePointSet.createNoDedup(0x000069, 0x00006a, 0x00012f, 0x00012f, 0x000249, 0x000249, 0x000268, 0x000268, 0x00029d, 0x00029d, 0x0002b2, 0x0002b2, 0x0003f3, 0x0003f3, 0x000456, - 0x000456, 0x000458, 0x000458, 0x001d62, 0x001d62, 0x001d96, 0x001d96, 0x001da4, 0x001da4, 0x001da8, 0x001da8, 0x001e2d, 0x001e2d, 0x001ecb, 0x001ecb, 0x002071, - 0x002071, 0x002148, 0x002149, 0x002c7c, 0x002c7c, 0x01d422, 0x01d423, 0x01d456, 0x01d457, 0x01d48a, 0x01d48b, 0x01d4be, 0x01d4bf, 0x01d4f2, 0x01d4f3, 0x01d526, - 0x01d527, 0x01d55a, 0x01d55b, 0x01d58e, 0x01d58f, 0x01d5c2, 0x01d5c3, 0x01d5f6, 0x01d5f7, 0x01d62a, 0x01d62b, 0x01d65e, 0x01d65f, 0x01d692, 0x01d693)); + SET_ENCODINGS.put("SD", CodePointSet.createNoDedup(0x000069, 0x00006a, 0x00012f, 0x00012f, 0x000249, 0x000249, 0x000268, 0x000268, 0x00029d, 0x00029d, 0x0002b2, 0x0002b2, 0x0003f3, 0x0003f3, + 0x000456, 0x000456, 0x000458, 0x000458, 0x001d62, 0x001d62, 0x001d96, 0x001d96, 0x001da4, 0x001da4, 0x001da8, 0x001da8, 0x001e2d, 0x001e2d, 0x001ecb, 0x001ecb, 0x002071, + 0x002071, 0x002148, 0x002149, 0x002c7c, 0x002c7c, 0x01d422, 0x01d423, 0x01d456, 0x01d457, 0x01d48a, 0x01d48b, 0x01d4be, 0x01d4bf, 0x01d4f2, 0x01d4f3, 0x01d526, 0x01d527, + 0x01d55a, 0x01d55b, 0x01d58e, 0x01d58f, 0x01d5c2, 0x01d5c3, 0x01d5f6, 0x01d5f7, 0x01d62a, 0x01d62b, 0x01d65e, 0x01d65f, 0x01d692, 0x01d693, 0x01df1a, 0x01df1a)); } private static void populateSTERM() { SET_ENCODINGS.put("STerm", - CodePointSet.createNoDedup(0x000021, 0x000021, 0x00002e, 0x00002e, 0x00003f, 0x00003f, 0x000589, 0x000589, 0x00061e, 0x00061f, 0x0006d4, 0x0006d4, 0x000700, 0x000702, 0x0007f9, + CodePointSet.createNoDedup(0x000021, 0x000021, 0x00002e, 0x00002e, 0x00003f, 0x00003f, 0x000589, 0x000589, 0x00061d, 0x00061f, 0x0006d4, 0x0006d4, 0x000700, 0x000702, 0x0007f9, 0x0007f9, 0x000837, 0x000837, 0x000839, 0x000839, 0x00083d, 0x00083e, 0x000964, 0x000965, 0x00104a, 0x00104b, 0x001362, 0x001362, 0x001367, 0x001368, 0x00166e, - 0x00166e, 0x001735, 0x001736, 0x001803, 0x001803, 0x001809, 0x001809, 0x001944, 0x001945, 0x001aa8, 0x001aab, 0x001b5a, 0x001b5b, 0x001b5e, 0x001b5f, 0x001c3b, - 0x001c3c, 0x001c7e, 0x001c7f, 0x00203c, 0x00203d, 0x002047, 0x002049, 0x002e2e, 0x002e2e, 0x002e3c, 0x002e3c, 0x003002, 0x003002, 0x00a4ff, 0x00a4ff, 0x00a60e, - 0x00a60f, 0x00a6f3, 0x00a6f3, 0x00a6f7, 0x00a6f7, 0x00a876, 0x00a877, 0x00a8ce, 0x00a8cf, 0x00a92f, 0x00a92f, 0x00a9c8, 0x00a9c9, 0x00aa5d, 0x00aa5f, 0x00aaf0, - 0x00aaf1, 0x00abeb, 0x00abeb, 0x00fe52, 0x00fe52, 0x00fe56, 0x00fe57, 0x00ff01, 0x00ff01, 0x00ff0e, 0x00ff0e, 0x00ff1f, 0x00ff1f, 0x00ff61, 0x00ff61, 0x010a56, - 0x010a57, 0x010f55, 0x010f59, 0x011047, 0x011048, 0x0110be, 0x0110c1, 0x011141, 0x011143, 0x0111c5, 0x0111c6, 0x0111cd, 0x0111cd, 0x0111de, 0x0111df, 0x011238, - 0x011239, 0x01123b, 0x01123c, 0x0112a9, 0x0112a9, 0x01144b, 0x01144c, 0x0115c2, 0x0115c3, 0x0115c9, 0x0115d7, 0x011641, 0x011642, 0x01173c, 0x01173e, 0x011944, - 0x011944, 0x011946, 0x011946, 0x011a42, 0x011a43, 0x011a9b, 0x011a9c, 0x011c41, 0x011c42, 0x011ef7, 0x011ef8, 0x016a6e, 0x016a6f, 0x016af5, 0x016af5, 0x016b37, - 0x016b38, 0x016b44, 0x016b44, 0x016e98, 0x016e98, 0x01bc9f, 0x01bc9f, 0x01da88, 0x01da88)); + 0x00166e, 0x001735, 0x001736, 0x001803, 0x001803, 0x001809, 0x001809, 0x001944, 0x001945, 0x001aa8, 0x001aab, 0x001b5a, 0x001b5b, 0x001b5e, 0x001b5f, 0x001b7d, + 0x001b7e, 0x001c3b, 0x001c3c, 0x001c7e, 0x001c7f, 0x00203c, 0x00203d, 0x002047, 0x002049, 0x002e2e, 0x002e2e, 0x002e3c, 0x002e3c, 0x002e53, 0x002e54, 0x003002, + 0x003002, 0x00a4ff, 0x00a4ff, 0x00a60e, 0x00a60f, 0x00a6f3, 0x00a6f3, 0x00a6f7, 0x00a6f7, 0x00a876, 0x00a877, 0x00a8ce, 0x00a8cf, 0x00a92f, 0x00a92f, 0x00a9c8, + 0x00a9c9, 0x00aa5d, 0x00aa5f, 0x00aaf0, 0x00aaf1, 0x00abeb, 0x00abeb, 0x00fe52, 0x00fe52, 0x00fe56, 0x00fe57, 0x00ff01, 0x00ff01, 0x00ff0e, 0x00ff0e, 0x00ff1f, + 0x00ff1f, 0x00ff61, 0x00ff61, 0x010a56, 0x010a57, 0x010f55, 0x010f59, 0x010f86, 0x010f89, 0x011047, 0x011048, 0x0110be, 0x0110c1, 0x011141, 0x011143, 0x0111c5, + 0x0111c6, 0x0111cd, 0x0111cd, 0x0111de, 0x0111df, 0x011238, 0x011239, 0x01123b, 0x01123c, 0x0112a9, 0x0112a9, 0x01144b, 0x01144c, 0x0115c2, 0x0115c3, 0x0115c9, + 0x0115d7, 0x011641, 0x011642, 0x01173c, 0x01173e, 0x011944, 0x011944, 0x011946, 0x011946, 0x011a42, 0x011a43, 0x011a9b, 0x011a9c, 0x011c41, 0x011c42, 0x011ef7, + 0x011ef8, 0x016a6e, 0x016a6f, 0x016af5, 0x016af5, 0x016b37, 0x016b38, 0x016b44, 0x016b44, 0x016e98, 0x016e98, 0x01bc9f, 0x01bc9f, 0x01da88, 0x01da88)); } private static void populateTERM() { SET_ENCODINGS.put("Term", CodePointSet.createNoDedup(0x000021, 0x000021, 0x00002c, 0x00002c, 0x00002e, 0x00002e, 0x00003a, 0x00003b, 0x00003f, 0x00003f, 0x00037e, 0x00037e, 0x000387, 0x000387, - 0x000589, 0x000589, 0x0005c3, 0x0005c3, 0x00060c, 0x00060c, 0x00061b, 0x00061b, 0x00061e, 0x00061f, 0x0006d4, 0x0006d4, 0x000700, 0x00070a, 0x00070c, 0x00070c, 0x0007f8, + 0x000589, 0x000589, 0x0005c3, 0x0005c3, 0x00060c, 0x00060c, 0x00061b, 0x00061b, 0x00061d, 0x00061f, 0x0006d4, 0x0006d4, 0x000700, 0x00070a, 0x00070c, 0x00070c, 0x0007f8, 0x0007f9, 0x000830, 0x00083e, 0x00085e, 0x00085e, 0x000964, 0x000965, 0x000e5a, 0x000e5b, 0x000f08, 0x000f08, 0x000f0d, 0x000f12, 0x00104a, 0x00104b, 0x001361, 0x001368, 0x00166e, 0x00166e, 0x0016eb, 0x0016ed, 0x001735, 0x001736, 0x0017d4, 0x0017d6, 0x0017da, 0x0017da, 0x001802, 0x001805, 0x001808, 0x001809, 0x001944, 0x001945, 0x001aa8, - 0x001aab, 0x001b5a, 0x001b5b, 0x001b5d, 0x001b5f, 0x001c3b, 0x001c3f, 0x001c7e, 0x001c7f, 0x00203c, 0x00203d, 0x002047, 0x002049, 0x002e2e, 0x002e2e, 0x002e3c, 0x002e3c, - 0x002e41, 0x002e41, 0x002e4c, 0x002e4c, 0x002e4e, 0x002e4f, 0x003001, 0x003002, 0x00a4fe, 0x00a4ff, 0x00a60d, 0x00a60f, 0x00a6f3, 0x00a6f7, 0x00a876, 0x00a877, 0x00a8ce, - 0x00a8cf, 0x00a92f, 0x00a92f, 0x00a9c7, 0x00a9c9, 0x00aa5d, 0x00aa5f, 0x00aadf, 0x00aadf, 0x00aaf0, 0x00aaf1, 0x00abeb, 0x00abeb, 0x00fe50, 0x00fe52, 0x00fe54, 0x00fe57, - 0x00ff01, 0x00ff01, 0x00ff0c, 0x00ff0c, 0x00ff0e, 0x00ff0e, 0x00ff1a, 0x00ff1b, 0x00ff1f, 0x00ff1f, 0x00ff61, 0x00ff61, 0x00ff64, 0x00ff64, 0x01039f, 0x01039f, 0x0103d0, - 0x0103d0, 0x010857, 0x010857, 0x01091f, 0x01091f, 0x010a56, 0x010a57, 0x010af0, 0x010af5, 0x010b3a, 0x010b3f, 0x010b99, 0x010b9c, 0x010f55, 0x010f59, 0x011047, 0x01104d, - 0x0110be, 0x0110c1, 0x011141, 0x011143, 0x0111c5, 0x0111c6, 0x0111cd, 0x0111cd, 0x0111de, 0x0111df, 0x011238, 0x01123c, 0x0112a9, 0x0112a9, 0x01144b, 0x01144d, 0x01145a, - 0x01145b, 0x0115c2, 0x0115c5, 0x0115c9, 0x0115d7, 0x011641, 0x011642, 0x01173c, 0x01173e, 0x011944, 0x011944, 0x011946, 0x011946, 0x011a42, 0x011a43, 0x011a9b, 0x011a9c, - 0x011aa1, 0x011aa2, 0x011c41, 0x011c43, 0x011c71, 0x011c71, 0x011ef7, 0x011ef8, 0x012470, 0x012474, 0x016a6e, 0x016a6f, 0x016af5, 0x016af5, 0x016b37, 0x016b39, 0x016b44, - 0x016b44, 0x016e97, 0x016e98, 0x01bc9f, 0x01bc9f, 0x01da87, 0x01da8a)); + 0x001aab, 0x001b5a, 0x001b5b, 0x001b5d, 0x001b5f, 0x001b7d, 0x001b7e, 0x001c3b, 0x001c3f, 0x001c7e, 0x001c7f, 0x00203c, 0x00203d, 0x002047, 0x002049, 0x002e2e, 0x002e2e, + 0x002e3c, 0x002e3c, 0x002e41, 0x002e41, 0x002e4c, 0x002e4c, 0x002e4e, 0x002e4f, 0x002e53, 0x002e54, 0x003001, 0x003002, 0x00a4fe, 0x00a4ff, 0x00a60d, 0x00a60f, 0x00a6f3, + 0x00a6f7, 0x00a876, 0x00a877, 0x00a8ce, 0x00a8cf, 0x00a92f, 0x00a92f, 0x00a9c7, 0x00a9c9, 0x00aa5d, 0x00aa5f, 0x00aadf, 0x00aadf, 0x00aaf0, 0x00aaf1, 0x00abeb, 0x00abeb, + 0x00fe50, 0x00fe52, 0x00fe54, 0x00fe57, 0x00ff01, 0x00ff01, 0x00ff0c, 0x00ff0c, 0x00ff0e, 0x00ff0e, 0x00ff1a, 0x00ff1b, 0x00ff1f, 0x00ff1f, 0x00ff61, 0x00ff61, 0x00ff64, + 0x00ff64, 0x01039f, 0x01039f, 0x0103d0, 0x0103d0, 0x010857, 0x010857, 0x01091f, 0x01091f, 0x010a56, 0x010a57, 0x010af0, 0x010af5, 0x010b3a, 0x010b3f, 0x010b99, 0x010b9c, + 0x010f55, 0x010f59, 0x010f86, 0x010f89, 0x011047, 0x01104d, 0x0110be, 0x0110c1, 0x011141, 0x011143, 0x0111c5, 0x0111c6, 0x0111cd, 0x0111cd, 0x0111de, 0x0111df, 0x011238, + 0x01123c, 0x0112a9, 0x0112a9, 0x01144b, 0x01144d, 0x01145a, 0x01145b, 0x0115c2, 0x0115c5, 0x0115c9, 0x0115d7, 0x011641, 0x011642, 0x01173c, 0x01173e, 0x011944, 0x011944, + 0x011946, 0x011946, 0x011a42, 0x011a43, 0x011a9b, 0x011a9c, 0x011aa1, 0x011aa2, 0x011c41, 0x011c43, 0x011c71, 0x011c71, 0x011ef7, 0x011ef8, 0x012470, 0x012474, 0x016a6e, + 0x016a6f, 0x016af5, 0x016af5, 0x016b37, 0x016b39, 0x016b44, 0x016b44, 0x016e97, 0x016e98, 0x01bc9f, 0x01bc9f, 0x01da87, 0x01da8a)); } private static void populateUIDEO() { - SET_ENCODINGS.put("UIdeo", CodePointSet.createNoDedup(0x003400, 0x004dbf, 0x004e00, 0x009ffc, 0x00fa0e, 0x00fa0f, 0x00fa11, 0x00fa11, 0x00fa13, 0x00fa14, 0x00fa1f, 0x00fa1f, 0x00fa21, - 0x00fa21, 0x00fa23, 0x00fa24, 0x00fa27, 0x00fa29, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x030000, 0x03134a)); + SET_ENCODINGS.put("UIdeo", CodePointSet.createNoDedup(0x003400, 0x004dbf, 0x004e00, 0x009fff, 0x00fa0e, 0x00fa0f, 0x00fa11, 0x00fa11, 0x00fa13, 0x00fa14, 0x00fa1f, 0x00fa1f, 0x00fa21, + 0x00fa21, 0x00fa23, 0x00fa24, 0x00fa27, 0x00fa29, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x030000, 0x03134a)); } private static void populateUPPER() { @@ -2343,7 +2389,7 @@ private static void populateUPPER() { 0x001f48, 0x001f4d, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f5f, 0x001f68, 0x001f6f, 0x001fb8, 0x001fbb, 0x001fc8, 0x001fcb, 0x001fd8, 0x001fdb, 0x001fe8, 0x001fec, 0x001ff8, 0x001ffb, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210b, 0x00210d, 0x002110, 0x002112, 0x002115, 0x002115, 0x002119, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x00212d, 0x002130, 0x002133, 0x00213e, 0x00213f, 0x002145, 0x002145, 0x002160, 0x00216f, 0x002183, - 0x002183, 0x0024b6, 0x0024cf, 0x002c00, 0x002c2e, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, 0x002c69, 0x002c69, 0x002c6b, 0x002c6b, 0x002c6d, 0x002c70, + 0x002183, 0x0024b6, 0x0024cf, 0x002c00, 0x002c2f, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, 0x002c69, 0x002c69, 0x002c6b, 0x002c6b, 0x002c6d, 0x002c70, 0x002c72, 0x002c72, 0x002c75, 0x002c75, 0x002c7e, 0x002c80, 0x002c82, 0x002c82, 0x002c84, 0x002c84, 0x002c86, 0x002c86, 0x002c88, 0x002c88, 0x002c8a, 0x002c8a, 0x002c8c, 0x002c8c, 0x002c8e, 0x002c8e, 0x002c90, 0x002c90, 0x002c92, 0x002c92, 0x002c94, 0x002c94, 0x002c96, 0x002c96, 0x002c98, 0x002c98, 0x002c9a, 0x002c9a, 0x002c9c, 0x002c9c, 0x002c9e, 0x002c9e, 0x002ca0, 0x002ca0, 0x002ca2, 0x002ca2, 0x002ca4, 0x002ca4, 0x002ca6, 0x002ca6, 0x002ca8, 0x002ca8, 0x002caa, 0x002caa, 0x002cac, 0x002cac, 0x002cae, @@ -2362,16 +2408,17 @@ private static void populateUPPER() { 0x00a76a, 0x00a76c, 0x00a76c, 0x00a76e, 0x00a76e, 0x00a779, 0x00a779, 0x00a77b, 0x00a77b, 0x00a77d, 0x00a77e, 0x00a780, 0x00a780, 0x00a782, 0x00a782, 0x00a784, 0x00a784, 0x00a786, 0x00a786, 0x00a78b, 0x00a78b, 0x00a78d, 0x00a78d, 0x00a790, 0x00a790, 0x00a792, 0x00a792, 0x00a796, 0x00a796, 0x00a798, 0x00a798, 0x00a79a, 0x00a79a, 0x00a79c, 0x00a79c, 0x00a79e, 0x00a79e, 0x00a7a0, 0x00a7a0, 0x00a7a2, 0x00a7a2, 0x00a7a4, 0x00a7a4, 0x00a7a6, 0x00a7a6, 0x00a7a8, 0x00a7a8, 0x00a7aa, 0x00a7ae, 0x00a7b0, 0x00a7b4, - 0x00a7b6, 0x00a7b6, 0x00a7b8, 0x00a7b8, 0x00a7ba, 0x00a7ba, 0x00a7bc, 0x00a7bc, 0x00a7be, 0x00a7be, 0x00a7c2, 0x00a7c2, 0x00a7c4, 0x00a7c7, 0x00a7c9, 0x00a7c9, 0x00a7f5, - 0x00a7f5, 0x00ff21, 0x00ff3a, 0x010400, 0x010427, 0x0104b0, 0x0104d3, 0x010c80, 0x010cb2, 0x0118a0, 0x0118bf, 0x016e40, 0x016e5f, 0x01d400, 0x01d419, 0x01d434, 0x01d44d, - 0x01d468, 0x01d481, 0x01d49c, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b5, 0x01d4d0, 0x01d4e9, 0x01d504, - 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d538, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, - 0x01d56c, 0x01d585, 0x01d5a0, 0x01d5b9, 0x01d5d4, 0x01d5ed, 0x01d608, 0x01d621, 0x01d63c, 0x01d655, 0x01d670, 0x01d689, 0x01d6a8, 0x01d6c0, 0x01d6e2, 0x01d6fa, 0x01d71c, - 0x01d734, 0x01d756, 0x01d76e, 0x01d790, 0x01d7a8, 0x01d7ca, 0x01d7ca, 0x01e900, 0x01e921, 0x01f130, 0x01f149, 0x01f150, 0x01f169, 0x01f170, 0x01f189)); + 0x00a7b6, 0x00a7b6, 0x00a7b8, 0x00a7b8, 0x00a7ba, 0x00a7ba, 0x00a7bc, 0x00a7bc, 0x00a7be, 0x00a7be, 0x00a7c0, 0x00a7c0, 0x00a7c2, 0x00a7c2, 0x00a7c4, 0x00a7c7, 0x00a7c9, + 0x00a7c9, 0x00a7d0, 0x00a7d0, 0x00a7d6, 0x00a7d6, 0x00a7d8, 0x00a7d8, 0x00a7f5, 0x00a7f5, 0x00ff21, 0x00ff3a, 0x010400, 0x010427, 0x0104b0, 0x0104d3, 0x010570, 0x01057a, + 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010c80, 0x010cb2, 0x0118a0, 0x0118bf, 0x016e40, 0x016e5f, 0x01d400, 0x01d419, 0x01d434, 0x01d44d, 0x01d468, + 0x01d481, 0x01d49c, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b5, 0x01d4d0, 0x01d4e9, 0x01d504, 0x01d505, + 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d538, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d56c, + 0x01d585, 0x01d5a0, 0x01d5b9, 0x01d5d4, 0x01d5ed, 0x01d608, 0x01d621, 0x01d63c, 0x01d655, 0x01d670, 0x01d689, 0x01d6a8, 0x01d6c0, 0x01d6e2, 0x01d6fa, 0x01d71c, 0x01d734, + 0x01d756, 0x01d76e, 0x01d790, 0x01d7a8, 0x01d7ca, 0x01d7ca, 0x01e900, 0x01e921, 0x01f130, 0x01f149, 0x01f150, 0x01f169, 0x01f170, 0x01f189)); } private static void populateVS() { - SET_ENCODINGS.put("VS", CodePointSet.createNoDedup(0x00180b, 0x00180d, 0x00fe00, 0x00fe0f, 0x0e0100, 0x0e01ef)); + SET_ENCODINGS.put("VS", CodePointSet.createNoDedup(0x00180b, 0x00180d, 0x00180f, 0x00180f, 0x00fe00, 0x00fe0f, 0x0e0100, 0x0e01ef)); } private static void populateWSPACE() { @@ -2386,7 +2433,7 @@ private static void populateXIDC() { 0x000483, 0x000487, 0x00048a, 0x00052f, 0x000531, 0x000556, 0x000559, 0x000559, 0x000560, 0x000588, 0x000591, 0x0005bd, 0x0005bf, 0x0005bf, 0x0005c1, 0x0005c2, 0x0005c4, 0x0005c5, 0x0005c7, 0x0005c7, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f2, 0x000610, 0x00061a, 0x000620, 0x000669, 0x00066e, 0x0006d3, 0x0006d5, 0x0006dc, 0x0006df, 0x0006e8, 0x0006ea, 0x0006fc, 0x0006ff, 0x0006ff, 0x000710, 0x00074a, 0x00074d, 0x0007b1, 0x0007c0, 0x0007f5, 0x0007fa, 0x0007fa, 0x0007fd, 0x0007fd, 0x000800, 0x00082d, 0x000840, - 0x00085b, 0x000860, 0x00086a, 0x0008a0, 0x0008b4, 0x0008b6, 0x0008c7, 0x0008d3, 0x0008e1, 0x0008e3, 0x000963, 0x000966, 0x00096f, 0x000971, 0x000983, 0x000985, 0x00098c, + 0x00085b, 0x000860, 0x00086a, 0x000870, 0x000887, 0x000889, 0x00088e, 0x000898, 0x0008e1, 0x0008e3, 0x000963, 0x000966, 0x00096f, 0x000971, 0x000983, 0x000985, 0x00098c, 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bc, 0x0009c4, 0x0009c7, 0x0009c8, 0x0009cb, 0x0009ce, 0x0009d7, 0x0009d7, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e3, 0x0009e6, 0x0009f1, 0x0009fc, 0x0009fc, 0x0009fe, 0x0009fe, 0x000a01, 0x000a03, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, 0x000a38, 0x000a39, 0x000a3c, 0x000a3c, 0x000a3e, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, @@ -2396,77 +2443,80 @@ private static void populateXIDC() { 0x000b3c, 0x000b44, 0x000b47, 0x000b48, 0x000b4b, 0x000b4d, 0x000b55, 0x000b57, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b63, 0x000b66, 0x000b6f, 0x000b71, 0x000b71, 0x000b82, 0x000b83, 0x000b85, 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bbe, 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcd, 0x000bd0, 0x000bd0, 0x000bd7, 0x000bd7, 0x000be6, 0x000bef, 0x000c00, 0x000c0c, 0x000c0e, - 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c60, 0x000c63, - 0x000c66, 0x000c6f, 0x000c80, 0x000c83, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbc, 0x000cc4, 0x000cc6, - 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000cde, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x000d00, 0x000d0c, 0x000d0e, 0x000d10, - 0x000d12, 0x000d44, 0x000d46, 0x000d48, 0x000d4a, 0x000d4e, 0x000d54, 0x000d57, 0x000d5f, 0x000d63, 0x000d66, 0x000d6f, 0x000d7a, 0x000d7f, 0x000d81, 0x000d83, 0x000d85, - 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000dca, 0x000dca, 0x000dcf, 0x000dd4, 0x000dd6, 0x000dd6, 0x000dd8, 0x000ddf, - 0x000de6, 0x000def, 0x000df2, 0x000df3, 0x000e01, 0x000e3a, 0x000e40, 0x000e4e, 0x000e50, 0x000e59, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, - 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000ec8, 0x000ecd, 0x000ed0, 0x000ed9, 0x000edc, 0x000edf, 0x000f00, 0x000f00, - 0x000f18, 0x000f19, 0x000f20, 0x000f29, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f3e, 0x000f47, 0x000f49, 0x000f6c, 0x000f71, 0x000f84, 0x000f86, - 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x001000, 0x001049, 0x001050, 0x00109d, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x0010fa, - 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, - 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x00135d, 0x00135f, - 0x001369, 0x001371, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, 0x0016a0, 0x0016ea, 0x0016ee, - 0x0016f8, 0x001700, 0x00170c, 0x00170e, 0x001714, 0x001720, 0x001734, 0x001740, 0x001753, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001772, 0x001773, 0x001780, 0x0017d3, - 0x0017d7, 0x0017d7, 0x0017dc, 0x0017dd, 0x0017e0, 0x0017e9, 0x00180b, 0x00180d, 0x001810, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, + 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3c, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, + 0x000c60, 0x000c63, 0x000c66, 0x000c6f, 0x000c80, 0x000c83, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbc, + 0x000cc4, 0x000cc6, 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000cdd, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x000d00, 0x000d0c, + 0x000d0e, 0x000d10, 0x000d12, 0x000d44, 0x000d46, 0x000d48, 0x000d4a, 0x000d4e, 0x000d54, 0x000d57, 0x000d5f, 0x000d63, 0x000d66, 0x000d6f, 0x000d7a, 0x000d7f, 0x000d81, + 0x000d83, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000dca, 0x000dca, 0x000dcf, 0x000dd4, 0x000dd6, 0x000dd6, + 0x000dd8, 0x000ddf, 0x000de6, 0x000def, 0x000df2, 0x000df3, 0x000e01, 0x000e3a, 0x000e40, 0x000e4e, 0x000e50, 0x000e59, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, + 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000ec8, 0x000ecd, 0x000ed0, 0x000ed9, 0x000edc, 0x000edf, + 0x000f00, 0x000f00, 0x000f18, 0x000f19, 0x000f20, 0x000f29, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f3e, 0x000f47, 0x000f49, 0x000f6c, 0x000f71, + 0x000f84, 0x000f86, 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x001000, 0x001049, 0x001050, 0x00109d, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, + 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, + 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, + 0x00135d, 0x00135f, 0x001369, 0x001371, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, 0x0016a0, + 0x0016ea, 0x0016ee, 0x0016f8, 0x001700, 0x001715, 0x00171f, 0x001734, 0x001740, 0x001753, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001772, 0x001773, 0x001780, 0x0017d3, + 0x0017d7, 0x0017d7, 0x0017dc, 0x0017dd, 0x0017e0, 0x0017e9, 0x00180b, 0x00180d, 0x00180f, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001920, 0x00192b, 0x001930, 0x00193b, 0x001946, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x0019d0, 0x0019da, 0x001a00, 0x001a1b, - 0x001a20, 0x001a5e, 0x001a60, 0x001a7c, 0x001a7f, 0x001a89, 0x001a90, 0x001a99, 0x001aa7, 0x001aa7, 0x001ab0, 0x001abd, 0x001abf, 0x001ac0, 0x001b00, 0x001b4b, 0x001b50, + 0x001a20, 0x001a5e, 0x001a60, 0x001a7c, 0x001a7f, 0x001a89, 0x001a90, 0x001a99, 0x001aa7, 0x001aa7, 0x001ab0, 0x001abd, 0x001abf, 0x001ace, 0x001b00, 0x001b4c, 0x001b50, 0x001b59, 0x001b6b, 0x001b73, 0x001b80, 0x001bf3, 0x001c00, 0x001c37, 0x001c40, 0x001c49, 0x001c4d, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cbf, - 0x001cd0, 0x001cd2, 0x001cd4, 0x001cfa, 0x001d00, 0x001df9, 0x001dfb, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, - 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, - 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x00203f, 0x002040, 0x002054, 0x002054, 0x002071, 0x002071, 0x00207f, - 0x00207f, 0x002090, 0x00209c, 0x0020d0, 0x0020dc, 0x0020e1, 0x0020e1, 0x0020e5, 0x0020f0, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, - 0x002118, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, - 0x002188, 0x002c00, 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002ce4, 0x002ceb, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, - 0x002d6f, 0x002d6f, 0x002d7f, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, - 0x002dd6, 0x002dd8, 0x002dde, 0x002de0, 0x002dff, 0x003005, 0x003007, 0x003021, 0x00302f, 0x003031, 0x003035, 0x003038, 0x00303c, 0x003041, 0x003096, 0x003099, 0x00309a, - 0x00309d, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, - 0x009ffc, 0x00a000, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a62b, 0x00a640, 0x00a66f, 0x00a674, 0x00a67d, 0x00a67f, 0x00a6f1, 0x00a717, 0x00a71f, - 0x00a722, 0x00a788, 0x00a78b, 0x00a7bf, 0x00a7c2, 0x00a7ca, 0x00a7f5, 0x00a827, 0x00a82c, 0x00a82c, 0x00a840, 0x00a873, 0x00a880, 0x00a8c5, 0x00a8d0, 0x00a8d9, 0x00a8e0, - 0x00a8f7, 0x00a8fb, 0x00a8fb, 0x00a8fd, 0x00a92d, 0x00a930, 0x00a953, 0x00a960, 0x00a97c, 0x00a980, 0x00a9c0, 0x00a9cf, 0x00a9d9, 0x00a9e0, 0x00a9fe, 0x00aa00, 0x00aa36, - 0x00aa40, 0x00aa4d, 0x00aa50, 0x00aa59, 0x00aa60, 0x00aa76, 0x00aa7a, 0x00aac2, 0x00aadb, 0x00aadd, 0x00aae0, 0x00aaef, 0x00aaf2, 0x00aaf6, 0x00ab01, 0x00ab06, 0x00ab09, - 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, 0x00ab2e, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab69, 0x00ab70, 0x00abea, 0x00abec, 0x00abed, 0x00abf0, 0x00abf9, - 0x00ac00, 0x00d7a3, 0x00d7b0, 0x00d7c6, 0x00d7cb, 0x00d7fb, 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb28, 0x00fb2a, - 0x00fb36, 0x00fb38, 0x00fb3c, 0x00fb3e, 0x00fb3e, 0x00fb40, 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbb1, 0x00fbd3, 0x00fc5d, 0x00fc64, 0x00fd3d, 0x00fd50, 0x00fd8f, - 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdf9, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2f, 0x00fe33, 0x00fe34, 0x00fe4d, 0x00fe4f, 0x00fe71, 0x00fe71, 0x00fe73, 0x00fe73, 0x00fe77, - 0x00fe77, 0x00fe79, 0x00fe79, 0x00fe7b, 0x00fe7b, 0x00fe7d, 0x00fe7d, 0x00fe7f, 0x00fefc, 0x00ff10, 0x00ff19, 0x00ff21, 0x00ff3a, 0x00ff3f, 0x00ff3f, 0x00ff41, 0x00ff5a, - 0x00ff66, 0x00ffbe, 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, 0x01003c, - 0x01003d, 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010140, 0x010174, 0x0101fd, 0x0101fd, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x0102e0, 0x0102e0, - 0x010300, 0x01031f, 0x01032d, 0x01034a, 0x010350, 0x01037a, 0x010380, 0x01039d, 0x0103a0, 0x0103c3, 0x0103c8, 0x0103cf, 0x0103d1, 0x0103d5, 0x010400, 0x01049d, 0x0104a0, - 0x0104a9, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010800, 0x010805, - 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, - 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a13, 0x010a15, 0x010a17, - 0x010a19, 0x010a35, 0x010a38, 0x010a3a, 0x010a3f, 0x010a3f, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae6, 0x010b00, 0x010b35, 0x010b40, - 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010d00, 0x010d27, 0x010d30, 0x010d39, 0x010e80, 0x010ea9, - 0x010eab, 0x010eac, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f50, 0x010fb0, 0x010fc4, 0x010fe0, 0x010ff6, 0x011000, 0x011046, 0x011066, - 0x01106f, 0x01107f, 0x0110ba, 0x0110d0, 0x0110e8, 0x0110f0, 0x0110f9, 0x011100, 0x011134, 0x011136, 0x01113f, 0x011144, 0x011147, 0x011150, 0x011173, 0x011176, 0x011176, - 0x011180, 0x0111c4, 0x0111c9, 0x0111cc, 0x0111ce, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x011237, 0x01123e, 0x01123e, 0x011280, 0x011286, 0x011288, - 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112ea, 0x0112f0, 0x0112f9, 0x011300, 0x011303, 0x011305, 0x01130c, 0x01130f, 0x011310, - 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133b, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, 0x011350, 0x011350, 0x011357, - 0x011357, 0x01135d, 0x011363, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011400, 0x01144a, 0x011450, 0x011459, 0x01145e, 0x011461, 0x011480, 0x0114c5, 0x0114c7, 0x0114c7, - 0x0114d0, 0x0114d9, 0x011580, 0x0115b5, 0x0115b8, 0x0115c0, 0x0115d8, 0x0115dd, 0x011600, 0x011640, 0x011644, 0x011644, 0x011650, 0x011659, 0x011680, 0x0116b8, 0x0116c0, - 0x0116c9, 0x011700, 0x01171a, 0x01171d, 0x01172b, 0x011730, 0x011739, 0x011800, 0x01183a, 0x0118a0, 0x0118e9, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, - 0x011915, 0x011916, 0x011918, 0x011935, 0x011937, 0x011938, 0x01193b, 0x011943, 0x011950, 0x011959, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d7, 0x0119da, 0x0119e1, 0x0119e3, - 0x0119e4, 0x011a00, 0x011a3e, 0x011a47, 0x011a47, 0x011a50, 0x011a99, 0x011a9d, 0x011a9d, 0x011ac0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c36, 0x011c38, 0x011c40, - 0x011c50, 0x011c59, 0x011c72, 0x011c8f, 0x011c92, 0x011ca7, 0x011ca9, 0x011cb6, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, - 0x011d3d, 0x011d3f, 0x011d47, 0x011d50, 0x011d59, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d8e, 0x011d90, 0x011d91, 0x011d93, 0x011d98, 0x011da0, 0x011da9, - 0x011ee0, 0x011ef6, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012400, 0x01246e, 0x012480, 0x012543, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, - 0x016a5e, 0x016a60, 0x016a69, 0x016ad0, 0x016aed, 0x016af0, 0x016af4, 0x016b00, 0x016b36, 0x016b40, 0x016b43, 0x016b50, 0x016b59, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, - 0x016e40, 0x016e7f, 0x016f00, 0x016f4a, 0x016f4f, 0x016f87, 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe4, 0x016ff0, 0x016ff1, 0x017000, 0x0187f7, 0x018800, - 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b11e, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, - 0x01bc90, 0x01bc99, 0x01bc9d, 0x01bc9e, 0x01d165, 0x01d169, 0x01d16d, 0x01d172, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, 0x01d244, 0x01d400, - 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, - 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, - 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, - 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01d7ce, 0x01d7ff, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, 0x01da75, 0x01da75, 0x01da84, - 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e100, 0x01e12c, - 0x01e130, 0x01e13d, 0x01e140, 0x01e149, 0x01e14e, 0x01e14e, 0x01e2c0, 0x01e2f9, 0x01e800, 0x01e8c4, 0x01e8d0, 0x01e8d6, 0x01e900, 0x01e94b, 0x01e950, 0x01e959, 0x01ee00, - 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, - 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, - 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, - 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x01fbf0, 0x01fbf9, 0x020000, - 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a, 0x0e0100, 0x0e01ef)); + 0x001cd0, 0x001cd2, 0x001cd4, 0x001cfa, 0x001d00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, 0x001f59, 0x001f5b, + 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, + 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x00203f, 0x002040, 0x002054, 0x002054, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, + 0x00209c, 0x0020d0, 0x0020dc, 0x0020e1, 0x0020e1, 0x0020e5, 0x0020f0, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002118, 0x00211d, + 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c00, + 0x002ce4, 0x002ceb, 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d6f, 0x002d7f, 0x002d96, 0x002da0, 0x002da6, + 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x002de0, 0x002dff, 0x003005, + 0x003007, 0x003021, 0x00302f, 0x003031, 0x003035, 0x003038, 0x00303c, 0x003041, 0x003096, 0x003099, 0x00309a, 0x00309d, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, + 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, + 0x00a62b, 0x00a640, 0x00a66f, 0x00a674, 0x00a67d, 0x00a67f, 0x00a6f1, 0x00a717, 0x00a71f, 0x00a722, 0x00a788, 0x00a78b, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, + 0x00a7d5, 0x00a7d9, 0x00a7f2, 0x00a827, 0x00a82c, 0x00a82c, 0x00a840, 0x00a873, 0x00a880, 0x00a8c5, 0x00a8d0, 0x00a8d9, 0x00a8e0, 0x00a8f7, 0x00a8fb, 0x00a8fb, 0x00a8fd, + 0x00a92d, 0x00a930, 0x00a953, 0x00a960, 0x00a97c, 0x00a980, 0x00a9c0, 0x00a9cf, 0x00a9d9, 0x00a9e0, 0x00a9fe, 0x00aa00, 0x00aa36, 0x00aa40, 0x00aa4d, 0x00aa50, 0x00aa59, + 0x00aa60, 0x00aa76, 0x00aa7a, 0x00aac2, 0x00aadb, 0x00aadd, 0x00aae0, 0x00aaef, 0x00aaf2, 0x00aaf6, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, + 0x00ab26, 0x00ab28, 0x00ab2e, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab69, 0x00ab70, 0x00abea, 0x00abec, 0x00abed, 0x00abf0, 0x00abf9, 0x00ac00, 0x00d7a3, 0x00d7b0, 0x00d7c6, + 0x00d7cb, 0x00d7fb, 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00fb1d, 0x00fb28, 0x00fb2a, 0x00fb36, 0x00fb38, 0x00fb3c, 0x00fb3e, + 0x00fb3e, 0x00fb40, 0x00fb41, 0x00fb43, 0x00fb44, 0x00fb46, 0x00fbb1, 0x00fbd3, 0x00fc5d, 0x00fc64, 0x00fd3d, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdf9, + 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2f, 0x00fe33, 0x00fe34, 0x00fe4d, 0x00fe4f, 0x00fe71, 0x00fe71, 0x00fe73, 0x00fe73, 0x00fe77, 0x00fe77, 0x00fe79, 0x00fe79, 0x00fe7b, + 0x00fe7b, 0x00fe7d, 0x00fe7d, 0x00fe7f, 0x00fefc, 0x00ff10, 0x00ff19, 0x00ff21, 0x00ff3a, 0x00ff3f, 0x00ff3f, 0x00ff41, 0x00ff5a, 0x00ff66, 0x00ffbe, 0x00ffc2, 0x00ffc7, + 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, 0x01003c, 0x01003d, 0x01003f, 0x01004d, 0x010050, + 0x01005d, 0x010080, 0x0100fa, 0x010140, 0x010174, 0x0101fd, 0x0101fd, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x0102e0, 0x0102e0, 0x010300, 0x01031f, 0x01032d, 0x01034a, + 0x010350, 0x01037a, 0x010380, 0x01039d, 0x0103a0, 0x0103c3, 0x0103c8, 0x0103cf, 0x0103d1, 0x0103d5, 0x010400, 0x01049d, 0x0104a0, 0x0104a9, 0x0104b0, 0x0104d3, 0x0104d8, + 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, + 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x010800, + 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, + 0x0108f4, 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a13, 0x010a15, + 0x010a17, 0x010a19, 0x010a35, 0x010a38, 0x010a3a, 0x010a3f, 0x010a3f, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae6, 0x010b00, 0x010b35, + 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010d00, 0x010d27, 0x010d30, 0x010d39, 0x010e80, + 0x010ea9, 0x010eab, 0x010eac, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f50, 0x010f70, 0x010f85, 0x010fb0, 0x010fc4, 0x010fe0, 0x010ff6, + 0x011000, 0x011046, 0x011066, 0x011075, 0x01107f, 0x0110ba, 0x0110c2, 0x0110c2, 0x0110d0, 0x0110e8, 0x0110f0, 0x0110f9, 0x011100, 0x011134, 0x011136, 0x01113f, 0x011144, + 0x011147, 0x011150, 0x011173, 0x011176, 0x011176, 0x011180, 0x0111c4, 0x0111c9, 0x0111cc, 0x0111ce, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x011237, + 0x01123e, 0x01123e, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112ea, 0x0112f0, 0x0112f9, 0x011300, + 0x011303, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133b, 0x011344, 0x011347, 0x011348, + 0x01134b, 0x01134d, 0x011350, 0x011350, 0x011357, 0x011357, 0x01135d, 0x011363, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011400, 0x01144a, 0x011450, 0x011459, 0x01145e, + 0x011461, 0x011480, 0x0114c5, 0x0114c7, 0x0114c7, 0x0114d0, 0x0114d9, 0x011580, 0x0115b5, 0x0115b8, 0x0115c0, 0x0115d8, 0x0115dd, 0x011600, 0x011640, 0x011644, 0x011644, + 0x011650, 0x011659, 0x011680, 0x0116b8, 0x0116c0, 0x0116c9, 0x011700, 0x01171a, 0x01171d, 0x01172b, 0x011730, 0x011739, 0x011740, 0x011746, 0x011800, 0x01183a, 0x0118a0, + 0x0118e9, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x011935, 0x011937, 0x011938, 0x01193b, 0x011943, 0x011950, 0x011959, + 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d7, 0x0119da, 0x0119e1, 0x0119e3, 0x0119e4, 0x011a00, 0x011a3e, 0x011a47, 0x011a47, 0x011a50, 0x011a99, 0x011a9d, 0x011a9d, 0x011ab0, + 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c36, 0x011c38, 0x011c40, 0x011c50, 0x011c59, 0x011c72, 0x011c8f, 0x011c92, 0x011ca7, 0x011ca9, 0x011cb6, 0x011d00, 0x011d06, + 0x011d08, 0x011d09, 0x011d0b, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d47, 0x011d50, 0x011d59, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, + 0x011d8e, 0x011d90, 0x011d91, 0x011d93, 0x011d98, 0x011da0, 0x011da9, 0x011ee0, 0x011ef6, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012400, 0x01246e, 0x012480, 0x012543, + 0x012f90, 0x012ff0, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016a60, 0x016a69, 0x016a70, 0x016abe, 0x016ac0, 0x016ac9, 0x016ad0, + 0x016aed, 0x016af0, 0x016af4, 0x016b00, 0x016b36, 0x016b40, 0x016b43, 0x016b50, 0x016b59, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e7f, 0x016f00, 0x016f4a, + 0x016f4f, 0x016f87, 0x016f8f, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe4, 0x016ff0, 0x016ff1, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01aff0, + 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01b000, 0x01b122, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, + 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01bc9d, 0x01bc9e, 0x01cf00, 0x01cf2d, 0x01cf30, 0x01cf46, 0x01d165, 0x01d169, 0x01d16d, 0x01d172, 0x01d17b, 0x01d182, 0x01d185, + 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, 0x01d244, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, + 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, + 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, + 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01d7ce, 0x01d7ff, 0x01da00, + 0x01da36, 0x01da3b, 0x01da6c, 0x01da75, 0x01da75, 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01df00, 0x01df1e, 0x01e000, 0x01e006, 0x01e008, 0x01e018, + 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a, 0x01e100, 0x01e12c, 0x01e130, 0x01e13d, 0x01e140, 0x01e149, 0x01e14e, 0x01e14e, 0x01e290, 0x01e2ae, 0x01e2c0, + 0x01e2f9, 0x01e7e0, 0x01e7e6, 0x01e7e8, 0x01e7eb, 0x01e7ed, 0x01e7ee, 0x01e7f0, 0x01e7fe, 0x01e800, 0x01e8c4, 0x01e8d0, 0x01e8d6, 0x01e900, 0x01e94b, 0x01e950, 0x01e959, + 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, + 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, + 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, + 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x01fbf0, 0x01fbf9, + 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a, 0x0e0100, 0x0e01ef)); } private static void populateXIDS() { @@ -2475,38 +2525,38 @@ private static void populateXIDS() { 0x00037f, 0x000386, 0x000386, 0x000388, 0x00038a, 0x00038c, 0x00038c, 0x00038e, 0x0003a1, 0x0003a3, 0x0003f5, 0x0003f7, 0x000481, 0x00048a, 0x00052f, 0x000531, 0x000556, 0x000559, 0x000559, 0x000560, 0x000588, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f2, 0x000620, 0x00064a, 0x00066e, 0x00066f, 0x000671, 0x0006d3, 0x0006d5, 0x0006d5, 0x0006e5, 0x0006e6, 0x0006ee, 0x0006ef, 0x0006fa, 0x0006fc, 0x0006ff, 0x0006ff, 0x000710, 0x000710, 0x000712, 0x00072f, 0x00074d, 0x0007a5, 0x0007b1, 0x0007b1, 0x0007ca, 0x0007ea, - 0x0007f4, 0x0007f5, 0x0007fa, 0x0007fa, 0x000800, 0x000815, 0x00081a, 0x00081a, 0x000824, 0x000824, 0x000828, 0x000828, 0x000840, 0x000858, 0x000860, 0x00086a, 0x0008a0, - 0x0008b4, 0x0008b6, 0x0008c7, 0x000904, 0x000939, 0x00093d, 0x00093d, 0x000950, 0x000950, 0x000958, 0x000961, 0x000971, 0x000980, 0x000985, 0x00098c, 0x00098f, 0x000990, - 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009bd, 0x0009ce, 0x0009ce, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e1, 0x0009f0, - 0x0009f1, 0x0009fc, 0x0009fc, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, 0x000a38, 0x000a39, - 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a72, 0x000a74, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, 0x000ab3, 0x000ab5, - 0x000ab9, 0x000abd, 0x000abd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae1, 0x000af9, 0x000af9, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, 0x000b2a, 0x000b30, - 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b3d, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b61, 0x000b71, 0x000b71, 0x000b83, 0x000b83, 0x000b85, 0x000b8a, 0x000b8e, - 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bd0, 0x000bd0, - 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c58, 0x000c5a, 0x000c60, 0x000c61, 0x000c80, 0x000c80, 0x000c85, - 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbd, 0x000cde, 0x000cde, 0x000ce0, 0x000ce1, 0x000cf1, 0x000cf2, - 0x000d04, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d4e, 0x000d4e, 0x000d54, 0x000d56, 0x000d5f, 0x000d61, 0x000d7a, 0x000d7f, 0x000d85, - 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000e01, 0x000e30, 0x000e32, 0x000e32, 0x000e40, 0x000e46, 0x000e81, 0x000e82, - 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb2, 0x000ebd, 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, - 0x000ec6, 0x000edc, 0x000edf, 0x000f00, 0x000f00, 0x000f40, 0x000f47, 0x000f49, 0x000f6c, 0x000f88, 0x000f8c, 0x001000, 0x00102a, 0x00103f, 0x00103f, 0x001050, 0x001055, - 0x00105a, 0x00105d, 0x001061, 0x001061, 0x001065, 0x001066, 0x00106e, 0x001070, 0x001075, 0x001081, 0x00108e, 0x00108e, 0x0010a0, 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, - 0x0010cd, 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, - 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, - 0x00135a, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, 0x0016a0, 0x0016ea, 0x0016ee, 0x0016f8, - 0x001700, 0x00170c, 0x00170e, 0x001711, 0x001720, 0x001731, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001780, 0x0017b3, 0x0017d7, 0x0017d7, 0x0017dc, - 0x0017dc, 0x001820, 0x001878, 0x001880, 0x0018a8, 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001950, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, - 0x0019b0, 0x0019c9, 0x001a00, 0x001a16, 0x001a20, 0x001a54, 0x001aa7, 0x001aa7, 0x001b05, 0x001b33, 0x001b45, 0x001b4b, 0x001b83, 0x001ba0, 0x001bae, 0x001baf, 0x001bba, - 0x001be5, 0x001c00, 0x001c23, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cbf, 0x001ce9, 0x001cec, 0x001cee, 0x001cf3, - 0x001cf5, 0x001cf6, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, 0x001e00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, 0x001f57, 0x001f59, - 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fcc, - 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x002102, - 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002118, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x002139, - 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c00, 0x002c2e, 0x002c30, 0x002c5e, 0x002c60, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, - 0x002cf3, 0x002d00, 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d6f, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, - 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x003005, 0x003007, 0x003021, 0x003029, 0x003031, - 0x003035, 0x003038, 0x00303c, 0x003041, 0x003096, 0x00309d, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, - 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, 0x009ffc, 0x00a000, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a61f, 0x00a62a, 0x00a62b, 0x00a640, - 0x00a66e, 0x00a67f, 0x00a69d, 0x00a6a0, 0x00a6ef, 0x00a717, 0x00a71f, 0x00a722, 0x00a788, 0x00a78b, 0x00a7bf, 0x00a7c2, 0x00a7ca, 0x00a7f5, 0x00a801, 0x00a803, 0x00a805, + 0x0007f4, 0x0007f5, 0x0007fa, 0x0007fa, 0x000800, 0x000815, 0x00081a, 0x00081a, 0x000824, 0x000824, 0x000828, 0x000828, 0x000840, 0x000858, 0x000860, 0x00086a, 0x000870, + 0x000887, 0x000889, 0x00088e, 0x0008a0, 0x0008c9, 0x000904, 0x000939, 0x00093d, 0x00093d, 0x000950, 0x000950, 0x000958, 0x000961, 0x000971, 0x000980, 0x000985, 0x00098c, + 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009bd, 0x0009ce, 0x0009ce, 0x0009dc, 0x0009dd, 0x0009df, + 0x0009e1, 0x0009f0, 0x0009f1, 0x0009fc, 0x0009fc, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, + 0x000a38, 0x000a39, 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a72, 0x000a74, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, + 0x000ab3, 0x000ab5, 0x000ab9, 0x000abd, 0x000abd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae1, 0x000af9, 0x000af9, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, + 0x000b2a, 0x000b30, 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b3d, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b61, 0x000b71, 0x000b71, 0x000b83, 0x000b83, 0x000b85, + 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, + 0x000bd0, 0x000bd0, 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, 0x000c60, + 0x000c61, 0x000c80, 0x000c80, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbd, 0x000cdd, 0x000cde, + 0x000ce0, 0x000ce1, 0x000cf1, 0x000cf2, 0x000d04, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d4e, 0x000d4e, 0x000d54, 0x000d56, 0x000d5f, + 0x000d61, 0x000d7a, 0x000d7f, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000e01, 0x000e30, 0x000e32, 0x000e32, + 0x000e40, 0x000e46, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb2, 0x000ebd, + 0x000ebd, 0x000ec0, 0x000ec4, 0x000ec6, 0x000ec6, 0x000edc, 0x000edf, 0x000f00, 0x000f00, 0x000f40, 0x000f47, 0x000f49, 0x000f6c, 0x000f88, 0x000f8c, 0x001000, 0x00102a, + 0x00103f, 0x00103f, 0x001050, 0x001055, 0x00105a, 0x00105d, 0x001061, 0x001061, 0x001065, 0x001066, 0x00106e, 0x001070, 0x001075, 0x001081, 0x00108e, 0x00108e, 0x0010a0, + 0x0010c5, 0x0010c7, 0x0010c7, 0x0010cd, 0x0010cd, 0x0010d0, 0x0010fa, 0x0010fc, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, + 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, + 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x001380, 0x00138f, 0x0013a0, 0x0013f5, 0x0013f8, 0x0013fd, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, + 0x0016a0, 0x0016ea, 0x0016ee, 0x0016f8, 0x001700, 0x001711, 0x00171f, 0x001731, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001780, 0x0017b3, 0x0017d7, + 0x0017d7, 0x0017dc, 0x0017dc, 0x001820, 0x001878, 0x001880, 0x0018a8, 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001950, 0x00196d, 0x001970, 0x001974, + 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x001a00, 0x001a16, 0x001a20, 0x001a54, 0x001aa7, 0x001aa7, 0x001b05, 0x001b33, 0x001b45, 0x001b4c, 0x001b83, 0x001ba0, 0x001bae, + 0x001baf, 0x001bba, 0x001be5, 0x001c00, 0x001c23, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c7d, 0x001c80, 0x001c88, 0x001c90, 0x001cba, 0x001cbd, 0x001cbf, 0x001ce9, 0x001cec, + 0x001cee, 0x001cf3, 0x001cf5, 0x001cf6, 0x001cfa, 0x001cfa, 0x001d00, 0x001dbf, 0x001e00, 0x001f15, 0x001f18, 0x001f1d, 0x001f20, 0x001f45, 0x001f48, 0x001f4d, 0x001f50, + 0x001f57, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f7d, 0x001f80, 0x001fb4, 0x001fb6, 0x001fbc, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, + 0x001fc6, 0x001fcc, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fdb, 0x001fe0, 0x001fec, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ffc, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, + 0x00209c, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210a, 0x002113, 0x002115, 0x002115, 0x002118, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, + 0x00212a, 0x002139, 0x00213c, 0x00213f, 0x002145, 0x002149, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c00, 0x002ce4, 0x002ceb, 0x002cee, 0x002cf2, 0x002cf3, 0x002d00, + 0x002d25, 0x002d27, 0x002d27, 0x002d2d, 0x002d2d, 0x002d30, 0x002d67, 0x002d6f, 0x002d6f, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, + 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x003005, 0x003007, 0x003021, 0x003029, 0x003031, 0x003035, 0x003038, + 0x00303c, 0x003041, 0x003096, 0x00309d, 0x00309f, 0x0030a1, 0x0030fa, 0x0030fc, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, + 0x003400, 0x004dbf, 0x004e00, 0x00a48c, 0x00a4d0, 0x00a4fd, 0x00a500, 0x00a60c, 0x00a610, 0x00a61f, 0x00a62a, 0x00a62b, 0x00a640, 0x00a66e, 0x00a67f, 0x00a69d, 0x00a6a0, + 0x00a6ef, 0x00a717, 0x00a71f, 0x00a722, 0x00a788, 0x00a78b, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, 0x00a7f2, 0x00a801, 0x00a803, 0x00a805, 0x00a807, 0x00a80a, 0x00a80c, 0x00a822, 0x00a840, 0x00a873, 0x00a882, 0x00a8b3, 0x00a8f2, 0x00a8f7, 0x00a8fb, 0x00a8fb, 0x00a8fd, 0x00a8fe, 0x00a90a, 0x00a925, 0x00a930, 0x00a946, 0x00a960, 0x00a97c, 0x00a984, 0x00a9b2, 0x00a9cf, 0x00a9cf, 0x00a9e0, 0x00a9e4, 0x00a9e6, 0x00a9ef, 0x00a9fa, 0x00a9fe, 0x00aa00, 0x00aa28, 0x00aa40, 0x00aa42, 0x00aa44, 0x00aa4b, 0x00aa60, 0x00aa76, 0x00aa7a, 0x00aa7a, 0x00aa7e, 0x00aaaf, 0x00aab1, 0x00aab1, 0x00aab5, 0x00aab6, 0x00aab9, 0x00aabd, 0x00aac0, 0x00aac0, 0x00aac2, @@ -2518,33 +2568,36 @@ private static void populateXIDS() { 0x00ffc2, 0x00ffc7, 0x00ffca, 0x00ffcf, 0x00ffd2, 0x00ffd7, 0x00ffda, 0x00ffdc, 0x010000, 0x01000b, 0x01000d, 0x010026, 0x010028, 0x01003a, 0x01003c, 0x01003d, 0x01003f, 0x01004d, 0x010050, 0x01005d, 0x010080, 0x0100fa, 0x010140, 0x010174, 0x010280, 0x01029c, 0x0102a0, 0x0102d0, 0x010300, 0x01031f, 0x01032d, 0x01034a, 0x010350, 0x010375, 0x010380, 0x01039d, 0x0103a0, 0x0103c3, 0x0103c8, 0x0103cf, 0x0103d1, 0x0103d5, 0x010400, 0x01049d, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, - 0x010563, 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, - 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, - 0x0109bf, 0x010a00, 0x010a00, 0x010a10, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae4, - 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x010d00, 0x010d23, 0x010e80, - 0x010ea9, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f45, 0x010fb0, 0x010fc4, 0x010fe0, 0x010ff6, 0x011003, 0x011037, 0x011083, 0x0110af, - 0x0110d0, 0x0110e8, 0x011103, 0x011126, 0x011144, 0x011144, 0x011147, 0x011147, 0x011150, 0x011172, 0x011176, 0x011176, 0x011183, 0x0111b2, 0x0111c1, 0x0111c4, 0x0111da, - 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x01122b, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, - 0x0112b0, 0x0112de, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133d, 0x01133d, 0x011350, - 0x011350, 0x01135d, 0x011361, 0x011400, 0x011434, 0x011447, 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114af, 0x0114c4, 0x0114c5, 0x0114c7, 0x0114c7, 0x011580, 0x0115ae, - 0x0115d8, 0x0115db, 0x011600, 0x01162f, 0x011644, 0x011644, 0x011680, 0x0116aa, 0x0116b8, 0x0116b8, 0x011700, 0x01171a, 0x011800, 0x01182b, 0x0118a0, 0x0118df, 0x0118ff, - 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x01192f, 0x01193f, 0x01193f, 0x011941, 0x011941, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d0, - 0x0119e1, 0x0119e1, 0x0119e3, 0x0119e3, 0x011a00, 0x011a00, 0x011a0b, 0x011a32, 0x011a3a, 0x011a3a, 0x011a50, 0x011a50, 0x011a5c, 0x011a89, 0x011a9d, 0x011a9d, 0x011ac0, - 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c2e, 0x011c40, 0x011c40, 0x011c72, 0x011c8f, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d30, 0x011d46, 0x011d46, - 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d89, 0x011d98, 0x011d98, 0x011ee0, 0x011ef2, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012400, 0x01246e, 0x012480, - 0x012543, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, 0x016b40, 0x016b43, 0x016b63, 0x016b77, + 0x010563, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, + 0x010600, 0x010736, 0x010740, 0x010755, 0x010760, 0x010767, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, + 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x010900, 0x010915, + 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a00, 0x010a10, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a60, 0x010a7c, 0x010a80, + 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae4, 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, 0x010c00, 0x010c48, 0x010c80, 0x010cb2, + 0x010cc0, 0x010cf2, 0x010d00, 0x010d23, 0x010e80, 0x010ea9, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f45, 0x010f70, 0x010f81, 0x010fb0, + 0x010fc4, 0x010fe0, 0x010ff6, 0x011003, 0x011037, 0x011071, 0x011072, 0x011075, 0x011075, 0x011083, 0x0110af, 0x0110d0, 0x0110e8, 0x011103, 0x011126, 0x011144, 0x011144, + 0x011147, 0x011147, 0x011150, 0x011172, 0x011176, 0x011176, 0x011183, 0x0111b2, 0x0111c1, 0x0111c4, 0x0111da, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, + 0x01122b, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112de, 0x011305, 0x01130c, 0x01130f, 0x011310, + 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133d, 0x01133d, 0x011350, 0x011350, 0x01135d, 0x011361, 0x011400, 0x011434, 0x011447, + 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114af, 0x0114c4, 0x0114c5, 0x0114c7, 0x0114c7, 0x011580, 0x0115ae, 0x0115d8, 0x0115db, 0x011600, 0x01162f, 0x011644, 0x011644, + 0x011680, 0x0116aa, 0x0116b8, 0x0116b8, 0x011700, 0x01171a, 0x011740, 0x011746, 0x011800, 0x01182b, 0x0118a0, 0x0118df, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, + 0x011913, 0x011915, 0x011916, 0x011918, 0x01192f, 0x01193f, 0x01193f, 0x011941, 0x011941, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d0, 0x0119e1, 0x0119e1, 0x0119e3, 0x0119e3, + 0x011a00, 0x011a00, 0x011a0b, 0x011a32, 0x011a3a, 0x011a3a, 0x011a50, 0x011a50, 0x011a5c, 0x011a89, 0x011a9d, 0x011a9d, 0x011ab0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, + 0x011c2e, 0x011c40, 0x011c40, 0x011c72, 0x011c8f, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d30, 0x011d46, 0x011d46, 0x011d60, 0x011d65, 0x011d67, 0x011d68, + 0x011d6a, 0x011d89, 0x011d98, 0x011d98, 0x011ee0, 0x011ef2, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012400, 0x01246e, 0x012480, 0x012543, 0x012f90, 0x012ff0, 0x013000, + 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016a70, 0x016abe, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, 0x016b40, 0x016b43, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016e40, 0x016e7f, 0x016f00, 0x016f4a, 0x016f50, 0x016f50, 0x016f93, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe3, 0x017000, 0x0187f7, 0x018800, - 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b11e, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, - 0x01bc90, 0x01bc99, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, - 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, - 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, - 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01e100, 0x01e12c, 0x01e137, 0x01e13d, 0x01e14e, 0x01e14e, - 0x01e2c0, 0x01e2eb, 0x01e800, 0x01e8c4, 0x01e900, 0x01e943, 0x01e94b, 0x01e94b, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, - 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, - 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, - 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, - 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, - 0x02fa1d, 0x030000, 0x03134a)); + 0x018cd5, 0x018d00, 0x018d08, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01b000, 0x01b122, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, + 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, + 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, + 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, + 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, + 0x01df00, 0x01df1e, 0x01e100, 0x01e12c, 0x01e137, 0x01e13d, 0x01e14e, 0x01e14e, 0x01e290, 0x01e2ad, 0x01e2c0, 0x01e2eb, 0x01e7e0, 0x01e7e6, 0x01e7e8, 0x01e7eb, 0x01e7ed, + 0x01e7ee, 0x01e7f0, 0x01e7fe, 0x01e800, 0x01e8c4, 0x01e900, 0x01e943, 0x01e94b, 0x01e94b, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, + 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, + 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, + 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, + 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, + 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); } private static void populateGC_CC() { @@ -2553,27 +2606,27 @@ private static void populateGC_CC() { private static void populateGC_CF() { SET_ENCODINGS.put("gc=Cf", - CodePointSet.createNoDedup(0x0000ad, 0x0000ad, 0x000600, 0x000605, 0x00061c, 0x00061c, 0x0006dd, 0x0006dd, 0x00070f, 0x00070f, 0x0008e2, 0x0008e2, 0x00180e, 0x00180e, 0x00200b, - 0x00200f, 0x00202a, 0x00202e, 0x002060, 0x002064, 0x002066, 0x00206f, 0x00feff, 0x00feff, 0x00fff9, 0x00fffb, 0x0110bd, 0x0110bd, 0x0110cd, 0x0110cd, 0x013430, - 0x013438, 0x01bca0, 0x01bca3, 0x01d173, 0x01d17a, 0x0e0001, 0x0e0001, 0x0e0020, 0x0e007f)); + CodePointSet.createNoDedup(0x0000ad, 0x0000ad, 0x000600, 0x000605, 0x00061c, 0x00061c, 0x0006dd, 0x0006dd, 0x00070f, 0x00070f, 0x000890, 0x000891, 0x0008e2, 0x0008e2, 0x00180e, + 0x00180e, 0x00200b, 0x00200f, 0x00202a, 0x00202e, 0x002060, 0x002064, 0x002066, 0x00206f, 0x00feff, 0x00feff, 0x00fff9, 0x00fffb, 0x0110bd, 0x0110bd, 0x0110cd, + 0x0110cd, 0x013430, 0x013438, 0x01bca0, 0x01bca3, 0x01d173, 0x01d17a, 0x0e0001, 0x0e0001, 0x0e0020, 0x0e007f)); } private static void populateGC_CN() { SET_ENCODINGS.put("gc=Cn", CodePointSet.createNoDedup(0x000378, 0x000379, 0x000380, 0x000383, 0x00038b, 0x00038b, 0x00038d, 0x00038d, 0x0003a2, 0x0003a2, 0x000530, 0x000530, 0x000557, - 0x000558, 0x00058b, 0x00058c, 0x000590, 0x000590, 0x0005c8, 0x0005cf, 0x0005eb, 0x0005ee, 0x0005f5, 0x0005ff, 0x00061d, 0x00061d, 0x00070e, 0x00070e, 0x00074b, 0x00074c, - 0x0007b2, 0x0007bf, 0x0007fb, 0x0007fc, 0x00082e, 0x00082f, 0x00083f, 0x00083f, 0x00085c, 0x00085d, 0x00085f, 0x00085f, 0x00086b, 0x00089f, 0x0008b5, 0x0008b5, 0x0008c8, - 0x0008d2, 0x000984, 0x000984, 0x00098d, 0x00098e, 0x000991, 0x000992, 0x0009a9, 0x0009a9, 0x0009b1, 0x0009b1, 0x0009b3, 0x0009b5, 0x0009ba, 0x0009bb, 0x0009c5, 0x0009c6, - 0x0009c9, 0x0009ca, 0x0009cf, 0x0009d6, 0x0009d8, 0x0009db, 0x0009de, 0x0009de, 0x0009e4, 0x0009e5, 0x0009ff, 0x000a00, 0x000a04, 0x000a04, 0x000a0b, 0x000a0e, 0x000a11, - 0x000a12, 0x000a29, 0x000a29, 0x000a31, 0x000a31, 0x000a34, 0x000a34, 0x000a37, 0x000a37, 0x000a3a, 0x000a3b, 0x000a3d, 0x000a3d, 0x000a43, 0x000a46, 0x000a49, 0x000a4a, - 0x000a4e, 0x000a50, 0x000a52, 0x000a58, 0x000a5d, 0x000a5d, 0x000a5f, 0x000a65, 0x000a77, 0x000a80, 0x000a84, 0x000a84, 0x000a8e, 0x000a8e, 0x000a92, 0x000a92, 0x000aa9, - 0x000aa9, 0x000ab1, 0x000ab1, 0x000ab4, 0x000ab4, 0x000aba, 0x000abb, 0x000ac6, 0x000ac6, 0x000aca, 0x000aca, 0x000ace, 0x000acf, 0x000ad1, 0x000adf, 0x000ae4, 0x000ae5, - 0x000af2, 0x000af8, 0x000b00, 0x000b00, 0x000b04, 0x000b04, 0x000b0d, 0x000b0e, 0x000b11, 0x000b12, 0x000b29, 0x000b29, 0x000b31, 0x000b31, 0x000b34, 0x000b34, 0x000b3a, - 0x000b3b, 0x000b45, 0x000b46, 0x000b49, 0x000b4a, 0x000b4e, 0x000b54, 0x000b58, 0x000b5b, 0x000b5e, 0x000b5e, 0x000b64, 0x000b65, 0x000b78, 0x000b81, 0x000b84, 0x000b84, - 0x000b8b, 0x000b8d, 0x000b91, 0x000b91, 0x000b96, 0x000b98, 0x000b9b, 0x000b9b, 0x000b9d, 0x000b9d, 0x000ba0, 0x000ba2, 0x000ba5, 0x000ba7, 0x000bab, 0x000bad, 0x000bba, - 0x000bbd, 0x000bc3, 0x000bc5, 0x000bc9, 0x000bc9, 0x000bce, 0x000bcf, 0x000bd1, 0x000bd6, 0x000bd8, 0x000be5, 0x000bfb, 0x000bff, 0x000c0d, 0x000c0d, 0x000c11, 0x000c11, - 0x000c29, 0x000c29, 0x000c3a, 0x000c3c, 0x000c45, 0x000c45, 0x000c49, 0x000c49, 0x000c4e, 0x000c54, 0x000c57, 0x000c57, 0x000c5b, 0x000c5f, 0x000c64, 0x000c65, 0x000c70, + 0x000558, 0x00058b, 0x00058c, 0x000590, 0x000590, 0x0005c8, 0x0005cf, 0x0005eb, 0x0005ee, 0x0005f5, 0x0005ff, 0x00070e, 0x00070e, 0x00074b, 0x00074c, 0x0007b2, 0x0007bf, + 0x0007fb, 0x0007fc, 0x00082e, 0x00082f, 0x00083f, 0x00083f, 0x00085c, 0x00085d, 0x00085f, 0x00085f, 0x00086b, 0x00086f, 0x00088f, 0x00088f, 0x000892, 0x000897, 0x000984, + 0x000984, 0x00098d, 0x00098e, 0x000991, 0x000992, 0x0009a9, 0x0009a9, 0x0009b1, 0x0009b1, 0x0009b3, 0x0009b5, 0x0009ba, 0x0009bb, 0x0009c5, 0x0009c6, 0x0009c9, 0x0009ca, + 0x0009cf, 0x0009d6, 0x0009d8, 0x0009db, 0x0009de, 0x0009de, 0x0009e4, 0x0009e5, 0x0009ff, 0x000a00, 0x000a04, 0x000a04, 0x000a0b, 0x000a0e, 0x000a11, 0x000a12, 0x000a29, + 0x000a29, 0x000a31, 0x000a31, 0x000a34, 0x000a34, 0x000a37, 0x000a37, 0x000a3a, 0x000a3b, 0x000a3d, 0x000a3d, 0x000a43, 0x000a46, 0x000a49, 0x000a4a, 0x000a4e, 0x000a50, + 0x000a52, 0x000a58, 0x000a5d, 0x000a5d, 0x000a5f, 0x000a65, 0x000a77, 0x000a80, 0x000a84, 0x000a84, 0x000a8e, 0x000a8e, 0x000a92, 0x000a92, 0x000aa9, 0x000aa9, 0x000ab1, + 0x000ab1, 0x000ab4, 0x000ab4, 0x000aba, 0x000abb, 0x000ac6, 0x000ac6, 0x000aca, 0x000aca, 0x000ace, 0x000acf, 0x000ad1, 0x000adf, 0x000ae4, 0x000ae5, 0x000af2, 0x000af8, + 0x000b00, 0x000b00, 0x000b04, 0x000b04, 0x000b0d, 0x000b0e, 0x000b11, 0x000b12, 0x000b29, 0x000b29, 0x000b31, 0x000b31, 0x000b34, 0x000b34, 0x000b3a, 0x000b3b, 0x000b45, + 0x000b46, 0x000b49, 0x000b4a, 0x000b4e, 0x000b54, 0x000b58, 0x000b5b, 0x000b5e, 0x000b5e, 0x000b64, 0x000b65, 0x000b78, 0x000b81, 0x000b84, 0x000b84, 0x000b8b, 0x000b8d, + 0x000b91, 0x000b91, 0x000b96, 0x000b98, 0x000b9b, 0x000b9b, 0x000b9d, 0x000b9d, 0x000ba0, 0x000ba2, 0x000ba5, 0x000ba7, 0x000bab, 0x000bad, 0x000bba, 0x000bbd, 0x000bc3, + 0x000bc5, 0x000bc9, 0x000bc9, 0x000bce, 0x000bcf, 0x000bd1, 0x000bd6, 0x000bd8, 0x000be5, 0x000bfb, 0x000bff, 0x000c0d, 0x000c0d, 0x000c11, 0x000c11, 0x000c29, 0x000c29, + 0x000c3a, 0x000c3b, 0x000c45, 0x000c45, 0x000c49, 0x000c49, 0x000c4e, 0x000c54, 0x000c57, 0x000c57, 0x000c5b, 0x000c5c, 0x000c5e, 0x000c5f, 0x000c64, 0x000c65, 0x000c70, 0x000c76, 0x000c8d, 0x000c8d, 0x000c91, 0x000c91, 0x000ca9, 0x000ca9, 0x000cb4, 0x000cb4, 0x000cba, 0x000cbb, 0x000cc5, 0x000cc5, 0x000cc9, 0x000cc9, 0x000cce, 0x000cd4, - 0x000cd7, 0x000cdd, 0x000cdf, 0x000cdf, 0x000ce4, 0x000ce5, 0x000cf0, 0x000cf0, 0x000cf3, 0x000cff, 0x000d0d, 0x000d0d, 0x000d11, 0x000d11, 0x000d45, 0x000d45, 0x000d49, + 0x000cd7, 0x000cdc, 0x000cdf, 0x000cdf, 0x000ce4, 0x000ce5, 0x000cf0, 0x000cf0, 0x000cf3, 0x000cff, 0x000d0d, 0x000d0d, 0x000d11, 0x000d11, 0x000d45, 0x000d45, 0x000d49, 0x000d49, 0x000d50, 0x000d53, 0x000d64, 0x000d65, 0x000d80, 0x000d80, 0x000d84, 0x000d84, 0x000d97, 0x000d99, 0x000db2, 0x000db2, 0x000dbc, 0x000dbc, 0x000dbe, 0x000dbf, 0x000dc7, 0x000dc9, 0x000dcb, 0x000dce, 0x000dd5, 0x000dd5, 0x000dd7, 0x000dd7, 0x000de0, 0x000de5, 0x000df0, 0x000df1, 0x000df5, 0x000e00, 0x000e3b, 0x000e3e, 0x000e5c, 0x000e80, 0x000e83, 0x000e83, 0x000e85, 0x000e85, 0x000e8b, 0x000e8b, 0x000ea4, 0x000ea4, 0x000ea6, 0x000ea6, 0x000ebe, 0x000ebf, 0x000ec5, 0x000ec5, 0x000ec7, 0x000ec7, @@ -2581,64 +2634,67 @@ private static void populateGC_CN() { 0x000fff, 0x0010c6, 0x0010c6, 0x0010c8, 0x0010cc, 0x0010ce, 0x0010cf, 0x001249, 0x001249, 0x00124e, 0x00124f, 0x001257, 0x001257, 0x001259, 0x001259, 0x00125e, 0x00125f, 0x001289, 0x001289, 0x00128e, 0x00128f, 0x0012b1, 0x0012b1, 0x0012b6, 0x0012b7, 0x0012bf, 0x0012bf, 0x0012c1, 0x0012c1, 0x0012c6, 0x0012c7, 0x0012d7, 0x0012d7, 0x001311, 0x001311, 0x001316, 0x001317, 0x00135b, 0x00135c, 0x00137d, 0x00137f, 0x00139a, 0x00139f, 0x0013f6, 0x0013f7, 0x0013fe, 0x0013ff, 0x00169d, 0x00169f, 0x0016f9, 0x0016ff, - 0x00170d, 0x00170d, 0x001715, 0x00171f, 0x001737, 0x00173f, 0x001754, 0x00175f, 0x00176d, 0x00176d, 0x001771, 0x001771, 0x001774, 0x00177f, 0x0017de, 0x0017df, 0x0017ea, - 0x0017ef, 0x0017fa, 0x0017ff, 0x00180f, 0x00180f, 0x00181a, 0x00181f, 0x001879, 0x00187f, 0x0018ab, 0x0018af, 0x0018f6, 0x0018ff, 0x00191f, 0x00191f, 0x00192c, 0x00192f, - 0x00193c, 0x00193f, 0x001941, 0x001943, 0x00196e, 0x00196f, 0x001975, 0x00197f, 0x0019ac, 0x0019af, 0x0019ca, 0x0019cf, 0x0019db, 0x0019dd, 0x001a1c, 0x001a1d, 0x001a5f, - 0x001a5f, 0x001a7d, 0x001a7e, 0x001a8a, 0x001a8f, 0x001a9a, 0x001a9f, 0x001aae, 0x001aaf, 0x001ac1, 0x001aff, 0x001b4c, 0x001b4f, 0x001b7d, 0x001b7f, 0x001bf4, 0x001bfb, - 0x001c38, 0x001c3a, 0x001c4a, 0x001c4c, 0x001c89, 0x001c8f, 0x001cbb, 0x001cbc, 0x001cc8, 0x001ccf, 0x001cfb, 0x001cff, 0x001dfa, 0x001dfa, 0x001f16, 0x001f17, 0x001f1e, - 0x001f1f, 0x001f46, 0x001f47, 0x001f4e, 0x001f4f, 0x001f58, 0x001f58, 0x001f5a, 0x001f5a, 0x001f5c, 0x001f5c, 0x001f5e, 0x001f5e, 0x001f7e, 0x001f7f, 0x001fb5, 0x001fb5, - 0x001fc5, 0x001fc5, 0x001fd4, 0x001fd5, 0x001fdc, 0x001fdc, 0x001ff0, 0x001ff1, 0x001ff5, 0x001ff5, 0x001fff, 0x001fff, 0x002065, 0x002065, 0x002072, 0x002073, 0x00208f, - 0x00208f, 0x00209d, 0x00209f, 0x0020c0, 0x0020cf, 0x0020f1, 0x0020ff, 0x00218c, 0x00218f, 0x002427, 0x00243f, 0x00244b, 0x00245f, 0x002b74, 0x002b75, 0x002b96, 0x002b96, - 0x002c2f, 0x002c2f, 0x002c5f, 0x002c5f, 0x002cf4, 0x002cf8, 0x002d26, 0x002d26, 0x002d28, 0x002d2c, 0x002d2e, 0x002d2f, 0x002d68, 0x002d6e, 0x002d71, 0x002d7e, 0x002d97, - 0x002d9f, 0x002da7, 0x002da7, 0x002daf, 0x002daf, 0x002db7, 0x002db7, 0x002dbf, 0x002dbf, 0x002dc7, 0x002dc7, 0x002dcf, 0x002dcf, 0x002dd7, 0x002dd7, 0x002ddf, 0x002ddf, - 0x002e53, 0x002e7f, 0x002e9a, 0x002e9a, 0x002ef4, 0x002eff, 0x002fd6, 0x002fef, 0x002ffc, 0x002fff, 0x003040, 0x003040, 0x003097, 0x003098, 0x003100, 0x003104, 0x003130, - 0x003130, 0x00318f, 0x00318f, 0x0031e4, 0x0031ef, 0x00321f, 0x00321f, 0x009ffd, 0x009fff, 0x00a48d, 0x00a48f, 0x00a4c7, 0x00a4cf, 0x00a62c, 0x00a63f, 0x00a6f8, 0x00a6ff, - 0x00a7c0, 0x00a7c1, 0x00a7cb, 0x00a7f4, 0x00a82d, 0x00a82f, 0x00a83a, 0x00a83f, 0x00a878, 0x00a87f, 0x00a8c6, 0x00a8cd, 0x00a8da, 0x00a8df, 0x00a954, 0x00a95e, 0x00a97d, - 0x00a97f, 0x00a9ce, 0x00a9ce, 0x00a9da, 0x00a9dd, 0x00a9ff, 0x00a9ff, 0x00aa37, 0x00aa3f, 0x00aa4e, 0x00aa4f, 0x00aa5a, 0x00aa5b, 0x00aac3, 0x00aada, 0x00aaf7, 0x00ab00, - 0x00ab07, 0x00ab08, 0x00ab0f, 0x00ab10, 0x00ab17, 0x00ab1f, 0x00ab27, 0x00ab27, 0x00ab2f, 0x00ab2f, 0x00ab6c, 0x00ab6f, 0x00abee, 0x00abef, 0x00abfa, 0x00abff, 0x00d7a4, - 0x00d7af, 0x00d7c7, 0x00d7ca, 0x00d7fc, 0x00d7ff, 0x00fa6e, 0x00fa6f, 0x00fada, 0x00faff, 0x00fb07, 0x00fb12, 0x00fb18, 0x00fb1c, 0x00fb37, 0x00fb37, 0x00fb3d, 0x00fb3d, - 0x00fb3f, 0x00fb3f, 0x00fb42, 0x00fb42, 0x00fb45, 0x00fb45, 0x00fbc2, 0x00fbd2, 0x00fd40, 0x00fd4f, 0x00fd90, 0x00fd91, 0x00fdc8, 0x00fdef, 0x00fdfe, 0x00fdff, 0x00fe1a, - 0x00fe1f, 0x00fe53, 0x00fe53, 0x00fe67, 0x00fe67, 0x00fe6c, 0x00fe6f, 0x00fe75, 0x00fe75, 0x00fefd, 0x00fefe, 0x00ff00, 0x00ff00, 0x00ffbf, 0x00ffc1, 0x00ffc8, 0x00ffc9, - 0x00ffd0, 0x00ffd1, 0x00ffd8, 0x00ffd9, 0x00ffdd, 0x00ffdf, 0x00ffe7, 0x00ffe7, 0x00ffef, 0x00fff8, 0x00fffe, 0x00ffff, 0x01000c, 0x01000c, 0x010027, 0x010027, 0x01003b, - 0x01003b, 0x01003e, 0x01003e, 0x01004e, 0x01004f, 0x01005e, 0x01007f, 0x0100fb, 0x0100ff, 0x010103, 0x010106, 0x010134, 0x010136, 0x01018f, 0x01018f, 0x01019d, 0x01019f, - 0x0101a1, 0x0101cf, 0x0101fe, 0x01027f, 0x01029d, 0x01029f, 0x0102d1, 0x0102df, 0x0102fc, 0x0102ff, 0x010324, 0x01032c, 0x01034b, 0x01034f, 0x01037b, 0x01037f, 0x01039e, - 0x01039e, 0x0103c4, 0x0103c7, 0x0103d6, 0x0103ff, 0x01049e, 0x01049f, 0x0104aa, 0x0104af, 0x0104d4, 0x0104d7, 0x0104fc, 0x0104ff, 0x010528, 0x01052f, 0x010564, 0x01056e, - 0x010570, 0x0105ff, 0x010737, 0x01073f, 0x010756, 0x01075f, 0x010768, 0x0107ff, 0x010806, 0x010807, 0x010809, 0x010809, 0x010836, 0x010836, 0x010839, 0x01083b, 0x01083d, - 0x01083e, 0x010856, 0x010856, 0x01089f, 0x0108a6, 0x0108b0, 0x0108df, 0x0108f3, 0x0108f3, 0x0108f6, 0x0108fa, 0x01091c, 0x01091e, 0x01093a, 0x01093e, 0x010940, 0x01097f, - 0x0109b8, 0x0109bb, 0x0109d0, 0x0109d1, 0x010a04, 0x010a04, 0x010a07, 0x010a0b, 0x010a14, 0x010a14, 0x010a18, 0x010a18, 0x010a36, 0x010a37, 0x010a3b, 0x010a3e, 0x010a49, - 0x010a4f, 0x010a59, 0x010a5f, 0x010aa0, 0x010abf, 0x010ae7, 0x010aea, 0x010af7, 0x010aff, 0x010b36, 0x010b38, 0x010b56, 0x010b57, 0x010b73, 0x010b77, 0x010b92, 0x010b98, - 0x010b9d, 0x010ba8, 0x010bb0, 0x010bff, 0x010c49, 0x010c7f, 0x010cb3, 0x010cbf, 0x010cf3, 0x010cf9, 0x010d28, 0x010d2f, 0x010d3a, 0x010e5f, 0x010e7f, 0x010e7f, 0x010eaa, - 0x010eaa, 0x010eae, 0x010eaf, 0x010eb2, 0x010eff, 0x010f28, 0x010f2f, 0x010f5a, 0x010faf, 0x010fcc, 0x010fdf, 0x010ff7, 0x010fff, 0x01104e, 0x011051, 0x011070, 0x01107e, - 0x0110c2, 0x0110cc, 0x0110ce, 0x0110cf, 0x0110e9, 0x0110ef, 0x0110fa, 0x0110ff, 0x011135, 0x011135, 0x011148, 0x01114f, 0x011177, 0x01117f, 0x0111e0, 0x0111e0, 0x0111f5, - 0x0111ff, 0x011212, 0x011212, 0x01123f, 0x01127f, 0x011287, 0x011287, 0x011289, 0x011289, 0x01128e, 0x01128e, 0x01129e, 0x01129e, 0x0112aa, 0x0112af, 0x0112eb, 0x0112ef, - 0x0112fa, 0x0112ff, 0x011304, 0x011304, 0x01130d, 0x01130e, 0x011311, 0x011312, 0x011329, 0x011329, 0x011331, 0x011331, 0x011334, 0x011334, 0x01133a, 0x01133a, 0x011345, - 0x011346, 0x011349, 0x01134a, 0x01134e, 0x01134f, 0x011351, 0x011356, 0x011358, 0x01135c, 0x011364, 0x011365, 0x01136d, 0x01136f, 0x011375, 0x0113ff, 0x01145c, 0x01145c, - 0x011462, 0x01147f, 0x0114c8, 0x0114cf, 0x0114da, 0x01157f, 0x0115b6, 0x0115b7, 0x0115de, 0x0115ff, 0x011645, 0x01164f, 0x01165a, 0x01165f, 0x01166d, 0x01167f, 0x0116b9, - 0x0116bf, 0x0116ca, 0x0116ff, 0x01171b, 0x01171c, 0x01172c, 0x01172f, 0x011740, 0x0117ff, 0x01183c, 0x01189f, 0x0118f3, 0x0118fe, 0x011907, 0x011908, 0x01190a, 0x01190b, - 0x011914, 0x011914, 0x011917, 0x011917, 0x011936, 0x011936, 0x011939, 0x01193a, 0x011947, 0x01194f, 0x01195a, 0x01199f, 0x0119a8, 0x0119a9, 0x0119d8, 0x0119d9, 0x0119e5, - 0x0119ff, 0x011a48, 0x011a4f, 0x011aa3, 0x011abf, 0x011af9, 0x011bff, 0x011c09, 0x011c09, 0x011c37, 0x011c37, 0x011c46, 0x011c4f, 0x011c6d, 0x011c6f, 0x011c90, 0x011c91, - 0x011ca8, 0x011ca8, 0x011cb7, 0x011cff, 0x011d07, 0x011d07, 0x011d0a, 0x011d0a, 0x011d37, 0x011d39, 0x011d3b, 0x011d3b, 0x011d3e, 0x011d3e, 0x011d48, 0x011d4f, 0x011d5a, - 0x011d5f, 0x011d66, 0x011d66, 0x011d69, 0x011d69, 0x011d8f, 0x011d8f, 0x011d92, 0x011d92, 0x011d99, 0x011d9f, 0x011daa, 0x011edf, 0x011ef9, 0x011faf, 0x011fb1, 0x011fbf, - 0x011ff2, 0x011ffe, 0x01239a, 0x0123ff, 0x01246f, 0x01246f, 0x012475, 0x01247f, 0x012544, 0x012fff, 0x01342f, 0x01342f, 0x013439, 0x0143ff, 0x014647, 0x0167ff, 0x016a39, - 0x016a3f, 0x016a5f, 0x016a5f, 0x016a6a, 0x016a6d, 0x016a70, 0x016acf, 0x016aee, 0x016aef, 0x016af6, 0x016aff, 0x016b46, 0x016b4f, 0x016b5a, 0x016b5a, 0x016b62, 0x016b62, - 0x016b78, 0x016b7c, 0x016b90, 0x016e3f, 0x016e9b, 0x016eff, 0x016f4b, 0x016f4e, 0x016f88, 0x016f8e, 0x016fa0, 0x016fdf, 0x016fe5, 0x016fef, 0x016ff2, 0x016fff, 0x0187f8, - 0x0187ff, 0x018cd6, 0x018cff, 0x018d09, 0x01afff, 0x01b11f, 0x01b14f, 0x01b153, 0x01b163, 0x01b168, 0x01b16f, 0x01b2fc, 0x01bbff, 0x01bc6b, 0x01bc6f, 0x01bc7d, 0x01bc7f, - 0x01bc89, 0x01bc8f, 0x01bc9a, 0x01bc9b, 0x01bca4, 0x01cfff, 0x01d0f6, 0x01d0ff, 0x01d127, 0x01d128, 0x01d1e9, 0x01d1ff, 0x01d246, 0x01d2df, 0x01d2f4, 0x01d2ff, 0x01d357, - 0x01d35f, 0x01d379, 0x01d3ff, 0x01d455, 0x01d455, 0x01d49d, 0x01d49d, 0x01d4a0, 0x01d4a1, 0x01d4a3, 0x01d4a4, 0x01d4a7, 0x01d4a8, 0x01d4ad, 0x01d4ad, 0x01d4ba, 0x01d4ba, - 0x01d4bc, 0x01d4bc, 0x01d4c4, 0x01d4c4, 0x01d506, 0x01d506, 0x01d50b, 0x01d50c, 0x01d515, 0x01d515, 0x01d51d, 0x01d51d, 0x01d53a, 0x01d53a, 0x01d53f, 0x01d53f, 0x01d545, - 0x01d545, 0x01d547, 0x01d549, 0x01d551, 0x01d551, 0x01d6a6, 0x01d6a7, 0x01d7cc, 0x01d7cd, 0x01da8c, 0x01da9a, 0x01daa0, 0x01daa0, 0x01dab0, 0x01dfff, 0x01e007, 0x01e007, - 0x01e019, 0x01e01a, 0x01e022, 0x01e022, 0x01e025, 0x01e025, 0x01e02b, 0x01e0ff, 0x01e12d, 0x01e12f, 0x01e13e, 0x01e13f, 0x01e14a, 0x01e14d, 0x01e150, 0x01e2bf, 0x01e2fa, - 0x01e2fe, 0x01e300, 0x01e7ff, 0x01e8c5, 0x01e8c6, 0x01e8d7, 0x01e8ff, 0x01e94c, 0x01e94f, 0x01e95a, 0x01e95d, 0x01e960, 0x01ec70, 0x01ecb5, 0x01ed00, 0x01ed3e, 0x01edff, - 0x01ee04, 0x01ee04, 0x01ee20, 0x01ee20, 0x01ee23, 0x01ee23, 0x01ee25, 0x01ee26, 0x01ee28, 0x01ee28, 0x01ee33, 0x01ee33, 0x01ee38, 0x01ee38, 0x01ee3a, 0x01ee3a, 0x01ee3c, - 0x01ee41, 0x01ee43, 0x01ee46, 0x01ee48, 0x01ee48, 0x01ee4a, 0x01ee4a, 0x01ee4c, 0x01ee4c, 0x01ee50, 0x01ee50, 0x01ee53, 0x01ee53, 0x01ee55, 0x01ee56, 0x01ee58, 0x01ee58, - 0x01ee5a, 0x01ee5a, 0x01ee5c, 0x01ee5c, 0x01ee5e, 0x01ee5e, 0x01ee60, 0x01ee60, 0x01ee63, 0x01ee63, 0x01ee65, 0x01ee66, 0x01ee6b, 0x01ee6b, 0x01ee73, 0x01ee73, 0x01ee78, - 0x01ee78, 0x01ee7d, 0x01ee7d, 0x01ee7f, 0x01ee7f, 0x01ee8a, 0x01ee8a, 0x01ee9c, 0x01eea0, 0x01eea4, 0x01eea4, 0x01eeaa, 0x01eeaa, 0x01eebc, 0x01eeef, 0x01eef2, 0x01efff, - 0x01f02c, 0x01f02f, 0x01f094, 0x01f09f, 0x01f0af, 0x01f0b0, 0x01f0c0, 0x01f0c0, 0x01f0d0, 0x01f0d0, 0x01f0f6, 0x01f0ff, 0x01f1ae, 0x01f1e5, 0x01f203, 0x01f20f, 0x01f23c, - 0x01f23f, 0x01f249, 0x01f24f, 0x01f252, 0x01f25f, 0x01f266, 0x01f2ff, 0x01f6d8, 0x01f6df, 0x01f6ed, 0x01f6ef, 0x01f6fd, 0x01f6ff, 0x01f774, 0x01f77f, 0x01f7d9, 0x01f7df, - 0x01f7ec, 0x01f7ff, 0x01f80c, 0x01f80f, 0x01f848, 0x01f84f, 0x01f85a, 0x01f85f, 0x01f888, 0x01f88f, 0x01f8ae, 0x01f8af, 0x01f8b2, 0x01f8ff, 0x01f979, 0x01f979, 0x01f9cc, - 0x01f9cc, 0x01fa54, 0x01fa5f, 0x01fa6e, 0x01fa6f, 0x01fa75, 0x01fa77, 0x01fa7b, 0x01fa7f, 0x01fa87, 0x01fa8f, 0x01faa9, 0x01faaf, 0x01fab7, 0x01fabf, 0x01fac3, 0x01facf, - 0x01fad7, 0x01faff, 0x01fb93, 0x01fb93, 0x01fbcb, 0x01fbef, 0x01fbfa, 0x01ffff, 0x02a6de, 0x02a6ff, 0x02b735, 0x02b73f, 0x02b81e, 0x02b81f, 0x02cea2, 0x02ceaf, 0x02ebe1, - 0x02f7ff, 0x02fa1e, 0x02ffff, 0x03134b, 0x0e0000, 0x0e0002, 0x0e001f, 0x0e0080, 0x0e00ff, 0x0e01f0, 0x0effff, 0x0ffffe, 0x0fffff, 0x10fffe, 0x10ffff)); + 0x001716, 0x00171e, 0x001737, 0x00173f, 0x001754, 0x00175f, 0x00176d, 0x00176d, 0x001771, 0x001771, 0x001774, 0x00177f, 0x0017de, 0x0017df, 0x0017ea, 0x0017ef, 0x0017fa, + 0x0017ff, 0x00181a, 0x00181f, 0x001879, 0x00187f, 0x0018ab, 0x0018af, 0x0018f6, 0x0018ff, 0x00191f, 0x00191f, 0x00192c, 0x00192f, 0x00193c, 0x00193f, 0x001941, 0x001943, + 0x00196e, 0x00196f, 0x001975, 0x00197f, 0x0019ac, 0x0019af, 0x0019ca, 0x0019cf, 0x0019db, 0x0019dd, 0x001a1c, 0x001a1d, 0x001a5f, 0x001a5f, 0x001a7d, 0x001a7e, 0x001a8a, + 0x001a8f, 0x001a9a, 0x001a9f, 0x001aae, 0x001aaf, 0x001acf, 0x001aff, 0x001b4d, 0x001b4f, 0x001b7f, 0x001b7f, 0x001bf4, 0x001bfb, 0x001c38, 0x001c3a, 0x001c4a, 0x001c4c, + 0x001c89, 0x001c8f, 0x001cbb, 0x001cbc, 0x001cc8, 0x001ccf, 0x001cfb, 0x001cff, 0x001f16, 0x001f17, 0x001f1e, 0x001f1f, 0x001f46, 0x001f47, 0x001f4e, 0x001f4f, 0x001f58, + 0x001f58, 0x001f5a, 0x001f5a, 0x001f5c, 0x001f5c, 0x001f5e, 0x001f5e, 0x001f7e, 0x001f7f, 0x001fb5, 0x001fb5, 0x001fc5, 0x001fc5, 0x001fd4, 0x001fd5, 0x001fdc, 0x001fdc, + 0x001ff0, 0x001ff1, 0x001ff5, 0x001ff5, 0x001fff, 0x001fff, 0x002065, 0x002065, 0x002072, 0x002073, 0x00208f, 0x00208f, 0x00209d, 0x00209f, 0x0020c1, 0x0020cf, 0x0020f1, + 0x0020ff, 0x00218c, 0x00218f, 0x002427, 0x00243f, 0x00244b, 0x00245f, 0x002b74, 0x002b75, 0x002b96, 0x002b96, 0x002cf4, 0x002cf8, 0x002d26, 0x002d26, 0x002d28, 0x002d2c, + 0x002d2e, 0x002d2f, 0x002d68, 0x002d6e, 0x002d71, 0x002d7e, 0x002d97, 0x002d9f, 0x002da7, 0x002da7, 0x002daf, 0x002daf, 0x002db7, 0x002db7, 0x002dbf, 0x002dbf, 0x002dc7, + 0x002dc7, 0x002dcf, 0x002dcf, 0x002dd7, 0x002dd7, 0x002ddf, 0x002ddf, 0x002e5e, 0x002e7f, 0x002e9a, 0x002e9a, 0x002ef4, 0x002eff, 0x002fd6, 0x002fef, 0x002ffc, 0x002fff, + 0x003040, 0x003040, 0x003097, 0x003098, 0x003100, 0x003104, 0x003130, 0x003130, 0x00318f, 0x00318f, 0x0031e4, 0x0031ef, 0x00321f, 0x00321f, 0x00a48d, 0x00a48f, 0x00a4c7, + 0x00a4cf, 0x00a62c, 0x00a63f, 0x00a6f8, 0x00a6ff, 0x00a7cb, 0x00a7cf, 0x00a7d2, 0x00a7d2, 0x00a7d4, 0x00a7d4, 0x00a7da, 0x00a7f1, 0x00a82d, 0x00a82f, 0x00a83a, 0x00a83f, + 0x00a878, 0x00a87f, 0x00a8c6, 0x00a8cd, 0x00a8da, 0x00a8df, 0x00a954, 0x00a95e, 0x00a97d, 0x00a97f, 0x00a9ce, 0x00a9ce, 0x00a9da, 0x00a9dd, 0x00a9ff, 0x00a9ff, 0x00aa37, + 0x00aa3f, 0x00aa4e, 0x00aa4f, 0x00aa5a, 0x00aa5b, 0x00aac3, 0x00aada, 0x00aaf7, 0x00ab00, 0x00ab07, 0x00ab08, 0x00ab0f, 0x00ab10, 0x00ab17, 0x00ab1f, 0x00ab27, 0x00ab27, + 0x00ab2f, 0x00ab2f, 0x00ab6c, 0x00ab6f, 0x00abee, 0x00abef, 0x00abfa, 0x00abff, 0x00d7a4, 0x00d7af, 0x00d7c7, 0x00d7ca, 0x00d7fc, 0x00d7ff, 0x00fa6e, 0x00fa6f, 0x00fada, + 0x00faff, 0x00fb07, 0x00fb12, 0x00fb18, 0x00fb1c, 0x00fb37, 0x00fb37, 0x00fb3d, 0x00fb3d, 0x00fb3f, 0x00fb3f, 0x00fb42, 0x00fb42, 0x00fb45, 0x00fb45, 0x00fbc3, 0x00fbd2, + 0x00fd90, 0x00fd91, 0x00fdc8, 0x00fdce, 0x00fdd0, 0x00fdef, 0x00fe1a, 0x00fe1f, 0x00fe53, 0x00fe53, 0x00fe67, 0x00fe67, 0x00fe6c, 0x00fe6f, 0x00fe75, 0x00fe75, 0x00fefd, + 0x00fefe, 0x00ff00, 0x00ff00, 0x00ffbf, 0x00ffc1, 0x00ffc8, 0x00ffc9, 0x00ffd0, 0x00ffd1, 0x00ffd8, 0x00ffd9, 0x00ffdd, 0x00ffdf, 0x00ffe7, 0x00ffe7, 0x00ffef, 0x00fff8, + 0x00fffe, 0x00ffff, 0x01000c, 0x01000c, 0x010027, 0x010027, 0x01003b, 0x01003b, 0x01003e, 0x01003e, 0x01004e, 0x01004f, 0x01005e, 0x01007f, 0x0100fb, 0x0100ff, 0x010103, + 0x010106, 0x010134, 0x010136, 0x01018f, 0x01018f, 0x01019d, 0x01019f, 0x0101a1, 0x0101cf, 0x0101fe, 0x01027f, 0x01029d, 0x01029f, 0x0102d1, 0x0102df, 0x0102fc, 0x0102ff, + 0x010324, 0x01032c, 0x01034b, 0x01034f, 0x01037b, 0x01037f, 0x01039e, 0x01039e, 0x0103c4, 0x0103c7, 0x0103d6, 0x0103ff, 0x01049e, 0x01049f, 0x0104aa, 0x0104af, 0x0104d4, + 0x0104d7, 0x0104fc, 0x0104ff, 0x010528, 0x01052f, 0x010564, 0x01056e, 0x01057b, 0x01057b, 0x01058b, 0x01058b, 0x010593, 0x010593, 0x010596, 0x010596, 0x0105a2, 0x0105a2, + 0x0105b2, 0x0105b2, 0x0105ba, 0x0105ba, 0x0105bd, 0x0105ff, 0x010737, 0x01073f, 0x010756, 0x01075f, 0x010768, 0x01077f, 0x010786, 0x010786, 0x0107b1, 0x0107b1, 0x0107bb, + 0x0107ff, 0x010806, 0x010807, 0x010809, 0x010809, 0x010836, 0x010836, 0x010839, 0x01083b, 0x01083d, 0x01083e, 0x010856, 0x010856, 0x01089f, 0x0108a6, 0x0108b0, 0x0108df, + 0x0108f3, 0x0108f3, 0x0108f6, 0x0108fa, 0x01091c, 0x01091e, 0x01093a, 0x01093e, 0x010940, 0x01097f, 0x0109b8, 0x0109bb, 0x0109d0, 0x0109d1, 0x010a04, 0x010a04, 0x010a07, + 0x010a0b, 0x010a14, 0x010a14, 0x010a18, 0x010a18, 0x010a36, 0x010a37, 0x010a3b, 0x010a3e, 0x010a49, 0x010a4f, 0x010a59, 0x010a5f, 0x010aa0, 0x010abf, 0x010ae7, 0x010aea, + 0x010af7, 0x010aff, 0x010b36, 0x010b38, 0x010b56, 0x010b57, 0x010b73, 0x010b77, 0x010b92, 0x010b98, 0x010b9d, 0x010ba8, 0x010bb0, 0x010bff, 0x010c49, 0x010c7f, 0x010cb3, + 0x010cbf, 0x010cf3, 0x010cf9, 0x010d28, 0x010d2f, 0x010d3a, 0x010e5f, 0x010e7f, 0x010e7f, 0x010eaa, 0x010eaa, 0x010eae, 0x010eaf, 0x010eb2, 0x010eff, 0x010f28, 0x010f2f, + 0x010f5a, 0x010f6f, 0x010f8a, 0x010faf, 0x010fcc, 0x010fdf, 0x010ff7, 0x010fff, 0x01104e, 0x011051, 0x011076, 0x01107e, 0x0110c3, 0x0110cc, 0x0110ce, 0x0110cf, 0x0110e9, + 0x0110ef, 0x0110fa, 0x0110ff, 0x011135, 0x011135, 0x011148, 0x01114f, 0x011177, 0x01117f, 0x0111e0, 0x0111e0, 0x0111f5, 0x0111ff, 0x011212, 0x011212, 0x01123f, 0x01127f, + 0x011287, 0x011287, 0x011289, 0x011289, 0x01128e, 0x01128e, 0x01129e, 0x01129e, 0x0112aa, 0x0112af, 0x0112eb, 0x0112ef, 0x0112fa, 0x0112ff, 0x011304, 0x011304, 0x01130d, + 0x01130e, 0x011311, 0x011312, 0x011329, 0x011329, 0x011331, 0x011331, 0x011334, 0x011334, 0x01133a, 0x01133a, 0x011345, 0x011346, 0x011349, 0x01134a, 0x01134e, 0x01134f, + 0x011351, 0x011356, 0x011358, 0x01135c, 0x011364, 0x011365, 0x01136d, 0x01136f, 0x011375, 0x0113ff, 0x01145c, 0x01145c, 0x011462, 0x01147f, 0x0114c8, 0x0114cf, 0x0114da, + 0x01157f, 0x0115b6, 0x0115b7, 0x0115de, 0x0115ff, 0x011645, 0x01164f, 0x01165a, 0x01165f, 0x01166d, 0x01167f, 0x0116ba, 0x0116bf, 0x0116ca, 0x0116ff, 0x01171b, 0x01171c, + 0x01172c, 0x01172f, 0x011747, 0x0117ff, 0x01183c, 0x01189f, 0x0118f3, 0x0118fe, 0x011907, 0x011908, 0x01190a, 0x01190b, 0x011914, 0x011914, 0x011917, 0x011917, 0x011936, + 0x011936, 0x011939, 0x01193a, 0x011947, 0x01194f, 0x01195a, 0x01199f, 0x0119a8, 0x0119a9, 0x0119d8, 0x0119d9, 0x0119e5, 0x0119ff, 0x011a48, 0x011a4f, 0x011aa3, 0x011aaf, + 0x011af9, 0x011bff, 0x011c09, 0x011c09, 0x011c37, 0x011c37, 0x011c46, 0x011c4f, 0x011c6d, 0x011c6f, 0x011c90, 0x011c91, 0x011ca8, 0x011ca8, 0x011cb7, 0x011cff, 0x011d07, + 0x011d07, 0x011d0a, 0x011d0a, 0x011d37, 0x011d39, 0x011d3b, 0x011d3b, 0x011d3e, 0x011d3e, 0x011d48, 0x011d4f, 0x011d5a, 0x011d5f, 0x011d66, 0x011d66, 0x011d69, 0x011d69, + 0x011d8f, 0x011d8f, 0x011d92, 0x011d92, 0x011d99, 0x011d9f, 0x011daa, 0x011edf, 0x011ef9, 0x011faf, 0x011fb1, 0x011fbf, 0x011ff2, 0x011ffe, 0x01239a, 0x0123ff, 0x01246f, + 0x01246f, 0x012475, 0x01247f, 0x012544, 0x012f8f, 0x012ff3, 0x012fff, 0x01342f, 0x01342f, 0x013439, 0x0143ff, 0x014647, 0x0167ff, 0x016a39, 0x016a3f, 0x016a5f, 0x016a5f, + 0x016a6a, 0x016a6d, 0x016abf, 0x016abf, 0x016aca, 0x016acf, 0x016aee, 0x016aef, 0x016af6, 0x016aff, 0x016b46, 0x016b4f, 0x016b5a, 0x016b5a, 0x016b62, 0x016b62, 0x016b78, + 0x016b7c, 0x016b90, 0x016e3f, 0x016e9b, 0x016eff, 0x016f4b, 0x016f4e, 0x016f88, 0x016f8e, 0x016fa0, 0x016fdf, 0x016fe5, 0x016fef, 0x016ff2, 0x016fff, 0x0187f8, 0x0187ff, + 0x018cd6, 0x018cff, 0x018d09, 0x01afef, 0x01aff4, 0x01aff4, 0x01affc, 0x01affc, 0x01afff, 0x01afff, 0x01b123, 0x01b14f, 0x01b153, 0x01b163, 0x01b168, 0x01b16f, 0x01b2fc, + 0x01bbff, 0x01bc6b, 0x01bc6f, 0x01bc7d, 0x01bc7f, 0x01bc89, 0x01bc8f, 0x01bc9a, 0x01bc9b, 0x01bca4, 0x01ceff, 0x01cf2e, 0x01cf2f, 0x01cf47, 0x01cf4f, 0x01cfc4, 0x01cfff, + 0x01d0f6, 0x01d0ff, 0x01d127, 0x01d128, 0x01d1eb, 0x01d1ff, 0x01d246, 0x01d2df, 0x01d2f4, 0x01d2ff, 0x01d357, 0x01d35f, 0x01d379, 0x01d3ff, 0x01d455, 0x01d455, 0x01d49d, + 0x01d49d, 0x01d4a0, 0x01d4a1, 0x01d4a3, 0x01d4a4, 0x01d4a7, 0x01d4a8, 0x01d4ad, 0x01d4ad, 0x01d4ba, 0x01d4ba, 0x01d4bc, 0x01d4bc, 0x01d4c4, 0x01d4c4, 0x01d506, 0x01d506, + 0x01d50b, 0x01d50c, 0x01d515, 0x01d515, 0x01d51d, 0x01d51d, 0x01d53a, 0x01d53a, 0x01d53f, 0x01d53f, 0x01d545, 0x01d545, 0x01d547, 0x01d549, 0x01d551, 0x01d551, 0x01d6a6, + 0x01d6a7, 0x01d7cc, 0x01d7cd, 0x01da8c, 0x01da9a, 0x01daa0, 0x01daa0, 0x01dab0, 0x01deff, 0x01df1f, 0x01dfff, 0x01e007, 0x01e007, 0x01e019, 0x01e01a, 0x01e022, 0x01e022, + 0x01e025, 0x01e025, 0x01e02b, 0x01e0ff, 0x01e12d, 0x01e12f, 0x01e13e, 0x01e13f, 0x01e14a, 0x01e14d, 0x01e150, 0x01e28f, 0x01e2af, 0x01e2bf, 0x01e2fa, 0x01e2fe, 0x01e300, + 0x01e7df, 0x01e7e7, 0x01e7e7, 0x01e7ec, 0x01e7ec, 0x01e7ef, 0x01e7ef, 0x01e7ff, 0x01e7ff, 0x01e8c5, 0x01e8c6, 0x01e8d7, 0x01e8ff, 0x01e94c, 0x01e94f, 0x01e95a, 0x01e95d, + 0x01e960, 0x01ec70, 0x01ecb5, 0x01ed00, 0x01ed3e, 0x01edff, 0x01ee04, 0x01ee04, 0x01ee20, 0x01ee20, 0x01ee23, 0x01ee23, 0x01ee25, 0x01ee26, 0x01ee28, 0x01ee28, 0x01ee33, + 0x01ee33, 0x01ee38, 0x01ee38, 0x01ee3a, 0x01ee3a, 0x01ee3c, 0x01ee41, 0x01ee43, 0x01ee46, 0x01ee48, 0x01ee48, 0x01ee4a, 0x01ee4a, 0x01ee4c, 0x01ee4c, 0x01ee50, 0x01ee50, + 0x01ee53, 0x01ee53, 0x01ee55, 0x01ee56, 0x01ee58, 0x01ee58, 0x01ee5a, 0x01ee5a, 0x01ee5c, 0x01ee5c, 0x01ee5e, 0x01ee5e, 0x01ee60, 0x01ee60, 0x01ee63, 0x01ee63, 0x01ee65, + 0x01ee66, 0x01ee6b, 0x01ee6b, 0x01ee73, 0x01ee73, 0x01ee78, 0x01ee78, 0x01ee7d, 0x01ee7d, 0x01ee7f, 0x01ee7f, 0x01ee8a, 0x01ee8a, 0x01ee9c, 0x01eea0, 0x01eea4, 0x01eea4, + 0x01eeaa, 0x01eeaa, 0x01eebc, 0x01eeef, 0x01eef2, 0x01efff, 0x01f02c, 0x01f02f, 0x01f094, 0x01f09f, 0x01f0af, 0x01f0b0, 0x01f0c0, 0x01f0c0, 0x01f0d0, 0x01f0d0, 0x01f0f6, + 0x01f0ff, 0x01f1ae, 0x01f1e5, 0x01f203, 0x01f20f, 0x01f23c, 0x01f23f, 0x01f249, 0x01f24f, 0x01f252, 0x01f25f, 0x01f266, 0x01f2ff, 0x01f6d8, 0x01f6dc, 0x01f6ed, 0x01f6ef, + 0x01f6fd, 0x01f6ff, 0x01f774, 0x01f77f, 0x01f7d9, 0x01f7df, 0x01f7ec, 0x01f7ef, 0x01f7f1, 0x01f7ff, 0x01f80c, 0x01f80f, 0x01f848, 0x01f84f, 0x01f85a, 0x01f85f, 0x01f888, + 0x01f88f, 0x01f8ae, 0x01f8af, 0x01f8b2, 0x01f8ff, 0x01fa54, 0x01fa5f, 0x01fa6e, 0x01fa6f, 0x01fa75, 0x01fa77, 0x01fa7d, 0x01fa7f, 0x01fa87, 0x01fa8f, 0x01faad, 0x01faaf, + 0x01fabb, 0x01fabf, 0x01fac6, 0x01facf, 0x01fada, 0x01fadf, 0x01fae8, 0x01faef, 0x01faf7, 0x01faff, 0x01fb93, 0x01fb93, 0x01fbcb, 0x01fbef, 0x01fbfa, 0x01ffff, 0x02a6e0, + 0x02a6ff, 0x02b739, 0x02b73f, 0x02b81e, 0x02b81f, 0x02cea2, 0x02ceaf, 0x02ebe1, 0x02f7ff, 0x02fa1e, 0x02ffff, 0x03134b, 0x0e0000, 0x0e0002, 0x0e001f, 0x0e0080, 0x0e00ff, + 0x0e01f0, 0x0effff, 0x0ffffe, 0x0fffff, 0x10fffe, 0x10ffff)); } private static void populateGC_CO() { @@ -2701,7 +2757,7 @@ private static void populateGC_LL() { 0x001f60, 0x001f67, 0x001f70, 0x001f7d, 0x001f80, 0x001f87, 0x001f90, 0x001f97, 0x001fa0, 0x001fa7, 0x001fb0, 0x001fb4, 0x001fb6, 0x001fb7, 0x001fbe, 0x001fbe, 0x001fc2, 0x001fc4, 0x001fc6, 0x001fc7, 0x001fd0, 0x001fd3, 0x001fd6, 0x001fd7, 0x001fe0, 0x001fe7, 0x001ff2, 0x001ff4, 0x001ff6, 0x001ff7, 0x00210a, 0x00210a, 0x00210e, 0x00210f, 0x002113, 0x002113, 0x00212f, 0x00212f, 0x002134, 0x002134, 0x002139, 0x002139, 0x00213c, 0x00213d, 0x002146, 0x002149, 0x00214e, 0x00214e, 0x002184, 0x002184, 0x002c30, - 0x002c5e, 0x002c61, 0x002c61, 0x002c65, 0x002c66, 0x002c68, 0x002c68, 0x002c6a, 0x002c6a, 0x002c6c, 0x002c6c, 0x002c71, 0x002c71, 0x002c73, 0x002c74, 0x002c76, 0x002c7b, + 0x002c5f, 0x002c61, 0x002c61, 0x002c65, 0x002c66, 0x002c68, 0x002c68, 0x002c6a, 0x002c6a, 0x002c6c, 0x002c6c, 0x002c71, 0x002c71, 0x002c73, 0x002c74, 0x002c76, 0x002c7b, 0x002c81, 0x002c81, 0x002c83, 0x002c83, 0x002c85, 0x002c85, 0x002c87, 0x002c87, 0x002c89, 0x002c89, 0x002c8b, 0x002c8b, 0x002c8d, 0x002c8d, 0x002c8f, 0x002c8f, 0x002c91, 0x002c91, 0x002c93, 0x002c93, 0x002c95, 0x002c95, 0x002c97, 0x002c97, 0x002c99, 0x002c99, 0x002c9b, 0x002c9b, 0x002c9d, 0x002c9d, 0x002c9f, 0x002c9f, 0x002ca1, 0x002ca1, 0x002ca3, 0x002ca3, 0x002ca5, 0x002ca5, 0x002ca7, 0x002ca7, 0x002ca9, 0x002ca9, 0x002cab, 0x002cab, 0x002cad, 0x002cad, 0x002caf, 0x002caf, 0x002cb1, 0x002cb1, 0x002cb3, @@ -2720,54 +2776,56 @@ private static void populateGC_LL() { 0x00a769, 0x00a76b, 0x00a76b, 0x00a76d, 0x00a76d, 0x00a76f, 0x00a76f, 0x00a771, 0x00a778, 0x00a77a, 0x00a77a, 0x00a77c, 0x00a77c, 0x00a77f, 0x00a77f, 0x00a781, 0x00a781, 0x00a783, 0x00a783, 0x00a785, 0x00a785, 0x00a787, 0x00a787, 0x00a78c, 0x00a78c, 0x00a78e, 0x00a78e, 0x00a791, 0x00a791, 0x00a793, 0x00a795, 0x00a797, 0x00a797, 0x00a799, 0x00a799, 0x00a79b, 0x00a79b, 0x00a79d, 0x00a79d, 0x00a79f, 0x00a79f, 0x00a7a1, 0x00a7a1, 0x00a7a3, 0x00a7a3, 0x00a7a5, 0x00a7a5, 0x00a7a7, 0x00a7a7, 0x00a7a9, 0x00a7a9, - 0x00a7af, 0x00a7af, 0x00a7b5, 0x00a7b5, 0x00a7b7, 0x00a7b7, 0x00a7b9, 0x00a7b9, 0x00a7bb, 0x00a7bb, 0x00a7bd, 0x00a7bd, 0x00a7bf, 0x00a7bf, 0x00a7c3, 0x00a7c3, 0x00a7c8, - 0x00a7c8, 0x00a7ca, 0x00a7ca, 0x00a7f6, 0x00a7f6, 0x00a7fa, 0x00a7fa, 0x00ab30, 0x00ab5a, 0x00ab60, 0x00ab68, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, - 0x00ff41, 0x00ff5a, 0x010428, 0x01044f, 0x0104d8, 0x0104fb, 0x010cc0, 0x010cf2, 0x0118c0, 0x0118df, 0x016e60, 0x016e7f, 0x01d41a, 0x01d433, 0x01d44e, 0x01d454, 0x01d456, - 0x01d467, 0x01d482, 0x01d49b, 0x01d4b6, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d4cf, 0x01d4ea, 0x01d503, 0x01d51e, 0x01d537, 0x01d552, 0x01d56b, - 0x01d586, 0x01d59f, 0x01d5ba, 0x01d5d3, 0x01d5ee, 0x01d607, 0x01d622, 0x01d63b, 0x01d656, 0x01d66f, 0x01d68a, 0x01d6a5, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6e1, 0x01d6fc, - 0x01d714, 0x01d716, 0x01d71b, 0x01d736, 0x01d74e, 0x01d750, 0x01d755, 0x01d770, 0x01d788, 0x01d78a, 0x01d78f, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7c9, 0x01d7cb, 0x01d7cb, - 0x01e922, 0x01e943)); + 0x00a7af, 0x00a7af, 0x00a7b5, 0x00a7b5, 0x00a7b7, 0x00a7b7, 0x00a7b9, 0x00a7b9, 0x00a7bb, 0x00a7bb, 0x00a7bd, 0x00a7bd, 0x00a7bf, 0x00a7bf, 0x00a7c1, 0x00a7c1, 0x00a7c3, + 0x00a7c3, 0x00a7c8, 0x00a7c8, 0x00a7ca, 0x00a7ca, 0x00a7d1, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d5, 0x00a7d7, 0x00a7d7, 0x00a7d9, 0x00a7d9, 0x00a7f6, 0x00a7f6, + 0x00a7fa, 0x00a7fa, 0x00ab30, 0x00ab5a, 0x00ab60, 0x00ab68, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff41, 0x00ff5a, 0x010428, 0x01044f, 0x0104d8, + 0x0104fb, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010cc0, 0x010cf2, 0x0118c0, 0x0118df, 0x016e60, 0x016e7f, 0x01d41a, 0x01d433, + 0x01d44e, 0x01d454, 0x01d456, 0x01d467, 0x01d482, 0x01d49b, 0x01d4b6, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d4cf, 0x01d4ea, 0x01d503, 0x01d51e, + 0x01d537, 0x01d552, 0x01d56b, 0x01d586, 0x01d59f, 0x01d5ba, 0x01d5d3, 0x01d5ee, 0x01d607, 0x01d622, 0x01d63b, 0x01d656, 0x01d66f, 0x01d68a, 0x01d6a5, 0x01d6c2, 0x01d6da, + 0x01d6dc, 0x01d6e1, 0x01d6fc, 0x01d714, 0x01d716, 0x01d71b, 0x01d736, 0x01d74e, 0x01d750, 0x01d755, 0x01d770, 0x01d788, 0x01d78a, 0x01d78f, 0x01d7aa, 0x01d7c2, 0x01d7c4, + 0x01d7c9, 0x01d7cb, 0x01d7cb, 0x01df00, 0x01df09, 0x01df0b, 0x01df1e, 0x01e922, 0x01e943)); } private static void populateGC_LM() { SET_ENCODINGS.put("gc=Lm", CodePointSet.createNoDedup(0x0002b0, 0x0002c1, 0x0002c6, 0x0002d1, 0x0002e0, 0x0002e4, 0x0002ec, 0x0002ec, 0x0002ee, 0x0002ee, 0x000374, 0x000374, 0x00037a, 0x00037a, 0x000559, - 0x000559, 0x000640, 0x000640, 0x0006e5, 0x0006e6, 0x0007f4, 0x0007f5, 0x0007fa, 0x0007fa, 0x00081a, 0x00081a, 0x000824, 0x000824, 0x000828, 0x000828, 0x000971, - 0x000971, 0x000e46, 0x000e46, 0x000ec6, 0x000ec6, 0x0010fc, 0x0010fc, 0x0017d7, 0x0017d7, 0x001843, 0x001843, 0x001aa7, 0x001aa7, 0x001c78, 0x001c7d, 0x001d2c, - 0x001d6a, 0x001d78, 0x001d78, 0x001d9b, 0x001dbf, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x002c7c, 0x002c7d, 0x002d6f, 0x002d6f, 0x002e2f, - 0x002e2f, 0x003005, 0x003005, 0x003031, 0x003035, 0x00303b, 0x00303b, 0x00309d, 0x00309e, 0x0030fc, 0x0030fe, 0x00a015, 0x00a015, 0x00a4f8, 0x00a4fd, 0x00a60c, - 0x00a60c, 0x00a67f, 0x00a67f, 0x00a69c, 0x00a69d, 0x00a717, 0x00a71f, 0x00a770, 0x00a770, 0x00a788, 0x00a788, 0x00a7f8, 0x00a7f9, 0x00a9cf, 0x00a9cf, 0x00a9e6, - 0x00a9e6, 0x00aa70, 0x00aa70, 0x00aadd, 0x00aadd, 0x00aaf3, 0x00aaf4, 0x00ab5c, 0x00ab5f, 0x00ab69, 0x00ab69, 0x00ff70, 0x00ff70, 0x00ff9e, 0x00ff9f, 0x016b40, - 0x016b43, 0x016f93, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, 0x016fe3, 0x01e137, 0x01e13d, 0x01e94b, 0x01e94b)); + 0x000559, 0x000640, 0x000640, 0x0006e5, 0x0006e6, 0x0007f4, 0x0007f5, 0x0007fa, 0x0007fa, 0x00081a, 0x00081a, 0x000824, 0x000824, 0x000828, 0x000828, 0x0008c9, + 0x0008c9, 0x000971, 0x000971, 0x000e46, 0x000e46, 0x000ec6, 0x000ec6, 0x0010fc, 0x0010fc, 0x0017d7, 0x0017d7, 0x001843, 0x001843, 0x001aa7, 0x001aa7, 0x001c78, + 0x001c7d, 0x001d2c, 0x001d6a, 0x001d78, 0x001d78, 0x001d9b, 0x001dbf, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x002c7c, 0x002c7d, 0x002d6f, + 0x002d6f, 0x002e2f, 0x002e2f, 0x003005, 0x003005, 0x003031, 0x003035, 0x00303b, 0x00303b, 0x00309d, 0x00309e, 0x0030fc, 0x0030fe, 0x00a015, 0x00a015, 0x00a4f8, + 0x00a4fd, 0x00a60c, 0x00a60c, 0x00a67f, 0x00a67f, 0x00a69c, 0x00a69d, 0x00a717, 0x00a71f, 0x00a770, 0x00a770, 0x00a788, 0x00a788, 0x00a7f2, 0x00a7f4, 0x00a7f8, + 0x00a7f9, 0x00a9cf, 0x00a9cf, 0x00a9e6, 0x00a9e6, 0x00aa70, 0x00aa70, 0x00aadd, 0x00aadd, 0x00aaf3, 0x00aaf4, 0x00ab5c, 0x00ab5f, 0x00ab69, 0x00ab69, 0x00ff70, + 0x00ff70, 0x00ff9e, 0x00ff9f, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x016b40, 0x016b43, 0x016f93, 0x016f9f, 0x016fe0, 0x016fe1, 0x016fe3, + 0x016fe3, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01e137, 0x01e13d, 0x01e94b, 0x01e94b)); } private static void populateGC_LO() { SET_ENCODINGS.put("gc=Lo", CodePointSet.createNoDedup(0x0000aa, 0x0000aa, 0x0000ba, 0x0000ba, 0x0001bb, 0x0001bb, 0x0001c0, 0x0001c3, 0x000294, 0x000294, 0x0005d0, 0x0005ea, 0x0005ef, 0x0005f2, 0x000620, 0x00063f, 0x000641, 0x00064a, 0x00066e, 0x00066f, 0x000671, 0x0006d3, 0x0006d5, 0x0006d5, 0x0006ee, 0x0006ef, 0x0006fa, 0x0006fc, 0x0006ff, 0x0006ff, - 0x000710, 0x000710, 0x000712, 0x00072f, 0x00074d, 0x0007a5, 0x0007b1, 0x0007b1, 0x0007ca, 0x0007ea, 0x000800, 0x000815, 0x000840, 0x000858, 0x000860, 0x00086a, 0x0008a0, - 0x0008b4, 0x0008b6, 0x0008c7, 0x000904, 0x000939, 0x00093d, 0x00093d, 0x000950, 0x000950, 0x000958, 0x000961, 0x000972, 0x000980, 0x000985, 0x00098c, 0x00098f, 0x000990, - 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009bd, 0x0009ce, 0x0009ce, 0x0009dc, 0x0009dd, 0x0009df, 0x0009e1, 0x0009f0, - 0x0009f1, 0x0009fc, 0x0009fc, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, 0x000a38, 0x000a39, - 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a72, 0x000a74, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, 0x000ab3, 0x000ab5, - 0x000ab9, 0x000abd, 0x000abd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae1, 0x000af9, 0x000af9, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, 0x000b2a, 0x000b30, - 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b3d, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b61, 0x000b71, 0x000b71, 0x000b83, 0x000b83, 0x000b85, 0x000b8a, 0x000b8e, - 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, 0x000bd0, 0x000bd0, - 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c58, 0x000c5a, 0x000c60, 0x000c61, 0x000c80, 0x000c80, 0x000c85, - 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbd, 0x000cde, 0x000cde, 0x000ce0, 0x000ce1, 0x000cf1, 0x000cf2, - 0x000d04, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d4e, 0x000d4e, 0x000d54, 0x000d56, 0x000d5f, 0x000d61, 0x000d7a, 0x000d7f, 0x000d85, - 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000e01, 0x000e30, 0x000e32, 0x000e33, 0x000e40, 0x000e45, 0x000e81, 0x000e82, - 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb3, 0x000ebd, 0x000ebd, 0x000ec0, 0x000ec4, 0x000edc, - 0x000edf, 0x000f00, 0x000f00, 0x000f40, 0x000f47, 0x000f49, 0x000f6c, 0x000f88, 0x000f8c, 0x001000, 0x00102a, 0x00103f, 0x00103f, 0x001050, 0x001055, 0x00105a, 0x00105d, - 0x001061, 0x001061, 0x001065, 0x001066, 0x00106e, 0x001070, 0x001075, 0x001081, 0x00108e, 0x00108e, 0x001100, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, - 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, - 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x001380, 0x00138f, 0x001401, 0x00166c, 0x00166f, 0x00167f, 0x001681, 0x00169a, 0x0016a0, - 0x0016ea, 0x0016f1, 0x0016f8, 0x001700, 0x00170c, 0x00170e, 0x001711, 0x001720, 0x001731, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, 0x001780, 0x0017b3, - 0x0017dc, 0x0017dc, 0x001820, 0x001842, 0x001844, 0x001878, 0x001880, 0x001884, 0x001887, 0x0018a8, 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, 0x00191e, 0x001950, - 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x001a00, 0x001a16, 0x001a20, 0x001a54, 0x001b05, 0x001b33, 0x001b45, 0x001b4b, 0x001b83, 0x001ba0, - 0x001bae, 0x001baf, 0x001bba, 0x001be5, 0x001c00, 0x001c23, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c77, 0x001ce9, 0x001cec, 0x001cee, 0x001cf3, 0x001cf5, 0x001cf6, 0x001cfa, - 0x001cfa, 0x002135, 0x002138, 0x002d30, 0x002d67, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, 0x002dc6, - 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x003006, 0x003006, 0x00303c, 0x00303c, 0x003041, 0x003096, 0x00309f, 0x00309f, 0x0030a1, 0x0030fa, 0x0030ff, - 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, 0x009ffc, 0x00a000, 0x00a014, 0x00a016, 0x00a48c, + 0x000710, 0x000710, 0x000712, 0x00072f, 0x00074d, 0x0007a5, 0x0007b1, 0x0007b1, 0x0007ca, 0x0007ea, 0x000800, 0x000815, 0x000840, 0x000858, 0x000860, 0x00086a, 0x000870, + 0x000887, 0x000889, 0x00088e, 0x0008a0, 0x0008c8, 0x000904, 0x000939, 0x00093d, 0x00093d, 0x000950, 0x000950, 0x000958, 0x000961, 0x000972, 0x000980, 0x000985, 0x00098c, + 0x00098f, 0x000990, 0x000993, 0x0009a8, 0x0009aa, 0x0009b0, 0x0009b2, 0x0009b2, 0x0009b6, 0x0009b9, 0x0009bd, 0x0009bd, 0x0009ce, 0x0009ce, 0x0009dc, 0x0009dd, 0x0009df, + 0x0009e1, 0x0009f0, 0x0009f1, 0x0009fc, 0x0009fc, 0x000a05, 0x000a0a, 0x000a0f, 0x000a10, 0x000a13, 0x000a28, 0x000a2a, 0x000a30, 0x000a32, 0x000a33, 0x000a35, 0x000a36, + 0x000a38, 0x000a39, 0x000a59, 0x000a5c, 0x000a5e, 0x000a5e, 0x000a72, 0x000a74, 0x000a85, 0x000a8d, 0x000a8f, 0x000a91, 0x000a93, 0x000aa8, 0x000aaa, 0x000ab0, 0x000ab2, + 0x000ab3, 0x000ab5, 0x000ab9, 0x000abd, 0x000abd, 0x000ad0, 0x000ad0, 0x000ae0, 0x000ae1, 0x000af9, 0x000af9, 0x000b05, 0x000b0c, 0x000b0f, 0x000b10, 0x000b13, 0x000b28, + 0x000b2a, 0x000b30, 0x000b32, 0x000b33, 0x000b35, 0x000b39, 0x000b3d, 0x000b3d, 0x000b5c, 0x000b5d, 0x000b5f, 0x000b61, 0x000b71, 0x000b71, 0x000b83, 0x000b83, 0x000b85, + 0x000b8a, 0x000b8e, 0x000b90, 0x000b92, 0x000b95, 0x000b99, 0x000b9a, 0x000b9c, 0x000b9c, 0x000b9e, 0x000b9f, 0x000ba3, 0x000ba4, 0x000ba8, 0x000baa, 0x000bae, 0x000bb9, + 0x000bd0, 0x000bd0, 0x000c05, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c3d, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, 0x000c60, + 0x000c61, 0x000c80, 0x000c80, 0x000c85, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbd, 0x000cbd, 0x000cdd, 0x000cde, + 0x000ce0, 0x000ce1, 0x000cf1, 0x000cf2, 0x000d04, 0x000d0c, 0x000d0e, 0x000d10, 0x000d12, 0x000d3a, 0x000d3d, 0x000d3d, 0x000d4e, 0x000d4e, 0x000d54, 0x000d56, 0x000d5f, + 0x000d61, 0x000d7a, 0x000d7f, 0x000d85, 0x000d96, 0x000d9a, 0x000db1, 0x000db3, 0x000dbb, 0x000dbd, 0x000dbd, 0x000dc0, 0x000dc6, 0x000e01, 0x000e30, 0x000e32, 0x000e33, + 0x000e40, 0x000e45, 0x000e81, 0x000e82, 0x000e84, 0x000e84, 0x000e86, 0x000e8a, 0x000e8c, 0x000ea3, 0x000ea5, 0x000ea5, 0x000ea7, 0x000eb0, 0x000eb2, 0x000eb3, 0x000ebd, + 0x000ebd, 0x000ec0, 0x000ec4, 0x000edc, 0x000edf, 0x000f00, 0x000f00, 0x000f40, 0x000f47, 0x000f49, 0x000f6c, 0x000f88, 0x000f8c, 0x001000, 0x00102a, 0x00103f, 0x00103f, + 0x001050, 0x001055, 0x00105a, 0x00105d, 0x001061, 0x001061, 0x001065, 0x001066, 0x00106e, 0x001070, 0x001075, 0x001081, 0x00108e, 0x00108e, 0x001100, 0x001248, 0x00124a, + 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, + 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, 0x00135a, 0x001380, 0x00138f, 0x001401, 0x00166c, 0x00166f, + 0x00167f, 0x001681, 0x00169a, 0x0016a0, 0x0016ea, 0x0016f1, 0x0016f8, 0x001700, 0x001711, 0x00171f, 0x001731, 0x001740, 0x001751, 0x001760, 0x00176c, 0x00176e, 0x001770, + 0x001780, 0x0017b3, 0x0017dc, 0x0017dc, 0x001820, 0x001842, 0x001844, 0x001878, 0x001880, 0x001884, 0x001887, 0x0018a8, 0x0018aa, 0x0018aa, 0x0018b0, 0x0018f5, 0x001900, + 0x00191e, 0x001950, 0x00196d, 0x001970, 0x001974, 0x001980, 0x0019ab, 0x0019b0, 0x0019c9, 0x001a00, 0x001a16, 0x001a20, 0x001a54, 0x001b05, 0x001b33, 0x001b45, 0x001b4c, + 0x001b83, 0x001ba0, 0x001bae, 0x001baf, 0x001bba, 0x001be5, 0x001c00, 0x001c23, 0x001c4d, 0x001c4f, 0x001c5a, 0x001c77, 0x001ce9, 0x001cec, 0x001cee, 0x001cf3, 0x001cf5, + 0x001cf6, 0x001cfa, 0x001cfa, 0x002135, 0x002138, 0x002d30, 0x002d67, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, + 0x002dc0, 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x003006, 0x003006, 0x00303c, 0x00303c, 0x003041, 0x003096, 0x00309f, 0x00309f, 0x0030a1, + 0x0030fa, 0x0030ff, 0x0030ff, 0x003105, 0x00312f, 0x003131, 0x00318e, 0x0031a0, 0x0031bf, 0x0031f0, 0x0031ff, 0x003400, 0x004dbf, 0x004e00, 0x00a014, 0x00a016, 0x00a48c, 0x00a4d0, 0x00a4f7, 0x00a500, 0x00a60b, 0x00a610, 0x00a61f, 0x00a62a, 0x00a62b, 0x00a66e, 0x00a66e, 0x00a6a0, 0x00a6e5, 0x00a78f, 0x00a78f, 0x00a7f7, 0x00a7f7, 0x00a7fb, 0x00a801, 0x00a803, 0x00a805, 0x00a807, 0x00a80a, 0x00a80c, 0x00a822, 0x00a840, 0x00a873, 0x00a882, 0x00a8b3, 0x00a8f2, 0x00a8f7, 0x00a8fb, 0x00a8fb, 0x00a8fd, 0x00a8fe, 0x00a90a, 0x00a925, 0x00a930, 0x00a946, 0x00a960, 0x00a97c, 0x00a984, 0x00a9b2, 0x00a9e0, 0x00a9e4, 0x00a9e7, 0x00a9ef, 0x00a9fa, 0x00a9fe, 0x00aa00, 0x00aa28, 0x00aa40, @@ -2782,24 +2840,26 @@ private static void populateGC_LO() { 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x010855, 0x010860, 0x010876, 0x010880, 0x01089e, 0x0108e0, 0x0108f2, 0x0108f4, 0x0108f5, 0x010900, 0x010915, 0x010920, 0x010939, 0x010980, 0x0109b7, 0x0109be, 0x0109bf, 0x010a00, 0x010a00, 0x010a10, 0x010a13, 0x010a15, 0x010a17, 0x010a19, 0x010a35, 0x010a60, 0x010a7c, 0x010a80, 0x010a9c, 0x010ac0, 0x010ac7, 0x010ac9, 0x010ae4, 0x010b00, 0x010b35, 0x010b40, 0x010b55, 0x010b60, 0x010b72, 0x010b80, 0x010b91, - 0x010c00, 0x010c48, 0x010d00, 0x010d23, 0x010e80, 0x010ea9, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f45, 0x010fb0, 0x010fc4, 0x010fe0, - 0x010ff6, 0x011003, 0x011037, 0x011083, 0x0110af, 0x0110d0, 0x0110e8, 0x011103, 0x011126, 0x011144, 0x011144, 0x011147, 0x011147, 0x011150, 0x011172, 0x011176, 0x011176, - 0x011183, 0x0111b2, 0x0111c1, 0x0111c4, 0x0111da, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, 0x01122b, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, - 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112de, 0x011305, 0x01130c, 0x01130f, 0x011310, 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, - 0x011335, 0x011339, 0x01133d, 0x01133d, 0x011350, 0x011350, 0x01135d, 0x011361, 0x011400, 0x011434, 0x011447, 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114af, 0x0114c4, - 0x0114c5, 0x0114c7, 0x0114c7, 0x011580, 0x0115ae, 0x0115d8, 0x0115db, 0x011600, 0x01162f, 0x011644, 0x011644, 0x011680, 0x0116aa, 0x0116b8, 0x0116b8, 0x011700, 0x01171a, - 0x011800, 0x01182b, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, 0x011916, 0x011918, 0x01192f, 0x01193f, 0x01193f, 0x011941, 0x011941, 0x0119a0, - 0x0119a7, 0x0119aa, 0x0119d0, 0x0119e1, 0x0119e1, 0x0119e3, 0x0119e3, 0x011a00, 0x011a00, 0x011a0b, 0x011a32, 0x011a3a, 0x011a3a, 0x011a50, 0x011a50, 0x011a5c, 0x011a89, - 0x011a9d, 0x011a9d, 0x011ac0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c2e, 0x011c40, 0x011c40, 0x011c72, 0x011c8f, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, - 0x011d30, 0x011d46, 0x011d46, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d89, 0x011d98, 0x011d98, 0x011ee0, 0x011ef2, 0x011fb0, 0x011fb0, 0x012000, 0x012399, - 0x012480, 0x012543, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, 0x016a38, 0x016a40, 0x016a5e, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, 0x016b63, 0x016b77, 0x016b7d, - 0x016b8f, 0x016f00, 0x016f4a, 0x016f50, 0x016f50, 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b11e, 0x01b150, 0x01b152, 0x01b164, 0x01b167, - 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01e100, 0x01e12c, 0x01e14e, 0x01e14e, 0x01e2c0, 0x01e2eb, 0x01e800, - 0x01e8c4, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, - 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, - 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, - 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x020000, - 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); + 0x010c00, 0x010c48, 0x010d00, 0x010d23, 0x010e80, 0x010ea9, 0x010eb0, 0x010eb1, 0x010f00, 0x010f1c, 0x010f27, 0x010f27, 0x010f30, 0x010f45, 0x010f70, 0x010f81, 0x010fb0, + 0x010fc4, 0x010fe0, 0x010ff6, 0x011003, 0x011037, 0x011071, 0x011072, 0x011075, 0x011075, 0x011083, 0x0110af, 0x0110d0, 0x0110e8, 0x011103, 0x011126, 0x011144, 0x011144, + 0x011147, 0x011147, 0x011150, 0x011172, 0x011176, 0x011176, 0x011183, 0x0111b2, 0x0111c1, 0x0111c4, 0x0111da, 0x0111da, 0x0111dc, 0x0111dc, 0x011200, 0x011211, 0x011213, + 0x01122b, 0x011280, 0x011286, 0x011288, 0x011288, 0x01128a, 0x01128d, 0x01128f, 0x01129d, 0x01129f, 0x0112a8, 0x0112b0, 0x0112de, 0x011305, 0x01130c, 0x01130f, 0x011310, + 0x011313, 0x011328, 0x01132a, 0x011330, 0x011332, 0x011333, 0x011335, 0x011339, 0x01133d, 0x01133d, 0x011350, 0x011350, 0x01135d, 0x011361, 0x011400, 0x011434, 0x011447, + 0x01144a, 0x01145f, 0x011461, 0x011480, 0x0114af, 0x0114c4, 0x0114c5, 0x0114c7, 0x0114c7, 0x011580, 0x0115ae, 0x0115d8, 0x0115db, 0x011600, 0x01162f, 0x011644, 0x011644, + 0x011680, 0x0116aa, 0x0116b8, 0x0116b8, 0x011700, 0x01171a, 0x011740, 0x011746, 0x011800, 0x01182b, 0x0118ff, 0x011906, 0x011909, 0x011909, 0x01190c, 0x011913, 0x011915, + 0x011916, 0x011918, 0x01192f, 0x01193f, 0x01193f, 0x011941, 0x011941, 0x0119a0, 0x0119a7, 0x0119aa, 0x0119d0, 0x0119e1, 0x0119e1, 0x0119e3, 0x0119e3, 0x011a00, 0x011a00, + 0x011a0b, 0x011a32, 0x011a3a, 0x011a3a, 0x011a50, 0x011a50, 0x011a5c, 0x011a89, 0x011a9d, 0x011a9d, 0x011ab0, 0x011af8, 0x011c00, 0x011c08, 0x011c0a, 0x011c2e, 0x011c40, + 0x011c40, 0x011c72, 0x011c8f, 0x011d00, 0x011d06, 0x011d08, 0x011d09, 0x011d0b, 0x011d30, 0x011d46, 0x011d46, 0x011d60, 0x011d65, 0x011d67, 0x011d68, 0x011d6a, 0x011d89, + 0x011d98, 0x011d98, 0x011ee0, 0x011ef2, 0x011fb0, 0x011fb0, 0x012000, 0x012399, 0x012480, 0x012543, 0x012f90, 0x012ff0, 0x013000, 0x01342e, 0x014400, 0x014646, 0x016800, + 0x016a38, 0x016a40, 0x016a5e, 0x016a70, 0x016abe, 0x016ad0, 0x016aed, 0x016b00, 0x016b2f, 0x016b63, 0x016b77, 0x016b7d, 0x016b8f, 0x016f00, 0x016f4a, 0x016f50, 0x016f50, + 0x017000, 0x0187f7, 0x018800, 0x018cd5, 0x018d00, 0x018d08, 0x01b000, 0x01b122, 0x01b150, 0x01b152, 0x01b164, 0x01b167, 0x01b170, 0x01b2fb, 0x01bc00, 0x01bc6a, 0x01bc70, + 0x01bc7c, 0x01bc80, 0x01bc88, 0x01bc90, 0x01bc99, 0x01df0a, 0x01df0a, 0x01e100, 0x01e12c, 0x01e14e, 0x01e14e, 0x01e290, 0x01e2ad, 0x01e2c0, 0x01e2eb, 0x01e7e0, 0x01e7e6, + 0x01e7e8, 0x01e7eb, 0x01e7ed, 0x01e7ee, 0x01e7f0, 0x01e7fe, 0x01e800, 0x01e8c4, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, + 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, + 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, + 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, + 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, + 0x02fa1d, 0x030000, 0x03134a)); } private static void populateGC_LT() { @@ -2859,7 +2919,7 @@ private static void populateGC_LU() { 0x001f48, 0x001f4d, 0x001f59, 0x001f59, 0x001f5b, 0x001f5b, 0x001f5d, 0x001f5d, 0x001f5f, 0x001f5f, 0x001f68, 0x001f6f, 0x001fb8, 0x001fbb, 0x001fc8, 0x001fcb, 0x001fd8, 0x001fdb, 0x001fe8, 0x001fec, 0x001ff8, 0x001ffb, 0x002102, 0x002102, 0x002107, 0x002107, 0x00210b, 0x00210d, 0x002110, 0x002112, 0x002115, 0x002115, 0x002119, 0x00211d, 0x002124, 0x002124, 0x002126, 0x002126, 0x002128, 0x002128, 0x00212a, 0x00212d, 0x002130, 0x002133, 0x00213e, 0x00213f, 0x002145, 0x002145, 0x002183, 0x002183, 0x002c00, - 0x002c2e, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, 0x002c69, 0x002c69, 0x002c6b, 0x002c6b, 0x002c6d, 0x002c70, 0x002c72, 0x002c72, 0x002c75, 0x002c75, + 0x002c2f, 0x002c60, 0x002c60, 0x002c62, 0x002c64, 0x002c67, 0x002c67, 0x002c69, 0x002c69, 0x002c6b, 0x002c6b, 0x002c6d, 0x002c70, 0x002c72, 0x002c72, 0x002c75, 0x002c75, 0x002c7e, 0x002c80, 0x002c82, 0x002c82, 0x002c84, 0x002c84, 0x002c86, 0x002c86, 0x002c88, 0x002c88, 0x002c8a, 0x002c8a, 0x002c8c, 0x002c8c, 0x002c8e, 0x002c8e, 0x002c90, 0x002c90, 0x002c92, 0x002c92, 0x002c94, 0x002c94, 0x002c96, 0x002c96, 0x002c98, 0x002c98, 0x002c9a, 0x002c9a, 0x002c9c, 0x002c9c, 0x002c9e, 0x002c9e, 0x002ca0, 0x002ca0, 0x002ca2, 0x002ca2, 0x002ca4, 0x002ca4, 0x002ca6, 0x002ca6, 0x002ca8, 0x002ca8, 0x002caa, 0x002caa, 0x002cac, 0x002cac, 0x002cae, 0x002cae, 0x002cb0, 0x002cb0, 0x002cb2, @@ -2878,12 +2938,13 @@ private static void populateGC_LU() { 0x00a76e, 0x00a779, 0x00a779, 0x00a77b, 0x00a77b, 0x00a77d, 0x00a77e, 0x00a780, 0x00a780, 0x00a782, 0x00a782, 0x00a784, 0x00a784, 0x00a786, 0x00a786, 0x00a78b, 0x00a78b, 0x00a78d, 0x00a78d, 0x00a790, 0x00a790, 0x00a792, 0x00a792, 0x00a796, 0x00a796, 0x00a798, 0x00a798, 0x00a79a, 0x00a79a, 0x00a79c, 0x00a79c, 0x00a79e, 0x00a79e, 0x00a7a0, 0x00a7a0, 0x00a7a2, 0x00a7a2, 0x00a7a4, 0x00a7a4, 0x00a7a6, 0x00a7a6, 0x00a7a8, 0x00a7a8, 0x00a7aa, 0x00a7ae, 0x00a7b0, 0x00a7b4, 0x00a7b6, 0x00a7b6, 0x00a7b8, 0x00a7b8, - 0x00a7ba, 0x00a7ba, 0x00a7bc, 0x00a7bc, 0x00a7be, 0x00a7be, 0x00a7c2, 0x00a7c2, 0x00a7c4, 0x00a7c7, 0x00a7c9, 0x00a7c9, 0x00a7f5, 0x00a7f5, 0x00ff21, 0x00ff3a, 0x010400, - 0x010427, 0x0104b0, 0x0104d3, 0x010c80, 0x010cb2, 0x0118a0, 0x0118bf, 0x016e40, 0x016e5f, 0x01d400, 0x01d419, 0x01d434, 0x01d44d, 0x01d468, 0x01d481, 0x01d49c, 0x01d49c, - 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b5, 0x01d4d0, 0x01d4e9, 0x01d504, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, - 0x01d514, 0x01d516, 0x01d51c, 0x01d538, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d56c, 0x01d585, 0x01d5a0, 0x01d5b9, - 0x01d5d4, 0x01d5ed, 0x01d608, 0x01d621, 0x01d63c, 0x01d655, 0x01d670, 0x01d689, 0x01d6a8, 0x01d6c0, 0x01d6e2, 0x01d6fa, 0x01d71c, 0x01d734, 0x01d756, 0x01d76e, 0x01d790, - 0x01d7a8, 0x01d7ca, 0x01d7ca, 0x01e900, 0x01e921)); + 0x00a7ba, 0x00a7ba, 0x00a7bc, 0x00a7bc, 0x00a7be, 0x00a7be, 0x00a7c0, 0x00a7c0, 0x00a7c2, 0x00a7c2, 0x00a7c4, 0x00a7c7, 0x00a7c9, 0x00a7c9, 0x00a7d0, 0x00a7d0, 0x00a7d6, + 0x00a7d6, 0x00a7d8, 0x00a7d8, 0x00a7f5, 0x00a7f5, 0x00ff21, 0x00ff3a, 0x010400, 0x010427, 0x0104b0, 0x0104d3, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, + 0x010594, 0x010595, 0x010c80, 0x010cb2, 0x0118a0, 0x0118bf, 0x016e40, 0x016e5f, 0x01d400, 0x01d419, 0x01d434, 0x01d44d, 0x01d468, 0x01d481, 0x01d49c, 0x01d49c, 0x01d49e, + 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b5, 0x01d4d0, 0x01d4e9, 0x01d504, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, + 0x01d516, 0x01d51c, 0x01d538, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d56c, 0x01d585, 0x01d5a0, 0x01d5b9, 0x01d5d4, + 0x01d5ed, 0x01d608, 0x01d621, 0x01d63c, 0x01d655, 0x01d670, 0x01d689, 0x01d6a8, 0x01d6c0, 0x01d6e2, 0x01d6fa, 0x01d71c, 0x01d734, 0x01d756, 0x01d76e, 0x01d790, 0x01d7a8, + 0x01d7ca, 0x01d7ca, 0x01e900, 0x01e921)); } private static void populateGC_MC() { @@ -2893,21 +2954,22 @@ private static void populateGC_MC() { 0x000bc2, 0x000bc6, 0x000bc8, 0x000bca, 0x000bcc, 0x000bd7, 0x000bd7, 0x000c01, 0x000c03, 0x000c41, 0x000c44, 0x000c82, 0x000c83, 0x000cbe, 0x000cbe, 0x000cc0, 0x000cc4, 0x000cc7, 0x000cc8, 0x000cca, 0x000ccb, 0x000cd5, 0x000cd6, 0x000d02, 0x000d03, 0x000d3e, 0x000d40, 0x000d46, 0x000d48, 0x000d4a, 0x000d4c, 0x000d57, 0x000d57, 0x000d82, 0x000d83, 0x000dcf, 0x000dd1, 0x000dd8, 0x000ddf, 0x000df2, 0x000df3, 0x000f3e, 0x000f3f, 0x000f7f, 0x000f7f, 0x00102b, 0x00102c, 0x001031, 0x001031, 0x001038, 0x001038, - 0x00103b, 0x00103c, 0x001056, 0x001057, 0x001062, 0x001064, 0x001067, 0x00106d, 0x001083, 0x001084, 0x001087, 0x00108c, 0x00108f, 0x00108f, 0x00109a, 0x00109c, 0x0017b6, - 0x0017b6, 0x0017be, 0x0017c5, 0x0017c7, 0x0017c8, 0x001923, 0x001926, 0x001929, 0x00192b, 0x001930, 0x001931, 0x001933, 0x001938, 0x001a19, 0x001a1a, 0x001a55, 0x001a55, - 0x001a57, 0x001a57, 0x001a61, 0x001a61, 0x001a63, 0x001a64, 0x001a6d, 0x001a72, 0x001b04, 0x001b04, 0x001b35, 0x001b35, 0x001b3b, 0x001b3b, 0x001b3d, 0x001b41, 0x001b43, - 0x001b44, 0x001b82, 0x001b82, 0x001ba1, 0x001ba1, 0x001ba6, 0x001ba7, 0x001baa, 0x001baa, 0x001be7, 0x001be7, 0x001bea, 0x001bec, 0x001bee, 0x001bee, 0x001bf2, 0x001bf3, - 0x001c24, 0x001c2b, 0x001c34, 0x001c35, 0x001ce1, 0x001ce1, 0x001cf7, 0x001cf7, 0x00302e, 0x00302f, 0x00a823, 0x00a824, 0x00a827, 0x00a827, 0x00a880, 0x00a881, 0x00a8b4, - 0x00a8c3, 0x00a952, 0x00a953, 0x00a983, 0x00a983, 0x00a9b4, 0x00a9b5, 0x00a9ba, 0x00a9bb, 0x00a9be, 0x00a9c0, 0x00aa2f, 0x00aa30, 0x00aa33, 0x00aa34, 0x00aa4d, 0x00aa4d, - 0x00aa7b, 0x00aa7b, 0x00aa7d, 0x00aa7d, 0x00aaeb, 0x00aaeb, 0x00aaee, 0x00aaef, 0x00aaf5, 0x00aaf5, 0x00abe3, 0x00abe4, 0x00abe6, 0x00abe7, 0x00abe9, 0x00abea, 0x00abec, - 0x00abec, 0x011000, 0x011000, 0x011002, 0x011002, 0x011082, 0x011082, 0x0110b0, 0x0110b2, 0x0110b7, 0x0110b8, 0x01112c, 0x01112c, 0x011145, 0x011146, 0x011182, 0x011182, - 0x0111b3, 0x0111b5, 0x0111bf, 0x0111c0, 0x0111ce, 0x0111ce, 0x01122c, 0x01122e, 0x011232, 0x011233, 0x011235, 0x011235, 0x0112e0, 0x0112e2, 0x011302, 0x011303, 0x01133e, - 0x01133f, 0x011341, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, 0x011357, 0x011357, 0x011362, 0x011363, 0x011435, 0x011437, 0x011440, 0x011441, 0x011445, 0x011445, - 0x0114b0, 0x0114b2, 0x0114b9, 0x0114b9, 0x0114bb, 0x0114be, 0x0114c1, 0x0114c1, 0x0115af, 0x0115b1, 0x0115b8, 0x0115bb, 0x0115be, 0x0115be, 0x011630, 0x011632, 0x01163b, - 0x01163c, 0x01163e, 0x01163e, 0x0116ac, 0x0116ac, 0x0116ae, 0x0116af, 0x0116b6, 0x0116b6, 0x011720, 0x011721, 0x011726, 0x011726, 0x01182c, 0x01182e, 0x011838, 0x011838, - 0x011930, 0x011935, 0x011937, 0x011938, 0x01193d, 0x01193d, 0x011940, 0x011940, 0x011942, 0x011942, 0x0119d1, 0x0119d3, 0x0119dc, 0x0119df, 0x0119e4, 0x0119e4, 0x011a39, - 0x011a39, 0x011a57, 0x011a58, 0x011a97, 0x011a97, 0x011c2f, 0x011c2f, 0x011c3e, 0x011c3e, 0x011ca9, 0x011ca9, 0x011cb1, 0x011cb1, 0x011cb4, 0x011cb4, 0x011d8a, 0x011d8e, - 0x011d93, 0x011d94, 0x011d96, 0x011d96, 0x011ef5, 0x011ef6, 0x016f51, 0x016f87, 0x016ff0, 0x016ff1, 0x01d165, 0x01d166, 0x01d16d, 0x01d172)); + 0x00103b, 0x00103c, 0x001056, 0x001057, 0x001062, 0x001064, 0x001067, 0x00106d, 0x001083, 0x001084, 0x001087, 0x00108c, 0x00108f, 0x00108f, 0x00109a, 0x00109c, 0x001715, + 0x001715, 0x001734, 0x001734, 0x0017b6, 0x0017b6, 0x0017be, 0x0017c5, 0x0017c7, 0x0017c8, 0x001923, 0x001926, 0x001929, 0x00192b, 0x001930, 0x001931, 0x001933, 0x001938, + 0x001a19, 0x001a1a, 0x001a55, 0x001a55, 0x001a57, 0x001a57, 0x001a61, 0x001a61, 0x001a63, 0x001a64, 0x001a6d, 0x001a72, 0x001b04, 0x001b04, 0x001b35, 0x001b35, 0x001b3b, + 0x001b3b, 0x001b3d, 0x001b41, 0x001b43, 0x001b44, 0x001b82, 0x001b82, 0x001ba1, 0x001ba1, 0x001ba6, 0x001ba7, 0x001baa, 0x001baa, 0x001be7, 0x001be7, 0x001bea, 0x001bec, + 0x001bee, 0x001bee, 0x001bf2, 0x001bf3, 0x001c24, 0x001c2b, 0x001c34, 0x001c35, 0x001ce1, 0x001ce1, 0x001cf7, 0x001cf7, 0x00302e, 0x00302f, 0x00a823, 0x00a824, 0x00a827, + 0x00a827, 0x00a880, 0x00a881, 0x00a8b4, 0x00a8c3, 0x00a952, 0x00a953, 0x00a983, 0x00a983, 0x00a9b4, 0x00a9b5, 0x00a9ba, 0x00a9bb, 0x00a9be, 0x00a9c0, 0x00aa2f, 0x00aa30, + 0x00aa33, 0x00aa34, 0x00aa4d, 0x00aa4d, 0x00aa7b, 0x00aa7b, 0x00aa7d, 0x00aa7d, 0x00aaeb, 0x00aaeb, 0x00aaee, 0x00aaef, 0x00aaf5, 0x00aaf5, 0x00abe3, 0x00abe4, 0x00abe6, + 0x00abe7, 0x00abe9, 0x00abea, 0x00abec, 0x00abec, 0x011000, 0x011000, 0x011002, 0x011002, 0x011082, 0x011082, 0x0110b0, 0x0110b2, 0x0110b7, 0x0110b8, 0x01112c, 0x01112c, + 0x011145, 0x011146, 0x011182, 0x011182, 0x0111b3, 0x0111b5, 0x0111bf, 0x0111c0, 0x0111ce, 0x0111ce, 0x01122c, 0x01122e, 0x011232, 0x011233, 0x011235, 0x011235, 0x0112e0, + 0x0112e2, 0x011302, 0x011303, 0x01133e, 0x01133f, 0x011341, 0x011344, 0x011347, 0x011348, 0x01134b, 0x01134d, 0x011357, 0x011357, 0x011362, 0x011363, 0x011435, 0x011437, + 0x011440, 0x011441, 0x011445, 0x011445, 0x0114b0, 0x0114b2, 0x0114b9, 0x0114b9, 0x0114bb, 0x0114be, 0x0114c1, 0x0114c1, 0x0115af, 0x0115b1, 0x0115b8, 0x0115bb, 0x0115be, + 0x0115be, 0x011630, 0x011632, 0x01163b, 0x01163c, 0x01163e, 0x01163e, 0x0116ac, 0x0116ac, 0x0116ae, 0x0116af, 0x0116b6, 0x0116b6, 0x011720, 0x011721, 0x011726, 0x011726, + 0x01182c, 0x01182e, 0x011838, 0x011838, 0x011930, 0x011935, 0x011937, 0x011938, 0x01193d, 0x01193d, 0x011940, 0x011940, 0x011942, 0x011942, 0x0119d1, 0x0119d3, 0x0119dc, + 0x0119df, 0x0119e4, 0x0119e4, 0x011a39, 0x011a39, 0x011a57, 0x011a58, 0x011a97, 0x011a97, 0x011c2f, 0x011c2f, 0x011c3e, 0x011c3e, 0x011ca9, 0x011ca9, 0x011cb1, 0x011cb1, + 0x011cb4, 0x011cb4, 0x011d8a, 0x011d8e, 0x011d93, 0x011d94, 0x011d96, 0x011d96, 0x011ef5, 0x011ef6, 0x016f51, 0x016f87, 0x016ff0, 0x016ff1, 0x01d165, 0x01d166, 0x01d16d, + 0x01d172)); } private static void populateGC_ME() { @@ -2918,42 +2980,43 @@ private static void populateGC_MN() { SET_ENCODINGS.put("gc=Mn", CodePointSet.createNoDedup(0x000300, 0x00036f, 0x000483, 0x000487, 0x000591, 0x0005bd, 0x0005bf, 0x0005bf, 0x0005c1, 0x0005c2, 0x0005c4, 0x0005c5, 0x0005c7, 0x0005c7, 0x000610, 0x00061a, 0x00064b, 0x00065f, 0x000670, 0x000670, 0x0006d6, 0x0006dc, 0x0006df, 0x0006e4, 0x0006e7, 0x0006e8, 0x0006ea, 0x0006ed, 0x000711, 0x000711, 0x000730, 0x00074a, 0x0007a6, 0x0007b0, 0x0007eb, 0x0007f3, 0x0007fd, 0x0007fd, 0x000816, 0x000819, 0x00081b, 0x000823, 0x000825, 0x000827, 0x000829, 0x00082d, 0x000859, - 0x00085b, 0x0008d3, 0x0008e1, 0x0008e3, 0x000902, 0x00093a, 0x00093a, 0x00093c, 0x00093c, 0x000941, 0x000948, 0x00094d, 0x00094d, 0x000951, 0x000957, 0x000962, 0x000963, - 0x000981, 0x000981, 0x0009bc, 0x0009bc, 0x0009c1, 0x0009c4, 0x0009cd, 0x0009cd, 0x0009e2, 0x0009e3, 0x0009fe, 0x0009fe, 0x000a01, 0x000a02, 0x000a3c, 0x000a3c, 0x000a41, - 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4d, 0x000a51, 0x000a51, 0x000a70, 0x000a71, 0x000a75, 0x000a75, 0x000a81, 0x000a82, 0x000abc, 0x000abc, 0x000ac1, 0x000ac5, - 0x000ac7, 0x000ac8, 0x000acd, 0x000acd, 0x000ae2, 0x000ae3, 0x000afa, 0x000aff, 0x000b01, 0x000b01, 0x000b3c, 0x000b3c, 0x000b3f, 0x000b3f, 0x000b41, 0x000b44, 0x000b4d, - 0x000b4d, 0x000b55, 0x000b56, 0x000b62, 0x000b63, 0x000b82, 0x000b82, 0x000bc0, 0x000bc0, 0x000bcd, 0x000bcd, 0x000c00, 0x000c00, 0x000c04, 0x000c04, 0x000c3e, 0x000c40, - 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c62, 0x000c63, 0x000c81, 0x000c81, 0x000cbc, 0x000cbc, 0x000cbf, 0x000cbf, 0x000cc6, 0x000cc6, 0x000ccc, - 0x000ccd, 0x000ce2, 0x000ce3, 0x000d00, 0x000d01, 0x000d3b, 0x000d3c, 0x000d41, 0x000d44, 0x000d4d, 0x000d4d, 0x000d62, 0x000d63, 0x000d81, 0x000d81, 0x000dca, 0x000dca, - 0x000dd2, 0x000dd4, 0x000dd6, 0x000dd6, 0x000e31, 0x000e31, 0x000e34, 0x000e3a, 0x000e47, 0x000e4e, 0x000eb1, 0x000eb1, 0x000eb4, 0x000ebc, 0x000ec8, 0x000ecd, 0x000f18, - 0x000f19, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f71, 0x000f7e, 0x000f80, 0x000f84, 0x000f86, 0x000f87, 0x000f8d, 0x000f97, 0x000f99, 0x000fbc, - 0x000fc6, 0x000fc6, 0x00102d, 0x001030, 0x001032, 0x001037, 0x001039, 0x00103a, 0x00103d, 0x00103e, 0x001058, 0x001059, 0x00105e, 0x001060, 0x001071, 0x001074, 0x001082, - 0x001082, 0x001085, 0x001086, 0x00108d, 0x00108d, 0x00109d, 0x00109d, 0x00135d, 0x00135f, 0x001712, 0x001714, 0x001732, 0x001734, 0x001752, 0x001753, 0x001772, 0x001773, - 0x0017b4, 0x0017b5, 0x0017b7, 0x0017bd, 0x0017c6, 0x0017c6, 0x0017c9, 0x0017d3, 0x0017dd, 0x0017dd, 0x00180b, 0x00180d, 0x001885, 0x001886, 0x0018a9, 0x0018a9, 0x001920, - 0x001922, 0x001927, 0x001928, 0x001932, 0x001932, 0x001939, 0x00193b, 0x001a17, 0x001a18, 0x001a1b, 0x001a1b, 0x001a56, 0x001a56, 0x001a58, 0x001a5e, 0x001a60, 0x001a60, - 0x001a62, 0x001a62, 0x001a65, 0x001a6c, 0x001a73, 0x001a7c, 0x001a7f, 0x001a7f, 0x001ab0, 0x001abd, 0x001abf, 0x001ac0, 0x001b00, 0x001b03, 0x001b34, 0x001b34, 0x001b36, - 0x001b3a, 0x001b3c, 0x001b3c, 0x001b42, 0x001b42, 0x001b6b, 0x001b73, 0x001b80, 0x001b81, 0x001ba2, 0x001ba5, 0x001ba8, 0x001ba9, 0x001bab, 0x001bad, 0x001be6, 0x001be6, - 0x001be8, 0x001be9, 0x001bed, 0x001bed, 0x001bef, 0x001bf1, 0x001c2c, 0x001c33, 0x001c36, 0x001c37, 0x001cd0, 0x001cd2, 0x001cd4, 0x001ce0, 0x001ce2, 0x001ce8, 0x001ced, - 0x001ced, 0x001cf4, 0x001cf4, 0x001cf8, 0x001cf9, 0x001dc0, 0x001df9, 0x001dfb, 0x001dff, 0x0020d0, 0x0020dc, 0x0020e1, 0x0020e1, 0x0020e5, 0x0020f0, 0x002cef, 0x002cf1, - 0x002d7f, 0x002d7f, 0x002de0, 0x002dff, 0x00302a, 0x00302d, 0x003099, 0x00309a, 0x00a66f, 0x00a66f, 0x00a674, 0x00a67d, 0x00a69e, 0x00a69f, 0x00a6f0, 0x00a6f1, 0x00a802, - 0x00a802, 0x00a806, 0x00a806, 0x00a80b, 0x00a80b, 0x00a825, 0x00a826, 0x00a82c, 0x00a82c, 0x00a8c4, 0x00a8c5, 0x00a8e0, 0x00a8f1, 0x00a8ff, 0x00a8ff, 0x00a926, 0x00a92d, - 0x00a947, 0x00a951, 0x00a980, 0x00a982, 0x00a9b3, 0x00a9b3, 0x00a9b6, 0x00a9b9, 0x00a9bc, 0x00a9bd, 0x00a9e5, 0x00a9e5, 0x00aa29, 0x00aa2e, 0x00aa31, 0x00aa32, 0x00aa35, - 0x00aa36, 0x00aa43, 0x00aa43, 0x00aa4c, 0x00aa4c, 0x00aa7c, 0x00aa7c, 0x00aab0, 0x00aab0, 0x00aab2, 0x00aab4, 0x00aab7, 0x00aab8, 0x00aabe, 0x00aabf, 0x00aac1, 0x00aac1, - 0x00aaec, 0x00aaed, 0x00aaf6, 0x00aaf6, 0x00abe5, 0x00abe5, 0x00abe8, 0x00abe8, 0x00abed, 0x00abed, 0x00fb1e, 0x00fb1e, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2f, 0x0101fd, - 0x0101fd, 0x0102e0, 0x0102e0, 0x010376, 0x01037a, 0x010a01, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a0f, 0x010a38, 0x010a3a, 0x010a3f, 0x010a3f, 0x010ae5, 0x010ae6, - 0x010d24, 0x010d27, 0x010eab, 0x010eac, 0x010f46, 0x010f50, 0x011001, 0x011001, 0x011038, 0x011046, 0x01107f, 0x011081, 0x0110b3, 0x0110b6, 0x0110b9, 0x0110ba, 0x011100, - 0x011102, 0x011127, 0x01112b, 0x01112d, 0x011134, 0x011173, 0x011173, 0x011180, 0x011181, 0x0111b6, 0x0111be, 0x0111c9, 0x0111cc, 0x0111cf, 0x0111cf, 0x01122f, 0x011231, - 0x011234, 0x011234, 0x011236, 0x011237, 0x01123e, 0x01123e, 0x0112df, 0x0112df, 0x0112e3, 0x0112ea, 0x011300, 0x011301, 0x01133b, 0x01133c, 0x011340, 0x011340, 0x011366, - 0x01136c, 0x011370, 0x011374, 0x011438, 0x01143f, 0x011442, 0x011444, 0x011446, 0x011446, 0x01145e, 0x01145e, 0x0114b3, 0x0114b8, 0x0114ba, 0x0114ba, 0x0114bf, 0x0114c0, - 0x0114c2, 0x0114c3, 0x0115b2, 0x0115b5, 0x0115bc, 0x0115bd, 0x0115bf, 0x0115c0, 0x0115dc, 0x0115dd, 0x011633, 0x01163a, 0x01163d, 0x01163d, 0x01163f, 0x011640, 0x0116ab, - 0x0116ab, 0x0116ad, 0x0116ad, 0x0116b0, 0x0116b5, 0x0116b7, 0x0116b7, 0x01171d, 0x01171f, 0x011722, 0x011725, 0x011727, 0x01172b, 0x01182f, 0x011837, 0x011839, 0x01183a, - 0x01193b, 0x01193c, 0x01193e, 0x01193e, 0x011943, 0x011943, 0x0119d4, 0x0119d7, 0x0119da, 0x0119db, 0x0119e0, 0x0119e0, 0x011a01, 0x011a0a, 0x011a33, 0x011a38, 0x011a3b, - 0x011a3e, 0x011a47, 0x011a47, 0x011a51, 0x011a56, 0x011a59, 0x011a5b, 0x011a8a, 0x011a96, 0x011a98, 0x011a99, 0x011c30, 0x011c36, 0x011c38, 0x011c3d, 0x011c3f, 0x011c3f, - 0x011c92, 0x011ca7, 0x011caa, 0x011cb0, 0x011cb2, 0x011cb3, 0x011cb5, 0x011cb6, 0x011d31, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d45, 0x011d47, - 0x011d47, 0x011d90, 0x011d91, 0x011d95, 0x011d95, 0x011d97, 0x011d97, 0x011ef3, 0x011ef4, 0x016af0, 0x016af4, 0x016b30, 0x016b36, 0x016f4f, 0x016f4f, 0x016f8f, 0x016f92, - 0x016fe4, 0x016fe4, 0x01bc9d, 0x01bc9e, 0x01d167, 0x01d169, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, 0x01d244, 0x01da00, 0x01da36, 0x01da3b, - 0x01da6c, 0x01da75, 0x01da75, 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, - 0x01e026, 0x01e02a, 0x01e130, 0x01e136, 0x01e2ec, 0x01e2ef, 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e94a, 0x0e0100, 0x0e01ef)); + 0x00085b, 0x000898, 0x00089f, 0x0008ca, 0x0008e1, 0x0008e3, 0x000902, 0x00093a, 0x00093a, 0x00093c, 0x00093c, 0x000941, 0x000948, 0x00094d, 0x00094d, 0x000951, 0x000957, + 0x000962, 0x000963, 0x000981, 0x000981, 0x0009bc, 0x0009bc, 0x0009c1, 0x0009c4, 0x0009cd, 0x0009cd, 0x0009e2, 0x0009e3, 0x0009fe, 0x0009fe, 0x000a01, 0x000a02, 0x000a3c, + 0x000a3c, 0x000a41, 0x000a42, 0x000a47, 0x000a48, 0x000a4b, 0x000a4d, 0x000a51, 0x000a51, 0x000a70, 0x000a71, 0x000a75, 0x000a75, 0x000a81, 0x000a82, 0x000abc, 0x000abc, + 0x000ac1, 0x000ac5, 0x000ac7, 0x000ac8, 0x000acd, 0x000acd, 0x000ae2, 0x000ae3, 0x000afa, 0x000aff, 0x000b01, 0x000b01, 0x000b3c, 0x000b3c, 0x000b3f, 0x000b3f, 0x000b41, + 0x000b44, 0x000b4d, 0x000b4d, 0x000b55, 0x000b56, 0x000b62, 0x000b63, 0x000b82, 0x000b82, 0x000bc0, 0x000bc0, 0x000bcd, 0x000bcd, 0x000c00, 0x000c00, 0x000c04, 0x000c04, + 0x000c3c, 0x000c3c, 0x000c3e, 0x000c40, 0x000c46, 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c62, 0x000c63, 0x000c81, 0x000c81, 0x000cbc, 0x000cbc, 0x000cbf, + 0x000cbf, 0x000cc6, 0x000cc6, 0x000ccc, 0x000ccd, 0x000ce2, 0x000ce3, 0x000d00, 0x000d01, 0x000d3b, 0x000d3c, 0x000d41, 0x000d44, 0x000d4d, 0x000d4d, 0x000d62, 0x000d63, + 0x000d81, 0x000d81, 0x000dca, 0x000dca, 0x000dd2, 0x000dd4, 0x000dd6, 0x000dd6, 0x000e31, 0x000e31, 0x000e34, 0x000e3a, 0x000e47, 0x000e4e, 0x000eb1, 0x000eb1, 0x000eb4, + 0x000ebc, 0x000ec8, 0x000ecd, 0x000f18, 0x000f19, 0x000f35, 0x000f35, 0x000f37, 0x000f37, 0x000f39, 0x000f39, 0x000f71, 0x000f7e, 0x000f80, 0x000f84, 0x000f86, 0x000f87, + 0x000f8d, 0x000f97, 0x000f99, 0x000fbc, 0x000fc6, 0x000fc6, 0x00102d, 0x001030, 0x001032, 0x001037, 0x001039, 0x00103a, 0x00103d, 0x00103e, 0x001058, 0x001059, 0x00105e, + 0x001060, 0x001071, 0x001074, 0x001082, 0x001082, 0x001085, 0x001086, 0x00108d, 0x00108d, 0x00109d, 0x00109d, 0x00135d, 0x00135f, 0x001712, 0x001714, 0x001732, 0x001733, + 0x001752, 0x001753, 0x001772, 0x001773, 0x0017b4, 0x0017b5, 0x0017b7, 0x0017bd, 0x0017c6, 0x0017c6, 0x0017c9, 0x0017d3, 0x0017dd, 0x0017dd, 0x00180b, 0x00180d, 0x00180f, + 0x00180f, 0x001885, 0x001886, 0x0018a9, 0x0018a9, 0x001920, 0x001922, 0x001927, 0x001928, 0x001932, 0x001932, 0x001939, 0x00193b, 0x001a17, 0x001a18, 0x001a1b, 0x001a1b, + 0x001a56, 0x001a56, 0x001a58, 0x001a5e, 0x001a60, 0x001a60, 0x001a62, 0x001a62, 0x001a65, 0x001a6c, 0x001a73, 0x001a7c, 0x001a7f, 0x001a7f, 0x001ab0, 0x001abd, 0x001abf, + 0x001ace, 0x001b00, 0x001b03, 0x001b34, 0x001b34, 0x001b36, 0x001b3a, 0x001b3c, 0x001b3c, 0x001b42, 0x001b42, 0x001b6b, 0x001b73, 0x001b80, 0x001b81, 0x001ba2, 0x001ba5, + 0x001ba8, 0x001ba9, 0x001bab, 0x001bad, 0x001be6, 0x001be6, 0x001be8, 0x001be9, 0x001bed, 0x001bed, 0x001bef, 0x001bf1, 0x001c2c, 0x001c33, 0x001c36, 0x001c37, 0x001cd0, + 0x001cd2, 0x001cd4, 0x001ce0, 0x001ce2, 0x001ce8, 0x001ced, 0x001ced, 0x001cf4, 0x001cf4, 0x001cf8, 0x001cf9, 0x001dc0, 0x001dff, 0x0020d0, 0x0020dc, 0x0020e1, 0x0020e1, + 0x0020e5, 0x0020f0, 0x002cef, 0x002cf1, 0x002d7f, 0x002d7f, 0x002de0, 0x002dff, 0x00302a, 0x00302d, 0x003099, 0x00309a, 0x00a66f, 0x00a66f, 0x00a674, 0x00a67d, 0x00a69e, + 0x00a69f, 0x00a6f0, 0x00a6f1, 0x00a802, 0x00a802, 0x00a806, 0x00a806, 0x00a80b, 0x00a80b, 0x00a825, 0x00a826, 0x00a82c, 0x00a82c, 0x00a8c4, 0x00a8c5, 0x00a8e0, 0x00a8f1, + 0x00a8ff, 0x00a8ff, 0x00a926, 0x00a92d, 0x00a947, 0x00a951, 0x00a980, 0x00a982, 0x00a9b3, 0x00a9b3, 0x00a9b6, 0x00a9b9, 0x00a9bc, 0x00a9bd, 0x00a9e5, 0x00a9e5, 0x00aa29, + 0x00aa2e, 0x00aa31, 0x00aa32, 0x00aa35, 0x00aa36, 0x00aa43, 0x00aa43, 0x00aa4c, 0x00aa4c, 0x00aa7c, 0x00aa7c, 0x00aab0, 0x00aab0, 0x00aab2, 0x00aab4, 0x00aab7, 0x00aab8, + 0x00aabe, 0x00aabf, 0x00aac1, 0x00aac1, 0x00aaec, 0x00aaed, 0x00aaf6, 0x00aaf6, 0x00abe5, 0x00abe5, 0x00abe8, 0x00abe8, 0x00abed, 0x00abed, 0x00fb1e, 0x00fb1e, 0x00fe00, + 0x00fe0f, 0x00fe20, 0x00fe2f, 0x0101fd, 0x0101fd, 0x0102e0, 0x0102e0, 0x010376, 0x01037a, 0x010a01, 0x010a03, 0x010a05, 0x010a06, 0x010a0c, 0x010a0f, 0x010a38, 0x010a3a, + 0x010a3f, 0x010a3f, 0x010ae5, 0x010ae6, 0x010d24, 0x010d27, 0x010eab, 0x010eac, 0x010f46, 0x010f50, 0x010f82, 0x010f85, 0x011001, 0x011001, 0x011038, 0x011046, 0x011070, + 0x011070, 0x011073, 0x011074, 0x01107f, 0x011081, 0x0110b3, 0x0110b6, 0x0110b9, 0x0110ba, 0x0110c2, 0x0110c2, 0x011100, 0x011102, 0x011127, 0x01112b, 0x01112d, 0x011134, + 0x011173, 0x011173, 0x011180, 0x011181, 0x0111b6, 0x0111be, 0x0111c9, 0x0111cc, 0x0111cf, 0x0111cf, 0x01122f, 0x011231, 0x011234, 0x011234, 0x011236, 0x011237, 0x01123e, + 0x01123e, 0x0112df, 0x0112df, 0x0112e3, 0x0112ea, 0x011300, 0x011301, 0x01133b, 0x01133c, 0x011340, 0x011340, 0x011366, 0x01136c, 0x011370, 0x011374, 0x011438, 0x01143f, + 0x011442, 0x011444, 0x011446, 0x011446, 0x01145e, 0x01145e, 0x0114b3, 0x0114b8, 0x0114ba, 0x0114ba, 0x0114bf, 0x0114c0, 0x0114c2, 0x0114c3, 0x0115b2, 0x0115b5, 0x0115bc, + 0x0115bd, 0x0115bf, 0x0115c0, 0x0115dc, 0x0115dd, 0x011633, 0x01163a, 0x01163d, 0x01163d, 0x01163f, 0x011640, 0x0116ab, 0x0116ab, 0x0116ad, 0x0116ad, 0x0116b0, 0x0116b5, + 0x0116b7, 0x0116b7, 0x01171d, 0x01171f, 0x011722, 0x011725, 0x011727, 0x01172b, 0x01182f, 0x011837, 0x011839, 0x01183a, 0x01193b, 0x01193c, 0x01193e, 0x01193e, 0x011943, + 0x011943, 0x0119d4, 0x0119d7, 0x0119da, 0x0119db, 0x0119e0, 0x0119e0, 0x011a01, 0x011a0a, 0x011a33, 0x011a38, 0x011a3b, 0x011a3e, 0x011a47, 0x011a47, 0x011a51, 0x011a56, + 0x011a59, 0x011a5b, 0x011a8a, 0x011a96, 0x011a98, 0x011a99, 0x011c30, 0x011c36, 0x011c38, 0x011c3d, 0x011c3f, 0x011c3f, 0x011c92, 0x011ca7, 0x011caa, 0x011cb0, 0x011cb2, + 0x011cb3, 0x011cb5, 0x011cb6, 0x011d31, 0x011d36, 0x011d3a, 0x011d3a, 0x011d3c, 0x011d3d, 0x011d3f, 0x011d45, 0x011d47, 0x011d47, 0x011d90, 0x011d91, 0x011d95, 0x011d95, + 0x011d97, 0x011d97, 0x011ef3, 0x011ef4, 0x016af0, 0x016af4, 0x016b30, 0x016b36, 0x016f4f, 0x016f4f, 0x016f8f, 0x016f92, 0x016fe4, 0x016fe4, 0x01bc9d, 0x01bc9e, 0x01cf00, + 0x01cf2d, 0x01cf30, 0x01cf46, 0x01d167, 0x01d169, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x01d242, 0x01d244, 0x01da00, 0x01da36, 0x01da3b, 0x01da6c, + 0x01da75, 0x01da75, 0x01da84, 0x01da84, 0x01da9b, 0x01da9f, 0x01daa1, 0x01daaf, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, + 0x01e02a, 0x01e130, 0x01e136, 0x01e2ae, 0x01e2ae, 0x01e2ec, 0x01e2ef, 0x01e8d0, 0x01e8d6, 0x01e944, 0x01e94a, 0x0e0100, 0x0e01ef)); } private static void populateGC_ND() { @@ -2964,8 +3027,8 @@ private static void populateGC_ND() { 0x001a89, 0x001a90, 0x001a99, 0x001b50, 0x001b59, 0x001bb0, 0x001bb9, 0x001c40, 0x001c49, 0x001c50, 0x001c59, 0x00a620, 0x00a629, 0x00a8d0, 0x00a8d9, 0x00a900, 0x00a909, 0x00a9d0, 0x00a9d9, 0x00a9f0, 0x00a9f9, 0x00aa50, 0x00aa59, 0x00abf0, 0x00abf9, 0x00ff10, 0x00ff19, 0x0104a0, 0x0104a9, 0x010d30, 0x010d39, 0x011066, 0x01106f, 0x0110f0, 0x0110f9, 0x011136, 0x01113f, 0x0111d0, 0x0111d9, 0x0112f0, 0x0112f9, 0x011450, 0x011459, 0x0114d0, 0x0114d9, 0x011650, 0x011659, 0x0116c0, - 0x0116c9, 0x011730, 0x011739, 0x0118e0, 0x0118e9, 0x011950, 0x011959, 0x011c50, 0x011c59, 0x011d50, 0x011d59, 0x011da0, 0x011da9, 0x016a60, 0x016a69, 0x016b50, - 0x016b59, 0x01d7ce, 0x01d7ff, 0x01e140, 0x01e149, 0x01e2f0, 0x01e2f9, 0x01e950, 0x01e959, 0x01fbf0, 0x01fbf9)); + 0x0116c9, 0x011730, 0x011739, 0x0118e0, 0x0118e9, 0x011950, 0x011959, 0x011c50, 0x011c59, 0x011d50, 0x011d59, 0x011da0, 0x011da9, 0x016a60, 0x016a69, 0x016ac0, + 0x016ac9, 0x016b50, 0x016b59, 0x01d7ce, 0x01d7ff, 0x01e140, 0x01e149, 0x01e2f0, 0x01e2f9, 0x01e950, 0x01e959, 0x01fbf0, 0x01fbf9)); } private static void populateGC_NL() { @@ -2993,20 +3056,22 @@ private static void populateGC_PC() { private static void populateGC_PD() { SET_ENCODINGS.put("gc=Pd", CodePointSet.createNoDedup(0x00002d, 0x00002d, 0x00058a, 0x00058a, 0x0005be, 0x0005be, 0x001400, 0x001400, 0x001806, 0x001806, 0x002010, 0x002015, 0x002e17, 0x002e17, 0x002e1a, - 0x002e1a, 0x002e3a, 0x002e3b, 0x002e40, 0x002e40, 0x00301c, 0x00301c, 0x003030, 0x003030, 0x0030a0, 0x0030a0, 0x00fe31, 0x00fe32, 0x00fe58, 0x00fe58, 0x00fe63, - 0x00fe63, 0x00ff0d, 0x00ff0d, 0x010ead, 0x010ead)); + 0x002e1a, 0x002e3a, 0x002e3b, 0x002e40, 0x002e40, 0x002e5d, 0x002e5d, 0x00301c, 0x00301c, 0x003030, 0x003030, 0x0030a0, 0x0030a0, 0x00fe31, 0x00fe32, 0x00fe58, + 0x00fe58, 0x00fe63, 0x00fe63, 0x00ff0d, 0x00ff0d, 0x010ead, 0x010ead)); } private static void populateGC_PE() { - SET_ENCODINGS.put("gc=Pe", CodePointSet.createNoDedup(0x000029, 0x000029, 0x00005d, 0x00005d, 0x00007d, 0x00007d, 0x000f3b, 0x000f3b, 0x000f3d, 0x000f3d, 0x00169c, 0x00169c, 0x002046, - 0x002046, 0x00207e, 0x00207e, 0x00208e, 0x00208e, 0x002309, 0x002309, 0x00230b, 0x00230b, 0x00232a, 0x00232a, 0x002769, 0x002769, 0x00276b, 0x00276b, 0x00276d, 0x00276d, - 0x00276f, 0x00276f, 0x002771, 0x002771, 0x002773, 0x002773, 0x002775, 0x002775, 0x0027c6, 0x0027c6, 0x0027e7, 0x0027e7, 0x0027e9, 0x0027e9, 0x0027eb, 0x0027eb, 0x0027ed, - 0x0027ed, 0x0027ef, 0x0027ef, 0x002984, 0x002984, 0x002986, 0x002986, 0x002988, 0x002988, 0x00298a, 0x00298a, 0x00298c, 0x00298c, 0x00298e, 0x00298e, 0x002990, 0x002990, - 0x002992, 0x002992, 0x002994, 0x002994, 0x002996, 0x002996, 0x002998, 0x002998, 0x0029d9, 0x0029d9, 0x0029db, 0x0029db, 0x0029fd, 0x0029fd, 0x002e23, 0x002e23, 0x002e25, - 0x002e25, 0x002e27, 0x002e27, 0x002e29, 0x002e29, 0x003009, 0x003009, 0x00300b, 0x00300b, 0x00300d, 0x00300d, 0x00300f, 0x00300f, 0x003011, 0x003011, 0x003015, 0x003015, - 0x003017, 0x003017, 0x003019, 0x003019, 0x00301b, 0x00301b, 0x00301e, 0x00301f, 0x00fd3e, 0x00fd3e, 0x00fe18, 0x00fe18, 0x00fe36, 0x00fe36, 0x00fe38, 0x00fe38, 0x00fe3a, - 0x00fe3a, 0x00fe3c, 0x00fe3c, 0x00fe3e, 0x00fe3e, 0x00fe40, 0x00fe40, 0x00fe42, 0x00fe42, 0x00fe44, 0x00fe44, 0x00fe48, 0x00fe48, 0x00fe5a, 0x00fe5a, 0x00fe5c, 0x00fe5c, - 0x00fe5e, 0x00fe5e, 0x00ff09, 0x00ff09, 0x00ff3d, 0x00ff3d, 0x00ff5d, 0x00ff5d, 0x00ff60, 0x00ff60, 0x00ff63, 0x00ff63)); + SET_ENCODINGS.put("gc=Pe", + CodePointSet.createNoDedup(0x000029, 0x000029, 0x00005d, 0x00005d, 0x00007d, 0x00007d, 0x000f3b, 0x000f3b, 0x000f3d, 0x000f3d, 0x00169c, 0x00169c, 0x002046, 0x002046, 0x00207e, + 0x00207e, 0x00208e, 0x00208e, 0x002309, 0x002309, 0x00230b, 0x00230b, 0x00232a, 0x00232a, 0x002769, 0x002769, 0x00276b, 0x00276b, 0x00276d, 0x00276d, 0x00276f, + 0x00276f, 0x002771, 0x002771, 0x002773, 0x002773, 0x002775, 0x002775, 0x0027c6, 0x0027c6, 0x0027e7, 0x0027e7, 0x0027e9, 0x0027e9, 0x0027eb, 0x0027eb, 0x0027ed, + 0x0027ed, 0x0027ef, 0x0027ef, 0x002984, 0x002984, 0x002986, 0x002986, 0x002988, 0x002988, 0x00298a, 0x00298a, 0x00298c, 0x00298c, 0x00298e, 0x00298e, 0x002990, + 0x002990, 0x002992, 0x002992, 0x002994, 0x002994, 0x002996, 0x002996, 0x002998, 0x002998, 0x0029d9, 0x0029d9, 0x0029db, 0x0029db, 0x0029fd, 0x0029fd, 0x002e23, + 0x002e23, 0x002e25, 0x002e25, 0x002e27, 0x002e27, 0x002e29, 0x002e29, 0x002e56, 0x002e56, 0x002e58, 0x002e58, 0x002e5a, 0x002e5a, 0x002e5c, 0x002e5c, 0x003009, + 0x003009, 0x00300b, 0x00300b, 0x00300d, 0x00300d, 0x00300f, 0x00300f, 0x003011, 0x003011, 0x003015, 0x003015, 0x003017, 0x003017, 0x003019, 0x003019, 0x00301b, + 0x00301b, 0x00301e, 0x00301f, 0x00fd3e, 0x00fd3e, 0x00fe18, 0x00fe18, 0x00fe36, 0x00fe36, 0x00fe38, 0x00fe38, 0x00fe3a, 0x00fe3a, 0x00fe3c, 0x00fe3c, 0x00fe3e, + 0x00fe3e, 0x00fe40, 0x00fe40, 0x00fe42, 0x00fe42, 0x00fe44, 0x00fe44, 0x00fe48, 0x00fe48, 0x00fe5a, 0x00fe5a, 0x00fe5c, 0x00fe5c, 0x00fe5e, 0x00fe5e, 0x00ff09, + 0x00ff09, 0x00ff3d, 0x00ff3d, 0x00ff5d, 0x00ff5d, 0x00ff60, 0x00ff60, 0x00ff63, 0x00ff63)); } private static void populateGC_PF() { @@ -3022,26 +3087,26 @@ private static void populateGC_PI() { private static void populateGC_PO() { SET_ENCODINGS.put("gc=Po", CodePointSet.createNoDedup(0x000021, 0x000023, 0x000025, 0x000027, 0x00002a, 0x00002a, 0x00002c, 0x00002c, 0x00002e, 0x00002f, 0x00003a, 0x00003b, 0x00003f, 0x000040, 0x00005c, 0x00005c, 0x0000a1, 0x0000a1, 0x0000a7, 0x0000a7, 0x0000b6, 0x0000b7, 0x0000bf, 0x0000bf, 0x00037e, 0x00037e, 0x000387, 0x000387, 0x00055a, 0x00055f, - 0x000589, 0x000589, 0x0005c0, 0x0005c0, 0x0005c3, 0x0005c3, 0x0005c6, 0x0005c6, 0x0005f3, 0x0005f4, 0x000609, 0x00060a, 0x00060c, 0x00060d, 0x00061b, 0x00061b, 0x00061e, + 0x000589, 0x000589, 0x0005c0, 0x0005c0, 0x0005c3, 0x0005c3, 0x0005c6, 0x0005c6, 0x0005f3, 0x0005f4, 0x000609, 0x00060a, 0x00060c, 0x00060d, 0x00061b, 0x00061b, 0x00061d, 0x00061f, 0x00066a, 0x00066d, 0x0006d4, 0x0006d4, 0x000700, 0x00070d, 0x0007f7, 0x0007f9, 0x000830, 0x00083e, 0x00085e, 0x00085e, 0x000964, 0x000965, 0x000970, 0x000970, 0x0009fd, 0x0009fd, 0x000a76, 0x000a76, 0x000af0, 0x000af0, 0x000c77, 0x000c77, 0x000c84, 0x000c84, 0x000df4, 0x000df4, 0x000e4f, 0x000e4f, 0x000e5a, 0x000e5b, 0x000f04, 0x000f12, 0x000f14, 0x000f14, 0x000f85, 0x000f85, 0x000fd0, 0x000fd4, 0x000fd9, 0x000fda, 0x00104a, 0x00104f, 0x0010fb, 0x0010fb, 0x001360, 0x001368, 0x00166e, 0x00166e, 0x0016eb, 0x0016ed, 0x001735, 0x001736, 0x0017d4, 0x0017d6, 0x0017d8, 0x0017da, 0x001800, 0x001805, 0x001807, 0x00180a, 0x001944, 0x001945, 0x001a1e, 0x001a1f, 0x001aa0, - 0x001aa6, 0x001aa8, 0x001aad, 0x001b5a, 0x001b60, 0x001bfc, 0x001bff, 0x001c3b, 0x001c3f, 0x001c7e, 0x001c7f, 0x001cc0, 0x001cc7, 0x001cd3, 0x001cd3, 0x002016, 0x002017, - 0x002020, 0x002027, 0x002030, 0x002038, 0x00203b, 0x00203e, 0x002041, 0x002043, 0x002047, 0x002051, 0x002053, 0x002053, 0x002055, 0x00205e, 0x002cf9, 0x002cfc, 0x002cfe, - 0x002cff, 0x002d70, 0x002d70, 0x002e00, 0x002e01, 0x002e06, 0x002e08, 0x002e0b, 0x002e0b, 0x002e0e, 0x002e16, 0x002e18, 0x002e19, 0x002e1b, 0x002e1b, 0x002e1e, 0x002e1f, - 0x002e2a, 0x002e2e, 0x002e30, 0x002e39, 0x002e3c, 0x002e3f, 0x002e41, 0x002e41, 0x002e43, 0x002e4f, 0x002e52, 0x002e52, 0x003001, 0x003003, 0x00303d, 0x00303d, 0x0030fb, - 0x0030fb, 0x00a4fe, 0x00a4ff, 0x00a60d, 0x00a60f, 0x00a673, 0x00a673, 0x00a67e, 0x00a67e, 0x00a6f2, 0x00a6f7, 0x00a874, 0x00a877, 0x00a8ce, 0x00a8cf, 0x00a8f8, 0x00a8fa, - 0x00a8fc, 0x00a8fc, 0x00a92e, 0x00a92f, 0x00a95f, 0x00a95f, 0x00a9c1, 0x00a9cd, 0x00a9de, 0x00a9df, 0x00aa5c, 0x00aa5f, 0x00aade, 0x00aadf, 0x00aaf0, 0x00aaf1, 0x00abeb, - 0x00abeb, 0x00fe10, 0x00fe16, 0x00fe19, 0x00fe19, 0x00fe30, 0x00fe30, 0x00fe45, 0x00fe46, 0x00fe49, 0x00fe4c, 0x00fe50, 0x00fe52, 0x00fe54, 0x00fe57, 0x00fe5f, 0x00fe61, - 0x00fe68, 0x00fe68, 0x00fe6a, 0x00fe6b, 0x00ff01, 0x00ff03, 0x00ff05, 0x00ff07, 0x00ff0a, 0x00ff0a, 0x00ff0c, 0x00ff0c, 0x00ff0e, 0x00ff0f, 0x00ff1a, 0x00ff1b, 0x00ff1f, - 0x00ff20, 0x00ff3c, 0x00ff3c, 0x00ff61, 0x00ff61, 0x00ff64, 0x00ff65, 0x010100, 0x010102, 0x01039f, 0x01039f, 0x0103d0, 0x0103d0, 0x01056f, 0x01056f, 0x010857, 0x010857, - 0x01091f, 0x01091f, 0x01093f, 0x01093f, 0x010a50, 0x010a58, 0x010a7f, 0x010a7f, 0x010af0, 0x010af6, 0x010b39, 0x010b3f, 0x010b99, 0x010b9c, 0x010f55, 0x010f59, 0x011047, - 0x01104d, 0x0110bb, 0x0110bc, 0x0110be, 0x0110c1, 0x011140, 0x011143, 0x011174, 0x011175, 0x0111c5, 0x0111c8, 0x0111cd, 0x0111cd, 0x0111db, 0x0111db, 0x0111dd, 0x0111df, - 0x011238, 0x01123d, 0x0112a9, 0x0112a9, 0x01144b, 0x01144f, 0x01145a, 0x01145b, 0x01145d, 0x01145d, 0x0114c6, 0x0114c6, 0x0115c1, 0x0115d7, 0x011641, 0x011643, 0x011660, - 0x01166c, 0x01173c, 0x01173e, 0x01183b, 0x01183b, 0x011944, 0x011946, 0x0119e2, 0x0119e2, 0x011a3f, 0x011a46, 0x011a9a, 0x011a9c, 0x011a9e, 0x011aa2, 0x011c41, 0x011c45, - 0x011c70, 0x011c71, 0x011ef7, 0x011ef8, 0x011fff, 0x011fff, 0x012470, 0x012474, 0x016a6e, 0x016a6f, 0x016af5, 0x016af5, 0x016b37, 0x016b3b, 0x016b44, 0x016b44, 0x016e97, - 0x016e9a, 0x016fe2, 0x016fe2, 0x01bc9f, 0x01bc9f, 0x01da87, 0x01da8b, 0x01e95e, 0x01e95f)); + 0x001aa6, 0x001aa8, 0x001aad, 0x001b5a, 0x001b60, 0x001b7d, 0x001b7e, 0x001bfc, 0x001bff, 0x001c3b, 0x001c3f, 0x001c7e, 0x001c7f, 0x001cc0, 0x001cc7, 0x001cd3, 0x001cd3, + 0x002016, 0x002017, 0x002020, 0x002027, 0x002030, 0x002038, 0x00203b, 0x00203e, 0x002041, 0x002043, 0x002047, 0x002051, 0x002053, 0x002053, 0x002055, 0x00205e, 0x002cf9, + 0x002cfc, 0x002cfe, 0x002cff, 0x002d70, 0x002d70, 0x002e00, 0x002e01, 0x002e06, 0x002e08, 0x002e0b, 0x002e0b, 0x002e0e, 0x002e16, 0x002e18, 0x002e19, 0x002e1b, 0x002e1b, + 0x002e1e, 0x002e1f, 0x002e2a, 0x002e2e, 0x002e30, 0x002e39, 0x002e3c, 0x002e3f, 0x002e41, 0x002e41, 0x002e43, 0x002e4f, 0x002e52, 0x002e54, 0x003001, 0x003003, 0x00303d, + 0x00303d, 0x0030fb, 0x0030fb, 0x00a4fe, 0x00a4ff, 0x00a60d, 0x00a60f, 0x00a673, 0x00a673, 0x00a67e, 0x00a67e, 0x00a6f2, 0x00a6f7, 0x00a874, 0x00a877, 0x00a8ce, 0x00a8cf, + 0x00a8f8, 0x00a8fa, 0x00a8fc, 0x00a8fc, 0x00a92e, 0x00a92f, 0x00a95f, 0x00a95f, 0x00a9c1, 0x00a9cd, 0x00a9de, 0x00a9df, 0x00aa5c, 0x00aa5f, 0x00aade, 0x00aadf, 0x00aaf0, + 0x00aaf1, 0x00abeb, 0x00abeb, 0x00fe10, 0x00fe16, 0x00fe19, 0x00fe19, 0x00fe30, 0x00fe30, 0x00fe45, 0x00fe46, 0x00fe49, 0x00fe4c, 0x00fe50, 0x00fe52, 0x00fe54, 0x00fe57, + 0x00fe5f, 0x00fe61, 0x00fe68, 0x00fe68, 0x00fe6a, 0x00fe6b, 0x00ff01, 0x00ff03, 0x00ff05, 0x00ff07, 0x00ff0a, 0x00ff0a, 0x00ff0c, 0x00ff0c, 0x00ff0e, 0x00ff0f, 0x00ff1a, + 0x00ff1b, 0x00ff1f, 0x00ff20, 0x00ff3c, 0x00ff3c, 0x00ff61, 0x00ff61, 0x00ff64, 0x00ff65, 0x010100, 0x010102, 0x01039f, 0x01039f, 0x0103d0, 0x0103d0, 0x01056f, 0x01056f, + 0x010857, 0x010857, 0x01091f, 0x01091f, 0x01093f, 0x01093f, 0x010a50, 0x010a58, 0x010a7f, 0x010a7f, 0x010af0, 0x010af6, 0x010b39, 0x010b3f, 0x010b99, 0x010b9c, 0x010f55, + 0x010f59, 0x010f86, 0x010f89, 0x011047, 0x01104d, 0x0110bb, 0x0110bc, 0x0110be, 0x0110c1, 0x011140, 0x011143, 0x011174, 0x011175, 0x0111c5, 0x0111c8, 0x0111cd, 0x0111cd, + 0x0111db, 0x0111db, 0x0111dd, 0x0111df, 0x011238, 0x01123d, 0x0112a9, 0x0112a9, 0x01144b, 0x01144f, 0x01145a, 0x01145b, 0x01145d, 0x01145d, 0x0114c6, 0x0114c6, 0x0115c1, + 0x0115d7, 0x011641, 0x011643, 0x011660, 0x01166c, 0x0116b9, 0x0116b9, 0x01173c, 0x01173e, 0x01183b, 0x01183b, 0x011944, 0x011946, 0x0119e2, 0x0119e2, 0x011a3f, 0x011a46, + 0x011a9a, 0x011a9c, 0x011a9e, 0x011aa2, 0x011c41, 0x011c45, 0x011c70, 0x011c71, 0x011ef7, 0x011ef8, 0x011fff, 0x011fff, 0x012470, 0x012474, 0x012ff1, 0x012ff2, 0x016a6e, + 0x016a6f, 0x016af5, 0x016af5, 0x016b37, 0x016b3b, 0x016b44, 0x016b44, 0x016e97, 0x016e9a, 0x016fe2, 0x016fe2, 0x01bc9f, 0x01bc9f, 0x01da87, 0x01da8b, 0x01e95e, 0x01e95f)); } private static void populateGC_PS() { @@ -3051,26 +3116,26 @@ private static void populateGC_PS() { 0x00276a, 0x00276c, 0x00276c, 0x00276e, 0x00276e, 0x002770, 0x002770, 0x002772, 0x002772, 0x002774, 0x002774, 0x0027c5, 0x0027c5, 0x0027e6, 0x0027e6, 0x0027e8, 0x0027e8, 0x0027ea, 0x0027ea, 0x0027ec, 0x0027ec, 0x0027ee, 0x0027ee, 0x002983, 0x002983, 0x002985, 0x002985, 0x002987, 0x002987, 0x002989, 0x002989, 0x00298b, 0x00298b, 0x00298d, 0x00298d, 0x00298f, 0x00298f, 0x002991, 0x002991, 0x002993, 0x002993, 0x002995, 0x002995, 0x002997, 0x002997, 0x0029d8, 0x0029d8, 0x0029da, - 0x0029da, 0x0029fc, 0x0029fc, 0x002e22, 0x002e22, 0x002e24, 0x002e24, 0x002e26, 0x002e26, 0x002e28, 0x002e28, 0x002e42, 0x002e42, 0x003008, 0x003008, 0x00300a, - 0x00300a, 0x00300c, 0x00300c, 0x00300e, 0x00300e, 0x003010, 0x003010, 0x003014, 0x003014, 0x003016, 0x003016, 0x003018, 0x003018, 0x00301a, 0x00301a, 0x00301d, - 0x00301d, 0x00fd3f, 0x00fd3f, 0x00fe17, 0x00fe17, 0x00fe35, 0x00fe35, 0x00fe37, 0x00fe37, 0x00fe39, 0x00fe39, 0x00fe3b, 0x00fe3b, 0x00fe3d, 0x00fe3d, 0x00fe3f, - 0x00fe3f, 0x00fe41, 0x00fe41, 0x00fe43, 0x00fe43, 0x00fe47, 0x00fe47, 0x00fe59, 0x00fe59, 0x00fe5b, 0x00fe5b, 0x00fe5d, 0x00fe5d, 0x00ff08, 0x00ff08, 0x00ff3b, - 0x00ff3b, 0x00ff5b, 0x00ff5b, 0x00ff5f, 0x00ff5f, 0x00ff62, 0x00ff62)); + 0x0029da, 0x0029fc, 0x0029fc, 0x002e22, 0x002e22, 0x002e24, 0x002e24, 0x002e26, 0x002e26, 0x002e28, 0x002e28, 0x002e42, 0x002e42, 0x002e55, 0x002e55, 0x002e57, + 0x002e57, 0x002e59, 0x002e59, 0x002e5b, 0x002e5b, 0x003008, 0x003008, 0x00300a, 0x00300a, 0x00300c, 0x00300c, 0x00300e, 0x00300e, 0x003010, 0x003010, 0x003014, + 0x003014, 0x003016, 0x003016, 0x003018, 0x003018, 0x00301a, 0x00301a, 0x00301d, 0x00301d, 0x00fd3f, 0x00fd3f, 0x00fe17, 0x00fe17, 0x00fe35, 0x00fe35, 0x00fe37, + 0x00fe37, 0x00fe39, 0x00fe39, 0x00fe3b, 0x00fe3b, 0x00fe3d, 0x00fe3d, 0x00fe3f, 0x00fe3f, 0x00fe41, 0x00fe41, 0x00fe43, 0x00fe43, 0x00fe47, 0x00fe47, 0x00fe59, + 0x00fe59, 0x00fe5b, 0x00fe5b, 0x00fe5d, 0x00fe5d, 0x00ff08, 0x00ff08, 0x00ff3b, 0x00ff3b, 0x00ff5b, 0x00ff5b, 0x00ff5f, 0x00ff5f, 0x00ff62, 0x00ff62)); } private static void populateGC_SC() { SET_ENCODINGS.put("gc=Sc", CodePointSet.createNoDedup(0x000024, 0x000024, 0x0000a2, 0x0000a5, 0x00058f, 0x00058f, 0x00060b, 0x00060b, 0x0007fe, 0x0007ff, 0x0009f2, 0x0009f3, 0x0009fb, 0x0009fb, 0x000af1, - 0x000af1, 0x000bf9, 0x000bf9, 0x000e3f, 0x000e3f, 0x0017db, 0x0017db, 0x0020a0, 0x0020bf, 0x00a838, 0x00a838, 0x00fdfc, 0x00fdfc, 0x00fe69, 0x00fe69, 0x00ff04, + 0x000af1, 0x000bf9, 0x000bf9, 0x000e3f, 0x000e3f, 0x0017db, 0x0017db, 0x0020a0, 0x0020c0, 0x00a838, 0x00a838, 0x00fdfc, 0x00fdfc, 0x00fe69, 0x00fe69, 0x00ff04, 0x00ff04, 0x00ffe0, 0x00ffe1, 0x00ffe5, 0x00ffe6, 0x011fdd, 0x011fe0, 0x01e2ff, 0x01e2ff, 0x01ecb0, 0x01ecb0)); } private static void populateGC_SK() { SET_ENCODINGS.put("gc=Sk", CodePointSet.createNoDedup(0x00005e, 0x00005e, 0x000060, 0x000060, 0x0000a8, 0x0000a8, 0x0000af, 0x0000af, 0x0000b4, 0x0000b4, 0x0000b8, 0x0000b8, 0x0002c2, 0x0002c5, 0x0002d2, - 0x0002df, 0x0002e5, 0x0002eb, 0x0002ed, 0x0002ed, 0x0002ef, 0x0002ff, 0x000375, 0x000375, 0x000384, 0x000385, 0x001fbd, 0x001fbd, 0x001fbf, 0x001fc1, 0x001fcd, - 0x001fcf, 0x001fdd, 0x001fdf, 0x001fed, 0x001fef, 0x001ffd, 0x001ffe, 0x00309b, 0x00309c, 0x00a700, 0x00a716, 0x00a720, 0x00a721, 0x00a789, 0x00a78a, 0x00ab5b, - 0x00ab5b, 0x00ab6a, 0x00ab6b, 0x00fbb2, 0x00fbc1, 0x00ff3e, 0x00ff3e, 0x00ff40, 0x00ff40, 0x00ffe3, 0x00ffe3, 0x01f3fb, 0x01f3ff)); + 0x0002df, 0x0002e5, 0x0002eb, 0x0002ed, 0x0002ed, 0x0002ef, 0x0002ff, 0x000375, 0x000375, 0x000384, 0x000385, 0x000888, 0x000888, 0x001fbd, 0x001fbd, 0x001fbf, + 0x001fc1, 0x001fcd, 0x001fcf, 0x001fdd, 0x001fdf, 0x001fed, 0x001fef, 0x001ffd, 0x001ffe, 0x00309b, 0x00309c, 0x00a700, 0x00a716, 0x00a720, 0x00a721, 0x00a789, + 0x00a78a, 0x00ab5b, 0x00ab5b, 0x00ab6a, 0x00ab6b, 0x00fbb2, 0x00fbc2, 0x00ff3e, 0x00ff3e, 0x00ff40, 0x00ff40, 0x00ffe3, 0x00ffe3, 0x01f3fb, 0x01f3ff)); } private static void populateGC_SM() { @@ -3097,16 +3162,17 @@ private static void populateGC_SO() { 0x0027bf, 0x002800, 0x0028ff, 0x002b00, 0x002b2f, 0x002b45, 0x002b46, 0x002b4d, 0x002b73, 0x002b76, 0x002b95, 0x002b97, 0x002bff, 0x002ce5, 0x002cea, 0x002e50, 0x002e51, 0x002e80, 0x002e99, 0x002e9b, 0x002ef3, 0x002f00, 0x002fd5, 0x002ff0, 0x002ffb, 0x003004, 0x003004, 0x003012, 0x003013, 0x003020, 0x003020, 0x003036, 0x003037, 0x00303e, 0x00303f, 0x003190, 0x003191, 0x003196, 0x00319f, 0x0031c0, 0x0031e3, 0x003200, 0x00321e, 0x00322a, 0x003247, 0x003250, 0x003250, 0x003260, 0x00327f, 0x00328a, 0x0032b0, - 0x0032c0, 0x0033ff, 0x004dc0, 0x004dff, 0x00a490, 0x00a4c6, 0x00a828, 0x00a82b, 0x00a836, 0x00a837, 0x00a839, 0x00a839, 0x00aa77, 0x00aa79, 0x00fdfd, 0x00fdfd, 0x00ffe4, - 0x00ffe4, 0x00ffe8, 0x00ffe8, 0x00ffed, 0x00ffee, 0x00fffc, 0x00fffd, 0x010137, 0x01013f, 0x010179, 0x010189, 0x01018c, 0x01018e, 0x010190, 0x01019c, 0x0101a0, 0x0101a0, - 0x0101d0, 0x0101fc, 0x010877, 0x010878, 0x010ac8, 0x010ac8, 0x01173f, 0x01173f, 0x011fd5, 0x011fdc, 0x011fe1, 0x011ff1, 0x016b3c, 0x016b3f, 0x016b45, 0x016b45, 0x01bc9c, - 0x01bc9c, 0x01d000, 0x01d0f5, 0x01d100, 0x01d126, 0x01d129, 0x01d164, 0x01d16a, 0x01d16c, 0x01d183, 0x01d184, 0x01d18c, 0x01d1a9, 0x01d1ae, 0x01d1e8, 0x01d200, 0x01d241, - 0x01d245, 0x01d245, 0x01d300, 0x01d356, 0x01d800, 0x01d9ff, 0x01da37, 0x01da3a, 0x01da6d, 0x01da74, 0x01da76, 0x01da83, 0x01da85, 0x01da86, 0x01e14f, 0x01e14f, 0x01ecac, - 0x01ecac, 0x01ed2e, 0x01ed2e, 0x01f000, 0x01f02b, 0x01f030, 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, 0x01f10d, 0x01f1ad, - 0x01f1e6, 0x01f202, 0x01f210, 0x01f23b, 0x01f240, 0x01f248, 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, 0x01f3fa, 0x01f400, 0x01f6d7, 0x01f6e0, 0x01f6ec, 0x01f6f0, - 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, 0x01f7e0, 0x01f7eb, 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, - 0x01f8b0, 0x01f8b1, 0x01f900, 0x01f978, 0x01f97a, 0x01f9cb, 0x01f9cd, 0x01fa53, 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7a, 0x01fa80, 0x01fa86, 0x01fa90, - 0x01faa8, 0x01fab0, 0x01fab6, 0x01fac0, 0x01fac2, 0x01fad0, 0x01fad6, 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca)); + 0x0032c0, 0x0033ff, 0x004dc0, 0x004dff, 0x00a490, 0x00a4c6, 0x00a828, 0x00a82b, 0x00a836, 0x00a837, 0x00a839, 0x00a839, 0x00aa77, 0x00aa79, 0x00fd40, 0x00fd4f, 0x00fdcf, + 0x00fdcf, 0x00fdfd, 0x00fdff, 0x00ffe4, 0x00ffe4, 0x00ffe8, 0x00ffe8, 0x00ffed, 0x00ffee, 0x00fffc, 0x00fffd, 0x010137, 0x01013f, 0x010179, 0x010189, 0x01018c, 0x01018e, + 0x010190, 0x01019c, 0x0101a0, 0x0101a0, 0x0101d0, 0x0101fc, 0x010877, 0x010878, 0x010ac8, 0x010ac8, 0x01173f, 0x01173f, 0x011fd5, 0x011fdc, 0x011fe1, 0x011ff1, 0x016b3c, + 0x016b3f, 0x016b45, 0x016b45, 0x01bc9c, 0x01bc9c, 0x01cf50, 0x01cfc3, 0x01d000, 0x01d0f5, 0x01d100, 0x01d126, 0x01d129, 0x01d164, 0x01d16a, 0x01d16c, 0x01d183, 0x01d184, + 0x01d18c, 0x01d1a9, 0x01d1ae, 0x01d1ea, 0x01d200, 0x01d241, 0x01d245, 0x01d245, 0x01d300, 0x01d356, 0x01d800, 0x01d9ff, 0x01da37, 0x01da3a, 0x01da6d, 0x01da74, 0x01da76, + 0x01da83, 0x01da85, 0x01da86, 0x01e14f, 0x01e14f, 0x01ecac, 0x01ecac, 0x01ed2e, 0x01ed2e, 0x01f000, 0x01f02b, 0x01f030, 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, + 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, 0x01f10d, 0x01f1ad, 0x01f1e6, 0x01f202, 0x01f210, 0x01f23b, 0x01f240, 0x01f248, 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, + 0x01f3fa, 0x01f400, 0x01f6d7, 0x01f6dd, 0x01f6ec, 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, 0x01f7e0, 0x01f7eb, 0x01f7f0, 0x01f7f0, 0x01f800, 0x01f80b, + 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01fa53, 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, + 0x01fa7c, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faac, 0x01fab0, 0x01faba, 0x01fac0, 0x01fac5, 0x01fad0, 0x01fad9, 0x01fae0, 0x01fae7, 0x01faf0, 0x01faf6, 0x01fb00, 0x01fb92, + 0x01fb94, 0x01fbca)); } private static void populateGC_ZL() { @@ -3131,13 +3197,13 @@ private static void populateSC_AGHB() { } private static void populateSC_AHOM() { - SET_ENCODINGS.put("sc=Ahom", CodePointSet.createNoDedup(0x011700, 0x01171a, 0x01171d, 0x01172b, 0x011730, 0x01173f)); + SET_ENCODINGS.put("sc=Ahom", CodePointSet.createNoDedup(0x011700, 0x01171a, 0x01171d, 0x01172b, 0x011730, 0x011746)); } private static void populateSC_ARAB() { - SET_ENCODINGS.put("sc=Arab", CodePointSet.createNoDedup(0x000600, 0x000604, 0x000606, 0x00060b, 0x00060d, 0x00061a, 0x00061c, 0x00061c, 0x00061e, 0x00061e, 0x000620, 0x00063f, 0x000641, - 0x00064a, 0x000656, 0x00066f, 0x000671, 0x0006dc, 0x0006de, 0x0006ff, 0x000750, 0x00077f, 0x0008a0, 0x0008b4, 0x0008b6, 0x0008c7, 0x0008d3, 0x0008e1, 0x0008e3, 0x0008ff, - 0x00fb50, 0x00fbc1, 0x00fbd3, 0x00fd3d, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdfd, 0x00fe70, 0x00fe74, 0x00fe76, 0x00fefc, 0x010e60, 0x010e7e, 0x01ee00, + SET_ENCODINGS.put("sc=Arab", CodePointSet.createNoDedup(0x000600, 0x000604, 0x000606, 0x00060b, 0x00060d, 0x00061a, 0x00061c, 0x00061e, 0x000620, 0x00063f, 0x000641, 0x00064a, 0x000656, + 0x00066f, 0x000671, 0x0006dc, 0x0006de, 0x0006ff, 0x000750, 0x00077f, 0x000870, 0x00088e, 0x000890, 0x000891, 0x000898, 0x0008e1, 0x0008e3, 0x0008ff, 0x00fb50, 0x00fbc2, + 0x00fbd3, 0x00fd3d, 0x00fd40, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdcf, 0x00fdcf, 0x00fdf0, 0x00fdff, 0x00fe70, 0x00fe74, 0x00fe76, 0x00fefc, 0x010e60, 0x010e7e, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, @@ -3157,7 +3223,7 @@ private static void populateSC_AVST() { } private static void populateSC_BALI() { - SET_ENCODINGS.put("sc=Bali", CodePointSet.createNoDedup(0x001b00, 0x001b4b, 0x001b50, 0x001b7c)); + SET_ENCODINGS.put("sc=Bali", CodePointSet.createNoDedup(0x001b00, 0x001b4c, 0x001b50, 0x001b7e)); } private static void populateSC_BAMU() { @@ -3186,7 +3252,7 @@ private static void populateSC_BOPO() { } private static void populateSC_BRAH() { - SET_ENCODINGS.put("sc=Brah", CodePointSet.createNoDedup(0x011000, 0x01104d, 0x011052, 0x01106f, 0x01107f, 0x01107f)); + SET_ENCODINGS.put("sc=Brah", CodePointSet.createNoDedup(0x011000, 0x01104d, 0x011052, 0x011075, 0x01107f, 0x01107f)); } private static void populateSC_BRAI() { @@ -3206,7 +3272,7 @@ private static void populateSC_CAKM() { } private static void populateSC_CANS() { - SET_ENCODINGS.put("sc=Cans", CodePointSet.createNoDedup(0x001400, 0x00167f, 0x0018b0, 0x0018f5)); + SET_ENCODINGS.put("sc=Cans", CodePointSet.createNoDedup(0x001400, 0x00167f, 0x0018b0, 0x0018f5, 0x011ab0, 0x011abf)); } private static void populateSC_CARI() { @@ -3229,6 +3295,10 @@ private static void populateSC_COPT() { SET_ENCODINGS.put("sc=Copt", CodePointSet.createNoDedup(0x0003e2, 0x0003ef, 0x002c80, 0x002cf3, 0x002cf9, 0x002cff)); } + private static void populateSC_CPMN() { + SET_ENCODINGS.put("sc=Cpmn", CodePointSet.createNoDedup(0x012f90, 0x012ff2)); + } + private static void populateSC_CPRT() { SET_ENCODINGS.put("sc=Cprt", CodePointSet.createNoDedup(0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x01083f)); } @@ -3272,10 +3342,12 @@ private static void populateSC_ELYM() { } private static void populateSC_ETHI() { - SET_ENCODINGS.put("sc=Ethi", CodePointSet.createNoDedup(0x001200, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, - 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, - 0x001318, 0x00135a, 0x00135d, 0x00137c, 0x001380, 0x001399, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, - 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, 0x00ab2e)); + SET_ENCODINGS.put("sc=Ethi", + CodePointSet.createNoDedup(0x001200, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, + 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, + 0x00135a, 0x00135d, 0x00137c, 0x001380, 0x001399, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, + 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, + 0x00ab2e, 0x01e7e0, 0x01e7e6, 0x01e7e8, 0x01e7eb, 0x01e7ed, 0x01e7ee, 0x01e7f0, 0x01e7fe)); } private static void populateSC_GEOR() { @@ -3284,8 +3356,7 @@ private static void populateSC_GEOR() { } private static void populateSC_GLAG() { - SET_ENCODINGS.put("sc=Glag", - CodePointSet.createNoDedup(0x002c00, 0x002c2e, 0x002c30, 0x002c5e, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a)); + SET_ENCODINGS.put("sc=Glag", CodePointSet.createNoDedup(0x002c00, 0x002c5f, 0x01e000, 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a)); } private static void populateSC_GONG() { @@ -3335,8 +3406,8 @@ private static void populateSC_HANG() { private static void populateSC_HANI() { SET_ENCODINGS.put("sc=Hani", CodePointSet.createNoDedup(0x002e80, 0x002e99, 0x002e9b, 0x002ef3, 0x002f00, 0x002fd5, 0x003005, 0x003005, 0x003007, 0x003007, 0x003021, 0x003029, 0x003038, 0x00303b, 0x003400, - 0x004dbf, 0x004e00, 0x009ffc, 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x016ff0, 0x016ff1, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, 0x02b81d, 0x02b820, - 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); + 0x004dbf, 0x004e00, 0x009fff, 0x00f900, 0x00fa6d, 0x00fa70, 0x00fad9, 0x016fe2, 0x016fe3, 0x016ff0, 0x016ff1, 0x020000, 0x02a6df, 0x02a700, 0x02b738, 0x02b740, + 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); } private static void populateSC_HANO() { @@ -3353,7 +3424,7 @@ private static void populateSC_HEBR() { } private static void populateSC_HIRA() { - SET_ENCODINGS.put("sc=Hira", CodePointSet.createNoDedup(0x003041, 0x003096, 0x00309d, 0x00309f, 0x01b001, 0x01b11e, 0x01b150, 0x01b152, 0x01f200, 0x01f200)); + SET_ENCODINGS.put("sc=Hira", CodePointSet.createNoDedup(0x003041, 0x003096, 0x00309d, 0x00309f, 0x01b001, 0x01b11f, 0x01b150, 0x01b152, 0x01f200, 0x01f200)); } private static void populateSC_HLUW() { @@ -3386,7 +3457,7 @@ private static void populateSC_KALI() { private static void populateSC_KANA() { SET_ENCODINGS.put("sc=Kana", CodePointSet.createNoDedup(0x0030a1, 0x0030fa, 0x0030fd, 0x0030ff, 0x0031f0, 0x0031ff, 0x0032d0, 0x0032fe, 0x003300, 0x003357, 0x00ff66, 0x00ff6f, 0x00ff71, - 0x00ff9d, 0x01b000, 0x01b000, 0x01b164, 0x01b167)); + 0x00ff9d, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, 0x01affe, 0x01b000, 0x01b000, 0x01b120, 0x01b122, 0x01b164, 0x01b167)); } private static void populateSC_KHAR() { @@ -3408,11 +3479,11 @@ private static void populateSC_KITS() { private static void populateSC_KNDA() { SET_ENCODINGS.put("sc=Knda", CodePointSet.createNoDedup(0x000c80, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbc, 0x000cc4, 0x000cc6, - 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000cde, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2)); + 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000cdd, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2)); } private static void populateSC_KTHI() { - SET_ENCODINGS.put("sc=Kthi", CodePointSet.createNoDedup(0x011080, 0x0110c1, 0x0110cd, 0x0110cd)); + SET_ENCODINGS.put("sc=Kthi", CodePointSet.createNoDedup(0x011080, 0x0110c2, 0x0110cd, 0x0110cd)); } private static void populateSC_LANA() { @@ -3425,10 +3496,12 @@ private static void populateSC_LAOO() { } private static void populateSC_LATN() { - SET_ENCODINGS.put("sc=Latn", CodePointSet.createNoDedup(0x000041, 0x00005a, 0x000061, 0x00007a, 0x0000aa, 0x0000aa, 0x0000ba, 0x0000ba, 0x0000c0, 0x0000d6, 0x0000d8, 0x0000f6, 0x0000f8, - 0x0002b8, 0x0002e0, 0x0002e4, 0x001d00, 0x001d25, 0x001d2c, 0x001d5c, 0x001d62, 0x001d65, 0x001d6b, 0x001d77, 0x001d79, 0x001dbe, 0x001e00, 0x001eff, 0x002071, 0x002071, - 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x00212a, 0x00212b, 0x002132, 0x002132, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c60, 0x002c7f, 0x00a722, 0x00a787, 0x00a78b, - 0x00a7bf, 0x00a7c2, 0x00a7ca, 0x00a7f5, 0x00a7ff, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab64, 0x00ab66, 0x00ab69, 0x00fb00, 0x00fb06, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a)); + SET_ENCODINGS.put("sc=Latn", + CodePointSet.createNoDedup(0x000041, 0x00005a, 0x000061, 0x00007a, 0x0000aa, 0x0000aa, 0x0000ba, 0x0000ba, 0x0000c0, 0x0000d6, 0x0000d8, 0x0000f6, 0x0000f8, 0x0002b8, 0x0002e0, + 0x0002e4, 0x001d00, 0x001d25, 0x001d2c, 0x001d5c, 0x001d62, 0x001d65, 0x001d6b, 0x001d77, 0x001d79, 0x001dbe, 0x001e00, 0x001eff, 0x002071, 0x002071, 0x00207f, + 0x00207f, 0x002090, 0x00209c, 0x00212a, 0x00212b, 0x002132, 0x002132, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c60, 0x002c7f, 0x00a722, 0x00a787, 0x00a78b, + 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, 0x00a7f2, 0x00a7ff, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab64, 0x00ab66, 0x00ab69, 0x00fb00, + 0x00fb06, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x01df00, 0x01df1e)); } private static void populateSC_LEPC() { @@ -3506,8 +3579,7 @@ private static void populateSC_MODI() { } private static void populateSC_MONG() { - SET_ENCODINGS.put("sc=Mong", - CodePointSet.createNoDedup(0x001800, 0x001801, 0x001804, 0x001804, 0x001806, 0x00180e, 0x001810, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x011660, 0x01166c)); + SET_ENCODINGS.put("sc=Mong", CodePointSet.createNoDedup(0x001800, 0x001801, 0x001804, 0x001804, 0x001806, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x011660, 0x01166c)); } private static void populateSC_MROO() { @@ -3575,6 +3647,10 @@ private static void populateSC_OSMA() { SET_ENCODINGS.put("sc=Osma", CodePointSet.createNoDedup(0x010480, 0x01049d, 0x0104a0, 0x0104a9)); } + private static void populateSC_OUGR() { + SET_ENCODINGS.put("sc=Ougr", CodePointSet.createNoDedup(0x010f70, 0x010f89)); + } + private static void populateSC_PALM() { SET_ENCODINGS.put("sc=Palm", CodePointSet.createNoDedup(0x010860, 0x01087f)); } @@ -3693,7 +3769,7 @@ private static void populateSC_TAGB() { } private static void populateSC_TAKR() { - SET_ENCODINGS.put("sc=Takr", CodePointSet.createNoDedup(0x011680, 0x0116b8, 0x0116c0, 0x0116c9)); + SET_ENCODINGS.put("sc=Takr", CodePointSet.createNoDedup(0x011680, 0x0116b9, 0x0116c0, 0x0116c9)); } private static void populateSC_TALE() { @@ -3720,8 +3796,8 @@ private static void populateSC_TAVT() { } private static void populateSC_TELU() { - SET_ENCODINGS.put("sc=Telu", CodePointSet.createNoDedup(0x000c00, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, - 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c60, 0x000c63, 0x000c66, 0x000c6f, 0x000c77, 0x000c7f)); + SET_ENCODINGS.put("sc=Telu", CodePointSet.createNoDedup(0x000c00, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3c, 0x000c44, 0x000c46, 0x000c48, 0x000c4a, + 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, 0x000c60, 0x000c63, 0x000c66, 0x000c6f, 0x000c77, 0x000c7f)); } private static void populateSC_TFNG() { @@ -3729,7 +3805,7 @@ private static void populateSC_TFNG() { } private static void populateSC_TGLG() { - SET_ENCODINGS.put("sc=Tglg", CodePointSet.createNoDedup(0x001700, 0x00170c, 0x00170e, 0x001714)); + SET_ENCODINGS.put("sc=Tglg", CodePointSet.createNoDedup(0x001700, 0x001715, 0x00171f, 0x00171f)); } private static void populateSC_THAA() { @@ -3749,6 +3825,14 @@ private static void populateSC_TIRH() { SET_ENCODINGS.put("sc=Tirh", CodePointSet.createNoDedup(0x011480, 0x0114c7, 0x0114d0, 0x0114d9)); } + private static void populateSC_TNSA() { + SET_ENCODINGS.put("sc=Tnsa", CodePointSet.createNoDedup(0x016a70, 0x016abe, 0x016ac0, 0x016ac9)); + } + + private static void populateSC_TOTO() { + SET_ENCODINGS.put("sc=Toto", CodePointSet.createNoDedup(0x01e290, 0x01e2ae)); + } + private static void populateSC_UGAR() { SET_ENCODINGS.put("sc=Ugar", CodePointSet.createNoDedup(0x010380, 0x01039d, 0x01039f, 0x01039f)); } @@ -3757,6 +3841,11 @@ private static void populateSC_VAII() { SET_ENCODINGS.put("sc=Vaii", CodePointSet.createNoDedup(0x00a500, 0x00a62b)); } + private static void populateSC_VITH() { + SET_ENCODINGS.put("sc=Vith", CodePointSet.createNoDedup(0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, + 0x0105b9, 0x0105bb, 0x0105bc)); + } + private static void populateSC_WARA() { SET_ENCODINGS.put("sc=Wara", CodePointSet.createNoDedup(0x0118a0, 0x0118f2, 0x0118ff, 0x0118ff)); } @@ -3787,10 +3876,10 @@ private static void populateSC_ZANB() { private static void populateSC_ZINH() { SET_ENCODINGS.put("sc=Zinh", - CodePointSet.createNoDedup(0x000300, 0x00036f, 0x000485, 0x000486, 0x00064b, 0x000655, 0x000670, 0x000670, 0x000951, 0x000954, 0x001ab0, 0x001ac0, 0x001cd0, 0x001cd2, 0x001cd4, - 0x001ce0, 0x001ce2, 0x001ce8, 0x001ced, 0x001ced, 0x001cf4, 0x001cf4, 0x001cf8, 0x001cf9, 0x001dc0, 0x001df9, 0x001dfb, 0x001dff, 0x00200c, 0x00200d, 0x0020d0, - 0x0020f0, 0x00302a, 0x00302d, 0x003099, 0x00309a, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2d, 0x0101fd, 0x0101fd, 0x0102e0, 0x0102e0, 0x01133b, 0x01133b, 0x01d167, - 0x01d169, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x0e0100, 0x0e01ef)); + CodePointSet.createNoDedup(0x000300, 0x00036f, 0x000485, 0x000486, 0x00064b, 0x000655, 0x000670, 0x000670, 0x000951, 0x000954, 0x001ab0, 0x001ace, 0x001cd0, 0x001cd2, 0x001cd4, + 0x001ce0, 0x001ce2, 0x001ce8, 0x001ced, 0x001ced, 0x001cf4, 0x001cf4, 0x001cf8, 0x001cf9, 0x001dc0, 0x001dff, 0x00200c, 0x00200d, 0x0020d0, 0x0020f0, 0x00302a, + 0x00302d, 0x003099, 0x00309a, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2d, 0x0101fd, 0x0101fd, 0x0102e0, 0x0102e0, 0x01133b, 0x01133b, 0x01cf00, 0x01cf2d, 0x01cf30, + 0x01cf46, 0x01d167, 0x01d169, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x0e0100, 0x0e01ef)); } private static void populateSC_ZYYY() { @@ -3799,40 +3888,40 @@ private static void populateSC_ZYYY() { 0x00060c, 0x00060c, 0x00061b, 0x00061b, 0x00061f, 0x00061f, 0x000640, 0x000640, 0x0006dd, 0x0006dd, 0x0008e2, 0x0008e2, 0x000964, 0x000965, 0x000e3f, 0x000e3f, 0x000fd5, 0x000fd8, 0x0010fb, 0x0010fb, 0x0016eb, 0x0016ed, 0x001735, 0x001736, 0x001802, 0x001803, 0x001805, 0x001805, 0x001cd3, 0x001cd3, 0x001ce1, 0x001ce1, 0x001ce9, 0x001cec, 0x001cee, 0x001cf3, 0x001cf5, 0x001cf7, 0x001cfa, 0x001cfa, 0x002000, 0x00200b, 0x00200e, 0x002064, 0x002066, 0x002070, 0x002074, 0x00207e, 0x002080, 0x00208e, 0x0020a0, - 0x0020bf, 0x002100, 0x002125, 0x002127, 0x002129, 0x00212c, 0x002131, 0x002133, 0x00214d, 0x00214f, 0x00215f, 0x002189, 0x00218b, 0x002190, 0x002426, 0x002440, 0x00244a, - 0x002460, 0x0027ff, 0x002900, 0x002b73, 0x002b76, 0x002b95, 0x002b97, 0x002bff, 0x002e00, 0x002e52, 0x002ff0, 0x002ffb, 0x003000, 0x003004, 0x003006, 0x003006, 0x003008, + 0x0020c0, 0x002100, 0x002125, 0x002127, 0x002129, 0x00212c, 0x002131, 0x002133, 0x00214d, 0x00214f, 0x00215f, 0x002189, 0x00218b, 0x002190, 0x002426, 0x002440, 0x00244a, + 0x002460, 0x0027ff, 0x002900, 0x002b73, 0x002b76, 0x002b95, 0x002b97, 0x002bff, 0x002e00, 0x002e5d, 0x002ff0, 0x002ffb, 0x003000, 0x003004, 0x003006, 0x003006, 0x003008, 0x003020, 0x003030, 0x003037, 0x00303c, 0x00303f, 0x00309b, 0x00309c, 0x0030a0, 0x0030a0, 0x0030fb, 0x0030fc, 0x003190, 0x00319f, 0x0031c0, 0x0031e3, 0x003220, 0x00325f, 0x00327f, 0x0032cf, 0x0032ff, 0x0032ff, 0x003358, 0x0033ff, 0x004dc0, 0x004dff, 0x00a700, 0x00a721, 0x00a788, 0x00a78a, 0x00a830, 0x00a839, 0x00a92e, 0x00a92e, 0x00a9cf, 0x00a9cf, 0x00ab5b, 0x00ab5b, 0x00ab6a, 0x00ab6b, 0x00fd3e, 0x00fd3f, 0x00fe10, 0x00fe19, 0x00fe30, 0x00fe52, 0x00fe54, 0x00fe66, 0x00fe68, 0x00fe6b, 0x00feff, 0x00feff, 0x00ff01, 0x00ff20, 0x00ff3b, 0x00ff40, 0x00ff5b, 0x00ff65, 0x00ff70, 0x00ff70, 0x00ff9e, 0x00ff9f, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, 0x00fff9, 0x00fffd, 0x010100, - 0x010102, 0x010107, 0x010133, 0x010137, 0x01013f, 0x010190, 0x01019c, 0x0101d0, 0x0101fc, 0x0102e1, 0x0102fb, 0x016fe2, 0x016fe3, 0x01bca0, 0x01bca3, 0x01d000, 0x01d0f5, - 0x01d100, 0x01d126, 0x01d129, 0x01d166, 0x01d16a, 0x01d17a, 0x01d183, 0x01d184, 0x01d18c, 0x01d1a9, 0x01d1ae, 0x01d1e8, 0x01d2e0, 0x01d2f3, 0x01d300, 0x01d356, 0x01d360, + 0x010102, 0x010107, 0x010133, 0x010137, 0x01013f, 0x010190, 0x01019c, 0x0101d0, 0x0101fc, 0x0102e1, 0x0102fb, 0x01bca0, 0x01bca3, 0x01cf50, 0x01cfc3, 0x01d000, 0x01d0f5, + 0x01d100, 0x01d126, 0x01d129, 0x01d166, 0x01d16a, 0x01d17a, 0x01d183, 0x01d184, 0x01d18c, 0x01d1a9, 0x01d1ae, 0x01d1ea, 0x01d2e0, 0x01d2f3, 0x01d300, 0x01d356, 0x01d360, 0x01d378, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d7cb, 0x01d7ce, 0x01d7ff, 0x01ec71, 0x01ecb4, 0x01ed01, 0x01ed3d, 0x01f000, 0x01f02b, 0x01f030, 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, 0x01f100, 0x01f1ad, 0x01f1e6, 0x01f1ff, 0x01f201, 0x01f202, 0x01f210, 0x01f23b, 0x01f240, - 0x01f248, 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6e0, 0x01f6ec, 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, 0x01f7e0, 0x01f7eb, - 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01f978, 0x01f97a, 0x01f9cb, 0x01f9cd, - 0x01fa53, 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7a, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faa8, 0x01fab0, 0x01fab6, 0x01fac0, 0x01fac2, 0x01fad0, 0x01fad6, - 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca, 0x01fbf0, 0x01fbf9, 0x0e0001, 0x0e0001, 0x0e0020, 0x0e007f)); + 0x01f248, 0x01f250, 0x01f251, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6dd, 0x01f6ec, 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, 0x01f7e0, 0x01f7eb, + 0x01f7f0, 0x01f7f0, 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01fa53, 0x01fa60, + 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7c, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faac, 0x01fab0, 0x01faba, 0x01fac0, 0x01fac5, 0x01fad0, 0x01fad9, 0x01fae0, 0x01fae7, + 0x01faf0, 0x01faf6, 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca, 0x01fbf0, 0x01fbf9, 0x0e0001, 0x0e0001, 0x0e0020, 0x0e007f)); } private static void populateSC_ZZZZ() { SET_ENCODINGS.put("sc=Zzzz", CodePointSet.createNoDedup(0x000378, 0x000379, 0x000380, 0x000383, 0x00038b, 0x00038b, 0x00038d, 0x00038d, 0x0003a2, 0x0003a2, 0x000530, 0x000530, 0x000557, - 0x000558, 0x00058b, 0x00058c, 0x000590, 0x000590, 0x0005c8, 0x0005cf, 0x0005eb, 0x0005ee, 0x0005f5, 0x0005ff, 0x00061d, 0x00061d, 0x00070e, 0x00070e, 0x00074b, 0x00074c, - 0x0007b2, 0x0007bf, 0x0007fb, 0x0007fc, 0x00082e, 0x00082f, 0x00083f, 0x00083f, 0x00085c, 0x00085d, 0x00085f, 0x00085f, 0x00086b, 0x00089f, 0x0008b5, 0x0008b5, 0x0008c8, - 0x0008d2, 0x000984, 0x000984, 0x00098d, 0x00098e, 0x000991, 0x000992, 0x0009a9, 0x0009a9, 0x0009b1, 0x0009b1, 0x0009b3, 0x0009b5, 0x0009ba, 0x0009bb, 0x0009c5, 0x0009c6, - 0x0009c9, 0x0009ca, 0x0009cf, 0x0009d6, 0x0009d8, 0x0009db, 0x0009de, 0x0009de, 0x0009e4, 0x0009e5, 0x0009ff, 0x000a00, 0x000a04, 0x000a04, 0x000a0b, 0x000a0e, 0x000a11, - 0x000a12, 0x000a29, 0x000a29, 0x000a31, 0x000a31, 0x000a34, 0x000a34, 0x000a37, 0x000a37, 0x000a3a, 0x000a3b, 0x000a3d, 0x000a3d, 0x000a43, 0x000a46, 0x000a49, 0x000a4a, - 0x000a4e, 0x000a50, 0x000a52, 0x000a58, 0x000a5d, 0x000a5d, 0x000a5f, 0x000a65, 0x000a77, 0x000a80, 0x000a84, 0x000a84, 0x000a8e, 0x000a8e, 0x000a92, 0x000a92, 0x000aa9, - 0x000aa9, 0x000ab1, 0x000ab1, 0x000ab4, 0x000ab4, 0x000aba, 0x000abb, 0x000ac6, 0x000ac6, 0x000aca, 0x000aca, 0x000ace, 0x000acf, 0x000ad1, 0x000adf, 0x000ae4, 0x000ae5, - 0x000af2, 0x000af8, 0x000b00, 0x000b00, 0x000b04, 0x000b04, 0x000b0d, 0x000b0e, 0x000b11, 0x000b12, 0x000b29, 0x000b29, 0x000b31, 0x000b31, 0x000b34, 0x000b34, 0x000b3a, - 0x000b3b, 0x000b45, 0x000b46, 0x000b49, 0x000b4a, 0x000b4e, 0x000b54, 0x000b58, 0x000b5b, 0x000b5e, 0x000b5e, 0x000b64, 0x000b65, 0x000b78, 0x000b81, 0x000b84, 0x000b84, - 0x000b8b, 0x000b8d, 0x000b91, 0x000b91, 0x000b96, 0x000b98, 0x000b9b, 0x000b9b, 0x000b9d, 0x000b9d, 0x000ba0, 0x000ba2, 0x000ba5, 0x000ba7, 0x000bab, 0x000bad, 0x000bba, - 0x000bbd, 0x000bc3, 0x000bc5, 0x000bc9, 0x000bc9, 0x000bce, 0x000bcf, 0x000bd1, 0x000bd6, 0x000bd8, 0x000be5, 0x000bfb, 0x000bff, 0x000c0d, 0x000c0d, 0x000c11, 0x000c11, - 0x000c29, 0x000c29, 0x000c3a, 0x000c3c, 0x000c45, 0x000c45, 0x000c49, 0x000c49, 0x000c4e, 0x000c54, 0x000c57, 0x000c57, 0x000c5b, 0x000c5f, 0x000c64, 0x000c65, 0x000c70, + 0x000558, 0x00058b, 0x00058c, 0x000590, 0x000590, 0x0005c8, 0x0005cf, 0x0005eb, 0x0005ee, 0x0005f5, 0x0005ff, 0x00070e, 0x00070e, 0x00074b, 0x00074c, 0x0007b2, 0x0007bf, + 0x0007fb, 0x0007fc, 0x00082e, 0x00082f, 0x00083f, 0x00083f, 0x00085c, 0x00085d, 0x00085f, 0x00085f, 0x00086b, 0x00086f, 0x00088f, 0x00088f, 0x000892, 0x000897, 0x000984, + 0x000984, 0x00098d, 0x00098e, 0x000991, 0x000992, 0x0009a9, 0x0009a9, 0x0009b1, 0x0009b1, 0x0009b3, 0x0009b5, 0x0009ba, 0x0009bb, 0x0009c5, 0x0009c6, 0x0009c9, 0x0009ca, + 0x0009cf, 0x0009d6, 0x0009d8, 0x0009db, 0x0009de, 0x0009de, 0x0009e4, 0x0009e5, 0x0009ff, 0x000a00, 0x000a04, 0x000a04, 0x000a0b, 0x000a0e, 0x000a11, 0x000a12, 0x000a29, + 0x000a29, 0x000a31, 0x000a31, 0x000a34, 0x000a34, 0x000a37, 0x000a37, 0x000a3a, 0x000a3b, 0x000a3d, 0x000a3d, 0x000a43, 0x000a46, 0x000a49, 0x000a4a, 0x000a4e, 0x000a50, + 0x000a52, 0x000a58, 0x000a5d, 0x000a5d, 0x000a5f, 0x000a65, 0x000a77, 0x000a80, 0x000a84, 0x000a84, 0x000a8e, 0x000a8e, 0x000a92, 0x000a92, 0x000aa9, 0x000aa9, 0x000ab1, + 0x000ab1, 0x000ab4, 0x000ab4, 0x000aba, 0x000abb, 0x000ac6, 0x000ac6, 0x000aca, 0x000aca, 0x000ace, 0x000acf, 0x000ad1, 0x000adf, 0x000ae4, 0x000ae5, 0x000af2, 0x000af8, + 0x000b00, 0x000b00, 0x000b04, 0x000b04, 0x000b0d, 0x000b0e, 0x000b11, 0x000b12, 0x000b29, 0x000b29, 0x000b31, 0x000b31, 0x000b34, 0x000b34, 0x000b3a, 0x000b3b, 0x000b45, + 0x000b46, 0x000b49, 0x000b4a, 0x000b4e, 0x000b54, 0x000b58, 0x000b5b, 0x000b5e, 0x000b5e, 0x000b64, 0x000b65, 0x000b78, 0x000b81, 0x000b84, 0x000b84, 0x000b8b, 0x000b8d, + 0x000b91, 0x000b91, 0x000b96, 0x000b98, 0x000b9b, 0x000b9b, 0x000b9d, 0x000b9d, 0x000ba0, 0x000ba2, 0x000ba5, 0x000ba7, 0x000bab, 0x000bad, 0x000bba, 0x000bbd, 0x000bc3, + 0x000bc5, 0x000bc9, 0x000bc9, 0x000bce, 0x000bcf, 0x000bd1, 0x000bd6, 0x000bd8, 0x000be5, 0x000bfb, 0x000bff, 0x000c0d, 0x000c0d, 0x000c11, 0x000c11, 0x000c29, 0x000c29, + 0x000c3a, 0x000c3b, 0x000c45, 0x000c45, 0x000c49, 0x000c49, 0x000c4e, 0x000c54, 0x000c57, 0x000c57, 0x000c5b, 0x000c5c, 0x000c5e, 0x000c5f, 0x000c64, 0x000c65, 0x000c70, 0x000c76, 0x000c8d, 0x000c8d, 0x000c91, 0x000c91, 0x000ca9, 0x000ca9, 0x000cb4, 0x000cb4, 0x000cba, 0x000cbb, 0x000cc5, 0x000cc5, 0x000cc9, 0x000cc9, 0x000cce, 0x000cd4, - 0x000cd7, 0x000cdd, 0x000cdf, 0x000cdf, 0x000ce4, 0x000ce5, 0x000cf0, 0x000cf0, 0x000cf3, 0x000cff, 0x000d0d, 0x000d0d, 0x000d11, 0x000d11, 0x000d45, 0x000d45, 0x000d49, + 0x000cd7, 0x000cdc, 0x000cdf, 0x000cdf, 0x000ce4, 0x000ce5, 0x000cf0, 0x000cf0, 0x000cf3, 0x000cff, 0x000d0d, 0x000d0d, 0x000d11, 0x000d11, 0x000d45, 0x000d45, 0x000d49, 0x000d49, 0x000d50, 0x000d53, 0x000d64, 0x000d65, 0x000d80, 0x000d80, 0x000d84, 0x000d84, 0x000d97, 0x000d99, 0x000db2, 0x000db2, 0x000dbc, 0x000dbc, 0x000dbe, 0x000dbf, 0x000dc7, 0x000dc9, 0x000dcb, 0x000dce, 0x000dd5, 0x000dd5, 0x000dd7, 0x000dd7, 0x000de0, 0x000de5, 0x000df0, 0x000df1, 0x000df5, 0x000e00, 0x000e3b, 0x000e3e, 0x000e5c, 0x000e80, 0x000e83, 0x000e83, 0x000e85, 0x000e85, 0x000e8b, 0x000e8b, 0x000ea4, 0x000ea4, 0x000ea6, 0x000ea6, 0x000ebe, 0x000ebf, 0x000ec5, 0x000ec5, 0x000ec7, 0x000ec7, @@ -3840,68 +3929,71 @@ private static void populateSC_ZZZZ() { 0x000fff, 0x0010c6, 0x0010c6, 0x0010c8, 0x0010cc, 0x0010ce, 0x0010cf, 0x001249, 0x001249, 0x00124e, 0x00124f, 0x001257, 0x001257, 0x001259, 0x001259, 0x00125e, 0x00125f, 0x001289, 0x001289, 0x00128e, 0x00128f, 0x0012b1, 0x0012b1, 0x0012b6, 0x0012b7, 0x0012bf, 0x0012bf, 0x0012c1, 0x0012c1, 0x0012c6, 0x0012c7, 0x0012d7, 0x0012d7, 0x001311, 0x001311, 0x001316, 0x001317, 0x00135b, 0x00135c, 0x00137d, 0x00137f, 0x00139a, 0x00139f, 0x0013f6, 0x0013f7, 0x0013fe, 0x0013ff, 0x00169d, 0x00169f, 0x0016f9, 0x0016ff, - 0x00170d, 0x00170d, 0x001715, 0x00171f, 0x001737, 0x00173f, 0x001754, 0x00175f, 0x00176d, 0x00176d, 0x001771, 0x001771, 0x001774, 0x00177f, 0x0017de, 0x0017df, 0x0017ea, - 0x0017ef, 0x0017fa, 0x0017ff, 0x00180f, 0x00180f, 0x00181a, 0x00181f, 0x001879, 0x00187f, 0x0018ab, 0x0018af, 0x0018f6, 0x0018ff, 0x00191f, 0x00191f, 0x00192c, 0x00192f, - 0x00193c, 0x00193f, 0x001941, 0x001943, 0x00196e, 0x00196f, 0x001975, 0x00197f, 0x0019ac, 0x0019af, 0x0019ca, 0x0019cf, 0x0019db, 0x0019dd, 0x001a1c, 0x001a1d, 0x001a5f, - 0x001a5f, 0x001a7d, 0x001a7e, 0x001a8a, 0x001a8f, 0x001a9a, 0x001a9f, 0x001aae, 0x001aaf, 0x001ac1, 0x001aff, 0x001b4c, 0x001b4f, 0x001b7d, 0x001b7f, 0x001bf4, 0x001bfb, - 0x001c38, 0x001c3a, 0x001c4a, 0x001c4c, 0x001c89, 0x001c8f, 0x001cbb, 0x001cbc, 0x001cc8, 0x001ccf, 0x001cfb, 0x001cff, 0x001dfa, 0x001dfa, 0x001f16, 0x001f17, 0x001f1e, - 0x001f1f, 0x001f46, 0x001f47, 0x001f4e, 0x001f4f, 0x001f58, 0x001f58, 0x001f5a, 0x001f5a, 0x001f5c, 0x001f5c, 0x001f5e, 0x001f5e, 0x001f7e, 0x001f7f, 0x001fb5, 0x001fb5, - 0x001fc5, 0x001fc5, 0x001fd4, 0x001fd5, 0x001fdc, 0x001fdc, 0x001ff0, 0x001ff1, 0x001ff5, 0x001ff5, 0x001fff, 0x001fff, 0x002065, 0x002065, 0x002072, 0x002073, 0x00208f, - 0x00208f, 0x00209d, 0x00209f, 0x0020c0, 0x0020cf, 0x0020f1, 0x0020ff, 0x00218c, 0x00218f, 0x002427, 0x00243f, 0x00244b, 0x00245f, 0x002b74, 0x002b75, 0x002b96, 0x002b96, - 0x002c2f, 0x002c2f, 0x002c5f, 0x002c5f, 0x002cf4, 0x002cf8, 0x002d26, 0x002d26, 0x002d28, 0x002d2c, 0x002d2e, 0x002d2f, 0x002d68, 0x002d6e, 0x002d71, 0x002d7e, 0x002d97, - 0x002d9f, 0x002da7, 0x002da7, 0x002daf, 0x002daf, 0x002db7, 0x002db7, 0x002dbf, 0x002dbf, 0x002dc7, 0x002dc7, 0x002dcf, 0x002dcf, 0x002dd7, 0x002dd7, 0x002ddf, 0x002ddf, - 0x002e53, 0x002e7f, 0x002e9a, 0x002e9a, 0x002ef4, 0x002eff, 0x002fd6, 0x002fef, 0x002ffc, 0x002fff, 0x003040, 0x003040, 0x003097, 0x003098, 0x003100, 0x003104, 0x003130, - 0x003130, 0x00318f, 0x00318f, 0x0031e4, 0x0031ef, 0x00321f, 0x00321f, 0x009ffd, 0x009fff, 0x00a48d, 0x00a48f, 0x00a4c7, 0x00a4cf, 0x00a62c, 0x00a63f, 0x00a6f8, 0x00a6ff, - 0x00a7c0, 0x00a7c1, 0x00a7cb, 0x00a7f4, 0x00a82d, 0x00a82f, 0x00a83a, 0x00a83f, 0x00a878, 0x00a87f, 0x00a8c6, 0x00a8cd, 0x00a8da, 0x00a8df, 0x00a954, 0x00a95e, 0x00a97d, - 0x00a97f, 0x00a9ce, 0x00a9ce, 0x00a9da, 0x00a9dd, 0x00a9ff, 0x00a9ff, 0x00aa37, 0x00aa3f, 0x00aa4e, 0x00aa4f, 0x00aa5a, 0x00aa5b, 0x00aac3, 0x00aada, 0x00aaf7, 0x00ab00, - 0x00ab07, 0x00ab08, 0x00ab0f, 0x00ab10, 0x00ab17, 0x00ab1f, 0x00ab27, 0x00ab27, 0x00ab2f, 0x00ab2f, 0x00ab6c, 0x00ab6f, 0x00abee, 0x00abef, 0x00abfa, 0x00abff, 0x00d7a4, - 0x00d7af, 0x00d7c7, 0x00d7ca, 0x00d7fc, 0x00f8ff, 0x00fa6e, 0x00fa6f, 0x00fada, 0x00faff, 0x00fb07, 0x00fb12, 0x00fb18, 0x00fb1c, 0x00fb37, 0x00fb37, 0x00fb3d, 0x00fb3d, - 0x00fb3f, 0x00fb3f, 0x00fb42, 0x00fb42, 0x00fb45, 0x00fb45, 0x00fbc2, 0x00fbd2, 0x00fd40, 0x00fd4f, 0x00fd90, 0x00fd91, 0x00fdc8, 0x00fdef, 0x00fdfe, 0x00fdff, 0x00fe1a, - 0x00fe1f, 0x00fe53, 0x00fe53, 0x00fe67, 0x00fe67, 0x00fe6c, 0x00fe6f, 0x00fe75, 0x00fe75, 0x00fefd, 0x00fefe, 0x00ff00, 0x00ff00, 0x00ffbf, 0x00ffc1, 0x00ffc8, 0x00ffc9, - 0x00ffd0, 0x00ffd1, 0x00ffd8, 0x00ffd9, 0x00ffdd, 0x00ffdf, 0x00ffe7, 0x00ffe7, 0x00ffef, 0x00fff8, 0x00fffe, 0x00ffff, 0x01000c, 0x01000c, 0x010027, 0x010027, 0x01003b, - 0x01003b, 0x01003e, 0x01003e, 0x01004e, 0x01004f, 0x01005e, 0x01007f, 0x0100fb, 0x0100ff, 0x010103, 0x010106, 0x010134, 0x010136, 0x01018f, 0x01018f, 0x01019d, 0x01019f, - 0x0101a1, 0x0101cf, 0x0101fe, 0x01027f, 0x01029d, 0x01029f, 0x0102d1, 0x0102df, 0x0102fc, 0x0102ff, 0x010324, 0x01032c, 0x01034b, 0x01034f, 0x01037b, 0x01037f, 0x01039e, - 0x01039e, 0x0103c4, 0x0103c7, 0x0103d6, 0x0103ff, 0x01049e, 0x01049f, 0x0104aa, 0x0104af, 0x0104d4, 0x0104d7, 0x0104fc, 0x0104ff, 0x010528, 0x01052f, 0x010564, 0x01056e, - 0x010570, 0x0105ff, 0x010737, 0x01073f, 0x010756, 0x01075f, 0x010768, 0x0107ff, 0x010806, 0x010807, 0x010809, 0x010809, 0x010836, 0x010836, 0x010839, 0x01083b, 0x01083d, - 0x01083e, 0x010856, 0x010856, 0x01089f, 0x0108a6, 0x0108b0, 0x0108df, 0x0108f3, 0x0108f3, 0x0108f6, 0x0108fa, 0x01091c, 0x01091e, 0x01093a, 0x01093e, 0x010940, 0x01097f, - 0x0109b8, 0x0109bb, 0x0109d0, 0x0109d1, 0x010a04, 0x010a04, 0x010a07, 0x010a0b, 0x010a14, 0x010a14, 0x010a18, 0x010a18, 0x010a36, 0x010a37, 0x010a3b, 0x010a3e, 0x010a49, - 0x010a4f, 0x010a59, 0x010a5f, 0x010aa0, 0x010abf, 0x010ae7, 0x010aea, 0x010af7, 0x010aff, 0x010b36, 0x010b38, 0x010b56, 0x010b57, 0x010b73, 0x010b77, 0x010b92, 0x010b98, - 0x010b9d, 0x010ba8, 0x010bb0, 0x010bff, 0x010c49, 0x010c7f, 0x010cb3, 0x010cbf, 0x010cf3, 0x010cf9, 0x010d28, 0x010d2f, 0x010d3a, 0x010e5f, 0x010e7f, 0x010e7f, 0x010eaa, - 0x010eaa, 0x010eae, 0x010eaf, 0x010eb2, 0x010eff, 0x010f28, 0x010f2f, 0x010f5a, 0x010faf, 0x010fcc, 0x010fdf, 0x010ff7, 0x010fff, 0x01104e, 0x011051, 0x011070, 0x01107e, - 0x0110c2, 0x0110cc, 0x0110ce, 0x0110cf, 0x0110e9, 0x0110ef, 0x0110fa, 0x0110ff, 0x011135, 0x011135, 0x011148, 0x01114f, 0x011177, 0x01117f, 0x0111e0, 0x0111e0, 0x0111f5, - 0x0111ff, 0x011212, 0x011212, 0x01123f, 0x01127f, 0x011287, 0x011287, 0x011289, 0x011289, 0x01128e, 0x01128e, 0x01129e, 0x01129e, 0x0112aa, 0x0112af, 0x0112eb, 0x0112ef, - 0x0112fa, 0x0112ff, 0x011304, 0x011304, 0x01130d, 0x01130e, 0x011311, 0x011312, 0x011329, 0x011329, 0x011331, 0x011331, 0x011334, 0x011334, 0x01133a, 0x01133a, 0x011345, - 0x011346, 0x011349, 0x01134a, 0x01134e, 0x01134f, 0x011351, 0x011356, 0x011358, 0x01135c, 0x011364, 0x011365, 0x01136d, 0x01136f, 0x011375, 0x0113ff, 0x01145c, 0x01145c, - 0x011462, 0x01147f, 0x0114c8, 0x0114cf, 0x0114da, 0x01157f, 0x0115b6, 0x0115b7, 0x0115de, 0x0115ff, 0x011645, 0x01164f, 0x01165a, 0x01165f, 0x01166d, 0x01167f, 0x0116b9, - 0x0116bf, 0x0116ca, 0x0116ff, 0x01171b, 0x01171c, 0x01172c, 0x01172f, 0x011740, 0x0117ff, 0x01183c, 0x01189f, 0x0118f3, 0x0118fe, 0x011907, 0x011908, 0x01190a, 0x01190b, - 0x011914, 0x011914, 0x011917, 0x011917, 0x011936, 0x011936, 0x011939, 0x01193a, 0x011947, 0x01194f, 0x01195a, 0x01199f, 0x0119a8, 0x0119a9, 0x0119d8, 0x0119d9, 0x0119e5, - 0x0119ff, 0x011a48, 0x011a4f, 0x011aa3, 0x011abf, 0x011af9, 0x011bff, 0x011c09, 0x011c09, 0x011c37, 0x011c37, 0x011c46, 0x011c4f, 0x011c6d, 0x011c6f, 0x011c90, 0x011c91, - 0x011ca8, 0x011ca8, 0x011cb7, 0x011cff, 0x011d07, 0x011d07, 0x011d0a, 0x011d0a, 0x011d37, 0x011d39, 0x011d3b, 0x011d3b, 0x011d3e, 0x011d3e, 0x011d48, 0x011d4f, 0x011d5a, - 0x011d5f, 0x011d66, 0x011d66, 0x011d69, 0x011d69, 0x011d8f, 0x011d8f, 0x011d92, 0x011d92, 0x011d99, 0x011d9f, 0x011daa, 0x011edf, 0x011ef9, 0x011faf, 0x011fb1, 0x011fbf, - 0x011ff2, 0x011ffe, 0x01239a, 0x0123ff, 0x01246f, 0x01246f, 0x012475, 0x01247f, 0x012544, 0x012fff, 0x01342f, 0x01342f, 0x013439, 0x0143ff, 0x014647, 0x0167ff, 0x016a39, - 0x016a3f, 0x016a5f, 0x016a5f, 0x016a6a, 0x016a6d, 0x016a70, 0x016acf, 0x016aee, 0x016aef, 0x016af6, 0x016aff, 0x016b46, 0x016b4f, 0x016b5a, 0x016b5a, 0x016b62, 0x016b62, - 0x016b78, 0x016b7c, 0x016b90, 0x016e3f, 0x016e9b, 0x016eff, 0x016f4b, 0x016f4e, 0x016f88, 0x016f8e, 0x016fa0, 0x016fdf, 0x016fe5, 0x016fef, 0x016ff2, 0x016fff, 0x0187f8, - 0x0187ff, 0x018cd6, 0x018cff, 0x018d09, 0x01afff, 0x01b11f, 0x01b14f, 0x01b153, 0x01b163, 0x01b168, 0x01b16f, 0x01b2fc, 0x01bbff, 0x01bc6b, 0x01bc6f, 0x01bc7d, 0x01bc7f, - 0x01bc89, 0x01bc8f, 0x01bc9a, 0x01bc9b, 0x01bca4, 0x01cfff, 0x01d0f6, 0x01d0ff, 0x01d127, 0x01d128, 0x01d1e9, 0x01d1ff, 0x01d246, 0x01d2df, 0x01d2f4, 0x01d2ff, 0x01d357, - 0x01d35f, 0x01d379, 0x01d3ff, 0x01d455, 0x01d455, 0x01d49d, 0x01d49d, 0x01d4a0, 0x01d4a1, 0x01d4a3, 0x01d4a4, 0x01d4a7, 0x01d4a8, 0x01d4ad, 0x01d4ad, 0x01d4ba, 0x01d4ba, - 0x01d4bc, 0x01d4bc, 0x01d4c4, 0x01d4c4, 0x01d506, 0x01d506, 0x01d50b, 0x01d50c, 0x01d515, 0x01d515, 0x01d51d, 0x01d51d, 0x01d53a, 0x01d53a, 0x01d53f, 0x01d53f, 0x01d545, - 0x01d545, 0x01d547, 0x01d549, 0x01d551, 0x01d551, 0x01d6a6, 0x01d6a7, 0x01d7cc, 0x01d7cd, 0x01da8c, 0x01da9a, 0x01daa0, 0x01daa0, 0x01dab0, 0x01dfff, 0x01e007, 0x01e007, - 0x01e019, 0x01e01a, 0x01e022, 0x01e022, 0x01e025, 0x01e025, 0x01e02b, 0x01e0ff, 0x01e12d, 0x01e12f, 0x01e13e, 0x01e13f, 0x01e14a, 0x01e14d, 0x01e150, 0x01e2bf, 0x01e2fa, - 0x01e2fe, 0x01e300, 0x01e7ff, 0x01e8c5, 0x01e8c6, 0x01e8d7, 0x01e8ff, 0x01e94c, 0x01e94f, 0x01e95a, 0x01e95d, 0x01e960, 0x01ec70, 0x01ecb5, 0x01ed00, 0x01ed3e, 0x01edff, - 0x01ee04, 0x01ee04, 0x01ee20, 0x01ee20, 0x01ee23, 0x01ee23, 0x01ee25, 0x01ee26, 0x01ee28, 0x01ee28, 0x01ee33, 0x01ee33, 0x01ee38, 0x01ee38, 0x01ee3a, 0x01ee3a, 0x01ee3c, - 0x01ee41, 0x01ee43, 0x01ee46, 0x01ee48, 0x01ee48, 0x01ee4a, 0x01ee4a, 0x01ee4c, 0x01ee4c, 0x01ee50, 0x01ee50, 0x01ee53, 0x01ee53, 0x01ee55, 0x01ee56, 0x01ee58, 0x01ee58, - 0x01ee5a, 0x01ee5a, 0x01ee5c, 0x01ee5c, 0x01ee5e, 0x01ee5e, 0x01ee60, 0x01ee60, 0x01ee63, 0x01ee63, 0x01ee65, 0x01ee66, 0x01ee6b, 0x01ee6b, 0x01ee73, 0x01ee73, 0x01ee78, - 0x01ee78, 0x01ee7d, 0x01ee7d, 0x01ee7f, 0x01ee7f, 0x01ee8a, 0x01ee8a, 0x01ee9c, 0x01eea0, 0x01eea4, 0x01eea4, 0x01eeaa, 0x01eeaa, 0x01eebc, 0x01eeef, 0x01eef2, 0x01efff, - 0x01f02c, 0x01f02f, 0x01f094, 0x01f09f, 0x01f0af, 0x01f0b0, 0x01f0c0, 0x01f0c0, 0x01f0d0, 0x01f0d0, 0x01f0f6, 0x01f0ff, 0x01f1ae, 0x01f1e5, 0x01f203, 0x01f20f, 0x01f23c, - 0x01f23f, 0x01f249, 0x01f24f, 0x01f252, 0x01f25f, 0x01f266, 0x01f2ff, 0x01f6d8, 0x01f6df, 0x01f6ed, 0x01f6ef, 0x01f6fd, 0x01f6ff, 0x01f774, 0x01f77f, 0x01f7d9, 0x01f7df, - 0x01f7ec, 0x01f7ff, 0x01f80c, 0x01f80f, 0x01f848, 0x01f84f, 0x01f85a, 0x01f85f, 0x01f888, 0x01f88f, 0x01f8ae, 0x01f8af, 0x01f8b2, 0x01f8ff, 0x01f979, 0x01f979, 0x01f9cc, - 0x01f9cc, 0x01fa54, 0x01fa5f, 0x01fa6e, 0x01fa6f, 0x01fa75, 0x01fa77, 0x01fa7b, 0x01fa7f, 0x01fa87, 0x01fa8f, 0x01faa9, 0x01faaf, 0x01fab7, 0x01fabf, 0x01fac3, 0x01facf, - 0x01fad7, 0x01faff, 0x01fb93, 0x01fb93, 0x01fbcb, 0x01fbef, 0x01fbfa, 0x01ffff, 0x02a6de, 0x02a6ff, 0x02b735, 0x02b73f, 0x02b81e, 0x02b81f, 0x02cea2, 0x02ceaf, 0x02ebe1, - 0x02f7ff, 0x02fa1e, 0x02ffff, 0x03134b, 0x0e0000, 0x0e0002, 0x0e001f, 0x0e0080, 0x0e00ff, 0x0e01f0, 0x10ffff)); + 0x001716, 0x00171e, 0x001737, 0x00173f, 0x001754, 0x00175f, 0x00176d, 0x00176d, 0x001771, 0x001771, 0x001774, 0x00177f, 0x0017de, 0x0017df, 0x0017ea, 0x0017ef, 0x0017fa, + 0x0017ff, 0x00181a, 0x00181f, 0x001879, 0x00187f, 0x0018ab, 0x0018af, 0x0018f6, 0x0018ff, 0x00191f, 0x00191f, 0x00192c, 0x00192f, 0x00193c, 0x00193f, 0x001941, 0x001943, + 0x00196e, 0x00196f, 0x001975, 0x00197f, 0x0019ac, 0x0019af, 0x0019ca, 0x0019cf, 0x0019db, 0x0019dd, 0x001a1c, 0x001a1d, 0x001a5f, 0x001a5f, 0x001a7d, 0x001a7e, 0x001a8a, + 0x001a8f, 0x001a9a, 0x001a9f, 0x001aae, 0x001aaf, 0x001acf, 0x001aff, 0x001b4d, 0x001b4f, 0x001b7f, 0x001b7f, 0x001bf4, 0x001bfb, 0x001c38, 0x001c3a, 0x001c4a, 0x001c4c, + 0x001c89, 0x001c8f, 0x001cbb, 0x001cbc, 0x001cc8, 0x001ccf, 0x001cfb, 0x001cff, 0x001f16, 0x001f17, 0x001f1e, 0x001f1f, 0x001f46, 0x001f47, 0x001f4e, 0x001f4f, 0x001f58, + 0x001f58, 0x001f5a, 0x001f5a, 0x001f5c, 0x001f5c, 0x001f5e, 0x001f5e, 0x001f7e, 0x001f7f, 0x001fb5, 0x001fb5, 0x001fc5, 0x001fc5, 0x001fd4, 0x001fd5, 0x001fdc, 0x001fdc, + 0x001ff0, 0x001ff1, 0x001ff5, 0x001ff5, 0x001fff, 0x001fff, 0x002065, 0x002065, 0x002072, 0x002073, 0x00208f, 0x00208f, 0x00209d, 0x00209f, 0x0020c1, 0x0020cf, 0x0020f1, + 0x0020ff, 0x00218c, 0x00218f, 0x002427, 0x00243f, 0x00244b, 0x00245f, 0x002b74, 0x002b75, 0x002b96, 0x002b96, 0x002cf4, 0x002cf8, 0x002d26, 0x002d26, 0x002d28, 0x002d2c, + 0x002d2e, 0x002d2f, 0x002d68, 0x002d6e, 0x002d71, 0x002d7e, 0x002d97, 0x002d9f, 0x002da7, 0x002da7, 0x002daf, 0x002daf, 0x002db7, 0x002db7, 0x002dbf, 0x002dbf, 0x002dc7, + 0x002dc7, 0x002dcf, 0x002dcf, 0x002dd7, 0x002dd7, 0x002ddf, 0x002ddf, 0x002e5e, 0x002e7f, 0x002e9a, 0x002e9a, 0x002ef4, 0x002eff, 0x002fd6, 0x002fef, 0x002ffc, 0x002fff, + 0x003040, 0x003040, 0x003097, 0x003098, 0x003100, 0x003104, 0x003130, 0x003130, 0x00318f, 0x00318f, 0x0031e4, 0x0031ef, 0x00321f, 0x00321f, 0x00a48d, 0x00a48f, 0x00a4c7, + 0x00a4cf, 0x00a62c, 0x00a63f, 0x00a6f8, 0x00a6ff, 0x00a7cb, 0x00a7cf, 0x00a7d2, 0x00a7d2, 0x00a7d4, 0x00a7d4, 0x00a7da, 0x00a7f1, 0x00a82d, 0x00a82f, 0x00a83a, 0x00a83f, + 0x00a878, 0x00a87f, 0x00a8c6, 0x00a8cd, 0x00a8da, 0x00a8df, 0x00a954, 0x00a95e, 0x00a97d, 0x00a97f, 0x00a9ce, 0x00a9ce, 0x00a9da, 0x00a9dd, 0x00a9ff, 0x00a9ff, 0x00aa37, + 0x00aa3f, 0x00aa4e, 0x00aa4f, 0x00aa5a, 0x00aa5b, 0x00aac3, 0x00aada, 0x00aaf7, 0x00ab00, 0x00ab07, 0x00ab08, 0x00ab0f, 0x00ab10, 0x00ab17, 0x00ab1f, 0x00ab27, 0x00ab27, + 0x00ab2f, 0x00ab2f, 0x00ab6c, 0x00ab6f, 0x00abee, 0x00abef, 0x00abfa, 0x00abff, 0x00d7a4, 0x00d7af, 0x00d7c7, 0x00d7ca, 0x00d7fc, 0x00f8ff, 0x00fa6e, 0x00fa6f, 0x00fada, + 0x00faff, 0x00fb07, 0x00fb12, 0x00fb18, 0x00fb1c, 0x00fb37, 0x00fb37, 0x00fb3d, 0x00fb3d, 0x00fb3f, 0x00fb3f, 0x00fb42, 0x00fb42, 0x00fb45, 0x00fb45, 0x00fbc3, 0x00fbd2, + 0x00fd90, 0x00fd91, 0x00fdc8, 0x00fdce, 0x00fdd0, 0x00fdef, 0x00fe1a, 0x00fe1f, 0x00fe53, 0x00fe53, 0x00fe67, 0x00fe67, 0x00fe6c, 0x00fe6f, 0x00fe75, 0x00fe75, 0x00fefd, + 0x00fefe, 0x00ff00, 0x00ff00, 0x00ffbf, 0x00ffc1, 0x00ffc8, 0x00ffc9, 0x00ffd0, 0x00ffd1, 0x00ffd8, 0x00ffd9, 0x00ffdd, 0x00ffdf, 0x00ffe7, 0x00ffe7, 0x00ffef, 0x00fff8, + 0x00fffe, 0x00ffff, 0x01000c, 0x01000c, 0x010027, 0x010027, 0x01003b, 0x01003b, 0x01003e, 0x01003e, 0x01004e, 0x01004f, 0x01005e, 0x01007f, 0x0100fb, 0x0100ff, 0x010103, + 0x010106, 0x010134, 0x010136, 0x01018f, 0x01018f, 0x01019d, 0x01019f, 0x0101a1, 0x0101cf, 0x0101fe, 0x01027f, 0x01029d, 0x01029f, 0x0102d1, 0x0102df, 0x0102fc, 0x0102ff, + 0x010324, 0x01032c, 0x01034b, 0x01034f, 0x01037b, 0x01037f, 0x01039e, 0x01039e, 0x0103c4, 0x0103c7, 0x0103d6, 0x0103ff, 0x01049e, 0x01049f, 0x0104aa, 0x0104af, 0x0104d4, + 0x0104d7, 0x0104fc, 0x0104ff, 0x010528, 0x01052f, 0x010564, 0x01056e, 0x01057b, 0x01057b, 0x01058b, 0x01058b, 0x010593, 0x010593, 0x010596, 0x010596, 0x0105a2, 0x0105a2, + 0x0105b2, 0x0105b2, 0x0105ba, 0x0105ba, 0x0105bd, 0x0105ff, 0x010737, 0x01073f, 0x010756, 0x01075f, 0x010768, 0x01077f, 0x010786, 0x010786, 0x0107b1, 0x0107b1, 0x0107bb, + 0x0107ff, 0x010806, 0x010807, 0x010809, 0x010809, 0x010836, 0x010836, 0x010839, 0x01083b, 0x01083d, 0x01083e, 0x010856, 0x010856, 0x01089f, 0x0108a6, 0x0108b0, 0x0108df, + 0x0108f3, 0x0108f3, 0x0108f6, 0x0108fa, 0x01091c, 0x01091e, 0x01093a, 0x01093e, 0x010940, 0x01097f, 0x0109b8, 0x0109bb, 0x0109d0, 0x0109d1, 0x010a04, 0x010a04, 0x010a07, + 0x010a0b, 0x010a14, 0x010a14, 0x010a18, 0x010a18, 0x010a36, 0x010a37, 0x010a3b, 0x010a3e, 0x010a49, 0x010a4f, 0x010a59, 0x010a5f, 0x010aa0, 0x010abf, 0x010ae7, 0x010aea, + 0x010af7, 0x010aff, 0x010b36, 0x010b38, 0x010b56, 0x010b57, 0x010b73, 0x010b77, 0x010b92, 0x010b98, 0x010b9d, 0x010ba8, 0x010bb0, 0x010bff, 0x010c49, 0x010c7f, 0x010cb3, + 0x010cbf, 0x010cf3, 0x010cf9, 0x010d28, 0x010d2f, 0x010d3a, 0x010e5f, 0x010e7f, 0x010e7f, 0x010eaa, 0x010eaa, 0x010eae, 0x010eaf, 0x010eb2, 0x010eff, 0x010f28, 0x010f2f, + 0x010f5a, 0x010f6f, 0x010f8a, 0x010faf, 0x010fcc, 0x010fdf, 0x010ff7, 0x010fff, 0x01104e, 0x011051, 0x011076, 0x01107e, 0x0110c3, 0x0110cc, 0x0110ce, 0x0110cf, 0x0110e9, + 0x0110ef, 0x0110fa, 0x0110ff, 0x011135, 0x011135, 0x011148, 0x01114f, 0x011177, 0x01117f, 0x0111e0, 0x0111e0, 0x0111f5, 0x0111ff, 0x011212, 0x011212, 0x01123f, 0x01127f, + 0x011287, 0x011287, 0x011289, 0x011289, 0x01128e, 0x01128e, 0x01129e, 0x01129e, 0x0112aa, 0x0112af, 0x0112eb, 0x0112ef, 0x0112fa, 0x0112ff, 0x011304, 0x011304, 0x01130d, + 0x01130e, 0x011311, 0x011312, 0x011329, 0x011329, 0x011331, 0x011331, 0x011334, 0x011334, 0x01133a, 0x01133a, 0x011345, 0x011346, 0x011349, 0x01134a, 0x01134e, 0x01134f, + 0x011351, 0x011356, 0x011358, 0x01135c, 0x011364, 0x011365, 0x01136d, 0x01136f, 0x011375, 0x0113ff, 0x01145c, 0x01145c, 0x011462, 0x01147f, 0x0114c8, 0x0114cf, 0x0114da, + 0x01157f, 0x0115b6, 0x0115b7, 0x0115de, 0x0115ff, 0x011645, 0x01164f, 0x01165a, 0x01165f, 0x01166d, 0x01167f, 0x0116ba, 0x0116bf, 0x0116ca, 0x0116ff, 0x01171b, 0x01171c, + 0x01172c, 0x01172f, 0x011747, 0x0117ff, 0x01183c, 0x01189f, 0x0118f3, 0x0118fe, 0x011907, 0x011908, 0x01190a, 0x01190b, 0x011914, 0x011914, 0x011917, 0x011917, 0x011936, + 0x011936, 0x011939, 0x01193a, 0x011947, 0x01194f, 0x01195a, 0x01199f, 0x0119a8, 0x0119a9, 0x0119d8, 0x0119d9, 0x0119e5, 0x0119ff, 0x011a48, 0x011a4f, 0x011aa3, 0x011aaf, + 0x011af9, 0x011bff, 0x011c09, 0x011c09, 0x011c37, 0x011c37, 0x011c46, 0x011c4f, 0x011c6d, 0x011c6f, 0x011c90, 0x011c91, 0x011ca8, 0x011ca8, 0x011cb7, 0x011cff, 0x011d07, + 0x011d07, 0x011d0a, 0x011d0a, 0x011d37, 0x011d39, 0x011d3b, 0x011d3b, 0x011d3e, 0x011d3e, 0x011d48, 0x011d4f, 0x011d5a, 0x011d5f, 0x011d66, 0x011d66, 0x011d69, 0x011d69, + 0x011d8f, 0x011d8f, 0x011d92, 0x011d92, 0x011d99, 0x011d9f, 0x011daa, 0x011edf, 0x011ef9, 0x011faf, 0x011fb1, 0x011fbf, 0x011ff2, 0x011ffe, 0x01239a, 0x0123ff, 0x01246f, + 0x01246f, 0x012475, 0x01247f, 0x012544, 0x012f8f, 0x012ff3, 0x012fff, 0x01342f, 0x01342f, 0x013439, 0x0143ff, 0x014647, 0x0167ff, 0x016a39, 0x016a3f, 0x016a5f, 0x016a5f, + 0x016a6a, 0x016a6d, 0x016abf, 0x016abf, 0x016aca, 0x016acf, 0x016aee, 0x016aef, 0x016af6, 0x016aff, 0x016b46, 0x016b4f, 0x016b5a, 0x016b5a, 0x016b62, 0x016b62, 0x016b78, + 0x016b7c, 0x016b90, 0x016e3f, 0x016e9b, 0x016eff, 0x016f4b, 0x016f4e, 0x016f88, 0x016f8e, 0x016fa0, 0x016fdf, 0x016fe5, 0x016fef, 0x016ff2, 0x016fff, 0x0187f8, 0x0187ff, + 0x018cd6, 0x018cff, 0x018d09, 0x01afef, 0x01aff4, 0x01aff4, 0x01affc, 0x01affc, 0x01afff, 0x01afff, 0x01b123, 0x01b14f, 0x01b153, 0x01b163, 0x01b168, 0x01b16f, 0x01b2fc, + 0x01bbff, 0x01bc6b, 0x01bc6f, 0x01bc7d, 0x01bc7f, 0x01bc89, 0x01bc8f, 0x01bc9a, 0x01bc9b, 0x01bca4, 0x01ceff, 0x01cf2e, 0x01cf2f, 0x01cf47, 0x01cf4f, 0x01cfc4, 0x01cfff, + 0x01d0f6, 0x01d0ff, 0x01d127, 0x01d128, 0x01d1eb, 0x01d1ff, 0x01d246, 0x01d2df, 0x01d2f4, 0x01d2ff, 0x01d357, 0x01d35f, 0x01d379, 0x01d3ff, 0x01d455, 0x01d455, 0x01d49d, + 0x01d49d, 0x01d4a0, 0x01d4a1, 0x01d4a3, 0x01d4a4, 0x01d4a7, 0x01d4a8, 0x01d4ad, 0x01d4ad, 0x01d4ba, 0x01d4ba, 0x01d4bc, 0x01d4bc, 0x01d4c4, 0x01d4c4, 0x01d506, 0x01d506, + 0x01d50b, 0x01d50c, 0x01d515, 0x01d515, 0x01d51d, 0x01d51d, 0x01d53a, 0x01d53a, 0x01d53f, 0x01d53f, 0x01d545, 0x01d545, 0x01d547, 0x01d549, 0x01d551, 0x01d551, 0x01d6a6, + 0x01d6a7, 0x01d7cc, 0x01d7cd, 0x01da8c, 0x01da9a, 0x01daa0, 0x01daa0, 0x01dab0, 0x01deff, 0x01df1f, 0x01dfff, 0x01e007, 0x01e007, 0x01e019, 0x01e01a, 0x01e022, 0x01e022, + 0x01e025, 0x01e025, 0x01e02b, 0x01e0ff, 0x01e12d, 0x01e12f, 0x01e13e, 0x01e13f, 0x01e14a, 0x01e14d, 0x01e150, 0x01e28f, 0x01e2af, 0x01e2bf, 0x01e2fa, 0x01e2fe, 0x01e300, + 0x01e7df, 0x01e7e7, 0x01e7e7, 0x01e7ec, 0x01e7ec, 0x01e7ef, 0x01e7ef, 0x01e7ff, 0x01e7ff, 0x01e8c5, 0x01e8c6, 0x01e8d7, 0x01e8ff, 0x01e94c, 0x01e94f, 0x01e95a, 0x01e95d, + 0x01e960, 0x01ec70, 0x01ecb5, 0x01ed00, 0x01ed3e, 0x01edff, 0x01ee04, 0x01ee04, 0x01ee20, 0x01ee20, 0x01ee23, 0x01ee23, 0x01ee25, 0x01ee26, 0x01ee28, 0x01ee28, 0x01ee33, + 0x01ee33, 0x01ee38, 0x01ee38, 0x01ee3a, 0x01ee3a, 0x01ee3c, 0x01ee41, 0x01ee43, 0x01ee46, 0x01ee48, 0x01ee48, 0x01ee4a, 0x01ee4a, 0x01ee4c, 0x01ee4c, 0x01ee50, 0x01ee50, + 0x01ee53, 0x01ee53, 0x01ee55, 0x01ee56, 0x01ee58, 0x01ee58, 0x01ee5a, 0x01ee5a, 0x01ee5c, 0x01ee5c, 0x01ee5e, 0x01ee5e, 0x01ee60, 0x01ee60, 0x01ee63, 0x01ee63, 0x01ee65, + 0x01ee66, 0x01ee6b, 0x01ee6b, 0x01ee73, 0x01ee73, 0x01ee78, 0x01ee78, 0x01ee7d, 0x01ee7d, 0x01ee7f, 0x01ee7f, 0x01ee8a, 0x01ee8a, 0x01ee9c, 0x01eea0, 0x01eea4, 0x01eea4, + 0x01eeaa, 0x01eeaa, 0x01eebc, 0x01eeef, 0x01eef2, 0x01efff, 0x01f02c, 0x01f02f, 0x01f094, 0x01f09f, 0x01f0af, 0x01f0b0, 0x01f0c0, 0x01f0c0, 0x01f0d0, 0x01f0d0, 0x01f0f6, + 0x01f0ff, 0x01f1ae, 0x01f1e5, 0x01f203, 0x01f20f, 0x01f23c, 0x01f23f, 0x01f249, 0x01f24f, 0x01f252, 0x01f25f, 0x01f266, 0x01f2ff, 0x01f6d8, 0x01f6dc, 0x01f6ed, 0x01f6ef, + 0x01f6fd, 0x01f6ff, 0x01f774, 0x01f77f, 0x01f7d9, 0x01f7df, 0x01f7ec, 0x01f7ef, 0x01f7f1, 0x01f7ff, 0x01f80c, 0x01f80f, 0x01f848, 0x01f84f, 0x01f85a, 0x01f85f, 0x01f888, + 0x01f88f, 0x01f8ae, 0x01f8af, 0x01f8b2, 0x01f8ff, 0x01fa54, 0x01fa5f, 0x01fa6e, 0x01fa6f, 0x01fa75, 0x01fa77, 0x01fa7d, 0x01fa7f, 0x01fa87, 0x01fa8f, 0x01faad, 0x01faaf, + 0x01fabb, 0x01fabf, 0x01fac6, 0x01facf, 0x01fada, 0x01fadf, 0x01fae8, 0x01faef, 0x01faf7, 0x01faff, 0x01fb93, 0x01fb93, 0x01fbcb, 0x01fbef, 0x01fbfa, 0x01ffff, 0x02a6e0, + 0x02a6ff, 0x02b739, 0x02b73f, 0x02b81e, 0x02b81f, 0x02cea2, 0x02ceaf, 0x02ebe1, 0x02f7ff, 0x02fa1e, 0x02ffff, 0x03134b, 0x0e0000, 0x0e0002, 0x0e001f, 0x0e0080, 0x0e00ff, + 0x0e01f0, 0x10ffff)); } private static void populateSCX_ADLM() { - SET_ENCODINGS.put("scx=Adlm", CodePointSet.createNoDedup(0x000640, 0x000640, 0x01e900, 0x01e94b, 0x01e950, 0x01e959, 0x01e95e, 0x01e95f)); + SET_ENCODINGS.put("scx=Adlm", CodePointSet.createNoDedup(0x00061f, 0x00061f, 0x000640, 0x000640, 0x01e900, 0x01e94b, 0x01e950, 0x01e959, 0x01e95e, 0x01e95f)); } private static void populateSCX_AGHB() { @@ -3909,18 +4001,18 @@ private static void populateSCX_AGHB() { } private static void populateSCX_AHOM() { - SET_ENCODINGS.put("scx=Ahom", CodePointSet.createNoDedup(0x011700, 0x01171a, 0x01171d, 0x01172b, 0x011730, 0x01173f)); + SET_ENCODINGS.put("scx=Ahom", CodePointSet.createNoDedup(0x011700, 0x01171a, 0x01171d, 0x01172b, 0x011730, 0x011746)); } private static void populateSCX_ARAB() { SET_ENCODINGS.put("scx=Arab", - CodePointSet.createNoDedup(0x000600, 0x000604, 0x000606, 0x00061c, 0x00061e, 0x0006dc, 0x0006de, 0x0006ff, 0x000750, 0x00077f, 0x0008a0, 0x0008b4, 0x0008b6, 0x0008c7, 0x0008d3, - 0x0008e1, 0x0008e3, 0x0008ff, 0x00fb50, 0x00fbc1, 0x00fbd3, 0x00fd3d, 0x00fd50, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdf0, 0x00fdfd, 0x00fe70, 0x00fe74, 0x00fe76, - 0x00fefc, 0x0102e0, 0x0102fb, 0x010e60, 0x010e7e, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, - 0x01ee32, 0x01ee34, 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, - 0x01ee4f, 0x01ee51, 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, - 0x01ee62, 0x01ee64, 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, - 0x01ee9b, 0x01eea1, 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x01eef0, 0x01eef1)); + CodePointSet.createNoDedup(0x000600, 0x000604, 0x000606, 0x0006dc, 0x0006de, 0x0006ff, 0x000750, 0x00077f, 0x000870, 0x00088e, 0x000890, 0x000891, 0x000898, 0x0008e1, 0x0008e3, + 0x0008ff, 0x00fb50, 0x00fbc2, 0x00fbd3, 0x00fd8f, 0x00fd92, 0x00fdc7, 0x00fdcf, 0x00fdcf, 0x00fdf0, 0x00fdff, 0x00fe70, 0x00fe74, 0x00fe76, 0x00fefc, 0x0102e0, + 0x0102fb, 0x010e60, 0x010e7e, 0x01ee00, 0x01ee03, 0x01ee05, 0x01ee1f, 0x01ee21, 0x01ee22, 0x01ee24, 0x01ee24, 0x01ee27, 0x01ee27, 0x01ee29, 0x01ee32, 0x01ee34, + 0x01ee37, 0x01ee39, 0x01ee39, 0x01ee3b, 0x01ee3b, 0x01ee42, 0x01ee42, 0x01ee47, 0x01ee47, 0x01ee49, 0x01ee49, 0x01ee4b, 0x01ee4b, 0x01ee4d, 0x01ee4f, 0x01ee51, + 0x01ee52, 0x01ee54, 0x01ee54, 0x01ee57, 0x01ee57, 0x01ee59, 0x01ee59, 0x01ee5b, 0x01ee5b, 0x01ee5d, 0x01ee5d, 0x01ee5f, 0x01ee5f, 0x01ee61, 0x01ee62, 0x01ee64, + 0x01ee64, 0x01ee67, 0x01ee6a, 0x01ee6c, 0x01ee72, 0x01ee74, 0x01ee77, 0x01ee79, 0x01ee7c, 0x01ee7e, 0x01ee7e, 0x01ee80, 0x01ee89, 0x01ee8b, 0x01ee9b, 0x01eea1, + 0x01eea3, 0x01eea5, 0x01eea9, 0x01eeab, 0x01eebb, 0x01eef0, 0x01eef1)); } private static void populateSCX_ARMI() { @@ -3936,7 +4028,7 @@ private static void populateSCX_AVST() { } private static void populateSCX_BALI() { - SET_ENCODINGS.put("scx=Bali", CodePointSet.createNoDedup(0x001b00, 0x001b4b, 0x001b50, 0x001b7c)); + SET_ENCODINGS.put("scx=Bali", CodePointSet.createNoDedup(0x001b00, 0x001b4c, 0x001b50, 0x001b7e)); } private static void populateSCX_BAMU() { @@ -3969,7 +4061,7 @@ private static void populateSCX_BOPO() { } private static void populateSCX_BRAH() { - SET_ENCODINGS.put("scx=Brah", CodePointSet.createNoDedup(0x011000, 0x01104d, 0x011052, 0x01106f, 0x01107f, 0x01107f)); + SET_ENCODINGS.put("scx=Brah", CodePointSet.createNoDedup(0x011000, 0x01104d, 0x011052, 0x011075, 0x01107f, 0x01107f)); } private static void populateSCX_BRAI() { @@ -3989,7 +4081,7 @@ private static void populateSCX_CAKM() { } private static void populateSCX_CANS() { - SET_ENCODINGS.put("scx=Cans", CodePointSet.createNoDedup(0x001400, 0x00167f, 0x0018b0, 0x0018f5)); + SET_ENCODINGS.put("scx=Cans", CodePointSet.createNoDedup(0x001400, 0x00167f, 0x0018b0, 0x0018f5, 0x011ab0, 0x011abf)); } private static void populateSCX_CARI() { @@ -4012,6 +4104,10 @@ private static void populateSCX_COPT() { SET_ENCODINGS.put("scx=Copt", CodePointSet.createNoDedup(0x0003e2, 0x0003ef, 0x002c80, 0x002cf3, 0x002cf9, 0x002cff, 0x0102e0, 0x0102fb)); } + private static void populateSCX_CPMN() { + SET_ENCODINGS.put("scx=Cpmn", CodePointSet.createNoDedup(0x010100, 0x010101, 0x012f90, 0x012ff2)); + } + private static void populateSCX_CPRT() { SET_ENCODINGS.put("scx=Cprt", CodePointSet.createNoDedup(0x010100, 0x010102, 0x010107, 0x010133, 0x010137, 0x01013f, 0x010800, 0x010805, 0x010808, 0x010808, 0x01080a, 0x010835, 0x010837, 0x010838, 0x01083c, 0x01083c, 0x01083f, 0x01083f)); @@ -4057,10 +4153,12 @@ private static void populateSCX_ELYM() { } private static void populateSCX_ETHI() { - SET_ENCODINGS.put("scx=Ethi", CodePointSet.createNoDedup(0x001200, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, - 0x00128d, 0x001290, 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, - 0x001318, 0x00135a, 0x00135d, 0x00137c, 0x001380, 0x001399, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, - 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, 0x00ab2e)); + SET_ENCODINGS.put("scx=Ethi", + CodePointSet.createNoDedup(0x001200, 0x001248, 0x00124a, 0x00124d, 0x001250, 0x001256, 0x001258, 0x001258, 0x00125a, 0x00125d, 0x001260, 0x001288, 0x00128a, 0x00128d, 0x001290, + 0x0012b0, 0x0012b2, 0x0012b5, 0x0012b8, 0x0012be, 0x0012c0, 0x0012c0, 0x0012c2, 0x0012c5, 0x0012c8, 0x0012d6, 0x0012d8, 0x001310, 0x001312, 0x001315, 0x001318, + 0x00135a, 0x00135d, 0x00137c, 0x001380, 0x001399, 0x002d80, 0x002d96, 0x002da0, 0x002da6, 0x002da8, 0x002dae, 0x002db0, 0x002db6, 0x002db8, 0x002dbe, 0x002dc0, + 0x002dc6, 0x002dc8, 0x002dce, 0x002dd0, 0x002dd6, 0x002dd8, 0x002dde, 0x00ab01, 0x00ab06, 0x00ab09, 0x00ab0e, 0x00ab11, 0x00ab16, 0x00ab20, 0x00ab26, 0x00ab28, + 0x00ab2e, 0x01e7e0, 0x01e7e6, 0x01e7e8, 0x01e7eb, 0x01e7ed, 0x01e7ee, 0x01e7f0, 0x01e7fe)); } private static void populateSCX_GEOR() { @@ -4069,8 +4167,8 @@ private static void populateSCX_GEOR() { } private static void populateSCX_GLAG() { - SET_ENCODINGS.put("scx=Glag", CodePointSet.createNoDedup(0x000484, 0x000484, 0x000487, 0x000487, 0x002c00, 0x002c2e, 0x002c30, 0x002c5e, 0x002e43, 0x002e43, 0x00a66f, 0x00a66f, 0x01e000, - 0x01e006, 0x01e008, 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a)); + SET_ENCODINGS.put("scx=Glag", CodePointSet.createNoDedup(0x000484, 0x000484, 0x000487, 0x000487, 0x002c00, 0x002c5f, 0x002e43, 0x002e43, 0x00a66f, 0x00a66f, 0x01e000, 0x01e006, 0x01e008, + 0x01e018, 0x01e01b, 0x01e021, 0x01e023, 0x01e024, 0x01e026, 0x01e02a)); } private static void populateSCX_GONG() { @@ -4129,9 +4227,9 @@ private static void populateSCX_HANI() { SET_ENCODINGS.put("scx=Hani", CodePointSet.createNoDedup(0x002e80, 0x002e99, 0x002e9b, 0x002ef3, 0x002f00, 0x002fd5, 0x003001, 0x003003, 0x003005, 0x003011, 0x003013, 0x00301f, 0x003021, 0x00302d, 0x003030, 0x003030, 0x003037, 0x00303f, 0x0030fb, 0x0030fb, 0x003190, 0x00319f, 0x0031c0, 0x0031e3, 0x003220, 0x003247, 0x003280, 0x0032b0, 0x0032c0, 0x0032cb, 0x0032ff, - 0x0032ff, 0x003358, 0x003370, 0x00337b, 0x00337f, 0x0033e0, 0x0033fe, 0x003400, 0x004dbf, 0x004e00, 0x009ffc, 0x00a700, 0x00a707, 0x00f900, 0x00fa6d, 0x00fa70, - 0x00fad9, 0x00fe45, 0x00fe46, 0x00ff61, 0x00ff65, 0x016ff0, 0x016ff1, 0x01d360, 0x01d371, 0x01f250, 0x01f251, 0x020000, 0x02a6dd, 0x02a700, 0x02b734, 0x02b740, - 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); + 0x0032ff, 0x003358, 0x003370, 0x00337b, 0x00337f, 0x0033e0, 0x0033fe, 0x003400, 0x004dbf, 0x004e00, 0x009fff, 0x00a700, 0x00a707, 0x00f900, 0x00fa6d, 0x00fa70, + 0x00fad9, 0x00fe45, 0x00fe46, 0x00ff61, 0x00ff65, 0x016fe2, 0x016fe3, 0x016ff0, 0x016ff1, 0x01d360, 0x01d371, 0x01f250, 0x01f251, 0x020000, 0x02a6df, 0x02a700, + 0x02b738, 0x02b740, 0x02b81d, 0x02b820, 0x02cea1, 0x02ceb0, 0x02ebe0, 0x02f800, 0x02fa1d, 0x030000, 0x03134a)); } private static void populateSCX_HANO() { @@ -4150,7 +4248,7 @@ private static void populateSCX_HEBR() { private static void populateSCX_HIRA() { SET_ENCODINGS.put("scx=Hira", CodePointSet.createNoDedup(0x003001, 0x003003, 0x003008, 0x003011, 0x003013, 0x00301f, 0x003030, 0x003035, 0x003037, 0x003037, 0x00303c, 0x00303d, 0x003041, 0x003096, 0x003099, - 0x0030a0, 0x0030fb, 0x0030fc, 0x00fe45, 0x00fe46, 0x00ff61, 0x00ff65, 0x00ff70, 0x00ff70, 0x00ff9e, 0x00ff9f, 0x01b001, 0x01b11e, 0x01b150, 0x01b152, 0x01f200, + 0x0030a0, 0x0030fb, 0x0030fc, 0x00fe45, 0x00fe46, 0x00ff61, 0x00ff65, 0x00ff70, 0x00ff70, 0x00ff9e, 0x00ff9f, 0x01b001, 0x01b11f, 0x01b150, 0x01b152, 0x01f200, 0x01f200)); } @@ -4183,8 +4281,10 @@ private static void populateSCX_KALI() { } private static void populateSCX_KANA() { - SET_ENCODINGS.put("scx=Kana", CodePointSet.createNoDedup(0x003001, 0x003003, 0x003008, 0x003011, 0x003013, 0x00301f, 0x003030, 0x003035, 0x003037, 0x003037, 0x00303c, 0x00303d, 0x003099, - 0x00309c, 0x0030a0, 0x0030ff, 0x0031f0, 0x0031ff, 0x0032d0, 0x0032fe, 0x003300, 0x003357, 0x00fe45, 0x00fe46, 0x00ff61, 0x00ff9f, 0x01b000, 0x01b000, 0x01b164, 0x01b167)); + SET_ENCODINGS.put("scx=Kana", + CodePointSet.createNoDedup(0x003001, 0x003003, 0x003008, 0x003011, 0x003013, 0x00301f, 0x003030, 0x003035, 0x003037, 0x003037, 0x00303c, 0x00303d, 0x003099, 0x00309c, 0x0030a0, + 0x0030ff, 0x0031f0, 0x0031ff, 0x0032d0, 0x0032fe, 0x003300, 0x003357, 0x00fe45, 0x00fe46, 0x00ff61, 0x00ff9f, 0x01aff0, 0x01aff3, 0x01aff5, 0x01affb, 0x01affd, + 0x01affe, 0x01b000, 0x01b000, 0x01b120, 0x01b122, 0x01b164, 0x01b167)); } private static void populateSCX_KHAR() { @@ -4207,12 +4307,12 @@ private static void populateSCX_KITS() { private static void populateSCX_KNDA() { SET_ENCODINGS.put("scx=Knda", CodePointSet.createNoDedup(0x000951, 0x000952, 0x000964, 0x000965, 0x000c80, 0x000c8c, 0x000c8e, 0x000c90, 0x000c92, 0x000ca8, 0x000caa, 0x000cb3, 0x000cb5, 0x000cb9, 0x000cbc, - 0x000cc4, 0x000cc6, 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000cde, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x001cd0, + 0x000cc4, 0x000cc6, 0x000cc8, 0x000cca, 0x000ccd, 0x000cd5, 0x000cd6, 0x000cdd, 0x000cde, 0x000ce0, 0x000ce3, 0x000ce6, 0x000cef, 0x000cf1, 0x000cf2, 0x001cd0, 0x001cd0, 0x001cd2, 0x001cd2, 0x001cda, 0x001cda, 0x001cf2, 0x001cf2, 0x001cf4, 0x001cf4, 0x00a830, 0x00a835)); } private static void populateSCX_KTHI() { - SET_ENCODINGS.put("scx=Kthi", CodePointSet.createNoDedup(0x000966, 0x00096f, 0x00a830, 0x00a839, 0x011080, 0x0110c1, 0x0110cd, 0x0110cd)); + SET_ENCODINGS.put("scx=Kthi", CodePointSet.createNoDedup(0x000966, 0x00096f, 0x00a830, 0x00a839, 0x011080, 0x0110c2, 0x0110cd, 0x0110cd)); } private static void populateSCX_LANA() { @@ -4225,11 +4325,13 @@ private static void populateSCX_LAOO() { } private static void populateSCX_LATN() { - SET_ENCODINGS.put("scx=Latn", CodePointSet.createNoDedup(0x000041, 0x00005a, 0x000061, 0x00007a, 0x0000aa, 0x0000aa, 0x0000ba, 0x0000ba, 0x0000c0, 0x0000d6, 0x0000d8, 0x0000f6, 0x0000f8, - 0x0002b8, 0x0002e0, 0x0002e4, 0x000363, 0x00036f, 0x000485, 0x000486, 0x000951, 0x000952, 0x0010fb, 0x0010fb, 0x001d00, 0x001d25, 0x001d2c, 0x001d5c, 0x001d62, 0x001d65, - 0x001d6b, 0x001d77, 0x001d79, 0x001dbe, 0x001e00, 0x001eff, 0x00202f, 0x00202f, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x0020f0, 0x0020f0, 0x00212a, - 0x00212b, 0x002132, 0x002132, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c60, 0x002c7f, 0x00a700, 0x00a707, 0x00a722, 0x00a787, 0x00a78b, 0x00a7bf, 0x00a7c2, 0x00a7ca, - 0x00a7f5, 0x00a7ff, 0x00a92e, 0x00a92e, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab64, 0x00ab66, 0x00ab69, 0x00fb00, 0x00fb06, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a)); + SET_ENCODINGS.put("scx=Latn", + CodePointSet.createNoDedup(0x000041, 0x00005a, 0x000061, 0x00007a, 0x0000aa, 0x0000aa, 0x0000ba, 0x0000ba, 0x0000c0, 0x0000d6, 0x0000d8, 0x0000f6, 0x0000f8, 0x0002b8, 0x0002e0, + 0x0002e4, 0x000363, 0x00036f, 0x000485, 0x000486, 0x000951, 0x000952, 0x0010fb, 0x0010fb, 0x001d00, 0x001d25, 0x001d2c, 0x001d5c, 0x001d62, 0x001d65, 0x001d6b, + 0x001d77, 0x001d79, 0x001dbe, 0x001e00, 0x001eff, 0x00202f, 0x00202f, 0x002071, 0x002071, 0x00207f, 0x00207f, 0x002090, 0x00209c, 0x0020f0, 0x0020f0, 0x00212a, + 0x00212b, 0x002132, 0x002132, 0x00214e, 0x00214e, 0x002160, 0x002188, 0x002c60, 0x002c7f, 0x00a700, 0x00a707, 0x00a722, 0x00a787, 0x00a78b, 0x00a7ca, 0x00a7d0, + 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, 0x00a7f2, 0x00a7ff, 0x00a92e, 0x00a92e, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab64, 0x00ab66, 0x00ab69, 0x00fb00, + 0x00fb06, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, 0x010780, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x01df00, 0x01df1e)); } private static void populateSCX_LEPC() { @@ -4307,7 +4409,7 @@ private static void populateSCX_MODI() { } private static void populateSCX_MONG() { - SET_ENCODINGS.put("scx=Mong", CodePointSet.createNoDedup(0x001800, 0x00180e, 0x001810, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x00202f, 0x00202f, 0x011660, 0x01166c)); + SET_ENCODINGS.put("scx=Mong", CodePointSet.createNoDedup(0x001800, 0x001819, 0x001820, 0x001878, 0x001880, 0x0018aa, 0x00202f, 0x00202f, 0x011660, 0x01166c)); } private static void populateSCX_MROO() { @@ -4344,7 +4446,7 @@ private static void populateSCX_NEWA() { } private static void populateSCX_NKOO() { - SET_ENCODINGS.put("scx=Nkoo", CodePointSet.createNoDedup(0x0007c0, 0x0007fa, 0x0007fd, 0x0007ff)); + SET_ENCODINGS.put("scx=Nkoo", CodePointSet.createNoDedup(0x00060c, 0x00060c, 0x00061b, 0x00061b, 0x00061f, 0x00061f, 0x0007c0, 0x0007fa, 0x0007fd, 0x0007ff, 0x00fd3e, 0x00fd3f)); } private static void populateSCX_NSHU() { @@ -4378,6 +4480,10 @@ private static void populateSCX_OSMA() { SET_ENCODINGS.put("scx=Osma", CodePointSet.createNoDedup(0x010480, 0x01049d, 0x0104a0, 0x0104a9)); } + private static void populateSCX_OUGR() { + SET_ENCODINGS.put("scx=Ougr", CodePointSet.createNoDedup(0x000640, 0x000640, 0x010af2, 0x010af2, 0x010f70, 0x010f89)); + } + private static void populateSCX_PALM() { SET_ENCODINGS.put("scx=Palm", CodePointSet.createNoDedup(0x010860, 0x01087f)); } @@ -4490,7 +4596,7 @@ private static void populateSCX_SYLO() { private static void populateSCX_SYRC() { SET_ENCODINGS.put("scx=Syrc", CodePointSet.createNoDedup(0x00060c, 0x00060c, 0x00061b, 0x00061c, 0x00061f, 0x00061f, 0x000640, 0x000640, 0x00064b, 0x000655, 0x000670, 0x000670, 0x000700, - 0x00070d, 0x00070f, 0x00074a, 0x00074d, 0x00074f, 0x000860, 0x00086a, 0x001df8, 0x001df8)); + 0x00070d, 0x00070f, 0x00074a, 0x00074d, 0x00074f, 0x000860, 0x00086a, 0x001df8, 0x001df8, 0x001dfa, 0x001dfa)); } private static void populateSCX_TAGB() { @@ -4498,7 +4604,7 @@ private static void populateSCX_TAGB() { } private static void populateSCX_TAKR() { - SET_ENCODINGS.put("scx=Takr", CodePointSet.createNoDedup(0x000964, 0x000965, 0x00a830, 0x00a839, 0x011680, 0x0116b8, 0x0116c0, 0x0116c9)); + SET_ENCODINGS.put("scx=Takr", CodePointSet.createNoDedup(0x000964, 0x000965, 0x00a830, 0x00a839, 0x011680, 0x0116b9, 0x0116c0, 0x0116c9)); } private static void populateSCX_TALE() { @@ -4527,9 +4633,9 @@ private static void populateSCX_TAVT() { private static void populateSCX_TELU() { SET_ENCODINGS.put("scx=Telu", - CodePointSet.createNoDedup(0x000951, 0x000952, 0x000964, 0x000965, 0x000c00, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3d, 0x000c44, 0x000c46, - 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c60, 0x000c63, 0x000c66, 0x000c6f, 0x000c77, 0x000c7f, 0x001cda, 0x001cda, 0x001cf2, - 0x001cf2)); + CodePointSet.createNoDedup(0x000951, 0x000952, 0x000964, 0x000965, 0x000c00, 0x000c0c, 0x000c0e, 0x000c10, 0x000c12, 0x000c28, 0x000c2a, 0x000c39, 0x000c3c, 0x000c44, 0x000c46, + 0x000c48, 0x000c4a, 0x000c4d, 0x000c55, 0x000c56, 0x000c58, 0x000c5a, 0x000c5d, 0x000c5d, 0x000c60, 0x000c63, 0x000c66, 0x000c6f, 0x000c77, 0x000c7f, 0x001cda, + 0x001cda, 0x001cf2, 0x001cf2)); } private static void populateSCX_TFNG() { @@ -4537,7 +4643,7 @@ private static void populateSCX_TFNG() { } private static void populateSCX_TGLG() { - SET_ENCODINGS.put("scx=Tglg", CodePointSet.createNoDedup(0x001700, 0x00170c, 0x00170e, 0x001714, 0x001735, 0x001736)); + SET_ENCODINGS.put("scx=Tglg", CodePointSet.createNoDedup(0x001700, 0x001715, 0x00171f, 0x00171f, 0x001735, 0x001736)); } private static void populateSCX_THAA() { @@ -4558,6 +4664,14 @@ private static void populateSCX_TIRH() { SET_ENCODINGS.put("scx=Tirh", CodePointSet.createNoDedup(0x000951, 0x000952, 0x000964, 0x000965, 0x001cf2, 0x001cf2, 0x00a830, 0x00a839, 0x011480, 0x0114c7, 0x0114d0, 0x0114d9)); } + private static void populateSCX_TNSA() { + SET_ENCODINGS.put("scx=Tnsa", CodePointSet.createNoDedup(0x016a70, 0x016abe, 0x016ac0, 0x016ac9)); + } + + private static void populateSCX_TOTO() { + SET_ENCODINGS.put("scx=Toto", CodePointSet.createNoDedup(0x01e290, 0x01e2ae)); + } + private static void populateSCX_UGAR() { SET_ENCODINGS.put("scx=Ugar", CodePointSet.createNoDedup(0x010380, 0x01039d, 0x01039f, 0x01039f)); } @@ -4566,6 +4680,11 @@ private static void populateSCX_VAII() { SET_ENCODINGS.put("scx=Vaii", CodePointSet.createNoDedup(0x00a500, 0x00a62b)); } + private static void populateSCX_VITH() { + SET_ENCODINGS.put("scx=Vith", CodePointSet.createNoDedup(0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, 0x0105b1, 0x0105b3, + 0x0105b9, 0x0105bb, 0x0105bc)); + } + private static void populateSCX_WARA() { SET_ENCODINGS.put("scx=Wara", CodePointSet.createNoDedup(0x0118a0, 0x0118f2, 0x0118ff, 0x0118ff)); } @@ -4598,48 +4717,48 @@ private static void populateSCX_ZANB() { private static void populateSCX_ZINH() { SET_ENCODINGS.put("scx=Zinh", - CodePointSet.createNoDedup(0x000300, 0x000341, 0x000343, 0x000344, 0x000346, 0x000362, 0x000953, 0x000954, 0x001ab0, 0x001ac0, 0x001dc2, 0x001df7, 0x001df9, 0x001df9, 0x001dfb, - 0x001dff, 0x00200c, 0x00200d, 0x0020d0, 0x0020ef, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2d, 0x0101fd, 0x0101fd, 0x01d167, 0x01d169, 0x01d17b, 0x01d182, 0x01d185, - 0x01d18b, 0x01d1aa, 0x01d1ad, 0x0e0100, 0x0e01ef)); + CodePointSet.createNoDedup(0x000300, 0x000341, 0x000343, 0x000344, 0x000346, 0x000362, 0x000953, 0x000954, 0x001ab0, 0x001ace, 0x001dc2, 0x001df7, 0x001df9, 0x001df9, 0x001dfb, + 0x001dff, 0x00200c, 0x00200d, 0x0020d0, 0x0020ef, 0x00fe00, 0x00fe0f, 0x00fe20, 0x00fe2d, 0x0101fd, 0x0101fd, 0x01cf00, 0x01cf2d, 0x01cf30, 0x01cf46, 0x01d167, + 0x01d169, 0x01d17b, 0x01d182, 0x01d185, 0x01d18b, 0x01d1aa, 0x01d1ad, 0x0e0100, 0x0e01ef)); } private static void populateSCX_ZYYY() { SET_ENCODINGS.put("scx=Zyyy", CodePointSet.createNoDedup(0x000000, 0x000040, 0x00005b, 0x000060, 0x00007b, 0x0000a9, 0x0000ab, 0x0000b9, 0x0000bb, 0x0000bf, 0x0000d7, 0x0000d7, 0x0000f7, 0x0000f7, 0x0002b9, 0x0002df, 0x0002e5, 0x0002e9, 0x0002ec, 0x0002ff, 0x000374, 0x000374, 0x00037e, 0x00037e, 0x000385, 0x000385, 0x000387, 0x000387, 0x000605, 0x000605, 0x0006dd, 0x0006dd, 0x0008e2, 0x0008e2, 0x000e3f, 0x000e3f, 0x000fd5, 0x000fd8, 0x0016eb, 0x0016ed, 0x002000, 0x00200b, 0x00200e, 0x00202e, 0x002030, 0x002064, 0x002066, - 0x002070, 0x002074, 0x00207e, 0x002080, 0x00208e, 0x0020a0, 0x0020bf, 0x002100, 0x002125, 0x002127, 0x002129, 0x00212c, 0x002131, 0x002133, 0x00214d, 0x00214f, 0x00215f, + 0x002070, 0x002074, 0x00207e, 0x002080, 0x00208e, 0x0020a0, 0x0020c0, 0x002100, 0x002125, 0x002127, 0x002129, 0x00212c, 0x002131, 0x002133, 0x00214d, 0x00214f, 0x00215f, 0x002189, 0x00218b, 0x002190, 0x002426, 0x002440, 0x00244a, 0x002460, 0x0027ff, 0x002900, 0x002b73, 0x002b76, 0x002b95, 0x002b97, 0x002bff, 0x002e00, 0x002e42, 0x002e44, - 0x002e52, 0x002ff0, 0x002ffb, 0x003000, 0x003000, 0x003004, 0x003004, 0x003012, 0x003012, 0x003020, 0x003020, 0x003036, 0x003036, 0x003248, 0x00325f, 0x00327f, 0x00327f, + 0x002e5d, 0x002ff0, 0x002ffb, 0x003000, 0x003000, 0x003004, 0x003004, 0x003012, 0x003012, 0x003020, 0x003020, 0x003036, 0x003036, 0x003248, 0x00325f, 0x00327f, 0x00327f, 0x0032b1, 0x0032bf, 0x0032cc, 0x0032cf, 0x003371, 0x00337a, 0x003380, 0x0033df, 0x0033ff, 0x0033ff, 0x004dc0, 0x004dff, 0x00a708, 0x00a721, 0x00a788, 0x00a78a, 0x00ab5b, - 0x00ab5b, 0x00ab6a, 0x00ab6b, 0x00fd3e, 0x00fd3f, 0x00fe10, 0x00fe19, 0x00fe30, 0x00fe44, 0x00fe47, 0x00fe52, 0x00fe54, 0x00fe66, 0x00fe68, 0x00fe6b, 0x00feff, 0x00feff, - 0x00ff01, 0x00ff20, 0x00ff3b, 0x00ff40, 0x00ff5b, 0x00ff60, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, 0x00fff9, 0x00fffd, 0x010190, 0x01019c, 0x0101d0, 0x0101fc, 0x016fe2, - 0x016fe3, 0x01d000, 0x01d0f5, 0x01d100, 0x01d126, 0x01d129, 0x01d166, 0x01d16a, 0x01d17a, 0x01d183, 0x01d184, 0x01d18c, 0x01d1a9, 0x01d1ae, 0x01d1e8, 0x01d2e0, 0x01d2f3, - 0x01d300, 0x01d356, 0x01d372, 0x01d378, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, - 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, - 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d7cb, 0x01d7ce, 0x01d7ff, 0x01ec71, 0x01ecb4, 0x01ed01, 0x01ed3d, 0x01f000, - 0x01f02b, 0x01f030, 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, 0x01f100, 0x01f1ad, 0x01f1e6, 0x01f1ff, 0x01f201, 0x01f202, - 0x01f210, 0x01f23b, 0x01f240, 0x01f248, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6e0, 0x01f6ec, 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, 0x01f7e0, - 0x01f7eb, 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01f978, 0x01f97a, 0x01f9cb, - 0x01f9cd, 0x01fa53, 0x01fa60, 0x01fa6d, 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7a, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faa8, 0x01fab0, 0x01fab6, 0x01fac0, 0x01fac2, 0x01fad0, - 0x01fad6, 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca, 0x01fbf0, 0x01fbf9, 0x0e0001, 0x0e0001, 0x0e0020, 0x0e007f)); + 0x00ab5b, 0x00ab6a, 0x00ab6b, 0x00fe10, 0x00fe19, 0x00fe30, 0x00fe44, 0x00fe47, 0x00fe52, 0x00fe54, 0x00fe66, 0x00fe68, 0x00fe6b, 0x00feff, 0x00feff, 0x00ff01, 0x00ff20, + 0x00ff3b, 0x00ff40, 0x00ff5b, 0x00ff60, 0x00ffe0, 0x00ffe6, 0x00ffe8, 0x00ffee, 0x00fff9, 0x00fffd, 0x010190, 0x01019c, 0x0101d0, 0x0101fc, 0x01cf50, 0x01cfc3, 0x01d000, + 0x01d0f5, 0x01d100, 0x01d126, 0x01d129, 0x01d166, 0x01d16a, 0x01d17a, 0x01d183, 0x01d184, 0x01d18c, 0x01d1a9, 0x01d1ae, 0x01d1ea, 0x01d2e0, 0x01d2f3, 0x01d300, 0x01d356, + 0x01d372, 0x01d378, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, + 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, + 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d7cb, 0x01d7ce, 0x01d7ff, 0x01ec71, 0x01ecb4, 0x01ed01, 0x01ed3d, 0x01f000, 0x01f02b, 0x01f030, + 0x01f093, 0x01f0a0, 0x01f0ae, 0x01f0b1, 0x01f0bf, 0x01f0c1, 0x01f0cf, 0x01f0d1, 0x01f0f5, 0x01f100, 0x01f1ad, 0x01f1e6, 0x01f1ff, 0x01f201, 0x01f202, 0x01f210, 0x01f23b, + 0x01f240, 0x01f248, 0x01f260, 0x01f265, 0x01f300, 0x01f6d7, 0x01f6dd, 0x01f6ec, 0x01f6f0, 0x01f6fc, 0x01f700, 0x01f773, 0x01f780, 0x01f7d8, 0x01f7e0, 0x01f7eb, 0x01f7f0, + 0x01f7f0, 0x01f800, 0x01f80b, 0x01f810, 0x01f847, 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, 0x01f8b0, 0x01f8b1, 0x01f900, 0x01fa53, 0x01fa60, 0x01fa6d, + 0x01fa70, 0x01fa74, 0x01fa78, 0x01fa7c, 0x01fa80, 0x01fa86, 0x01fa90, 0x01faac, 0x01fab0, 0x01faba, 0x01fac0, 0x01fac5, 0x01fad0, 0x01fad9, 0x01fae0, 0x01fae7, 0x01faf0, + 0x01faf6, 0x01fb00, 0x01fb92, 0x01fb94, 0x01fbca, 0x01fbf0, 0x01fbf9, 0x0e0001, 0x0e0001, 0x0e0020, 0x0e007f)); } private static void populateSCX_ZZZZ() { SET_ENCODINGS.put("scx=Zzzz", CodePointSet.createNoDedup(0x000378, 0x000379, 0x000380, 0x000383, 0x00038b, 0x00038b, 0x00038d, 0x00038d, 0x0003a2, 0x0003a2, 0x000530, 0x000530, 0x000557, - 0x000558, 0x00058b, 0x00058c, 0x000590, 0x000590, 0x0005c8, 0x0005cf, 0x0005eb, 0x0005ee, 0x0005f5, 0x0005ff, 0x00061d, 0x00061d, 0x00070e, 0x00070e, 0x00074b, 0x00074c, - 0x0007b2, 0x0007bf, 0x0007fb, 0x0007fc, 0x00082e, 0x00082f, 0x00083f, 0x00083f, 0x00085c, 0x00085d, 0x00085f, 0x00085f, 0x00086b, 0x00089f, 0x0008b5, 0x0008b5, 0x0008c8, - 0x0008d2, 0x000984, 0x000984, 0x00098d, 0x00098e, 0x000991, 0x000992, 0x0009a9, 0x0009a9, 0x0009b1, 0x0009b1, 0x0009b3, 0x0009b5, 0x0009ba, 0x0009bb, 0x0009c5, 0x0009c6, - 0x0009c9, 0x0009ca, 0x0009cf, 0x0009d6, 0x0009d8, 0x0009db, 0x0009de, 0x0009de, 0x0009e4, 0x0009e5, 0x0009ff, 0x000a00, 0x000a04, 0x000a04, 0x000a0b, 0x000a0e, 0x000a11, - 0x000a12, 0x000a29, 0x000a29, 0x000a31, 0x000a31, 0x000a34, 0x000a34, 0x000a37, 0x000a37, 0x000a3a, 0x000a3b, 0x000a3d, 0x000a3d, 0x000a43, 0x000a46, 0x000a49, 0x000a4a, - 0x000a4e, 0x000a50, 0x000a52, 0x000a58, 0x000a5d, 0x000a5d, 0x000a5f, 0x000a65, 0x000a77, 0x000a80, 0x000a84, 0x000a84, 0x000a8e, 0x000a8e, 0x000a92, 0x000a92, 0x000aa9, - 0x000aa9, 0x000ab1, 0x000ab1, 0x000ab4, 0x000ab4, 0x000aba, 0x000abb, 0x000ac6, 0x000ac6, 0x000aca, 0x000aca, 0x000ace, 0x000acf, 0x000ad1, 0x000adf, 0x000ae4, 0x000ae5, - 0x000af2, 0x000af8, 0x000b00, 0x000b00, 0x000b04, 0x000b04, 0x000b0d, 0x000b0e, 0x000b11, 0x000b12, 0x000b29, 0x000b29, 0x000b31, 0x000b31, 0x000b34, 0x000b34, 0x000b3a, - 0x000b3b, 0x000b45, 0x000b46, 0x000b49, 0x000b4a, 0x000b4e, 0x000b54, 0x000b58, 0x000b5b, 0x000b5e, 0x000b5e, 0x000b64, 0x000b65, 0x000b78, 0x000b81, 0x000b84, 0x000b84, - 0x000b8b, 0x000b8d, 0x000b91, 0x000b91, 0x000b96, 0x000b98, 0x000b9b, 0x000b9b, 0x000b9d, 0x000b9d, 0x000ba0, 0x000ba2, 0x000ba5, 0x000ba7, 0x000bab, 0x000bad, 0x000bba, - 0x000bbd, 0x000bc3, 0x000bc5, 0x000bc9, 0x000bc9, 0x000bce, 0x000bcf, 0x000bd1, 0x000bd6, 0x000bd8, 0x000be5, 0x000bfb, 0x000bff, 0x000c0d, 0x000c0d, 0x000c11, 0x000c11, - 0x000c29, 0x000c29, 0x000c3a, 0x000c3c, 0x000c45, 0x000c45, 0x000c49, 0x000c49, 0x000c4e, 0x000c54, 0x000c57, 0x000c57, 0x000c5b, 0x000c5f, 0x000c64, 0x000c65, 0x000c70, + 0x000558, 0x00058b, 0x00058c, 0x000590, 0x000590, 0x0005c8, 0x0005cf, 0x0005eb, 0x0005ee, 0x0005f5, 0x0005ff, 0x00070e, 0x00070e, 0x00074b, 0x00074c, 0x0007b2, 0x0007bf, + 0x0007fb, 0x0007fc, 0x00082e, 0x00082f, 0x00083f, 0x00083f, 0x00085c, 0x00085d, 0x00085f, 0x00085f, 0x00086b, 0x00086f, 0x00088f, 0x00088f, 0x000892, 0x000897, 0x000984, + 0x000984, 0x00098d, 0x00098e, 0x000991, 0x000992, 0x0009a9, 0x0009a9, 0x0009b1, 0x0009b1, 0x0009b3, 0x0009b5, 0x0009ba, 0x0009bb, 0x0009c5, 0x0009c6, 0x0009c9, 0x0009ca, + 0x0009cf, 0x0009d6, 0x0009d8, 0x0009db, 0x0009de, 0x0009de, 0x0009e4, 0x0009e5, 0x0009ff, 0x000a00, 0x000a04, 0x000a04, 0x000a0b, 0x000a0e, 0x000a11, 0x000a12, 0x000a29, + 0x000a29, 0x000a31, 0x000a31, 0x000a34, 0x000a34, 0x000a37, 0x000a37, 0x000a3a, 0x000a3b, 0x000a3d, 0x000a3d, 0x000a43, 0x000a46, 0x000a49, 0x000a4a, 0x000a4e, 0x000a50, + 0x000a52, 0x000a58, 0x000a5d, 0x000a5d, 0x000a5f, 0x000a65, 0x000a77, 0x000a80, 0x000a84, 0x000a84, 0x000a8e, 0x000a8e, 0x000a92, 0x000a92, 0x000aa9, 0x000aa9, 0x000ab1, + 0x000ab1, 0x000ab4, 0x000ab4, 0x000aba, 0x000abb, 0x000ac6, 0x000ac6, 0x000aca, 0x000aca, 0x000ace, 0x000acf, 0x000ad1, 0x000adf, 0x000ae4, 0x000ae5, 0x000af2, 0x000af8, + 0x000b00, 0x000b00, 0x000b04, 0x000b04, 0x000b0d, 0x000b0e, 0x000b11, 0x000b12, 0x000b29, 0x000b29, 0x000b31, 0x000b31, 0x000b34, 0x000b34, 0x000b3a, 0x000b3b, 0x000b45, + 0x000b46, 0x000b49, 0x000b4a, 0x000b4e, 0x000b54, 0x000b58, 0x000b5b, 0x000b5e, 0x000b5e, 0x000b64, 0x000b65, 0x000b78, 0x000b81, 0x000b84, 0x000b84, 0x000b8b, 0x000b8d, + 0x000b91, 0x000b91, 0x000b96, 0x000b98, 0x000b9b, 0x000b9b, 0x000b9d, 0x000b9d, 0x000ba0, 0x000ba2, 0x000ba5, 0x000ba7, 0x000bab, 0x000bad, 0x000bba, 0x000bbd, 0x000bc3, + 0x000bc5, 0x000bc9, 0x000bc9, 0x000bce, 0x000bcf, 0x000bd1, 0x000bd6, 0x000bd8, 0x000be5, 0x000bfb, 0x000bff, 0x000c0d, 0x000c0d, 0x000c11, 0x000c11, 0x000c29, 0x000c29, + 0x000c3a, 0x000c3b, 0x000c45, 0x000c45, 0x000c49, 0x000c49, 0x000c4e, 0x000c54, 0x000c57, 0x000c57, 0x000c5b, 0x000c5c, 0x000c5e, 0x000c5f, 0x000c64, 0x000c65, 0x000c70, 0x000c76, 0x000c8d, 0x000c8d, 0x000c91, 0x000c91, 0x000ca9, 0x000ca9, 0x000cb4, 0x000cb4, 0x000cba, 0x000cbb, 0x000cc5, 0x000cc5, 0x000cc9, 0x000cc9, 0x000cce, 0x000cd4, - 0x000cd7, 0x000cdd, 0x000cdf, 0x000cdf, 0x000ce4, 0x000ce5, 0x000cf0, 0x000cf0, 0x000cf3, 0x000cff, 0x000d0d, 0x000d0d, 0x000d11, 0x000d11, 0x000d45, 0x000d45, 0x000d49, + 0x000cd7, 0x000cdc, 0x000cdf, 0x000cdf, 0x000ce4, 0x000ce5, 0x000cf0, 0x000cf0, 0x000cf3, 0x000cff, 0x000d0d, 0x000d0d, 0x000d11, 0x000d11, 0x000d45, 0x000d45, 0x000d49, 0x000d49, 0x000d50, 0x000d53, 0x000d64, 0x000d65, 0x000d80, 0x000d80, 0x000d84, 0x000d84, 0x000d97, 0x000d99, 0x000db2, 0x000db2, 0x000dbc, 0x000dbc, 0x000dbe, 0x000dbf, 0x000dc7, 0x000dc9, 0x000dcb, 0x000dce, 0x000dd5, 0x000dd5, 0x000dd7, 0x000dd7, 0x000de0, 0x000de5, 0x000df0, 0x000df1, 0x000df5, 0x000e00, 0x000e3b, 0x000e3e, 0x000e5c, 0x000e80, 0x000e83, 0x000e83, 0x000e85, 0x000e85, 0x000e8b, 0x000e8b, 0x000ea4, 0x000ea4, 0x000ea6, 0x000ea6, 0x000ebe, 0x000ebf, 0x000ec5, 0x000ec5, 0x000ec7, 0x000ec7, @@ -4647,63 +4766,66 @@ private static void populateSCX_ZZZZ() { 0x000fff, 0x0010c6, 0x0010c6, 0x0010c8, 0x0010cc, 0x0010ce, 0x0010cf, 0x001249, 0x001249, 0x00124e, 0x00124f, 0x001257, 0x001257, 0x001259, 0x001259, 0x00125e, 0x00125f, 0x001289, 0x001289, 0x00128e, 0x00128f, 0x0012b1, 0x0012b1, 0x0012b6, 0x0012b7, 0x0012bf, 0x0012bf, 0x0012c1, 0x0012c1, 0x0012c6, 0x0012c7, 0x0012d7, 0x0012d7, 0x001311, 0x001311, 0x001316, 0x001317, 0x00135b, 0x00135c, 0x00137d, 0x00137f, 0x00139a, 0x00139f, 0x0013f6, 0x0013f7, 0x0013fe, 0x0013ff, 0x00169d, 0x00169f, 0x0016f9, 0x0016ff, - 0x00170d, 0x00170d, 0x001715, 0x00171f, 0x001737, 0x00173f, 0x001754, 0x00175f, 0x00176d, 0x00176d, 0x001771, 0x001771, 0x001774, 0x00177f, 0x0017de, 0x0017df, 0x0017ea, - 0x0017ef, 0x0017fa, 0x0017ff, 0x00180f, 0x00180f, 0x00181a, 0x00181f, 0x001879, 0x00187f, 0x0018ab, 0x0018af, 0x0018f6, 0x0018ff, 0x00191f, 0x00191f, 0x00192c, 0x00192f, - 0x00193c, 0x00193f, 0x001941, 0x001943, 0x00196e, 0x00196f, 0x001975, 0x00197f, 0x0019ac, 0x0019af, 0x0019ca, 0x0019cf, 0x0019db, 0x0019dd, 0x001a1c, 0x001a1d, 0x001a5f, - 0x001a5f, 0x001a7d, 0x001a7e, 0x001a8a, 0x001a8f, 0x001a9a, 0x001a9f, 0x001aae, 0x001aaf, 0x001ac1, 0x001aff, 0x001b4c, 0x001b4f, 0x001b7d, 0x001b7f, 0x001bf4, 0x001bfb, - 0x001c38, 0x001c3a, 0x001c4a, 0x001c4c, 0x001c89, 0x001c8f, 0x001cbb, 0x001cbc, 0x001cc8, 0x001ccf, 0x001cfb, 0x001cff, 0x001dfa, 0x001dfa, 0x001f16, 0x001f17, 0x001f1e, - 0x001f1f, 0x001f46, 0x001f47, 0x001f4e, 0x001f4f, 0x001f58, 0x001f58, 0x001f5a, 0x001f5a, 0x001f5c, 0x001f5c, 0x001f5e, 0x001f5e, 0x001f7e, 0x001f7f, 0x001fb5, 0x001fb5, - 0x001fc5, 0x001fc5, 0x001fd4, 0x001fd5, 0x001fdc, 0x001fdc, 0x001ff0, 0x001ff1, 0x001ff5, 0x001ff5, 0x001fff, 0x001fff, 0x002065, 0x002065, 0x002072, 0x002073, 0x00208f, - 0x00208f, 0x00209d, 0x00209f, 0x0020c0, 0x0020cf, 0x0020f1, 0x0020ff, 0x00218c, 0x00218f, 0x002427, 0x00243f, 0x00244b, 0x00245f, 0x002b74, 0x002b75, 0x002b96, 0x002b96, - 0x002c2f, 0x002c2f, 0x002c5f, 0x002c5f, 0x002cf4, 0x002cf8, 0x002d26, 0x002d26, 0x002d28, 0x002d2c, 0x002d2e, 0x002d2f, 0x002d68, 0x002d6e, 0x002d71, 0x002d7e, 0x002d97, - 0x002d9f, 0x002da7, 0x002da7, 0x002daf, 0x002daf, 0x002db7, 0x002db7, 0x002dbf, 0x002dbf, 0x002dc7, 0x002dc7, 0x002dcf, 0x002dcf, 0x002dd7, 0x002dd7, 0x002ddf, 0x002ddf, - 0x002e53, 0x002e7f, 0x002e9a, 0x002e9a, 0x002ef4, 0x002eff, 0x002fd6, 0x002fef, 0x002ffc, 0x002fff, 0x003040, 0x003040, 0x003097, 0x003098, 0x003100, 0x003104, 0x003130, - 0x003130, 0x00318f, 0x00318f, 0x0031e4, 0x0031ef, 0x00321f, 0x00321f, 0x009ffd, 0x009fff, 0x00a48d, 0x00a48f, 0x00a4c7, 0x00a4cf, 0x00a62c, 0x00a63f, 0x00a6f8, 0x00a6ff, - 0x00a7c0, 0x00a7c1, 0x00a7cb, 0x00a7f4, 0x00a82d, 0x00a82f, 0x00a83a, 0x00a83f, 0x00a878, 0x00a87f, 0x00a8c6, 0x00a8cd, 0x00a8da, 0x00a8df, 0x00a954, 0x00a95e, 0x00a97d, - 0x00a97f, 0x00a9ce, 0x00a9ce, 0x00a9da, 0x00a9dd, 0x00a9ff, 0x00a9ff, 0x00aa37, 0x00aa3f, 0x00aa4e, 0x00aa4f, 0x00aa5a, 0x00aa5b, 0x00aac3, 0x00aada, 0x00aaf7, 0x00ab00, - 0x00ab07, 0x00ab08, 0x00ab0f, 0x00ab10, 0x00ab17, 0x00ab1f, 0x00ab27, 0x00ab27, 0x00ab2f, 0x00ab2f, 0x00ab6c, 0x00ab6f, 0x00abee, 0x00abef, 0x00abfa, 0x00abff, 0x00d7a4, - 0x00d7af, 0x00d7c7, 0x00d7ca, 0x00d7fc, 0x00f8ff, 0x00fa6e, 0x00fa6f, 0x00fada, 0x00faff, 0x00fb07, 0x00fb12, 0x00fb18, 0x00fb1c, 0x00fb37, 0x00fb37, 0x00fb3d, 0x00fb3d, - 0x00fb3f, 0x00fb3f, 0x00fb42, 0x00fb42, 0x00fb45, 0x00fb45, 0x00fbc2, 0x00fbd2, 0x00fd40, 0x00fd4f, 0x00fd90, 0x00fd91, 0x00fdc8, 0x00fdef, 0x00fdfe, 0x00fdff, 0x00fe1a, - 0x00fe1f, 0x00fe53, 0x00fe53, 0x00fe67, 0x00fe67, 0x00fe6c, 0x00fe6f, 0x00fe75, 0x00fe75, 0x00fefd, 0x00fefe, 0x00ff00, 0x00ff00, 0x00ffbf, 0x00ffc1, 0x00ffc8, 0x00ffc9, - 0x00ffd0, 0x00ffd1, 0x00ffd8, 0x00ffd9, 0x00ffdd, 0x00ffdf, 0x00ffe7, 0x00ffe7, 0x00ffef, 0x00fff8, 0x00fffe, 0x00ffff, 0x01000c, 0x01000c, 0x010027, 0x010027, 0x01003b, - 0x01003b, 0x01003e, 0x01003e, 0x01004e, 0x01004f, 0x01005e, 0x01007f, 0x0100fb, 0x0100ff, 0x010103, 0x010106, 0x010134, 0x010136, 0x01018f, 0x01018f, 0x01019d, 0x01019f, - 0x0101a1, 0x0101cf, 0x0101fe, 0x01027f, 0x01029d, 0x01029f, 0x0102d1, 0x0102df, 0x0102fc, 0x0102ff, 0x010324, 0x01032c, 0x01034b, 0x01034f, 0x01037b, 0x01037f, 0x01039e, - 0x01039e, 0x0103c4, 0x0103c7, 0x0103d6, 0x0103ff, 0x01049e, 0x01049f, 0x0104aa, 0x0104af, 0x0104d4, 0x0104d7, 0x0104fc, 0x0104ff, 0x010528, 0x01052f, 0x010564, 0x01056e, - 0x010570, 0x0105ff, 0x010737, 0x01073f, 0x010756, 0x01075f, 0x010768, 0x0107ff, 0x010806, 0x010807, 0x010809, 0x010809, 0x010836, 0x010836, 0x010839, 0x01083b, 0x01083d, - 0x01083e, 0x010856, 0x010856, 0x01089f, 0x0108a6, 0x0108b0, 0x0108df, 0x0108f3, 0x0108f3, 0x0108f6, 0x0108fa, 0x01091c, 0x01091e, 0x01093a, 0x01093e, 0x010940, 0x01097f, - 0x0109b8, 0x0109bb, 0x0109d0, 0x0109d1, 0x010a04, 0x010a04, 0x010a07, 0x010a0b, 0x010a14, 0x010a14, 0x010a18, 0x010a18, 0x010a36, 0x010a37, 0x010a3b, 0x010a3e, 0x010a49, - 0x010a4f, 0x010a59, 0x010a5f, 0x010aa0, 0x010abf, 0x010ae7, 0x010aea, 0x010af7, 0x010aff, 0x010b36, 0x010b38, 0x010b56, 0x010b57, 0x010b73, 0x010b77, 0x010b92, 0x010b98, - 0x010b9d, 0x010ba8, 0x010bb0, 0x010bff, 0x010c49, 0x010c7f, 0x010cb3, 0x010cbf, 0x010cf3, 0x010cf9, 0x010d28, 0x010d2f, 0x010d3a, 0x010e5f, 0x010e7f, 0x010e7f, 0x010eaa, - 0x010eaa, 0x010eae, 0x010eaf, 0x010eb2, 0x010eff, 0x010f28, 0x010f2f, 0x010f5a, 0x010faf, 0x010fcc, 0x010fdf, 0x010ff7, 0x010fff, 0x01104e, 0x011051, 0x011070, 0x01107e, - 0x0110c2, 0x0110cc, 0x0110ce, 0x0110cf, 0x0110e9, 0x0110ef, 0x0110fa, 0x0110ff, 0x011135, 0x011135, 0x011148, 0x01114f, 0x011177, 0x01117f, 0x0111e0, 0x0111e0, 0x0111f5, - 0x0111ff, 0x011212, 0x011212, 0x01123f, 0x01127f, 0x011287, 0x011287, 0x011289, 0x011289, 0x01128e, 0x01128e, 0x01129e, 0x01129e, 0x0112aa, 0x0112af, 0x0112eb, 0x0112ef, - 0x0112fa, 0x0112ff, 0x011304, 0x011304, 0x01130d, 0x01130e, 0x011311, 0x011312, 0x011329, 0x011329, 0x011331, 0x011331, 0x011334, 0x011334, 0x01133a, 0x01133a, 0x011345, - 0x011346, 0x011349, 0x01134a, 0x01134e, 0x01134f, 0x011351, 0x011356, 0x011358, 0x01135c, 0x011364, 0x011365, 0x01136d, 0x01136f, 0x011375, 0x0113ff, 0x01145c, 0x01145c, - 0x011462, 0x01147f, 0x0114c8, 0x0114cf, 0x0114da, 0x01157f, 0x0115b6, 0x0115b7, 0x0115de, 0x0115ff, 0x011645, 0x01164f, 0x01165a, 0x01165f, 0x01166d, 0x01167f, 0x0116b9, - 0x0116bf, 0x0116ca, 0x0116ff, 0x01171b, 0x01171c, 0x01172c, 0x01172f, 0x011740, 0x0117ff, 0x01183c, 0x01189f, 0x0118f3, 0x0118fe, 0x011907, 0x011908, 0x01190a, 0x01190b, - 0x011914, 0x011914, 0x011917, 0x011917, 0x011936, 0x011936, 0x011939, 0x01193a, 0x011947, 0x01194f, 0x01195a, 0x01199f, 0x0119a8, 0x0119a9, 0x0119d8, 0x0119d9, 0x0119e5, - 0x0119ff, 0x011a48, 0x011a4f, 0x011aa3, 0x011abf, 0x011af9, 0x011bff, 0x011c09, 0x011c09, 0x011c37, 0x011c37, 0x011c46, 0x011c4f, 0x011c6d, 0x011c6f, 0x011c90, 0x011c91, - 0x011ca8, 0x011ca8, 0x011cb7, 0x011cff, 0x011d07, 0x011d07, 0x011d0a, 0x011d0a, 0x011d37, 0x011d39, 0x011d3b, 0x011d3b, 0x011d3e, 0x011d3e, 0x011d48, 0x011d4f, 0x011d5a, - 0x011d5f, 0x011d66, 0x011d66, 0x011d69, 0x011d69, 0x011d8f, 0x011d8f, 0x011d92, 0x011d92, 0x011d99, 0x011d9f, 0x011daa, 0x011edf, 0x011ef9, 0x011faf, 0x011fb1, 0x011fbf, - 0x011ff2, 0x011ffe, 0x01239a, 0x0123ff, 0x01246f, 0x01246f, 0x012475, 0x01247f, 0x012544, 0x012fff, 0x01342f, 0x01342f, 0x013439, 0x0143ff, 0x014647, 0x0167ff, 0x016a39, - 0x016a3f, 0x016a5f, 0x016a5f, 0x016a6a, 0x016a6d, 0x016a70, 0x016acf, 0x016aee, 0x016aef, 0x016af6, 0x016aff, 0x016b46, 0x016b4f, 0x016b5a, 0x016b5a, 0x016b62, 0x016b62, - 0x016b78, 0x016b7c, 0x016b90, 0x016e3f, 0x016e9b, 0x016eff, 0x016f4b, 0x016f4e, 0x016f88, 0x016f8e, 0x016fa0, 0x016fdf, 0x016fe5, 0x016fef, 0x016ff2, 0x016fff, 0x0187f8, - 0x0187ff, 0x018cd6, 0x018cff, 0x018d09, 0x01afff, 0x01b11f, 0x01b14f, 0x01b153, 0x01b163, 0x01b168, 0x01b16f, 0x01b2fc, 0x01bbff, 0x01bc6b, 0x01bc6f, 0x01bc7d, 0x01bc7f, - 0x01bc89, 0x01bc8f, 0x01bc9a, 0x01bc9b, 0x01bca4, 0x01cfff, 0x01d0f6, 0x01d0ff, 0x01d127, 0x01d128, 0x01d1e9, 0x01d1ff, 0x01d246, 0x01d2df, 0x01d2f4, 0x01d2ff, 0x01d357, - 0x01d35f, 0x01d379, 0x01d3ff, 0x01d455, 0x01d455, 0x01d49d, 0x01d49d, 0x01d4a0, 0x01d4a1, 0x01d4a3, 0x01d4a4, 0x01d4a7, 0x01d4a8, 0x01d4ad, 0x01d4ad, 0x01d4ba, 0x01d4ba, - 0x01d4bc, 0x01d4bc, 0x01d4c4, 0x01d4c4, 0x01d506, 0x01d506, 0x01d50b, 0x01d50c, 0x01d515, 0x01d515, 0x01d51d, 0x01d51d, 0x01d53a, 0x01d53a, 0x01d53f, 0x01d53f, 0x01d545, - 0x01d545, 0x01d547, 0x01d549, 0x01d551, 0x01d551, 0x01d6a6, 0x01d6a7, 0x01d7cc, 0x01d7cd, 0x01da8c, 0x01da9a, 0x01daa0, 0x01daa0, 0x01dab0, 0x01dfff, 0x01e007, 0x01e007, - 0x01e019, 0x01e01a, 0x01e022, 0x01e022, 0x01e025, 0x01e025, 0x01e02b, 0x01e0ff, 0x01e12d, 0x01e12f, 0x01e13e, 0x01e13f, 0x01e14a, 0x01e14d, 0x01e150, 0x01e2bf, 0x01e2fa, - 0x01e2fe, 0x01e300, 0x01e7ff, 0x01e8c5, 0x01e8c6, 0x01e8d7, 0x01e8ff, 0x01e94c, 0x01e94f, 0x01e95a, 0x01e95d, 0x01e960, 0x01ec70, 0x01ecb5, 0x01ed00, 0x01ed3e, 0x01edff, - 0x01ee04, 0x01ee04, 0x01ee20, 0x01ee20, 0x01ee23, 0x01ee23, 0x01ee25, 0x01ee26, 0x01ee28, 0x01ee28, 0x01ee33, 0x01ee33, 0x01ee38, 0x01ee38, 0x01ee3a, 0x01ee3a, 0x01ee3c, - 0x01ee41, 0x01ee43, 0x01ee46, 0x01ee48, 0x01ee48, 0x01ee4a, 0x01ee4a, 0x01ee4c, 0x01ee4c, 0x01ee50, 0x01ee50, 0x01ee53, 0x01ee53, 0x01ee55, 0x01ee56, 0x01ee58, 0x01ee58, - 0x01ee5a, 0x01ee5a, 0x01ee5c, 0x01ee5c, 0x01ee5e, 0x01ee5e, 0x01ee60, 0x01ee60, 0x01ee63, 0x01ee63, 0x01ee65, 0x01ee66, 0x01ee6b, 0x01ee6b, 0x01ee73, 0x01ee73, 0x01ee78, - 0x01ee78, 0x01ee7d, 0x01ee7d, 0x01ee7f, 0x01ee7f, 0x01ee8a, 0x01ee8a, 0x01ee9c, 0x01eea0, 0x01eea4, 0x01eea4, 0x01eeaa, 0x01eeaa, 0x01eebc, 0x01eeef, 0x01eef2, 0x01efff, - 0x01f02c, 0x01f02f, 0x01f094, 0x01f09f, 0x01f0af, 0x01f0b0, 0x01f0c0, 0x01f0c0, 0x01f0d0, 0x01f0d0, 0x01f0f6, 0x01f0ff, 0x01f1ae, 0x01f1e5, 0x01f203, 0x01f20f, 0x01f23c, - 0x01f23f, 0x01f249, 0x01f24f, 0x01f252, 0x01f25f, 0x01f266, 0x01f2ff, 0x01f6d8, 0x01f6df, 0x01f6ed, 0x01f6ef, 0x01f6fd, 0x01f6ff, 0x01f774, 0x01f77f, 0x01f7d9, 0x01f7df, - 0x01f7ec, 0x01f7ff, 0x01f80c, 0x01f80f, 0x01f848, 0x01f84f, 0x01f85a, 0x01f85f, 0x01f888, 0x01f88f, 0x01f8ae, 0x01f8af, 0x01f8b2, 0x01f8ff, 0x01f979, 0x01f979, 0x01f9cc, - 0x01f9cc, 0x01fa54, 0x01fa5f, 0x01fa6e, 0x01fa6f, 0x01fa75, 0x01fa77, 0x01fa7b, 0x01fa7f, 0x01fa87, 0x01fa8f, 0x01faa9, 0x01faaf, 0x01fab7, 0x01fabf, 0x01fac3, 0x01facf, - 0x01fad7, 0x01faff, 0x01fb93, 0x01fb93, 0x01fbcb, 0x01fbef, 0x01fbfa, 0x01ffff, 0x02a6de, 0x02a6ff, 0x02b735, 0x02b73f, 0x02b81e, 0x02b81f, 0x02cea2, 0x02ceaf, 0x02ebe1, - 0x02f7ff, 0x02fa1e, 0x02ffff, 0x03134b, 0x0e0000, 0x0e0002, 0x0e001f, 0x0e0080, 0x0e00ff, 0x0e01f0, 0x10ffff)); + 0x001716, 0x00171e, 0x001737, 0x00173f, 0x001754, 0x00175f, 0x00176d, 0x00176d, 0x001771, 0x001771, 0x001774, 0x00177f, 0x0017de, 0x0017df, 0x0017ea, 0x0017ef, 0x0017fa, + 0x0017ff, 0x00181a, 0x00181f, 0x001879, 0x00187f, 0x0018ab, 0x0018af, 0x0018f6, 0x0018ff, 0x00191f, 0x00191f, 0x00192c, 0x00192f, 0x00193c, 0x00193f, 0x001941, 0x001943, + 0x00196e, 0x00196f, 0x001975, 0x00197f, 0x0019ac, 0x0019af, 0x0019ca, 0x0019cf, 0x0019db, 0x0019dd, 0x001a1c, 0x001a1d, 0x001a5f, 0x001a5f, 0x001a7d, 0x001a7e, 0x001a8a, + 0x001a8f, 0x001a9a, 0x001a9f, 0x001aae, 0x001aaf, 0x001acf, 0x001aff, 0x001b4d, 0x001b4f, 0x001b7f, 0x001b7f, 0x001bf4, 0x001bfb, 0x001c38, 0x001c3a, 0x001c4a, 0x001c4c, + 0x001c89, 0x001c8f, 0x001cbb, 0x001cbc, 0x001cc8, 0x001ccf, 0x001cfb, 0x001cff, 0x001f16, 0x001f17, 0x001f1e, 0x001f1f, 0x001f46, 0x001f47, 0x001f4e, 0x001f4f, 0x001f58, + 0x001f58, 0x001f5a, 0x001f5a, 0x001f5c, 0x001f5c, 0x001f5e, 0x001f5e, 0x001f7e, 0x001f7f, 0x001fb5, 0x001fb5, 0x001fc5, 0x001fc5, 0x001fd4, 0x001fd5, 0x001fdc, 0x001fdc, + 0x001ff0, 0x001ff1, 0x001ff5, 0x001ff5, 0x001fff, 0x001fff, 0x002065, 0x002065, 0x002072, 0x002073, 0x00208f, 0x00208f, 0x00209d, 0x00209f, 0x0020c1, 0x0020cf, 0x0020f1, + 0x0020ff, 0x00218c, 0x00218f, 0x002427, 0x00243f, 0x00244b, 0x00245f, 0x002b74, 0x002b75, 0x002b96, 0x002b96, 0x002cf4, 0x002cf8, 0x002d26, 0x002d26, 0x002d28, 0x002d2c, + 0x002d2e, 0x002d2f, 0x002d68, 0x002d6e, 0x002d71, 0x002d7e, 0x002d97, 0x002d9f, 0x002da7, 0x002da7, 0x002daf, 0x002daf, 0x002db7, 0x002db7, 0x002dbf, 0x002dbf, 0x002dc7, + 0x002dc7, 0x002dcf, 0x002dcf, 0x002dd7, 0x002dd7, 0x002ddf, 0x002ddf, 0x002e5e, 0x002e7f, 0x002e9a, 0x002e9a, 0x002ef4, 0x002eff, 0x002fd6, 0x002fef, 0x002ffc, 0x002fff, + 0x003040, 0x003040, 0x003097, 0x003098, 0x003100, 0x003104, 0x003130, 0x003130, 0x00318f, 0x00318f, 0x0031e4, 0x0031ef, 0x00321f, 0x00321f, 0x00a48d, 0x00a48f, 0x00a4c7, + 0x00a4cf, 0x00a62c, 0x00a63f, 0x00a6f8, 0x00a6ff, 0x00a7cb, 0x00a7cf, 0x00a7d2, 0x00a7d2, 0x00a7d4, 0x00a7d4, 0x00a7da, 0x00a7f1, 0x00a82d, 0x00a82f, 0x00a83a, 0x00a83f, + 0x00a878, 0x00a87f, 0x00a8c6, 0x00a8cd, 0x00a8da, 0x00a8df, 0x00a954, 0x00a95e, 0x00a97d, 0x00a97f, 0x00a9ce, 0x00a9ce, 0x00a9da, 0x00a9dd, 0x00a9ff, 0x00a9ff, 0x00aa37, + 0x00aa3f, 0x00aa4e, 0x00aa4f, 0x00aa5a, 0x00aa5b, 0x00aac3, 0x00aada, 0x00aaf7, 0x00ab00, 0x00ab07, 0x00ab08, 0x00ab0f, 0x00ab10, 0x00ab17, 0x00ab1f, 0x00ab27, 0x00ab27, + 0x00ab2f, 0x00ab2f, 0x00ab6c, 0x00ab6f, 0x00abee, 0x00abef, 0x00abfa, 0x00abff, 0x00d7a4, 0x00d7af, 0x00d7c7, 0x00d7ca, 0x00d7fc, 0x00f8ff, 0x00fa6e, 0x00fa6f, 0x00fada, + 0x00faff, 0x00fb07, 0x00fb12, 0x00fb18, 0x00fb1c, 0x00fb37, 0x00fb37, 0x00fb3d, 0x00fb3d, 0x00fb3f, 0x00fb3f, 0x00fb42, 0x00fb42, 0x00fb45, 0x00fb45, 0x00fbc3, 0x00fbd2, + 0x00fd90, 0x00fd91, 0x00fdc8, 0x00fdce, 0x00fdd0, 0x00fdef, 0x00fe1a, 0x00fe1f, 0x00fe53, 0x00fe53, 0x00fe67, 0x00fe67, 0x00fe6c, 0x00fe6f, 0x00fe75, 0x00fe75, 0x00fefd, + 0x00fefe, 0x00ff00, 0x00ff00, 0x00ffbf, 0x00ffc1, 0x00ffc8, 0x00ffc9, 0x00ffd0, 0x00ffd1, 0x00ffd8, 0x00ffd9, 0x00ffdd, 0x00ffdf, 0x00ffe7, 0x00ffe7, 0x00ffef, 0x00fff8, + 0x00fffe, 0x00ffff, 0x01000c, 0x01000c, 0x010027, 0x010027, 0x01003b, 0x01003b, 0x01003e, 0x01003e, 0x01004e, 0x01004f, 0x01005e, 0x01007f, 0x0100fb, 0x0100ff, 0x010103, + 0x010106, 0x010134, 0x010136, 0x01018f, 0x01018f, 0x01019d, 0x01019f, 0x0101a1, 0x0101cf, 0x0101fe, 0x01027f, 0x01029d, 0x01029f, 0x0102d1, 0x0102df, 0x0102fc, 0x0102ff, + 0x010324, 0x01032c, 0x01034b, 0x01034f, 0x01037b, 0x01037f, 0x01039e, 0x01039e, 0x0103c4, 0x0103c7, 0x0103d6, 0x0103ff, 0x01049e, 0x01049f, 0x0104aa, 0x0104af, 0x0104d4, + 0x0104d7, 0x0104fc, 0x0104ff, 0x010528, 0x01052f, 0x010564, 0x01056e, 0x01057b, 0x01057b, 0x01058b, 0x01058b, 0x010593, 0x010593, 0x010596, 0x010596, 0x0105a2, 0x0105a2, + 0x0105b2, 0x0105b2, 0x0105ba, 0x0105ba, 0x0105bd, 0x0105ff, 0x010737, 0x01073f, 0x010756, 0x01075f, 0x010768, 0x01077f, 0x010786, 0x010786, 0x0107b1, 0x0107b1, 0x0107bb, + 0x0107ff, 0x010806, 0x010807, 0x010809, 0x010809, 0x010836, 0x010836, 0x010839, 0x01083b, 0x01083d, 0x01083e, 0x010856, 0x010856, 0x01089f, 0x0108a6, 0x0108b0, 0x0108df, + 0x0108f3, 0x0108f3, 0x0108f6, 0x0108fa, 0x01091c, 0x01091e, 0x01093a, 0x01093e, 0x010940, 0x01097f, 0x0109b8, 0x0109bb, 0x0109d0, 0x0109d1, 0x010a04, 0x010a04, 0x010a07, + 0x010a0b, 0x010a14, 0x010a14, 0x010a18, 0x010a18, 0x010a36, 0x010a37, 0x010a3b, 0x010a3e, 0x010a49, 0x010a4f, 0x010a59, 0x010a5f, 0x010aa0, 0x010abf, 0x010ae7, 0x010aea, + 0x010af7, 0x010aff, 0x010b36, 0x010b38, 0x010b56, 0x010b57, 0x010b73, 0x010b77, 0x010b92, 0x010b98, 0x010b9d, 0x010ba8, 0x010bb0, 0x010bff, 0x010c49, 0x010c7f, 0x010cb3, + 0x010cbf, 0x010cf3, 0x010cf9, 0x010d28, 0x010d2f, 0x010d3a, 0x010e5f, 0x010e7f, 0x010e7f, 0x010eaa, 0x010eaa, 0x010eae, 0x010eaf, 0x010eb2, 0x010eff, 0x010f28, 0x010f2f, + 0x010f5a, 0x010f6f, 0x010f8a, 0x010faf, 0x010fcc, 0x010fdf, 0x010ff7, 0x010fff, 0x01104e, 0x011051, 0x011076, 0x01107e, 0x0110c3, 0x0110cc, 0x0110ce, 0x0110cf, 0x0110e9, + 0x0110ef, 0x0110fa, 0x0110ff, 0x011135, 0x011135, 0x011148, 0x01114f, 0x011177, 0x01117f, 0x0111e0, 0x0111e0, 0x0111f5, 0x0111ff, 0x011212, 0x011212, 0x01123f, 0x01127f, + 0x011287, 0x011287, 0x011289, 0x011289, 0x01128e, 0x01128e, 0x01129e, 0x01129e, 0x0112aa, 0x0112af, 0x0112eb, 0x0112ef, 0x0112fa, 0x0112ff, 0x011304, 0x011304, 0x01130d, + 0x01130e, 0x011311, 0x011312, 0x011329, 0x011329, 0x011331, 0x011331, 0x011334, 0x011334, 0x01133a, 0x01133a, 0x011345, 0x011346, 0x011349, 0x01134a, 0x01134e, 0x01134f, + 0x011351, 0x011356, 0x011358, 0x01135c, 0x011364, 0x011365, 0x01136d, 0x01136f, 0x011375, 0x0113ff, 0x01145c, 0x01145c, 0x011462, 0x01147f, 0x0114c8, 0x0114cf, 0x0114da, + 0x01157f, 0x0115b6, 0x0115b7, 0x0115de, 0x0115ff, 0x011645, 0x01164f, 0x01165a, 0x01165f, 0x01166d, 0x01167f, 0x0116ba, 0x0116bf, 0x0116ca, 0x0116ff, 0x01171b, 0x01171c, + 0x01172c, 0x01172f, 0x011747, 0x0117ff, 0x01183c, 0x01189f, 0x0118f3, 0x0118fe, 0x011907, 0x011908, 0x01190a, 0x01190b, 0x011914, 0x011914, 0x011917, 0x011917, 0x011936, + 0x011936, 0x011939, 0x01193a, 0x011947, 0x01194f, 0x01195a, 0x01199f, 0x0119a8, 0x0119a9, 0x0119d8, 0x0119d9, 0x0119e5, 0x0119ff, 0x011a48, 0x011a4f, 0x011aa3, 0x011aaf, + 0x011af9, 0x011bff, 0x011c09, 0x011c09, 0x011c37, 0x011c37, 0x011c46, 0x011c4f, 0x011c6d, 0x011c6f, 0x011c90, 0x011c91, 0x011ca8, 0x011ca8, 0x011cb7, 0x011cff, 0x011d07, + 0x011d07, 0x011d0a, 0x011d0a, 0x011d37, 0x011d39, 0x011d3b, 0x011d3b, 0x011d3e, 0x011d3e, 0x011d48, 0x011d4f, 0x011d5a, 0x011d5f, 0x011d66, 0x011d66, 0x011d69, 0x011d69, + 0x011d8f, 0x011d8f, 0x011d92, 0x011d92, 0x011d99, 0x011d9f, 0x011daa, 0x011edf, 0x011ef9, 0x011faf, 0x011fb1, 0x011fbf, 0x011ff2, 0x011ffe, 0x01239a, 0x0123ff, 0x01246f, + 0x01246f, 0x012475, 0x01247f, 0x012544, 0x012f8f, 0x012ff3, 0x012fff, 0x01342f, 0x01342f, 0x013439, 0x0143ff, 0x014647, 0x0167ff, 0x016a39, 0x016a3f, 0x016a5f, 0x016a5f, + 0x016a6a, 0x016a6d, 0x016abf, 0x016abf, 0x016aca, 0x016acf, 0x016aee, 0x016aef, 0x016af6, 0x016aff, 0x016b46, 0x016b4f, 0x016b5a, 0x016b5a, 0x016b62, 0x016b62, 0x016b78, + 0x016b7c, 0x016b90, 0x016e3f, 0x016e9b, 0x016eff, 0x016f4b, 0x016f4e, 0x016f88, 0x016f8e, 0x016fa0, 0x016fdf, 0x016fe5, 0x016fef, 0x016ff2, 0x016fff, 0x0187f8, 0x0187ff, + 0x018cd6, 0x018cff, 0x018d09, 0x01afef, 0x01aff4, 0x01aff4, 0x01affc, 0x01affc, 0x01afff, 0x01afff, 0x01b123, 0x01b14f, 0x01b153, 0x01b163, 0x01b168, 0x01b16f, 0x01b2fc, + 0x01bbff, 0x01bc6b, 0x01bc6f, 0x01bc7d, 0x01bc7f, 0x01bc89, 0x01bc8f, 0x01bc9a, 0x01bc9b, 0x01bca4, 0x01ceff, 0x01cf2e, 0x01cf2f, 0x01cf47, 0x01cf4f, 0x01cfc4, 0x01cfff, + 0x01d0f6, 0x01d0ff, 0x01d127, 0x01d128, 0x01d1eb, 0x01d1ff, 0x01d246, 0x01d2df, 0x01d2f4, 0x01d2ff, 0x01d357, 0x01d35f, 0x01d379, 0x01d3ff, 0x01d455, 0x01d455, 0x01d49d, + 0x01d49d, 0x01d4a0, 0x01d4a1, 0x01d4a3, 0x01d4a4, 0x01d4a7, 0x01d4a8, 0x01d4ad, 0x01d4ad, 0x01d4ba, 0x01d4ba, 0x01d4bc, 0x01d4bc, 0x01d4c4, 0x01d4c4, 0x01d506, 0x01d506, + 0x01d50b, 0x01d50c, 0x01d515, 0x01d515, 0x01d51d, 0x01d51d, 0x01d53a, 0x01d53a, 0x01d53f, 0x01d53f, 0x01d545, 0x01d545, 0x01d547, 0x01d549, 0x01d551, 0x01d551, 0x01d6a6, + 0x01d6a7, 0x01d7cc, 0x01d7cd, 0x01da8c, 0x01da9a, 0x01daa0, 0x01daa0, 0x01dab0, 0x01deff, 0x01df1f, 0x01dfff, 0x01e007, 0x01e007, 0x01e019, 0x01e01a, 0x01e022, 0x01e022, + 0x01e025, 0x01e025, 0x01e02b, 0x01e0ff, 0x01e12d, 0x01e12f, 0x01e13e, 0x01e13f, 0x01e14a, 0x01e14d, 0x01e150, 0x01e28f, 0x01e2af, 0x01e2bf, 0x01e2fa, 0x01e2fe, 0x01e300, + 0x01e7df, 0x01e7e7, 0x01e7e7, 0x01e7ec, 0x01e7ec, 0x01e7ef, 0x01e7ef, 0x01e7ff, 0x01e7ff, 0x01e8c5, 0x01e8c6, 0x01e8d7, 0x01e8ff, 0x01e94c, 0x01e94f, 0x01e95a, 0x01e95d, + 0x01e960, 0x01ec70, 0x01ecb5, 0x01ed00, 0x01ed3e, 0x01edff, 0x01ee04, 0x01ee04, 0x01ee20, 0x01ee20, 0x01ee23, 0x01ee23, 0x01ee25, 0x01ee26, 0x01ee28, 0x01ee28, 0x01ee33, + 0x01ee33, 0x01ee38, 0x01ee38, 0x01ee3a, 0x01ee3a, 0x01ee3c, 0x01ee41, 0x01ee43, 0x01ee46, 0x01ee48, 0x01ee48, 0x01ee4a, 0x01ee4a, 0x01ee4c, 0x01ee4c, 0x01ee50, 0x01ee50, + 0x01ee53, 0x01ee53, 0x01ee55, 0x01ee56, 0x01ee58, 0x01ee58, 0x01ee5a, 0x01ee5a, 0x01ee5c, 0x01ee5c, 0x01ee5e, 0x01ee5e, 0x01ee60, 0x01ee60, 0x01ee63, 0x01ee63, 0x01ee65, + 0x01ee66, 0x01ee6b, 0x01ee6b, 0x01ee73, 0x01ee73, 0x01ee78, 0x01ee78, 0x01ee7d, 0x01ee7d, 0x01ee7f, 0x01ee7f, 0x01ee8a, 0x01ee8a, 0x01ee9c, 0x01eea0, 0x01eea4, 0x01eea4, + 0x01eeaa, 0x01eeaa, 0x01eebc, 0x01eeef, 0x01eef2, 0x01efff, 0x01f02c, 0x01f02f, 0x01f094, 0x01f09f, 0x01f0af, 0x01f0b0, 0x01f0c0, 0x01f0c0, 0x01f0d0, 0x01f0d0, 0x01f0f6, + 0x01f0ff, 0x01f1ae, 0x01f1e5, 0x01f203, 0x01f20f, 0x01f23c, 0x01f23f, 0x01f249, 0x01f24f, 0x01f252, 0x01f25f, 0x01f266, 0x01f2ff, 0x01f6d8, 0x01f6dc, 0x01f6ed, 0x01f6ef, + 0x01f6fd, 0x01f6ff, 0x01f774, 0x01f77f, 0x01f7d9, 0x01f7df, 0x01f7ec, 0x01f7ef, 0x01f7f1, 0x01f7ff, 0x01f80c, 0x01f80f, 0x01f848, 0x01f84f, 0x01f85a, 0x01f85f, 0x01f888, + 0x01f88f, 0x01f8ae, 0x01f8af, 0x01f8b2, 0x01f8ff, 0x01fa54, 0x01fa5f, 0x01fa6e, 0x01fa6f, 0x01fa75, 0x01fa77, 0x01fa7d, 0x01fa7f, 0x01fa87, 0x01fa8f, 0x01faad, 0x01faaf, + 0x01fabb, 0x01fabf, 0x01fac6, 0x01facf, 0x01fada, 0x01fadf, 0x01fae8, 0x01faef, 0x01faf7, 0x01faff, 0x01fb93, 0x01fb93, 0x01fbcb, 0x01fbef, 0x01fbfa, 0x01ffff, 0x02a6e0, + 0x02a6ff, 0x02b739, 0x02b73f, 0x02b81e, 0x02b81f, 0x02cea2, 0x02ceaf, 0x02ebe1, 0x02f7ff, 0x02fa1e, 0x02ffff, 0x03134b, 0x0e0000, 0x0e0002, 0x0e001f, 0x0e0080, 0x0e00ff, + 0x0e01f0, 0x10ffff)); } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/CaseFoldTable.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/CaseFoldTable.java index 73131fc51010..2589cef46975 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/CaseFoldTable.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/CaseFoldTable.java @@ -579,8 +579,8 @@ public void appendRangesTo(RangesBuffer buffer, int startIndex, int endIndex) { 0x002183, 0x002184, ALTERNATING_UL, 0, 0x0024b6, 0x0024cf, INTEGER_OFFSET, 26, 0x0024d0, 0x0024e9, INTEGER_OFFSET, -26, - 0x002c00, 0x002c2e, INTEGER_OFFSET, 48, - 0x002c30, 0x002c5e, INTEGER_OFFSET, -48, + 0x002c00, 0x002c2f, INTEGER_OFFSET, 48, + 0x002c30, 0x002c5f, INTEGER_OFFSET, -48, 0x002c60, 0x002c61, ALTERNATING_AL, 0, 0x002c62, 0x002c62, INTEGER_OFFSET, -10743, 0x002c63, 0x002c63, INTEGER_OFFSET, -3814, @@ -624,12 +624,13 @@ public void appendRangesTo(RangesBuffer buffer, int startIndex, int endIndex) { 0x00a7b1, 0x00a7b1, INTEGER_OFFSET, -42282, 0x00a7b2, 0x00a7b2, INTEGER_OFFSET, -42261, 0x00a7b3, 0x00a7b3, INTEGER_OFFSET, 928, - 0x00a7b4, 0x00a7bf, ALTERNATING_AL, 0, - 0x00a7c2, 0x00a7c3, ALTERNATING_AL, 0, + 0x00a7b4, 0x00a7c3, ALTERNATING_AL, 0, 0x00a7c4, 0x00a7c4, INTEGER_OFFSET, -48, 0x00a7c5, 0x00a7c5, INTEGER_OFFSET, -42307, 0x00a7c6, 0x00a7c6, INTEGER_OFFSET, -35384, 0x00a7c7, 0x00a7ca, ALTERNATING_UL, 0, + 0x00a7d0, 0x00a7d1, ALTERNATING_AL, 0, + 0x00a7d6, 0x00a7d9, ALTERNATING_AL, 0, 0x00a7f5, 0x00a7f6, ALTERNATING_UL, 0, 0x00ab53, 0x00ab53, INTEGER_OFFSET, -928, 0x00ab70, 0x00abbf, INTEGER_OFFSET, -38864, @@ -639,6 +640,14 @@ public void appendRangesTo(RangesBuffer buffer, int startIndex, int endIndex) { 0x010428, 0x01044f, INTEGER_OFFSET, -40, 0x0104b0, 0x0104d3, INTEGER_OFFSET, 40, 0x0104d8, 0x0104fb, INTEGER_OFFSET, -40, + 0x010570, 0x01057a, INTEGER_OFFSET, 39, + 0x01057c, 0x01058a, INTEGER_OFFSET, 39, + 0x01058c, 0x010592, INTEGER_OFFSET, 39, + 0x010594, 0x010595, INTEGER_OFFSET, 39, + 0x010597, 0x0105a1, INTEGER_OFFSET, -39, + 0x0105a3, 0x0105b1, INTEGER_OFFSET, -39, + 0x0105b3, 0x0105b9, INTEGER_OFFSET, -39, + 0x0105bb, 0x0105bc, INTEGER_OFFSET, -39, 0x010c80, 0x010cb2, INTEGER_OFFSET, 64, 0x010cc0, 0x010cf2, INTEGER_OFFSET, -64, 0x0118a0, 0x0118bf, INTEGER_OFFSET, 32, @@ -965,8 +974,8 @@ public void appendRangesTo(RangesBuffer buffer, int startIndex, int endIndex) { 0x002183, 0x002184, ALTERNATING_UL, 0, 0x0024b6, 0x0024cf, INTEGER_OFFSET, 26, 0x0024d0, 0x0024e9, INTEGER_OFFSET, -26, - 0x002c00, 0x002c2e, INTEGER_OFFSET, 48, - 0x002c30, 0x002c5e, INTEGER_OFFSET, -48, + 0x002c00, 0x002c2f, INTEGER_OFFSET, 48, + 0x002c30, 0x002c5f, INTEGER_OFFSET, -48, 0x002c60, 0x002c61, ALTERNATING_AL, 0, 0x002c62, 0x002c62, INTEGER_OFFSET, -10743, 0x002c63, 0x002c63, INTEGER_OFFSET, -3814, @@ -1010,12 +1019,13 @@ public void appendRangesTo(RangesBuffer buffer, int startIndex, int endIndex) { 0x00a7b1, 0x00a7b1, INTEGER_OFFSET, -42282, 0x00a7b2, 0x00a7b2, INTEGER_OFFSET, -42261, 0x00a7b3, 0x00a7b3, INTEGER_OFFSET, 928, - 0x00a7b4, 0x00a7bf, ALTERNATING_AL, 0, - 0x00a7c2, 0x00a7c3, ALTERNATING_AL, 0, + 0x00a7b4, 0x00a7c3, ALTERNATING_AL, 0, 0x00a7c4, 0x00a7c4, INTEGER_OFFSET, -48, 0x00a7c5, 0x00a7c5, INTEGER_OFFSET, -42307, 0x00a7c6, 0x00a7c6, INTEGER_OFFSET, -35384, 0x00a7c7, 0x00a7ca, ALTERNATING_UL, 0, + 0x00a7d0, 0x00a7d1, ALTERNATING_AL, 0, + 0x00a7d6, 0x00a7d9, ALTERNATING_AL, 0, 0x00a7f5, 0x00a7f6, ALTERNATING_UL, 0, 0x00ab53, 0x00ab53, INTEGER_OFFSET, -928, 0x00ab70, 0x00abbf, INTEGER_OFFSET, -38864, @@ -1025,6 +1035,14 @@ public void appendRangesTo(RangesBuffer buffer, int startIndex, int endIndex) { 0x010428, 0x01044f, INTEGER_OFFSET, -40, 0x0104b0, 0x0104d3, INTEGER_OFFSET, 40, 0x0104d8, 0x0104fb, INTEGER_OFFSET, -40, + 0x010570, 0x01057a, INTEGER_OFFSET, 39, + 0x01057c, 0x01058a, INTEGER_OFFSET, 39, + 0x01058c, 0x010592, INTEGER_OFFSET, 39, + 0x010594, 0x010595, INTEGER_OFFSET, 39, + 0x010597, 0x0105a1, INTEGER_OFFSET, -39, + 0x0105a3, 0x0105b1, INTEGER_OFFSET, -39, + 0x0105b3, 0x0105b9, INTEGER_OFFSET, -39, + 0x0105bb, 0x0105bc, INTEGER_OFFSET, -39, 0x010c80, 0x010cb2, INTEGER_OFFSET, 64, 0x010cc0, 0x010cf2, INTEGER_OFFSET, -64, 0x0118a0, 0x0118bf, INTEGER_OFFSET, 32, @@ -1528,8 +1546,8 @@ public void appendRangesTo(RangesBuffer buffer, int startIndex, int endIndex) { 0x002183, 0x002184, ALTERNATING_UL, 0, 0x0024b6, 0x0024cf, INTEGER_OFFSET, 26, 0x0024d0, 0x0024e9, INTEGER_OFFSET, -26, - 0x002c00, 0x002c2e, INTEGER_OFFSET, 48, - 0x002c30, 0x002c5e, INTEGER_OFFSET, -48, + 0x002c00, 0x002c2f, INTEGER_OFFSET, 48, + 0x002c30, 0x002c5f, INTEGER_OFFSET, -48, 0x002c60, 0x002c61, ALTERNATING_AL, 0, 0x002c62, 0x002c62, INTEGER_OFFSET, -10743, 0x002c63, 0x002c63, INTEGER_OFFSET, -3814, @@ -1573,12 +1591,13 @@ public void appendRangesTo(RangesBuffer buffer, int startIndex, int endIndex) { 0x00a7b1, 0x00a7b1, INTEGER_OFFSET, -42282, 0x00a7b2, 0x00a7b2, INTEGER_OFFSET, -42261, 0x00a7b3, 0x00a7b3, INTEGER_OFFSET, 928, - 0x00a7b4, 0x00a7bf, ALTERNATING_AL, 0, - 0x00a7c2, 0x00a7c3, ALTERNATING_AL, 0, + 0x00a7b4, 0x00a7c3, ALTERNATING_AL, 0, 0x00a7c4, 0x00a7c4, INTEGER_OFFSET, -48, 0x00a7c5, 0x00a7c5, INTEGER_OFFSET, -42307, 0x00a7c6, 0x00a7c6, INTEGER_OFFSET, -35384, 0x00a7c7, 0x00a7ca, ALTERNATING_UL, 0, + 0x00a7d0, 0x00a7d1, ALTERNATING_AL, 0, + 0x00a7d6, 0x00a7d9, ALTERNATING_AL, 0, 0x00a7f5, 0x00a7f6, ALTERNATING_UL, 0, 0x00ab53, 0x00ab53, INTEGER_OFFSET, -928, 0x00ab70, 0x00abbf, INTEGER_OFFSET, -38864, @@ -1593,6 +1612,14 @@ public void appendRangesTo(RangesBuffer buffer, int startIndex, int endIndex) { 0x010428, 0x01044f, INTEGER_OFFSET, -40, 0x0104b0, 0x0104d3, INTEGER_OFFSET, 40, 0x0104d8, 0x0104fb, INTEGER_OFFSET, -40, + 0x010570, 0x01057a, INTEGER_OFFSET, 39, + 0x01057c, 0x01058a, INTEGER_OFFSET, 39, + 0x01058c, 0x010592, INTEGER_OFFSET, 39, + 0x010594, 0x010595, INTEGER_OFFSET, 39, + 0x010597, 0x0105a1, INTEGER_OFFSET, -39, + 0x0105a3, 0x0105b1, INTEGER_OFFSET, -39, + 0x0105b3, 0x0105b9, INTEGER_OFFSET, -39, + 0x0105bb, 0x0105bc, INTEGER_OFFSET, -39, 0x010c80, 0x010cb2, INTEGER_OFFSET, 64, 0x010cc0, 0x010cf2, INTEGER_OFFSET, -64, 0x0118a0, 0x0118bf, INTEGER_OFFSET, 32, diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/flavors/RubyCaseFoldingData.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/flavors/RubyCaseFoldingData.java index 5ff5eca0e68b..4efcb62e609d 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/flavors/RubyCaseFoldingData.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/flavors/RubyCaseFoldingData.java @@ -1010,6 +1010,7 @@ public class RubyCaseFoldingData { CASE_FOLD.put(0x2C2C, new int[]{0x2C5C}); CASE_FOLD.put(0x2C2D, new int[]{0x2C5D}); CASE_FOLD.put(0x2C2E, new int[]{0x2C5E}); + CASE_FOLD.put(0x2C2F, new int[]{0x2C5F}); CASE_FOLD.put(0x2C60, new int[]{0x2C61}); CASE_FOLD.put(0x2C62, new int[]{0x026B}); CASE_FOLD.put(0x2C63, new int[]{0x1D7D}); @@ -1190,12 +1191,16 @@ public class RubyCaseFoldingData { CASE_FOLD.put(0xA7BA, new int[]{0xA7BB}); CASE_FOLD.put(0xA7BC, new int[]{0xA7BD}); CASE_FOLD.put(0xA7BE, new int[]{0xA7BF}); + CASE_FOLD.put(0xA7C0, new int[]{0xA7C1}); CASE_FOLD.put(0xA7C2, new int[]{0xA7C3}); CASE_FOLD.put(0xA7C4, new int[]{0xA794}); CASE_FOLD.put(0xA7C5, new int[]{0x0282}); CASE_FOLD.put(0xA7C6, new int[]{0x1D8E}); CASE_FOLD.put(0xA7C7, new int[]{0xA7C8}); CASE_FOLD.put(0xA7C9, new int[]{0xA7CA}); + CASE_FOLD.put(0xA7D0, new int[]{0xA7D1}); + CASE_FOLD.put(0xA7D6, new int[]{0xA7D7}); + CASE_FOLD.put(0xA7D8, new int[]{0xA7D9}); CASE_FOLD.put(0xA7F5, new int[]{0xA7F6}); CASE_FOLD.put(0xAB70, new int[]{0x13A0}); CASE_FOLD.put(0xAB71, new int[]{0x13A1}); @@ -1391,6 +1396,41 @@ public class RubyCaseFoldingData { CASE_FOLD.put(0x104D1, new int[]{0x104F9}); CASE_FOLD.put(0x104D2, new int[]{0x104FA}); CASE_FOLD.put(0x104D3, new int[]{0x104FB}); + CASE_FOLD.put(0x10570, new int[]{0x10597}); + CASE_FOLD.put(0x10571, new int[]{0x10598}); + CASE_FOLD.put(0x10572, new int[]{0x10599}); + CASE_FOLD.put(0x10573, new int[]{0x1059A}); + CASE_FOLD.put(0x10574, new int[]{0x1059B}); + CASE_FOLD.put(0x10575, new int[]{0x1059C}); + CASE_FOLD.put(0x10576, new int[]{0x1059D}); + CASE_FOLD.put(0x10577, new int[]{0x1059E}); + CASE_FOLD.put(0x10578, new int[]{0x1059F}); + CASE_FOLD.put(0x10579, new int[]{0x105A0}); + CASE_FOLD.put(0x1057A, new int[]{0x105A1}); + CASE_FOLD.put(0x1057C, new int[]{0x105A3}); + CASE_FOLD.put(0x1057D, new int[]{0x105A4}); + CASE_FOLD.put(0x1057E, new int[]{0x105A5}); + CASE_FOLD.put(0x1057F, new int[]{0x105A6}); + CASE_FOLD.put(0x10580, new int[]{0x105A7}); + CASE_FOLD.put(0x10581, new int[]{0x105A8}); + CASE_FOLD.put(0x10582, new int[]{0x105A9}); + CASE_FOLD.put(0x10583, new int[]{0x105AA}); + CASE_FOLD.put(0x10584, new int[]{0x105AB}); + CASE_FOLD.put(0x10585, new int[]{0x105AC}); + CASE_FOLD.put(0x10586, new int[]{0x105AD}); + CASE_FOLD.put(0x10587, new int[]{0x105AE}); + CASE_FOLD.put(0x10588, new int[]{0x105AF}); + CASE_FOLD.put(0x10589, new int[]{0x105B0}); + CASE_FOLD.put(0x1058A, new int[]{0x105B1}); + CASE_FOLD.put(0x1058C, new int[]{0x105B3}); + CASE_FOLD.put(0x1058D, new int[]{0x105B4}); + CASE_FOLD.put(0x1058E, new int[]{0x105B5}); + CASE_FOLD.put(0x1058F, new int[]{0x105B6}); + CASE_FOLD.put(0x10590, new int[]{0x105B7}); + CASE_FOLD.put(0x10591, new int[]{0x105B8}); + CASE_FOLD.put(0x10592, new int[]{0x105B9}); + CASE_FOLD.put(0x10594, new int[]{0x105BB}); + CASE_FOLD.put(0x10595, new int[]{0x105BC}); CASE_FOLD.put(0x10C80, new int[]{0x10CC0}); CASE_FOLD.put(0x10C81, new int[]{0x10CC1}); CASE_FOLD.put(0x10C82, new int[]{0x10CC2}); diff --git a/regex/src/com.oracle.truffle.regex/tools/run_scripts.sh b/regex/src/com.oracle.truffle.regex/tools/run_scripts.sh index df4d0ec92b75..54ee2383d991 100755 --- a/regex/src/com.oracle.truffle.regex/tools/run_scripts.sh +++ b/regex/src/com.oracle.truffle.regex/tools/run_scripts.sh @@ -47,7 +47,7 @@ then exit 1 fi -UNICODE_VERSION=13.0.0 +UNICODE_VERSION=14.0.0 mkdir -p ./dat From b5455be456ea265d6aaf7c4075e5ef642baa7634 Mon Sep 17 00:00:00 2001 From: Jirka Marsik Date: Wed, 29 Sep 2021 19:08:36 +0200 Subject: [PATCH 225/681] Update to the released version of Unicode 14 --- .../regex/charset/UnicodePropertyData.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodePropertyData.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodePropertyData.java index d86acfc89730..25c8a8c4fffd 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodePropertyData.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/UnicodePropertyData.java @@ -1683,11 +1683,12 @@ private static void populateCASED() { 0x00a640, 0x00a66d, 0x00a680, 0x00a69d, 0x00a722, 0x00a787, 0x00a78b, 0x00a78e, 0x00a790, 0x00a7ca, 0x00a7d0, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d9, 0x00a7f5, 0x00a7f6, 0x00a7f8, 0x00a7fa, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab68, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff21, 0x00ff3a, 0x00ff41, 0x00ff5a, 0x010400, 0x01044f, 0x0104b0, 0x0104d3, 0x0104d8, 0x0104fb, 0x010570, 0x01057a, 0x01057c, 0x01058a, 0x01058c, 0x010592, 0x010594, 0x010595, 0x010597, 0x0105a1, 0x0105a3, - 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, 0x0118a0, 0x0118df, 0x016e40, 0x016e7f, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, - 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, - 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, - 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, - 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01df00, 0x01df09, 0x01df0b, 0x01df1e, 0x01e900, 0x01e943, 0x01f130, 0x01f149, 0x01f150, 0x01f169, 0x01f170, 0x01f189)); + 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010780, 0x010780, 0x010783, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x010c80, 0x010cb2, 0x010cc0, 0x010cf2, + 0x0118a0, 0x0118df, 0x016e40, 0x016e7f, 0x01d400, 0x01d454, 0x01d456, 0x01d49c, 0x01d49e, 0x01d49f, 0x01d4a2, 0x01d4a2, 0x01d4a5, 0x01d4a6, 0x01d4a9, 0x01d4ac, 0x01d4ae, + 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d505, 0x01d507, 0x01d50a, 0x01d50d, 0x01d514, 0x01d516, 0x01d51c, 0x01d51e, 0x01d539, 0x01d53b, 0x01d53e, + 0x01d540, 0x01d544, 0x01d546, 0x01d546, 0x01d54a, 0x01d550, 0x01d552, 0x01d6a5, 0x01d6a8, 0x01d6c0, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6fa, 0x01d6fc, 0x01d714, 0x01d716, + 0x01d734, 0x01d736, 0x01d74e, 0x01d750, 0x01d76e, 0x01d770, 0x01d788, 0x01d78a, 0x01d7a8, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7cb, 0x01df00, 0x01df09, 0x01df0b, 0x01df1e, + 0x01e900, 0x01e943, 0x01f130, 0x01f149, 0x01f150, 0x01f169, 0x01f170, 0x01f189)); } private static void populateDI() { @@ -2236,11 +2237,11 @@ private static void populateLOWER() { 0x00a7b5, 0x00a7b7, 0x00a7b7, 0x00a7b9, 0x00a7b9, 0x00a7bb, 0x00a7bb, 0x00a7bd, 0x00a7bd, 0x00a7bf, 0x00a7bf, 0x00a7c1, 0x00a7c1, 0x00a7c3, 0x00a7c3, 0x00a7c8, 0x00a7c8, 0x00a7ca, 0x00a7ca, 0x00a7d1, 0x00a7d1, 0x00a7d3, 0x00a7d3, 0x00a7d5, 0x00a7d5, 0x00a7d7, 0x00a7d7, 0x00a7d9, 0x00a7d9, 0x00a7f6, 0x00a7f6, 0x00a7f8, 0x00a7fa, 0x00ab30, 0x00ab5a, 0x00ab5c, 0x00ab68, 0x00ab70, 0x00abbf, 0x00fb00, 0x00fb06, 0x00fb13, 0x00fb17, 0x00ff41, 0x00ff5a, 0x010428, 0x01044f, 0x0104d8, 0x0104fb, 0x010597, 0x0105a1, - 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010cc0, 0x010cf2, 0x0118c0, 0x0118df, 0x016e60, 0x016e7f, 0x01d41a, 0x01d433, 0x01d44e, 0x01d454, 0x01d456, - 0x01d467, 0x01d482, 0x01d49b, 0x01d4b6, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, 0x01d4c5, 0x01d4cf, 0x01d4ea, 0x01d503, 0x01d51e, 0x01d537, 0x01d552, 0x01d56b, - 0x01d586, 0x01d59f, 0x01d5ba, 0x01d5d3, 0x01d5ee, 0x01d607, 0x01d622, 0x01d63b, 0x01d656, 0x01d66f, 0x01d68a, 0x01d6a5, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6e1, 0x01d6fc, - 0x01d714, 0x01d716, 0x01d71b, 0x01d736, 0x01d74e, 0x01d750, 0x01d755, 0x01d770, 0x01d788, 0x01d78a, 0x01d78f, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7c9, 0x01d7cb, 0x01d7cb, - 0x01df00, 0x01df09, 0x01df0b, 0x01df1e, 0x01e922, 0x01e943)); + 0x0105a3, 0x0105b1, 0x0105b3, 0x0105b9, 0x0105bb, 0x0105bc, 0x010780, 0x010780, 0x010783, 0x010785, 0x010787, 0x0107b0, 0x0107b2, 0x0107ba, 0x010cc0, 0x010cf2, 0x0118c0, + 0x0118df, 0x016e60, 0x016e7f, 0x01d41a, 0x01d433, 0x01d44e, 0x01d454, 0x01d456, 0x01d467, 0x01d482, 0x01d49b, 0x01d4b6, 0x01d4b9, 0x01d4bb, 0x01d4bb, 0x01d4bd, 0x01d4c3, + 0x01d4c5, 0x01d4cf, 0x01d4ea, 0x01d503, 0x01d51e, 0x01d537, 0x01d552, 0x01d56b, 0x01d586, 0x01d59f, 0x01d5ba, 0x01d5d3, 0x01d5ee, 0x01d607, 0x01d622, 0x01d63b, 0x01d656, + 0x01d66f, 0x01d68a, 0x01d6a5, 0x01d6c2, 0x01d6da, 0x01d6dc, 0x01d6e1, 0x01d6fc, 0x01d714, 0x01d716, 0x01d71b, 0x01d736, 0x01d74e, 0x01d750, 0x01d755, 0x01d770, 0x01d788, + 0x01d78a, 0x01d78f, 0x01d7aa, 0x01d7c2, 0x01d7c4, 0x01d7c9, 0x01d7cb, 0x01d7cb, 0x01df00, 0x01df09, 0x01df0b, 0x01df1e, 0x01e922, 0x01e943)); } private static void populateMATH() { From b73a890a00cb784896ce63c1afe4ff85ce43c70e Mon Sep 17 00:00:00 2001 From: Jirka Marsik Date: Wed, 29 Sep 2021 19:09:59 +0200 Subject: [PATCH 226/681] Update changelog for Unicode 14 --- regex/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/regex/CHANGELOG.md b/regex/CHANGELOG.md index 49f8154f8996..9a59d3b48c43 100644 --- a/regex/CHANGELOG.md +++ b/regex/CHANGELOG.md @@ -5,6 +5,7 @@ This changelog summarizes major changes between TRegex versions relevant to lang ## Version 22.0.0 * Added new `ASCII` encoding that callers can use when compiling a regex to limit the range of code point matches to [0x00, 0x7f]. +* Updated Unicode data (case-folding, character properties) to version 14 of the Unicode standard. ## Version 21.3.0 From 4b37ff269e155fe3187f3bb443153ef2fd1976eb Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 28 Sep 2021 17:47:41 -0700 Subject: [PATCH 227/681] Remove MultiTypeState.bb field. --- .../graal/pointsto/DefaultAnalysisPolicy.java | 2 +- .../graal/pointsto/PointsToAnalysis.java | 4 +-- .../graal/pointsto/flow/CloneTypeFlow.java | 4 +-- .../flow/DynamicNewInstanceTypeFlow.java | 2 +- .../oracle/graal/pointsto/flow/TypeFlow.java | 4 +-- .../pointsto/reports/AnalysisReporter.java | 5 +-- .../AbstractAnalysisResultsBuilder.java | 2 +- .../results/StaticAnalysisResultsBuilder.java | 2 +- .../pointsto/results/StrengthenGraphs.java | 3 +- .../pointsto/typestate/MultiTypeState.java | 18 ++++------ .../pointsto/typestate/PointsToStats.java | 6 ++-- .../pointsto/typestate/SingleTypeState.java | 2 +- .../graal/pointsto/typestate/TypeState.java | 32 ++++++++--------- .../svm/hosted/HostedConfiguration.java | 2 +- .../svm/hosted/NativeImageGenerator.java | 12 +++---- .../hosted/dashboard/PointsToJsonObject.java | 34 +++++++++---------- 16 files changed, 65 insertions(+), 69 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/DefaultAnalysisPolicy.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/DefaultAnalysisPolicy.java index 7b791018a845..7104dbb620e7 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/DefaultAnalysisPolicy.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/DefaultAnalysisPolicy.java @@ -189,7 +189,7 @@ public void onObservedUpdate(PointsToAnalysis bb) { receiverState = filterReceiverState(bb, receiverState); } - for (AnalysisType type : receiverState.types()) { + for (AnalysisType type : receiverState.types(bb)) { if (isSaturated()) { /*- * The receiver can become saturated during the callees linking, which saturates 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 b7eca5883197..d73228a53fc1 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 @@ -44,8 +44,6 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLongArray; -import com.oracle.graal.pointsto.flow.FieldTypeFlow; -import com.oracle.graal.pointsto.reports.StatisticsPrinter; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; @@ -63,6 +61,7 @@ import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; import com.oracle.graal.pointsto.flow.AllSynchronizedTypeFlow; +import com.oracle.graal.pointsto.flow.FieldTypeFlow; import com.oracle.graal.pointsto.flow.MethodTypeFlow; import com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder; import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.AbstractUnsafeLoadTypeFlow; @@ -76,6 +75,7 @@ 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.typestate.PointsToStats; import com.oracle.graal.pointsto.typestate.TypeState; import com.oracle.graal.pointsto.util.CompletionExecutor; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/CloneTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/CloneTypeFlow.java index 305ddef2ec71..a2eeea1dd95d 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/CloneTypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/CloneTypeFlow.java @@ -95,7 +95,7 @@ public void onObservedUpdate(PointsToAnalysis bb) { /* Nothing to be cloned if the input state is not a concrete type state. */ resultState = inputState.forNonNull(bb); } else { - resultState = inputState.typesStream() + resultState = inputState.typesStream(bb) .filter(t -> !currentState.containsType(t)) .map(type -> TypeState.forClone(bb, cloneSite, type, allocationContext)) .reduce(TypeState.forEmpty(), (s1, s2) -> TypeState.forUnion(bb, s1, s2)); @@ -115,7 +115,7 @@ public void update(PointsToAnalysis bb) { TypeState inputState = input.getState(); TypeState cloneState = this.getState(); - for (AnalysisType type : inputState.types()) { + for (AnalysisType type : inputState.types(bb)) { if (type.isArray()) { if (bb.analysisPolicy().aliasArrayTypeFlows()) { /* All arrays are aliased, no need to model the array clone operation. */ diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/DynamicNewInstanceTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/DynamicNewInstanceTypeFlow.java index 94684e7bfc2c..a3363ca105b5 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/DynamicNewInstanceTypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/DynamicNewInstanceTypeFlow.java @@ -92,7 +92,7 @@ public void onObservedUpdate(PointsToAnalysis bb) { TypeState currentTypeState = getState(); /* Generate a heap object for every new incoming type. */ - TypeState resultState = newTypeState.typesStream() + TypeState resultState = newTypeState.typesStream(bb) .filter(t -> !currentTypeState.containsType(t)) .map(type -> TypeState.forAllocation(bb, allocationSite, type, allocationContext)) .reduce(TypeState.forEmpty(), (s1, s2) -> TypeState.forUnion(bb, s1, s2)); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java index c39d8e98809c..164b1e9c59ce 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java @@ -245,7 +245,7 @@ public boolean isCloseToAllInstantiated(PointsToAnalysis bb) { public void setState(PointsToAnalysis bb, TypeState state) { assert !bb.extendedAsserts() || this instanceof InstanceOfTypeFlow || - state.verifyDeclaredType(declaredType) : "declaredType: " + declaredType.toJavaName(true) + " state: " + state; + state.verifyDeclaredType(bb, declaredType) : "declaredType: " + declaredType.toJavaName(true) + " state: " + state; this.state = state; } @@ -335,7 +335,7 @@ private boolean checkTypeState(PointsToAnalysis bb, TypeState before, TypeState */ return true; } - assert after.verifyDeclaredType(declaredType) : String.format("The type state of %s contains types that are not assignable from its declared type %s. " + + assert after.verifyDeclaredType(bb, declaredType) : String.format("The type state of %s contains types that are not assignable from its declared type %s. " + "%nState before: %s. %nState after: %s", format(false, true), declaredType.toJavaName(true), formatState(bb, before), formatState(bb, after)); return true; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReporter.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReporter.java index 934bc68b935c..c4439de06b6f 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReporter.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReporter.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.options.OptionValues; import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.typestate.PointsToStats; @@ -58,8 +59,8 @@ public static void printAnalysisReports(String imageName, OptionValues options, if (PointstoOptions.PrintSynchronizedAnalysis.getValue(options)) { TypeState allSynchronizedTypeState = bb.getAllSynchronizedTypeState(); - String typesString = allSynchronizedTypeState.closeToAllInstantiated(bb) ? "close to all instantiated" : // - StreamSupport.stream(allSynchronizedTypeState.types().spliterator(), false).map(AnalysisType::getName).collect(Collectors.joining(", ")); + String typesString = allSynchronizedTypeState.closeToAllInstantiated((PointsToAnalysis) bb) ? "close to all instantiated" : // + StreamSupport.stream(allSynchronizedTypeState.types(bb).spliterator(), false).map(AnalysisType::getName).collect(Collectors.joining(", ")); System.out.println(); System.out.println("AllSynchronizedTypes"); System.out.println("Synchronized types #: " + allSynchronizedTypeState.typesCount()); 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 d7f26876dc6c..6664431a1d04 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 @@ -127,7 +127,7 @@ private JavaTypeProfile cachedTypeProfile(JavaTypeProfile[] cache, int cacheIdx, private JavaTypeProfile createTypeProfile(TypeState typeState) { double probability = 1d / typeState.typesCount(); - JavaTypeProfile.ProfiledType[] pitems = typeState.typesStream() + JavaTypeProfile.ProfiledType[] pitems = typeState.typesStream(bb) .map(analysisType -> converter == null ? analysisType : converter.lookup(analysisType)) .sorted() .map(type -> new JavaTypeProfile.ProfiledType(type, probability)) 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 46ac547d7f32..de37df8331fb 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 @@ -163,7 +163,7 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { .forEach(monitorEnter -> { TypeState monitorEntryState = monitorEnter.getState(); String typesString = monitorEntryState.closeToAllInstantiated(bb) ? "close to all instantiated" - : StreamSupport.stream(monitorEntryState.types().spliterator(), false).map(AnalysisType::getName).collect(Collectors.joining(", ")); + : StreamSupport.stream(monitorEntryState.types(bb).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 9bf0bedcdb59..eed030e88e94 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 @@ -82,7 +82,6 @@ import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.typestate.TypeState; - import com.oracle.svm.util.ImageBuildStatistics; import jdk.vm.ci.meta.JavaKind; @@ -496,7 +495,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()) { + for (AnalysisType typeStateType : nodeTypeState.types(bb)) { if (oldType == null || (oldStamp.isExactType() ? oldType.equals(typeStateType) : oldType.isAssignableFrom(typeStateType))) { typeStateTypes.add(typeStateType); } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/MultiTypeState.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/MultiTypeState.java index a684cfefe6fc..ed9025dce0f5 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/MultiTypeState.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/MultiTypeState.java @@ -29,7 +29,6 @@ import java.util.Iterator; import com.oracle.graal.pointsto.BigBang; - import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.flow.context.object.AnalysisObject; import com.oracle.graal.pointsto.meta.AnalysisType; @@ -37,7 +36,6 @@ public class MultiTypeState extends TypeState { - protected final PointsToAnalysis bb; /** The objects of this type state. */ protected final AnalysisObject[] objects; /** See {@link #getObjectTypeIds()}. */ @@ -58,7 +56,6 @@ public class MultiTypeState extends TypeState { /** Creates a new type state using the provided types bit set and objects. */ MultiTypeState(PointsToAnalysis bb, boolean canBeNull, int properties, BitSet typesBitSet, AnalysisObject... objects) { super(properties); - this.bb = bb; this.objects = objects; /* * Trim the typesBitSet to size eagerly. The typesBitSet is effectively immutable, i.e., no @@ -81,14 +78,13 @@ public class MultiTypeState extends TypeState { this.merged = false; assert typesCount > 1 : "Multi type state with single type."; assert objects.length > 1 : "Multi type state with single object."; - assert !bb.extendedAsserts() || checkObjects(); + assert !bb.extendedAsserts() || checkObjects(bb); PointsToStats.registerTypeState(bb, this); } /** Create a type state with the same content and a reversed canBeNull value. */ private MultiTypeState(PointsToAnalysis bb, boolean canBeNull, MultiTypeState other) { super(other.properties); - this.bb = bb; this.objects = other.objects; this.typesBitSet = other.typesBitSet; this.typesCount = other.typesCount; @@ -115,7 +111,7 @@ public int[] getObjectTypeIds() { return objectTypeIds; } - private boolean checkObjects() { + private boolean checkObjects(PointsToAnalysis bb) { assert bb.extendedAsserts(); for (int idx = 0; idx < objects.length - 1; idx++) { @@ -178,7 +174,7 @@ AnalysisType lastType() { * by way of bit set iteration. */ @Override - public Iterator typesIterator() { + public Iterator typesIterator(BigBang bb) { return new Iterator() { /** Initialize to the index of the first set bit. */ @@ -204,7 +200,7 @@ public boolean containsType(AnalysisType exactType) { } @Override - public TypeState exactTypeState(PointsToAnalysis unused, AnalysisType exactType) { + public TypeState exactTypeState(PointsToAnalysis bb, AnalysisType exactType) { if (containsType(exactType)) { AnalysisObject[] resultObjects = objectsArray(exactType); return new SingleTypeState(bb, canBeNull, bb.analysisPolicy().makeProperties(bb, resultObjects), resultObjects); @@ -214,7 +210,7 @@ public TypeState exactTypeState(PointsToAnalysis unused, AnalysisType exactType) } @Override - public TypeState forCanBeNull(PointsToAnalysis unused, boolean resultCanBeNull) { + public TypeState forCanBeNull(PointsToAnalysis bb, boolean resultCanBeNull) { if (resultCanBeNull == this.canBeNull()) { return this; } else { @@ -318,7 +314,7 @@ public final boolean canBeNull() { /** Note that the objects of this type state have been merged. */ @Override - public void noteMerge(PointsToAnalysis unused) { + public void noteMerge(PointsToAnalysis bb) { assert bb.analysisPolicy().isMergingEnabled(); if (!merged) { @@ -330,7 +326,7 @@ public void noteMerge(PointsToAnalysis unused) { } @Override - public boolean closeToAllInstantiated(BigBang unused) { + public boolean closeToAllInstantiated(PointsToAnalysis bb) { if (typesCount > 200) { MultiTypeState allInstState = (MultiTypeState) bb.getAllInstantiatedTypes(); return typesCount * 100L / allInstState.typesCount > 75; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/PointsToStats.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/PointsToStats.java index 896ff2873c10..35abaad83559 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/PointsToStats.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/PointsToStats.java @@ -43,10 +43,10 @@ import java.util.function.Function; import java.util.stream.Collectors; -import com.oracle.graal.pointsto.BigBang; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.nodes.ValueNode; +import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.flow.ActualReturnTypeFlow; import com.oracle.graal.pointsto.flow.AllInstantiatedTypeFlow; @@ -628,7 +628,7 @@ private static String formatType(AnalysisType type, boolean qualified) { } @SuppressWarnings("unused") - private static String asDetailedString(TypeState s) { + private static String asDetailedString(BigBang bb, TypeState s) { if (s.isEmpty()) { return ""; } @@ -637,7 +637,7 @@ private static String asDetailedString(TypeState s) { } String canBeNull = s.canBeNull() ? "null" : "!null"; - String types = s.typesStream().map(JavaType::getUnqualifiedName).sorted().collect(Collectors.joining(", ")); + String types = s.typesStream(bb).map(JavaType::getUnqualifiedName).sorted().collect(Collectors.joining(", ")); return canBeNull + ", " + types; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/SingleTypeState.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/SingleTypeState.java index 1ab6c96127eb..7dd0cc8b1e84 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/SingleTypeState.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/SingleTypeState.java @@ -106,7 +106,7 @@ public AnalysisType exactType() { } @Override - protected Iterator typesIterator() { + protected Iterator typesIterator(BigBang bb) { return new Iterator() { boolean hasNext = true; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeState.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeState.java index 9aa59deafd57..40864e26be70 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeState.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeState.java @@ -33,8 +33,8 @@ import java.util.stream.StreamSupport; import com.oracle.graal.pointsto.AnalysisPolicy; -import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.flow.context.AnalysisContext; import com.oracle.graal.pointsto.flow.context.BytecodeLocation; @@ -77,16 +77,16 @@ public int getProperties() { public abstract AnalysisType exactType(); /** Provides an iterator over the types. */ - protected abstract Iterator typesIterator(); + protected abstract Iterator typesIterator(BigBang bb); /** Provides an iterable for the types for easy "for-each loop" iteration. */ - public Iterable types() { - return this::typesIterator; + public Iterable types(BigBang bb) { + return () -> typesIterator(bb); } /** Provides a stream for the types. */ - public Stream typesStream() { - return StreamSupport.stream(types().spliterator(), false); + public Stream typesStream(BigBang bb) { + return StreamSupport.stream(types(bb).spliterator(), false); } /** Returns true if this type state contains the type, otherwise it returns false. */ @@ -240,9 +240,9 @@ public void noteMerge(@SuppressWarnings("unused") PointsToAnalysis bb) { */ public abstract TypeState exactTypeState(PointsToAnalysis bb, AnalysisType exactType); - public boolean verifyDeclaredType(AnalysisType declaredType) { + public boolean verifyDeclaredType(BigBang bb, AnalysisType declaredType) { if (declaredType != null) { - for (AnalysisType e : types()) { + for (AnalysisType e : types(bb)) { if (!declaredType.isAssignableFrom(e)) { return false; } @@ -255,7 +255,7 @@ public boolean verifyDeclaredType(AnalysisType declaredType) { * The {@link MultiTypeState} overrides this method and provides the proper test. All the other * type states have only 0 or 1 types. */ - public boolean closeToAllInstantiated(@SuppressWarnings("unused") BigBang bb) { + public boolean closeToAllInstantiated(@SuppressWarnings("unused") PointsToAnalysis bb) { return false; } @@ -386,7 +386,7 @@ public static TypeState forContextInsensitiveTypeState(PointsToAnalysis bb, Type AnalysisObject[] objectsArray = new AnalysisObject[multiState.typesCount()]; int i = 0; - for (AnalysisType type : multiState.types()) { + for (AnalysisType type : multiState.types(bb)) { objectsArray[i++] = type.getContextInsensitiveAnalysisObject(); } /* @@ -437,7 +437,7 @@ public static TypeState forIntersection(PointsToAnalysis bb, TypeState s1, TypeS * All filtered types (s1) must be marked as instantiated to ensures that the filter state * (s2) has been updated before a type appears in the input, otherwise types can be missed. */ - assert !bb.extendedAsserts() || checkTypes(s1); + assert !bb.extendedAsserts() || checkTypes(bb, s1); if (s1.isEmpty()) { return s1; } else if (s1.isNull()) { @@ -463,7 +463,7 @@ public static TypeState forSubtraction(PointsToAnalysis bb, TypeState s1, TypeSt * All filtered types (s1) must be marked as instantiated to ensures that the filter state * (s2) has been updated before a type appears in the input, otherwise types can be missed. */ - assert !bb.extendedAsserts() || checkTypes(s1); + assert !bb.extendedAsserts() || checkTypes(bb, s1); if (s1.isEmpty()) { return s1; } else if (s1.isNull()) { @@ -484,8 +484,8 @@ public static TypeState forSubtraction(PointsToAnalysis bb, TypeState s1, TypeSt } } - private static boolean checkTypes(TypeState state) { - for (AnalysisType type : state.types()) { + private static boolean checkTypes(BigBang bb, TypeState state) { + for (AnalysisType type : state.types(bb)) { if (!type.isInstantiated()) { System.out.println("Processing a type not yet marked as instantiated: " + type.getName()); return false; @@ -1416,7 +1416,7 @@ public int typesCount() { } @Override - public Iterator typesIterator() { + public Iterator typesIterator(BigBang bb) { return Collections.emptyIterator(); } @@ -1507,7 +1507,7 @@ public int typesCount() { } @Override - public Iterator typesIterator() { + public Iterator typesIterator(BigBang bb) { return Collections.emptyIterator(); } 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 406c6e8ca7d8..4e7930ba7365 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 @@ -207,7 +207,7 @@ private static Set getForceMonitorSlotTypes(BigBang bb) { /** Process the types that the analysis found as needing synchronization. */ protected void processedSynchronizedTypes(BigBang bb, HostedUniverse hUniverse, Set immutableTypes) { TypeState allSynchronizedTypeState = bb.getAllSynchronizedTypeState(); - for (AnalysisType type : allSynchronizedTypeState.types()) { + for (AnalysisType type : allSynchronizedTypeState.types(bb)) { maybeSetMonitorField(hUniverse, immutableTypes, 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 5ef607941bab..b01843f59fa6 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 @@ -1419,8 +1419,8 @@ private static boolean addAssertionLIRPhases(LIRSuites lirSuites, boolean hosted return true; } - private static String format(TypeState state) { - return state.typesStream().map(t -> t.toJavaName(true)).collect(Collectors.joining(",")); + private static String format(BigBang bb, TypeState state) { + return state.typesStream(bb).map(t -> t.toJavaName(true)).collect(Collectors.joining(",")); } private void checkUniverse() { @@ -1446,8 +1446,8 @@ private void checkUniverse() { String methodKey = method.format("%H.%n(%p)"); bigbang.getUnsupportedFeatures().addMessage(methodKey, method, "Parameter " + i + " of " + methodKey + " has declared type " + declaredType.toJavaName(true) + - ", with assignable types: " + format(declaredTypeState) + - ", which is incompatible with analysis inferred types: " + format(parameterState) + "."); + ", with assignable types: " + format(bb, declaredTypeState) + + ", which is incompatible with analysis inferred types: " + format(bb, parameterState) + "."); } } } @@ -1464,8 +1464,8 @@ private void checkUniverse() { String fieldKey = field.format("%H.%n"); bigbang.getUnsupportedFeatures().addMessage(fieldKey, null, "Field " + fieldKey + " has declared type " + declaredType.toJavaName(true) + - ", with assignable types: " + format(declaredTypeState) + - ", which is incompatible with analysis inferred types: " + format(state) + "."); + ", with assignable types: " + format(bb, declaredTypeState) + + ", which is incompatible with analysis inferred types: " + format(bb, state) + "."); } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/dashboard/PointsToJsonObject.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/dashboard/PointsToJsonObject.java index d843b675b506..60de2504feb7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/dashboard/PointsToJsonObject.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/dashboard/PointsToJsonObject.java @@ -36,11 +36,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import com.oracle.graal.pointsto.BigBang; import org.graalvm.graphio.GraphOutput; import org.graalvm.graphio.GraphStructure; import org.graalvm.nativeimage.hosted.Feature.OnAnalysisExitAccess; +import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.flow.ActualParameterTypeFlow; import com.oracle.graal.pointsto.flow.ActualReturnTypeFlow; @@ -596,7 +596,7 @@ private WrapperClazz(Class wrappedClass, int inputs, int uses, String name) { */ private void serializeMethods(BigBang bb) { for (AnalysisMethod method : bb.getUniverse().getMethods()) { - serializeMethod(new AnalysisWrapper(method.getClass(), method)); + serializeMethod(bb, new AnalysisWrapper(method.getClass(), method)); } } @@ -605,7 +605,7 @@ private void serializeMethods(BigBang bb) { * * @param methodWrapper wrapped AnalysisMethod whose type flows to serialize */ - private void serializeMethod(AnalysisWrapper methodWrapper) { + private void serializeMethod(BigBang bb, AnalysisWrapper methodWrapper) { assert !known.get(methodWrapper.id); known.set(methodWrapper.id); flows.set(methodWrapper.id, methodWrapper); @@ -622,7 +622,7 @@ private void serializeMethod(AnalysisWrapper methodWrapper) { } // Serialize this type flow to a JSON object, add it to the node index. - serializeTypeFlow(flow); + serializeTypeFlow(bb, flow); } } @@ -638,7 +638,7 @@ private void serializeMethod(AnalysisWrapper methodWrapper) { * * @param flow TypeFlow to serialize */ - private void serializeTypeFlow(TypeFlow flow) { + private void serializeTypeFlow(BigBang bb, TypeFlow flow) { int flowId = flow.id(); if (known.get(flowId)) { @@ -661,13 +661,13 @@ private void serializeTypeFlow(TypeFlow flow) { flowWrapper.calleeNames.add(callee.getQualifiedName()); } } else if (flow instanceof NewInstanceTypeFlow || flow instanceof DynamicNewInstanceTypeFlow) { - flowWrapper.types = serializeTypeState(flow.getState()); + flowWrapper.types = serializeTypeState(bb, flow.getState()); } else if (flow instanceof LoadFieldTypeFlow.LoadInstanceFieldTypeFlow || flow instanceof LoadFieldTypeFlow.LoadStaticFieldTypeFlow) { LoadFieldTypeFlow loadFlow = (LoadFieldTypeFlow) flow; flowWrapper.qualifiedName = fieldName(loadFlow.field()); } else if (flow instanceof StoreFieldTypeFlow.StoreInstanceFieldTypeFlow || flow instanceof StoreFieldTypeFlow.StoreStaticFieldTypeFlow) { TypeState typeState = flow.getState(); - flowWrapper.types = serializeTypeState(typeState); + flowWrapper.types = serializeTypeState(bb, typeState); StoreFieldTypeFlow storeFlow = (StoreFieldTypeFlow) flow; flowWrapper.qualifiedName = fieldName(storeFlow.field()); } else if (flow instanceof FieldTypeFlow) { @@ -678,8 +678,8 @@ private void serializeTypeFlow(TypeFlow flow) { } // Set inputs and uses for this node. - collectInputs(flow, flowWrapper.inputs); - collectUses(flow, flowWrapper.uses); + collectInputs(bb, flow, flowWrapper.inputs); + collectUses(bb, flow, flowWrapper.uses); } /** @@ -775,20 +775,20 @@ private static String getCodeLocation(TypeFlow flow) { * @param flow TypeFlow who's inputs and observees to collect * @param targetList target array for input use and observee IDs to */ - private void collectInputs(TypeFlow flow, Map targetList) { + private void collectInputs(BigBang bb, TypeFlow flow, Map targetList) { for (Object input : flow.getInputs()) { TypeFlow inputFlow = (TypeFlow) input; addUnique(targetList, inputFlow.id()); // Indirect recursive call. Call with methodId = -1 to indicate that, at this point, // we don't know the method ID of the parent methods of the input flows. - serializeTypeFlow(inputFlow); + serializeTypeFlow(bb, inputFlow); } for (Object observee : flow.getObservees()) { TypeFlow observeeFlow = (TypeFlow) observee; addUnique(targetList, observeeFlow.id()); // Indirect recursive call. Call with methodId = -1 to indicate that, at this point, // we don't know the method ID of the parent methods of the observee flows. - serializeTypeFlow(observeeFlow); + serializeTypeFlow(bb, observeeFlow); } } @@ -800,20 +800,20 @@ private void collectInputs(TypeFlow flow, Map targetList) { * @param flow TypeFlow who's uses and observers to collect * @param targetList target list for adding use and observer IDs to */ - private void collectUses(TypeFlow flow, Map targetList) { + private void collectUses(BigBang bb, TypeFlow flow, Map targetList) { for (Object use : flow.getUses()) { TypeFlow useFlow = (TypeFlow) use; addUnique(targetList, useFlow.id()); // Indirect recursive call. Call with methodId = -1 to indicate that, at this point, // we don't know the method ID of the parent methods of the use flows. - serializeTypeFlow(useFlow); + serializeTypeFlow(bb, useFlow); } for (Object observer : flow.getObservers()) { TypeFlow observerFlow = (TypeFlow) observer; addUnique(targetList, observerFlow.id()); // Indirect recursive call. Call with methodId = -1 to indicate that, at this point, // we don't know the method ID of the parent methods of the observer flows. - serializeTypeFlow(observerFlow); + serializeTypeFlow(bb, observerFlow); } } @@ -834,9 +834,9 @@ private static void addUnique(Map list, T element) { * @param typeState the TypeState to be serialized. * @return a list of the formatted class names of the classes included in the given TypeState. */ - private static ArrayList serializeTypeState(TypeState typeState) { + private static ArrayList serializeTypeState(BigBang bb, TypeState typeState) { ArrayList types = new ArrayList<>(); - for (AnalysisType type : typeState.types()) { + for (AnalysisType type : typeState.types(bb)) { types.add(type.toJavaName()); } return types; From a067cad36009b265cddd94847de5d9287918caee Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Wed, 29 Sep 2021 18:50:14 -0700 Subject: [PATCH 228/681] Refactor closeToAllInstantiated. --- .../graal/pointsto/flow/MethodTypeFlowBuilder.java | 5 +---- .../src/com/oracle/graal/pointsto/flow/TypeFlow.java | 7 ++----- .../graal/pointsto/reports/AnalysisReporter.java | 3 ++- .../pointsto/results/StaticAnalysisResultsBuilder.java | 3 ++- .../graal/pointsto/typestate/MultiTypeState.java | 10 ---------- .../com/oracle/graal/pointsto/typestate/TypeState.java | 8 -------- .../graal/pointsto/typestate/TypeStateUtils.java | 8 ++++++++ 7 files changed, 15 insertions(+), 29 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java index 58e5bc85844e..1f2c7ec381ce 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java @@ -779,10 +779,7 @@ protected void node(FixedNode n) { } else { /* * Without precise type information the dynamic new instance node has to - * generate a heap object for each instantiated type. This means that the source - * flow for dynamic new instance is 'close to all instantiated' and will be - * reduced to abstract objects, unless - * BootImageAnalysisOptions.ReduceCloseToAllInstantiatedFlows is disabled. + * generate a heap object for each instantiated type. */ instanceType = bb.getObjectType(); instanceTypeBuilder = TypeFlowBuilder.create(bb, instanceType, AllInstantiatedTypeFlow.class, () -> { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java index 164b1e9c59ce..74800ec5f649 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java @@ -39,6 +39,7 @@ import com.oracle.graal.pointsto.results.StaticAnalysisResultsBuilder; import com.oracle.graal.pointsto.typestate.PointsToStats; import com.oracle.graal.pointsto.typestate.TypeState; +import com.oracle.graal.pointsto.typestate.TypeStateUtils; import com.oracle.graal.pointsto.util.CompletionExecutor.DebugContextRunnable; import com.oracle.graal.pointsto.util.ConcurrentLightHashSet; import com.oracle.svm.util.ClassUtil; @@ -239,10 +240,6 @@ public boolean isAllInstantiated() { return this instanceof AllInstantiatedTypeFlow; } - public boolean isCloseToAllInstantiated(PointsToAnalysis bb) { - return this.getState().closeToAllInstantiated(bb); - } - public void setState(PointsToAnalysis bb, TypeState state) { assert !bb.extendedAsserts() || this instanceof InstanceOfTypeFlow || state.verifyDeclaredType(bb, declaredType) : "declaredType: " + declaredType.toJavaName(true) + " state: " + state; @@ -341,7 +338,7 @@ private boolean checkTypeState(PointsToAnalysis bb, TypeState before, TypeState } private static String formatState(PointsToAnalysis bb, TypeState typeState) { - if (typeState.closeToAllInstantiated(bb)) { + if (TypeStateUtils.closeToAllInstantiated(bb, typeState)) { return "close to AllInstantiated"; } return typeState.toString(); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReporter.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReporter.java index c4439de06b6f..c1bd31aa2efe 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReporter.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReporter.java @@ -36,6 +36,7 @@ import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.typestate.PointsToStats; import com.oracle.graal.pointsto.typestate.TypeState; +import com.oracle.graal.pointsto.typestate.TypeStateUtils; public class AnalysisReporter { public static void printAnalysisReports(String imageName, OptionValues options, String reportsPath, BigBang bb) { @@ -59,7 +60,7 @@ public static void printAnalysisReports(String imageName, OptionValues options, if (PointstoOptions.PrintSynchronizedAnalysis.getValue(options)) { TypeState allSynchronizedTypeState = bb.getAllSynchronizedTypeState(); - String typesString = allSynchronizedTypeState.closeToAllInstantiated((PointsToAnalysis) bb) ? "close to all instantiated" : // + String typesString = TypeStateUtils.closeToAllInstantiated((PointsToAnalysis) bb, allSynchronizedTypeState) ? "close to all instantiated" : // StreamSupport.stream(allSynchronizedTypeState.types(bb).spliterator(), false).map(AnalysisType::getName).collect(Collectors.joining(", ")); System.out.println(); System.out.println("AllSynchronizedTypes"); 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 de37df8331fb..32ed909ecabf 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 @@ -47,6 +47,7 @@ import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.results.StaticAnalysisResults.BytecodeEntry; import com.oracle.graal.pointsto.typestate.TypeState; +import com.oracle.graal.pointsto.typestate.TypeStateUtils; import jdk.vm.ci.meta.JavaMethodProfile; import jdk.vm.ci.meta.JavaTypeProfile; @@ -162,7 +163,7 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod method) { .sorted(Comparator.comparingInt(m2 -> m2.getState().typesCount())) .forEach(monitorEnter -> { TypeState monitorEntryState = monitorEnter.getState(); - String typesString = monitorEntryState.closeToAllInstantiated(bb) ? "close to all instantiated" + String typesString = TypeStateUtils.closeToAllInstantiated(bb, monitorEntryState) ? "close to all instantiated" : StreamSupport.stream(monitorEntryState.types(bb).spliterator(), false).map(AnalysisType::getName).collect(Collectors.joining(", ")); StringBuilder strb = new StringBuilder(); strb.append("Location: "); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/MultiTypeState.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/MultiTypeState.java index ed9025dce0f5..722f844d2ea4 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/MultiTypeState.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/MultiTypeState.java @@ -325,16 +325,6 @@ public void noteMerge(PointsToAnalysis bb) { } } - @Override - public boolean closeToAllInstantiated(PointsToAnalysis bb) { - if (typesCount > 200) { - MultiTypeState allInstState = (MultiTypeState) bb.getAllInstantiatedTypes(); - return typesCount * 100L / allInstState.typesCount > 75; - } - - return false; - } - @Override public int hashCode() { int result = 1; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeState.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeState.java index 40864e26be70..43dde5bf1f3e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeState.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeState.java @@ -251,14 +251,6 @@ public boolean verifyDeclaredType(BigBang bb, AnalysisType declaredType) { return true; } - /** - * The {@link MultiTypeState} overrides this method and provides the proper test. All the other - * type states have only 0 or 1 types. - */ - public boolean closeToAllInstantiated(@SuppressWarnings("unused") PointsToAnalysis bb) { - return false; - } - @Override public int hashCode() { return super.hashCode(); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeStateUtils.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeStateUtils.java index 84070f087493..32555ed4b2cc 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeStateUtils.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/TypeStateUtils.java @@ -384,4 +384,12 @@ protected static BitSet set(BitSet bs1, int bitIndex) { return bsr; } + public static boolean closeToAllInstantiated(PointsToAnalysis bb, TypeState state) { + if (state.typesCount() > 200) { + MultiTypeState allInstState = (MultiTypeState) bb.getAllInstantiatedTypes(); + return state.typesCount() * 100L / allInstState.typesCount() > 75; + } + return false; + } + } From d1c80bfdb6d4d742b3f88496ed9515ee39a4a8d1 Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Thu, 30 Sep 2021 07:43:27 +0200 Subject: [PATCH 229/681] improve handling of VM_DEATH event and make sure we include a specific reply and apply suspend policy if the event was requested --- .../espresso/jdwp/api/VMEventListener.java | 4 +-- .../jdwp/api/VMEventListenerImpl.java | 28 +++++++++++++------ .../jdwp/impl/DebuggerController.java | 5 +++- .../espresso/jdwp/impl/JDWPInstrument.java | 10 +++---- .../jdwp/impl/RequestedJDWPEvents.java | 4 +-- .../espresso/jdwp/impl/SocketConnection.java | 15 ++++++++++ 6 files changed, 48 insertions(+), 18 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListener.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListener.java index bfd654e7dda2..0dad3f93ef25 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListener.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListener.java @@ -37,7 +37,7 @@ public interface VMEventListener extends VMListener { void breakpointHit(BreakpointInfo info, CallFrame frame, Object currentThread); - void vmDied(); + boolean vmDied(); void addClassUnloadRequestId(int id); @@ -47,7 +47,7 @@ public interface VMEventListener extends VMListener { void addVMStartRequest(int id); - void addVMDeathRequest(int id); + void addVMDeathRequest(int id, byte suspendPolicy); void addClassPrepareRequest(ClassPrepareRequest request); diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java index 78a4963c1088..75b298918783 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java @@ -78,6 +78,7 @@ public final class VMEventListenerImpl implements VMEventListener { private byte threadStartSuspendPolicy; private byte threadDeathSuspendPolicy; private int vmDeathRequestId; + private byte vmDeathSuspendPolicy = SuspendStrategy.NONE; private int vmStartRequestId; private final List heldEvents = new ArrayList<>(); private final Map currentContendedMonitor = new HashMap<>(); @@ -891,17 +892,27 @@ public void vmStarted(boolean suspend) { } @Override - public void vmDied() { + public boolean vmDied() { if (connection == null) { - return; + return false; } PacketStream stream = new PacketStream().commandPacket().commandSet(64).command(100); - stream.writeByte(SuspendStrategy.NONE); - stream.writeInt(1); + stream.writeByte(vmDeathSuspendPolicy); + if (vmDeathRequestId != 0) { + stream.writeInt(2); + // requested event + stream.writeByte(RequestedJDWPEvents.VM_DEATH); + stream.writeInt(vmDeathRequestId); + // automatic event + } else { + // only automatic event to send + stream.writeInt(1); + } stream.writeByte(RequestedJDWPEvents.VM_DEATH); - stream.writeInt(vmDeathRequestId != -1 ? vmDeathRequestId : 0); + stream.writeInt(0); // don't queue this packet, send immediately connection.sendVMDied(stream); + return vmDeathSuspendPolicy != SuspendStrategy.NONE; } @Override @@ -937,13 +948,14 @@ public void removeThreadDiedRequestId() { } @Override - public void addVMDeathRequest(int id) { - this.vmStartRequestId = id; + public void addVMDeathRequest(int id, byte suspendPolicy) { + this.vmDeathRequestId = id; + this.vmDeathSuspendPolicy = suspendPolicy; } @Override public void addVMStartRequest(int id) { - this.vmDeathRequestId = id; + this.vmStartRequestId = id; } @Override diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java index eb4e8c8ffa6b..f65ab0b5eaa0 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java @@ -467,7 +467,10 @@ public void disposeDebugger(boolean prepareReconnect) { if (!prepareReconnect) { // OK, we're closing down the context which is equivalent // to a dead VM from a JDWP client point of view - eventListener.vmDied(); + if(eventListener.vmDied()) { + // we're asked to suspend + suspend(null, context.asGuestThread(Thread.currentThread()), SuspendStrategy.EVENT_THREAD, Collections.emptyList(), null, false); + } } // Creating a new thread, because the reset method // will interrupt all active jdwp threads, which might diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWPInstrument.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWPInstrument.java index b74b1bf46b9a..149b6d000823 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWPInstrument.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWPInstrument.java @@ -58,11 +58,6 @@ protected void onCreate(TruffleInstrument.Env instrumentEnv) { } public void reset(boolean prepareForReconnect) { - // close the connection to the debugger - if (connection != null) { - connection.close(); - } - // stop all running jdwp threads in an orderly fashion for (Thread activeThread : activeThreads) { activeThread.interrupt(); @@ -93,6 +88,11 @@ public void reset(boolean prepareForReconnect) { // resume all threads controller.resumeAll(true); + // close the connection to the debugger + if (connection != null) { + connection.close(); + } + if (prepareForReconnect) { // replace the controller instance controller.reInitialize(); diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/RequestedJDWPEvents.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/RequestedJDWPEvents.java index 324fb472edfc..c77e71fb4a62 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/RequestedJDWPEvents.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/RequestedJDWPEvents.java @@ -168,8 +168,8 @@ public CommandResult registerEvent(Packet packet, Commands callback) { case VM_START: // no debuggers should ask for this event eventListener.addVMStartRequest(packet.id); break; - case VM_DEATH: // no debuggers should request this event - eventListener.addVMDeathRequest(packet.id); + case VM_DEATH: + eventListener.addVMDeathRequest(packet.id, suspendPolicy); break; case MONITOR_CONTENDED_ENTER: eventListener.addMonitorContendedEnterRequest(packet.id, filter); diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/SocketConnection.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/SocketConnection.java index 68a266fcd276..e89797f29ead 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/SocketConnection.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/SocketConnection.java @@ -51,10 +51,25 @@ public final class SocketConnection implements Runnable { } public void close() throws IOException { + // send outstanding packets before closing + while (!queue.isEmpty()) { + for (PacketStream packetStream : queue) { + byte[] shipment = packetStream.prepareForShipment(); + try { + writePacket(shipment); + } catch (ConnectionClosedException e) { + JDWP.LOGGER.finest("connection was closed when trying to flush queue"); + } + } + } + socketOutput.flush(); + synchronized (closeLock) { if (closed) { return; } + JDWP.LOGGER.fine("closing socket now"); + if (serverSocket != null) { serverSocket.close(); } From 9b84745e209190546d2ee3d2242ede006f9f8e6f Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Thu, 30 Sep 2021 10:30:54 +0200 Subject: [PATCH 230/681] implement jdwp commands relating to Java 9+ modules --- .../truffle/espresso/jdwp/api/ErrorCodes.java | 1 + .../espresso/jdwp/api/JDWPContext.java | 7 ++ .../truffle/espresso/jdwp/api/KlassRef.java | 7 ++ .../truffle/espresso/jdwp/api/ModuleRef.java | 45 ++++++++ .../jdwp/impl/DebuggerConnection.java | 19 ++++ .../truffle/espresso/jdwp/impl/JDWP.java | 105 ++++++++++++++++++ .../espresso/impl/ClassRegistries.java | 15 +++ .../truffle/espresso/impl/EntryTable.java | 6 + .../oracle/truffle/espresso/impl/Klass.java | 6 + .../truffle/espresso/impl/ModuleTable.java | 17 ++- .../espresso/runtime/JDWPContextImpl.java | 6 + 11 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ModuleRef.java diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ErrorCodes.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ErrorCodes.java index 7f1c44d8eea9..4b1e417b2650 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ErrorCodes.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ErrorCodes.java @@ -35,6 +35,7 @@ public final class ErrorCodes { public static final int INVALID_FRAMEID = 30; public static final int OPAQUE_FRAME = 32; public static final int INVALID_SLOT = 35; + public static final int INVALID_MODULE = 42; public static final int INVALID_CLASS_FORMAT = 60; public static final int FAILS_VERIFICATION = 62; public static final int ADD_METHOD_NOT_IMPLEMENTED = 63; diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java index e5f3aa2f2cb5..7c2ff2dba891 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java @@ -505,4 +505,11 @@ public interface JDWPContext { * @return true is guest object is a member of the klass */ boolean isMemberOf(Object guestObject, KlassRef klass); + + /** + * Returns all defined modules. + * @return all modules + */ + ModuleRef[] getAllModulesRefs(); + } diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/KlassRef.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/KlassRef.java index c78f0c8ce3ad..4af2cd86c195 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/KlassRef.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/KlassRef.java @@ -181,4 +181,11 @@ public interface KlassRef { * @return the extension */ String getSourceDebugExtension(); + + /** + * Returns the Module reference of the class. + * + * @return the module reference + */ + ModuleRef getModule(); } diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ModuleRef.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ModuleRef.java new file mode 100644 index 000000000000..4e55f6636592 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ModuleRef.java @@ -0,0 +1,45 @@ +/* + * 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. + * + * 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.truffle.espresso.jdwp.api; + +/** + * Interface representing a module reference in the VM. + */ +public interface ModuleRef { + + ModuleRef[] EMPTY_ARRAY = new ModuleRef[0]; + + /** + * Returns the name of the module. + * + * @return module name + */ + String name(); + + /** + * Returns the guest object representing the defining classloader of the module. + * + * @return the defining classloader + */ + Object classLoader(); +} diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java index 68f1a7f4294f..62f975da6cdf 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java @@ -286,6 +286,9 @@ private void processPacket(Packet packet) { case JDWP.VirtualMachine.INSTANCE_COUNTS.ID: result = JDWP.VirtualMachine.INSTANCE_COUNTS.createReply(packet); break; + case JDWP.VirtualMachine.ALL_MODULES.ID: + result = JDWP.VirtualMachine.ALL_MODULES.createReply(packet, context); + break; default: break; } @@ -347,6 +350,9 @@ private void processPacket(Packet packet) { case JDWP.ReferenceType.CONSTANT_POOL.ID: result = JDWP.ReferenceType.CONSTANT_POOL.createReply(packet, context); break; + case JDWP.ReferenceType.MODULE.ID: + result = JDWP.ReferenceType.MODULE.createReply(packet, context); + break; } break; } @@ -571,6 +577,19 @@ private void processPacket(Packet packet) { } break; } + case JDWP.ModuleReference.ID: { + switch (packet.cmd) { + case JDWP.ModuleReference.NAME.ID: + result = JDWP.ModuleReference.NAME.createReply(packet, context); + break; + case JDWP.ModuleReference.CLASSLOADER.ID: + result = JDWP.ModuleReference.CLASSLOADER.createReply(packet, context); + break; + default: + break; + } + break; + } case JDWP.Event.ID: { switch (packet.cmd) { case JDWP.Event.COMPOSITE.ID: diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java index ba6a26c0d1c6..c48448e67950 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java @@ -43,6 +43,7 @@ import com.oracle.truffle.espresso.jdwp.api.LineNumberTableRef; import com.oracle.truffle.espresso.jdwp.api.LocalRef; import com.oracle.truffle.espresso.jdwp.api.MethodRef; +import com.oracle.truffle.espresso.jdwp.api.ModuleRef; import com.oracle.truffle.espresso.jdwp.api.MonitorStackInfo; import com.oracle.truffle.espresso.jdwp.api.RedefineInfo; import com.oracle.truffle.espresso.jdwp.api.TagConstants; @@ -465,6 +466,21 @@ static CommandResult createReply(Packet packet) { return new CommandResult(reply); } } + + static class ALL_MODULES { + public static final int ID = 22; + + static CommandResult createReply(Packet packet, JDWPContext context) { + PacketStream reply = new PacketStream().replyPacket().id(packet.id); + + ModuleRef[] moduleRefs = context.getAllModulesRefs(); + reply.writeInt(moduleRefs.length); + for (ModuleRef moduleRef : moduleRefs) { + reply.writeLong(context.getIds().getIdAsLong(moduleRef)); + } + return new CommandResult(reply); + } + } } static class ReferenceType { @@ -976,6 +992,35 @@ static CommandResult createReply(Packet packet, JDWPContext context) { return new CommandResult(reply); } } + + static class MODULE { + + public static final int ID = 19; + + static CommandResult createReply(Packet packet, JDWPContext context) { + PacketStream input = new PacketStream(packet); + PacketStream reply = new PacketStream().replyPacket().id(packet.id); + + long typeId = input.readLong(); + KlassRef klass = verifyRefType(typeId, reply, context); + + if (klass == null) { + // input could be a classObjectId + Object object = context.getIds().fromId((int) typeId); + klass = context.getReflectedType(object); + } + + if (klass == null) { + return new CommandResult(reply); + } + + ModuleRef module = klass.getModule(); + long moduleID = context.getIds().getIdAsLong(module); + reply.writeLong(moduleID); + + return new CommandResult(reply); + } + } } static class ClassType { @@ -2866,6 +2911,55 @@ static CommandResult createReply(Packet packet, JDWPContext context) { } } + static class ModuleReference { + public static final int ID = 18; + + static class NAME { + + public static final int ID = 1; + + public static CommandResult createReply(Packet packet, JDWPContext context) { + PacketStream input = new PacketStream(packet); + PacketStream reply = new PacketStream().replyPacket().id(packet.id); + + long moduleId = input.readLong(); + ModuleRef module = verifyModule(moduleId, reply, context); + + if (module == null) { + return new CommandResult(reply); + } + + reply.writeString(module.name()); + return new CommandResult(reply); + } + } + + static class CLASSLOADER { + + public static final int ID = 2; + + public static CommandResult createReply(Packet packet, JDWPContext context) { + PacketStream input = new PacketStream(packet); + PacketStream reply = new PacketStream().replyPacket().id(packet.id); + + long moduleId = input.readLong(); + ModuleRef module = verifyModule(moduleId, reply, context); + + if (module == null) { + return new CommandResult(reply); + } + + Object loader = module.classLoader(); + if (loader == null || loader == context.getNullObject()) { // system class loader + reply.writeLong(0); + } else { + reply.writeLong(context.getIds().getIdAsLong(loader)); + } + return new CommandResult(reply); + } + } + } + static class Event { public static final int ID = 64; @@ -3100,6 +3194,17 @@ private static KlassRef verifyRefType(long refTypeId, PacketStream reply, JDWPCo return klass; } + private static ModuleRef verifyModule(long moduleId, PacketStream reply, JDWPContext context) { + ModuleRef module; + try { + module = (ModuleRef) context.getIds().fromId((int) moduleId); + } catch (ClassCastException ex) { + reply.errorCode(ErrorCodes.INVALID_MODULE); + return null; + } + return module; + } + private static FieldRef verifyFieldRef(long fieldId, PacketStream reply, JDWPContext context) { FieldRef field; try { diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistries.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistries.java index 8ccc73a41e62..3b935e71735b 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistries.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistries.java @@ -38,6 +38,7 @@ import com.oracle.truffle.espresso.descriptors.Symbol; import com.oracle.truffle.espresso.descriptors.Symbol.Type; import com.oracle.truffle.espresso.descriptors.Types; +import com.oracle.truffle.espresso.jdwp.api.ModuleRef; import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.redefinition.DefineKlassListener; import com.oracle.truffle.espresso.runtime.EspressoContext; @@ -194,6 +195,20 @@ public Klass[] getAllLoadedClasses() { return list.toArray(Klass.EMPTY_ARRAY); } + public ModuleRef[] getAllModuleRefs() { + ArrayList list = new ArrayList<>(); + // add modules from boot registry + list.addAll(bootClassRegistry.modules().entries()); + + // add modules from all other registries + synchronized (weakClassLoaderSet) { + for (StaticObject classLoader : weakClassLoaderSet) { + list.addAll(getClassRegistry(classLoader).modules().entries()); + } + } + return list.toArray(ModuleRef.EMPTY_ARRAY); + } + /** * Do not call directly. Use * {@link com.oracle.truffle.espresso.meta.Meta#loadKlassOrFail(Symbol, StaticObject, StaticObject)} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/EntryTable.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/EntryTable.java index b644d99f0c98..a8b4a135c3d1 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/EntryTable.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/EntryTable.java @@ -23,6 +23,8 @@ package com.oracle.truffle.espresso.impl; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Objects; import java.util.concurrent.locks.Lock; @@ -42,6 +44,10 @@ protected EntryTable(ReadWriteLock lock) { this.writeBlock = new BlockLock(lock.writeLock()); } + public Collection entries() { + return Collections.unmodifiableCollection(entries.values()); + } + public static final class BlockLock implements AutoCloseable { private final Lock lock; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java index ccb341aa9b16..1306ac952d91 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java @@ -30,6 +30,7 @@ import java.util.function.IntFunction; import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.espresso.jdwp.api.ModuleRef; import org.graalvm.collections.EconomicSet; import com.oracle.truffle.api.CompilerDirectives; @@ -1564,5 +1565,10 @@ public String getSourceDebugExtension() { return null; } + @Override + public final ModuleRef getModule() { + return module(); + } + // endregion jdwp-specific } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java index eb92346df63d..9999ae9a5fa9 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java @@ -28,6 +28,7 @@ import com.oracle.truffle.espresso.descriptors.Symbol; import com.oracle.truffle.espresso.descriptors.Symbol.Name; +import com.oracle.truffle.espresso.jdwp.api.ModuleRef; import com.oracle.truffle.espresso.runtime.EspressoContext; import com.oracle.truffle.espresso.runtime.StaticObject; @@ -52,7 +53,7 @@ public ModuleEntry createAndAddEntry(Symbol name, ClassRegistry registry, return moduleEntry; } - public static class ModuleEntry extends EntryTable.NamedEntry { + public static class ModuleEntry extends EntryTable.NamedEntry implements ModuleRef { // TODO: module versions. ModuleEntry(Symbol name, ClassRegistry data) { @@ -60,6 +61,20 @@ public static class ModuleEntry extends EntryTable.NamedEntry { this.registry = data; } + public String name() { + Symbol name = getName(); + if (name == null) { + // JDWP expects the unnamed module to return empty string + return ""; + } else { + return name.toString(); + } + } + + public Object classLoader() { + return registry.getClassLoader(); + } + public static ModuleEntry createUnnamedModuleEntry(StaticObject module, ClassRegistry registry) { ModuleEntry result = new ModuleEntry(null, registry); result.setCanReadAllUnnamed(); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java index 5d9ad20ae91c..8a9adc3a2b3d 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java @@ -54,6 +54,7 @@ import com.oracle.truffle.espresso.jdwp.api.JDWPSetup; import com.oracle.truffle.espresso.jdwp.api.KlassRef; import com.oracle.truffle.espresso.jdwp.api.MethodRef; +import com.oracle.truffle.espresso.jdwp.api.ModuleRef; import com.oracle.truffle.espresso.jdwp.api.MonitorStackInfo; import com.oracle.truffle.espresso.jdwp.api.RedefineInfo; import com.oracle.truffle.espresso.jdwp.api.TagConstants; @@ -721,6 +722,11 @@ public boolean isMemberOf(Object guestObject, KlassRef klass) { } } + @Override + public ModuleRef[] getAllModulesRefs() { + return context.getRegistries().getAllModuleRefs(); + } + public void rerunclinit(ObjectKlass oldKlass) { classInitializerActions.add(new ReloadingAction(oldKlass)); } From b5de1833a44ec69ef545243bb2a5c522bdb1885c Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 30 Sep 2021 10:59:47 +0200 Subject: [PATCH 231/681] refactor new match rule. --- .../aarch64/test/AArch64NegateShiftTest.java | 2 +- .../core/aarch64/AArch64NodeMatchRules.java | 14 ++++++---- .../lir/aarch64/AArch64ArithmeticOp.java | 28 ------------------- 3 files changed, 10 insertions(+), 34 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64NegateShiftTest.java b/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64NegateShiftTest.java index 0f74f5096bc7..6917c7f868cd 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64NegateShiftTest.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64NegateShiftTest.java @@ -32,7 +32,7 @@ import java.util.function.Predicate; public class AArch64NegateShiftTest extends AArch64MatchRuleTest { - private static final Predicate predicate = op -> (op instanceof AArch64ArithmeticOp.NegShiftOp); + private static final Predicate predicate = op -> (op instanceof AArch64ArithmeticOp.BinaryShiftOp); /** * negateShift match rule tests for shift operations with int type. diff --git a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java index 103d8f5cb21b..c061468d0eff 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java @@ -73,6 +73,7 @@ import org.graalvm.compiler.nodes.calc.ZeroExtendNode; import org.graalvm.compiler.nodes.memory.MemoryAccess; +import jdk.vm.ci.aarch64.AArch64; import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.AllocatableValue; @@ -668,18 +669,21 @@ public ComplexMatchResult logicShift(BinaryNode binary, ValueNode a, BinaryNode return emitBinaryShift(op, a, (ShiftNode) shift); } + /** + * Goal: fold shift into negate operation using AArch64's sub (shifted register) instruction. + */ @MatchRule("(Negate (UnsignedRightShift=shift a Constant=b))") @MatchRule("(Negate (RightShift=shift a Constant=b))") @MatchRule("(Negate (LeftShift=shift a Constant=b))") public ComplexMatchResult negShift(BinaryNode shift, ValueNode a, ConstantNode b) { - assert b.getStackKind().isNumericInteger(); - assert a.getStackKind().isNumericInteger(); - int shiftAmt = b.asJavaConstant().asInt(); + assert isNumericInteger(a, b); + int shiftAmt = getClampedShiftAmt((ShiftNode) shift); AArch64Assembler.ShiftType shiftType = shiftTypeMap.get(shift.getClass()); return builder -> { AllocatableValue src = moveSp(gen.asAllocatable(operand(a))); - Variable result = gen.newVariable(LIRKind.combine(operand(a))); - gen.append(new AArch64ArithmeticOp.NegShiftOp(result, src, shiftType, shiftAmt)); + LIRKind kind = LIRKind.combine(operand(a)); + Variable result = gen.newVariable(kind); + gen.append(new AArch64ArithmeticOp.BinaryShiftOp(AArch64ArithmeticOp.SUB, result, AArch64.zr.asValue(kind), src, shiftType, shiftAmt)); return result; }; } diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java index 8f44d473baa3..d3b60cf23865 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java @@ -679,34 +679,6 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { } } - public static class NegShiftOp extends AArch64LIRInstruction { - private static final LIRInstructionClass TYPE = LIRInstructionClass.create(NegShiftOp.class); - @Def(REG) protected AllocatableValue result; - @Use(REG) protected AllocatableValue src; - private final AArch64Assembler.ShiftType shiftType; - private final int shiftAmt; - - /** - * Computes result = - shiftType(src, shiftAmt). - * - * @param shiftType defines left shift, right shift, arithmetic, logical. - * @param shiftAmt must be in range 0 to 31 for ints (63 for longs). - */ - public NegShiftOp(AllocatableValue result, AllocatableValue src, AArch64Assembler.ShiftType shiftType, int shiftAmt) { - super(TYPE); - this.result = result; - this.src = src; - this.shiftType = shiftType; - this.shiftAmt = shiftAmt; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - int size = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; - masm.neg(size, asRegister(result), asRegister(src), shiftType, shiftAmt); - } - } - public static class MultiplyAddSubOp extends AArch64LIRInstruction { private static final LIRInstructionClass TYPE = LIRInstructionClass.create(MultiplyAddSubOp.class); From 935e1a4cff7f59c6671ca7458e2de98b0bda24e2 Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Thu, 30 Sep 2021 11:30:37 +0200 Subject: [PATCH 232/681] avoid hiding name field and rename method to explicit jdwpName() --- .../src/com/oracle/truffle/espresso/jdwp/api/ModuleRef.java | 2 +- .../src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java | 2 +- .../src/com/oracle/truffle/espresso/impl/ModuleTable.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ModuleRef.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ModuleRef.java index 4e55f6636592..1bde578b8058 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ModuleRef.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/ModuleRef.java @@ -34,7 +34,7 @@ public interface ModuleRef { * * @return module name */ - String name(); + String jdwpName(); /** * Returns the guest object representing the defining classloader of the module. diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java index c48448e67950..c51f0ee87f58 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java @@ -2929,7 +2929,7 @@ public static CommandResult createReply(Packet packet, JDWPContext context) { return new CommandResult(reply); } - reply.writeString(module.name()); + reply.writeString(module.jdwpName()); return new CommandResult(reply); } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java index 9999ae9a5fa9..fc264bbeb2ed 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java @@ -61,8 +61,7 @@ public static class ModuleEntry extends EntryTable.NamedEntry implements ModuleR this.registry = data; } - public String name() { - Symbol name = getName(); + public String jdwpName() { if (name == null) { // JDWP expects the unnamed module to return empty string return ""; @@ -72,6 +71,7 @@ public String name() { } public Object classLoader() { + getNameAsString() return registry.getClassLoader(); } From 1b485ee9e245843222fb1b2420e996e602221327 Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Thu, 30 Sep 2021 11:46:58 +0200 Subject: [PATCH 233/681] minor --- .../src/com/oracle/truffle/espresso/impl/ModuleTable.java | 1 - 1 file changed, 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java index fc264bbeb2ed..6afb0e33dbf2 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ModuleTable.java @@ -71,7 +71,6 @@ public String jdwpName() { } public Object classLoader() { - getNameAsString() return registry.getClassLoader(); } From 8dd794e1947d33908da9d00f5bff3889ed88dd89 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 29 Sep 2021 17:47:06 +0200 Subject: [PATCH 234/681] Implement intrinsics llvm.(umax/umin).* --- .../parser/factories/BasicNodeFactory.java | 52 ++++- .../intrinsics/c/LLVMCMathsIntrinsics.java | 194 ++++++++++++++++++ 2 files changed, 236 insertions(+), 10 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java index aac96d172e97..84e227bb12b5 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java @@ -100,6 +100,7 @@ import com.oracle.truffle.llvm.runtime.nodes.control.LLVMLoopNode; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVM80BitFloatRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMAddressRetNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMArrayRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMDoubleRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMFloatRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMI16RetNodeGen; @@ -109,7 +110,6 @@ import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMI8RetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMIVarBitRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMStructRetNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMArrayRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMVectorRetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMRetNodeFactory.LLVMVoidReturnNodeGen; import com.oracle.truffle.llvm.runtime.nodes.control.LLVMSwitchNode; @@ -128,6 +128,8 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMFAbsNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMFAbsVectorNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMPowNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMUmaxVectorNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMUminVectorNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMTruffleGetArgCountNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMTruffleGetArgNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMAssumeNodeGen; @@ -163,14 +165,14 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMArithmeticFactory.LLVMArithmeticWithOverflowNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMArithmeticFactory.LLVMSimpleArithmeticPrimitiveNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceAddNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceMulNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceAndNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceMulNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceOrNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceXorNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceUnsignedMaxNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceSignedMaxNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceUnsignedMinNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceSignedMinNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceUnsignedMaxNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceUnsignedMinNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMVectorReduceFactory.LLVMVectorReduceXorNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountLeadingZeroesNodeFactory.CountLeadingZeroesI16NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountLeadingZeroesNodeFactory.CountLeadingZeroesI32NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountLeadingZeroesNodeFactory.CountLeadingZeroesI64NodeGen; @@ -1374,14 +1376,24 @@ private LLVMExpressionNode createMemmoveIntrinsic(LLVMExpressionNode[] args) { } } + static final class TypeSuffix { + final String suffix; + final String length; + + TypeSuffix(String suffix, String length) { + this.suffix = suffix; + this.length = length; + } + } + // matches the type suffix of an LLVM intrinsic function, including the dot - private static final Pattern INTRINSIC_TYPE_SUFFIX_PATTERN = Pattern.compile("\\S+(?\\.(?:[vp]\\d+)?[if]\\d+)$"); + private static final Pattern INTRINSIC_TYPE_SUFFIX_PATTERN = Pattern.compile("\\S+(?\\.(?:[vp](?\\d+))?[if]\\d+)$"); - private static String getTypeSuffix(String intrinsicName) { + private static TypeSuffix getTypeSuffix(String intrinsicName) { assert intrinsicName != null; final Matcher typeSuffixMatcher = INTRINSIC_TYPE_SUFFIX_PATTERN.matcher(intrinsicName); if (typeSuffixMatcher.matches()) { - return typeSuffixMatcher.group("suffix"); + return new TypeSuffix(typeSuffixMatcher.group("suffix"), typeSuffixMatcher.group("length")); } return null; } @@ -1719,9 +1731,9 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV // strip the type suffix for intrinsics that are supported for more than one data type. If // we do not implement the corresponding data type the node will just report a missing // specialization at run-time - String typeSuffix = getTypeSuffix(intrinsicName); + TypeSuffix typeSuffix = getTypeSuffix(intrinsicName); if (typeSuffix != null) { - intrinsicName = intrinsicName.substring(0, intrinsicName.length() - typeSuffix.length()); + intrinsicName = intrinsicName.substring(0, intrinsicName.length() - typeSuffix.suffix.length()); } if ("llvm.prefetch".equals(intrinsicName)) { @@ -1732,6 +1744,26 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV return LLVMIsConstantNodeGen.create(args[1]); } + if ("llvm.umax".equals(intrinsicName) && typeSuffix != null && typeSuffix.length != null) { + // format '.([vp]\d+)?[if]\d+)' + try { + int vectorLength = Integer.parseInt(typeSuffix.length); + return LLVMUmaxVectorNodeGen.create(args[1], args[2], vectorLength); + } catch (NumberFormatException e) { + // fall through + } + } + + if ("llvm.umin".equals(intrinsicName) && typeSuffix != null && typeSuffix.length != null) { + // format '.([vp]\d+)?[if]\d+)' + try { + int vectorLength = Integer.parseInt(typeSuffix.length); + return LLVMUminVectorNodeGen.create(args[1], args[2], vectorLength); + } catch (NumberFormatException e) { + // fall through + } + } + return LLVMX86_MissingBuiltin.create(declaration.getName()); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java index c1ca6b30cac7..bcc98ffa8d3e 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java @@ -29,6 +29,7 @@ */ package com.oracle.truffle.llvm.runtime.nodes.intrinsics.c; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.NodeField; @@ -48,6 +49,11 @@ import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer; import com.oracle.truffle.llvm.runtime.vector.LLVMDoubleVector; import com.oracle.truffle.llvm.runtime.vector.LLVMFloatVector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI16Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI1Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI32Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI64Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI8Vector; /** * Implements the C functions from math.h. @@ -803,4 +809,192 @@ protected LLVM80BitFloat doLLVM80BitFloat(LLVM80BitFloat magnitude, LLVM80BitFlo } } } + + @NodeChild(type = LLVMExpressionNode.class) + @NodeChild(type = LLVMExpressionNode.class) + @NodeField(name = "vectorLength", type = int.class) + abstract static class LLVMUnsignedVectorMinMaxNode extends LLVMBuiltin { + protected abstract int getVectorLength(); + + @SuppressWarnings("unused") + protected boolean compare(boolean a, boolean b) { + throw CompilerDirectives.shouldNotReachHere(); + } + + private byte compare(byte a, byte b) { + return (byte) compare((int) a, (int) b); + } + + private short compare(short a, short b) { + return (short) compare((int) a, (int) b); + } + + @SuppressWarnings("unused") + protected int compare(int a, int b) { + throw CompilerDirectives.shouldNotReachHere(); + } + + @SuppressWarnings("unused") + protected long compare(long a, long b) { + throw CompilerDirectives.shouldNotReachHere(); + } + + @SuppressWarnings("unused") + protected float compare(float a, float b) { + throw CompilerDirectives.shouldNotReachHere(); + } + + @SuppressWarnings("unused") + protected double compare(double a, double b) { + throw CompilerDirectives.shouldNotReachHere(); + } + + @Specialization + @ExplodeLoop + protected LLVMI1Vector doI1Vector(LLVMI1Vector a, LLVMI1Vector b) { + assert a.getLength() == getVectorLength(); + assert b.getLength() == getVectorLength(); + boolean[] result = new boolean[getVectorLength()]; + for (int i = 0; i < getVectorLength(); i++) { + result[i] = compare(a.getValue(i), b.getValue(i)); + } + return LLVMI1Vector.create(result); + } + + @Specialization + @ExplodeLoop + protected LLVMI8Vector doI8Vector(LLVMI8Vector a, LLVMI8Vector b) { + assert a.getLength() == getVectorLength(); + assert b.getLength() == getVectorLength(); + byte[] result = new byte[getVectorLength()]; + for (int i = 0; i < getVectorLength(); i++) { + byte aValue = a.getValue(i); + byte bValue = b.getValue(i); + result[i] = compare(aValue, bValue); + } + return LLVMI8Vector.create(result); + } + + @Specialization + @ExplodeLoop + protected LLVMI16Vector doI16Vector(LLVMI16Vector a, LLVMI16Vector b) { + assert a.getLength() == getVectorLength(); + assert b.getLength() == getVectorLength(); + short[] result = new short[getVectorLength()]; + for (int i = 0; i < getVectorLength(); i++) { + short aValue = a.getValue(i); + short bValue = b.getValue(i); + result[i] = compare(aValue, bValue); + } + return LLVMI16Vector.create(result); + } + + @Specialization + @ExplodeLoop + protected LLVMI32Vector doI32Vector(LLVMI32Vector a, LLVMI32Vector b) { + assert a.getLength() == getVectorLength(); + assert b.getLength() == getVectorLength(); + int[] result = new int[getVectorLength()]; + for (int i = 0; i < getVectorLength(); i++) { + int aValue = a.getValue(i); + int bValue = b.getValue(i); + result[i] = compare(aValue, bValue); + } + return LLVMI32Vector.create(result); + } + + @Specialization + @ExplodeLoop + protected LLVMI64Vector doI64Vector(LLVMI64Vector a, LLVMI64Vector b) { + assert a.getLength() == getVectorLength(); + assert b.getLength() == getVectorLength(); + long[] result = new long[getVectorLength()]; + for (int i = 0; i < getVectorLength(); i++) { + long aValue = a.getValue(i); + long bValue = b.getValue(i); + result[i] = Long.compareUnsigned(aValue, bValue) >= 0 ? aValue : bValue; + } + return LLVMI64Vector.create(result); + } + + @Specialization + @ExplodeLoop + protected LLVMFloatVector doFloatVector(LLVMFloatVector a, LLVMFloatVector b) { + assert a.getLength() == getVectorLength(); + assert b.getLength() == getVectorLength(); + float[] result = new float[getVectorLength()]; + for (int i = 0; i < getVectorLength(); i++) { + result[i] = compare(a.getValue(i), b.getValue(i)); + } + return LLVMFloatVector.create(result); + } + + @Specialization + @ExplodeLoop + protected LLVMDoubleVector doDoubleVector(LLVMDoubleVector a, LLVMDoubleVector b) { + assert a.getLength() == getVectorLength(); + assert b.getLength() == getVectorLength(); + double[] result = new double[getVectorLength()]; + for (int i = 0; i < getVectorLength(); i++) { + result[i] = compare(a.getValue(i), b.getValue(i)); + } + return LLVMDoubleVector.create(result); + } + } + + public abstract static class LLVMUmaxVectorNode extends LLVMUnsignedVectorMinMaxNode { + + @Override + protected final boolean compare(boolean a, boolean b) { + return a || b; + } + + @Override + protected final int compare(int a, int b) { + return Integer.compareUnsigned(a, b) >= 0 ? a : b; + } + + @Override + protected final long compare(long a, long b) { + return Long.compareUnsigned(a, b) >= 0 ? a : b; + } + + @Override + protected final float compare(float a, float b) { + return Math.max(a, b); + } + + @Override + protected final double compare(double a, double b) { + return Math.max(a, b); + } + } + + public abstract static class LLVMUminVectorNode extends LLVMUnsignedVectorMinMaxNode { + + @Override + protected final boolean compare(boolean a, boolean b) { + return a && b; + } + + @Override + protected final int compare(int a, int b) { + return Integer.compareUnsigned(a, b) <= 0 ? a : b; + } + + @Override + protected final long compare(long a, long b) { + return Long.compareUnsigned(a, b) <= 0 ? a : b; + } + + @Override + protected final float compare(float a, float b) { + return Math.min(a, b); + } + + @Override + protected final double compare(double a, double b) { + return Math.min(a, b); + } + } } From defb7a9cc2a0e8451531544c478b40defd58834f Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Thu, 30 Sep 2021 12:00:15 +0200 Subject: [PATCH 235/681] rename method and take the read lock --- .../com/oracle/truffle/espresso/impl/ClassRegistries.java | 4 ++-- .../src/com/oracle/truffle/espresso/impl/EntryTable.java | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistries.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistries.java index 3b935e71735b..85b70512fd78 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistries.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ClassRegistries.java @@ -198,12 +198,12 @@ public Klass[] getAllLoadedClasses() { public ModuleRef[] getAllModuleRefs() { ArrayList list = new ArrayList<>(); // add modules from boot registry - list.addAll(bootClassRegistry.modules().entries()); + list.addAll(bootClassRegistry.modules().values()); // add modules from all other registries synchronized (weakClassLoaderSet) { for (StaticObject classLoader : weakClassLoaderSet) { - list.addAll(getClassRegistry(classLoader).modules().entries()); + list.addAll(getClassRegistry(classLoader).modules().values()); } } return list.toArray(ModuleRef.EMPTY_ARRAY); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/EntryTable.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/EntryTable.java index a8b4a135c3d1..33c58d17fe3f 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/EntryTable.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/EntryTable.java @@ -44,8 +44,11 @@ protected EntryTable(ReadWriteLock lock) { this.writeBlock = new BlockLock(lock.writeLock()); } - public Collection entries() { - return Collections.unmodifiableCollection(entries.values()); + @SuppressWarnings("try") + public Collection values() { + try (BlockLock block = read()) { + return Collections.unmodifiableCollection(entries.values()); + } } public static final class BlockLock implements AutoCloseable { From 5bfeedce57fab2f520424c9e952b8fa84dc0938b Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 30 Sep 2021 12:00:58 +0200 Subject: [PATCH 236/681] Fix style --- .../runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java index bcc98ffa8d3e..96af96fb6182 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java @@ -816,7 +816,6 @@ protected LLVM80BitFloat doLLVM80BitFloat(LLVM80BitFloat magnitude, LLVM80BitFlo abstract static class LLVMUnsignedVectorMinMaxNode extends LLVMBuiltin { protected abstract int getVectorLength(); - @SuppressWarnings("unused") protected boolean compare(boolean a, boolean b) { throw CompilerDirectives.shouldNotReachHere(); } @@ -829,22 +828,18 @@ private short compare(short a, short b) { return (short) compare((int) a, (int) b); } - @SuppressWarnings("unused") protected int compare(int a, int b) { throw CompilerDirectives.shouldNotReachHere(); } - @SuppressWarnings("unused") protected long compare(long a, long b) { throw CompilerDirectives.shouldNotReachHere(); } - @SuppressWarnings("unused") protected float compare(float a, float b) { throw CompilerDirectives.shouldNotReachHere(); } - @SuppressWarnings("unused") protected double compare(double a, double b) { throw CompilerDirectives.shouldNotReachHere(); } From d7938b149b5c819163dba1c7be2a9a0edb9fe262 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 30 Sep 2021 14:23:23 +0200 Subject: [PATCH 237/681] Use pre-build GNU-R for fastr linux jobs. --- vm/ci_common/common.hocon | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vm/ci_common/common.hocon b/vm/ci_common/common.hocon index 32202174f47f..42cfe66a25ff 100644 --- a/vm/ci_common/common.hocon +++ b/vm/ci_common/common.hocon @@ -121,13 +121,14 @@ fastr_linux: ${fastr} { pcre2: "==10.37", zlib: ">=1.2.11", curl: ">=7.50.1", - gnur: "==4.0.3-gcc4.8.5-pcre8.42" + gnur: "==4.0.3-gcc4.8.5-pcre2" } environment: { TZDIR: "/usr/share/zoneinfo" PKG_INCLUDE_FLAGS_OVERRIDE : "-I/cm/shared/apps/zlib/1.2.11/include -I/cm/shared/apps/bzip2/1.0.6/include -I/cm/shared/apps/xz/5.2.2/include -I/cm/shared/apps/pcre2/10.37/include -I/cm/shared/apps/curl/7.50.1/include" PKG_LDFLAGS_OVERRIDE : "-L/cm/shared/apps/zlib/1.2.11/lib -L/cm/shared/apps/bzip2/1.0.6/lib -L/cm/shared/apps/xz/5.2.2/lib -L/cm/shared/apps/pcre2/10.37/lib -L/cm/shared/apps/curl/7.50.1/lib -L/cm/shared/apps/gcc/4.8.5/lib64" FASTR_FC: "/cm/shared/apps/gcc/4.8.5/bin/gfortran" + GNUR_HOME_BINARY: "/cm/shared/apps/gnur/4.0.3-gcc4.8.5-pcre2/lib64/R" } downloads: { BLAS_LAPACK_DIR: { name: "fastr-403-blas-lapack-gcc", version: "4.8.5", platformspecific: true }, From 59693d32185f307422a8a770883afd51f9aa4846 Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Thu, 30 Sep 2021 14:27:55 +0200 Subject: [PATCH 238/681] checkstyle fixes --- .../src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java | 1 + .../oracle/truffle/espresso/jdwp/impl/DebuggerController.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java index 7c2ff2dba891..56dc2c3c41db 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java @@ -508,6 +508,7 @@ public interface JDWPContext { /** * Returns all defined modules. + * * @return all modules */ ModuleRef[] getAllModulesRefs(); diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java index f65ab0b5eaa0..746f20f27ec6 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java @@ -467,7 +467,7 @@ public void disposeDebugger(boolean prepareReconnect) { if (!prepareReconnect) { // OK, we're closing down the context which is equivalent // to a dead VM from a JDWP client point of view - if(eventListener.vmDied()) { + if (eventListener.vmDied()) { // we're asked to suspend suspend(null, context.asGuestThread(Thread.currentThread()), SuspendStrategy.EVENT_THREAD, Collections.emptyList(), null, false); } From afc79f3a58aaae9d72c866c44b15ba39ce7b8824 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Tue, 2 Mar 2021 15:44:35 +0100 Subject: [PATCH 239/681] Truffle Exit Events. --- .../test/ContextLookupCompilationTest.java | 1 + .../test/TruffleContextCompilationTest.java | 42 +- ...cle_truffle_espresso_polyglot_Interop.java | 10 +- sdk/src/org.graalvm.polyglot/snapshot.sigtest | 3 +- .../src/org/graalvm/polyglot/Context.java | 35 +- .../graalvm/polyglot/PolyglotException.java | 11 +- .../polyglot/impl/AbstractPolyglotImpl.java | 2 +- truffle/CHANGELOG.md | 4 + truffle/docs/Exit.md | 107 +++ truffle/docs/exitschema.png | Bin 0 -> 29782 bytes truffle/docs/hardexitschema.png | Bin 0 -> 86566 bytes .../instrumentation/test/ContextExitTest.java | 653 ++++++++++++++++++ ...ContextInterruptCloseCancelOrExitTest.java | 583 ++++++++++++++++ .../ContextInterruptCloseOrCancelTest.java | 259 ------- .../test/InstrumentationTestLanguage.java | 55 +- .../test/ThreadsActivationListenerTest.java | 3 + .../test/TruffleContextTest.java | 88 ++- .../truffle/api/interop/ExceptionType.java | 15 +- .../truffle/api/interop/InteropLibrary.java | 53 +- .../api/test/TruffleSafepointTest.java | 21 + .../api/test/polyglot/ChildContextTest.java | 4 +- .../api/test/polyglot/ContextPolicyTest.java | 63 +- .../LanguageFinalizationFailureTest.java | 3 +- .../api/test/polyglot/ProxyLanguage.java | 9 + .../api/test/wrapper/HostEngineDispatch.java | 4 +- .../api/test/wrapper/HostEntryPoint.java | 2 +- .../com.oracle.truffle.api/snapshot.sigtest | 12 + .../oracle/truffle/api/LanguageAccessor.java | 5 + .../oracle/truffle/api/TruffleContext.java | 94 ++- .../oracle/truffle/api/TruffleLanguage.java | 114 ++- .../com/oracle/truffle/api/impl/Accessor.java | 6 + .../truffle/polyglot/EngineAccessor.java | 21 +- .../polyglot/PauseThreadLocalAction.java | 2 +- .../polyglot/PolyglotContextConfig.java | 4 +- .../truffle/polyglot/PolyglotContextImpl.java | 463 +++++++++++-- .../polyglot/PolyglotEngineDispatch.java | 4 +- .../truffle/polyglot/PolyglotEngineImpl.java | 10 +- .../polyglot/PolyglotExceptionImpl.java | 40 +- .../oracle/truffle/polyglot/PolyglotImpl.java | 8 +- .../polyglot/PolyglotLanguageContext.java | 48 +- .../truffle/polyglot/PolyglotThread.java | 16 + .../polyglot/PolyglotThreadLocalActions.java | 3 +- .../oracle/truffle/sl/test/SLExitTest.java | 129 ++++ .../src/com/oracle/truffle/sl/SLLanguage.java | 8 + .../truffle/sl/builtins/SLExitBuiltin.java | 59 ++ .../SLRegisterShutdownHookBuiltin.java | 61 ++ .../oracle/truffle/sl/runtime/SLContext.java | 34 + .../com.oracle.truffle.tck/snapshot.sigtest | 2 + 48 files changed, 2691 insertions(+), 482 deletions(-) create mode 100644 truffle/docs/Exit.md create mode 100644 truffle/docs/exitschema.png create mode 100644 truffle/docs/hardexitschema.png create mode 100644 truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextExitTest.java create mode 100644 truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseCancelOrExitTest.java delete mode 100644 truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseOrCancelTest.java create mode 100644 truffle/src/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLExitTest.java create mode 100644 truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLExitBuiltin.java create mode 100644 truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLRegisterShutdownHookBuiltin.java diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ContextLookupCompilationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ContextLookupCompilationTest.java index e4149a45b545..74585745bed1 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ContextLookupCompilationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ContextLookupCompilationTest.java @@ -280,6 +280,7 @@ public void testInnerContexts() { assertLookupsInnerContext(); } finally { innerContext.leave(null, prev); + innerContext.close(); } assertLookupsInnerContext(); context.leave(); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleContextCompilationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleContextCompilationTest.java index 97d4b07f8974..35f9ccdf4d1b 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleContextCompilationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleContextCompilationTest.java @@ -56,27 +56,31 @@ public void testInnerContextsDeoptimize() { Env env = Language.REFERENCE.get(null); TruffleContext context = env.newContextBuilder().build(); - OptimizedCallTarget target = assertCompiling(new RootNode(null) { - @Override - public Object execute(VirtualFrame frame) { - Object prev = context.enter(this); - try { - // barrier ensures that the deopt does not move up or downwards - barrier(); - Object arg = frame.getArguments()[0]; - if (arg != FIRST_RUN) { - CompilerDirectives.transferToInterpreterAndInvalidate(); + try { + OptimizedCallTarget target = assertCompiling(new RootNode(null) { + @Override + public Object execute(VirtualFrame frame) { + Object prev = context.enter(this); + try { + // barrier ensures that the deopt does not move up or downwards + barrier(); + Object arg = frame.getArguments()[0]; + if (arg != FIRST_RUN) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + } + barrier(); + } finally { + context.leave(this, prev); } - barrier(); - } finally { - context.leave(this, prev); + return null; } - return null; - } - }); - assertTrue(target.isValid()); - target.call(new Object()); - assertFalse(target.isValid()); + }); + assertTrue(target.isValid()); + target.call(new Object()); + assertFalse(target.isValid()); + } finally { + context.close(); + } } private OptimizedCallTarget assertCompiling(RootNode node) { diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_polyglot_Interop.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_polyglot_Interop.java index d289fa3968d9..351bdfc34962 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_polyglot_Interop.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_com_oracle_truffle_espresso_polyglot_Interop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -695,9 +695,11 @@ boolean doCached( /** * Returns exception exit status of the receiver. Throws {@code UnsupportedMessageException} * when the receiver is not an {@link InteropLibrary#isException(Object) exception} of the - * {@link ExceptionType#EXIT exit type}. A return value zero indicates that the execution of the - * application was successful, a non-zero value that it failed. The individual interpretation of - * non-zero values depends on the application. + * {@link ExceptionType#EXIT exit type}. See + * Context Exit + * for further information. A return value zero indicates that the execution of the application + * was successful, a non-zero value that it failed. The individual interpretation of non-zero + * values depends on the application. * * @see InteropLibrary#getExceptionExitStatus(Object) * @since 20.3 diff --git a/sdk/src/org.graalvm.polyglot/snapshot.sigtest b/sdk/src/org.graalvm.polyglot/snapshot.sigtest index 632579394e7b..f49816641c7b 100644 --- a/sdk/src/org.graalvm.polyglot/snapshot.sigtest +++ b/sdk/src/org.graalvm.polyglot/snapshot.sigtest @@ -178,8 +178,9 @@ meth public org.graalvm.polyglot.Context$Builder processHandler(org.graalvm.poly meth public org.graalvm.polyglot.Context$Builder resourceLimits(org.graalvm.polyglot.ResourceLimits) meth public org.graalvm.polyglot.Context$Builder serverTransport(org.graalvm.polyglot.io.MessageTransport) meth public org.graalvm.polyglot.Context$Builder timeZone(java.time.ZoneId) +meth public org.graalvm.polyglot.Context$Builder useSystemExit(boolean) supr java.lang.Object -hfds allowAllAccess,allowCreateProcess,allowCreateThread,allowExperimentalOptions,allowHostAccess,allowHostClassLoading,allowIO,allowNativeAccess,allowValueSharing,arguments,currentWorkingDirectory,customFileSystem,customLogHandler,environment,environmentAccess,err,hostAccess,hostClassFilter,hostClassLoader,in,messageTransport,onlyLanguages,options,out,polyglotAccess,processHandler,resourceLimits,sharedEngine,zone +hfds allowAllAccess,allowCreateProcess,allowCreateThread,allowExperimentalOptions,allowHostAccess,allowHostClassLoading,allowIO,allowNativeAccess,allowValueSharing,arguments,currentWorkingDirectory,customFileSystem,customLogHandler,environment,environmentAccess,err,hostAccess,hostClassFilter,hostClassLoader,in,messageTransport,onlyLanguages,options,out,polyglotAccess,processHandler,resourceLimits,sharedEngine,useSystemExit,zone CLSS public final org.graalvm.polyglot.Engine innr public final Builder diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java index 55953f2dcfec..584e5011e8c0 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java @@ -293,6 +293,26 @@ * currently executing code. If the context is currently executing some code, a different thread may * kill the running execution and close the context using {@link #close(boolean)}. * + *

Context Exit

+ * + * A context is exited naturally by calling the {@link #close} method. A context may also be exited + * at the guest application request. There are two ways a guest language may exit. + *
    + *
  • Soft exit. A guest language throws a special exception that causes the embedder thread to + * eventually throw a {@link PolyglotException} with {@link PolyglotException#isExit()} returning + * true and {@link PolyglotException#getExitStatus()} returning the exit status code + * specified by the guest application. The special exception does not influence other threads and + * does not trigger context close on its own. Closing the context is up to the embedder. + *
  • Hard exit. A guest language uses a builtin command that unwinds all context threads and + * closes the context by force. Embedder threads also throw a {@link PolyglotException} with + * {@link PolyglotException#isExit()} returning true and + * {@link PolyglotException#getExitStatus()} returning the exit status code specified by the guest + * application. However, the context is closed automatically. The hard exit can be customized using + * {@link Builder#useSystemExit(boolean)}. If true, the context threads are unwound by + * calling {@link System#exit(int)} with the exit status parameter specified by the guest + * application. This operation terminates the whole host application. + *
+ * *

Pre-Initialization

* * The context pre-initialization can be used to perform expensive builtin creation in the time of @@ -1024,6 +1044,7 @@ public final class Builder { private ZoneId zone; private Path currentWorkingDirectory; private ClassLoader hostClassLoader; + private boolean useSystemExit; Builder(String... onlyLanguages) { Objects.requireNonNull(onlyLanguages); @@ -1684,6 +1705,18 @@ public Builder hostClassLoader(ClassLoader classLoader) { return this; } + /** + * Specifies whether {@link System#exit(int)} may be used to improve efficiency of stack + * unwinding for context exit requested by the guest application. + * + * @since 22.0 + * @see Context + */ + public Builder useSystemExit(boolean enabled) { + this.useSystemExit = enabled; + return this; + } + /** * Creates a new context instance from the configuration provided in the builder. The same * context builder can be used to create multiple context instances. @@ -1796,7 +1829,7 @@ public Context build() { io, hostClassLoading, experimentalOptions, localHostLookupFilter, contextOptions, arguments == null ? Collections.emptyMap() : arguments, onlyLanguages, customFileSystem, customLogHandler, createProcess, processHandler, environmentAccess, environment, zone, limits, - localCurrentWorkingDirectory, hostClassLoader, allowValueSharing); + localCurrentWorkingDirectory, hostClassLoader, allowValueSharing, useSystemExit); return ctx; } diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotException.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotException.java index 06161bb2c7c3..e4e8b88fc6dd 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotException.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotException.java @@ -328,10 +328,11 @@ public boolean isInterrupted() { /** * Returns true if this exception is caused by an attempt of a guest language - * program to exit the application using a builtin command. The provided exit code can be - * accessed using {@link #getExitStatus()}. + * program to exit the application. The provided exit code can be accessed using + * {@link #getExitStatus()}. This can be the result of either the soft or the hard exit. * * @since 19.0 + * @see Context */ public boolean isExit() { return dispatch.isExit(impl); @@ -378,9 +379,11 @@ public Value getGuestObject() { /** * Returns the exit status if this exception indicates that the application was {@link #isExit() - * exited}. The exit status is intended to be passed to {@link System#exit(int)}. + * exited}. The exit status is intended to be passed to {@link System#exit(int)}. In case of + * hard exit the application can be configured to call {@link System#exit(int)} directly using + * {@link Context.Builder#useSystemExit(boolean)}. * - * @see #isExit() + * @see Context * @since 19.0 */ public int getExitStatus() { diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java index 3dd202ce7013..4fcab9a61840 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java @@ -507,7 +507,7 @@ public abstract Context createContext(Object receiver, OutputStream out, OutputS Map options, Map arguments, String[] onlyLanguages, FileSystem fileSystem, Object logHandlerOrStream, boolean allowCreateProcess, ProcessHandler processHandler, EnvironmentAccess environmentAccess, Map environment, ZoneId zone, Object limitsImpl, String currentWorkingDirectory, ClassLoader hostClassLoader, - boolean allowValueSharing); + boolean allowValueSharing, boolean useSystemExit); public abstract String getImplementationName(Object receiver); diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 9271dad7a637..d20fc98755c6 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -6,6 +6,10 @@ This changelog summarizes major changes between Truffle versions relevant to lan * Truffle DSL generated code now inherits all annotations on constructor parameters to the static create factory method. * Changed behavior of `RootNode#getCallTarget()` such that it lazily initializes its call target. This enforces a one-to-one relationship between root nodes and call targets, which avoids several problems, for example, with regard to instrumentation. As a consequence, `RootNode.setCallTarget()` is deprecated and so will be `TruffleRuntime#createCallTarget()` soon. Please use `RootNode#getCallTarget()` to access the call target of a root node from now on. +* In `TruffleLanguage.finalizeContext(Object)`, there is a new requirement for leaving all remaining unclosed inner contexts created by the language on all threads where the contexts are still active. +No active inner context is allowed after `TruffleLanguage.finalizeContext(Object)` returns. Not complying with this requirement will result in an internal error. Please note that inactive inner contexts are still closed implicitly by the parent context. +* Added `TruffleContext.closeExited(Node, int)` to hard exit an entered truffle context. See [the documentation](https://github.com/oracle/graal/blob/master/truffle/docs/Exit.md). +* Added `TruffleLanguage.exitContext(Object, ExitMode, int)` to allow languages perform actions before natural/hard context exit. Languages are encouraged to run all their shutdown hooks in exitContext instead of finalizeContext. ## Version 21.3.0 * Added a `@GenerateWrapper.Ignore` annotation to prevent methods from being instrumented in wrapper classes. diff --git a/truffle/docs/Exit.md b/truffle/docs/Exit.md new file mode 100644 index 000000000000..e20630417ae2 --- /dev/null +++ b/truffle/docs/Exit.md @@ -0,0 +1,107 @@ +# Context Exit + +Different Truffle (guest) languages may use different mechanisms for exiting. This is not optimal as a Truffle language has no way to detect and handle an exit triggered by a different language. + +As of 22.0 Truffle has support for polyglot context hard explicit exit triggered by guest languages using [TruffleContext.closeExited(Node,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleContext.html#closeExited-com.oracle.truffle.api.nodes.Node-int-). +It provides a unified way for languages to trigger the exit of the underlying polyglot context. When triggered, all initialized +guest languages are first notified using [TruffleLanguage.exitContext(C,ExitMode,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.html#exitContext-C-com.oracle.truffle.api.TruffleLanguage.ExitMode-int), then all context threads are stopped, and finally, the context is closed. +The hard explicit exit is simply referred to as "hard exit". + +The hard exit is only one of the three types of exit in Truffle. There are the following types of exit. + +* The new hard exit introduced above + * Hard exit notifications are executed with `ExitMode.HARD` as the second parameter of `TruffleLanguage.exitContext(C,ExitMode,int)`. +* Implicit "natural exit" + * Occurs during normal context close. + * The newly introduced exit notifications are executed for the natural exit as well, but threads are not forced to stop after the natural exit notifications, and so context threads that are still running can block the natural exit. + * Natural exit notifications are executed with `ExitMode.NATURAL` as the second parameter of `TruffleLanguage.exitContext(C,ExitMode,int)`. +* "Soft exit" + * Explicit exit triggered by throwing a Truffle exception of the exception type `ExceptionType.EXIT`. + * The exception is not automatically thrown in other threads by Truffle and it does not trigger exit notifications or context close on its own. + * The context is still fully usable after a soft exit and the soft exit can be followed by either the natural or the hard exit. + +For completeness, a polyglot context can be also closed by cancelling it using `Context.close(true)`, `TruffleContext.closeCancelled(Node,String)`, or `TruffleContext.closeResourceExhausted(Node,String)`. +The cancel operation leads to immediate stopping of all context threads and closing the context without any exit notifications. + +## Soft exit + +The soft exit is triggered by throwing a Truffle exception of the exception type `ExceptionType.EXIT` - soft exit exception. The exception is not automatically thrown in other threads by Truffle and it does not trigger exit notifications or context close on its own. +If not caught by languages, the soft exit exception eventually causes the embedder thread to throw a `PolyglotException` to the host with `PolyglotException.isExit() == true` and `PolyglotException.getExitStatus()` equal to the value specified by the soft exit exception. + +The context is still fully usable after a soft exit, but the embedder should close the context when it sees the `PolyglotException` with `PolyglotException.isExit() == true`, in which case the soft exit is followed by the natural exit. + +## Natural Exit + +![Natural exit schema](./exitschema.png "Natural exit schema") + +The natural exit occurs during a normal context close triggered by `Context.close()` or `TruffleContext.close()`. The natural exit illustrated in the figure above consists of the following steps: + +1. The natural exit is triggered by `Context.close()` or `TruffleContext.close()`. + +2. Exit notifications for all initialized languages are executed - `TruffleLanguage.exitContext(C,ExitMode,int)`, where `ExitMode.NATURAL` is used as the `ExitMode` parameter. + * Guest code runs normally during exit notifications. + +3. All initialized languages are finalized. + * `TruffleLanguage.finalizeContext(C)` is called for all initalized languages. + * Guest code runs normally during finalization. + +4. All languages are disposed. + * `TruffleLanguage.disposeContext(C)` is called for all languages. + +## Hard Exit + +![Hard exit schema](./hardexitschema.png "Hard exit schema") + +This section describes the hard exit process in detail. The hard exit for a polyglot context can be customized by `Context.Builder.useSystemExit(boolean)`. Therefore, +the following description is divided into two subsections. One for the case when +system exit is not enabled (`Context.Builder.useSystemExit(false)` - the default) and one for the case when system exit +is enabled (`Context.Builder#useSystemExit(true)`). The illustration of the exit process is depicted in the figure above. The figure also relates the exit process to the context cancelling process. +The red color of some of the boxes indicates that the context is invalid at that point and no guest code can be run. More precisely, the first Truffle safepoint will throw either a special `ThreadDeath` exit exception or +a special `ThreadDeath` cancel exception depending on whether the hard exit or the cancel operation is in progress. + +### Behavior if useSystemExit is disabled (default) + +1. The exit is triggered by [TruffleContext.closeExited(Node,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleContext.html#closeExited-com.oracle.truffle.api.nodes.Node-int-). + +2. Exit notifications for all initialized languages are executed - [TruffleLanguage.exitContext(C,ExitMode,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.html#exitContext-C-com.oracle.truffle.api.TruffleLanguage.ExitMode-int), where `ExitMode.HARD` is used as the `ExitMode` parameter. + * Guest code runs normally during exit notifications. + * If the context is not cancelled during exit notifications (during step 2a) and reaches step 2b, the exit process proceeds with the next step. Otherwise, the exit notifications are interrupted and the context is immediately cancelled. + +3. All context threads are forced to stop by throwing a special `ThreadDeath` exit exception from Truffle safepoints. + * To exit threads reliably, languages need to ensure that `ThreadDeath` is always immediately rethrown and guest language exception handlers and finally blocks are not run. + * The embedder threads eventually throw a `PolyglotException` to the host with `PolyglotException.isExit() == true` and `PolyglotException.getExitStatus()` + being equal to the exit code originally specified as the second parameter to the first call to`TruffleContext.closeExited(Node,int)`. + * Note that from step 3 the exit process is similar to the cancelling process as indicated by the figure, but the cancelling process uses a special `ThreadDeath` cancel exception + and the `PolyglotException` thrown to the host has `PolyglotException.isCancelled() == true` instead of `PolyglotException.isExit() == true`. + +4. All initialized languages are finalized. + * `TruffleLanguage.finalizeContext(C)` is called for all initalized languages. + * Running any guest code in `TruffleLanguage.finalizeContext(C)` will throw the special `ThreadDeath` exit exception from the first Truffle safepoint. + * Languages should skip any finalization that would require running guest code. A language can find out if it can run guest code in `TruffleLanguage.finalizeContext(C)` by checking if `TruffleLanguage.exitContext(C,ExitMode,int)` was previously called with ExitMode.NATURAL, + or by checking that `TruffleContext.isClosed()` returns `false`. + + +5. All languages are disposed. + * `TruffleLanguage.disposeContext(C)` is called for all languages. + +6. The context is closed. + +### Behavior if useSystemExit is enabled + +1. The exit is triggered by [TruffleContext.closeExited(Node,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleContext.html#closeExited-com.oracle.truffle.api.nodes.Node-int-). + * Same as with system exit disabled. + +2. Exit notifications for all initialized languages are executed - [TruffleLanguage.exitContext(C,ExitMode,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.html#exitContext-C-com.oracle.truffle.api.TruffleLanguage.ExitMode-int), where `ExitMode.HARD` is used as the `ExitMode` parameter. + * Same as with system exit disabled. + +3. `System.exit(int)` is called to terminate the whole host application providing the fastest exit possible. + * The exit code passed to `System.exit(int)` + is the one originally specified as the second parameter to the first call to`TruffleContext.closeExited(Node,int)`. + +## Example Usage + +The [SimpleLanguage](https://github.com/graalvm/simplelanguage) demonstrates the usage of the hard context exit. The following aspects are demonstrated. + +* [SLExitBuiltin](https://github.com/graalvm/simplelanguage/blob/master/language/src/main/java/com/oracle/truffle/sl/builtins/SLExitBuiltin.java) demonstrates triggering the context exit. +* [SLRegisterShutdownHookBuiltin](https://github.com/graalvm/simplelanguage/blob/master/language/src/main/java/com/oracle/truffle/sl/builtins/SLRegisterShutdownHookBuiltin.java) demonstrates registration of shutdown hooks that are executed during the exit notification defined in [SLLanguage](https://github.com/graalvm/simplelanguage/blob/master/language/src/main/java/com/oracle/truffle/sl/SLLanguage.java). +* [SLExitTest](https://github.com/graalvm/simplelanguage/blob/master/language/src/test/java/com/oracle/truffle/sl/test/SLExitTest.java) demonstrates the usage of the builtins defined above. \ No newline at end of file diff --git a/truffle/docs/exitschema.png b/truffle/docs/exitschema.png new file mode 100644 index 0000000000000000000000000000000000000000..a0d11beba1847a19263f815ac1ca4cf4a0191c3d GIT binary patch literal 29782 zcmcG$1yr2dvZ#v_JOp=wySs)2*8~U>+#Q0u2X}V~PH=a3cXw@|ad%#mwQ}y=`<(Ue z+jorjXY^onQ`A4JX3hC`)mJk?pJm06;Bn!>z`&3s#D(R-z#vt@z`%Xpz<@q^X9RZ* z`T?UWB_<5^^7=2cB|irA3EX#aRa-Eyw-m20aNk;K4A6(Lb`mlousd(i-=HFi(&vVO zff0jA2n#7XEgr5o+F{Hr_MM%i+RDF&^ZpD0^`?cCUmP}yn5KpE%h>@2owA}LoeG1l zScR9SFuGz+VS$&I9f=Ij4^0{3mY7tQ6C&^*Z~GZ-?sjvhFE=xsK|zgw#WQW&iB{1 zoOqiuV5vq*=SO;BIO7zFt&U*^O;5`SBdo=qXPEc3h22|379^~7NR7x$C##Z|CIoJA za?ql!t?&A3Fa`8r+nVS79xRK5Uu2P-J-;sQ3@H`s?Y0MBnke|*C>iZoJs3rl8_cR` zHr0`nHYw(L2H-Apo-(YavV=Urjd~geSesKj@s){Xgz=_1W}t(N2ARwm3VbV-@78NA zW{taifv7`X6{vajjxiK}&@m;;I+458D)#4$Z^TslTt|>|S^2GsWspB?&yZ4w%Z#oQEu|lg zG1W-rA`S25hiOA{Vp4)`?juh0Z_YZ+D)7_WAQXV(f=B$ z_-?$MYBeonwlt%Q1474l^PT*Gm#sigNB>nv*yn~zHqv?`{-)SIuBNyQKyj1XcDuY^ zDcaomMkO_d-5LYN|sK!HfFBc1HjLcA`)bL%44_0DZT==o+}%?|OZ7w3xq<>6E;8i8NU z+S+A?1exoZVX0-neKt*i8Wd}wP_zuSb6`*vP92g=3U@CAAYnf%09+9 z6uZdPyiJR(;0jV>&(JVJsCRwf5jaxy7C2gDrPYOF6=m1fo|`b2*6Lm&@ZFy(<*yvy)F&gpaux%sF0%yB9mxp`Zi=u#}r& zGdACl<{xxu>^7mxXSx@wP) zvJ1;@DK4V1a*z%`&)Fcami6A|k!G%j%~6%#0;LFOmyw9?XSY7o1=I>lOTis*n0X5&IhjK3pi2T>=i}M ziufYun@+Ie9p3Spm+#5dgi(46Eo?=xL*nsC!=uzsNnG}Xuo_|eESDa*7=rD|5&jpu zoKf>ARy*2_aI^Q-=0q+Ffhi@u?x7ym5d1ux?Q8v;dvje*&oy%McGEfXOCHrG^2ysr zwnO-;!9aM%QbOQLpit;snA)d??v9V#+CAaO`ZJYT` zn1tf>Ia-&KIpe!gan5*6TJ9$^UsSS4TXl@8B^DeaSSvl>bh{1Eg1j2OYBk|}cwye? zNT;?dFr?hdK3~s+EY%amcdN}CtQx9bm!g)EbSB7h(zK$FYp{R$==SVhBuM5y*3?C) zx0OD2XYc4c8UQc&i^oK^(^7CVX&2}nIuP=I*eQOmV8G>pb zQgd-P?&K`4dN1srI)7hDuldYxnUJi}YAzV%~h{8`t&h3|{#+5R$4;>YMx>3^_ zE=IW7t$|Ur2_|WArsj@j_U%nn5g5=p&)LqE7QEVg^q0*!zil2$47T(4T+ z*nyj`Ff!0sLMqWAB`)7aBC!9SlN)K`lT?uy@xVCxCEZweWE2Yb?GcZVT`by1TbO?D zDV;7;NLL#O9ENt*qn_vpMYh9ZzD0hBP>HaiI(+h11` zSs4oSNDGd@aG~i8?0pcV#2pvsZiXDyj|PHL?ZMNZZx@#}`oggFYxLKpwj`1-3EPM? zMh^6fRG&(`H`L;kUeX8mG_StzsE$=B?^pTF|Goc+d)wg2S@9vZM+J4kZJUt|`0=wM zFrA)WHupjeMDvFoM|a|AFIuZR1vE>DN`6bvmb4`L(DQW0(!Q}0-^v)8bx+QDs02Z4 zbapY9ftpqw5s2}y=d9Hth0ODiF2VOS%_8YY(6!#{eXBxD&gwlq+_q_)*Bx~L(WL|- zC^&RQZ$(cVIe5HZR>6SU?B>?bb1x{6v6KSmYpP4%-^zj}QI$~^5i`8)#B!*8(aPt3 zcIrq8qZF*{5=q(G7!ixM6u8{r$B(yL>9#}2(JYw0sB=-zAK?PyWVI7Rd;Mn%kjvTk zu{n}Z(#C;6WYVbUrrc(Ax9&kDI%)4FCN3z?aEEIj8v|nv?uuGq3}aH5t9rgk{D_xU zK4UD(&Imb081bbQa^#!iPt_t9bl#L;NWtK^gAcbF>=inIy~7FVCj%^MWH8u)2SXNv zPQ`G_L!-3{L^oh&=zO@S6!a$hYph1q^R(HS?3Vd{@X2? zyb-}4s*Nams{~>i8En@wp1~R6i)Hm1>iP2=jx4rDZXdcQ4jsW3O=~m#>p&Xg1fRtP zuwD$L@mvsYt`56HOA=ndbGZ}RLszH?PM)%P5=GxoabFDqVgL(D$r(zKXJ#l4Z%x%GbUcJ?5k z)a=4rvXSsR9>2f~U%MmNN+TDv3VC}4! z4}|QZvI4IQ*a+Q(iaqThPRh0=0<7#YRJYx%7A4fR#`IXZk5U^Ej}SSxm|It#R_BG*)OZl~NX(eGK)p#igto&HTNUqW?@+3@gn($&aQF)6i-j^}pqtq`N@G6L5}5!{MO0cJ@9U zRO{7Gv6Dbf2!0n~p_i~neN zgj|5HlsEAli$f|(SP-=CJx_-J*&nvEwPVdeI(1wk9=PmOH%)cXltoNJ;>;{PrHC&4 zOyQ4+!(w)QxZn$mLdfSjTdex&HG4yi$`bo+C@A{>=>PXr^gkcr9}WL#Lf}88{(r{s zj{@5?=J4L)6X#nIf~)q|hpH#b&qudsTXCZ=H%%w4z=S17$#^=PwFXCY*`mp5HRCm;gOmoM6UtzrQ~T)Z>Po`G!isUH$rd#MV`;w9 zF!1m+rj8ieQh~yagoHCfv{E=Yb23+|ui9eCLB?aY;o-Q+^YecxEhTPKcwzers&NSC z7?0ZtMUfm#7b;+U{Pe9eA>kzdEziA*G*Uh}QSG@$f4O}8gFx2L;1 z_WJB>;B)tHjRLP4b-orU@w*Mt*O@mhIyTw^uS4GbuIqrpcQda!5AphF$+0wx3}ltO zopEEPIBK2ISbF2t!OT+HQk%20vqA5x(u)hJFFCJDgJE8kTH6C>R}?`0Y-xB>n=92w zpz3(7u)Nk+?(A~wU=K=u`$;4s4hhnP2(x~U%rGdP%hI%V0iX)eED4QI!Vhapl~?ntkCK5 zSE^fe0lI({%^ZXV2g5UHG}?udkiMEyZA>P$ZIxv(6yKJ>sP!!8<#4oEqV&J!XGgn6 zMIDfj`1e3TyFkv{%i|T-=bnMz{zm6_p#Ul9-naYadUa5<9zf(#uQu@(WaFJ@tbR}a ze3x!a)grAM38&_C1|_7=kg~KqnXqLud~P!U^P-jz^hP*mJf^r`!DK5vtu0^OQ-Tr^-X_x94Be^0fJQ|f2+?$V4>IMi zD1CK3DCd1OKk&a6-+x}t`lI2`4)EVJ{8`}tC{XHG!o(R5DtPf-oT7)rUTz1C36c%F zq7>z|^xn{NoEb$EoMbLe16h)PlAh!=18`>B?08S;A}IAw`7~b~ZJTW@$L+nGZyXIB za-M!UXT4}t-P)-Km=#I)B6~PL!R?lYkoA1^;b62}kHQRK(BOF1la$75zoB$Depp-K zn;m66Ia-`!DLDa)?_MZtRVo1#IkC`qMd6?UKM&2%O{ROnMDPL#cgm zzNeigwhLaOx4f=vRwD>&q6$0S2GY1+F3PmJ)W6U8U?5CS0@85jw&A_?#<&a!knXU;Z`&A8WE+H)3E#t=-y~EQzNu6Q6{3R9UhVPR~kg-x5PbBr)Q*V$yE%_kS zX6Qo4i57o1?MVr77)!OwsWt8`4;S+Z1}2g1t^=>=S!EoR@=wWY%6^n0aO_qnDCLIo zW^=d8@?Edo?~^D=A`go3n_`B6lZm(-i;HP92gOHdmYntdwEhpgM}@m z33qPb)t9c|o^spUCdc`4JzNWju%cR%-oWguTFw`6NPFgf+KRS_L`G z%uMd3sqMp`V@`UPQsxnAgPlY-6Zfr+Di?HsFrHBahfr*1jTq48wA{jnF={xu(4dcM z%|L6wbDf*ciM=WV=jrwih3|o91&9ty2Q^(FMh!VUEG*9=-JamG;V9p`NoG0Y=8#6e zetZPHtu}(buQnSi4kRDOp7HY55UXN#N40W9%#&-n9uBulZF^c@r?l8xYvl9QdcD5l)`^ z_d`4yIb%34wtjpk+>`g~SXnw-qznmqtVMzR2FrT7;HSU15*Wg3VB_cs9X9cG&f4bw zp(E5-E#2cO-O$zaI?-cX z`*ak%wwDco7E(g$_BchbT#KDD(C}h#Wd1Bm_T;P@u11IAMYKD9Iwgu=Q^SHO4cAq7 zo$P)dRh_daHJm=-8qIMuPWeD;K)}yd2J}sVT-DDuYN=<`A}BHb-L%Cl7@l^l*{A&U zu7(yfTL^lvBz(1o9|{cRv85tCwr$0WrZxGRa0rI-P`o!w2u>|G-CbQ^tlmc%E&Wz- z9Y1CZyduVI$*Qs1bd5~Tr%Gx`YR4KlfMq`>?5!yr77IAS|9KsH{wni z>^-s3czCfBApu6LNUU8ugMe}#uFk{?fU@@$cFK(?hcbRuOR6sm?#-+>ObpGZr)=$^ z21~I4x4YWh2OMR7R`=EpWA3RDo_w74gM3|$oMPualSkcnaRqa~;A#WUngwr&84wYR z0v^KBjgpp^wS;tI0X#~Bt5-Z--{RXt@00hn%qgbqlkF8&wZ)SCDjnr?RYLH`ys*I) zn=IZUf$~UNay*nQ*R}6Hau)wpY?d6A_*sj4!+hTZce%F==1Cfot%b66Hz%Mo^(98q z;$b3B!X&zG%-~v~<<{xza09iubM>5Dq2fp`9R`0G-+@PDX7d37=Etk$T8jnu1?vNz z)Qm=~-NO9S#j>n?>y6$vnA{XOT7E18gLdFB>8qYHpPKJ>?6%aM<60G|=Ez>ZJ$|K{Tikw14Yc>E;fX8S zz8HDWs&}>U@L^ZMLBCPeFZ2`HZFQbO{>JjfroO-6B?ZcLY1oYPR(tYVpd-%TwPq>` zx6}71Z7cz>O|hL!Q$eA(X>4f2i5a){7WjGOfwNnf=ZCj9PWRb2#^&7{5QtI&$FUc5 zF|H3otfEE(p6X)|@sf6g4}3CDX{pH%bXxAr-epRCI)z-Ruter!6{%m@B_}|I>u<`H z5SW9tuBlPk0rK=mhyxVZv)Y5(XUl0x^?}@4=45Ffk_Br56DXTU_9O()hud*gQuAL6 z<9!+noR7*@WlxGnj?Sv4PEB8Kiun#K23pc*su%=iHQ)N{usmT_ zN9vl!R_Zb3A7;1&GltmCT5{=U`0?@A%A-{hB+hr^@NJyrt9nXqaqrCf^zyONfJ?b1 zH-~QNF1z%-9=G5n%~K5Aau_+DFEy2DgDAP4P9mYxUx!~zAsaGS)VoXWg4`X-XHG<` zh*4;25GdylNXR!S9rD)JX#-f31eIGlvPvAJrNEHBaXg#-T9;wW#{)=~jwduD0Fy!a ziDV@_=|HfcOf&+b)LU{$Tg!7gN-X~23r6>$3}iW)!WPG)bb~HMk zYZw;WpHe#3hkq`muZS(<57ErV3!n+?3@B4fwq_wTt$1sF#-Z~{N*?xeMf;yh=y0Q? zP23wy%;qvClUe!>sqSi%l?MBdf_Ph^Ny`gbtIRg&#H9;B>>U^;)8V6AUWc;_BZR;z zMbgK8>uJXHh(+9Z1kQcukz<=GF<>Jsk_<7cYL&wIG(9{3SzcyvXO3IFuzb8IZ6=DdQ;Sxb6uBc zyMAP8@>~;+FL^KXEw*)AA0W$nywnh~g^bpf4Ohp;eM1-Rh?WePR}#9v$@OCp?fQwL zur}9|l(D9}Frfae6Qd_DF6H~W#K?6W2q4TJY_OF%W#=IpR@}`jURn@HXUuk7nka`b zkGXd+H-)hfP%u@0(sppObm4Bu(^xvx}=txQKr3uEu*o69xM^_(auv7STV ztX?Gfo~N-d;kF15KEMs-I;RIDP-^$3$Jtw8v2}@l&>q0M54IEg2A@Qch!b*G|FVg{ z6GTDLo0F&}Bu#wYl#s}61P7ZPW1Z+J(i!ahMV;@I+QGv#+;42Crn9MY$Vir@7CyICyy;C>K_a4>(aak3mf^*GJ%$+zN0e^XPp zmYag`(^`eTb+INcEk${&g&sp{W|WP=XeT11byt=*kK*2T7K-l)ly6u)+{0?W)$nR{ ziBnKM1-oD44_jF?*WDQ2;oJ5!X&*_<6+Rs7?CuRZ5oNmWJJgIN1l$9U+%39RQb;Un zQl;Jza4|k0^@ndQvxJO5GK3c4IK?5pAMb$%hWNvuRCQ;@m&Pa&t86k z|A~E;+$SLdMOEyj4`A!cs`FW9IqlJ~1XtAJrBImih*Y;nz-3kWBpR}-)##m^U`^X#Wx@507}@QogAwg5qD3G_~Q}USptfDFCuyz(GZ0$zf zAi4h5C#INqri&4)KnIu42J?2kyUE(%rCgg^1c}&CP|z6X(DYz}f{?>h$YO?Vk?qnN zWA|%%@JDkJYGH;lXDwtbv>;i{NKt`fbIf5+w90P*EahLV zWYWAIZ#EGOtXVbh3UBT#01m0U`NykD?HD7Y&M1p>k9^4V$rfChih}}nv z!#GtCVO^$L@#U&!pxFc!v9hyf+N-U0B1!=1BN8uZYn+-c&s5?sqgQ;m(;*%$W;)h~ z?{!ChhOEwF_2jK_Y%y6V;5J1x3r34!_`T5I0GMC$~FD2YvY1=rs zSISo2Z7Hi_Y;~WSf2b;lSLPyeRnWT~vMV(13Qg(*5S0f)c3h zjI8gXm5*lc-su}W?EB*L8U|>~MJtVHYnWd%W=#k#5A9_zHl$=eNeQx6N5OJk+aA`V z(P6+9;(xBkVpAivH2D^sE2TTnZvVy#-`K}&4CWmKjdmE1_kQEG;t+_*j2&l`yFL?Q z@-1Yr65wj{pVOLg5_J{uhAXd`*&L?;G@(wN!<%R2eU!FZ0mqSpPB^XuT&Lt2auTFu zmN;!0h0=jyY<+Tcy2pq_!3|&3vk%kkOwTwTW_!x7+xW#bX5I{ST%|HWGKu$#sTao% z7D-P5nT_>VUso}GvM-QJ&9H4?EZ^dX-?E$vCFiU}#QIX503en%au2CRV)${$Dy7JbEt@Bd* zl&ef5rFr)2ME`8&fd5WQv3jTS$o1O}muw3dqiMbB4KczxR}axz>%a|VF&iy!s#=k& z#ztbxM^D&Oyr30lh-jJ>4) zGe&z6W*{XHV8gwH8u|2CPIjU~WdF-}fejePS*g-)2Z z9@-4|4=JE#oRIOKT4(1~*~Yjw@xDWCh9k95k{o!0Ehl4o`WKJOu^K<=luI7?^@oSE zS8Y+&hb@-2`DDk|z?#%5X7u=IRgF#$ z9{J@TS7(zahRexid#2#trt!C5UoB-G0Yi_!KtrNUd2sN;Qj5Q|PVVP)6I>pxF}Z%D z{O$q2>d_Qb^O1}G7vNE&82gIXu6r!Ht?ovZ770*j!iuxpLjPW9RiC0KN{3cPeCip| z?aD|Ke}U{K2^Ooy^GvOexmgeAJE7hJZ;VP?GblJRPA^Z*_CD5_vT9MWOoHhLGSoNkaJC0(j6`a+w8WwQP-qS_~9<*;q*7%@2 z@Ij0{b#&=8!o>j({jckq%Ouc@=!~YS-{Y=>#!^&?G3(!)Eb!sxevR1{0D<|)lI-6? zyK`5Rjl&+`C-u^OX*o#nv_#cG6PrUBB`AQ~-G>)_Ry?2XU;)&9uq8K}&HeC!va@N1 zVfhC@^hD0`*4kykVsBT(e9W|W{Tm0gVrdiJ!kXQy;hnnF&GcWhfqM^y`cisxSY=i3 z1tL&c{&ynz-u1Z+{UdK|{?tWPeVY;Qpn>H^omGB?n;DCN)e}}WrDvx_M||7O^L8&` zeu4x!PcF+!I-wZw!&4&T+!E5ERU@b(DgK_O`W0Z3ysVitW`YWopSloVEB>#^&hLu< ze}jJiKOnn*#|lwx2%v7=^NWgO$b!#<54^uSb%pM!p-4z($EAuvc)H$nSbRU7}pJ zdhAmS+}O|&wB40XdPgovMic!y_nZO0g+Q$CxKJT~bk(PL>6MpCmcMEM4L}?jI_-Qe zUoOKr_!V0AkK}@4NMwArL@kBQV$n{@W47X3$!I}A!TKwp{1;;R2eL(H*e}*uwMoML zfr|}3nk_E${bM&*NH8t~fNyrTXuvq5f)Dl%TE+&S49N_d${JMs7P z6M+J8Qfkw`V|H5-Hos@n#&J;FL$u{}xUYShg7LfxU`Sm|7Y~oWZ>KKk;@2dOx@*T% zvNISL5*`+Y)Hvyw%x+fe41$Cs81$g~M`a1UV%x+SQ~Oo-n-xLzBi?(+?!WIsMs)77 zD*1b^#3!;|jaN4`%u`;dG?1etCx_mCtn)|0JDzWKcO?}85fb5?y>an)aa6$0PMq_c zhT~J>Qro_j-fKg^t3?p?lS`0S2M)jQ`byiMVJ4@h+=pVRZ7JyKOXlwk*v)2_iEwaK zr6xc!sMOy;(|XRi4g{tU5)!uFZW`eB{DGfy#DEKB7sA(w&M}?@ao@I}?QQ)R7K6dm zf#Kmx_*cGpd%E!}_!Vo5PrM@RHaJhum+d9XCJP*6^xsPXWEgtz#X#IM*emW7pLm^K zPf}}Z>)d1xi^iS)DAJ$)I(zFFuVe8shgKcfXKB%3m=fDSYp8gHgwQx?zF4(I&R2zq z)eBlSRw^Q&(bZNa1AW6Zg=dS#c-_pa6qIE_)Un`AaA3cnXo+O*wL7~&b2tfzH!ADV z?gjT{qdD)Uj|PLbq(?pJ)QaZX-@OVGA&elyK-ZsD@bByBKi{_gX!yV1*ZOP9si8zZ z?H<3J4|geW5st@D3cN%zMI1fy9NBwl)+7~>QLg3!$B7?N{gF}fQ~Unki6nRJA0i2S zgTs5fb48ih#1M_H47b=^?=AKXztL{tHiDYj0&Feg^5>DKjM);2C`5pXYZ+AVt zM7Cgne15sVJnM!|Vpf4?6lx)`9EY&B`in!%0J;{8XB??{;Vu z2cDtsblAbV61>)Fu;LTwH*CX#LL@fNCEOa^up~skCffle(k5rs69&SfrBY(4C3-08 zCN5{gf5bPA7XHfZwqHm{YEEC!Yh*slRy7af6H4BfVlJbLmbIkV1X4PCOk>ZA@|MX7 z|8G71SF4tz7aa{yLnZea3_HCILZIj=KBupGTQRt1>5SB03VkSogR*JO^*WwA=x31K)U7uH?3?83#*En%4kpoknPjVZo%dF50aEnu9x9Y4zpv(~jqB zxEhMk>GT%BARh80hwXg|wQ9B;FChH1NHbzn`$kW<{5FyZ|U zag7wgoF!w>8{Xeg3?CD3u-)ouguc{<-*xMKg}wX}p7efoV0!_Ttl?Z4iPavqt(8Br z@3^$X>pBi+6@a{&UJ>j>xvtV@)KUrLa_tkCZC(lp==y{+&mM}k`VcjRHB!L#{|$!S zg?%ZtkoS`anPail7P+r3>~Jlr8pT*@sjpXvkm9OUZ!Md4ZeC?h6ezKE<3Zf1(`OxP z)y|{anlqrZ#z~*XK6_8fJC~IR-R|qf^U3M72e9}3;py`5^O5>b1+GRXh?rxGjzHNs z?D<^Oh)|Cocc_%s>Qwo7SB?aR8wE6cd#F^lRRwPXSXoSAqCL$GNKH5$f-J^c`gP z$GQtIxb{q?6Mo)I72JZ)y0N8lwgq(`1<95Q-W~0DOQ*H@cTZ~U3zTzWj9MB!8Qq+X zE_c3Sr={Xg0#>ZLie-nW^k8Z-G|H79 z-Owq+$#pmoY1%KoV$y-iMne)2fW*tIt{+Zd*CLO}fX3etNgxQQ+Qf<}Wo+fow-}+z z#eFBzojZh|Acw`K*Jjj#5>T%8aUX<{{O4}E4^`trz4h+4Qsfq_9p!F*MOp_!Wz1F| zq6=SqDVzKmJ-|Fhz{l;50z3OC>Q<)4gxDU}zwZTba-G!np&KxFYhbsc3nFFNbeweY z`%Je>>7juaU;>vlQt!t%TSz8)|4pFDh`0^RzX!}Qqko`C`stTE4adpT4o)`c9K-xl z7>D&XhsIPtFGF3zNEM;bad#JQs3uxxZj%_SSjSqr333J{Fcw7B&|*j zmy@#2SDAtaA|tc06!emYYq9sWIR-#!f0rE^1~&>6mRcVq=r+ge)vuda1FPS==3yGF%aH@4p4CXK0vXcr@$cH zE-m-I3#u7{%3(tW9Hs|SQhUQr0FUE@rJ<^gPtUFw+P<`gy!0Iwt9L*5arZ0%!={IO zyj+5a4vd}te0@}GUE>_qzaHWsq(e?c##6$Zk3sAI4zB5at8v*2o9(21Z7Xf~&cuY_ z&G#}b^n#OgYas$WAq&`XDsAc_G|yYhNQOXwy*Wgm#uoU+&h%;E#SkZ6zz8 zEfN3gD27wL`0^8f+X;`5>G;v*p*kKdVXUb=<<(>Bdma_LeW4sb5rK=@Gm}+T z1c*|XbZ3}MALQ(dp1TMSWke!6`8Z$miszH!om~o5Z-X~X?RGuyG9um0(rSPR0x#Mm zT5=vK>|d@A@lG__P?I(xNCVq1Pz)M210x)@b>F^KoF7w%S_c?;;q+|uA7Vi#76MgY zT%~_L(O4Eugqmu?MhW74-{=v@*A{M=!xy;xUnFZI!Ze~RO+wM5!VP>8F64aj$W{Sc)J<|({M z4Xgshn+4f#AG|{9`#Xc^N4x0K*u3e3K38_ph8}#|h<;8s;+L`~{&%iW9P`gyp^xQX zxPlJ>eG<-oqGhdAFOe0C#q;~&Nq6jvW3GeyoC>RZg-5$-kDjAl2LZ75{FbGwn_A5i zTVIezx1BSJ-Y##G4gGy2O) zvSeer33R-BRoyU(+RR>DHC?(2;^6sm9dNu%;+8u4i>D80+5HT)*cZ!lJt&T2!_H&8 zU1!a_RiEgNR}>%|?#nG%A!KUPyP~>VR3<4A@#wevWh6dDiF*AM6NH*}x;(2rpg8U+ z1P_A5PaDxZ`Y5Rct0@rAb?ORVT6`GLz-<3BNWc%VN-~n7_tSKL_v@K}jd?Z&V1xb>&Dj*?hf1 zZMH?=r7W1A_WT8ij8Eju!XMqhW$;HW5If3H42;*g(2>$TyauJ*VDw6dxL_7d7-eOj zQBpZ;B#`2dIBxu`ImBzKsoe9KRyjv~MfNNq-NyH+w$oPDo1RF@j1ZitGJ_*JsVH0NGItzFgF{NvZTE@06ehiXZo@Z}NMk zkAHdrB+e|h&zVDQb*GnIj?Q-Jvtpvx zM^}Hwj}FYbStQJ8Pb9IFIGDJBJi$fQC+UDO;!o2hf-5$cF4&xN zI`}+%8Nv#Y0VJqii2<+xPm%5k_XrOUk;^BDm0pu||7+W8z24gmQviiq zp5zbF?gYvV-Nedz@}kYYpUa4abB z+jbl#P{*6}H1oVf9)nHATa8sUL)jX>d2+G_b-oXFFF~(C+zWI~th&?AYOMyPwT1Z@ zDN~kYREGqqoep`!zD05yFE!F*$kLRUhzUX%y4SudG~eTf$~1{tjO6DEEO7yN4hC_{fi(F(%sM-+^6Y4E=3h;(6t1qKTX6yCo>E zbpf6_2!Z06;OzCsB(xw6CFmUqiEh;Ep#)GbGD!$%9|T<@n6H&GRMd+8-@pIw0xJ6d zmjc3cm4Dsh-!^38w0AU;gI;UvQwlpeI3R)%B16{G`0rD!eV8uD*hCJTtihPBQGCq@%l13vELilVXPAW zEw*vwBW#sqxzcFiIbi`U^j6Ez_3ydA95orw6#9{trm-1f4g>(O_Se@V+v#3i2Xb6i zUt8?Epggm=QeI7cHO-zs0h7BonL8x=m$fglZjHnfYT~)_1BZu)?-UdiO6*p8mzEwn z?=Ap97FS_mtAtjq6Hjck48x1s?yWC9G@E@vB~Q-!fto}D8j*Vzk3F#iifKIdi%+1V zN654GDOfE%phc!xmUzpSBH`<^8mxj}g2)k`T35yx0Y3rkS%MB)mEUQ(il~GCGf);N zXlMcsR@R}(T#KW{nryR~U-n_Dujff#XKn0fS((;!tNVj{WA)Bgx>qwmgTI6iq4Xg7 z9rmE0-_Mju;dsD+7x7TFP}k7VYiVxIN~Hf=G{^7b&wi_^ypiY1#Z#K!DjyBv}RLG}Pq zI!foOBw7LoML+g7Dd>^+Uk@iePlTt?FsAE)7VsYZd9xbKojb^hF1hUCNfzP0zMp)4 zzx3j`#xO}=RIX(J)X80KPDDfAEfgL>3YisaD+_ZoGK62>e(apwg$xCbgf`~+CnZ*l zHu{=$CE_f_BNCwRRkg)uU-9#fr7Op)_oIM;m7EAV^CrjFdWkwYeg8J)z)r_V6Ix!Lv9qEf8^hybUcvfRA6Hdz)Og(UIUcPr3k~dp zbb|jFkhODe;4$7iU8o`{#_D5PgU-~{v}0I&wGGPCrITbr7(bozH>CNBqPLL(1gaZh zGNpRo6xZ}}$H&-fZzK-*1>H=O-?)QO)wdQd&d=6(6dIc+S}1mKS9xS`FNIT>sXyaR zP3Kvdsc5pX)Q*-++=p~Mps~-SFFPh#3w}bM>;ybqnSH)ffrfN$ZFSzEdqGk1*X;KT ztF;9*SkuVS2-w%~ELa(>Mn*Hp=a?i` z^--fndF&6W)o9{=Ww?#Z&T=bDLcQ8QGIOpWu?gVwIGSuB-B1uITt&n`>5JRh?cQ$qv)pWfawD6Vg7_eFyT zhu{+2o#56;Ah>Je?iL&Z!KHBv?iL8{?(PsgXakMAbIAVhecrmaYM(my%bnG$s#n$g zFxTp}#u(2SztM9?5L}@vPhHi5-7d;Y<55p(Ob?Qzn66wFGLoZK2D^SDp*rkRb<`53R#grh*u#E zABJdDAseZ4P83N->4Oyx-mzY-ju9NC3P4))BbDTL?*UJQH3wTqiuN&&`skE5gOL=P zl%#I`Ru7F4zSl`%(RY`n!a}Q+0062&>2UhUobTKxPR*eoiI6wP@^2~yKW=0HIp%4pk z$At=S+3elV4U`DVh)^mqG6wD&K17XIn`Dn4FSE2qt33m>IYdeWxM;YWlXQha^~;(CWynGfF{he~TrZtnL1H>r!CRC#Lq_F4wW ztHJMe=sWxhEugTB@jzv0Z?$7L)>yr{Yw7O%b_%s$=XhOYwSVQp^(1p8N#$qRZfiP9 zDX1})Pt$k5AY66rv(gfnib`#)!Fj~x$>j@&n!8&EGdw^P5R=@LjU=rUevV*{fNH6B zjs6&cOSZhsPt(!JVALjC7;iN~D3Ru5eZ^1Uze>p=ZAXMps;qg2(zafzoU{#A z(6i4`lcHD1s4l_A(Bfti;ThPxKQB8TA!U7YVP4&okn~I zttSoyD;?Dq#Y0K#)*_h$C7AHai@NK8bLFGLU4!pZ`Ei1L9UR+!5e(Kbx~CMa8mXW) zBCq3aiQ<9+kJh!`OmTyfuzN-Y~u@~#(gpSxhS(*&ch&%T77S?(3U(>$sR)B4tG z+VV^WOWXBTIX^MEw!weDz(3mCpM&0^5dxs7H>Tr%vP$!KF>xyL6wV0LtTZ7 zm@*;lT`J400jI3{2nNXqor=K43tJ)DdHU z9t>q#{or0Q&sA)qY~#LusJHhujXaD-y^KbycwK3A4CAMq0V7^sV`$y$$?aW?l)65) zt%^N^F^6RNpf25M-|w}gmLWY7vvZo8n_;O^r-Ac(>Oll0ikpYyLuy}SwgtS~4HP_z zOCQs5tyYER?sn^ETN+7BuFo}*_}D^qF}Y)(3Xx))@wsgZ_+9qyl8dDCR#yoh39=Ge zx!bmVc~|#uC1`b4&uvIg9muItNUF$_g$(|NQGuizltUt-U*0TVXH2!aTeisUkFNa# zjb41f`3K3B6mFh0hu8g=`3XJ!PY1>Hi_TmNhZUB!@?;1TS10w>k0j9pcMCHy zuw}d?_zlnI4UL4>pC^u86f{-Q82S0Nsb%1VqB{(7IfQSrEZ|h|5$F@YOyEJCt6S&|42qyTjr~`DilH%$`=pay9DjFzs`OO7GhdJzG#78duX+5(4V-GiyM~69bVk za=;0%Pfc-;t}&>AG?GmFnr-gYo!2apWycPz{h2&5 zodtN`PMBl;yRLc(g<|wc>%hNb=%b5Lsh*5EZwJeRY_1*rR>cCJQtTD4iXxdT=l1Zo zTu>nE7|gV;_%sI?a-AJbc>g)ubAGR=piEx>g78|u`MOwf)gtME ztL>tJ)@%Ep48XLAEQTEnZRlHtb?NoGj@HY`=j^Sw{qK158~+;rZ@DY;^`9xzHhU_{ z=g%t`((oppQ~@1=l>b)5FZEAr$G7O&wH9}yCxfl&;y;V{k1GGaPhd#mwL{CorGpRqCm6b>e9lAP3DsxKCvQu79K0P5Y>7;i0&B_N0B-F_VvW-XC?9BN>v*e(q9su$i_2e} zq)H|-6UYRW1j zHY%jx#uMIk9Pa1zJpEazvzmw7mxoAg3wAddpzF(q`w_@505zIo>?%GA$m;_czI|W!f%rp%}W=S|ToEyJ93x z`$+p90IlHDi6K%vWK{Bct0JRP`jMutHn`vnE7?8_@WLrQi%G_^98A=C+#kJhvvtvE zXG9GZyVzU7>`mI!@e+nT@0~;Xu$Oy#WOL$7y8m`5 z9USj`n-N=6LjKJ1*Z3chUpRV9tBtiM!cLd)2&Xrad@crkq~F59;_(gtR{5Z`{z_s3 zCKDZD?8GVSK9&e|l)5*+(R~oieY~4JsvjeG)B1gskTvCikKX8%VjsnJHAtrB&Z@p9 zvJ;&zC4Z996EF?{&q_v6q`O;x8^J=udjA}e56}9${Q_0k{sc`slO+|)9cTLyu4m{K z@Tf}uuQ_Ji1 zF!WQM7YEETLRVcSS%ofoS64kaR&N4*xj)0Q;$ct1;~mfUo>6>_pAWf{BdSeR?{fHq zrp2gDGQ5QGewd?)jfeQL-8g`9v=JO1!}}{z-7rx^P9sOIpADA_Q23en167GaL^ll( z225^0R%wN{?PDcWKDQgj^c~4*ah(r8lS%|Wl-eX0uCkPPc_6#c_y#OPqve*UqT`LX z=C3ubII@71gY)djWOS&i}9~ke1d{N z10@}uXm-!-6jigNA7g-?6MmO+nY1IkFPdByfBzmNvZ68TkpJb=5BTUlRQbcj!1e7# z?r^Qw&iYTq&f;f%FK4lWkL+y*%>Hm{v7!l{@1-lt4J!P_-opw(8RNZYLF;b0ia0B? zLcrEPp}@J?Txi38@YWWE5#5`@=zjLju@jvvHh@IGSC?(pR~qY&i#2R(v?QCb5@fTL z0oHLfN6TM|NP(^!b1vawg&0>f69A^1OAj-A=i4e9YIa=~H`pn%DAaIAtJ3Oq!|-N4VYwN_$ zu51evlxJud(~anDhADH;4%CijOzHq0M5}<2)SCxhBlb|=TonU8f$G^_xOO8(W*&3_ z%UQ|8opn-JUB2A8x(7=}%R~DSb6un@lvvWWjP`l6U z+47F1HGD`!Vav~fR|XC$-FB6SDAGl)rR#Hiq&~Jl-rzcF2EP-jcKeah%^8LU*?54I z@izm`g+Ij$dl(m#>_y&e$uO~qFgcLu#AV~dQ`At?<7caJBYW?rGyErqhwe~e&&lyb;1B1V5AIgvnP9YxQhM>zzh?rM)4QK z*qovKaQV0bJG?TbFna!AIP&S}fE)IaXS~PsBmNP826U;50~66A)E-vu+%vM(%3Fh~ zCyY{Y@uA?0Ca(p?wA^%wJjK@WU0w}2js)dqt>a(M6Xas2!$4XFEoKhwJt`ep&_g$- zeMS^tvAhLlk5+=FpDYD289Go0L*bGZ6-dBFrli*ImTct0S|7AGS2I>gZtBG$cIP0M z>6(&nQb5(i3Nn2D^?Kt;+&Zt*NJ6kUh);1Xhc`or8xb-8tF9pshc|b4Tx=ryHEn46 zmm3B#HB?SOV>is;zS2W{=R~l zT#=uA5$gH%j~k$t!v!=w^$3g|QcLxXI@8XOto?n5;L{Ttk=IupYzwu<_&%I;g}UBT}G=@xhcHIH5U*9Tb<`0;Q@gb%dK9+*SFA?tV_~PjR&3Q{|EN z-!wohaYS9TC72ltYXipu%Ab;0dV1Bo{Uvn<{I`t8r6mIqqmv&rJ*ib1o5tJ(fDDMN zjtYZi)64DH9Yp>(ajGE0;TZ^qDa+m6CXToU;ubyn_3j8 z_+AvrO!<6NXiG1)XJFKaq%lB(Ny`1qZ)V|c`X67lMbbCoYaM@Ma%Hzn3Ws@NZpMdOTozogBRU7PxY z1}oEXL=JytSL9z#`JRvpayj;fRY~WjL}FgVj7x)0S(9xr>Dkq~WT22Eo#WI|6MfDl zgRY_~I-|8y{)QDS&%ymaPjf?lN?#WT6=`5ata1s z1HR4s^}dE?m#JUp);@aYPAlRC=6Irj&zrfPu5Ji{Ft|+PhD^{i$Te{WaDsk5g){=# zX@sJ&Ke|WMrb;_Emj{5_;in7s09$iZcjB;axJ5#b3uD{OLh3UzH{uDB&_Cr~Mf?NT zgp&t498jL0I$YTsOrek^U~yKLzblHbZ2!q&h=uSg3JQyq-FI!+1}SW3a~F}k8HbU7 zg|@D`X0tyOTY{+>WTBK3Vi2qdMW-apCTT1euZFW99Ltq1Bt2S}qo)@Jkp}4Khe!*` zD8ylUVWVoGps+jt?h!y_6RGJ91+S`=iWG2%0j??(hZP;;i?rLcs;U@@U#x&7^My8c zqJcy3uS2(txREdGtsqC2WD7})W04c(J~3#IQ9~myU&hMk=LUS7WKb%i5@-?ZRjw(|C#jl6!M~B6@`25l zqCex7H-r+-H5sFj9^?FN~;Hc0PtJ`Y?N9iN?BAw3~X4kq(}vRsv1iBe8W zpuuE^OJz^70W+DOi)C`Zy}^pdi9TZ{QYKJZ9WiEiDq$Ncp25eUYTeqAKu))cI#N=(grjB@*+y96yIj#^XY z&|7?Yp)5d++8R%+B$pLce*4~d57{^M0Hd<668_yoRoAeI)t%=Ef{ch7(F~D=lRQ^2 zoc8WeB;3uiv5p1_r_{gb8$vJW^v655V-=>)iTUL&Kvz55@84cVG5wg(h>G7!p0M-& zS+>%{94D9Da{*<3N&nt%v$&c^6~a9T2}bdqSRLHnN~&GDiKi!PjGV^20^o=QY6e3$+FRK;)G*^+96KLL^dU& z)USrA&;UI>83|tedjY8gD+%<-QG1%tDvZAmB8ADkX7 z;NO#+BAq?OkE44Fk}LTh9zU&TV+PWHWBEnb79=rP1@kSTx+U}@708&0!LC+z?QAw; zl6`Cu=PSsz_tj4eDf}#2rbcbtQeZ$>MxV4U}9_SKYyA()P{m zg!=)BGp-wa!Y?=IUgvln(bpp$dDg1G-m2B9?boP7zxSPoKW-HK?mKDL#4%1L^<{Sy z6U9;F2G73Gw7V%?k274PIzPzGPOi;ZrpCei!tDDZ02sQ-26ew8U$3~i!3~a(jDFomhgL@ zdCoZ?E(v`QYiG1-uPABmB%*kX&tX67lZHKXslJkp$YOfxFoY8p%z}lb^}n(+An`(? ztv;|Mg}WU1aGnJzf2Q`FeV+EW&-(NCDZQH9J`Q}<+GE`AeUryDlY`TzoxL$!%$hj; zYPP^Tp_rXfrSenS51Ty_x7IO1%)+V7IFVjFqDeiGTAhBd3xK^YYC|ZEs;tP|B&yew zm;Fxew@V?<^Jo7*g9x4Xcbz2Qp3&U|vh>#=9Jc}T!>12xgeV&On9d)B#8VqJ<=Jlg z!mJqCjF(%NHslgKjc+3 zuU9H!LA2a;I9tHSR}k)U@%Zz2IjFS!YT)0XLee;k21(Y7f!jg<*GIquYqYw6U){e@ zmTX#lh`dnsoqNP zn(+Nv>|=F8=DKMWcx-7I&R4IG{Z)4lwe7{3Us-BIV_s2vVz|s^KF~ldfdKz-RJCjA zJ2_DcPNK%YfQ1r;JSwiU6csY(V3Lw%EY#_vjYcAyKvtJYI+tG|7g^or^)&hd`GIEi zxT0yt_0jU4UsGlaVn}t5zTl=w;U#erUS)Ug0?PK`pfF|&H!mNe&fGXU&2lW1Z1;A4 zOxf7~zT&#p&!_&mDj_12HDhLiKANNf>wd%lSD+}Z;bD>hNyVGL)uO+0i9Ys?_nJh{ zPNxwkgF>!!DC22x`w3(qBr+#bcbur$u$XAbA0|xc9N?aw-R~4tTE;+WQSCeeW%IOM%CvPE(ITzK)?=F0NFGsXr$SP3VV^N6gzRD<& zht_U28xw65)cOT7i*=f|Q{|k`hyBuxccl}G*H^!eoF2hUP05+)$M>fHaAmCW3<;%F zdG837AJdg%Ww=%5aofojaIXk!ACJ0hZY$OGPkaxjcC2)Z3&W-sZ~Q!Of{%RnveEV0 zxLPMqB%BD4co2j~khIw#Q%&M&dWq1Je&6cbj$buO_1NwjAXD?w){}DKUnX2eTCU}i zzImctwt}8KwQCSz=a(=*Mx3fN*Q;*c9tuXuTYC$_nJ)Oz`|Pi660^#k_C$h1MLqK! zy0d|*yso~JP)e_M88uvTS~du`V(ZMy?tr*6U}aCZN;NXJDMF>r~k*=DsG?nPWyL6wmJI2 zRz-|P*7{BZUq>mViB%w^iH?eZ110+kMB}P!>v#s{f1CxR{DVoL)sXVFbj!-6RpbPI zJ=y^H5_3C0Ij2u5mf6@FrQ)z|Sk zUK-bVE7NP{ zZ1Kv-jI5bMdA8mKy4c)o0=`6Hd>JVaY4)Z=;Sr0P4+#mk)=tkk6L*Ng6G*XeUh12B zRj!h!)N$j#g6CPy9)mu^!{^G4cY+*9{`MJxOg1~_lXo8)hvFxobLI| z)m}eJ(=h!OreILl|C}Pu1HNGn#VH?wpBMmjhMLnYSl_;EvaBZ;yPU38CR(dAZ_Mk- z__hU)H6KdQ%4ZxZ1da&PQsf#pB&lX?XPd<5)|6k`(UZeaI@k5-cWl$jI*&w2+f}(W z1$DXmnHkVkX7pB-ct1HAx?Fkmzi(+mWY+dgg)kZJE(tE~ zuAA}al-vfIYZWQhCui9e*-8K9Y`Tcaby;dl?L_2Vtvcc2pL7v0aAH0e42k53#%WH; z`OgU^*l=QrYJ_QyO)_=ZlFE0N#dj5(JIgaBQ{~E^JXEj3nl5ty@Cz6(2gu@BjjGQN$PChRY(h#1q5$`1q}3cl58wp1G8J;eON#(C9EntbL(CnQLJJ_r;CkIIz{=!!?U6rJ_bFk$25< zY2d)#c>4~1-OhH?|2##Uznmu=-Q1$x-i~X+I>XVYrBDeGxTM zsZwYi=yr(KKaM)xvQuwN;pHv!c5R7FO3|VSH^QN zcF49(B(xyT20Hsd;Tl(MR2s|_Lz&n)rSO8y20qG9so)}|fj`;|EW3@Mov1@BIO!vD zKF8~~rS9i)OD{hp{a-@|ndo9n0@?p?#QTMi54!5N_b#1CQCarfKIip{NdbUg73l|W zn?`Ul9T`aAlGArI_MSiL-wN0mIAT6CH(Ub))qW3a%rQ?i08S)Vx_)!o?e@c;(mXvSRRvQ*Y#%-|7&vznQMPVC*6@ zlTF1tu>?xID@KFX-y2>jlJhr>DO(bddd5JJGH;ggao}V7F5d zsEWP`Z@?={pe6PvKA)A~;g_mnq3O}hr2j$-{HF^b?!;if8~-hBY5uCiqff-tax{vA z)vhh|?&7IUyf840-0RY(Y~?#AikiU-x7`GfmTU9+UwR;7w;rW&*1CPi{^4P+#3NBU zc>mffS48TKL;5=k-^A5F-~Lh+ literal 0 HcmV?d00001 diff --git a/truffle/docs/hardexitschema.png b/truffle/docs/hardexitschema.png new file mode 100644 index 0000000000000000000000000000000000000000..09abaa44647b8842bd63c140dba244fa1e8a9abc GIT binary patch literal 86566 zcmdqIbyOWsv@VE~paFtgfZ*;BEJ1@OxNCsm?jGEOL$KiPZU=$}5AH4}xE$c%Op~A7 zci+8l-mIB5f6R1NpjT5}ReRUBckS-)>#z?BQs^i|C@?TE=+f`Sm0(~H++kqg(w-p! zR}9(IEP-E0MzT`kFpp3FzPA^~16Q8gz1MVvfq6mm^dB~$K@JzVi0mXSFM+)M932B5 ze^$zn69(oLjI{VW6}N?hWmmVCs*C-n#|JhZ)PV}3wr~?zc>!==P*5mUJ1?*3uEKF~ zRSx{xg^aR`=Q>ds=ujp+k2698-+GMMxU7hXz7Tzt_K7#{a+87iao;8lMuSUQF8PBL%$6I3*Z5)-qR zJ@XPPRyMOE=HhpcdBg%ewnMYyH#hna9IR%qHZDhdPKh6oIvv@6tVa6~EA{`I^D26T zI7Y|*2tl7!0TT4xF)_}SeD9QZF2mS6AiikZ8L4<(8v>jT_aIX}Kf>-oGmo={4L-`? z(amko#kF`SV#aNXs~P6bLACytE;GXF2_bp(u~yq?3Mes4-zT)0@$%~dTK?u_X;a6c zzvCm%x^JM59pmcbwp1a$>&aU)+gW{)%@@Qw?L({)$<-nZ-&9(8-z5@HRBamEpcBj8 zJIoAKcJuMDdAfDv^wu^V3|$+nl`{!$x2=h_Ehuc?&j#aI+%4X&8$90Xx^Kh>%vD^6 zYR2EJIs2dPH2CaPcsrP+M}#IIQ76VX#l;A=hu;buu-w>d@ekxD#wYB!3=lV#Ha62o zUxS6gy0%_?f!40*rt9>yNhpnHbF`I{Z|HdKYisw*F$6D6xVVoWq6Vn;@r_-&f*K1o zhQ%=+?(kOcn!YY0KT^_hfOem%7i~JFixtUBgf30hZqd^}xIBl_W z7l>@g4bz?Vm4SQgu3f2!T(X*H<+b7ICt=OD4DnnZ=E{A=T$CBFN3}e4MXiDK>eD#h1keBCx`muOI3&r?W)5dRqHx1m7%DjTk-L!{W3^a;%rq4J)0rP>*%e9+U~Y z%qZrcy{jNyW6D;sbw@9+IFc+slN{*z-F9l))R?7fkcG0$t3w2)q|AROz4f|chf3m6 zV}Er}TF_mA36+1KBb6~}Z$HZ6F_H&dYFoZH)b2kY6fK9M zT`1JqD1h_hQKo|U5l^gz`&FkAt^KUJ*IAc%63I zMmP5Styl=65cCp z7zrD}MCTmzbR@>RouzBwImG#LsxxiR5|i*}SZP!fxM29)6P4b0zwLL(fAv24g6Y8q zl@MX#AbZul#`hv!Q-DzW+QUi&v{au(4N+(NJ!pAiU!NtAks>j=u2Tk~t85iia7Xcf zOSFhLN;_koZ`A0|b%_{hu(x!Mr(Do6b|K%*^6TTB`O>WigH}zL?hX1PXZY3SC9c<8 z2NC=m*Y(9M6vdnT= zJD6>M-`X@9lv1WKc<^JI@K-gN?Om#B&stgD*l442sF|WD|X`hPyPXQCI@bE%>AdMQ-mOSP!lpU>aSDy4GkxRFfIAwmFnBI(vz~53Lr{ z{mh?lhtJ467Px8>PdfL=t3X@bsF!EHqeh7_r-YTxH_Ynw#MSWX=^>?@T3!D(e+aD< zE%%r{aolYNi93-NT~*Q*Q++rEuz`^y582 zka^$-@HYysax28LzuBI(7wFssKM_Ds(sOQQ_L#)$oR*>V*IIvQ(u$a!&2&%-%SDy=5F z$xBXrYl=~=5L42{joM54f=3T*utZ;4?T7oaBKUScpT<`~3;4f@Z3zD)>{v%^)>%j_ z(Mr&$R1Kp!E~OTLa;Z0u?9fU_N0j=_QN-gDmR(s$RLFWlDpl3JHsq&#m>E*teNsI57d?aE7Hy9_Zqb>8(85oMSjyMN~So)7$6zX+^T~U{Px^7U`uvi|h zdTb4XskyeC*>il{;qz@ya^Ld=-LJ#A$THsuac3-kb2GlIl)qUEnLqChu_BBYje8zk zkAjQZR2Y-WmQ`t5P95b?=j|jMb6FAi?v3Zl;Ybhvtp<-b53h?yC=mex(wf|w_|N#Z zH|})nNv~&w7yao`jpu7U(2IG|^LD?7gz4QQF6PKHIFt4NeurguhLhR)^U|jM8rMTm zFxI(IWH`84@ub*SXy$=1BLC*|QF9?DEFRVB>`3Lva1(hd^a6t;O2#Sc3LUCPiWasC zxd}zqXmv#DIQs0NmpGS5u=J~mV-afR=W81*=Mm)Mn|2<+XLSl z(nBlHN?K#nt$A!aoR{pC^Zo!IWDDFnoj*H_ySB)2=#kZWgmrhI^Y9 zju|$`skc6DKiwSr`kR)JvvO#$=I!4$VP|Ea>eElukHmw|;HxdRCy#}Yu4CuX(Y?#} zAVBt;EI76yJw_6J$E>r8zy{ysZ%D48^c2EA+ z2|2Xm($A~a6T1QV$4_zyiP`I4kYqk@N@o~}!SX}0YHm8Be?xwc?$E{^3SA{cK|ZwVu$O_x6A z#E_0ca3qv=G_zgArCs?8u0xjTmy!aI*bc{Y<9pCB|5CsS_Qi~Ms}815=I@PBZlTd!N|uWX!XGX zuUKApp3Joe3GI$(b!;+=)v)VI>i2TF5SF3vSKRK{=`6PW*nKzqBVl|~#AdfLdV_RR z@`ZN^-91(HIVOu$>Gzi%;iVNNc0RCD?z*Xkse)h3$A&d;Eg(PCeoG_ZwRyF{3S5?z zZIHf3Bc|BylBtV3crQ;giNJY}|G@h@S#S|&guWJe8!gmD63bhV*kT*~Yk*Y|Y?cE;hBGoJRh7=@f)!`%lnQO&o#O{6>d$*TO!%~9UL=E!HUkpWg_U@Ah0mX; z+9u1nP&Iq9P8FE2ymu#F7yYuYr=|Y7j?flx+Sq(Uf^YQI88;v+_3g$MuZH85;)CEB zt*?){!PRWRefuPVqq1>2;vra?6CD4c&0NT^6qQ%6;iUjgMbC;8O}t@dbn2Lhw4blt zGo*2R65FJcK^7>dt4`C)hSg^0zn+`Y4%%U>eGA9?SwZnA(j1Su`09)w!Y)( zTca@022@i)PmoXWygu_MUngt~NY*oLc1X`{*WreYoQ_4V2X*{ylSjLuN^{~nUZ2ir z)|u1ggWfydIkn$B+>dG%Gg>j=>c+7~~(iZ>QLW?Iww zh|1N_vZ>*CYHv|M9d83COo5PIzv@qst-+VwrXWGqd~il!tKWv!85>4LOgB}irf`s| z>F1x^=*k{XAv@~S84#*NI~C zxw)gt!Evpe-S|w?AGd+fjVJTr zYj5r1Vkb&omGKQ~*?Smr5s?}U-{Ht+UQYA(-enT*mBR>1ht0R~@}^28yDnANnZ7b7 zC@$1UYH(D?>)DFOulOxEJsYeIz$ML0dNuK?w({Q%Tiwr@K8x&YXy_FE#1(m3tT}SO zO4!S?*Aul4(AC$}6zg(XBerdtmW{cFCtS%l^P!$LEaUSwN92EY`+=R;73s!huoYR1 zK&c291p)C-w_k^*jdkD;O2G}`d}fvrHX3MtX5+D*p0^@~Wn-P}FQ3e|eOM`dZZ3ID z+c!zU@pTw@I5D5O5!L;?_yq{Km?7(}>!tpSeRO>yjB61s7J~j8iOTA{__5UV?r9$G zJ76W#h>hZ%ji|JFt!Wr?v1ZRL6~Dr+iGA))BRpLlDI_m&VF&u}I-3#%z*A?fWY+;@Ql1$EE za}irwelR2b`vsviR~q@v&v$w*~=EoglEdL{WgfaO43=z=2u-A14ijkaZ&V5Knyv=_tH)8pA&@2?~Hn-O@}xZ z6fNvE=4V#=r`E^Hr^PAsKk^C_tfULvxSH+sl|l5z7OK_=rW79nvdlo8g%Ic(@p$lz z_tAQT^s&9M5OD$3xA?*u-MO)@-fA{>dWC~>?#k~i)17s;pCxp3eh` zRUbe3HnkGhPO|oJG5u1jT4a){KZw)2dvjAqJdf+--z=-R{W^%B7Vq-TGdn%6)9aI% zY3y07Bn47*hfl|61#IGpiKxRknL*IuYk?n1`$#wEM>4s67xw9Ik{q!zt^0S4%xY#B z`DiK{KHA^rGd3$4R`5oiq&02tAZd^YXtp18rosi4{weofrolNd_pcDPLA&C;E^ny3 zYPNohtUlY3GgvLDf1P4LPcDsk9I>Tt^QnA1)Itq@667C6yy3V)<&0Yj5s;*>WQ1_V zOR;^~$HB5O849~6;Wr9l5MI+5gO0WJM$6%F8sZnzd~FLHBPag>*DZOmPs^DjD}mOp z7fmvPB8aXoRD>WaQw;z3zFs>gY)xuea1L&+C#BD-i>@!l*f=kdt!$P0Fb&7zyJd!ejlCE0 z4m$)Ky?OE5a@XPZ5Px-rX8!JM5G~pyId^1P@mGa8L1M`8_UW$WwZ)#37U-J1Wbw>> z`J?qbhZ%!NM%6gWhQh*honat!v*3Ze=02kR?z(H_lao!b{AYe~Vgbf0L&V9Q^Z{>yN8zPc(L^B(23nS0S=zjj#kJ?@7=i;8bz3bZ68I=s% z_J+-9fw8W(Y-cEqWqBYK+8T(M4#lXWb#gxE1}fz2c{mwHzRlb z#KJ7lT07J=zP{@1qg zsRMi#+hF~w+z(P&$}b%QcNWV7R*bi!CNH*tE$i2CjZM!p8A>yshKljl553s4x+Wzz z#^1daHtZ897VmlJ`<6l^?k3^LWg+ZX$ZPuZCj-kx@)skcIh|eQ-s9woEn)n&m7mG@ z^~geRTge}W!ml_d6Lf5plO5RA`_dpA%}I~bn*?6d*upyAe!VyXRVAX#3_%O;WB7Z* zdeGRq%-M}zqFcdSUqBR&+A~X?gq9aUgGacunh!=IN=ZE3HNMmzO`jp1x-+T_?ho>f zY++S#XPZMlpqar5%vz6JcOgSwBdb651t)e?+k@E;Xi_eX5410ciPcz4p{x9j!Hx&l z@ubfcBEPzD6(8?#zm{aP?rZC2Cf&nIaQ<3e+OR%(>)fZKkAq56AcPY_ys|lX+p$qC zaPx7fB@Gv1T65=ze_`vESy&LAorJ%(m;#FTHJs>nove^%{!+G^XR7hMY$n`AOn)6H zVGE2+7}vzg*R#$Ja9qb3CzM9k)Q+`6@D(!m^nUN#Ah$8DZf;`J~X{8 z@Xq54V5w=(eV=ttCqiz&HoNgo^0Fk-pSM0(P`2_JF`>4e;lh&lCor_-dIgu|Yai6- zM?4fG@7;+#&%I!>^=V@B+0K9<=e3^2&f*ecf2WcO-=>~-rlocucC8hUh}WAa5gr=l z{M!J*yS~@ou3P6=I)iN6yi$G}kLL-*&tKcavR~6MWGSkk5Z_KNekvAi>=!op(C>j@ za$r0(IPz=Pr0={m%s7ARQypkibTeAH2#d_-0f>Tn1hd{JJ6&`jD8O zM+fdn_%inNRGT>sU0`2cXX}wL-Il0O4mKBqVdlQ^i$rL zD(BNT8@e|SHuy#x4lJs}KD#nUj@kQBsO{FD$&oNxILzGDDHf;l59w8`SiV|nT24ZG z5e4m!?X+epgPE_{q%MzXSIXX(mj<(Yoy7=FRL<;1SgSi8Z|F>`XD?o1HrFe|e>sqv ztM|d5u~BZym2zkDyC@^3ps#F2Q_w8XY_Y9RNZ9$ju<6g*C@fqOqE$=4F)P$}k2y-i z;)Q^-BbS|;#W*HoJTx^b_^8WecrUV9F4eM@`yt%zbK7?8g}^aJ6M5!RkN2UV`cgl{ce<JGK|IVp{6d zrUV~wSD9~!CmRvHk({T3vO1CF4N_G&7q;8ItDJQEE20^cf~fBHMuQI z*2GosG@OkzoW8ZKVqTWKfK?oC4OV4;c{=4LpolU)z}<9IedNY#Pp-#aN4n>JZ{8U%TQ>NWmsrv!Yk%k z?1AiUElSE{eCAmO!fyjqfAd*NNJT&YzkNO@bBl51rkPV&rfq*L%ZWd$?ik*reji#z z<(a!-L5EFggF9dHE}t4DK52i{f!|!Oa)SXN!O$kTa1pWi z$Epmwh0{3AMt^0Cg^XSw)Q$zy|8Z5X00V@EzJLB+ULO7D{qoott1i%;tMdPb?aM>>WM-xf_~rC9uKQoSpp4(- zuAt-n_V%`ky101H@;~#Uhc!1he`xNwy}d02JhoxOaQ0`+&;-9)voj4Qyu$x!CJG7| zgZDyobaa~ktC;{EqM-?fK|n^Pr6;1?c>ZsXue#afB;JV&zLOyP5+G?8ewcgPa< z_Bn$@W9ck8it#6=mz678^y8R}T*>Mt_qYfik(# zA0By>d3f{w?r!4td>0Z=NelQ$iLbc07#0Q=7Pk1`o|-FkTUqGUD|FgQV~(dwXGP`N z@c<*}+qSm0Uj1@l#yTYdz{KLHr>A#GY})7_lX;edY1HH&EdVx_;uC~_&)0$})eF#}zsHU3-@kvKLrDWP zR&sj+OyN^lUESQ6o*yo{zIzul*=PY|#L$-+fVVfyffmm`oWwDgPJh!)sMN*><`7FF zEiL^6=H0t@1OJ!=_x6wX03To?=aF%v+yP}tn0eqBqqNJn*=jf{rOhZrtz$2^! zXs}kjQV*5&{P;$V`KiO4A>9&0tqN+&%v>N4)9tfGqkE0)SDsdo;g4AoPuCNk?A?ka zwrN_IVr6CZTZSwNo9qYm(WD@gT;zRz>R z#=#MD@WsTyP*4H_^9ir9j$67lCIrF7x2J%~p)begIo;vl;gtcP{_*Y>$^Fg6?TSUc zDfq#6f2Mp^N>Y+c^%KyWcsL7mfAZZ>y?Bq~pN>>YRCdMtqe+v&4;@K=c~Jkzf!Wvh zk&B!>OAf%)pJ?PCn_tb#&j&UdO3Ge*a&mo)S6p0N@1EfJ5%AC`r$MKmd$3{3$T#jq zrAoba?ysa@iTLc+bO5&i#}X9<1;tC?NlW~X24bSNrgWKqd)C=Arcdo7uqDJ$QKeK~ zT7QE}dx?g{YpEsRb#Z>$zQBkLY>Jr6z-=<3#jIy@q^5H#xz(y<I4 z@9clRO4s<)xL&KaySrQQDfiOHb3f?6Ecw_j_e{gbgGVvQsWRzkATrT|| zHyp`jhT}5!JuSq4T>Z7``>2ci$G3`q=UgnzH_m%1d~btLa1|K-bK}#^{!%|vAojrj zY-ta6y1Sycooc>cUo^uAbjIda?^D3 z#T1P(Yj?mhVl$NBO-%B!b+@~s{8~@Qk)yS+81Tx(vt}`hOZ5QI<~iS zU{o8fwBFUY5#HwJNY{Jfs5Dcc3t$wiR{fY_HDiu9ZuU-D2YHK3u4dqSg{m(Ww>>V{ ziK6q?ug)KvKhNEl-6vQae=Kvkk8(wh-h#T(YA`q)TJAR&MyY=kz`b2P9>mEa>2Vp6 z8vZsFLfJmi8;v@u>*ejq3YtT%|4ZNT2%-N1;Y01$9SPazWMkgmJ=?H2I)15PaEBg& zze0gEWi=l|d`u+U`m6&&Zb_ig9`LM0Be|vg#^G=+wl4gc-MyRY+^Jf+V*pV3CIK~& z8oGl`%fa8pK>XmP92poEuN{IVMe5H*dck)nntKho{?P`xAQz|Bd|s{*eGsp$3EA~^ zKZ;tF=GJwS|F7y04DA1fIz*oxg_h=d1TAD><(KM`4uH=d_))5j`C$blV2d>tH2Cym$92-72%)t@TL?C$63azaN6qS;DfTU zYRl(~*cm1{vT22Q)fU>OqacCJ`MOX1yDU8&MnSLM3-)C8Rze27jjuTS+#iffC9&~7 z$DPee&iFz}SYtq$=CaYTx{;@9d7!v8#*aAhv5DeKr^DWb#f3|cwo;_JF_-E2pw@n4lA_dPR8@p`Pxh3ZGW3oTMt zV*y!l2G(PtyIH@OuPE`c|0qX9Py3~14(Lf}=Dyu0vtzExe24w&{jgfg%ckw!{u0-H z@7Mi!s*^}*xgt}>m@x8`0N9`2D&rDn^+*okk+Iq4P8)4^#t$YUqeoZ&bO04c)8V(L zuumhcy6|F_L8E+c%dbnfqk2fRNx;hnw@<6>pFNIqHb!(Do9`XS$tB-^pnPuW3--(9 zM7M^)h%VEVA=!S0A^n=ZnalMvZS@eimKL?mk|)P&iX}&#)j(UzcHsv9rEh#BJUP3` zFsD_RZjYT$5f@4z%>PEzAkN5&&!YK0<_g)kwjUiK7MQA4@Ls&3nmHR zfDwP%=73UaGdbSGb#`K|!A`hZff2VAJ+GRT095{4$cDpJOiS z=B>K%TQG}Pg9ioYvBlt;p0P$6PnLSCsv&T7cz*LIGj8?ceKgwMhs10}-`<=M3y3ed z6*X~HrH5ZEsU?TI;mZy%6uNqLJuG<3r!7o46!;^GaG{=t3R!O~%~4HxE({*AZ?O7H zjLqPDKfktX?ZE}?(rhbUfM@+?F|W^7kESyIUjheSSAFgHY;OTb*KJ1?cnEfBAsZzi z>nd8#^PTCSf|p1_Y(|O05OYj5HFaSJe~fQeZF>oOm7~Cl zeum%fT<1S35T^MNSJ&w+kn7Ak+u?ynEi-&81~}$54(Bzm&;225dNA*WBxvY28TzxT zEuFhyE}}jmMG@)QOxKAH%Zy2ZjQ@oUW=pcR^Kwwo?Z+WNW9iI60r?8g>a2p0Efc=S z>T*~6p=)qG-UU%&w_tT(6tY5NAml~bEZGl2Cu--?3~rpUL>`3UE%f0mr)80Q&js5a zQ(`g!44pPS?2#Ml{pwAz+%(!>)k)}_yO?UW@9ozIkU-AC6YW8~Nb}<4{DBa-LXM75 zJv4Vil#D@bHf43lB&N1*+K8iz=Y6W`u>Bf1^C|x&(EHwBs5|@ZO_x6Ae+~@|7nInZ z8*LbQo|5#T;`8!LVgr?<_t1yN@mh7_K}{GA{+dq|{pkk9zx?)oAn`r!#F!y-9;TVR zR{1Tl`h!=Q*%*~kq$OZ>hfL7X-_Y_`P+vCQaL=^WqIOSyeei!#me9Fz#NuORNKNLO z^C20OFC^*(*c3XCe7}1nO9dYhn_@4n5cbGU?o_YNf3XZ%m9FjdX7W7dDe$T8zc9gI z=^aF7wS^y6w(Wwt)of;q3ste+yit9VnHqsXI zZ`?WR5A!#?aA>c^tJAFjsejyX8V4WH-UTNU+N;v-oQ|amTMDI);*`0Wp=c{JtF+j2 zP*tD^xgv#OiDp;^|EjCOt-_u$dghIMSF$Aj z@4-bq_jBU}OqFugbz3H2g+0HE_okuj?L<=Zu=_d9L*x0@u8BBe-Rzf_7T`u9y#d6Y zL7Dt7m+iU;&Ja)Qp=d~-!}{g2E;26uW%i3hR~L$0$@rP8H<&f<)(TkNk(z@$0T^E2 z^dt^B1;9qc-~M~e$=MQISZg#qBJLMOW}}M+xf2WdMTLx}5@XUbeBGKvC?dzepc5R@ z3J70+!y-^eY&IH~&F)35HEFd3iyE#yi5u||KQBQ4DyGSnsnVWdZxYdGTBeFp zSEIN{)3rD-|u_w%pTTCsf64 zFDe)oJ9BnF9OJ>k5Xtqh9G@g zP5IHI?4A=(_F{a=QPB+U%!M*nP##%G?tG7R4$oSt7{Vus8QuwVaLWEV)j*^4L$%*6 zOX_pTwZ)9q1fA5P6d3aPScV|47QDP7mtGrVGHK>$To_XH(ZKUC|8fX(l49)gNr1x0 zrWT98>KYMy48n%eXMqWaMnw-i*XQOh^%VPte<~~0seFg@xGyd6O;{g7$Lct79(OW| z_UpecmnPX+Xy|&)u&(=cry*Ha_B}SvI+7*VbmsF!3UWU>JyyI;rUe;VfnP*Mau1Vm zes*Hc&Cvm`s9b-->}P5Ew9hmz zeb;V<0^wa?XU^toFF{mu(W!f(o~^~rl-@~*FQ4-qH$u&yb%Ku#CcPqy_`sz#*`|}8 zQmKKT1Y_|}N&fWmNk%d?W5BrYUyX*lD`!B*&T4;;8EDHkgm?O;ZFKH|+Y$TJPXR6E zoFYaLimh8BP`yZs5TxD%mqIU{ml3Ap-qmGAkn%e7jp}gPn8(MCS(p;fL^&%G&sqCd zlRYODiqj6&J$)p!qaOo)mZ%K}P9N}X*&PPyMB)1VccKkZKsq7LFNdbhsMUZzWRCh+ z+O$`K62zK`Tct}MqU%|i(=(6=CP=j1uBaAz?qUTli~&*4D21%VL={RKP(Y`u(&@2Z zav4&1LLFT4Qwdho$3e#VlefE4%cINB8dE-zYxZZlO>SQ@SY$B_g1`bvsMW_of(~B^ zT@!vAhd}PcW1T$EvlbVQ)3rXRYw=XA&)o}XZ^X}4o04iaFq+RdbfpH=aa!cdTBmq_ zMwTL_309Z=)+p$0OT3y?$G=}6?n}bPo-xk{xl1w499*F6P8m2FNf1H2d#zYMy0bkulHLY z*>Cd`#8%Aid|R=q!`;=oY<>*&6IU6J4KnD( z_E%vkv6S_Ia+YGh$rU^|yZDnUKH)ieASIoRiGGRedSslx*3~09 zHB04w)t|1HfVY1K)^2!nA#52|;;*QIuzkn$mS%u`JnxOw6u}+t*vew`TU4F4lH}e~ zDk(c7gVGoFEqux(LBz-vnZy&56L&C4tokdbQM@Z|YuO=W9;&;*tBCo8Rux&`arR?u zVG7#60*wH4D(l9 zmRNSIh$&C7Tw6dMs^}jKx;#VeoQ3gJ!!}QStW%c}?P|U~5Y<6hVCkN%hcd{d>v$@l z2o!X5h9jJuLa6pn`iE0IIpc$;3fahawg1vs{ExB__=W#g7Q%UpX6nF1ufS%Njew{r z^IZ|w=kJBXf-W8GXgVC3ceM5Ul^nJxo7}V>JnX=ih2fPf{mNia8-3}{^pMR`zdmnF zFErGC-)fiM!=m3w*8034Bd^0HE&+@+&@9`~_CQ~92Z_=oJn-yb#SvMSp4u3j=igvh z2-dlKZ`t=SOwNeIj!w+2RqwcYpMui3ikLwR2M0GQ=akN7*ah*vIlnIcm@CUWhbL|rpVJcVcP-XW#* z^Ec6gO-oD%Wz;J8HHS?M3t5l$>IV-q?yKQ^UWCTy0a8z%c>F-Z1!+bI2i6kd?B2+?{^st8~0z?cTX zMtXY-s$b>Tc;4hP@#&nD^K(p2KFmvYu>5B|$b2kLK;Ck#yV(R+blYBQpli4ms<~`VT-!YvnS~}vD7*3veuu=-4UnDkqW%2(s*cg1X--n zEobm*d~eA`3T^R0Gxq7uzGeM}3q?MQq985%boXYF2(!uZ^n5?t`Lp~L>oEswXX2d! z_u;G6<2;?M6r&iuu4F~UPx3i9RC%vjqAn7Y8jvsp8zJA+yo!RFy%Mm|t+6(#~{^v6Zmv&Ne39-nBEYB5|}?Bvl;y~S3Y zqUV^6oI8cJSuYfl&G77u#nHVYb@PsI0|}4wu(585EsZQ*tmBT17hMl$tfWx5>L@z@ zk3tOKJ=_1O5F^ne@_!@57zH`CbVhv^GoKgAS<{Fr+gRXHZOJ^c);EEM$20j>lhezl z8P0da(QzUKT#5Gd%3Q-O*sXkNHD94gS!QHC)2rwka8E#YEI6BdPJBptl&1@Y%ba|j zrmvU!qx!(1uKD))0ylc@+1F-4VQ*%A`3!|2-bb+u$QPXV?~BNhq)9RbqGxj}^M{^9 z4R+*vQ63?Sm*~bb-`7k(`iln>pxVUIkJ7eVro#-?*B%A z?`~r)HAq`-d{`2|*S;)j8Tst4iiqchkG|ddtHv;M zSIXa;kn64%Zt+*qT(XU|zTs?m{N42i3`YxBNc#|AC{` z&OlJvLTr$Ex!59$db+^S0Mufkp0PhJOObWn0zc(3;!1y{+}PIe@M?_zdJzN!$#+8Mk@G81UZ4- z)A61R!F{j_8oegc524JR4)}_KoH6@`k;k}<8SSRWZF96{5XHj|Rs)Nklot=*<=sFu z0K60fadIE(x=@~a@m>X$-U zvoyyVEC--0a}u;}Is*~bsZ~rI?*jtlrDY%RN%p(jXar3rg!-d*@W+tH<$RtxmFz`h za<(F4p)VYl)h64fzt1_0Z>D=Xd+N-#mNtv%?iWq?W$P~&*R>}%NmTbc%pA7~togV(;6UpkN^e|T zZ;v}3%XwG5AdgRPgl0=nT{OzR=)keK3&=t>PJ-?AOUS8kzApA^~h_KKE(hyAYisv74C8MYSJ}3b} zc7CPx%{h@HZES-|!zWdLq>6W zv%d)F&aam^zR2mqmjJSJtE1ej^k!9-#lJdT)X4$8!qZBSbdWH7+oUjXp@RS%{Ir_H zz_OC~;p=;yhF$E>HmbD(lks`}{CReDb@evv-b{I`K0x!ueJDtNQd{U)jOtY+-ZnNh zHC55bf3p(txpPbGiy}Ur102fuhb@y8&pTgua_^I$k>^0(p7Bo&J^*@xNiGxMh47X> z9&kX{L&#SUtBm`j`xJ#PrfS2(L*MT<_&z?gzyKUtz2&TM5m1Us|M_Nj3;Wj-QI;ze zlL>pWS6V4tXE9xJ`R5MjleHfUFw-Tf0y|)EGC-gFd&}v~er3!PGd(yu+7L~`@1W-4 z(UO$|aHns!N4LhA0A}ki5=e(qR8$mOa zqzM+i<{utON3^2-azXzQlJzJD?{<6G*w3QdQWx>m?adQw_lWd|_hMmJE>!T&Q!CdB z0R#^wfV_h9iA%-B1-=ubqN3`C&Q%*vzXd4Byib4F9*3~!XlQb&?8becBYHOkoqm5P zmm+ijRPxlX2MM3u_h|EPNWd4Vp$UKSYAo+`TbwlCxE#zi!U8zI%#w(}yHHU9zNHRX z%GZK%-kak8{^W}%Vp4ny`(i?tRY9V`_V7DfR$@Mpg5Sf&s<%v13p zDkg>l1OokE44Y2Q9l(a0ji&Pt0vxIo@M<}dnD@w8LPC6NqS5tu1o z_NX1Y0yQ!+VqgG>#N;I1Ru^u#XDBE#(UFmYB~NbrV_{yx$>rtfH$ahKy|S{R$ zd;E0c%O@Knj{1Scr_nA}bZcj#h22v}O)1-X`aC@&c_a>|O=SwqYrWvKs0?8JAn-X( zW)`pQiXXq@4jSoG{7I+*_WX&3?*PAic1(96LAHzhvgsc!fIh3N(=CmvFX4R`W=t`^ z#1gH=bYb3oJ9T%51?Ot$WjF2%EMAN0?-Owwf{)exWNCNZm?BF}E{6*ZK!AC-YB$>W zsuU}2H&HSIy$|VD0Q^t<-M&oC@-mW;QxX{gA&&+S&n(&Zlai+unA33pH$^|CQ{>O%IlVMM z00DuJmj__&?D1gPSx0pq5BX$OxbZjMJ476K38enF65=FS0&G=S&V6J8Qly>-EjoezoKLQnsRBM7O288R2?fY=QDBT1ws9}vI*HJqmBk1vS# zbc}&7&JJ~&9eNRAfC(rKB{I5(Z~!Bd75x-@MiID$v)t;ce{^{04Fe+yWXX$;#|K9F zCu3|kC-P-Q;Qiv`C((;lO0pw?fsq-`UI4SZMlgN9xlaUDrWo7AqS1V2Y zVET+=YhSh_F2rV$ zDYkBNfS-Xc;>MhgmfYoQO-Ec{JAougyVT-bDrgb}44w&~I8jkvei|MIA3vG#kGDks z@)o&P%_nI^S=k}Fe5K;w6Zu1X=e!_brUUNyta@c=FiOQLn_F8>0Z)eO{cX4y4-e0J z1U~B#dY%xP(_jL9?jK({2L=W((- zQu^&47qo*YfD_x+*4Fl5*7o*@M4y)ZAH%DABk-Xt8dYnIi89p3OU)1>;CEr!3(@zZ zVG$9W?T%mtei$HRBwv^St0eR>Hsoo}{bglkdaRl?d9*MX2bM9;aWqRr zU-hNL-wwv0l3en@PZnv-ZDcehr(Fme$V%00Y@La<$p9aEaXa zj-8&jQQeELP@Gw)ml5h7^Y{`rX)#$Aw9}~SXx;oKYLv%ft9`6j(oN<$Mf08pb-3uw zbS$^!jG!zbMW7cnMqUOMfW?{d=U?A{_yCfeL>M;Lqb1ngMuM%bNt#Q${+SlAYSl3D z5Vig(n$}tzM@a>2Yw*#0d-K2x^?5@XlmU60RnQ>;KE4^suSCJXuS@=a``{Dc9{316 zW}<>=3u++e>n0{7d@5QTa0xsgz9U=Sf3u*+Iis9MFt6sO+HriApKRQGxM=RywzaT8 zQJ$vGLiWl0`}--*YI!>F`1bG=yrD3|TfdtoLw$h(TpGqo67L<;h>QDuIp-?2&|kc) zgxX*zGc2YmoByTAwUc_g5Qf;7q>?5X2amU>_So%`r~cz@Ok87IA&+}Y9csI9jc6C= z%1q(vnEPCisg!3}9)3weIt$+e^2I;M$XipMU2RFIU>!oN_ z_yf6fW3+NoeO{7wvl&ii&Yu?5Z$=82EG8tgg4i|Pw|~oiyRjuYf3Vgq+3fQU&)c?| zdhiv%C{a79%GB%+%?P8wAhemCVDAuoGiRg_!XUfaU_DjA|ITs$T#1cl@778%0pa~_ z(OXc@e65)!oSzPhI*>wlIi6s@Y(Gj5C?z?>Z!ZrYVLKNaZ67hW1HMrD_Qq04?Q!&p z!?fvl_&{niX+J(AJLDMlV~^_T;xEulR@f&_;B04jyJqUVlhK^JQ;=R*Q#xsR!GZhT z=td%b*}K&mYPr|et<VmverhhU@Gyjh>!-8$;T{7Mj(6WekG#QUzBf3xL0(J^VeMWuR2^HLkv zif!s0HiBuHbqCe7NVl&e21}oea5D+JPD6IRvmZGst#PqtLVyxN8aiudHI4(}TO zZV6)gvmg$ilD=!L|D3Jf^${~Dj6XIpD1v=Y*j`^2p@I023;|fiRm+D-RurCX0riE+ zNv{r2|4l|Y9}bffA8v0UgnlGSK<0e<)4n3pp4^korvxw9W4?mIZ{k5J84hFQLI(Ox zff(KtK-{E5I0APgQ~b#z)b||&dGbLs)eYgAU3yjs^^nXRiXbM#l10PH_~F?rR2I!c zgZA!p%Uw}dYx;0z*=g|&MY^Hr>IPhY>#16Ln|v*A?58!AuY?QX&-)U&!Ctor~anA<+>{#)n-X; z(f3LD-%uZXi5q@>)?O~>>d2te3}zDHj3-(U7^jA;@d2i>a2Rv zh$o~F*gf#iG4xdsN2h2vJ$JwOAd2Yd85NcTi2BATNt6Yv$ z{hQ{=^hF!`blJC=(vlM)i1h%7s+E3Rq#;|4+ z59is0M?t9K^C3kyHnC%GXAjcC44jQsI4_wGLh`8dsKoBP^yo=D1v!KEGbcLK_9abx zNv$+IfMAWCVg#A0dJnB%cnwgp=FEl&vaV38eyQC2p?=9%+66pjqxg4M8d&g?gVAxT8 zAfF%ir$|joI)f@Ao*mH7RXzJ5kwLU3`SO^OgQC+Bz&Zr5HH%f6g7$Qw-#&V)IXX(w5n*Q6jnqk(=Cx?0E zW3#L12>jpvVw3kua^p6#oD{r~sx%1rmroO-`>&yQ6p;LJhOt~QqB z0rUwlb%PViRIoEo$sNyCqZ!!mqt8R*16gW0U0c_BU}GUpLn4Ij;#^2U&L|H}K2FlH ze$0SHH_;~?_!`fV7TP}?-6!d9uCvzA{mX7MwI1qGBZ1=Z?TtRrmil0{?k$Hb^V!+7 zQ$B&#*3dFO)5$xqw+n_CmWcS6S0UxEt8YQ)Fo$?q9Z{XzD?{+`;VQ#>lyfE%CpxRM z^(FcDaEiM*%T;mZNU%i&e;;4W9%>_(ja{PitiOE86wpWTr3Hyd%p6&cD7JsmXJwaR zGo9FHCpC!P_2qVAj-FpQO zkO&}_j1%JHQ>#e9lQ%=O>qW(ry6)jZR|8b|gRuK+3X_gqF(YQ;oqV={r^{lE*_qRr zRvd|7O5g9_sTQ>8O*3ru^UX)* zJ^JS}9AV3M9hbWxD9q6KlP5xfS#~JTKK?wrl;eoX6PXWCdmm-w*tbEZ!fI$0<>M61 zm-U(0cV2T%j$48;guJAj@-p%CMm>MzLOehpdHE`}tNQL>BSSxQ==xeF#2}elNZn5;5X5!`Z8-*xieN`AW%OA8Erj-i8BB4q^5pE zkf7Au#{4oSqyA9q;@GiAYvQPjZ|t$|5&Z!U4|6Q_Sm62)_u}2iw-jg8X)7V~%6e7{ zNAw(776Vjw9Eg4s#Z-H~`(fE5Q^r_^V3a%Jn9FsL_%q$~37o;~JFEHk z249`WfE?*A!bF8O06g6T@^f?VMYqm3dOOKZobGKxJ39QF#KeLycH#lN^BcJHOJ%4q zQ9!G}-)8ZPBXAXvnT4g|0Kjuuyr1&7wZd-K#!Tk*}^^8HyVWxqttRkSUW0@#Ibgi=C>d{=9=%aepbbxy36!hW`PMO%CV#nV&XqI ztgOs*np`#VaR?)CzBqcP4r^2IcA~AY-A-Bf--HYu8@;IS2w02QoU)uQA`^Aa?~{t4 zMux`OyJe<38FsI(ty5a`1oNIR$~>}$PRQRT&5?n6L8`ICJYji8vyAbnVr#ixs5vva7)FDe z+kh#+u^WJSl6R+NI-luDK9@=aDt1Q5Jbf;j_A!n&l^zJXf(bw>!rn~3*>7n1)TgrN zSE>74!|B^{4ad^?y_S)r?YZQ+G$*~n(x!vPHfv|I{e#=m%;3cjkE_?(2>i30=D!34_Ug0n4v$=akC z5sW%7P99`E%{cvPF(Xr@jj?42nLm5?>sl;X^Zu=BI`*5cK37*`M3mmwv~0#tMk=%& zLG$(lyE&*;Ik(!5dQk#IpT6($b1~R@sWEdXY4O!P*}JCBrIqzyJ<;5wIx*QfDk{>e z;^Q#l0{*h-`r^k5!M%%~A<>=wVf^WIk1=6qgWedvy>*25^03JXFl^@Kt~svWV#hnp z*c^;JwV6Jpoux{BMSdhnvZ?g?406YtWp0_Z2R7Ry#;sm_@?1$ns&cYuZQfLDO-+@) zqwI}2$L=&RadKCgH%@gdXt>X{C0kw$f|B_O70w<}7f;36k0Uqk_+*D%I^LYI&RXWp zQ?5d`_eMvKF(bBhQ>s)1*p=7$Cx28;>=|GC6d^2c(kng?R3UPYO;W_A5L)%dX~x;B zzve(bMnY5S?49p!-M!wNojYw680K3Q>$L*B{Gyo+Py}8NgnbH&is)(IV_{)6Q{(Mj zukeZanZCZhGH6t2&vJdZD%Ywlat2dgm0S2B;m`En+MITVaqU-{HcU-S-uYeajv}U{ zq$nrjC%Us}C}L)>wW#r5OV(v2B+dH^FC!YQCnVN0$uOPOFf3MW=6v7PC(>~Ig_Yad z_^|=ZruTrBPx@?y&fPvhLHxkVhZB+)4H~&{6AqL1@!;6CQ?u@Doz=8IopZ=G3-FJ6 zubV?=;B+D;A+eiobwBG%#!f80upA29Sp6Y*#3QhMx_bV*N<3`zWclzrO6OUu{W#;1 zI1nzq=vX!4>a zK;v(@9PBq2j70iQ_i5W%x5*(-#>S=`AB;vmo{BeGV~9-v9~%Xbmab>bmcZK6)!m)J zCoM`Uf0eS?8XyS@XVBtuV8OspHh<7)4|J=^sYbyHja(+LV{~Y!q>F?^NWBEbq>4Il zuE6LGiNgoR#f@|86(xP7(r!_Uihq`;Nh*PYf_lM147~)*26aF`dCaH*1f@5yqAUek z2V|%KL@-AW19Nl_Z*S6x`FX{mFZ^g|aqraC)vM@CLbmO(=|4B|`2mOs^vii~Y}b0e z@9g>iqts0B6*{O zG-#Jkt7H*h=Jl?(k_+C*sJ!pQltDuI(73#9Zs93hd+Yy=+m}isBtG+-Uzz&N;cPGy zBV#^T>sgVKp(6_ci6qg;yN&EPeUm9nw75Ov`Z5DwQ(y1tBr$A zVpOqx3*I?v?~Xi!vx{aPYuag3kxL1rQu9|=Vv-wk}%Wln$d)?0mJO7TG8AH z!Mu=Tu3;_VaGdLId%AS!w!_^=g;P!wn>xkUzP;2W%r_EVgUt1FEWhuMKH(REq7?S| zxCsshjH5|^=PoE}9?uUIc<-BA%pH!*g>jK;CceL?kG91eo;&q1AATJWk{K0jkE>L~ zwmEOGUCz1FoD``(ec37^v2S?XkH1?Q=WDwCc75G;`d4sdQI|tyP!-vBxbyO`*5;rP zZ<4!R-uRDXZNTb{d2%C{A5f0`Y%WNW10J#MuWqWIb4Qq*J z>3nxR+pyvE9U`uA$oBqmw%`%Yw-qR=HV50c_19piq8!;xm^GG5XnbU5YJ@Pu!jfa{ z4IjF@ThZ4F2K$DTUs$Y^)u;K=Kk73%##9$)59+uxvm<~8I{Os ze_r%lt}ux6vGF~_@pO}LMMA&>gm{#rEy%7y>OI>2lfP8?H7*lf2=!Ck*FRo^jjVBv_CC1Venx|G~GE^k}h2P0>#>RLPk?=OX9gm&5h408s zXmg_oTz?)xu@ug`$H)h)%qx(CxAzk(n2!S<6(Djs`2wvvtoV;q>1a^`;J%mQLtgHE zwaLY1U;9)X0unCsancU9$ao4?iA7hoxVAPQ6>UAj9?|C2PADN>_4^>(yS=9*4~#Ls zx;Tvmo@z|7v}{?G&Wn?x#ZQ`vg4*b`SFlES^yYgqg}Sd*^OD|Aj9 zlF0B`cfXY;w==@*Ev3?KX`(hiZdTV6Z+VgzX)u(isV@6Mc0oW@J2{_;-(qH$cX&5w zI#4x^mk^b*n7= z*;YvH5A;1J=}*KrHJBt20R=8216f~EGYzdYP<+YpdDytVD(c__>ym4*2Lwm0gOb@M zX(A|0|8!CGsgQoM?<7k5F9qY<@81zLeBZ>)TEG6jwitgN9%5a2 zFHYNG=#A|h$|u`M2`eb^VAGQm7-0DO3Q6uO?3yyxzk-7RpSCbR4D5kF?tkeG5rE#H z`*pPBrf@Ih{XbGg&aDQMY^Pj6Y+n&8p-S!r5UcwJ@FD&v9hLyG9j0JA?;%fzbaCC3=w za)WJ#;^Q4vghYNJU{X0TfZe`T)h36HJ#fI{`|Fy^CwB5}Juna_`m`}X|dkbsnh4+N4{F;3k0u6s&Zrn^^}f#BV(I*wa0dtWnu z{6~}qeaHV+6By0VIjQ}UROvfi_!sB{O5!RIusQu6))9=6nfF-vZGXOmPdN94=9G}V zez$|qj630hBx6_s8FN)a$)o=ko&c*&8j=%w4FLsZ+6ececz|j;3VEK`ekr75# zdV1-6q3rir?F#k84J0Y@weP*p#OlLb^E>`rC5;Uu0fAAiJU?rvTlK;#{E`%7WaBx= zHj)pT^rOsIXEh19vb|!^s{fM(5HK?zA!tV%#Xn|OP4MV<@EM2UIQwaoZnX19lTk_J zjVl;-9_Rk4{>^o><}b@{_MB-n^;}?{vC*tW#`(O@lYRZ`nSJeVw|p z`oqz-L2*g~!NAVKBjQ5`(d4va35oyEoNEO~t6JP?Ad^7L>Dzmv*rHiD0|KRS55`FbWaBTmQtZD-_(TM$cd6G2^9Q1}Ltgh-?9a97C&VPN3+y(( z58Q7q9=<>-!OEJ5KG2n8FAxZ3`dQlVD0_WSXDS~ zh*}Q23Y*65LhZxYq6_z>S+!n!W>NakHeFF6+^S&yHaGs#^}0=cv^~X0i+#(E45t@y z-LFe~ee5?T<04$@Z-bmtbEpYiz5}*@J%tM?PSCI(UMjS2Z*Pr29zfLRt>_*>=22Y(P5=NlHP*lp*kD9(zv9ZH4gms70aJMM$AdwRHDfd!a4(b7@C|Ow^E*{ShMZ&%PXX9!WFxZYz zoa1$UIa+8!|lvoA*Fw<%*iXOzfk6BY-Ao zs^NBFcgrYzryUDg18m@7;GkPTVOheRW%s>-$aCq}Uy1x!VdV9{&2)&Mnm zUYUnF0(ulU9&lOn^C#^{yZ0S8WB?E^D=z}>f=k4IvlrV@Tvk)2jX>gp4D<&`H~}L; zzA^y$h(wJFgU*h2V7+AvRpfzb7W2x0zUv9#P9Wuho=CY1gs^fyCQyvmX;=IPPH|Rh zYRMdcdk;lT+0R~HUhc2L*!^i}GQA6vFS>VvB4-_(a#MUcEz8c8` zqc|*EO)I%-9+$Y4TZ$Y8G)i55uz=i}eeh#0SqE>O+221<08-T7%jkB}a-n`LtkX*) zkfIhl>aM!NTd%yc_*LQvI+gPQZbZt%=T)RYci^=X*5qi>`y=}3IyW=ki#4J7^Ao9m zuZ`7m+#LhQA&2HtDHCc(O8zD3JX?Ms9o`AYnw0wTMz{*;##DnOufsK`SWXz_C#LXf zd97sEE6G~a4q990q3=)5u1G1)zW%N4QKVTC>aMUUe@@{!QlPf(P9LF>Jmi2$<#w=V z(FYieUuIzjj3q>VNwqKHPS!>q%W~6)Fkf{2tVbh%G2>H@v;R7-y;K~Fv`K7pQ56?+ z7l_$O(p|?~`1U3nbdL!KH`i4YRk9vL{Y4Q$^i5kzYc~gheNg^Hsa%DF^JEgO((Mty z*bEu7nJv0PHg9G;Mrphe$*+N9=EdXN-U=`tZ6H-L*%ONN1R2oY{_;-}6?|4-=0E#V$K8X%ahM0*#b9JUOZCh$5*5=t z7;mI(c@VGwvq1Uk66PK4^jPFFy^%lZhMTcle?H?wSAZoD_{)s}*HcIOfjC52)O!Jo zIR!_(Kb{rz2UOJ1xBA+ioA!!}rNC<(r_j6fg9l?kCRZhRmsUgMF`-k|(t2Fgy9ht> z^COJ#{LkRc6e}Hg|7t9MkAe{kzSZAx^?PMZPrWaTLB53@9JGw9i|%U?K`H$$#GJKkepbFweK+e-9*tDx z&CZZKo4~X1Ush`aC3XEciqa&!7L0ueYzc z3YvUsHCj)G`YO4M3qKRx@=@}yd?}mT?^<$QI-dTJDt1&2d^xpl1x;*bh z5DnW?rpH;6OkfTFNaOw8dIzk7hkcKPE*f3{apM*!IMR~USZHaM4oX}!rs+dQwc90L zrbitT1CD3jX2>qE?vlGamR2YEy$dKZ&8`_<)at#s zjlh0lvqDg==t6VS*DyXgxh?dZ_<0^n3}uVk^=!m=Tn4z2Vs~_s8eE>lcI8>JvS;T4 zAI}tHD~XHXB>|ghywEZ}GXJ`8rvUhK@7Nh)%(c9U2R%mNpWBY53 z!VTd9!BX?pn52Gnf;nT~P<_!_B8k(OKhX8QW}bBHeI+954B;6d{N%`+%mL@`3i+M1 zZLz3Ny2(ojIp0w-nf|$3%|k0@V|j?#X#5`bZLI?;mP}@(W65!Sx<1}PSHKbD3$0S+ z4ygkJGfbRtY`km)|DQj(8a09fdfSE*6avQ>zvFx|50+=8TZg8VM^r$Hh}|9jRYz`I zk+GKI^IvJcfSBEow@q?Z^#MsfxWZvc5Y9mrZ@9jqqGSnb|z^VeLe?Ng`rktG|akmEadj zUOv*H>oKauk0;*tCJu9(w&EvS)J-I!ob{-HlVS{=Tp@yo28oRsYk2Kdl-foiA7}QW z0J$;HD}e^?ZBM@vA+I_eRPgrurg~Sh*VPxSOzHLG=t@oBeS-Wn!C{RmXsbce)J`re z3cOT_l=c`d;3@+c!O-;kJ%muTq|S+wbo~1f6wT&GisVg(Og&!W`6Os88-A3m(zJGe z7z7TmNUbIlH16ey(94Qy8#7|rL)YjX!gTN{4U~aj$4!EmG9(I z5#xAVdQyjE9X8m)eJkc1%07cG<{OM(egU-5l&Xo@HJyT*)3)CN0tAAd-mM z=@)bl;6qYVZyc**M_!p!Upj0*!6at#qnfJ0`}x9?^CSn9vzN}5hJLZ5CV$vw(jjFQ zLHMQu-9NL&K zCTG@fA}~^GPjNW^U|}!2%D2i>yc9cRN8b1NvRZs0)P$D-pi2MGdiM*Z}l4av<_2L0!5M&+w9E+B6%M);J?4UzI-poFPk0s_NhD3xR96b8s zw5yoJe)cHhAX*OCN77fltJf3l=NsnZ`#XpkF-K0qR?IAh!S0OjB9Uk4x{FQ7^EzW8 zQOt1{pF9KbUebT=T7}XJ(scJ`Q_A@fi)*a*zf2Ec{B40Q@9M$>vEfw7Nt?{o-TuPd zbo3LGmlMVd^(Nno*W`c*AD0M3QgY zTCr*>QR-<8a0%9IY$Ljh{w-&aBR-3hN53|LU$p*6t<_4$5Jt66xX;3wN#=o825iKa zFK_uc{0=#IQ9+r#>&4o%)E~aKcE3Mw5vQYN&hCPWAu=nS3+PVZTO{n&4mNu88qYXs z1$~KIiuF4!GA!9c-=9Zpt@S3Fc=E_*mZyv3Rs{wNG~IVgM}7S{?d_<6@==cZLZ9#a%vAn37{`xRN zQNA0($@kXqU(9O^#Qv0whd=Md3BRUZ16Cn-yW2^+GeD)kHvs`7I)LO-nS}uvXiH9l zgFk5;;UEzpIfvHL)TEpD50&%rrbdhN3+2Ty48msoBYbR5pM7!=%;s;`gA@Z4@yA3v zcl(6yZ}ehoNN(12FMfzzeBm-=1{wd>6OdmIFhoE?qQm3e)bAV%gc~1LYUx0W9PE(y z<9yQtEGoF9?^5Jfv=WkS5_Lti$4H;LOvD|I5@N^GIm%&jE=E{gHb2iWQ;1c}buA1N zK!URI;SnBN@XJK|0zLyK^>L8;VDo6&A2_L#<1(_$#T4)R5ZT^368f`{lg zie>DxZGUJWs0nGVekX?GZTcB{FY55x4NKASJMyhWFNvdbb?22oG$n?4IES#xtN@S2qIiAYv{&uaWXqzTDoXg+4urT=r6P0e6ecwu&}WiP&FW_4IxadK{zb#s^tN%x<< zMb!pJS>u!^0j&Uh+~iRxGWTtJ#j}A3s5!Mk?4b3p zA3hMM?h#2LBj&5T0Z*`Nfn@I_B**>~Q36_BIsArqx2vH;iATT+qL`7v2EnH3W<&Mi zlb_55-0^pVD#N6b{35#&662F8HJCoe$mJRaNLArz$D9PJoMn;98tO|mE*m6{$M#;s z=%5!ngx&qb_-SPiZ8qT{r{~M2^PXF79Ni09scbW${Q1p;y1(E2xC+&Cs8p||^33_N zU|ArdsosfwtRE85*Y_t$Raa>R6I+L#mFZqTKO1XZ*b?$889Uv-Nllc3FaggFyv3z*e68z{GJj{+q?r$$077fA{#b;Sw4SzPu zww=tMSO2~tHGB2A?NF@z?Z8Upg=ml$Fkm+Kdu0|;S1N4Ln z0VjN}6HupQ9~~pW&;Sh#4gRbU6d|u~T1yNRWX+v71#5DcQ1;ZbV;$9DiVJD4Lv*P% zc|Y=Q@_}eC&R4X4M+Ouq!C-M22jGS7TcYsd$yIdpU*X6Z+57>$VxpZD3d((Z4@iB~t1xqMsxX+XFtFC&h~ zMN)MZ74X875PzG__t1TDq&kuc1im@?ktxqCDE%!qNUt2se zFxpskbw|u;@jeY7a)%`v1D!pi^}~@SCq8D|mThNV_t%lev*THQ{mq_>s0jzUNEe~6 zqZS6nI$lJ2!Th^oIQENE!Qy)eKQ$x}Nt#j0UWLMbD-x;BY`p(vwSt!!^{!j4eWJ-| zs1A*f&0;`!#PQ`Y2hB6*GyNak5pfxJ)JNFpNlov-_?XMgd_m7d0Z_cgPFqd=)d zmmj8C-S!cZxsdw`-`(Yz!O|`lxGw3Dm%gFjN+7{Y8fwgN?sfi_&AON#PvLc8#pHqF zH++1NLAQsa?5|^`V#x`LGEhG>QXidYo5WmM@+15Z)*u=Z{*EdRb?Z+bE9(G8>gW35 z)?x)xPxK0Wde0@%?o+azSM74`ROr^9l)SjgSZ*~A0-h~!IvOd`t;`KtjRP%g0%c=8 ze`^zXISTPH75T;CQF>JE5W`Y!b|oQYTk~^l<{R2OH;d_Mnh38CZp_k(Wz-z3UXYKy zsYA>3+?#Nc%mo!;m{9-dhVE%Qe|~Vq(#>KtoVH_-suYMD6~%keYq3wCzOA33GMGqJkL1CYtAxGq`;MCcvSwXH5PByW>8 z!YD3tr}5h;-f9JYr0nVDaf3*vCz<#GO%kh{lmV81l`N?@`pLV36w+XQAuhuTj|f6< z?u~{5uE#g*0JoTto`CR;$4R8GlRJWcf|w4YHNzU}hr2Y1!#?1iiKtlcx6IZ9k+Z~C zGMuc-9zzxPmEvVrMy$f{!v>+hR|T?mFYz_zc(>tJxo7O~dWXvaqOqGNG`SsFSS9o3 z6oyAHa{77|XnStK%6(&aV$XUjZBC>S2k#EPN&m2dWAz)Xa;Q)u>QBU?DwHw&d~eaz zkP{Ixg4;C;kmJBj;(4QID={6t zLz#WYO&9MS{KxFp)=*LLOth}AOqQQaLWKQe;rImo?CF$>S_q?IAo{-@<;$6~z|6QJ z!|2T5cVOAB5E*8Ak2{SdH^OW}fI+ST%lmDc+68x|Nz$A;tNM ztla$rH5!KPB&8y*LpH1XXFt44r3s28W%Zl7Cem^}0I|(ZTf^?NAUfr>QOPNvD z5bqKD>tez~liv-1S4`Kt0-e9i{KS9;LBS%YJ{>RCQUI;t!A4fE>-`~+QjO^l+{rQ! zy~7902wcYA45iD|d(#-zzYrOfao1%T8*9n9VL#q-xxO|Wh6v9ohS&NjRB++Xn>U$E zjX7v?zQJ9E&xHjw6teUtVZ7{<=y$}1>JKf^TG4?75Z_Cy4+Krq(Jq~k6+L|rOVpT` z?pVM*8!t7{+@2=I^M&!%J^1|;el^-Jd^8RR6}ml?8X$g)o8p!m)Vl0 zQAy1E{(U|V3J%qSqkrFX7U=z&171=L0gqi990zu(BLf1 zMI&j3`fw{eRLzrl{yn4mY68hY5SPGYeV>T->Kq=L zB`u1OP6g`%AL%UrGvZ)cH9hn=+gq-;v-<)q%f@|CA+Hx735@k~SjSb$I<5}6eN~*# z-U}bb27=_I;XV8eXK~bfKY=yN=Yy+_S|A5&FZx&(1qZ~DjwXLd_kr0(mCn<_~*g8n$$2WnmnCIcqjY+H@zc2hhSpdMMYRp@%X9pe*@MCjqY-}DA6Ej*+KtO@$ zgWI1ZyJd=yZK@b4N>>+`Hs7~b-*9k<7YL)x=7O0iVT*1cxXrz$2gJ`vM*%Mp9t1>r zdrbbTHy)o^2lVNM?#|ZSK>?qVXkJ9Y*O~OcrS6ZF6F`g43>;7f8Ey|Is7@>P1666+ zzW)AnaB+kaG*hN=_N%yfkL@4p7-)A7eNd@1d2908zl{=H@=*W%Y+_N}-w5xsLd1HP zEOWPG$!zA|F`g!U2TSe}LAW%-7;?LHTiCv&{rxpZ?(x>-+=#?wXhdU_81R0L{;M6& z!4V~|pul|&Y_v09>aQIr#RhSK!+(l2At3>#K&8a|_INQE%*~!7BL%49*1rn!qgcnS zN)Ryw%AlnG$gGF?|E-uskGfF9ThFVVhF9F&MhOhD%bb6T>;L3@fN>C|qVG*Y;#pkp zPXE>b(+|$j3iQ}C^Ta|kfXnBjpQJ?uRUG>N>_5;$_i(gEVFJ#>g2kWjgimja0G@$? zxSr7fZ1e5CJ=`W>J_F7_V7A(1K*4h1*G9)bJ~41=2n~RP$%+-~BaBQ;KWG#(dBebv zW_(|UB=PCOl88_jvXiA9l?mi}4svm12(yA4Gi^ip2v)+e!s5Jb%RBvWi}&txer=&7}$3~1!Rz*N9wJiTo~s`~-?NAM7=I1aImZxo8?(a3w+^3Q$N2Oj zoD6>sEg-~7GW}eZA5|>qbHw+K2CI>l@7dq}*e8sX>H(5hxUI zEB`;~z4!`0`n(sohSA=LT2S(IIXEq+Vbr32Z|vS~r1Cl<<^OhH?m7RW!}9FQizo#n z7f|r)?)%7=qlpor9LhqN(j?3czgu|iq;IDF3O)z-YH*75=CO+~G)YUC<)=@)t!km0 z&zj`|L)22GLI*_s-B zh++p8@|(ns_ALf`{|7DmC9eGm)%x&x6Xa)ynaBziB-a=~OZJrlk|GGPCb6a3vVL>b z`=zwW!un{njF%yw3cf}ZS^^zuZm?TC-)I>ZXy|2LuAy`b0It#7$hMKMMdr6+{rvVTZYp4EBeA*g>2r>p7W-SOoJ zB%PATsyp_co+g}Wb zNJx+s9hTE8T&K+o38&?bgL4*>4H8`#91mvR@Q*9PPEna8a!OhFTvn|9$`|~{At;fo z_t(#Y&@!|28!=Iu1!m`(+lYjUkFU#y3M_32QgpN=Ect8dz8g> zqtVEbt+@sgjQ7QRow61z;)^fb7?agC7dr!K4#v-VVbBnqXodMCOao?DQ5~VPPTqsm>`&(0Nh}tNA9K^^N19eT7aA!96aEiosb>qY zKM#)_O!MDELxCiJq`S06o>;|blUl9geRSWSz28E~Qy&B34=X?xLmEi1#H;`hi&E5O z{%#K}bl4DC2!RO@PI>db-dDy21psp!2#1^(ie`@7#cMVRW%vgayG82WZ zLKEWpL3R1ir9&C=Br?q$`=!(56-uC|HUm*(VZwc*RnkBGV{r1Jos}>TPlt$ntWGyU z3N|2+JnMli^mS8)zaR_f$OzMP9y50#EVoP@xsL@TvV_6EKSjPXgfjRsSu8dcL~Q}F zi<3F;y!nf%tHxfZ>9TzNhnup~8~?MGe1NfbpsRmH=k9z0+zSM1uHz{=mXLf995pn* z)9a#}_#VcD!l|I*PfIw;xutfy&mWI+D-|Gz3DQM^y~!#V!w-wRY=z7PNj-=eNQ46{ zj3Kdp@MvD!UU|J?mv;@9GU?v1*j%2J`XtW(yon&>g+1-q=JIJH4|xR-u)?3O)FV9K z>_Zv_JlafP_?Wo?O;SYTp*Xy+l9!j)c!f?QGZY99$k5Qi!G+Vx!H|c@lZ2!*@x^N- zzm;8xLWsvAV1dx%U%i`BGPyh|9}tEcUST5?E4%B9=hv4!5otr24F#{r{*ag>mv?5M z$|)(UJv@1)G2Rl6GgOuaXhVv8sqA^3)L7F+Qv*qcVv|vUx;{gM`e$Qd0S`6l9^mpk z9G1I^CurHBNi{$w1o56=nt z67wAnl_*un=icG1u8tE7cB*_M&ybpSGAuEJ+jE(%aQ6o^boOZ#!sd3CVlXP^K|Zhiway|vjmj0k;Xo(iG}+hq#Oj;Ey|N$}4Tj zWFsNTT*+`o=0tLf@(*JMxa#y`^bEuY0t9TY!-gW0^q1vF-Pd6 z9%x|ffNv!$tF#c{R$4U!;#o-ce_Lh=L59G^;>^X#sc#JIZ*!2HpK{d|GYJv8-*fkr zbisAm*(3Ps7WblA-$Bd=KuG9E$y}=frikHvZNf!Jtxc4$)PwMn zMHeUVmL}=QT2Kl(XO?c%p<_62y3FU?^b_zwXnleEt67hb<5t8)8fcgY2ub zKW25@#%WC3mIHyU0@AiXb0FqNZy_WMx;I-rf(g1C-*j zf0UJFu;4`D13@_f@JK z2tLp$38wUh3I6EHI~zZ@(8bVQ=7bEn-36hUY|tsg5VS#FVq{^-%o0n*eL%p6OCobz zcK`Ki?ytn67?gn!CqiG0Hl{id%#4!j_#J*ywB1+QP}yHhzKDfrO%>)Os+asiQreP5 z1H?BD*?pGE7M+!QRbs`n=tV2c4*Gt6z^|vBh+xa5_KkVFF!JO#;p;$#k zdb;)yFlee6Fr4(7-Ou#n0LQ&z4M?3~%E6LTQGS!L+8T(vt0*Z+*mK}D0~%==5hY|H z+JtS1aP?lvW4xN@Bd~Z=ve^2+Us0b`;mGL=Azg@Ydp6hRg3@{h1kw<%GoRoXuXaT( z9(}*IdO%iMj0ENlz-qSpa=Vxx2K3g5v$k|X&?0e=Gre*L{KZKfJ%YwUCvz41X?;Dc zIpMiNr`hO)cx}fLQvS6T-MbZf=^9v5H@y&2CccULCt2lO_CYxF=wA@>bIwigJV;I_ zrMp*{;Ec*!F=*q9<4F>rsdIc1KE109FM>iHLF>h9waeAL!+Mo_eYcOg+~pn5KLH9D z%YA!E*Bo1g`eB12qIC^F_3jj8yrz>b9cozu>jlpnUm#j*!{ zsP)gzat#9AKiaON4?DjH29^OJL7oQCW|n5hEh%A805F-1378o$()$@*tm5>EiM&AT zOvJN(!DZt4>VSa;wMXM!-dxD%-m(F-^@kA^L-+dd%0o_&3Njl*xskgKipw=>ply;D zsJ*!otzHw6(QB;qzp?h#QCYT4`{-?gD5ZeXg3=`*3R2RN(j_H=NGmCgfFdX$-Klgb z-KYpicb9^6xAdOV?|px3@4eRd*WRqfay^g2eO+hF9COUfG2Y3PA$U$oQ4Jn{9c!y} z>U(>)6yOW%%o*?2-rin4e}8|qs7s=`k8Esgs2@EV;SGN9!_LtW|Ig;0j(-X^y*GiG z(+Qh`faT&C*robU^8yipK$emB_pN1BS1PFx$FJeAF|NWh^_Hd(x7Cd8b%1U1DTnQlsK`u(%u`87ky{ShhJ?|IVX9mB37wO5kPZGAK3*;9(4`tlV9o{g>qy zG9tdQ78<7QbZ%P z@e-mPSVpc0(mzkl5%7UFxsfyQtDH9e+(=DL%>vuSMo#0i4@!|iCwsGrV@&?E(7AZh z_4DVP5d1iTMeyp1-1HnA`nDT?nl9Mg(+!D@9kGJwx)v>)1rULM=Rsqw4ub)m$YOVp z(2Rt~CUC}$6+kt+X8j-pb~%z&tAG;o>xbW!D|@a&S5-tZjBzeqveO5JG%^fELu24N zs9F@m<6s}1`OnYoKz&4E19a@1!5Dz93l`{<^_@pQ2(ki!^RRvGP$C@j>Xpb0^sv;V zcRf=EGvagn>OZUH!b+081NvrHV5Z>$4h~KcNXiwX51#(n)@C^iB4?_)y18F}KW~QG z3VRNkB5^tV&9{QasLoRnd|xd=NZQ-gY)!VTTmOU{O`y@Y$k+`Ed}Iwkp9y?{AwO+V`F0qc+;fO z(NPCEdX+z`tHPs$gMZo4I-f`qipCr%w2l!I$9)JECel~%iIKGGc491J!<3|$#edFH zUD+P;I!!0u)BuBA6ESu*Nf$-5QLlc>9;>E zd=06YU;!$QuVZ6^iW(Ysse2@_-Aph0`B<5olSf8HJ%gry^^oA;$6m8Hd}6TRwi!2v z)q(WO_Ib=TkQCkPNq^|_TdfYP!7Yo8>ps`HxVpRQ>*+LaUgq51-Y!f5gS0R|Kh3k{ zqMR8P0cvhedmGcMXHUOsgjh0Qg7=#u(U+nkxe(k%E_hsT(;GfDVbJwV4poz%z%Ku+ ztf)Az3sQ-=Dk5_ul5q7q5~`&f`r6+T-e6DQcWe*+X7HAi5^mL_X;TKI#_p1^*{@d6crWKY1jk<6O*g& zs0Rr|6GuQGgoItYXzr@#fS58&PYnX&;1&z-2!x!&>c1cu6WKDYU-tYlQD_s<<9qN| zyeQ}*uJkym>GC{vCXbkyxOf^oKl&hf`(pVQFTOY{Dt=&r#RrK#`)9_+sme#wklA*c zo}9eQ8ruk3o2eA~gg%NYp)#pOF#S}rv7uo&Gb1AmWcwP6fRW{cgFit68=Hu>zRnl_ z;VBICid?8cFE#i}1cGsIIEdPr=uY4Sk(X=-m@F@qpeT}>^O_vPBJwa!jO2LF_` zGX$a&*x(o`AW+JLp#S~pmt()ycXz4LNs7V~#df2BL(q$ZUcR`n@SPj<0otsOH&&Oql+3#XB(;IZz^%uMMzF@$7U&}Q*Z)Rk)J zqyv_mI?bzdKm$FC;g7fPVC-f)29uDGFbj&Be5dl!i=UhaJ6p_!j1mJwdM60X?xZsM z!x+}UU1*~?DlVCYA(8RtPQSu}^#?ON_^#ei@@Sfp-@%pH{4dn2{UURp6T?2b3J2-u z2b#w)!@)Z&EQ}e%R4vCruFC=(Vt#sAndTTkmpQonZl^G5^05xjfj2K)W7h^-JMlOa zD_LC}&b_XVju!|DQ=Y;A)5+}umfxi|e3^xfO$`?h&!HUc7J3JG*tq=`aB8YuyvDIr3)AVZc@$pfDTs9Yo--azOEg2%W-u>)06TNq5q$7~VH_%!xEiL6?Ff8gh zgH_O^a`IbI#)n}4Hadmj(9OI>ctcX>5;pd)QItnHOQ03eoO z=NsX#Ye9Sb%T-tcP)*s|+JNXLv2p6$B?{hKG4+OhlS-ZhAx#|}13a9ZO#p3_3JVHk z-oJZSSkHH#V805kjtjEx$k&{~*v)m)NL?p*xdmHH*@GV9-`y)?dsM=z4~pVXJqJ9h zYwYH`KS$hldg0_$-rSe1;d}n<*){ZnGBPr~3mh8i>Ul`QT@4=}{}tenaHw>t`u_1W z2(~WrANx|f|E0tjAmjuCVQS8S0o?rA+IssMazUU0d7;*$O>ws z{XfTV^XKOuXpy0!^-)BI0H&LI6N4dmv~cVX2VYL^eYJ(=00b!f1N!X-w|+P{IDCN% z2>R7dK2jG%a|b{U=?I#jZoh|Rp=V&&1%ZqvfRAR{(3gB{1r#lV(Os1&DDgn0I&JmY z7KEa6n_ubiMcI16qP_tMumvyhvavBS<9-1F#ZzDibD6wB>^1>DrqpU|K^{AKf#dF- zJ2fp+>!)EKCcxodSS|2YTvXQ7%rG`I3|Zfpmc@mm5r))HLPJBd>x>BY?L?D5RD&@| zgf@q}p#-8#2!QfFH>iMwmZ=;TjgJsDGC-##02Uy4@J^gI4FsLk(HrOGS-G3H-xLaEV zOVk(Bp0sd;T{H9Y6aaApwv~czSiXEZ{Hs#f$<`Op!-yP1$?ght9dd%IvnALaEzp{Y z&&-^sl$$xadHDjANG={3*Hyp_^U8jGh4daebaY_9-n@B(&&lJX9Wgm+Xn*BO=zA}( z)0QeKJ^V1ZI)YapTaL`(R<^^Rg;?#s$%ufY*gS=*Td%V>-&BMI%@yQT4< zZ76DGWyOE)-0OwUpFh)p-tT%;Ya022Y*`fRS^5skH zoZQ?i <=wBLZ`8h4yER)5Ot72V9|xx)w0S;EJLouw9lUv-*wE|g1L}_k=wsw zV#xOPTi`eAqkjORLdT#`^LX>M-jMY{~O_)D@%MC;qzltGSp&zu4C;y?kT z!s%CE#o&;lXU(nE5fMpth87>f|Kc=QUII81PH_5_7QwtZqb0p@wmkamgWb^B*Gd)lp{v7uT1abNJ;InyD0Ba&H(gU{t9A<5O zU90jb$Yn>hM(#rRT8Ho~17K$e4|C`)U#LE|fq-3(J+fuirrZ^U>9G3WdI|O&{QQ-ga_5Sl!u5DD*O{D&2rU5YFg-r$(QYj(d}$CSPmrJ^dkK7s#UcpWM4ZMzH)s3~oR)`5L^aX1 zoaoRatYQ>;_bL(5GqC3Wf%E|9?Ck9~;o8>V!h_>^pU3sT?xP41>To6UrBOI$Y@d{w zmZ5&(3CPpbW*vX{gD}X^bfiAX?^{N&AP(r-K1D)SEg(1Xg%tC(t!>%Aw)W(Cm0X3B ztAT=yOaUB)3YXoyb#jI${U$A@&IJPJ_hYM42-K-Y<5SHPboTsP_u~F7)Ah;5AtknKmIq*7A3c-p`(*S zMMU(cd3G~*J?__kYXQnN^7SaSwX`x-J<5SF^s}I%HZhqcASMpCfy={jgPpy-A2ebm zX@fgaltIO3W5ku_rR|RvWe8R-4(JzoW)2RG;G@y@cJ>_*u^;{gr_3K#NO98(P*2RO zpFbZ+f%duq!1CUKfsP7?+-QE4h!}xnV5ZgD4IP~FRJi(F1Lk;s1HA*7InZv_q#>xlYZyce0fE5pQ?d^-bETXHb zT-(rwLCV8D30*NxHo%BZz!h}f&491m++0hYr%%&PK@hulaDeYr4($=O=O;6tiwuHI$=g(VRz|#0NCFRQl zbqBguZ&1z>_|sA33u=XzVAG3>1IW=@BEoA*o*eF$aUI;PiKv1Cu6A^KLPA1Vfwn`~ zy}GJO;R#p97ZeCIy|GXI^hvX-dbG8bRsK#+%lGfJuTvNgeKEbM5<>BFKDL@GY z0`UBf6z<7XMD)e<^b+)*KmROiV36b@F8(8_bhUL5q8bd2GyQIF4FSXfo>ClytK2pD04={(TGw3ZUV``t|eD(<2+FZT1jY z`}K>U-tdbVSX?0sXi3j@b9L=Mjfn$_!uEeMC|l*ysmjAZ?i}a=pRo+hx>g9qGx#WO zQ$Kn3?C*2*&*0`C`TF@upHF)OWGy~`g?-5fH!ts_T|`_X#sCbHxsg6Cff>&9^fWU% zGsq5Jgvb)Xf$UlxEv@qJLqmK%Ez=ugqoaACi8wY-#T+0m`yn-&V)Ft6egTA%YU-QfT29)mVNC2=r8BV@XTrUtxlVyQ3Y8aesI^!m$F|H=A^ zf9(1cMP{~K0x`Z3aK0lL43zV5zJSpV44lMUoHn+$BN9?l`0pWP3Hf1~eMlFc<)48iz+mzTE!^?3xHz zXI-s224pngjx2Hvbagp_%pTQGI7G9y%@-qb{YR=eF5$6x@Tq0sdj__Hm5S|1U0u+DA;PeyhTJ(&a; zx|n-z`&(zgn>IAi3n5G7{h~+7)pK2=o!u%KtGj;qe!W6b!9CYXWc0t(gH1CER} zK1)*1{AF|V#j``7*+GHZ7q$%-g*Vm^57nNkvKoIF%{6^1t-FEs%3QZ07pW&o+K z4P-?o_C#V+-UbJExuI7A=}vL@(}zmXd9;qt9yegvGamsD)P${@y~#Ca7zG z>0NI{crCK`vU74&Wu&FQJWx;oQ743pN*U54yZZXtN`Z@A08Y0cHPu)dt<^8J3RtI_ zo5+=&0}!9zh)&i!fB#_{-nfFnK}~+Nby1hhq_cq5hIv)-!0q}%Ov?zY_al#TiZUpLtnkzH^W zJO-vvLVjnyhe1mn;Y?5o-HW=3qKFIVWYZw36UB(=*23rtRiK9OOMo5uYNRMj56M`N zcJBvl3I&~W>K=TMt^!m>*ZjtQd#-DWD(y`S3s6=->13ne3x(iNp;mqA(j_j=XzQMA zjr`%8=%T@QV}1P)J)AHAl}t5@UjXb(15T@(Q@YudDR0As1Qa#G+`s3DA58VQCaA z!mGSMc;zL92RWRSUOKQKG(tk-^fWZz_K%MaBv;8C>H+T-NCxI)B4ygeO5%EiNRlt^$xo*B?co+mVo>xLOIB?cZQ8QJe~V zRXE%_JY*r!AT~(rt)Vzu56V$FqM9RjfvgEY4g|6(-_VJq2KDAW-Jr$JWU)X18F6q= zya4l5f!!eU{zmY`3the&Xq`xr6F|ftx`aTP0#M{^J(G=afHgiYM;X}3iI0fDoK)Q7)&iMVB6qV<-;SaRe=;OBX1X$?Cex!g8U zvq+8cTw(_)>pSb{8!CUCqF}UBa>QwLi0J8xz&L~7f3k#r`0^L{SwXKCwD)0%4 z>5BShkw_pPhlVyDRzYB)NFr$o(5b6 zx398vc6}Z)w@*+=44Z|RyuT7;ZY=Eyg8Vx$O;Pv^2CBy1Bp&b9o>=}+71D)h$Pf|{ zi-`7sZk>u+L9K#>1if)|NsUt>744ac5}oq;l8+ur>vvgG>T^B)WLe5ciFZKk-A=?} zX2-n3V`nxP_)}o_p6IhSn_9CQL?)mlb_V05|0NEuf#ku3%5Srm=@?l#lN!&YvhE#+ zJXg-XClvEJ0`jKv5!JxeF=eXCJZ9I_Ow_BdueWqRIoe$Zd|#CWrt^5GTtQxbIUN2~ zCY1CBv9qwKd~5w&;}CF-^E*BUJG3cBURHL|FZ!_b^1FIFp~O{Ai@{qSPELCZr4t7* zgv=4768jArK*vc_Gq+m1s~smZ3|HMYoH66$9P^|?L||sS!WmKd;-L;kjOds5*^zqr zlXv>|Zw~QSY?*LgTy}S| zjxJlRd^|gHMO>`rZ;k6RYitrqXY1@F_l%9{Dn5GD@*@Q zyc{1{T?ZyV74ZLy>7#?)%E#*e-cd6*x9Ntza#UYn!s)PrAEqav#2)&^D$zMr{W3yP zDRauX)Mt*euphhb@849N>A0g3MWk|Q94o*&=|0)#Y8slidU3TSJx8B5S-RHd${d^n z6(;|X(-?5ae%V=B%3rVGlJw7Vz>a}y-PS@9p4{Ap9=byhl)`#pMqxhyQda=!ZJgXW z99rm@v-6XHD0nd*w`tkr0SGZd1R^JXu6Llj<#C?kcs0m*+#q>dIUd@bm z1kOnY4Tm?`x95B4NsZ}@Tk@S@%uJcBXAu>h^C8G^A<3$Asu~j!W1EJ!Nh>|Ye1Fub z|C^XJowBYd_J<0S*3P!6*`2$cW!Ya12QutoB+2Mbl-lc%+Bb}Se>2}JB~hJ`*A?i` zH_?h*ncfe#GF`#LKU|Oo01L+(o(bwFj9Hagpab8NccM8`@XSxfA=`8m|=O zSalpWqjQ`N;JC&*;6GKb{PBFL3Q;C+HYFSJH9<2Cak{|KMG&_Qq|KJgjJF>z;*Rd| zIhQ;vlsDF4&iI*S*v__Nlt5*PozBP1HB?H@n3`gt?~P<%ccq*Mg);5(1ME}lAJ4?c zshU1yl8hYA^deZT^)=V6;$HSXP(I;UaQ_(phl!xpy6oCPWzTPpBgx7;TT%Y|@^{wH z%(x8blV|d(tmfxx@1(Xd#2+9#m&~L!UDWx5EVd~+_doDXmW8eeD)|zp0IFu$lPL515*Dsy_$j-!+ ziT`wC1=TqeqJwebp4u~SXl=cEV|{(SKZ+1?cqAn1vd=c&a%;x2PJ1)O_?P(}gnd5u zZf520#i06N-AOVr9$q zr;VL*KB$;~-1kJNO0cr7`B`I(V3uBjJBFyx7CB=K>a`s!2;D~PFviOvj^%DDA zXOm3dwjD%GaP9sT>dp0)VaE0B85&@Pn{F?r|@A=r-0nYYsyEYG&OX^7vgGT1&+&AXdUDdkK5gx7M;w+ zt`2S8;Z%TBNBc_+t=4LrPdDv?b;W|5rev7sFYdbxa8%@d{(Mo8a8BFajkR)AdC@4i zr^8CiNOSL8-T5FU(@Y)j#uh267NGe8<>(7ZFmC|_&VXesUOx+aX{jnL?Y98IR|9lV z&rtZ*F}YR#uKWF5Mo>_&BZ1HMsRjH!^V2umd|5EjGaxWfK?p+tf!w8J#h>4Gjx*s7 zego!THsfU60zh&*_}{BjhuZ&RS=e%#Zm{uwn)>18>OZBmq#<&z_IOP7^@LkL`&fyv zh4W6&8A&ms3;}~{{p^8Poe4zm$2f|2Ncc4;&&#!6%%fe#4pyGN5bMlu#!02*;o+Ht zEw5LZHrr|XTNuk2KcC)5!DoQ@s$D9>X?dw7N}Xv5>{E|_$i?p1Wu!RjuFW~Kby+-f zp&B55j(6`%`{`TKM>LWlqi2?d%HmTmoR_^cw~o1;GQWpa`#?r>vUOQEH(Het6JNAj zV^gCl6E*pMTav_P4d+j*dH)z8zQuC|sxu>4LKkQwYiG-xY>K>n&$GQV+|7z9bXe-& zvCEQaf9|0EGP9_zmR>J{*{Elo0eoQa%!_wbDeAJ-G411 z>-r`!s|>eC1$DbJ+;ip*PV4Wl#v@=j|eaV8!0pcd;LrVLN^Tyocn~+?krZX1%KYc7piiYYz^L-eP2B2be+{8RbPsl{k9+L^d_X;qS~GHnpQl$oFQkwiEYqb+Ov96<&_(?R*<|rFYcS= zxGbe>R`m_5bTi?{pKUyDX-uBt>=KDzQ-3)^u!+8{bN2 z=4WyOPwhb+XL8~|nXI6uV)x+0vo-rNmOGY9wkSFQ-0z!IP@wDw4BEf!8j6_4OYxJf zx88p<@_%!Q^l}M!T|QI;92F8`_yrNYsQ!RRBDkXBUO9@8AmchR1ldytl%EEIrJ9|O zuN($p!jPBr=fIF{Oa%#3VPRm-LgRNIpR6xfqe}7~U|iz9QhXEj`d6=#Gl0;M;MXkZs@rk@w#Qo>(DY^3mnOvd22-$oQ{C#nqR4A5i@Y zbk5Nr77C@UVGHg7pRk3OpiW>W1am#Yhao0YMc^D@u{j5-tpfhEtE=k_MDW~@Xn_Wz zHVZIo*^qMHK;Z#OoqhX81KICBL$A3fNPg`iE!0Cz!wAx-TaUjtp~^?VkTLyX-w@B= z1`MUgF2 zkw&Ccs1Z@e06jA%O>ap_|9bDRiG<)l$R)mFaFuA3~B}DWWzQG*nwhYC~ z>dD9?X58MoHZPSQEy=jhcK)GQqpEkl_qiJ%lZ#0pcC>%~{4HX*8=;N}hL>LJgOwtG zDI=1xXEsrDRESu?SjcqMY;4$s!=~Y(xFsp+`anp?<>IO;fojA92*aogJ5+XxNInQ; z5Dnc8NKqr|y4fW>Ulj*vW`vTYcADtu=<}%Ht$e|Xk(I~jhsteYzk%st>4_i5YU9e|-2Iau0xuWJDTq|=W1YyX za(tmitO?@ar(jIP6v*->Gm(GqgVaSM1_N|NGs>-a{Qd1affDb$yu9N7ZYwHFn2g2c zF+%hfwBqsuLl0wS{-tr)+!CQO!%|LOe)T7r0K|Z#U~JtW6UK9u9M$bAs<^N2#e|-g zmYs`iFkNG;HWA^XVlkb0(VVpj0eBJnx@%PiX?VR72B!yhWJ za?a$%q|XsOcxCv2Z@F?ddY4PS&zj{VPV!Y)imAUY{!{iVE%ZCNcq$292??h$KFT(1 zg8MpV8@oU1aV;M@srkz4WmPgIVe4jFcg-;^2Ci-19D7?7cKmHQNAB5f!>2|c450)| z>-_!NbGLEVKmF3?fDmYyAeBkGi2wd7V+{EXvi@H`T68O)+Aj<7jpc{g(M)s3og0gO zK_oBM${)?IFX~ei#zS&(kcdv5YON)}MeV{pYb!D0<@ke*`oPfLoRj4XDZ(>RArZ|y zFRQ9dT%de>5Gq9p*9QK4K&4!-LS1-#FDo;V=gcrGDN1#z{fK9!REdv2?-OHIn5cyD zF(lRCsMf2u%-WVNaI~B6FeGsgZfYi9KVB93J-SEBWcpV@X!0QEiAwp%*r?Qn5{9>L zT-V+9G^8`VZm@qOW+YH)ZXg~t-3+3Z%OM^7wOYM;*eMS41gt86%s7F>)A%Pw860c* zahNn12jy1&@{o4>9P;4iZP$~>)!8Ts34@VBa50~t5Hv7$GcQMe!07{1s7MM+~!_9lX~x*js>Tk&0zo6oZvp6&Xb`M zGMQT%=af~NY8&LYJ6?^ z&0+SB-Z9*2la^BtwDKB1z9a9+*gq|wunz=Jx(lc&nC9i>X$)F8w2jQ_K^fK|lS&%J zW$d#naQQ7J1BDy&QJcD_pGN)&{jT zBLnjI*;Jdqmxn0bS0d+avFtwyW0I~29!OuXy-GP6p(#=HKSrFWo`tr$CZ{x9goN>ex{ZBy{P!| z)3~g}_Ciucl2knYb_YKeeNSADU!d4AAkw!EL`X<-4k`2Zh~w><38;zkh$rhx!&n zcKy8nUm1$7wExcxg~IGw()M;7j__lbpBX?? z=DF<^)D^Qn1;aW-#Q=Ts!8d#`OcyoAe(`Ory;b7wNG#)65qm%xKGS1+>dgJ-qKWXo zs!>Vn4x#C$fgew5P+{USnlL*Jb)M@5zxlRXpnA0fq93bj_oE87_NktIX2>zcD5SqT z#u}C;raOjk+T|KPB{zvxp zlxN-63XM1w7Gk$W9p0liOOhmzAZC2JI`o-)&f9@saXPoFE24voZ!C5chT3}Fl?gpB zin$&Z7yMjLbqJe@Mzzp%qnBESiKOfGcQc1^k=ZY-7{9o^3Vuhk@r3&c_f@E*618E- zm^Lb5TY>`{85x=He!ycsQnLIGq+2MV7ljMIgD*E7ru&viI9$R$dwO@K3?I4xaJH=# zK0{4^_}^he7*+#cp;#9eV;O~oYY7W#a}bwX>LWWBI~ymUyr4GP;U-C%O~+{@PYV26 z`J?(dx6(+Ggh{u?^B<}TzlktOH|}4oo~Xv<>D~O)Gjq{m*ryYNU466^$4J-}VstV* z6ev&JX_r3pCXB)HNFQJF($DQIEe|Pywe3~6mo8bK&gD4rNH#xQ7XaSvYF^uZk>7x@ z;pB9;tYw2~_wiZG_gi{S!sQVewR#gC<{Q0lIEqWS?#gmHftIO14s{7Hb(C$e z48CeyIoIenu#X-Y8GV}Co$&BLRd%Q)3FWAHDHKTQdx{wSY43}NWd#1LKK3JOmSy2p z#$=6ud>hl2@<*6!W{b@|YLre$=-Z6;ht z(Vg)>+0(r@r+JIZ%;xg;_a`AstLm{?a?xfUI`LlGm^)o7n@7vJkF4^bOULw}XfE0; zfgsE@UNG^H_nH0Nb~a7IDGxh}gczpzZv|Twi$n45*_C;{&Lv) zWD<|HwttwZ(P`M96J=Y2eTkTeILmxx`Htr25p(w+DO5r>C+nor^H-*~ii#3=&d#lB zx3B1IC@b%arzST(ATO`s`X<`=`=ZB$T1IEO)yx;%O~J~{(X5Jsp9z(mk8e1gbnP@X zcFn%zK`ld&uE#)g+y`hy0*cH0KM6s+g8Hy1fzDW8QO{f(O%3pf&lywOA z4W~mxL_-bv`71+jaGI2{wL+JS-q9wzRobua9f@q3zb#-$++DQSn~U3w+jLEwO0caJ z?6AE==NCO2seUkjkZj(FPx;wkDUiRqXPvey$&H?W*`rG0JxN8kGHAs0h@AGh91|$a zYst(m)VUH<<2pCQ8lMv2>@cP!;{WF`uA|yFM!ADql~y@KWveh0&&Is+?cD?uLYjFM zAHn&bMvr!l2c*o}Tm*G$JtSw-&Nl@G%2V=MboI5qDZit_ZtpbRVmixqpi-P7=Q`dq z8%}4L{%CPBzI3V0oczpnmQ^yN3y$px`Fr9QQ**Qj9@W*Dm)5-S&PwO{xJqu05ov7> zd+L`zJ|gtPeyhv+=ViYVsIPCF1%2fm(6CYi-bc>~CUDi>wi^8#1yYbk46odewg8(8sy0Q}uFP z5i>XVWvU&9zy=waUnV4UqhD(O@w(+CQZ|xZt%HgS=0Q)wjQQMakwHbzratkzglldc zE-Ud|*4aNQ8_!IeW{Rzt7BeO&s(@jY>F-ihLy!EeC8D?Jt9`90`Q4XtXvP+;xWaKv zxi0Qj9$cAhp}e-yX7~E~voPZr$z3WT!=WHc=9R81KCIs7xjPa%2;TWc4}`N&$e%>u zbc%j3RWr_#)EX$cXKk8tph$b4<$+uwg~m8VY`7o=)AoJBU9N6LOp3v;YbUc}mH{5K z+f9qEmsOfqmQ0H@J+I5i_69BYTMv^>Fv=S%k#o3BInn!ux!3;I&X0asZdm`;U(Ew& zf{H_(;7U-2q`Df#)te1k?2FXzJKxTSbTZjXE?|qQ2d5=4fbbR6jCPzMfU(Db z{0!wT?z?dx#NfMc!J%H+A{-wF%HPlSg`JHy)>-v2~ELlO~ohZQpY~+$Yk%{^~jzWNuge z)LYjVCaO9Z=HZKmyEa_m+U^(GN7&3J z7JH&6lIogrn>AFkcHoe$@d>r|-?B$-Tp=vos^QM!c7VDZS-5EOPt0|PgrOZj}v`0<`n*iZ5fKMs?>|Mn}FV3*xTQ~ckuUbnNE#s zxpVur*Y&s1wkNmJRkpIw?yVQ{Gc%iP|@1gfu5x@mM z{4Z!4+RBilZ!zq}p$9EKkevSQ2SslK9KbCXzPrky4MelV)v(QrxVX7b%*|auCqZ_n z4qrG2H5YjpWkW93&0TJzQ-e)VP&XZ#uw9_H`_bvI1;#DsVc-#miBU~Ahg#&Us;S{! znzbTrwH#%Z-H)3Z4@nKJ>8ro}?2Md)O2B$>i#_850|R{5uP5okY^~t9MQBMOo1L30 z8-U@R1LNcFiOI>2X+Nre)~R+bHjBS!FIu>&21T|jiUjQ}@KEZI8sP?f*q_umH`IC!o1F&Iw6eBzQujRO3FjZe~{X`Ec*s)Nu5!RYPfrERpk;pgwq z)lsgOte61-mir*ogIuTyV^QUc~PaH`Z$-c-3_o7e+Z|6qG{ z!h;yI1f%I}VfOp+V_EoQ;!9|0q=_Vw!FVh}>SO{71BthSn+MzZ;^ME5Hdmp={?5>a zL^z1O`yJk|uD^vATcJe3oNV~@v!ulxQXjh>peOkYIko^bW;Ic00c(TBm2}VBl$Mw8 z%T~?oZUbJZ5E>>a25UV$9+iNDQ2O@mCcayE!+X*xG_t-6(^+WpFdv3qx-(#(KH(*$le!zbHAZ@S>hfWAlkISizG z-Jy44^*aZfxcGfn*Q(&!+FI}Y{QN@r6GQ;Km}i~CWx@@tt!q2bas$knfQje{N(Z;0 zN{Y(}I+os@GJp+Tfdq*Th}+^rD`X{<3Nk|*ojerp2@Y|=MLBm7E{d8KbTeU~IC?sT z5eHsZh=hQkQ{mx5j__a_+I18A9vQ@ zrZ5&+jqMx2mn<|`{XsjErI`GE`JodYz%+8fr>)oU{|&^Wla+13F1hsIcjkfe>G4#k zS|10eZU%Rqlb5&5PX@GLjo!Z9favgPykO2Eq(+M+l!$Ed^3}5Y&oMAC2w%N=l^ROR zZ7EJ4{2r@z8AyRV>~E;BlYn9(hnu%J@ zmH&~?+qW6N9*6kW;6U9U8zlwBVV_y?cjzIVL?=czjFGVJCjnt~H2~Jg_03J&jqPoF zJRBUeWc6%fzJb`-SSe!$SC|k;_(_$S`&u#n6Ic&nB>TyOX-yRN_yg(!BvA4IQ`d_h zfwp8R=01${(}gA~g#sQ(5#vzNJ7s|O(n6ReG;rZTYr-7*os>eZWqg%UR|ws%0g8PC zM0w#ZeDFBrrJv~N=yb&`LZxNM^78U7A3y&AtepEpFy9HBW~&NB65qPIUaSH;vSe>> z-vi`VPVL@IEIIW-88p-0bBC7OH@IZCc}Xu{Hf)TzPD{%i74;`sbQ!ctc(h9_NTImh zJViP4GBg**YHDfe8o}}lRY8JB>-qENp|JJP3CNUaTMf7jq&RQ#Rz^OA?n!G-Giweg zB^`xHK!)&yO3*a-0Y)#1ehIt^mp}_4x38NC;$Q=&5-rZr(x!O%NmDTwtxVMF zry;Ka&4G&AaN2m#uI1(~GfBRAJJ(YNe4pCRk2bLGnY$YTLI?$dJ6J+~K?PZ@L^Jp3 z?*_=EA8gGRQoTIxM~SHRJic>kUVY{blKV32e;+Ixq-0n7tgB<7eftj(5%LEgrXR-KHXYuA>T1yHNTr8Y6tcSvAN5v<6@8YQ(p+z5k1#al zw13^?JBwsbpcr`2m$?%90U4l&%6M^RrUY8lvKjIf(di0+(?uk%M1NhW z#sE@&vLqaO0%89?wf@JCu)%5PV=cEm45AXe%FwlG=W>&B%2D{dfQ^{>rrt zyn<+H(E;CC%Y~wvelOBjs2XN%qmlwKP`>2(kf zS-@6)?eV^lONt4ABjz%6=N>}{vk3(qQm5{Ny|2Cl;ZFQ@?5Z-qw>W-)w@^mA2pW3r z!PhwYB5*yUlMgCu{h&Lq2>U zs014UxGy`zwi+xiIPDX=ozHn@eObDDWRu-+inpP^e2xvy5rab9GffEXd-w(p0Q#M5 z^*l5OnH6~`!5A*K9C7e~E)$2+{D z{^3m@AD=$Kd9E`dCiFj%#Z}STapqI(NK@NZT9ThGfGG? zK~0EVJjAX}?D{pMx1X{32@S$ZXg3ZJG92;TbP=Xe#`y<9>)`= z+h2@4U7Q0`UGHKDJ^un4bTKQ|rYT*97weZ`4u5)z06y_M7!|em)F={i9g~GF`*qm+ z8kpZZCA`1C-!!xvx|9kc1`nNgSE}8?OT>qUgj~XTbOfGe@jABGodYT|Dk>{AnC<$G zqcIr}zlMa84@{T!jU1SEd;wOg$vp6XKs=M?MVAdl5!rh<2tj%L{{C8fNSGWXB_?6; zE?x&;qXP2iSXfvdfC4@j6}{(mKYV!uIyM^L18gytefV&I@8z0-xv;P>1AM2Wlh<6X zCnd#D4Oc;AsM@u)wKe6USoOj7VyQE7lF~OX=K^w8&hGOcEvdAfRd7Nps+=k#=o&eN zwuI+d=dYXjx6w`ZhMTO2js>(1uDa~aA_Eo4u6s|D;Osgw8Nhp9f}DLHi*Ci1cT!Rk z$r7`IxVUvnpBWu;8XRJ|?YM=HQ>=R!hwZW4sP zDE(nNtx~4y1%P4l&@I8v1yRV>9jl2N-EWPJjrD-h_YklEK@cOp0i=Nu2-hedzOA7W zA*dPbHAk`@$Z9_80dS5BrYw7d{B7Z=&};1c|U zZ>k1y!X7ma2-{B-1wgqP^ji4WKt;Y8+B#@JRe4WANLU>NUE9PX;89%AK0(Ma#6U+! z+*Dozdf+cmu!b%GG>{)a<>8f!+LT;eTwzz}<)VJi&+{?6*i2WUfvm#F6xP)}X$2{O z^x0iabaBuTXN99)<&1z03E2Cu5S*kBz*3EF3@gwEKRY@+jH95W+~qQZMWKN)zyA|9 z)FvEFKbFIJEeeVan|0t>;O^L-*d}fQj$(o45lbA1o;FJkK=Y*NiiFZn%Z#l>BmB+D zK2f;-Yv}rmLI^VCPs}pzTwZy&2xheoobAbqnx?+DEChjxjQ*l@jAv=7BkYy)OA|1sq=K}x``6Bj5LjARw1aYiB?ys3Z9`2V8>rjx zRw3LlZR13b@p<#6A4Z!u6CwBt?ymAKRHV?Mz2B_3tL^px%8_!wJd@-C;jy1*46Y=- z`pcK~P$VJV)Uku^K=dyfu+U#SIF_2k5+6Zupaj2g1z<6G)p8AJ5{=F;FOP{qG)5{7 z&lI)`Gl)H~^!4>k;7?zmW7XQXnZucp^vWp|GDB1MVZi(Mlfqkk(8BcC(Z;6W8+>eI z0LyX2RYB9;g=m z^T#Q^fCR8m904Q7dtf{MUvY$B4ohwI)A5@(Zis0CahDE_sQZ8}T}q%X;}yD6$aim9 zwg6BaO8W6bybf|3ZSFk?V?C+{7jta!0&UJaX{!At{00ab9I1s|H5YVS6q&RW8LqaYTrhn*;e zi=IcqrhS$vy!pM2E8FIOYXJ_!_+9_5y+*(}>PIrp6Je&;)vzY~DCTWiQ62Ox?+03-`q!zSl~^o$Jcv8U`MK$L6|nULFh;c!UE z^GIh4NbDf7V)}3G**ZKtJObSNOP)t?2m+)&pRj=~623Svi`4+Rt6$*g!~*RQ$k_Ib z$UZDq`&t6{pIw0I_#5K+frpuK*J@q^*b{HL0gPrJ3|4>*&RYF(nQD;`po8@rNV0i4 z9zFz`;miq$k0gGR0h<#JU?qX|JVH^)M3#j_m(m&3cVEDJxj&Fw6a;KqEJd;a_V5eH zdin+q{sVwNKtoFXbjMWvZ)gIf#sM;l&4++M0E$dJehsdafPv--ovI&Gc_ZQ88o9O|>V8fpO@P`2a1;C|K&b0??$$gmfl#!7+2h^|5 z@%df1{Q;6Vw@e~nV_U$;1z=db0JRerpeBv|r`+7{AKlv2zK#r5Sd9je-av~J17z`9 z06@?_yS?@DUhxESivIu(-EWjW|5O64P3nUlO^3MUR!xLa5 z_66_cS}-6WErAYfTJGa;0eip(=XWtq*9b_DZv3S2{tSkLfNcu}5X$gl|Jx2@ApCLz zFlyIRbs50sg+xUSWCF^exn;&3FMqNRQ33zB8N6pKyaEzY>xi`8zy{Y2_yOZ|fD8oI zmgwu#$X7sKtfjQL_z$EQc*z10;5j&@TytYd3o{{a`0*dUpQf)V~8<7L55!4=V5+*5)I0D zi-Z297Vq&bMH&OeTZ`nuyjO-a28bAJSXvy4xjl2T^FT$ZE1IDex+MA`3E;PLi5>f_ zF($0&@Uuo6a=fjHsl>0!$NdocTaEFQ4n`D&_BWuQgoOt!YlB{?8LMyY(k5t^Y`Prd zp)n>(`%0mJiCYM%M3GS>@n;el8t@It&pc4QJwuWA#WAmnqAn2L9DnQ7y)4?V;4HLl#myTr1P@e@A1 zp!)H#?li^An$6KetT$%ex(ZJdDBpvQI@_5hqNffdiU+0aw_%Q+>;&}u1xZ&Y^cuQK zZ4cmxCMuN-xnBhd^+3t^g>ug&&i0G&v;F?rG{7wFZ=nPu(kW`nKBg`@0@O4l9Q_N( zpR9Pz#jQC_rlE&Dk7cDg1G7oYp#rR(=Yr4@%OPTZV)gT-hf@m^%k$>S*nX!eT_5j` z$t22!R_!2!9a{>KElu2<_=PSsFGLW)oHiJb*a<)O9F4PpN|uM)h(_A`X(U@2D6brN zA#ulg-C3r`83{~u`bXSf=;&axNrxidg0>!_1sT^sGOmFq#&1=r(~2)5KTx1e00ZJ5 znyXAygA8VVGx-CQA6GK^&6Hwdv#YC(FZ;&!mzf#6)@cBILcZAZ3)hB?F@_8#D7mX% zhK@N;7_v?9syCBohuq@yqdQE66|&TCT$BPUL$rPezs;pIis(tupg@@EH(N=q3M$%2 z8I#LOGSyXZcO+yUy(E~m7MRM$+DG)QWPh9*VjL< zjaLS6;m>|W`{=n=FlM}WcIO~~+tz^0;^;&KJ@t83WpS)C1aDwQ${{Mu&|%Q-N7Q2t zbo9M&67P&`07%&0Ryb)GNAV_R;|LOOf4Vx-c7(#h`n0R(8)^9nQkdRIZ_NU#$}~af zwKChbh=IIVXnsg_WOHHs0I7hz&|Du3R6lWFWTvB#B2kjes$~NfO>t2;HBcmtQk_X^5kFJYHD_ zy?Eya-<*DJJHgxI!lMcOC2eD|oY?4uuCVNa<*w~nHXE@k+b zXl+9aK_22`sEzDlmuM?Tk&!S1{|eM9e`~G#cT^x=#)Co?j>tT1 z@Xn}(Xmz^>Y>&bPc!FxnDKtee)#!=ok!s=Wyc&LOgF|a<9=Dq&2tczaj9Id{8*}zw zErJ7W(y$C+dDofy*^G|m3ZjDtdSexIPj^4BkCa3nTF9dbEoxyvv5G6D;e}&h5<%OKO z6j>1(R>>+l4Nr0Ap4>dx)xC4r5sDYZhO_zUsKZkW5f8n6D0ES&>@89&B%xY=H%em2 zVgdR>zvc@PlJyc7&N28N(*%{-a3F+f0=>r&w3R%7{q)lt%KsrXO5+lKb+}?-w^lXf5vI?3-Ya82ut@7HXc%kgllr z{9uaD8{|DsDfn2#yAmB@(%xQj#tQDr5t?xkq`nk=pIfY7b@A{h)bB@igqjHyIIB#5 zsRaoo>vRTOsMNEgUl_{dUVmkI&YzRoEuP{_r<72c7T?3|XCrm>FqtaH7?P8+SVfQ= zae!-DkW)Li{7Lmb6hN6aKDWY>%Fe=M_;JR$mp$J z-zRfoVx?5VKpRS8YwubsL*Zy(f)=HEY4)mER=?R}u=_S%0DhGS_CLE5M@8?Ej}EeU zPcDfB(i3V%4>rUr#IRaKE;?qRh$1e|Y7keKB$Mhj?)pQdi*NrOL{2H0bN@8ls1}l8 z<&~mc8I&bt5c}R>D2r>Uq2Xj4fQ%$@d zFYuB>S%|n;E`f9Y?ysXTmW0z$O23;`-nfXZgiO_}yEE6~KfDehjyO$G~6)En*t#;Ie?o{Zh6P7Sy#^Rnj zKB5MEg7soE?!jUqub79G%qA*S{f#&n9{`O4QvDcF>HpprTeDKtST?u}RkrgJbu_5= zOA-FjB4M$E?O?@pXo6aBSz?sRBIdHL^3sy<7$%P&K zqX0a;sT-X}U--}a#hZ5*e{}o>nbs_~b@RBI=}Ry{9Iyr2d16Rn3IcJ*19|NN;V1XM zu^GPFR4HcvvYVEr3VIewgIZ@lSa~cz7=$t3-?|cD={iWm2}VE4+!7snK1J0R0$ut6{(Gu z5>+qNR9SfNMUv!-%AYt`*93zuBZt$1)PzOS_J;m{t45b*NWaQFU($^ zew1+S`*Vf*=gFg^%dqw%CWh+EV0pf!ArAE-G_kM`jx9)HVppfulcL1E3`IWRjTtGO zq^*5S!%9%Z>!wKA`KGx+z%_MZzYPUPt#}+`)xG`P*LYL;Ru}6{uYH{gOB2KaihkRPgR$L zMIy13&V*c8Sf4e;YDV5dleWPM?|s#o`-=Pp{Z;f7(|x=oNiduFib643Z2Z$w^ze0` zft=23J$A^HUqJx>o6)1C7)7fs)7gBk-6~xu<(6ek-}`HhVOqfNaE4YL+0vFLOeoK7 z@p}5Tp%t&yUTiw%gu1`~G58{2c4HIYE*g!E@=S)7omVqkcsWzPZjeK~_p@ab`J1MfFRs$8v(UWN8x& zVf{hKpB{l88Bt8qHi3<~Gh(PtY{fIHakDE9@A$AoT+@e9bG}!06uFN>&QG4uLcU9# z8j$3N$dNw|lPr~)*&TnoXP(}XaG^<)|EgwOmigW3zeGRsi4SjBNmg8c5|^rEq_fIH z^QS1ejoGR*GdL;5L#!e7_cnB%-7Jsx zv;3CZ+qUj^Z;D$*>*E!zmXw6JPe#gf{c~x3-?hCMZO*xOD4~1`A%tq67^+9|d{mMm zYI|BKLQ^`7zR@=~nROswRjdsYVIwI-3+m7!aH!3}J?eja14at~do4Np20B+USgTM1 zYpGlXq>^46Dp^}*{cp? z3mku|DyD>zCqX#tHo@)HYwh0_5iMf>O!%EEIpNX6B6QkX7@UY1e24sUSz@YK3uBx0 zD}~Sv!mdP7CaI>bT3;21ho(5X#SdGZ?t6dCa!D)3$4kC+XdHppNZkZY^de8Q=^>=I z6Cz!+KJqT~x?+8-SnL%AT|pmZyX_8W+Fs;Zc1~VBmQML`)vK}!V{&Ma)eD_1rYw+` zKgA0COsm4aa0G8LyuwRH_-gWSi}*p_cQQM6U*dU&@JRhg#VgDsy4Dsr!N4960F7tG zAT&DDXd%5F?kV4te=hlPyS|}?=bIo!eiboJRJc7S?>NEr7}i=~_KHUxjF7hCs#j8H-pCq+gU0`Ukw z)Zz<0qIsi|LR486O=$7rP#nI>mw7iIQ+9+6c7`=&ys7# z%);AH)lZdNxR3HRWdxkEZ8ZwZ$n%Gxv*BQ zXUG8ZxK4#QW{^Y0D7mM>MiL(>xL$)sgN+gtib}{`j+6#^I~*8xAOM-KC}Hs7CMSu8 z!>xaF;Gy^nm&W%5+CuC?&bo< z2J65*=&(OSm{>i|UIt}VBoAc3T*8>UU-Lm<_tn9_E_`kSL&|02rXTjG?z{@ceqs(~ zP%;0DvwYW0mvz=-IbHCo{kt_P6Ng@!*~GpkL!qa9DhPB?MvDo7S@a|g?hAT~Iiu=| zzRHcjm}Puhf6iCy$dqU$?6i6?I%=Jdje+G4KcMbNzTQh^ZIL#7~4N7j-CWGAd5m zJ^N@*{QWlkJ8Js;3jdeVke9d^Ru~%hR7enp-ti-`JRmHQJpmL2?=1cokbR>S_cw3Z zk%N_l%E22z&rcrCdo{#f8<(UDItI>Y!LO@^JH+cGF_i-`3eez)SR^i}-rJo5)WRx7 zHCj&~v!pM9$}h+35LOZ?5*^(UI>lSdK5qaaCKV}g=`$(z)tlyB%FP)iYEE1Duua;T z`dqX3i@ZFIoR(K_WlBbMT@~I*pRj~R|K)62=F*nmk|kf@5uZPl+{TkIOX{1&BEP;p z-T1=UwvDz!eW5l#0t(X&c+}Md4>(7Y$7O!&d2f`+&ux055vCaXh+>i7S!hQNBAQ=+ z#!}O3UiTPk-HU1=CbAlae{%`W{f;{6=+HlAbnLSJh?v~r))Ij11h!h>SD_bpGoUK# zi!BO=M*lH}{(R-rK+fXNB;&)}z0J?GPLhToCS@>>kgYHcDdCdJd{f9!4_qY$g@Kv* z8QZTogtN-G=+&u?!*tjE$(I~);gUfzE0}Ab8=VSLZEKRg)c@SAfX_hijigI&r&XU; z_7weiwIq>7GU#B?T&LNUqW`oN1`5f}-T63ypR|snFc#Zv*IcS!MAU0T+Le;#4GJa5 zCrz(f6%l>r99?dyAfT?qdTpDiY*H;50;&vomCBAW}F_wdk~(i&VT>zzG{ zUvJS796}J3OAV7&Wl$rP-t_c`l`6nL3Oa~{t$i&ejQ`w}ANNP3GCDCNe-7I5o4f?1 z7;QlKO3-se*dITaO$8=y<^rjqXZ3kcMJQbc!TJhnDCht{08c`Uv%8J9K--<`%KbEi zBZp^wf0rne%Nul3{~huE8`YV}J?O({NtZ7L*DY|$L=kO4EPWrMT-_P>B9)GhE=9D4 z_!V+?6YL0avLn$XW$mamj_TkNGV%tlY_c}03$<7iQsvtomRctrPXjTw)n4-R#>KC9 zZvZgd*LV>C%e#Fj!t(+!=7-}uRDjd>huE|BSC0Qz&NwAQQM)gu>{fj;{zATVnt`kH zr0c%utJB@fGR%#pym&5pjQrf`CPlnzg(}^MK`n%SOL_$Np2*OmbM>2WXh@BO#h&}V z-c-!X(L29BovR9~=oay%^MO2~>KAuR<|UNQ*_omVJu=Y$(bo31dvkM|U@lddO#Zf7A|JbA3oa{C)XO<}LoyN^J!&$q^8LQbeRu=bLvHh4!j zIng}6_X|uYaHSqnkKZ`h4;zp(Xcq#Kd4sIYp~fqg`0N90;6kfoH-KV*J@QZ0R4&v|q!lYB@jDbsrC@W<^d!^7Jo;51Teo7~p zDSz&tnI=y*5;xt~h=gixUT63E?8Ve4&->(ewm*Z=5xIw7UTGaFigwjAv$|$(^hLy% zWj=fq&uVLqWY3v*7{6h(r^eS^U!#)%$*58FzqkO%4s&F~d3q+xA2!|^^WY3SEp;<_ z^B5F!@HIJNl$;7hUZPFqbALr1aFXpTYD7_>xvxY5ac~gFy&vs=%7+(H&n&XZD7a&= z!|<(aK`IWTBlW8f<)($sMba{TjyY^1s)|%{LE^Taftrf)h*ZP~JPK0%Z)aky#sFDa z@95WM%KpMlce0+qc>i5b4=v@trEzZ?5HbxBW$82vHt)rbyJ%SGwe}W8E&ZYAVjqVMQwSD z3XNaXf)7*yLOmHvEiOLaBFfCpSH4zTju)TLvPlg8o!4}Gak|EB=8HUp;nBQ6JuM`X1Wpvj0N~EP5|@I5CoRD1C?q zqSzzy9JZlz?-v34*kr!A!zQ-mDxM>#v z8xg#ZD=Wqiykk>-s^x&UD*9M3${|}wygBgcOeeXgsjMrGR}gVrlaT_1-bXxu^@W|~ z`@`*V(!m#tFEPQHxZx0};%sTR_$eHO`Mzqo9upIewzYB(Xmd+$i; z?b$6)-u5c!CKxsAo_=UedosADO;oN-v&klNRG z9547P-h#Ruf*vFmSL%YmzuSSOGTqGE>J<=I>cvJy%}m_Y)lzfPiDI882!}#c)urNg zvk%O3-^-kApi`nnC{Rv}+9T=o#I$NqBKdfwiaz5c6FkBbf(mJobWca$l@%fQX8 zW^Qp1QI)@?crPMj!E9v&fG0x$jTJcb!U#~q%+yVdYX=Ky;AMv=;z!KUU{3#o#M920J{xG<8rNi>%H37)ek7(py`LSgQ zXNQapm-P#hR$PfiFR-&{U&6PkWZ7i07CjPtO-z+$@<$E6TsJ?AJcE7-fLwyG<13UyhxiEF60+u(TIg z^4u(NvC_K6#z!f9EuUMH-+ulajoACFXIcNtQ?HunbPjkp+<(IXj0gq}Vk{+KLp(I%zVVaL46?O)Jfb;&d(_f0dj{1}IVYgBJW zy>Dn!$7$mDB|0HiJL|259BlY%)W0Xn1(F?$#K0r>-`K5y%pi{skZf!LX27&F6aOC} zfq+}^zmsJ0zwiF=h4h?=;M*HRsA5L|g@8wu!Fd-B0pLuV=xBJLAmnf~pk)EO+W@di zfByt>f2+*6fipTpQh<2`eDBHw9a_8<%zgsXt=er`fG>f+IJ`W|0xYW7GUcU~vI$11efPG=Zs$PIbxv<-CClplV9N5PcN- z+dT!1B(;6_U}ykQ1ohv25dkU7PZqq4PtZ$woFnO`Mh7KU<0Vn>0 zPeDg3UK-fiM6hR8?~ydcK2M5Q=Tnj+no0Jq`tg3w4A(Jx$ITH#^V#f`c_I^_de!t2 z>YE+Cq2%F?#j($)RPTu-u~T2Im-dg|2dEq$wBk2M-}|wRj9aN3P|)2dw_bw-#hzyI5z|59vG?wxI{$y zZ2(==D%NjwX-V(|Ai0W+0M-=vL8^aWss^%22LLMmwZF?4fv@>{pk2QF)q~(IQllRr zUppw;qyuf97><$t_xs<0(K{qF+C4bFKpn^#d2%JI(BriX+%VsWms~Cw@H~LVejZBC$uYDA zYM&Xs4+G}SOb@t|F)$!NKz`p%`*}Z+Xt@R>N*%DFTpeIoeCmh?h+7uOlpXW_hj%ma zh$GO#DDU(^sy5wHiC}X3Id!$nL7>)sjED!N{93) zh1IpFPvn%oHGGEPbp(D5!vE_>aHA}s|I=uoshp6^e>YullL#RG4IcRVc+kJ+2461| z{I7R_%PFZk|1}@DJO#rf1-ul%umAJ6XOwhR9+eh529;$c_AP4Mw_8yg7z*Rx{CFy; zB#0-~zl7k2sThzFJJyDKd5sfSav@6HZ~y zqoR(yoTC548NfY(Kg*3i^x0#=MUvKn6j!+&?Ipf{z9B^AVMg{fCt|FD<@hUH$xJ7Y>9*JO3#3%`T&#_tM7dq+`pREUL&tolHDMHS%Uqy!x@>rFx`31 zx@J#gQVF^82`nMJ3el9Fc7;c%Ho3iCSDGY!r=r4eERa6BSh(ADb-`<4O!ab&Xw1@| z=$U|&g9tW(mCa}wUN+dUu|wSW8k&((?*SpQ=!^QU5Khm_J^>b|*DRf(DK9U}>_%Lg zNCU|+o+p8byz_-Ws1o~IuDrf$ziK?$G+fS0Bd)%=6S*O0*blw1Z9BS}m(nrx)kpKn z*7GAIVYP0x@R{#nv>nUASCkEgBadtA?L_XZ*>MR-@7Du@cHCa35AKN8nO1SDR77-ern? zyrYvDU5wne64;iPcuFMUEA%0aVGLYKYJZiV^J?3J1Qsj9-<6?3yKQ>Ad;B(8%Dcfj zs{j3~NYT$GVzSC+*oji%hdJLSZ1c!|lFwc0smaw_UPr(Dx_95mo;gm5(LW2CFTV)m zuLu(37Lb`s-gsUiUPMiHaP7~1*X(13|3C@TJT~F0KT3iSCFwaymwXDqTX5}vH*#N%CL|eZ zI#b5A_CjhmhR!=u{x^M z&eBPIFW;;LZk9AMkIN$Lf!^w5;I?BeTuFuM?wF0EB8}Hx3Z&9q^B#{mTL81_$6*}D zZ{b*(!e9J+KWuQDudGo9@&&5lW5j-kY_VT={thaoIv5u3(j3`W$D4WIpRY2z-Z?$1 zvKIHV*PEudiWG7{4}#t1n!mvc=UO$R3HF;LRKbN)T-T$L==-IgNv*H)E4Nl2z%-=% zYo+!XY{pFICXnA2z9EdblL&D7>5e7;a*LH{vx33jK=#xt8^u%>Ac>)66z;x<@0m9x zqWc(%SYiuug>7KV49S~fB+vhhHAKJ}CC@INP$E3R)`?3ADz*!dx;adoH5De+n?*Wq zMXdIdp%xfj2{r#fwn{h+_j|a{ysy%0BH$e{GASR$O81yKocaDx&s$gf&<&`?d|M-C zt+61qfDA)vRT2plbu5r8VZ-kS^pB&0g{oy}m9CgIUiVV1bvGv(1pF`^N~AGp4cT2N zT`&nm_u_3qgs`kFkR;IXax|%9jI5GNAL`^YO3iM?+3G8<&aU{N+{{!0uT`|9tf$`Z zPqq>?b0>*$<+-9mz}s?VGC_wul(l&y%DP#Ksp8~N3Xv|L9oV*=_e@WCccif$MMz{n z*x+}I>V_)1aN2S^L>YB?z7=UF*otaT9L)LZC0p|6SJ#8VwBrncVvaP3(%`_oyCvXr zezSnAaw{dH$1}7#p`N6YLDFr9a11d6OvQWF&QW`a)s=ozIZ3=}2FIn?OYkVo-CB8r zjm4haFKl3kBoO7NLaq6QnSU0VciT20z^Qi2+_@dL;C#vngLR;1vg6g)s-uYzXoN_9 z%`@6-C4pKW5c+r+twIlaYr|Jc8X}oxB;D z-H8R9i3x;rOmpg?;%>f3VmeH?O`1JTPQpqkam%>J^+JLQ$w84y22)sb*Y86i93a## zv=pW?=+vQZLT<48MRZU&>FIV*hN?(Q#P3XGR3=ig+tE_mZp3hzRYW;4NmwBMG`xsJ z78jH2!a_^Kcxy4=wwoO=^TUI{#zF9>If(!I@ zLyua#ge`guL7DfEjMT1sJ94mxjPH8%xq1ECrKtMr9<{wL2TY!hw`tF)JH3$a#-Zx9 z2^AvzsVII1>0(22Gb|RV@9Ux5#I2Rz-+_zy>y8b97~a6V6A(jp*s%Ay9SaIXF8Tce z)p(?Dz8eio|2nUX)ZpBpEfyU9WxKw#^<5<*#qna7_Ot)PSAL=}a~Mu&4;qacMOg_o zOw1qO&)hI5ib)1m%PH2On_+g60vyCMu}KrpxG=L3E8Dfb=IMAgT$@^?gaol+o)j@@aohq>RHd{kGe;C5ewaq>B3r*ZYowOzYVf^c<~&(CW3LNc3Anw*W%*{x0-4O2lFI_c1G~HaE^*~EB8YOCQXv1nvP~zQ zR(yjXBoG3ZroEIj;I&92Acz&bm74wa2Xm_%%*+sffW*{;ArXQB4WpnO>F-~<7SSm4 zU)H;>=Mqpu7Lrak?}m6cn1<--r?CyoK9}XyicyJN_(DLE+o_hNy#90^8yWE_RE4yy zaAn5|hO9%6&zeN@NJVQn-nN^U&5IZ2ns9iarT#SAxjq(IP?`bbdNV3fda9KE(5=PI z6%_&6#?7Q#oxIOUV7~=zR~G5Gv0ul;3YFWwz;j}d zAJA>Po>H7W+ zY=U9zl+8JxH$U0zkI;!uiC_b7;=|k3mS3){sHc3vhaW&5Y0cIq=H3fis~TUkmxTt4 z`8?|qS$oIRw8{A!`ZiCa3Q~MnQCXjmjr;7#T8?E`U&X#YIJ#7|UkQzYSE#~&txz4m zqUNyZV_vo`_f}Zv8u3Gnx`~IEv@c6KcUnZPemYY7M0M5WGb@6pxV>Aa!vbRN64!EC zV>e5FmLB!+tVyT5rDmtu1^b?(Xp>*fn@qQ$EjLl#y8h|^9gX^py<`~kNZ$owDpF?C zmCLwn^Ty0l1F~1|)XeEQ_;GgDWbDD4}sPgdf&Gjkbi$njb01V3%=*o+~1slGi=S9Nl3lA?MZ&xJ$Z)3D&(X<*sWGr zicC3m>UfNYeA5ybdX9q3kE@`ZsaEQ&)6sE?-7s0Opc zNQL6dVbq=Z%i&p&iAY?0_Ow*5VaLlj6~@8~)wyDxz!~Sy1j9ofv%EqQ+_9|0vF5u@ zJ-N}hl$oo+c_cJ@Yl*+K=dz%thN|j6PTPNmtH-=+T_SR&I6=ru&Y4iN;q5_XC zT}q#l1bry&S8NL|J7ebSHr=k=aUn9v*MGyzU+aq2U(@%dd^@ap+9%wvlzTP^BH%JroyDdq}hqt8dhmTnrJ1`7q1dk{|5#LGVaI$`YfUd3A7GIRU!t9%#~e zC7St4cSuY(+hWx=(Oo0~xhrtBcni1$&yRV)j#Q|PR%!=86=|P39&){{+{va@cFe}S zj7<&8b0=C|5obs5QCr;7&W8Q5wCvLhRm@MakXM)mZ#eV@@0m)z%4O z*5f8|YL2dYuWzw@8U(i9M(?u0V6g@Dl_G%e`I_PpfIna5nGodug+%_p07ZZy{9g#^ z(0_siZnuT5*Y{%I_A}^_6YGk5`S`c`_u}nEF08B62WZW2)loKJpb1(x{SzPyMM)_E z)DO!5kla?FxKcnmn|?zj8yBGUaAmsz-s=9n{(plZ{cXZxumGJM4WJ|>>&bm)W@fP8E1(nPY3p(b=3`7OXE`_n)WDpHynw)Bt;1 z8D#&EO-mIUnO#6fDEFIDn=f-60K#9nn*ViR%aAWFE}Dt)@x8l~J@_>N2z7tvAMB}0 zV7ZUY{I|D_Q2qg@X{wRfPCyCtEkNVOEc3tnfz+z1Q(d6WZXJM*{{!0v{sFIyJy$p` zeE)9T^%qZ7CD2mC7?_!PLjlyf`K$|AV!Ab>?dhS~*_{}=9~dM3Se7bpUkW_DJ`&YpQacg7RSh^Ef&tChG`56@=kF;WwyXPz}Ari8{?IkN%;?W${ekGt~jToX zQD|mwu4(Jk{jlZBdH!I(^z&b6G zw<#+SAlJ{E>m#dShs{g9pUM@HzO5Y6US+qxPHC**#ND&lvib!XyYB6*9Jl{C?QoP7 z$@k`~eY#}wm*K9c{k6JGy)?ALp|L0L3M!rrV?t;`y!dF?p zZm(hc+9|J}*U@n1;Zw{siniNv7v{`aBL8rj-`Uu8f`!M(b;T z)$X@fydAV$TTV6Anl7!vwYXiXJzmVoLRD2alySVjSGkoCYa(jYedi)NITqT6n|G6Q zc70DPnvaBIDJ5!V=HkW{$@9QqhQWNO?V@K)4fVuD^#7G3_YPVSN87Pb92+>sJ2Hn`;kvi zgQmB)TY{+D=LIyP8IyvxA?mpwGo>wScBah)Ky9X29$*Xt7x!u2q#M{7UH2fcl(u|A z{4{g{@y97(+AHyQ9@BHLz9oCICum@K%n zzk@4C`-b4yqGW{I%PD2N?&nqm5}mmnE;bkBpEZ%nvimzeMPbP-*i(5C;++igE(1T? zJg@pWJ6)%lc61MR0bck)oIvzEbSJXi81)y|4(dG*yl1OB1_csoeX)+bf`NJL zdKEK_#UCD2%(6eY-A5`a%|;7b6Xg_FcpsZ+I8g9C8AQRR-H-^Lc?l=b_CIxE=)YDw zpFaQ0U~Lu=G0IW@^=$d?XwZlg&}#Anv{^qu~KP)?~ zG@sO;JKPc|Ye?PmD(SkTwP5V}Z$5NkF@yvicVH4u=g*opCJWH@?RPL5|Gd)Pk@P`v z_zYX7v>)S@*Z$J3@SlTLdTc~PKoOA#GU@dP3jmGxO|Md|3=HgjNJ<(j4i2f){%uRz z;^My@s=N228Wtp8kcv$&B~GE?Re{wM!1cB8Btn)k-yi~!;r*|D2sget`SXrZ+5xe88t*m?25V#V zeBU-BTfjp0=IVJyF9h;!V=A5U>ebXz6y}x&wU};Q{yV7utGKfaific>_TU7U1cF0= z;1D3VOn{&X!QF$q>)`IL!6CQ>9o*d|NN|GN;1G1aNpersxj){w?!RwWP1V%iGi|$j ztzN62?sXhTeXq*3N~V-A(W75$SW0}whN8=7cD5UhFvg0)(?)K=xXj9@E5h2;!AAI3 zN1?t`upd}lcrH4#X~e04X0`l5ctL>4M2c&&5~-p%yVLkRWHydk4F9C5uq>Cn_e z4-HbAZ}I|DRVQ3hXd9IUP>*vHG#Ilz+%2TL)*%&!EeWIFTYww36Dsu-*AkuY`>xA8 zw?;E!yop@7KR8Sp_i9$T@jQ%lX027VF-s@gqc7f6O}l-6swd z=LnX=L8>>(8=u$iaGGTjVwykL@DF7CdXts~xo3N_T|S7JDEum*x5QKXblO$BOFmxj zq#SZ7v@&qm+0>M6>jlgOY}b`cxi}V8kkEopd>U2UH^TWFXMdp1WSZ+u@V((>09Gwm z1UUNdK4wjcAX6gvGd8ZJ4Gdt8ghX&9vsQvD5@M1C>{yF}mF;?*CL*ijI#%pY-%Vqt zYw@QFv4RKVXM{Zohv08fg?6_pykul(o%vG;PuC;fJ(s8|S@~0d;ENZe-e&qvBlR`uqyh zy&f9L+06rY+*nH5UfpE-dW2P1?(Q*>-VJdkR3#znQ$tex5?duNjC48lEW$&Sc8kCI zaFEVV@3VZTr+bpjE=B^e@*e80*Z5giN1l}OM0%T?LT>`Pn^? z*K;~WMRydYhp%aOySl!ieKlA!%8B}$wFrH17`fV1gEaoO!kvPei30m7pPVrZVQjIdvDLVXmPq ze7}$4YzdKcd+wOOH(e=r`8Dw)j8urT=k?x>w)~C?eC;3l?zuJLfv)E#z9bmtW=k1vBw3)`^dC#@7%lPW1WS-6g?T=IBH#K5Jf3c&H&2p=s zda<)gl~ggRNP6Jqx#e(SYv}D>wUhYS2eY*95MKx>`i}~R*>)VMlmfv%4t8T=IS%s}HpG-AYg%RY1+u;a?#&-y{3pJSDlkqg{D?khZSKY9Hp#N~dk z2AI#@U`?6meKqA%$6jtunaFjRw;B9#Q1D}xKbGXKQ=s`6Kt1M17(8Gyi}6v| zU1J-zUjTrB#AKi$IH$Lm|tC%OFE55FfC-CW{ zY4P(WWN@PM8{=8Em-;%Q=92N05qW-n6h!6>=97cI{AK{}mut8U{(-e26`z{X?^5c$Cg1N?z+^4)lN-%WN$fab=P0l7TkHOpPz4LBsW7$HZu2KV)uH%{u$EVNZAztf5co=08nNv0p8&XYv)E%xz13m{P z2Q#Z~+rsd2%eCc~38h%U_@d8yrVPMr_wPN*}&9%QpU2R+LjSXSvSV(Dyi z>*{kWB_fOYFQ=GshBYhRJWPnC3O8f79w7D9c!TOv+aK4ohyMfGf>MZbU@a#H-5!1X z^>mXy`OE^bA)6#f!bLNm5~II<^smPxotC>QoVH=~$#l zZh4nqNkwj@5C+h6khYhJ%KHk3cMi>0x@@BQ(T2h~%yN?dEe<2J;brT|rC~$*{hm8~ z!7-GR-xS7I{4p9YUoJW>IKM@RH;a;>YL`cdb*zn}9Rj@NZF@qmJ6S@g2XzF@@7VVI zSoYB?y~Y$*cgLO1G+gldbZ>Nw&X`&XH%PS5u8-{fsm#~c;uF2;U?@r#BG;Ge_ZF1-1^}sNxcP!2s8i?CrlA!S*iTzhg4uH)gM_fjvE_zaE?=Z#`qr5MF4V4M=Gn=$x&OgI2Hwv$3~*((zKodVVA$c=6PPZJ zxhF#RM$r zI`IkVh_eqLNKpBvUQV&#p#wtw0WUr7O}*H!E_@HIACLFP6sp3^%P4XL2Qx(3etu zemLvK_CWUiZH|!F;~L*AXnABn+0Uu_t^af2qfPQ zgE6X1;!3$qfw8TUQ+{Jar_DKL|Jx))R>IU5i~|GY(q${F*u zpi>qApraYy^@x%+%NLN9GC09gK;DsTeqYnOsWv2hFi_1R)?^y`*Q!L2E@6eqV7qikPBk(%=_+57wMfICPe3Lm<_&k=3;}@`v`-%?4 zGz&k6Y;DU$rCMB0RXQ5mEyw%U)%`HK>hMYz3aP1{`HsKvW_{JrPcg9Cm>g_9$bm>P zfyywP`Bhvb7t00fT7Dh=>k+fjik6&wuJ;IPV;Dd``W=vso~KA8#T~`fsPh#>@G}<& zq6$l0rLB_FnI&%MC(NU2J7b4^e$#g!H4zqP((^y?*OlL{>(2LQ4iH6Qh-`-tP^pS9 zag_yK=U)Fh7(N~dW=_0#_X32wWNXv2By^%L*3)dJO!smOxfMw+q6H}sB<6?6B})7~ zC`w+LzWn(*w&}*(%H`(J1W67%O3C1y%BaeXYuAvx^jGwGaLYc?k`LQ2No5i?Oba^N z;DsK6vC79baiYOri=GPk$gI`1xr52rwu9(+3)%K3YfMl)xjeA*22T1Pkaj8Q+fE_9 zuDCV~i3fr(b{lvzKD`Fb`vR#IG@YzwIRD?2jad?h=$ND46JjHf%E9k9MJsFkgzi^@6zqk#bXth1Z%xVd7E8NI5JH`FGxMf)|uCPqietW41jY?h6#bTZLX(fa>7i4 zKWj`Ld(9KQ&n@753js*3lG0L08d5USBH?q$vx387&Nqhdrh>klc7kt^g1+RT%i~`u z5txxbatKgXjw0rCG9zvlUW$=z2b}S$sIE&QG$d4;zHXLX z3#6GLe);g@&E;jyyYW?xy~~v$MV;Polbvrkz7PIZM$h5Jd4%I)le5m=Wn&Kgo_tJa z$>>FUQarlRe}T5FjNUh--^l~R`G^&S*SX3cDtHvDGP-h8m0*#pI0XcW^cQ!F^63ajJ9$**F+q=ePMuS4Lp>!J}+87&vIo*~!YG_*f~ zEKX;#mkpma1A|6e?E1Y-4^XoJ1q#i)lmcvIhSKZ9`cdTw95ea7Qp)Css#u; zCWV6$T7Eal^?lcVNjZ#t?(hKRqyQX?w(mJlazspVwmMI=MB%C> zpo{~jA=4A3{LDA<@_19BO@$8eDm_pSuO2`{BUv@jJc5^FCqcG$E>38wNNn?Uk5Vi! zKj66bF^5vUYfcleMMDZqhaq7Z&d)8e3WaN5#gu*l`hP?m405Gx49>GwH>|T(Mw)Zy zqxYpPXTfMfoZT2sbCik$6u3HK9LiH*TB!KHz9n!17-bS@!nmqo85Mb1hIexry%Y+r z;ot-Y{Z3RG-j>+q5WjG206q9(!)XoK(n)g z;w~ox3O=YH&S6R*pu;(A*q5(?PE7incw09Cl^@{0s~qI{Md{0fJnm0$!l_mmMKD=D zJ^o@3w&4v?ww@A};;SVN=x6QQuX7`9&A>j?4DM4Y1xqV%#3rPp{OEj4a(1E$u55)L zs%9bZ0b)drI@;T9nEqnayoisc3s!_0gEhD_mF*t9D4=7a>y%8LRpBTnNIV1<15_2*OV%JI5UkgW1<$jBo zl71`t0!+x1k4HJ@K?v&TaJ5Clynd)6EcLpWq%AQEvPtmnmy%OcMc-}@mE5}4tbFv7A%UxTqYAgBWynHCNq(ByaA!)DL;2#>PxFsG~ z+n(B9=`S4s6Cpg3R|o(G+zx0R;KH_avM(RIxh}NRcQS~#k>|z8Ku6e78<%fwh`nY* zFuW^y%SmFm*22S#+(H~w;E5m4@9xFNSjWdVs@XFl`_IFZlTPmG8H@GFTX0yADMZ9Z zc&!%gkuoOq7#GjMF>GO`IY6A3=;x(i z8UblBP#~Nk80*<`fh#sjjw<8f$SqaJUs=rx(otGkZNp`jcjHF8pQa7v7D27Lj_g3k z8_s=9Wn*V8$Ft&^|7N+ym+G1t*r&6c`5%#Go z2at&_rWeRN;*%6J*>v_w++T&n953~Oy6JBbHoM#O(|w2pt~24ffn9kJ8=RAVb@}BH z?dG2;w!*zy&J}jXH^dJoA+*2v_|b(~sH+d|r_4;wI{hLf#OMrSXOSM-PXsxJ-E+sZ zIKMq`vC-@M`|=R#&zn9@&gJ7sHdGFr=ew?JS23BeX$ETKiuWM}EOLH@7OJp&KFJ)B zu2Ez@uILwy4rB`AHrUipy05=K(m3Pu;E(Y2vnLvVK8AuJ0g^+f=U_FsiF5ng>O1O7UgS7(G$RVFP^yuixePWfqU^h2KHYEXpcA(lu)Saf zP5df!#TB>2 z@sOWBe)w-p%ere@94u)J5$tkACfY8!yM9%qnq1E+Cs-1t&z(gdAbO5n(V}%H%Zr~c zeyipV?I0cKp4m?Lqw@`EJbq?QdC7|c8G!4sgDM}0A< z6DC0A-a|ds&Sml|c?KvAERsWb-;~BF+F^`%MB%0^;n}QB%PgduNJ1`%URe8tq#{gI~eu{63q& z*kMJztIZTXn9EaQc-aT>b9Bs`Q~XMy=81(c2xltT)cZ_d2|a+$GoTAUvbL=V`c@NN z37pZXOwPy#{gXTEZ>R#aQ{lB_Scp0pi{4jvq2*-~{gSi3hhz?zp$*JQhzMQYCGl4> zsF3)iAd#fXAkt*MSR@t`?QN(uz!;t&;f0!1&`#`2>-v|lx|=92XEK3BR(Rd`=cCfB zTJ|GWN6%-~JfrRc+}WmKms~mFiVenS=eWwKoLVXKpfV7dc}jL}kK`*0sLyz+6%#1C zBc!WHgYI;m=2W!XV5wzVT=5D)-`l(d?0G#s?elxgA<_)?GjD9pSPZg_pcbY=lLOGq1F=gBG`~G14(z2oN-6?O)xEX*yGiyPyCD&BFsY zLD-dtHu$Ec+$?o2Rq2zCcTaLk&T7m%;NqsEN3WsG6j$*5TsyQG^Vaw0#^Cux)hW?b z`S5FyV}jL(-5jkp6Ef0l#vVk#`FKUKU`@e^?F;5H4whli^0R#*>#?k*`1uYm;dSMUC5zA*PP&s%)zjn@dLt8+poc1= zQwBbYyNjWJc1pI@JeMg@O{A5od9qX$QInH?5H!ldO@WmPrmVf`C!3$fCk11UePIU;M=RXQB$XqQXI`i;UQrY$X1saK z8%d9FQOiyv^%58mqK1HF5FB>4Tu9Cj=fTFQ7BS@^7!RvZ9|0y{&qMdYYG%zY z7DV{4(Q?zEqsrYd$MBZZOSMR%kokCe>iMM5w_|^^h@q8WPak@_Pom$i(vv2b4<|Qw z2v<;|7Gqb{#(_q+<|$yGWfgZ#kMGB%F_DeVNgl?db51eZ*JH9oCgNUq79uVkEK8Lu zP5U@pv&LJ=+1So(y(<*Yzh}H*Vt`CTfLjzbZdQW+MT$OpH=3S{uHEyy=?_l)+(K2K z?@Exk4oTf7F2?wZfRnj_6e7$eI>vx*5=LwaKDW{=WSlq(>uTU!zUKA={d?LG8(*5` zaDMeeP5t+u#b)r$X?Mi*g#Rw0-$! z$@uYKY?Iu<}11Zr9mlMJ$GQ$x4Q zSvXYk!Wu*eiw)B&p~pAII@=U?H3fXF<^AVnvZc|#8n3J<1eVgtHzT(U6$2nJ?%Aj+~Kgv!|cZhvVBzZB2bWgMd3OK4f z^|#ij`Bl}Ko@$S2xjuxq)ZNQDx`~g)|C|Du6_adz;`37jRgEYXf?-r=(DP*XwXN=Dl2S9qvt}ltoJA? zK!t~5QVsf*JM2~hJ{VrGBBisj*r(X&aMJ(1G}fGMe3y1XuZ@APge00*xTLRdEZ@@Y zsATrMe#OwFiVQy?&v7c7Sz|Cf#!w4ruu-K8IVlMuV>ZMT%?_rp!X z+@iy6YV<;_3CjhRizCl8cgq6<(bBFVd^XTa>1T2jF>Xkd2plz+y*ka0bP*b~{rQe_ zOFAMBWGON-NYXYi@uk=6Y) zNz4-X_e?mO$(yfLBlyhEn0+3_Cau20M!#9j2JPn^ZeHX%GV*2rvnhLu>Hk1V*uh8% z#t0ZGp$;P@F8)PI;3A5!vX3j4`}nNEG@Ez|71Z`*H6V}wLJ*oIuR#s1PSif<7$viO)_HkKVxd3Gg)d~nY^1c-28iuQ3{-6iF z%u=a($eoeSC7wyJ&-tv-bL*wRR&Ynw=3=*h`AgE2z_yC}5T#Bsf_VtxF@aL!$>O@j zm<>ImFYnjRQ~CHK)XnFKCuVFnb=cvRDfDiSyQ+W!QfAeRJH5R8(vF#v##M@Tm?ydn zRoY4hgV~yy(KUInm`wf?8N%iNB0ifp$MDisZ#X+*-_i+ z=^Yo+w7F*&mMUvjlP@DhXQ1j}r!!CS#QjR+Fq$PzpOZG}ZWe9RQ(Goi7TX3-FX!lG z_mzs=dN4G&%L|;uV*T3oq?%!Nf5h?Pn$Y_^K~3~ia+~8L|vcF_9PggePHO?$U0zaYxO~ zS>vp|Yu`Umm?|TKhV?pwJ|Z%5zHEYlnr>cvp0LU1VW_0U`EIM9SFNPagFN0!Xre2B z3+{L836j$I%*-6lwI?fAFVZ<0ZlimN(tpL>IOd;dzV7ZWOOO?%_oyPrTD8AiWFEos zdDajjldYIWN!C&8JkoS~{5t=zezWSe4ZnehXYpah@tFH(4{?w8((bF_ZDouC%$gU+ zXcGt#3A!<#meTZ0tKGiaWSx!f1sVt4s_03i2Wd>%Z);1rmo2jK_73F4DiaW@$mto5 z&3@A&)9Go~c}Z`$n^+X|Tovj*yQW)d)%IdR{&Z(+m#|{Zu5hGB?S;TeM3X@gtF_y4 zJ|TugF8gDPTW@ei&&U?hM27q4M&+t$phDWuJM*RFR;37=ODD@O5$BgAP;XEnb6{*x zY~tPJIcS1K5IMbRx?iySK$rH1p^<#V?pW;?r4)W@mj2iC6AsYWEAJL=88ok-y)+a6N-XwqC z$|!6F(i*8%YJ9VMBy0l`uu5mL?G#q*yNN-qq8{9=lkV~h} z#kUw=pJ&O&6d<|9H1lneL3at*vc8EiNE4XT!x~%m#Z2wN;HqhMd#0rfnp2rQ_7@M9 zqT^j$kc%k`suDdUkZsvr-%{o{?kF&hqOoKdo~m*7@ia zFO4c){J9w-1a9Q~WioarD9YD9u&Aq}r0Uu3t$R`#Wxtrex-nB_MSx!4(qR1P;yFva z)?2r7Ld<+a?_ouzhMF5D*ZfjLZ+osFTTx(9+LM7s&#`D<6Bge3uU^bpd3W+$ji;zBc<=?@gPuU!et;IXs!Rsz7VpBVHG^KIx zy|CDkXd3Ay*hDEs)qJFjy$}|U@_S_Y`q_OrcDt%#6C(Vzk+BeJaG-kpHRZ#BA~@yv zaix(5a<}#cxrO{&0w=7Lu%2P?pVAM&PV5aAM?9d zD7ZYVr}+yKmYVa$obo%06Re9KZ&ga3q(Fp UTGN9>e*Z>V{L}kNQGNga2NcxNp8x;= literal 0 HcmV?d00001 diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextExitTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextExitTest.java new file mode 100644 index 000000000000..3f6f974fc247 --- /dev/null +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextExitTest.java @@ -0,0 +1,653 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.api.instrumentation.test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.PolyglotException; +import org.graalvm.polyglot.Source; +import org.junit.After; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleContext; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.instrumentation.EventContext; +import com.oracle.truffle.api.instrumentation.ExecutionEventListener; +import com.oracle.truffle.api.instrumentation.SourceSectionFilter; +import com.oracle.truffle.api.instrumentation.TruffleInstrument; +import com.oracle.truffle.api.nodes.Node; + +public class ContextExitTest { + @Rule public TestName testNameRule = new TestName(); + + @After + public void checkInterrupted() { + Assert.assertFalse("Interrupted flag was left set by test: " + testNameRule.getMethodName(), Thread.interrupted()); + } + + @Test + public void testInnerContext() throws Exception { + try (Context context = Context.create()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "CONTEXT(CONTEXT(STATEMENT))", "TestInnerContext").build(); + context.eval(source); + } + } + + @Test + public void testExitFromMainThread() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,EXIT(1)),CALL(foo))", "ExitFromMainThread").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMultipleMainThreads() throws Exception { + int nThreads = 10; + ExecutorService executorService = Executors.newFixedThreadPool(nThreads); + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + List> futures = new ArrayList<>(); + for (int i = 0; i < nThreads; i++) { + int j = i; + futures.add(executorService.submit(() -> { + try { + String code; + if (j % 2 == 0) { + code = "ROOT(SLEEP(100),EXIT(1))"; + } else { + code = "LOOP(infinity,STATEMENT)"; + } + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, code, "ExitFromMainThread" + j).build(); + context.eval(source); + Assert.fail(); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + })); + } + for (Future future : futures) { + future.get(); + } + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + + @Test + public void testExitFromMainThreadWithOnePolyglotThread() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,LOOP(infinity,STATEMENT)),SPAWN(foo),EXIT(1))", "ExitFromMainThread1PT").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMainThreadWithOnePolyglotThreadExplicitEnter() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + context.enter(); + try { + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,LOOP(infinity,STATEMENT)),SPAWN(foo),SLEEP(100),EXIT(1))", "ExitFromMainThread1PT").build(); + context.eval(source); + Assert.fail(); + } finally { + context.leave(); + } + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMainThreadWithTwoPolyglotThreads() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,LOOP(infinity,STATEMENT)),SPAWN(foo),SPAWN(foo),EXIT(1))", "ExitFromMainThread2PT").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMainThreadWithTenPolyglotThreads() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,LOOP(infinity,STATEMENT)),LOOP(10,SPAWN(foo)),EXIT(1))", "ExitFromMainThread10PT").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMainThreadWithOnePolyglotThreadSleepBeforeExit() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,LOOP(infinity,STATEMENT)),SPAWN(foo),SLEEP(100),EXIT(1))", "ExitFromMainThread1PT").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMainThreadWithTwoPolyglotThreadsSleepBeforeExit() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,LOOP(infinity,STATEMENT)),SPAWN(foo),SPAWN(foo),SLEEP(100),EXIT(1))", "ExitFromMainThread2PT").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMainThreadWithTenPolyglotThreadsSleepBeforeExit() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,LOOP(infinity,STATEMENT)),LOOP(10,SPAWN(foo)),SLEEP(100),EXIT(1))", "ExitFromMainThread10PT").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMultipleThreads() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,EXIT(1)),LOOP(10,SPAWN(foo)),EXIT(1))", "ExitFromMultipleThreads").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMultipleThreadsWithSleepInMainThread() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,EXIT(1)),LOOP(10,SPAWN(foo)),SLEEP(100),EXIT(1))", "ExitFromMultipleThreadsSleepInMain").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromMultipleInnerContextThreadsWithNoExitInMainThread() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(CONTEXT(DEFINE(foo,EXIT(1)),LOOP(10,SPAWN(foo)),JOIN()))", + "ExitFromMultipleInnerContextThreadsSleepAndNoExitInMain").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit() && !pe.isInterrupted()) { + /* + * Inner context is the one being exited, hence the exiting prroperty of the outer + * context is not set, and so if the exit happens during JOIN() the final polyglot + * exception has only the interrupted property. + */ + throw pe; + } + } + } + + @Test + public void testExitFromMultipleInnerContextThreadsWithNoExitInMainThread2() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, + "ROOT(DEFINE(foo,CONTEXT(DEFINE(foo,EXIT(1)),LOOP(10,SPAWN(foo)),LOOP(infinity,STATEMENT))),SPAWN(foo),JOIN())", + "ExitFromMultipleInnerContextThreadsSleepAndNoExitInMain").build(); + context.eval(source); + /* + * Here the exit happens completely outside of the main thread of the outer context, and + * so the outer context finishes normally. + */ + } + } + + @Test + public void testExitFromMultipleThreadsWithSleepInPolyglotThread() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,SLEEP(100),EXIT(1)),LOOP(10,SPAWN(foo)),EXIT(1))", "ExitFromMultipleThreadsSleepInPolyglot").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromSpawnedThread() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,EXIT(1)),SPAWN(foo),JOIN())", "ExitFromSpawnedThread").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testExitFromSpawnedThread2() throws Exception { + try (Context context = Context.newBuilder().allowCreateThread(true).build()) { + context.initialize(InstrumentationTestLanguage.ID); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,EXIT(1)),SPAWN(foo),LOOP(infinity,STATEMENT))", "ExitFromSpawnedThread2").build(); + context.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testMultipleContextDeadlockOnExit() throws InterruptedException, ExecutionException { + /* + * Parallel exit of two context where in one thread context2 enters and exits when also + * context1 is entered and in a second thread context1 enters and exits when also context2 + * is entered. + */ + ExecutorService executorService = Executors.newFixedThreadPool(2); + try (Engine engine = Engine.newBuilder().build()) { + try (Context context1 = Context.newBuilder().engine(engine).allowCreateThread(true).build(); Context context2 = Context.newBuilder().engine(engine).allowCreateThread(true).build()) { + TruffleInstrument.Env instrumentEnv = engine.getInstruments().get("InstrumentationUpdateInstrument").lookup(TruffleInstrument.Env.class); + TruffleContext truffleContext1; + TruffleContext truffleContext2; + context1.enter(); + truffleContext1 = instrumentEnv.getEnteredContext(); + context1.leave(); + context2.enter(); + truffleContext2 = instrumentEnv.getEnteredContext(); + context2.leave(); + instrumentEnv.getInstrumenter().attachExecutionEventListener(SourceSectionFilter.newBuilder().tagIs(InstrumentationTestLanguage.ConstantTag.class).build(), + new ExecutionEventListener() { + @Override + public void onEnter(EventContext ctx, VirtualFrame frame) { + } + + @Override + public void onReturnValue(EventContext ctx, VirtualFrame frame, Object result) { + if (result instanceof Integer) { + if ((Integer) result == 1) { + callExit(truffleContext2, ctx.getInstrumentedNode()); + } + if ((Integer) result == 2) { + callExit(truffleContext1, ctx.getInstrumentedNode()); + } + } + } + + @CompilerDirectives.TruffleBoundary + private void callExit(TruffleContext ctx, Node node) { + Object prev = ctx.enter(node); + try { + CallTarget callTarget = instrumentEnv.parse( + com.oracle.truffle.api.source.Source.newBuilder(InstrumentationTestLanguage.ID, "EXIT(1)", "ExitDirectly").build()); + callTarget.call(); + } catch (IOException io) { + throw new RuntimeException(io); + } finally { + ctx.leave(node, prev); + } + } + + @Override + public void onReturnExceptional(EventContext ctx, VirtualFrame frame, Throwable exception) { + + } + }); + Future future1 = executorService.submit(() -> { + try { + context1.eval(InstrumentationTestLanguage.ID, "CONSTANT(1)"); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + }); + Future future2 = executorService.submit(() -> { + try { + context2.eval(InstrumentationTestLanguage.ID, "CONSTANT(2)"); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + }); + future1.get(); + future2.get(); + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + } + + @Test + public void testMultipleContextDeadlockOnExit2() throws InterruptedException, ExecutionException { + ExecutorService executorService = Executors.newFixedThreadPool(2); + try (Engine engine = Engine.create()) { + try (Context context1 = Context.newBuilder().engine(engine).allowCreateThread(true).build(); Context context2 = Context.newBuilder().engine(engine).allowCreateThread(true).build()) { + TruffleInstrument.Env instrumentEnv = engine.getInstruments().get("InstrumentationUpdateInstrument").lookup(TruffleInstrument.Env.class); + TruffleContext truffleContext1; + TruffleContext truffleContext2; + context1.enter(); + truffleContext1 = instrumentEnv.getEnteredContext(); + context1.leave(); + context2.enter(); + truffleContext2 = instrumentEnv.getEnteredContext(); + context2.leave(); + instrumentEnv.getInstrumenter().attachExecutionEventListener(SourceSectionFilter.newBuilder().tagIs(InstrumentationTestLanguage.ConstantTag.class).build(), + new ExecutionEventListener() { + @Override + public void onEnter(EventContext ctx, VirtualFrame frame) { + } + + @Override + public void onReturnValue(EventContext ctx, VirtualFrame frame, Object result) { + if (result instanceof Integer) { + if ((Integer) result == 1) { + callExit(truffleContext2, ctx.getInstrumentedNode()); + } + if ((Integer) result == 2) { + callExit(truffleContext1, ctx.getInstrumentedNode()); + } + } + } + + @CompilerDirectives.TruffleBoundary + private void callExit(TruffleContext ctx, Node node) { + Object prev = ctx.enter(node); + try { + CallTarget callTarget = instrumentEnv.parse(com.oracle.truffle.api.source.Source.newBuilder(InstrumentationTestLanguage.ID, + "ROOT(DEFINE(foo,EXIT(1)),SPAWN(foo),JOIN())", "ExitFromSpawnedThread").build()); + callTarget.call(); + } catch (IOException io) { + throw new RuntimeException(io); + } finally { + ctx.leave(node, prev); + } + } + + @Override + public void onReturnExceptional(EventContext ctx, VirtualFrame frame, Throwable exception) { + + } + }); + Future future1 = executorService.submit(() -> { + try { + context1.eval(InstrumentationTestLanguage.ID, "CONSTANT(1)"); + } catch (PolyglotException pe) { + if (!pe.isExit() && !pe.isInterrupted()) { + /* + * context1 can interrupt context2 while it is not exiting yet, because + * it shares one thread with it, and vice versa. + */ + throw pe; + } + } + }); + Future future2 = executorService.submit(() -> { + try { + context2.eval(InstrumentationTestLanguage.ID, "CONSTANT(2)"); + } catch (PolyglotException pe) { + if (!pe.isExit() && !pe.isInterrupted()) { + /* + * context1 can interrupt context2 while it is not exiting yet, because + * it shares one thread with it, and vice versa. + */ + throw pe; + } + } + }); + future1.get(); + future2.get(); + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + } + + @Test + public void testMultipleContextDeadlockOnExit3() throws InterruptedException, ExecutionException { + ExecutorService executorService = Executors.newFixedThreadPool(2); + try (Engine engine = Engine.newBuilder().build()) { + try (Context context1 = Context.newBuilder().engine(engine).allowCreateThread(true).build(); Context context2 = Context.newBuilder().engine(engine).allowCreateThread(true).build()) { + TruffleInstrument.Env instrumentEnv = engine.getInstruments().get("InstrumentationUpdateInstrument").lookup(TruffleInstrument.Env.class); + TruffleContext truffleContext1; + TruffleContext truffleContext2; + context1.enter(); + truffleContext1 = instrumentEnv.getEnteredContext(); + context1.leave(); + context2.enter(); + truffleContext2 = instrumentEnv.getEnteredContext(); + context2.leave(); + AtomicBoolean callExit = new AtomicBoolean(true); + AtomicBoolean callExitToBeCalledForContext1 = new AtomicBoolean(); + AtomicBoolean callExitToBeCalledForContext2 = new AtomicBoolean(); + CountDownLatch callExitForContext1Latch = new CountDownLatch(1); + CountDownLatch callExitForContext2Latch = new CountDownLatch(1); + instrumentEnv.getInstrumenter().attachExecutionEventListener(SourceSectionFilter.newBuilder().tagIs(InstrumentationTestLanguage.ConstantTag.class).build(), + new ExecutionEventListener() { + @Override + public void onEnter(EventContext ctx, VirtualFrame frame) { + } + + @Override + public void onReturnValue(EventContext ctx, VirtualFrame frame, Object result) { + if (result instanceof Integer) { + if ((Integer) result == 1) { + callExitForContext2(ctx.getInstrumentedNode()); + } + if ((Integer) result == 2) { + callExitForContext1(ctx.getInstrumentedNode()); + } + } + } + + @CompilerDirectives.TruffleBoundary + private void callExitForContext1(Node node) { + callExitToBeCalledForContext1.set(true); + try { + callExit(truffleContext1, node); + } finally { + callExitForContext1Latch.countDown(); + } + + } + + @CompilerDirectives.TruffleBoundary + private void callExitForContext2(Node node) { + callExitToBeCalledForContext2.set(true); + try { + callExit(truffleContext2, node); + } finally { + callExitForContext2Latch.countDown(); + } + + } + + @CompilerDirectives.TruffleBoundary + private void callExit(TruffleContext ctx, Node node) { + Object prev = ctx.enter(node); + try { + CallTarget callTarget = instrumentEnv.parse( + com.oracle.truffle.api.source.Source.newBuilder(InstrumentationTestLanguage.ID, "EXIT(1)", "ExitDirectly").build()); + callTarget.call(); + } catch (IOException io) { + throw new RuntimeException(io); + } finally { + ctx.leave(node, prev); + } + } + + @Override + public void onReturnExceptional(EventContext ctx, VirtualFrame frame, Throwable exception) { + + } + }); + Future future1 = executorService.submit(() -> { + try { + context1.eval(InstrumentationTestLanguage.ID, "CONTEXT(DEFINE(foo,CONSTANT(1)),SPAWN(foo),JOIN())"); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + }); + Future future2 = executorService.submit(() -> { + try { + context2.eval(InstrumentationTestLanguage.ID, "CONTEXT(DEFINE(foo,CONSTANT(2)),SPAWN(foo),JOIN())"); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + }); + future1.get(); + future2.get(); + /* + * Each exit is executed by a separate call to Context#eval in a polyglot thread of + * the other context, so waiting for the futures to finish is not sufficient as it + * does not wait for the polyglot threads. InstrumentationTestLanguage waits for + * polyglot threads in finalizeContext executed by close, but in order for this to + * work, we would have to execute the closes in a particular order which is not + * deterministic as it depends on interleaving of the two threads. So a close could + * fail because a polyglot thread of one context might initiate a main thread of the + * other context (it is the same thread but from one context's view it is a polyglot + * thread and from the other context's view it is a main thread) which makes + * standard close throw IllegalStateException saying the context is still active in + * other threads. + */ + callExit.set(false); + if (callExitToBeCalledForContext1.get()) { + /* + * callExitToBeCalledForContext1 might be set after this check evaluates to + * false, but then the exit is not actually executed because callExit is false. + */ + callExitForContext1Latch.await(); + } + if (callExitToBeCalledForContext2.get()) { + /* + * callExitToBeCalledForContext2 might be set after this check evaluates to + * false, but then the exit is not actually executed because callExit is false. + */ + callExitForContext2Latch.await(); + } + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + } +} diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseCancelOrExitTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseCancelOrExitTest.java new file mode 100644 index 000000000000..0d71c92d1461 --- /dev/null +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseCancelOrExitTest.java @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.api.instrumentation.test; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.HostAccess; +import org.graalvm.polyglot.PolyglotException; +import org.graalvm.polyglot.Source; +import org.junit.After; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.instrumentation.EventContext; +import com.oracle.truffle.api.instrumentation.ExecutionEventListener; +import com.oracle.truffle.api.instrumentation.SourceSectionFilter; +import com.oracle.truffle.api.instrumentation.TruffleInstrument; +import com.oracle.truffle.api.interop.ArityException; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest; +import com.oracle.truffle.api.test.polyglot.ProxyLanguage; + +public class ContextInterruptCloseCancelOrExitTest extends AbstractPolyglotTest { + + @Rule public TestName testNameRule = new TestName(); + + @After + public void checkInterrupted() { + Assert.assertFalse("Interrupted flag was left set by test: " + testNameRule.getMethodName(), Thread.interrupted()); + } + + @Test + public void testInterruptPolyglotThreadWhileClosing() throws ExecutionException, InterruptedException, IOException { + enterContext = false; + AtomicReference runOnNaturalContextExit = new AtomicReference<>(); + ProxyLanguage proxyLanguage = new ProxyLanguage() { + + @Override + protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { + return true; + } + + @Override + protected void exitContext(LanguageContext ctx, ExitMode exitMode, int exitCode) { + if (exitMode == ExitMode.NATURAL && runOnNaturalContextExit.get() != null) { + runOnNaturalContextExit.get().run(); + } + } + }; + setupEnv(Context.newBuilder().allowCreateThread(true), proxyLanguage); + ExecutorService executorService = Executors.newSingleThreadExecutor(); + try { + CountDownLatch interruptLatch = new CountDownLatch(1); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,CONSTANT(42),LOOP(infinity,STATEMENT)),SPAWN(foo))", "InfiniteLoop").build(); + attachListener(interruptLatch::countDown, instrumentEnv); + Future future = executorService.submit(() -> { + context.eval(source); + }); + interruptLatch.await(); + future.get(); + AtomicReference> interruptFutureReference = new AtomicReference<>(); + runOnNaturalContextExit.set(() -> { + /* + * When inner context is closed we know that the parent context is being closed. + * Parent context is entered in the current thread, so we must interrupt in a + * different thread. + */ + Future interruptFuture = executorService.submit(() -> { + try { + context.interrupt(Duration.ofSeconds(5)); + } catch (TimeoutException te) { + throw new AssertionError(te); + } + }); + interruptFutureReference.set(interruptFuture); + boolean interruptedExceptionSwallowed = false; + try { + /* + * The parent context is entered in the current thread, so the interrupt will + * try to interrupt it. Therefore, we have to ignore the InterruptedException in + * order for the close operation to be able to successfully continue. We cannot + * wait for the interrupt future here though, because it waits also for the + * current entered thread. + */ + interruptFuture.get(); + } catch (ExecutionException e) { + throw new AssertionError(e); + } catch (InterruptedException ie) { + interruptedExceptionSwallowed = true; + } + Assert.assertTrue(interruptedExceptionSwallowed); + Assert.assertFalse(interruptFuture.isDone()); + }); + context.close(); + assertContextState("CLOSED"); + Assert.assertNotNull(interruptFutureReference.get()); + interruptFutureReference.get().get(); + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + + @Test + public void testCancelPolyglotThreadWhileClosing() throws ExecutionException, InterruptedException, IOException { + enterContext = false; + AtomicReference runOnNaturalContextExit = new AtomicReference<>(); + ProxyLanguage proxyLanguage = new ProxyLanguage() { + + @Override + protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { + return true; + } + + @Override + protected void exitContext(LanguageContext ctx, ExitMode exitMode, int exitCode) { + if (exitMode == ExitMode.NATURAL && runOnNaturalContextExit.get() != null) { + runOnNaturalContextExit.get().run(); + } + } + }; + setupEnv(Context.newBuilder().allowCreateThread(true), proxyLanguage); + ExecutorService executorService = Executors.newSingleThreadExecutor(); + try { + CountDownLatch cancelLatch = new CountDownLatch(1); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,CONSTANT(42),LOOP(infinity,STATEMENT)),SPAWN(foo))", "InfiniteLoop").build(); + attachListener(cancelLatch::countDown, instrumentEnv); + Future future = executorService.submit(() -> { + context.eval(source); + }); + cancelLatch.await(); + future.get(); + runOnNaturalContextExit.set(() -> { + /* + * Cancel must work even when entered. + */ + context.close(true); + }); + context.close(); + assertContextState("CLOSED_CANCELLED"); + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + + private void assertContextState(String expectedState) { + Object contextState; + try { + Field implField = context.getClass().getDeclaredField("receiver"); + implField.setAccessible(true); + Object contextImpl = implField.get(context); + Field stateField = contextImpl.getClass().getDeclaredField("state"); + stateField.setAccessible(true); + contextState = stateField.get(contextImpl); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + Assert.assertEquals(expectedState, ((Enum) contextState).name()); + } + + private static void attachListener(Runnable runnable, TruffleInstrument.Env instrumentEnv) { + instrumentEnv.getInstrumenter().attachExecutionEventListener(SourceSectionFilter.newBuilder().tagIs(InstrumentationTestLanguage.ConstantTag.class).build(), new ExecutionEventListener() { + @Override + public void onEnter(EventContext c, VirtualFrame frame) { + executeSideEffect(); + } + + @CompilerDirectives.TruffleBoundary + void executeSideEffect() { + runnable.run(); + } + + @Override + public void onReturnValue(EventContext c, VirtualFrame frame, Object result) { + + } + + @Override + public void onReturnExceptional(EventContext c, VirtualFrame frame, Throwable exception) { + + } + }); + } + + static TruffleInstrument.Env getInstrumentEnv(Engine engine) { + return engine.getInstruments().get("InstrumentationUpdateInstrument").lookup(TruffleInstrument.Env.class); + } + + static Context staticCtx; + + public static void callExit() { + try { + staticCtx.eval(InstrumentationTestLanguage.ID, "EXIT(1)"); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + } + + @Test + public void testNestedExitOnHost() { + setupEnv(Context.newBuilder(ProxyLanguage.ID, InstrumentationTestLanguage.ID).allowHostClassLoading(true).allowHostClassLookup((s) -> true).allowHostAccess(HostAccess.ALL), + new ProxyLanguage() { + @Override + protected CallTarget parse(ParsingRequest request) { + return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + @Override + public Object execute(VirtualFrame frame) { + LanguageContext languageContext = LanguageContext.get(this); + Object javaClass = languageContext.getEnv().lookupHostSymbol(ContextInterruptCloseCancelOrExitTest.class.getName()); + try { + InteropLibrary.getUncached().invokeMember(javaClass, "callExit"); + } catch (UnsupportedMessageException | ArityException | UnknownIdentifierException | UnsupportedTypeException e) { + throw new RuntimeException(e); + } + return 0; + } + }); + } + + @Override + protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { + return true; + } + + }); + staticCtx = context; + try { + context.eval(ProxyLanguage.ID, ""); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + context.close(); + } + + @Test + public void testCancelDuringExitNotification() throws ExecutionException, InterruptedException { + CountDownLatch cancelLatch = new CountDownLatch(1); + enterContext = false; + Object waitObject = new Object(); + setupEnv(Context.newBuilder(ProxyLanguage.ID).allowHostClassLoading(true).allowHostClassLookup((s) -> true).allowHostAccess(HostAccess.ALL), + getWaitOnExitLanguage(cancelLatch, waitObject)); + + ExecutorService executorService = Executors.newSingleThreadExecutor(); + try { + Future future = executorService.submit(() -> { + try { + context.eval(ProxyLanguage.ID, ""); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isCancelled()) { + throw pe; + } + } + }); + cancelLatch.await(); + context.close(true); + future.get(); + assertContextState("CLOSED_CANCELLED"); + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + + @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") + @Test + public void testInterruptDuringExitNotification() throws ExecutionException, InterruptedException { + CountDownLatch interruptLatch = new CountDownLatch(1); + Object waitObject = new Object(); + enterContext = false; + setupEnv(Context.newBuilder(ProxyLanguage.ID).allowHostClassLoading(true).allowHostClassLookup((s) -> true).allowHostAccess(HostAccess.ALL), + getWaitOnExitLanguage(interruptLatch, waitObject)); + + ExecutorService executorService = Executors.newSingleThreadExecutor(); + try { + Future future = executorService.submit(() -> { + try { + context.eval(ProxyLanguage.ID, ""); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + } + }); + interruptLatch.await(); + try { + context.interrupt(Duration.ofSeconds(1)); + Assert.fail(); + } catch (TimeoutException e) { + } + synchronized (waitObject) { + waitObject.notifyAll(); + } + future.get(); + context.close(); + assertContextState("CLOSED_EXITED"); + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + + private static ProxyLanguage getWaitOnExitLanguage(CountDownLatch signalWaitingStarted, Object waitObject) { + return new ProxyLanguage() { + @Override + protected CallTarget parse(ParsingRequest request) { + return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + @Override + public Object execute(VirtualFrame frame) { + LanguageContext languageContext = LanguageContext.get(this); + languageContext.getEnv().getContext().closeExited(this, 1); + return 0; + } + }); + } + + @Override + protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { + return true; + } + + @Override + protected void exitContext(LanguageContext ctx, ExitMode exitMode, int exitCode) { + waitIndefinitely(); + } + + @CompilerDirectives.TruffleBoundary + private void waitIndefinitely() { + try { + synchronized (waitObject) { + signalWaitingStarted.countDown(); + waitObject.wait(); + } + } catch (InterruptedException ie) { + throw new AssertionError(ie); + } + } + }; + } + + @Test + public void testExitWhileClosing() throws ExecutionException, InterruptedException, IOException { + enterContext = false; + AtomicReference runOnNaturalContextExit = new AtomicReference<>(); + ProxyLanguage proxyLanguage = new ProxyLanguage() { + + @Override + protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { + return true; + } + + @Override + protected void exitContext(LanguageContext ctx, ExitMode exitMode, int exitCode) { + if (exitMode == ExitMode.NATURAL && runOnNaturalContextExit.get() != null) { + runOnNaturalContextExit.get().run(); + } + } + }; + setupEnv(Context.newBuilder().allowCreateThread(true), proxyLanguage); + ExecutorService executorService = Executors.newSingleThreadExecutor(); + try { + CountDownLatch exitLatch = new CountDownLatch(1); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,CONSTANT(42),LOOP(infinity,STATEMENT)),SPAWN(foo))", "InfiniteLoop").build(); + attachListener(exitLatch::countDown, instrumentEnv); + Future future = executorService.submit(() -> { + context.eval(source); + }); + exitLatch.await(); + future.get(); + runOnNaturalContextExit.set(() -> { + // No effect calling context exit during closing + context.eval(InstrumentationTestLanguage.ID, "EXIT(1)"); + context.close(true); + }); + context.close(); + assertContextState("CLOSED_CANCELLED"); + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + + @Test + public void testParallelCloseCancelExitAndInterrupt() throws InterruptedException, IOException, ExecutionException { + ExecutorService executorService = Executors.newFixedThreadPool(31); + Context ctx = Context.newBuilder().build(); + try { + ctx.initialize(InstrumentationTestLanguage.ID); + CountDownLatch passLatch = new CountDownLatch(10); + Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "BLOCK(CONSTANT(42),LOOP(infinity, STATEMENT))", "InfiniteLoop").build(); + TruffleInstrument.Env instrEnv = getInstrumentEnv(ctx.getEngine()); + attachListener(passLatch::countDown, instrEnv); + List> futures = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + futures.add(executorService.submit(() -> { + try { + ctx.eval(source); + Assert.fail(); + } catch (PolyglotException pe) { + if (!pe.isInterrupted() && !pe.isCancelled() && !pe.isExit()) { + throw pe; + } + } + })); + } + passLatch.await(); + Random rnd = new Random(); + AtomicBoolean exitOrCancel = new AtomicBoolean(); + CountDownLatch safetyGuardLatch = new CountDownLatch(20); + for (int i = 0; i < 20; i++) { + futures.add(executorService.submit(() -> { + int randInt = rnd.nextInt(4); + switch (randInt) { + case 0: + exitOrCancel.set(true); + safetyGuardLatch.countDown(); + ctx.close(true); + break; + case 1: + safetyGuardLatch.countDown(); + try { + ctx.interrupt(Duration.ofSeconds(50)); + } catch (TimeoutException te) { + throw new AssertionError(te); + } + break; + case 2: + safetyGuardLatch.countDown(); + try { + ctx.close(); + } catch (IllegalStateException ise) { + if (!"The context is currently executing on another thread. Set cancelIfExecuting to true to stop the execution on this thread.".equals(ise.getMessage()) && + !"Another main thread was started while closing a polyglot context!".equals(ise.getMessage())) { + throw ise; + } + } + break; + case 3: + exitOrCancel.set(true); + safetyGuardLatch.countDown(); + try { + ctx.eval(InstrumentationTestLanguage.ID, "EXIT(1)"); + } catch (PolyglotException pe) { + if (!pe.isCancelled() && !pe.isExit() && !pe.isInterrupted()) { + throw pe; + } + } catch (IllegalStateException ise) { + if (!"The Context is already closed.".equals(ise.getMessage())) { + throw ise; + } + } + break; + } + })); + } + futures.add(executorService.submit(() -> { + try { + safetyGuardLatch.await(); + } catch (InterruptedException ie) { + } + if (!exitOrCancel.get()) { + ctx.close(true); + } + })); + for (Future future : futures) { + future.get(); + } + } finally { + try { + ctx.close(); + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + } + + private static final Node DUMMY_NODE = new Node() { + }; + + @Test + public void testExitFromExitNotification() { + setupEnv(Context.newBuilder(), new ProxyLanguage() { + @Override + protected CallTarget parse(ParsingRequest request) { + return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + @Override + public Object execute(VirtualFrame frame) { + LanguageContext languageContext = LanguageContext.get(this); + languageContext.getEnv().getContext().closeExited(this, 1); + return 0; + } + }); + } + + @Override + protected void exitContext(LanguageContext ctx, ExitMode exitMode, int exitCode) { + ctx.getEnv().getContext().closeExited(DUMMY_NODE, 5); + } + + }); + try { + context.eval(ProxyLanguage.ID, ""); + } catch (PolyglotException pe) { + if (!pe.isExit() || pe.getExitStatus() != 1) { + throw pe; + } + } + } +} diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseOrCancelTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseOrCancelTest.java deleted file mode 100644 index cd90fa70e562..000000000000 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseOrCancelTest.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * The Universal Permissive License (UPL), Version 1.0 - * - * Subject to the condition set forth below, permission is hereby granted to any - * person obtaining a copy of this software, associated documentation and/or - * data (collectively the "Software"), free of charge and under any and all - * copyright rights in the Software, and any and all patent rights owned or - * freely licensable by each licensor hereunder covering either (i) the - * unmodified Software as contributed to or provided by such licensor, or (ii) - * the Larger Works (as defined below), to deal in both - * - * (a) the Software, and - * - * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if - * one is included with the Software each a "Larger Work" to which the Software - * is contributed by such licensors), - * - * without restriction, including without limitation the rights to copy, create - * derivative works of, display, perform, and distribute the Software and make, - * use, sell, offer for sale, import, export, have made, and have sold the - * Software and the Larger Work(s), and to sublicense the foregoing rights on - * either these or other terms. - * - * This license is subject to the following condition: - * - * The above copyright notice and either this complete permission notice or at a - * minimum a reference to the UPL must be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.oracle.truffle.api.instrumentation.test; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.time.Duration; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicReference; - -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Engine; -import org.graalvm.polyglot.Source; -import org.junit.After; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; - -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleContext; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.instrumentation.ContextsListener; -import com.oracle.truffle.api.instrumentation.EventContext; -import com.oracle.truffle.api.instrumentation.ExecutionEventListener; -import com.oracle.truffle.api.instrumentation.SourceSectionFilter; -import com.oracle.truffle.api.instrumentation.TruffleInstrument; -import com.oracle.truffle.api.nodes.LanguageInfo; -import com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest; -import com.oracle.truffle.api.test.polyglot.ProxyLanguage; - -public class ContextInterruptCloseOrCancelTest extends AbstractPolyglotTest { - private void runOnContextClose(TruffleContext triggerCtx, Runnable r) { - instrumentEnv.getInstrumenter().attachContextsListener(new ContextsListener() { - @Override - public void onContextCreated(TruffleContext ctx) { - - } - - @Override - public void onLanguageContextCreated(TruffleContext ctx, LanguageInfo lang) { - - } - - @Override - public void onLanguageContextInitialized(TruffleContext ctx, LanguageInfo lang) { - - } - - @Override - public void onLanguageContextFinalized(TruffleContext ctx, LanguageInfo lang) { - - } - - @Override - public void onLanguageContextDisposed(TruffleContext ctx, LanguageInfo lang) { - - } - - @Override - public void onContextClosed(TruffleContext ctx) { - if (ctx == triggerCtx) { - r.run(); - } - } - }, false); - } - - @Rule public TestName testNameRule = new TestName(); - - @After - public void checkInterrupted() { - Assert.assertFalse("Interrupted flag was left set by test: " + testNameRule.getMethodName(), Thread.interrupted()); - } - - @Test - public void testInterruptPolyglotThreadWhileClosing() throws ExecutionException, InterruptedException, IOException { - enterContext = false; - setupEnv(Context.newBuilder().allowCreateThread(true), new ProxyLanguage() { - @Override - protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { - return true; - } - }); - ExecutorService executorService = Executors.newSingleThreadExecutor(); - try { - CountDownLatch interruptLatch = new CountDownLatch(1); - Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,CONSTANT(42),LOOP(infinity,STATEMENT)),SPAWN(foo))", "InfiniteLoop").build(); - attachListener(interruptLatch::countDown, instrumentEnv); - Future future = executorService.submit(() -> { - context.eval(source); - }); - interruptLatch.await(); - future.get(); - TruffleContext innerContext = languageEnv.newContextBuilder().build(); - AtomicReference> interruptFutureReference = new AtomicReference<>(); - runOnContextClose(innerContext, () -> { - /* - * When inner context is closed we know that the parent context is being closed. - * Parent context is entered in the current thread, so we must interrupt in a - * different thread. - */ - Future interruptFuture = executorService.submit(() -> { - try { - context.interrupt(Duration.ofSeconds(5)); - } catch (TimeoutException te) { - throw new AssertionError(te); - } - }); - interruptFutureReference.set(interruptFuture); - boolean interruptedExceptionSwallowed = false; - try { - /* - * The parent context is entered in the current thread, so the interrupt will - * try to interrupt it. Therefore, we have to ignore the InterruptedException in - * order for the close operation to be able to successfully continue. We cannot - * wait for the interrupt future here though, because it waits also for the - * current entered thread. - */ - interruptFuture.get(); - } catch (ExecutionException e) { - throw new AssertionError(e); - } catch (InterruptedException ie) { - interruptedExceptionSwallowed = true; - } - Assert.assertTrue(interruptedExceptionSwallowed); - Assert.assertFalse(interruptFuture.isDone()); - }); - context.close(); - assertContextState("CLOSED"); - Assert.assertNotNull(interruptFutureReference.get()); - interruptFutureReference.get().get(); - } finally { - executorService.shutdownNow(); - executorService.awaitTermination(100, TimeUnit.SECONDS); - } - } - - @Test - public void testCancelPolyglotThreadWhileClosing() throws ExecutionException, InterruptedException, IOException { - enterContext = false; - setupEnv(Context.newBuilder().allowCreateThread(true), new ProxyLanguage() { - @Override - protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { - return true; - } - }); - ExecutorService executorService = Executors.newSingleThreadExecutor(); - try { - CountDownLatch cancelLatch = new CountDownLatch(1); - Source source = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(DEFINE(foo,CONSTANT(42),LOOP(infinity,STATEMENT)),SPAWN(foo))", "InfiniteLoop").build(); - attachListener(cancelLatch::countDown, instrumentEnv); - Future future = executorService.submit(() -> { - context.eval(source); - }); - cancelLatch.await(); - future.get(); - TruffleContext innerContext = languageEnv.newContextBuilder().build(); - runOnContextClose(innerContext, () -> { - /* - * Cancel must work even when entered. - */ - context.close(true); - }); - context.close(); - assertContextState("CLOSED_CANCELLED"); - } finally { - executorService.shutdownNow(); - executorService.awaitTermination(100, TimeUnit.SECONDS); - } - } - - private void assertContextState(String expectedState) { - Object contextState; - try { - Field implField = context.getClass().getDeclaredField("receiver"); - implField.setAccessible(true); - Object contextImpl = implField.get(context); - Field stateField = contextImpl.getClass().getDeclaredField("state"); - stateField.setAccessible(true); - contextState = stateField.get(contextImpl); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); - } - Assert.assertEquals(expectedState, ((Enum) contextState).name()); - } - - private static void attachListener(Runnable runnable, TruffleInstrument.Env instrumentEnv) { - instrumentEnv.getInstrumenter().attachExecutionEventListener(SourceSectionFilter.newBuilder().tagIs(InstrumentationTestLanguage.ConstantTag.class).build(), new ExecutionEventListener() { - @Override - public void onEnter(EventContext c, VirtualFrame frame) { - executeSideEffect(); - } - - @CompilerDirectives.TruffleBoundary - void executeSideEffect() { - runnable.run(); - } - - @Override - public void onReturnValue(EventContext c, VirtualFrame frame, Object result) { - - } - - @Override - public void onReturnExceptional(EventContext c, VirtualFrame frame, Throwable exception) { - - } - }); - } - - static TruffleInstrument.Env getInstrumentEnv(Engine engine) { - return engine.getInstruments().get("InstrumentationUpdateInstrument").lookup(TruffleInstrument.Env.class); - } -} diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationTestLanguage.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationTestLanguage.java index a337f9457c59..80340aea7578 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationTestLanguage.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/InstrumentationTestLanguage.java @@ -61,6 +61,8 @@ import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; +import org.junit.Assert; + import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -72,6 +74,7 @@ import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleLanguage.Registration; +import com.oracle.truffle.api.TruffleSafepoint; import com.oracle.truffle.api.TruffleStackTraceElement; import com.oracle.truffle.api.dsl.Cached.Shared; import com.oracle.truffle.api.exception.AbstractTruffleException; @@ -215,7 +218,7 @@ static class ConstantTag extends Tag { public static final String[] TAG_NAMES = new String[]{"EXPRESSION", "DEFINE", "CONTEXT", "LOOP", "STATEMENT", "CALL", "RECURSIVE_CALL", "CALL_WITH", "BLOCK", "ROOT_BODY", "ROOT", "CONSTANT", "VARIABLE", "ARGUMENT", "READ_VAR", "PRINT", "ALLOCATION", "SLEEP", "SPAWN", "JOIN", "INVALIDATE", "INTERNAL", "INNER_FRAME", "MATERIALIZE_CHILD_EXPRESSION", "MATERIALIZE_CHILD_STMT_AND_EXPR", "MATERIALIZE_CHILD_STMT_AND_EXPR_NC", "MATERIALIZE_CHILD_STMT_AND_EXPR_SEPARATELY", "MATERIALIZE_CHILD_STATEMENT", "BLOCK_NO_SOURCE_SECTION", - "TRY", "CATCH", "THROW", "UNEXPECTED_RESULT", "MULTIPLE"}; + "TRY", "CATCH", "THROW", "UNEXPECTED_RESULT", "MULTIPLE", "EXIT"}; public InstrumentationTestLanguage() { } @@ -381,7 +384,7 @@ private BaseNode statement() { int numberOfIdents = 0; if (tag.equals("DEFINE") || tag.equals("ARGUMENT") || tag.equals("READ_VAR") || tag.equals("CALL") || tag.equals("LOOP") || tag.equals("CONSTANT") || tag.equals("UNEXPECTED_RESULT") || - tag.equals("SLEEP") || tag.equals("SPAWN") | tag.equals("CATCH")) { + tag.equals("SLEEP") || tag.equals("SPAWN") || tag.equals("CATCH") || tag.equals("EXIT")) { numberOfIdents = 1; } else if (tag.equals("VARIABLE") || tag.equals("RECURSIVE_CALL") || tag.equals("CALL_WITH") || tag.equals("PRINT") || tag.equals("THROW")) { numberOfIdents = 2; @@ -550,6 +553,8 @@ private BaseNode createNode(String tag, String[] idents, SourceSection sourceSec return new UnexpectedResultNode(idents[0]); case "MULTIPLE": return new MultipleNode(childArray, multipleTags); + case "EXIT": + return new ExitNode(idents[0]); default: throw new AssertionError(); } @@ -1513,6 +1518,12 @@ public Object execute(VirtualFrame frame) { returnValue = child.execute(frame); } } + /* + * Normally we would go through call target here which guarantees poll at the end. + * This language doesn't use call target here, for simplicity, so we need to poll + * manually. + */ + TruffleSafepoint.pollHere(this); } finally { inner.leave(this, prev); inner.close(); @@ -1561,6 +1572,31 @@ protected BaseNode copyUninitialized(Set> materializedTags) } } + static class ExitNode extends InstrumentedNode { + private final int exitCode; + + ExitNode(String exitCodeStr) { + this.exitCode = Integer.parseInt(exitCodeStr); + } + + @Override + public Object execute(VirtualFrame frame) { + throwExitException(); + return null; + } + + @TruffleBoundary + private void throwExitException() { + InstrumentContext context = InstrumentContext.get(this); + context.env.getContext().closeExited(this, exitCode); + } + + @Override + protected BaseNode copyUninitialized(Set> materializedTags) { + return new ExitNode(String.valueOf(exitCode)); + } + } + private static class SpawnNode extends InstrumentedNode { @Child private DirectCallNode callNode; @@ -1639,7 +1675,7 @@ private static Thread.UncaughtExceptionHandler getPolyglotThreadUncaughtExceptio return (t, e) -> { InteropLibrary interop = InteropLibrary.getUncached(); boolean interrupted; - boolean cancelled = false; + boolean cancelledOrExited = false; if (interop.isException(e)) { try { ExceptionType exceptionType = interop.getExceptionType(e); @@ -1649,9 +1685,9 @@ private static Thread.UncaughtExceptionHandler getPolyglotThreadUncaughtExceptio } } else { interrupted = e != null && e.getCause() instanceof InterruptedException; - cancelled = e instanceof ThreadDeath; + cancelledOrExited = e instanceof ThreadDeath; } - if (e != null && !interrupted && !cancelled) { + if (e != null && !interrupted && !cancelledOrExited) { Env currentEnv = context.env; try { e.printStackTrace(new PrintStream(currentEnv.err())); @@ -3219,6 +3255,15 @@ public String fileExtension() { protected void finalizeContext(InstrumentContext context) { joinSpawnedThreads(context, true); } + + @Override + protected void exitContext(InstrumentContext context, ExitMode exitMode, int exitCode) { + if (exitMode == ExitMode.HARD) { + CallTarget callTarget = context.env.parseInternal(Source.newBuilder(ID, "CONSTANT(42)", "ConstandFortyTwo").build()); + Object result = callTarget.call(); + Assert.assertEquals(42, result); + } + } } class InstrumentContext { diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ThreadsActivationListenerTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ThreadsActivationListenerTest.java index ccf3a6c7b7a8..2a67173d4f10 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ThreadsActivationListenerTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ThreadsActivationListenerTest.java @@ -85,6 +85,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { c0.enter(); TruffleContext ic0 = this.languageEnv.newContextBuilder().build(); + TruffleContext ic0CreatorHandle = ic0; Object prev = ic0.enter(null); // look language handle on the context it is not the same as // the creator handle. The creator handle can be closed. @@ -148,6 +149,8 @@ public void onLeaveThread(TruffleContext c) { assertList(entered, ic0, tc0, ic0); assertList(left, ic0, ic0, tc0); + + ic0CreatorHandle.close(); } @Test diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TruffleContextTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TruffleContextTest.java index d7c3ba496aa7..cf6307482db5 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TruffleContextTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/TruffleContextTest.java @@ -120,6 +120,7 @@ public void testCreate() { assertFalse(tc.isEntered()); assertFalse(tc.isClosed()); assertFalse(tc.isCancelling()); + assertFalse(tc.isExiting()); assertNotNull(tc.toString()); assertEquals(tc.getParent(), languageEnv.getContext()); @@ -130,6 +131,7 @@ public void testCreate() { assertFalse(tc.isEntered()); assertFalse(tc.isClosed()); + tc.close(); } @Test @@ -337,6 +339,78 @@ public void onReturnExceptional(EventContext ctx, VirtualFrame frame, Throwable } } + @Test + public void testExiting() throws ExecutionException, InterruptedException { + setupEnv(Context.newBuilder(), new ProxyLanguage() { + @Override + protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { + return true; + } + }); + + ExecutorService executorService = Executors.newFixedThreadPool(1); + try { + AtomicReference entered = new AtomicReference<>(); + CountDownLatch waitUntilExited = new CountDownLatch(1); + instrumentEnv.getInstrumenter().attachExecutionEventListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.StatementTag.class).build(), new ExecutionEventListener() { + @TruffleBoundary + @Override + public void onEnter(EventContext ctx, VirtualFrame frame) { + entered.set(instrumentEnv.getEnteredContext()); + } + + @Override + public void onReturnValue(EventContext ctx, VirtualFrame frame, Object result) { + + } + + @Override + public void onReturnExceptional(EventContext ctx, VirtualFrame frame, Throwable exception) { + + } + }); + Future future = executorService.submit(() -> { + context.enter(); + try { + context.eval(InstrumentationTestLanguage.ID, "ROOT(STATEMENT,EXIT(1))"); + fail(); + } catch (PolyglotException pe) { + if (!pe.isExit()) { + throw pe; + } + assertEquals(1, pe.getExitStatus()); + assertTrue(entered.get().isExiting()); + } finally { + context.leave(); + } + waitUntilExited.countDown(); + }); + + boolean othrerThreadExited = false; + while (!othrerThreadExited) { + try { + waitUntilExited.await(); + othrerThreadExited = true; + } catch (InterruptedException ie) { + } + } + /* + * Multi-threading is necessary, otherwise the context is closed while entered and we + * cannot check isExiting(). + */ + context.leave(); + TruffleContext tc = entered.get(); + tc.close(); + + future.get(); + assertFalse(tc.isExiting()); + assertTrue(tc.isClosed()); + } finally { + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); + } + } + @Test public void testCancellingUncaughtExceptionHandler() { ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -420,6 +494,8 @@ public void testContextHierarchy() { tc2.leave(null, prev2); tc1.leave(null, prev1); + tc2.close(); + tc1.close(); } @Test @@ -450,6 +526,7 @@ public void testInitializeCreatorContext() { } finally { innerContext.leave(null, prev); } + innerContext.close(); innerContext = languageEnv.newContextBuilder().initializeCreatorContext(true).build(); prev = innerContext.enter(null); @@ -458,6 +535,7 @@ public void testInitializeCreatorContext() { } finally { innerContext.leave(null, prev); } + innerContext.close(); } @Test @@ -484,6 +562,7 @@ public void testEvalInnerContextEvalErrors() { assertFails(() -> innerContext.evalInternal(null, com.oracle.truffle.api.source.Source.newBuilder("foobarbazz$_", "", "").build()), IllegalArgumentException.class, (e) -> { assertTrue(e.getMessage(), e.getMessage().startsWith("A language with id 'foobarbazz$_' is not installed. Installed languages are:")); }); + innerContext.close(); } @Test @@ -518,6 +597,7 @@ public void testEvalInnerContextError() throws InteropException { } assertEquals(3, innerException.executeCount); assertEquals(3, outerObject.executeCount); + innerContext.close(); } @SuppressWarnings("serial") @@ -574,6 +654,7 @@ public void testPublicEvalInnerContext() { com.oracle.truffle.api.source.Source internal = com.oracle.truffle.api.source.Source.newBuilder(LanguageSPIOrderTest.INTERNAL, "", "test").build(); assertFails(() -> innerContext.evalPublic(null, internal), IllegalArgumentException.class); + innerContext.close(); } @Test @@ -587,6 +668,7 @@ public void testEvalInnerContext() throws InteropException { // test that objects that cross the boundary are entered in the inner context EvalContextTestObject innerObject = new EvalContextTestObject(); EvalContextTestObject outerObject = new EvalContextTestObject(); + innerContext.close(); setupLanguageThatReturns(() -> innerObject); innerContext = languageEnv.newContextBuilder().build(); innerObject.expectedContext = innerContext; @@ -603,6 +685,7 @@ public void testEvalInnerContext() throws InteropException { assertEquals(2, innerObject.executeCount); assertEquals(2, outerObject.executeCount); + innerContext.close(); } @ExportLibrary(InteropLibrary.class) @@ -659,6 +742,7 @@ protected boolean areOptionsCompatible(OptionValues firstOptions, OptionValues n assertFalse(multiContextInitialized.get()); internalContext.evalInternal(null, com.oracle.truffle.api.source.Source.newBuilder(ProxyLanguage.ID, "", "").build()); assertTrue(multiContextInitialized.get()); + internalContext.close(); } @Test @@ -681,8 +765,9 @@ protected boolean areOptionsCompatible(OptionValues firstOptions, OptionValues n return true; } }); - languageEnv.newContextBuilder().initializeCreatorContext(true).build(); + TruffleContext ic = languageEnv.newContextBuilder().initializeCreatorContext(true).build(); assertTrue(multiContextInitialized.get()); + ic.close(); } private void setupLanguageThatReturns(Supplier supplier) { @@ -743,6 +828,7 @@ public void testLeaveAndEnterInnerContext() { } finally { tc.leave(null, prev); } + tc.close(); } private static Class getCancelExecutionClass() { diff --git a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ExceptionType.java b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ExceptionType.java index 09540c91cb5b..6148d37c8fa1 100644 --- a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ExceptionType.java +++ b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ExceptionType.java @@ -53,9 +53,18 @@ */ public enum ExceptionType { /** - * Indicates that the application was exited within the guest language program. To obtain the - * exit status use {@link InteropLibrary#getExceptionExitStatus(Object) getExceptionExitStatus}. - * + * Indicates that the application was soft-exited within the guest language program. To obtain + * the exit status use {@link InteropLibrary#getExceptionExitStatus(Object) + * getExceptionExitStatus}. See + * Context Exit + * for further information. + *

+ * If a language uses hard exits, it should not use soft exits, i.e. throw exceptions of this + * type on its own. + *

+ * If a language that does not use soft exits sees an exception of this type, it should re-throw + * it like other foreign exceptions, triggering finally blocks. + * * @see InteropLibrary#getExceptionExitStatus(Object) * @since 20.3 */ diff --git a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropLibrary.java b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropLibrary.java index 3eb3726b9421..784de11a146b 100644 --- a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropLibrary.java +++ b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropLibrary.java @@ -40,6 +40,28 @@ */ package com.oracle.truffle.api.interop; +import static com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere; +import static com.oracle.truffle.api.interop.AssertUtils.assertString; +import static com.oracle.truffle.api.interop.AssertUtils.preCondition; +import static com.oracle.truffle.api.interop.AssertUtils.validArguments; +import static com.oracle.truffle.api.interop.AssertUtils.validInteropArgument; +import static com.oracle.truffle.api.interop.AssertUtils.validInteropReturn; +import static com.oracle.truffle.api.interop.AssertUtils.validNonInteropArgument; +import static com.oracle.truffle.api.interop.AssertUtils.validProtocolArgument; +import static com.oracle.truffle.api.interop.AssertUtils.validProtocolReturn; +import static com.oracle.truffle.api.interop.AssertUtils.validScope; +import static com.oracle.truffle.api.interop.AssertUtils.violationInvariant; +import static com.oracle.truffle.api.interop.AssertUtils.violationPost; + +import java.nio.ByteOrder; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.zone.ZoneRules; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleLanguage; @@ -65,28 +87,6 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.utilities.TriState; -import java.nio.ByteOrder; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.zone.ZoneRules; - -import static com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere; -import static com.oracle.truffle.api.interop.AssertUtils.assertString; -import static com.oracle.truffle.api.interop.AssertUtils.preCondition; -import static com.oracle.truffle.api.interop.AssertUtils.validInteropArgument; -import static com.oracle.truffle.api.interop.AssertUtils.validProtocolArgument; -import static com.oracle.truffle.api.interop.AssertUtils.validArguments; -import static com.oracle.truffle.api.interop.AssertUtils.validNonInteropArgument; -import static com.oracle.truffle.api.interop.AssertUtils.validInteropReturn; -import static com.oracle.truffle.api.interop.AssertUtils.validProtocolReturn; -import static com.oracle.truffle.api.interop.AssertUtils.validScope; -import static com.oracle.truffle.api.interop.AssertUtils.violationInvariant; -import static com.oracle.truffle.api.interop.AssertUtils.violationPost; - /** * Represents the library that specifies the interoperability message protocol between Truffle * languages, tools and embedders. Every method represents one message specified by the protocol. In @@ -1852,7 +1852,6 @@ public Duration asDuration(Object receiver) throws UnsupportedMessageException { * @since 19.3 */ @Abstract(ifExported = {"throwException"}) - @SuppressWarnings("deprecation") public boolean isException(Object receiver) { // A workaround for missing inheritance feature for default exports. return InteropAccessor.EXCEPTION.isException(receiver) || @@ -1936,9 +1935,11 @@ public boolean isExceptionIncompleteSource(Object receiver) throws UnsupportedMe /** * Returns exception exit status of the receiver. Throws {@code UnsupportedMessageException} * when the receiver is not an {@link #isException(Object) exception} of the - * {@link ExceptionType#EXIT exit type}. A return value zero indicates that the execution of the - * application was successful, a non-zero value that it failed. The individual interpretation of - * non-zero values depends on the application. + * {@link ExceptionType#EXIT exit type}. See + * Context Exit + * for further information. A return value zero indicates that the execution of the application + * was successful, a non-zero value that it failed. The individual interpretation of non-zero + * values depends on the application. * * @see #isException(Object) * @see #getExceptionType(Object) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleSafepointTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleSafepointTest.java index d61359d39964..dec719e438de 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleSafepointTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleSafepointTest.java @@ -284,6 +284,7 @@ protected void perform(Access access) { @Test public void testNullArgs() { try (TestSetup setup = setupSafepointLoop(1, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { @@ -299,6 +300,7 @@ protected void perform(Access access) { @Test public void testSynchronousRecursiveError() throws InterruptedException, AssertionError, ExecutionException { try (TestSetup setup = setupSafepointLoop(1, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { @@ -335,6 +337,7 @@ protected void perform(Access inner) { public void testSynchronous() { forEachConfig((threads, events) -> { TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; }); @@ -383,6 +386,7 @@ public void testSynchronous() { public void testAsynchronous() { forEachConfig((threads, events) -> { try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { @@ -526,6 +530,7 @@ private static boolean isStopped(AtomicBoolean stopped) { public void testStackTrace() { forEachConfig((threads, events) -> { try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { @@ -563,6 +568,14 @@ protected void perform(Access access) { }); } + @TruffleBoundary + private static void sleepNanosBoundary(int nanos) { + try { + Thread.sleep(0, nanos); + } catch (InterruptedException ie) { + } + } + @Test public void testException() { forEachConfig((threads, events) -> { @@ -570,6 +583,7 @@ public void testException() { AtomicReference latchRef = new AtomicReference<>(null); List exceptions = Collections.synchronizedList(new ArrayList<>()); try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; }, (e) -> { @@ -1018,6 +1032,7 @@ public void testContextCancellation() { forEachConfig((threads, events) -> { List exceptions = Collections.synchronizedList(new ArrayList<>()); try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; }, new Consumer() { @@ -1070,6 +1085,7 @@ protected void perform(Access innerAccess) { public void testEventCancellation() { forEachConfig((threads, events) -> { try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { @@ -1139,6 +1155,7 @@ public void testSafepointALot() { @Test public void testNonSideEffectInvalidErrorThrown() throws InterruptedException { try (TestSetup setup = setupSafepointLoop(1, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { @@ -1319,6 +1336,7 @@ static class GuestException extends AbstractTruffleException { public void testSubmitAsInstrument() { forEachConfig((threads, events) -> { try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { @@ -1337,6 +1355,7 @@ public void testSubmitAsInstrument() { public void testSubmitRecurringWaitWithCancel() { forEachConfig((threads, events) -> { try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { @@ -1361,6 +1380,7 @@ public void testSubmitRecurringWaitWithCancel() { public void testSubmitRecurringWait() { forEachConfig((threads, events) -> { try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { @@ -1385,6 +1405,7 @@ public void testSubmitRecurringWait() { public void testSubmitRecurringCancel() { forEachConfig((threads, events) -> { try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> { + sleepNanosBoundary(50000); TruffleSafepoint.poll(node); return false; })) { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ChildContextTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ChildContextTest.java index 9c8edaca978b..3c76a71e1bd6 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ChildContextTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ChildContextTest.java @@ -44,6 +44,7 @@ import org.junit.Test; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; @@ -95,7 +96,8 @@ protected LanguageContext createContext(Env env) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { - REFERENCE.get(null).env.newContextBuilder().build(); + TruffleContext tc = REFERENCE.get(null).env.newContextBuilder().build(); + tc.close(); return RootNode.createConstantNode("foo").getCallTarget(); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolicyTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolicyTest.java index 755085e63133..13e74f225b5a 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolicyTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolicyTest.java @@ -705,7 +705,7 @@ Object execute(Object[] args, @TruffleBoundary private void doAssertions() { assertSame(expectedLanguage, expectedLanguage.getLanguageReference().get(null)); - assertSame(expectedEnvironment, expectedLanguage.getContextReference0().get(null)); + assertSame(expectedEnvironment, expectedLanguage.getContextReference0().get(null).env); } @TruffleBoundary @@ -742,10 +742,15 @@ protected LanguageRootNode(BaseLanguage language, boolean innerContext) { @Override public Object execute(VirtualFrame frame) { - Env env = language.getContextReference0().get(this); + LangContext langContext = language.getContextReference0().get(this); TruffleContext context = null; if (innerContext) { - context = env.newContextBuilder().build(); + if (langContext.innerContext == null) { + context = langContext.env.newContextBuilder().build(); + langContext.innerContext = context; + } else { + context = langContext.innerContext; + } } Object prev = null; if (context != null) { @@ -755,7 +760,7 @@ public Object execute(VirtualFrame frame) { SharedObject obj = new SharedObject( context, language.getLanguageReference().get(null), - language.getContextReference0().get(null)); + language.getContextReference0().get(null).env); return obj; } finally { if (context != null) { @@ -766,11 +771,20 @@ public Object execute(VirtualFrame frame) { } } - abstract static class BaseLanguage extends TruffleLanguage { + static class LangContext { + final Env env; + TruffleContext innerContext; + + LangContext(Env env) { + this.env = env; + } + } + + abstract static class BaseLanguage extends TruffleLanguage { abstract LanguageReference getLanguageReference(); - abstract ContextReference getContextReference0(); + abstract ContextReference getContextReference0(); } @Registration(id = EXCLUSIVE0, name = EXCLUSIVE0, contextPolicy = ContextPolicy.EXCLUSIVE) @@ -796,18 +810,25 @@ protected CallTarget parse(ParsingRequest request) throws Exception { } @Override - protected Env createContext(Env env) { + protected LangContext createContext(Env env) { contextCreate.add(this); - return env; + return new LangContext(env); + } + + @Override + protected void finalizeContext(LangContext context) { + if (context.innerContext != null) { + context.innerContext.close(); + } } @Override - protected void disposeContext(Env context) { + protected void disposeContext(LangContext context) { contextDispose.add(this); } @Override - ContextReference getContextReference0() { + ContextReference getContextReference0() { return CONTEXT_REF; } @@ -816,7 +837,7 @@ LanguageReference getLanguageReference() { return REFERENCE; } - static final ContextReference CONTEXT_REF = ContextReference.create(ExclusiveLanguage0.class); + static final ContextReference CONTEXT_REF = ContextReference.create(ExclusiveLanguage0.class); static final LanguageReference REFERENCE = LanguageReference.create(ExclusiveLanguage0.class); } @@ -837,7 +858,7 @@ protected OptionDescriptors getOptionDescriptors() { } @Override - ContextReference getContextReference0() { + ContextReference getContextReference0() { return CONTEXT_REF; } @@ -846,7 +867,7 @@ LanguageReference getLanguageReference() { return REFERENCE; } - static final ContextReference CONTEXT_REF = ContextReference.create(ExclusiveLanguage1.class); + static final ContextReference CONTEXT_REF = ContextReference.create(ExclusiveLanguage1.class); static final LanguageReference REFERENCE = LanguageReference.create(ExclusiveLanguage1.class); } @@ -866,7 +887,7 @@ protected OptionDescriptors getOptionDescriptors() { } @Override - ContextReference getContextReference0() { + ContextReference getContextReference0() { return CONTEXT_REF; } @@ -875,7 +896,7 @@ LanguageReference getLanguageReference() { return REFERENCE; } - static final ContextReference CONTEXT_REF = ContextReference.create(ReuseLanguage0.class); + static final ContextReference CONTEXT_REF = ContextReference.create(ReuseLanguage0.class); static final LanguageReference REFERENCE = LanguageReference.create(ReuseLanguage0.class); } @@ -895,7 +916,7 @@ protected OptionDescriptors getOptionDescriptors() { } @Override - ContextReference getContextReference0() { + ContextReference getContextReference0() { return CONTEXT_REF; } @@ -904,7 +925,7 @@ LanguageReference getLanguageReference() { return REFERENCE; } - static final ContextReference CONTEXT_REF = ContextReference.create(ReuseLanguage1.class); + static final ContextReference CONTEXT_REF = ContextReference.create(ReuseLanguage1.class); static final LanguageReference REFERENCE = LanguageReference.create(ReuseLanguage1.class); } @@ -924,7 +945,7 @@ protected OptionDescriptors getOptionDescriptors() { } @Override - ContextReference getContextReference0() { + ContextReference getContextReference0() { return CONTEXT_REF; } @@ -933,7 +954,7 @@ LanguageReference getLanguageReference() { return REFERENCE; } - static final ContextReference CONTEXT_REF = ContextReference.create(SharedLanguage0.class); + static final ContextReference CONTEXT_REF = ContextReference.create(SharedLanguage0.class); static final LanguageReference REFERENCE = LanguageReference.create(SharedLanguage0.class); } @@ -953,7 +974,7 @@ protected OptionDescriptors getOptionDescriptors() { } @Override - ContextReference getContextReference0() { + ContextReference getContextReference0() { return CONTEXT_REF; } @@ -962,7 +983,7 @@ LanguageReference getLanguageReference() { return REFERENCE; } - static final ContextReference CONTEXT_REF = ContextReference.create(SharedLanguage1.class); + static final ContextReference CONTEXT_REF = ContextReference.create(SharedLanguage1.class); static final LanguageReference REFERENCE = LanguageReference.create(SharedLanguage1.class); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageFinalizationFailureTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageFinalizationFailureTest.java index 63519bfe3fe0..f4cb97ff8c90 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageFinalizationFailureTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageFinalizationFailureTest.java @@ -122,7 +122,8 @@ protected void disposeContext(LanguageContext languageContext) { }); context.close(true); Assert.assertTrue(disposeCalled.get()); - Assert.assertTrue(outStream.toString().contains("Exception was thrown while finalizing a polyglot context that is being cancelled. Such exceptions are expected during cancelling.")); + Assert.assertTrue(outStream.toString().contains( + "Exception was thrown while finalizing a polyglot context that is being cancelled or exited. Such exceptions are expected during cancelling or exiting.")); } @Test diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ProxyLanguage.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ProxyLanguage.java index e9c0ec48363e..808515e9dd08 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ProxyLanguage.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ProxyLanguage.java @@ -179,6 +179,15 @@ protected void finalizeContext(LanguageContext context) { } } + @Override + protected void exitContext(LanguageContext context, ExitMode exitMode, int exitCode) { + if (wrapper) { + delegate.exitContext(context, exitMode, exitCode); + } else { + super.exitContext(context, exitMode, exitCode); + } + } + @Override protected void disposeContext(LanguageContext context) { if (wrapper) { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEngineDispatch.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEngineDispatch.java index f69d045ab454..5b8c4855e1d4 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEngineDispatch.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEngineDispatch.java @@ -81,14 +81,14 @@ public Context createContext(Object receiver, OutputStream out, OutputStream err boolean allowNativeAccess, boolean allowCreateThread, boolean allowHostIO, boolean allowHostClassLoading, boolean allowExperimentalOptions, Predicate classFilter, Map options, Map arguments, String[] onlyLanguages, FileSystem fileSystem, Object logHandlerOrStream, boolean allowCreateProcess, ProcessHandler processHandler, EnvironmentAccess environmentAccess, Map environment, ZoneId zone, Object limitsImpl, String currentWorkingDirectory, - ClassLoader hostClassLoader, boolean allowValueSharing) { + ClassLoader hostClassLoader, boolean allowValueSharing, boolean useSystemExit) { HostEngine engine = (HostEngine) receiver; Engine localEngine = engine.localEngine; AbstractEngineDispatch dispatch = api.getDispatch(localEngine); Object engineReceiver = api.getReceiver(localEngine); Context localContext = dispatch.createContext(engineReceiver, out, err, in, allowHostAccess, hostAccess, polyglotAccess, allowNativeAccess, allowCreateThread, allowHostIO, allowHostClassLoading, allowExperimentalOptions, classFilter, options, arguments, onlyLanguages, fileSystem, logHandlerOrStream, allowCreateProcess, processHandler, - environmentAccess, environment, zone, limitsImpl, currentWorkingDirectory, hostClassLoader, true); + environmentAccess, environment, zone, limitsImpl, currentWorkingDirectory, hostClassLoader, true, useSystemExit); long guestContextId = hostToGuest.remoteCreateContext(engine.remoteEngine); HostContext context = new HostContext(engine, guestContextId, localContext); hostToGuest.registerHostContext(guestContextId, context); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEntryPoint.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEntryPoint.java index d1c203af96d1..04ba211fbc15 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEntryPoint.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEntryPoint.java @@ -123,7 +123,7 @@ public long remoteCreateContext(long engineId) { false, false, false, false, false, null, new HashMap<>(), new HashMap<>(), new String[0], null, null, false, null, EnvironmentAccess.NONE, - null, null, null, null, null, true); + null, null, null, null, null, true, false); return guestToHost(remoteContext); } diff --git a/truffle/src/com.oracle.truffle.api/snapshot.sigtest b/truffle/src/com.oracle.truffle.api/snapshot.sigtest index 624aa717e19d..239c38dffb90 100644 --- a/truffle/src/com.oracle.truffle.api/snapshot.sigtest +++ b/truffle/src/com.oracle.truffle.api/snapshot.sigtest @@ -236,6 +236,7 @@ meth public boolean isActive() meth public boolean isCancelling() meth public boolean isClosed() meth public boolean isEntered() +meth public boolean isExiting() meth public com.oracle.truffle.api.TruffleContext getParent() meth public int hashCode() meth public java.lang.Object enter() @@ -246,6 +247,7 @@ meth public java.lang.Object evalPublic(com.oracle.truffle.api.nodes.Node,com.or meth public java.util.concurrent.Future pause() meth public void close() meth public void closeCancelled(com.oracle.truffle.api.nodes.Node,java.lang.String) +meth public void closeExited(com.oracle.truffle.api.nodes.Node,int) meth public void closeResourceExhausted(com.oracle.truffle.api.nodes.Node,java.lang.String) meth public void leave(com.oracle.truffle.api.nodes.Node,java.lang.Object) meth public void leave(java.lang.Object) @@ -402,6 +404,7 @@ innr public abstract interface static Provider innr public abstract static ContextReference innr public abstract static LanguageReference innr public final static !enum ContextPolicy +innr public final static !enum ExitMode innr public final static Env innr public final static InlineParsingRequest innr public final static ParsingRequest @@ -445,6 +448,7 @@ meth protected static <%0 extends java.lang.Object, %1 extends com.oracle.truffl anno 0 java.lang.Deprecated() meth protected void disposeContext({com.oracle.truffle.api.TruffleLanguage%0}) meth protected void disposeThread({com.oracle.truffle.api.TruffleLanguage%0},java.lang.Thread) +meth protected void exitContext({com.oracle.truffle.api.TruffleLanguage%0},com.oracle.truffle.api.TruffleLanguage$ExitMode,int) meth protected void finalizeContext({com.oracle.truffle.api.TruffleLanguage%0}) meth protected void initializeContext({com.oracle.truffle.api.TruffleLanguage%0}) throws java.lang.Exception meth protected void initializeMultiThreading({com.oracle.truffle.api.TruffleLanguage%0}) @@ -559,6 +563,14 @@ supr java.lang.Object hfds UNSET_CONTEXT,applicationArguments,config,context,contextUnchangedAssumption,err,in,initialized,initializedUnchangedAssumption,languageServicesCollector,options,out,polyglotLanguageContext,services,spi,valid hcls TruffleFileFactory +CLSS public final static !enum com.oracle.truffle.api.TruffleLanguage$ExitMode + outer com.oracle.truffle.api.TruffleLanguage +fld public final static com.oracle.truffle.api.TruffleLanguage$ExitMode HARD +fld public final static com.oracle.truffle.api.TruffleLanguage$ExitMode NATURAL +meth public static com.oracle.truffle.api.TruffleLanguage$ExitMode valueOf(java.lang.String) +meth public static com.oracle.truffle.api.TruffleLanguage$ExitMode[] values() +supr java.lang.Enum + CLSS public final static com.oracle.truffle.api.TruffleLanguage$InlineParsingRequest outer com.oracle.truffle.api.TruffleLanguage meth public com.oracle.truffle.api.frame.MaterializedFrame getFrame() diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/LanguageAccessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/LanguageAccessor.java index ec39ae736bb5..1f482a54b138 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/LanguageAccessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/LanguageAccessor.java @@ -347,6 +347,11 @@ public void finalizeContext(TruffleLanguage.Env env) { env.getSpi().finalizeContext(env.context); } + @Override + public void exitContext(Env env, TruffleLanguage.ExitMode exitMode, int exitCode) { + env.getSpi().exitContext(env.context, exitMode, exitCode); + } + @Override public void disposeThread(TruffleLanguage.Env env, Thread current) { env.getSpi().disposeThread(env.context, current); diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleContext.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleContext.java index 2866797340f2..5141aa978475 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleContext.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleContext.java @@ -297,7 +297,8 @@ public boolean isActive() { /** * Returns true if the context was closed else false. A context may be - * closed if {@link #close()} or {@link #closeCancelled(Node, String)} was called previously. + * closed if {@link #close()}, {@link #closeCancelled(Node, String)}, or + * {@link #closeExited(Node, int)} was called previously. * * @since 20.3 */ @@ -326,6 +327,22 @@ public boolean isCancelling() { } } + /** + * Returns true if the context is being hard-exited else false. A + * context may be in the process of exit if {@link #closeExited(Node, int)} was called + * previously. + * + * @since 22.0 + */ + @TruffleBoundary + public boolean isExiting() { + try { + return LanguageAccessor.engineAccess().isContextExiting(polyglotContext); + } catch (Throwable t) { + throw Env.engineToLanguageException(t); + } + } + /** * Pause execution on all threads for this context. This call does not wait for the threads to * be actually paused. Instead, a future is returned that can be used to wait for the execution @@ -494,18 +511,25 @@ public void close() { /** * Force closes the context as cancelled and stops all the execution on all active threads using - * a {@link ThreadDeath} exception. If this context is not currently {@link #isEntered() - * entered} on the current thread then this method waits until the close operation is complete - * and {@link #isClosed()} returns true, else it throws the cancelled exception - * upon its completion of this method. If an attempt to close a context was successful then - * consecutive calls to close have no effect. + * a special {@link ThreadDeath} cancel exception. If this context is not currently + * {@link #isEntered() entered} on the current thread then this method waits until the close + * operation is complete and {@link #isClosed()} returns true, else it throws the + * cancelled exception upon its completion of this method. If an attempt to close a context was + * successful then consecutive calls to close have no effect. + *

+ * The throwing of the special {@link ThreadDeath} cancel exception also applies to any guest + * code run during {@link TruffleLanguage#finalizeContext(Object)} which means that + * {@link TruffleLanguage#finalizeContext(Object)} cannot run guest code during the cancel + * operation. *

* If forced and this context currently {@link #isEntered() entered} on the current thread and * no other context is entered on the current thread then this method directly throws a * {@link ThreadDeath} error instead of completing to indicate that the current thread should be * stopped. The thrown {@link ThreadDeath} must not be caught by the guest language and freely - * propagated to the guest application to cancel the execution on the current thread. If a - * context is {@link #isActive() active} on the current thread, but not {@link #isEntered() + * propagated to the guest application to cancel the execution on the current thread. Please + * note that this means that the guest language's finally blocks must not be executed. + *

+ * If a context is {@link #isActive() active} on the current thread, but not {@link #isEntered() * entered}, then an {@link IllegalStateException} is thrown, as parent contexts that are active * on the current thread cannot be cancelled. * @@ -534,6 +558,60 @@ public void closeCancelled(Node closeLocation, String message) { } } + /** + * Initiates force close of the context as exited - + * {@link com.oracle.truffle.api.TruffleLanguage.ExitMode#HARD hard exit}. Requires the context + * to be entered on the current thread. Languages are first notified by calling + * {@link TruffleLanguage#exitContext(Object, TruffleLanguage.ExitMode, int)} and then the + * closing of the context is initiated. Execution on all active threads including the current + * thread is stopped by throwing a special {@link ThreadDeath} exit exception. This method does + * not wait for the execution on other threads to be stopped, it throws the {@link ThreadDeath} + * exception as soon as possible. To exit threads reliably, guest languages need to ensure that + * the {@link ThreadDeath} is always immediately rethrown and guest language exception handlers + * and finally blocks are not run. + *

+ * The throwing of the special {@link ThreadDeath} exit exception also applies to any guest code + * run during {@link TruffleLanguage#finalizeContext(Object)} which means that + * {@link TruffleLanguage#finalizeContext(Object)} cannot run guest code during hard exit. + *

+ * The exit code can be specified only once and the first call to this method also executes the + * {@link TruffleLanguage#exitContext(Object, TruffleLanguage.ExitMode, int) exit notifications} + * on the same thread. Further calls to this method will ensure that the following guest code on + * the calling thread is not executed by throwing the {@link ThreadDeath} exit exception, and + * the exit location is used as the stopping point of the thread, but the passed exit code is + * ignored and exit notifications are not run. + *

+ * In case the context is in one of the following states + *

    + *
  • the context is being closed + *
  • the context is already closed + *
  • the context threads are being unwound as a part of the cancelling process + *
  • the context threads are being unwound as a part of the hard exit process that comes after + * exit notifications + *
+ * then calling this method has no effect. + * + * @param exitLocation the node where the exit occurred. + * @param exitCode exitCode provided to the embedder and tools that observe the exit. + * @throws IllegalStateException if the context is not {@link #isEntered() entered} on the + * current thread. + * @see Context + * Exit + * + * @since 22.0 + */ + @TruffleBoundary + public void closeExited(Node exitLocation, int exitCode) { + if (!isEntered()) { + throw new IllegalStateException("Exit cannot be initiated for this context because it is not currently entered."); + } + try { + LanguageAccessor.engineAccess().exitContext(polyglotContext, exitLocation, exitCode); + } catch (Throwable t) { + throw Env.engineToLanguageException(t); + } + } + /** * Force closes the context due to resource exhaustion. This method is equivalent to calling * {@link #closeCancelled(Node, String) closeCancelled(location, message)} except in addition diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java index 5413cbe096c1..15926e8b9db0 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @@ -590,24 +590,43 @@ protected void initializeContext(C context) throws Exception { /** * Performs language context finalization actions that are necessary before language contexts * are {@link #disposeContext(Object) disposed}. However, in case the underlying polyglot - * context is being cancelled, {@link #disposeContext(Object)} is called even if + * context is being cancelled or hard-exited, {@link #disposeContext(Object)} is called even if * {@link #finalizeContext(Object)} throws a {@link TruffleException} or a {@link ThreadDeath} - * exception. All installed languages must remain usable after finalization. The finalization - * order can be influenced by specifying {@link Registration#dependentLanguages() language - * dependencies}. By default internal languages are finalized last, otherwise the default order - * is unspecified but deterministic. + * cancel or exit exception. *

- * While finalization code is run, other language contexts may become initialized. In such a + * For the hard exit a language is supposed to run its finalization actions that require running + * guest code in {@link #exitContext(Object, ExitMode, int)}, but please note that after + * {@link #exitContext(Object, ExitMode, int)} runs for a language, the language can still be + * invoked from {@link #exitContext(Object, ExitMode, int)} for a different language. Therefore, + * for instance, finalization for standard streams should both flush and set them to unbuffered + * mode at the end of exitContext, so that running guest code is not required to dispose the + * streams after that point. + *

+ * All installed languages must remain usable after finalization. The finalization order can be + * influenced by specifying {@link Registration#dependentLanguages() language dependencies}. By + * default internal languages are finalized last, otherwise, the default order is unspecified + * but deterministic. + *

+ * While the finalization code is run, other language contexts may become initialized. In such a * case, the finalization order may be non-deterministic and/or not respect the order specified * by language dependencies. *

- * All threads {@link Env#createThread(Runnable) created} by a language must be stopped and + * All threads {@link Env#createThread(Runnable) created} by the language must be stopped and * joined during finalizeContext. The languages are responsible for fulfilling that contract, - * otherwise an {@link AssertionError} is thrown. It's not safe to use the + * otherwise, an {@link AssertionError} is thrown. It's not safe to use the * {@link ExecutorService#awaitTermination(long, java.util.concurrent.TimeUnit)} to detect * Thread termination as the polyglot thread may be cancelled before executing the executor * worker. *

+ * During finalizeContext, all unclosed inner contexts {@link Env#newContextBuilder() created} + * by the language must be left on all threads where the contexts are still active. No active + * inner context is allowed after {@link #finalizeContext(Object)} returns, otherwise it is an + * internal error. + *

+ * Non-active inner contexts {@link Env#newContextBuilder() created} by the language that are + * still unclosed after {@link #finalizeContext(Object)} returns are automatically closed by + * Truffle. + *

* Typical implementation looks like: * * {@link TruffleLanguageSnippets.AsyncThreadLanguage#finalizeContext} @@ -620,6 +639,60 @@ protected void initializeContext(C context) throws Exception { protected void finalizeContext(C context) { } + /** + * Performs language exit event actions that are necessary before language contexts are + * {@link #finalizeContext(Object) finalized}. However, in case the underlying polyglot context + * is being cancelled, {@link #exitContext(Object, ExitMode, int) exit notifications} are not + * executed. Also, for {@link ExitMode#HARD hard exit}, {@link #finalizeContext(Object)} is + * called even if {@link #exitContext(Object, ExitMode, int)} throws a {@link TruffleException} + * or a {@link ThreadDeath} cancel or exit exception. All initialized language contexts must + * remain usable after exit notifications. In case a {@link TruffleException} or the + * {@link ThreadDeath} exit exception is thrown during a {@link ExitMode#HARD hard exit + * notification}, it is just logged and otherwise ignored and the notification process continues + * with the next language in order. In case the {@link ThreadDeath} cancel exception is thrown, + * it means the context is being cancelled in which case the exit notification process + * immediately stops. The exit notification order can be influenced by specifying + * {@link Registration#dependentLanguages() language dependencies} - The exit notification for + * language A that depends on language B is executed before the exit notification for language + * B. By default, notifications for internal languages are executed last, otherwise, the default + * order is unspecified but deterministic. + *

+ * During {@link ExitMode#HARD hard exit} notification, a language is supposed to run its + * finalization actions that require running guest code instead of running them in + * {@link #finalizeContext(Object)}. + *

+ * While the exit notification code is run, all languages remain fully functional. Also, other + * language contexts may become initialized. In such a case, the notification order may be + * non-deterministic and/or not respect the order specified by language dependencies. + *

+ * In case {@link TruffleContext#closeExited(Node, int)} is called during a + * {@link ExitMode#NATURAL natural exit notification}, it is ignored. In case it is called + * during a {@link ExitMode#HARD hard exit notification}, it just throws the special + * {@link ThreadDeath} exit exception, which is then just logged as described above. + *

+ * In case the underlying polyglot context is cancelled by e.g. + * {@link TruffleContext#closeCancelled(Node, String)} during exit notifications, guest code + * executed during exit notification is regularly cancelled, i.e., throws the + * {@link ThreadDeath} cancel exception, and the notification process does not continue as + * described above. + *

+ * In the case of {@link ExitMode#HARD hard exit}, if the current context has inner contexts + * that are still active, the execution for them will be stopped as well after all language exit + * notifications are executed for the outer context, but the exit notifications for the inner + * contexts are not automatically executed. The language needs to take appropriate action to + * make sure inner contexts are exited properly. + * + * @param context language context. + * @param exitMode mode of exit. + * @param exitCode exit code that was specified for exit. + * @see Context + * Exit + * + * @since 22.0 + */ + protected void exitContext(C context, ExitMode exitMode, int exitCode) { + } + /** * @since 19.0 * @deprecated in 1.0. Got renamed to {@link #initializeMultipleContexts()} instead. Instead of @@ -3381,8 +3454,8 @@ public Object createHostAdapterClassWithStaticOverrides(Class[] types, Object * logger must not be stored in a TruffleLanguage subclass. It is recommended to create all * language loggers in {@link TruffleLanguage#createContext(Env)}. * - * @param loggerName the the name of a {@link TruffleLogger}, if a {@code loggerName} is - * null or empty a root logger for language or instrument is returned + * @param loggerName the name of a {@link TruffleLogger}, if a {@code loggerName} is null or + * empty a root logger for language or instrument is returned * @return a {@link TruffleLogger} * @since 21.1 * @@ -3968,6 +4041,27 @@ public enum ContextPolicy { } + /** + * Mode of exit operation. + * + * @since 22.0 + * @see #exitContext(Object, ExitMode, int) + */ + public enum ExitMode { + /** + * Natural exit that occurs during normal context close. + * + * @since 22.0 + * + */ + NATURAL, + /** + * Hard exit triggered by {@link TruffleContext#closeExited(Node, int)}. + * + * @since 22.0 + */ + HARD + } } class TruffleLanguageSnippets { diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java index a71a3669320c..1f7bb14dfd15 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java @@ -376,6 +376,8 @@ public final void detachOutputConsumer(DispatchOutputStream dos, OutputStream ou public abstract void closeContext(Object polyglotContext, boolean force, Node closeLocation, boolean resourceExhaused, String resourceExhausedReason); + public abstract void exitContext(Object polyglotContext, Node exitLocation, int exitCode); + public abstract boolean isContextEntered(Object polyglotContext); public abstract boolean isContextActive(Object polyglotContext); @@ -569,6 +571,8 @@ public abstract Process createSubProcess(Object polyglotLanguageContext, List pause(Object polyglotContext); public abstract void resume(Object polyglotContext, Future pauseFuture); @@ -701,6 +705,8 @@ public abstract Env createEnv(Object polyglotLanguageContext, TruffleLanguage public abstract void finalizeContext(Env localEnv); + public abstract void exitContext(Env localEnv, TruffleLanguage.ExitMode exitMode, int exitCode); + public abstract Iterable findLegacyLocalScopes(Env env, Node node, Frame frame); public abstract Iterable findTopScopes(Env env); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java index ae3e4fe8bbb8..156a05f6ae48 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java @@ -1371,6 +1371,13 @@ public boolean isContextCancelling(Object polyglotContext) { return localContextState.isCancelling(); } + @Override + public boolean isContextExiting(Object polyglotContext) { + PolyglotContextImpl context = ((PolyglotContextImpl) polyglotContext); + PolyglotContextImpl.State contextState = context.state; + return contextState.isExiting(); + } + @Override public Future pause(Object polyglotContext) { PolyglotContextImpl context = ((PolyglotContextImpl) polyglotContext); @@ -1408,12 +1415,12 @@ public void closeContext(Object impl, boolean force, Node closeLocation, boolean } else { synchronized (context) { /* - * Closing the context on another thread done as a part of cancelling enters the - * context which could lead to the following IllegalStateException if the - * cancelling flag was not checked. + * Closing the context on another thread done as a part of cancelling or exiting + * enters the context which could lead to the following IllegalStateException if + * the cancelling flag was not checked. */ PolyglotContextImpl.State localContextState = context.state; - if (context.isActiveNotCancelled(false) && !localContextState.isCancelling()) { + if (context.isActiveNotCancelled(false) && !localContextState.isCancelling() && !localContextState.isExiting()) { /* * Polyglot threads are still allowed to run at this point. They are * required to be finished after finalizeContext. @@ -1512,6 +1519,12 @@ public boolean areStaticObjectSafetyChecksRelaxed(Object polyglotLanguageInstanc public String getStaticObjectStorageStrategy(Object polyglotLanguageInstance) { return ((PolyglotLanguageInstance) polyglotLanguageInstance).getEngine().getEngineOptionValues().get(PolyglotEngineOptions.StaticObjectStorageStrategy).name(); } + + @Override + public void exitContext(Object impl, Node exitLocation, int exitCode) { + PolyglotContextImpl context = ((PolyglotContextImpl) impl); + context.closeExited(exitLocation, exitCode); + } } abstract static class AbstractClassLoaderSupplier implements Supplier { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PauseThreadLocalAction.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PauseThreadLocalAction.java index d4e21876e0d8..2b809d562231 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PauseThreadLocalAction.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PauseThreadLocalAction.java @@ -72,7 +72,7 @@ protected void perform(ThreadLocalAction.Access access) { public void apply(Object waitObject) throws InterruptedException { synchronized (waitObject) { PolyglotContextImpl.State localContextState = context.state; - while (pause && !localContextState.isClosed() && !localContextState.isCancelling()) { + while (pause && !localContextState.isClosed() && !localContextState.isCancelling() && !localContextState.isExiting()) { waitObject.wait(); } } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextConfig.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextConfig.java index e8a2e5477c39..e3fa665fe9dd 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextConfig.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextConfig.java @@ -94,6 +94,7 @@ final class PolyglotContextConfig { private final List configuredInstruments; final HostAccess hostAccess; final boolean allowValueSharing; + final boolean useSystemExit; PolyglotContextConfig(PolyglotEngineImpl engine, OutputStream out, OutputStream err, InputStream in, boolean hostLookupAllowed, PolyglotAccess polyglotAccess, boolean nativeAccessAllowed, boolean createThreadAllowed, @@ -101,7 +102,7 @@ final class PolyglotContextConfig { Predicate classFilter, Map applicationArguments, EconomicSet allowedPublicLanguages, Map options, FileSystem publicFileSystem, FileSystem internalFileSystem, Handler logHandler, boolean createProcessAllowed, ProcessHandler processHandler, EnvironmentAccess environmentAccess, Map environment, - ZoneId timeZone, PolyglotLimits limits, ClassLoader hostClassLoader, HostAccess hostAccess, boolean allowValueSharing) { + ZoneId timeZone, PolyglotLimits limits, ClassLoader hostClassLoader, HostAccess hostAccess, boolean allowValueSharing, boolean useSystemExit) { assert out != null; assert err != null; assert in != null; @@ -165,6 +166,7 @@ final class PolyglotContextConfig { this.environment = environment == null ? Collections.emptyMap() : environment; this.hostAccess = hostAccess; this.hostClassLoader = hostClassLoader; + this.useSystemExit = useSystemExit; } public ZoneId getTimeZone() { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java index fbdde245fb52..f39903316827 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java @@ -78,7 +78,6 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; -import com.oracle.truffle.api.TruffleOptions; import org.graalvm.collections.EconomicSet; import org.graalvm.options.OptionValues; import org.graalvm.polyglot.Context; @@ -98,6 +97,7 @@ import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLogger; +import com.oracle.truffle.api.TruffleOptions; import com.oracle.truffle.api.TruffleSafepoint; import com.oracle.truffle.api.frame.FrameInstance; import com.oracle.truffle.api.interop.InteropLibrary; @@ -107,6 +107,7 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.polyglot.PolyglotEngineImpl.CancelExecution; import com.oracle.truffle.polyglot.PolyglotEngineImpl.StableLocalLocations; import com.oracle.truffle.polyglot.PolyglotLanguageContext.ValueMigrationException; @@ -137,18 +138,27 @@ final class PolyglotContextImpl implements com.oracle.truffle.polyglot.PolyglotI VALID_TRANSITIONS.put(State.DEFAULT, new State[]{ State.CLOSING, State.INTERRUPTING, - State.CANCELLING + State.PENDING_EXIT, + State.CANCELLING, + State.EXITING, // only for child contexts }); VALID_TRANSITIONS.put(State.CLOSING, new State[]{ State.CLOSED, State.CLOSING_INTERRUPTING, State.CLOSING_CANCELLING, + State.CLOSING_EXITING, // only for child contexts State.DEFAULT }); VALID_TRANSITIONS.put(State.INTERRUPTING, new State[]{ State.DEFAULT, State.CLOSING_INTERRUPTING, State.CANCELLING, + State.PENDING_EXIT, + State.EXITING, // only for child contexts + }); + VALID_TRANSITIONS.put(State.PENDING_EXIT, new State[]{ + State.EXITING, + State.CANCELLING }); VALID_TRANSITIONS.put(State.CANCELLING, new State[]{ State.CLOSING_CANCELLING @@ -157,16 +167,26 @@ final class PolyglotContextImpl implements com.oracle.truffle.polyglot.PolyglotI State.CLOSED, State.CLOSING, State.CLOSING_CANCELLING, + State.CLOSING_EXITING, // only for child contexts State.INTERRUPTING }); VALID_TRANSITIONS.put(State.CLOSING_CANCELLING, new State[]{ State.CLOSED_CANCELLED, State.CANCELLING }); + VALID_TRANSITIONS.put(State.CLOSING_EXITING, new State[]{ + State.CLOSED_EXITED, + State.EXITING + }); + VALID_TRANSITIONS.put(State.EXITING, new State[]{ + State.CLOSING_EXITING + }); VALID_TRANSITIONS.put(State.CLOSED, new State[0]); VALID_TRANSITIONS.put(State.CLOSED_CANCELLED, new State[0]); + VALID_TRANSITIONS.put(State.CLOSED_EXITED, + new State[0]); } enum State { @@ -178,9 +198,20 @@ enum State { * Interrupt operation has been started. Threads are being interrupted. */ INTERRUPTING, + /* + * Explicit exit was called in the DEFAULT or the INTERRUPTING state and exit notifications + * (see TruffleLanguage#exitContext) are about to be executed or are already executing. the + * PENDING_EXIT state overrides the INTERRUPTING state. + */ + PENDING_EXIT, + /* + * Exit operation has been initiated after exit notifications were executed in the + * PENDING_EXIT state. Threads are being stopped. + */ + EXITING, /* * Cancel operation has been initiated. Threads are being stopped. The CANCELLING state - * overrides the INTERRUPTING state. + * overrides the INTERRUPTING and the PENDING_EXIT state. */ CANCELLING, /* @@ -214,6 +245,12 @@ enum State { * case the state goes back to CANCELLING. */ CLOSING_CANCELLING, + /* + * Close operation has been initiated and at the same time exit operation is in progress. + * Transition to this state can be only from the EXITING state. Close operation that started + * in the CLOSING_EXITING state must finish successfully, otherwise it is an internal error. + */ + CLOSING_EXITING, /* * Closing operation in the CLOSING or the CLOSING_INTERRUPTING state has finished * successfully. @@ -222,7 +259,11 @@ enum State { /* * Closing operation in the CLOSING_CANCELLING state has finished successfully. */ - CLOSED_CANCELLED; + CLOSED_CANCELLED, + /* + * Closing operation in the CLOSING_EXITING state has finished successfully. + */ + CLOSED_EXITED; /* * The context is not usable and may be in an inconsistent state. @@ -230,9 +271,12 @@ enum State { boolean isInvalidOrClosed() { switch (this) { case CANCELLING: + case EXITING: case CLOSING_CANCELLING: + case CLOSING_EXITING: case CLOSED: case CLOSED_CANCELLED: + case CLOSED_EXITED: return true; default: return false; @@ -259,11 +303,22 @@ boolean isCancelling() { } } + boolean isExiting() { + switch (this) { + case EXITING: + case CLOSING_EXITING: + return true; + default: + return false; + } + } + boolean isClosing() { switch (this) { case CLOSING: case CLOSING_INTERRUPTING: case CLOSING_CANCELLING: + case CLOSING_EXITING: return true; default: return false; @@ -274,6 +329,7 @@ boolean isClosed() { switch (this) { case CLOSED: case CLOSED_CANCELLED: + case CLOSED_EXITED: return true; default: return false; @@ -283,6 +339,7 @@ boolean isClosed() { private boolean shouldCacheThreadInfo() { switch (this) { case DEFAULT: + case PENDING_EXIT: return true; default: return false; @@ -308,14 +365,24 @@ private boolean isTransitionAllowed(State fromState, State toState) { private boolean isAdditionalTransitionConditionSatisfied(State fromState, State toState) { assert Thread.holdsLock(this); - if (fromState.isClosing() && !toState.isClosing()) { - return closingThread == Thread.currentThread(); + if (fromState.isClosing() != toState.isClosing()) { + if (closingThread != Thread.currentThread()) { + return false; + } + } + if (!fromState.isExiting() && toState.isExiting() && fromState != State.PENDING_EXIT) { + if (parent == null) { + return false; + } } return true; } private ExecutorService cleanupExecutorService; private Future cleanupFuture; + volatile int exitCode; + private volatile String exitMessage; + volatile Thread closeExitedTriggerThread; private volatile String invalidMessage; volatile boolean invalidResourceLimit; volatile Thread closingThread; @@ -434,8 +501,12 @@ private PolyglotContextImpl() { this.state = State.INTERRUPTING; } else if (parent.state.isCancelling()) { this.state = State.CANCELLING; + } else if (parent.state.isExiting()) { + this.state = State.EXITING; } this.invalidMessage = this.parent.invalidMessage; + this.exitCode = this.parent.exitCode; + this.exitMessage = this.parent.exitMessage; this.contextBoundLoggers = this.parent.contextBoundLoggers; this.threadLocalActions = new PolyglotThreadLocalActions(this); if (!parent.config.logLevels.isEmpty()) { @@ -594,7 +665,7 @@ Object[] enterThreadChanged(boolean notifyEnter, boolean enterReverted, boolean PolyglotThreadInfo threadInfo = getCurrentThreadInfo(); if (enterReverted && threadInfo.getEnteredCount() == 0) { threadLocalActions.notifyThreadActivation(threadInfo, false); - if ((state.isCancelling() || state == State.CLOSED_CANCELLED) && !threadInfo.isActive()) { + if ((state.isCancelling() || state.isExiting() || state == State.CLOSED_CANCELLED || state == State.CLOSED_EXITED) && !threadInfo.isActive()) { notifyThreadClosed(threadInfo); } if (state.isInterrupting() && !threadInfo.isActive()) { @@ -829,7 +900,7 @@ PolyglotThreadInfo leaveThreadChanged(Object[] prev, boolean notifyLeft, boolean threadLocalActions.notifyThreadActivation(threadInfo, false); } - if ((state.isCancelling() || state == State.CLOSED_CANCELLED) && !info.isActive()) { + if ((state.isCancelling() || state.isExiting() || state == State.CLOSED_CANCELLED || state == State.CLOSED_EXITED) && !info.isActive()) { notifyThreadClosed(info); } @@ -1019,7 +1090,11 @@ void checkClosed() { /* * If invalidMessage == null, then invalid flag was set by close. */ - throw createCancelException(null); + if (exitMessage == null) { + throw createCancelException(null); + } else { + throw createExitException(null); + } } if (state.isClosed()) { throw PolyglotEngineException.illegalState("The Context is already closed."); @@ -1316,7 +1391,7 @@ void cancel(boolean resourceLimit, String message) { private void closeAndMaybeWait(boolean force, List> futures) { if (force) { - PolyglotEngineImpl.cancel(this, futures); + PolyglotEngineImpl.cancelOrExit(this, futures); } else { boolean closeCompleted = closeImpl(true); if (!closeCompleted) { @@ -1333,7 +1408,7 @@ private void closeAndMaybeWait(boolean force, List> futures) { private void setState(State targetState) { assert Thread.holdsLock(this); - assert isTransitionAllowed(state, targetState); + assert isTransitionAllowed(state, targetState) : "Transition from " + state.name() + " to " + targetState.name() + " not allowed!"; state = targetState; notifyAll(); } @@ -1342,7 +1417,7 @@ private List> setInterrupting() { assert Thread.holdsLock(this); State targetState; List> futures = new ArrayList<>(); - if (!state.isInterrupting() && !state.isInvalidOrClosed()) { + if (!state.isInterrupting() && !state.isInvalidOrClosed() && state != State.PENDING_EXIT) { switch (state) { case CLOSING: targetState = State.CLOSING_INTERRUPTING; @@ -1385,7 +1460,7 @@ private void finishInterruptForChildContexts() { } } - List> interruptChildContexts() { + private List> interruptChildContexts() { PolyglotContextImpl[] childContextsToInterrupt = null; List> futures; synchronized (this) { @@ -1449,7 +1524,7 @@ public boolean interrupt(Duration timeout) { * threads being stopped. If that happens before the timeout, the interrupt is * successful. */ - return PolyglotEngineImpl.cancelOrInterrupt(this, futures, startMillis, timeout); + return PolyglotEngineImpl.cancelOrExitOrInterrupt(this, futures, startMillis, timeout); } finally { try { if (childContextsToInterrupt != null) { @@ -1707,14 +1782,9 @@ private List> setCancelling(boolean resourceLimit, String message) } invalidResourceLimit = resourceLimit; invalidMessage = message; + exitMessage = null; setState(targetState); - PolyglotThreadInfo info = getCurrentThreadInfo(); - futures.add(threadLocalActions.submit(null, PolyglotEngineImpl.ENGINE_ID, new CancellationThreadLocalAction(), true)); - if (info != PolyglotThreadInfo.NULL) { - info.cancelled = true; - Thread.interrupted(); - } - setCachedThreadInfo(PolyglotThreadInfo.NULL); + submitCancellationThreadLocalAction(futures); childContextsToCancel = childContexts.toArray(new PolyglotContextImpl[childContexts.size()]); } } @@ -1726,8 +1796,57 @@ private List> setCancelling(boolean resourceLimit, String message) return futures; } + private void submitCancellationThreadLocalAction(List> futures) { + PolyglotThreadInfo info = getCurrentThreadInfo(); + futures.add(threadLocalActions.submit(null, PolyglotEngineImpl.ENGINE_ID, new CancellationThreadLocalAction(), true)); + if (info != PolyglotThreadInfo.NULL) { + info.cancelled = true; + Thread.interrupted(); + } + setCachedThreadInfo(PolyglotThreadInfo.NULL); + } + + private List> setExiting(PolyglotContextImpl triggeringParent, String message) { + PolyglotContextImpl[] childContextsToCancel = null; + List> futures = new ArrayList<>(); + synchronized (this) { + if (!state.isInvalidOrClosed()) { + assert message != null; + State targetState; + if (state.isClosing()) { + targetState = State.CLOSING_EXITING; + } else { + targetState = State.EXITING; + } + invalidMessage = message; + if (triggeringParent != null) { + /* + * triggeringParent is not null (and equal to parent) if the exit was initiated + * by some ancestor of this context (not necessarily the parent) and not this + * context directly. This means that the triggeringParent can be null even if + * parent is not null. + */ + exitMessage = triggeringParent.exitMessage; + exitCode = triggeringParent.exitCode; + } + setState(targetState); + if (!config.useSystemExit) { + submitCancellationThreadLocalAction(futures); + } + childContextsToCancel = childContexts.toArray(new PolyglotContextImpl[childContexts.size()]); + } + } + if (childContextsToCancel != null) { + for (PolyglotContextImpl childCtx : childContextsToCancel) { + futures.addAll(childCtx.setExiting(this, message)); + } + } + return futures; + } + private void setClosingState() { assert Thread.holdsLock(this); + setCachedThreadInfo(PolyglotThreadInfo.NULL); closingThread = Thread.currentThread(); closingLock.lock(); State targetState; @@ -1738,6 +1857,9 @@ private void setClosingState() { case INTERRUPTING: targetState = State.CLOSING_INTERRUPTING; break; + case EXITING: + targetState = State.CLOSING_EXITING; + break; default: targetState = State.CLOSING; break; @@ -1753,6 +1875,9 @@ private void setClosedState() { case CLOSING_CANCELLING: targetState = State.CLOSED_CANCELLED; break; + case CLOSING_EXITING: + targetState = State.CLOSED_EXITED; + break; case CLOSING_INTERRUPTING: case CLOSING: targetState = State.CLOSED; @@ -1776,6 +1901,9 @@ private void restoreFromClosingState(boolean cancelOperation) { case CLOSING_CANCELLING: targetState = State.CANCELLING; break; + case CLOSING_EXITING: + targetState = State.EXITING; + break; default: targetState = State.DEFAULT; break; @@ -1789,12 +1917,12 @@ boolean closeImpl(boolean notifyInstruments) { /* * Close operation initiated in the DEFAULT or INTERRUPTING state can fail in which case the - * context will go back to the corresponsing non-closing e.g. DEFAULT -> CLOSING -> DEFAULT. - * Please note that while the default close is in progress, i.e. the context state is in - * CLOSING or CLOSING_INTERRUPTING state, the state can be overriden by CLOSING_CANCELLING. - * Even in this case the default close can still fail and if that is the case the context - * state goes back to CANCELLING. The close operation is then guaranteed to be completed by - * the process that initiated cancel. + * context will go back to the corresponsing non-closing state e.g. DEFAULT -> CLOSING -> + * DEFAULT. Please note that while the default close is in progress, i.e. the context state + * is in CLOSING or CLOSING_INTERRUPTING state, the state can be overriden by + * CLOSING_CANCELLING state. Even in this case the default close can still fail and if that + * is the case the context state goes back to the CANCELLING state. The close operation is + * then guaranteed to be completed by the process that initiated cancel or exit. * * This block performs the following checks: * @@ -1805,18 +1933,22 @@ boolean closeImpl(boolean notifyInstruments) { * 3) The close is currently being performed on another thread -> wait for the other thread * to finish closing and start checking again from check 1). * - * 4) The close was not yet performed, cancelling or executing is not in progress, but other - * threads are still executing -> return false + * 4) The close was not yet performed, cancelling or exiting is not in progress, the context + * is not in the PENDING_EXIT state, but other threads are still executing -> return false * - * 5) The close was not yet performed and cancelling is in progress -> wait for other - * threads to complete and start checking again from check 1) skipping check 5) (this check) - * as no other threads can be executing anymore. + * 5) The close was not yet performed and the context is in the PENDING_EXIT state -> wait + * for the context to go to an invalid state (cancelling, exititng, or their closing or + * closed variants) and start checking from check 1). + * + * 6) The close was not yet performed and cancelling or exiting is in progress -> wait for + * other threads to complete and start checking again from check 1) skipping check 6) (this + * check) as no other threads can be executing anymore. * - * 6) The close was not yet performed and no thread is executing -> perform close + * 7) The close was not yet performed and no thread is executing -> perform close */ boolean waitForClose = false; - boolean finishCancel = false; - boolean cancelOperation; + boolean finishCancelOrExit = false; + boolean cancelOrExitOperation; acquireClosingLock: while (true) { if (waitForClose) { closingLock.lock(); @@ -1827,10 +1959,12 @@ boolean closeImpl(boolean notifyInstruments) { switch (state) { case CLOSED: case CLOSED_CANCELLED: + case CLOSED_EXITED: return true; case CLOSING: case CLOSING_INTERRUPTING: case CLOSING_CANCELLING: + case CLOSING_EXITING: assert closingThread != null; if (closingThread == Thread.currentThread()) { // currently closing recursively -> just complete @@ -1841,21 +1975,30 @@ boolean closeImpl(boolean notifyInstruments) { waitForClose = true; continue acquireClosingLock; } + case PENDING_EXIT: + while (!state.isInvalidOrClosed()) { + try { + wait(); + } catch (InterruptedException ie) { + } + } + continue acquireClosingLock; case CANCELLING: + case EXITING: assert cachedThreadInfo == PolyglotThreadInfo.NULL; /* - * When cancelling, we have to wait for all other threads to complete - even - * for the the default close, otherwise the default close executed - * prematurely as the result of leaving the context on the main thread due - * to cancel exception could fail because of other threads still being - * active. The correct behavior is that the normal close finishes + * When cancelling or exiting, we have to wait for all other threads to + * complete - even for the the default close, otherwise the default close + * executed prematurely as the result of leaving the context on the main + * thread due to cancel exception could fail because of other threads still + * being active. The correct behavior is that the normal close finishes * successfully and the cancel exception spreads further (if not caught * before close is executed). */ - if (!finishCancel) { + if (!finishCancelOrExit) { waitForThreads(0, 0); waitForClose = true; - finishCancel = true; + finishCancelOrExit = true; /* * During wait this thread didn't hold the polyglot context lock, so * some other thread might have acquired closingLock in the meantime. In @@ -1870,14 +2013,14 @@ boolean closeImpl(boolean notifyInstruments) { /* * Just continue with the close if we have already waited for threads in the * previous iteration of the main loop. We cannot wait for the close to be - * completed by the thread that executes cancelling, because it might be - * waiting for this thread which would lead to a deadlock. Default close is - * allowed to be executed when entered. Also, this might be an inner - * context, which, even if not entered, might block a parent's thread which - * could be entered on the current thread. + * completed by the thread that executes cancelling or exiting, because it + * might be waiting for this thread which would lead to a deadlock. Default + * close is allowed to be executed when entered. Also, this might be an + * inner context, which, even if not entered, might block a parent's thread + * which could be entered on the current thread. */ setClosingState(); - cancelOperation = true; + cancelOrExitOperation = true; break acquireClosingLock; case INTERRUPTING: case DEFAULT: @@ -1890,15 +2033,15 @@ boolean closeImpl(boolean notifyInstruments) { return false; } setClosingState(); - cancelOperation = false; + cancelOrExitOperation = false; break acquireClosingLock; default: - assert false; + assert false : state.name(); } } } - return finishClose(cancelOperation, notifyInstruments); + return finishClose(cancelOrExitOperation, notifyInstruments); } synchronized void clearExplicitContextStack() { @@ -1917,7 +2060,7 @@ synchronized void clearExplicitContextStack() { } } - private boolean finishClose(boolean cancelOperation, boolean notifyInstruments) { + private boolean finishClose(boolean cancelOrExitOperation, boolean notifyInstruments) { /* * If we reach here then we can continue with the close. This means that no other concurrent * close is running and no other thread is currently executing. Note that only the context @@ -1932,14 +2075,14 @@ private boolean finishClose(boolean cancelOperation, boolean notifyInstruments) assert !state.isClosed(); Object[] prev; try { - prev = this.enterThreadChanged(false, false, !cancelOperation, cancelOperation); + prev = this.enterThreadChanged(false, false, !cancelOrExitOperation, cancelOrExitOperation); } catch (Throwable t) { synchronized (this) { - restoreFromClosingState(cancelOperation); + restoreFromClosingState(cancelOrExitOperation); } throw t; } - if (cancelOperation) { + if (cancelOrExitOperation) { synchronized (this) { /* * Cancellation thread local action needs to be submitted here in case @@ -1949,9 +2092,26 @@ private boolean finishClose(boolean cancelOperation, boolean notifyInstruments) } } try { - closeChildContexts(notifyInstruments); + if (cancelOrExitOperation) { + closeChildContexts(notifyInstruments); + } else { + exitContextNotification(TruffleLanguage.ExitMode.NATURAL, 0); + } + + finalizeContext(notifyInstruments, cancelOrExitOperation); - finalizeContext(notifyInstruments, cancelOperation); + List unclosedChildContexts; + synchronized (this) { + unclosedChildContexts = getUnclosedChildContexts(); + } + for (PolyglotContextImpl childCtx : unclosedChildContexts) { + if (childCtx.isActive()) { + throw new IllegalStateException("There is an active child contexts after finalizeContext!"); + } + } + if (!unclosedChildContexts.isEmpty()) { + closeChildContexts(notifyInstruments); + } // finalization performed commit close -> no reinitialization allowed @@ -1962,9 +2122,11 @@ private boolean finishClose(boolean cancelOperation, boolean notifyInstruments) synchronized (this) { /* * The assert is synchronized because all accesses to childContexts must be - * synchronized. + * synchronized. We cannot simply assert that childContexts are empty, because + * removing the child context from its parent childContexts list can be done in + * another thread after the assertion. */ - assert !success || childContextsClosed() : "Polyglot context close marked as successful, but there are unclosed child contexts."; + assert !success || getUnclosedChildContexts().isEmpty() : "Polyglot context close marked as successful, but there are unclosed child contexts."; this.leaveThreadChanged(prev, false, true); if (success) { remainingThreads = threads.keySet().toArray(new Thread[0]); @@ -1972,7 +2134,7 @@ private boolean finishClose(boolean cancelOperation, boolean notifyInstruments) if (success) { setClosedState(); } else { - restoreFromClosingState(cancelOperation); + restoreFromClosingState(cancelOrExitOperation); } disposing = false; // triggers a thread changed event which requires slow path enter @@ -2057,19 +2219,15 @@ private boolean finishClose(boolean cancelOperation, boolean notifyInstruments) return true; } - /** - * Used in assertion only. We cannot simply assert that childContexts are empty, because - * removing the child context from its parent childContexts list can be done in another thread - * after the assertion. - */ - private boolean childContextsClosed() { + private List getUnclosedChildContexts() { assert Thread.holdsLock(this); + List unclosedChildContexts = new ArrayList<>(); for (PolyglotContextImpl childCtx : childContexts) { if (!childCtx.state.isClosed()) { - return false; + unclosedChildContexts.add(childCtx); } } - return true; + return unclosedChildContexts; } private void closeChildContexts(boolean notifyInstruments) { @@ -2082,6 +2240,123 @@ private void closeChildContexts(boolean notifyInstruments) { } } + static final class ExitException extends ThreadDeath { + private static final long serialVersionUID = -4838571769179260137L; + + private final Node location; + private final String exitMessage; + private final int exitCode; + + ExitException(Node location, int exitCode, String exitMessage) { + this.location = location; + this.exitCode = exitCode; + this.exitMessage = exitMessage; + } + + Node getLocation() { + return location; + } + + SourceSection getSourceLocation() { + return location == null ? null : location.getEncapsulatingSourceSection(); + } + + @Override + public String getMessage() { + return exitMessage; + } + + int getExitCode() { + return exitCode; + } + } + + private boolean setPendingExit(int code) { + synchronized (this) { + State targetState; + if (state == State.DEFAULT || state == State.INTERRUPTING) { + targetState = State.PENDING_EXIT; + exitCode = code; + exitMessage = "Exit was called with exit code " + code + "."; + closeExitedTriggerThread = Thread.currentThread(); + setState(targetState); + return true; + } + } + return false; + } + + void closeExited(Node exitLocation, int code) { + if (setPendingExit(code)) { + /* + * If this thread set PENDING_EXIT state and ran exit notifications, it will also be the + * one to execute the transition to EXITING state, unless the exit notifications were + * cancelled by cancelling the whole context. + */ + exitContextNotification(TruffleLanguage.ExitMode.HARD, code); + List> futures = setExiting(null, exitMessage); + if (!futures.isEmpty()) { + closeHereOrCancelInCleanupThread(futures); + } + } else { + synchronized (this) { + if (!state.isInvalidOrClosed()) { + /* + * Normally, if closeExited is called more than once, the subsequent calls wait + * until the context is invalid, which means that either the first call to + * closeExited finished running the exit notifications and set the context state + * to the (invalid) state EXITING, or the context was cancelled during the exit + * notifications and it is in the (invalid) state CANCELLING. However, we cannot + * wait for the invalid state when closeExited is called from an exit + * notification because the invalid state is only set when exit notifications + * are finished or cancelled, and so in these cases, we throw the exit exception + * immediately. + */ + PolyglotThreadInfo info = getCurrentThreadInfo(); + if (closeExitedTriggerThread == info.getThread() || (info.isPolyglotThread(this) && ((PolyglotThread) info.getThread()).hardExitNotificationThread)) { + throw createExitException(exitLocation); + } + } + } + } + + /* + * It is possible that the context is not invalid, but the exit operation was not allowed, + * because the context is being closed in which case the state is neither invalid nor + * PENDING_EXIT. In this case the closeExited operation is a no-op. + */ + State localState = state; + if (localState == State.PENDING_EXIT || localState.isInvalidOrClosed()) { + /* + * Wait for the context to become invalid. If this is the first call to closeExited that + * ran the exit notifications and set the exiting state, then the context is already + * invalid, otherwise we wait here until the first call to closeExited has done its job. + */ + TruffleSafepoint.setBlockedThreadInterruptible(exitLocation, new TruffleSafepoint.Interruptible() { + @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") + @Override + public void apply(PolyglotContextImpl ctx) throws InterruptedException { + synchronized (ctx) { + while (!ctx.state.isInvalidOrClosed()) { + ctx.wait(); + } + } + } + }, this); + + localState = state; + if (config.useSystemExit && (localState.isExiting() || localState == State.CLOSED_EXITED)) { + System.exit(exitCode); + } + /* + * Poll will throw the correct exception. Either the ThreadDeath exit or the ThreadDeath + * cancel exception based on whether the exit notifications were finished and the hard + * exit can be completed, or the context was cancelled during exit notifications. + */ + TruffleSafepoint.pollHere(exitLocation); + } + } + private void closeHereOrCancelInCleanupThread(List> futures) { boolean cancelInSeparateThread = false; synchronized (this) { @@ -2106,7 +2381,7 @@ private void closeHereOrCancelInCleanupThread(List> futures) { registerCleanupTask(new Runnable() { @Override public void run() { - PolyglotEngineImpl.cancel(PolyglotContextImpl.this, futures); + PolyglotEngineImpl.cancelOrExit(PolyglotContextImpl.this, futures); } }); } @@ -2202,9 +2477,37 @@ private List disposeContext() { return disposedContexts; } - private void finalizeContext(boolean notifyInstruments, boolean cancelOperation) { + private void exitContextNotification(TruffleLanguage.ExitMode exitMode, int code) { + // we need to run exit notifications at least twice in case an exit notification run has + // initialized new contexts + boolean exitNotificationPerformed; + try { + do { + exitNotificationPerformed = false; + for (int i = contexts.length - 1; i >= 0; i--) { + PolyglotLanguageContext context = contexts[i]; + if (context.isInitialized()) { + exitNotificationPerformed |= context.exitContext(exitMode, code); + } + } + } while (exitNotificationPerformed); + } catch (Throwable t) { + if (exitMode == TruffleLanguage.ExitMode.HARD) { + if (t instanceof PolyglotEngineImpl.CancelExecution) { + engine.getEngineLogger().log(Level.FINE, "Execution was cancelled during exit notifications!", t); + } else { + throw t; + } + } else { + throw t; + } + } + + } + + private void finalizeContext(boolean notifyInstruments, boolean cancelOrExitOperation) { // we need to run finalization at least twice in case a finalization run has - // initialized a new contexts + // initialized new contexts boolean finalizationPerformed; do { finalizationPerformed = false; @@ -2213,14 +2516,14 @@ private void finalizeContext(boolean notifyInstruments, boolean cancelOperation) for (int i = contexts.length - 1; i >= 0; i--) { PolyglotLanguageContext context = contexts[i]; if (context.isInitialized()) { - finalizationPerformed |= context.finalizeContext(cancelOperation, notifyInstruments); + finalizationPerformed |= context.finalizeContext(cancelOrExitOperation, notifyInstruments); } } } while (finalizationPerformed); } synchronized void sendInterrupt() { - if (!state.isInterrupting() && !state.isCancelling()) { + if (!state.isInterrupting() && !state.isCancelling() && !state.isExiting()) { return; } for (PolyglotThreadInfo threadInfo : threads.values()) { @@ -2501,7 +2804,7 @@ static PolyglotContextImpl preInitialize(final PolyglotEngineImpl engine) { allowedLanguages, Collections.emptyMap(), fs, internalFs, engine.logHandler, false, null, - EnvironmentAccess.INHERIT, null, null, null, null, null, true); + EnvironmentAccess.INHERIT, null, null, null, null, null, true, false); final PolyglotContextImpl context = new PolyglotContextImpl(engine, config); synchronized (engine.lock) { @@ -2661,6 +2964,10 @@ private CancelExecution createCancelException(Node location) { return new CancelExecution(location, invalidMessage, invalidResourceLimit); } + private ExitException createExitException(Node location) { + return new ExitException(location, exitCode, exitMessage); + } + private static boolean overridesPatchContext(String languageId) { if (TruffleOptions.AOT) { return LanguageCache.overridesPathContext(languageId); @@ -2725,8 +3032,12 @@ protected void perform(Access access) { PolyglotContextImpl.this.threadLocalActions.submit(new Thread[]{access.getThread()}, PolyglotEngineImpl.ENGINE_ID, this, new HandshakeConfig(true, false, false, true)); State localState = PolyglotContextImpl.this.state; - if (localState.isInvalidOrClosed() || localState.isCancelling()) { - throw createCancelException(access.getLocation()); + if (localState.isCancelling() || localState.isExiting() || localState == State.CLOSED_CANCELLED || localState == State.CLOSED_EXITED) { + if (localState.isExiting() || localState == State.CLOSED_EXITED) { + throw createExitException(access.getLocation()); + } else { + throw createCancelException(access.getLocation()); + } } } } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineDispatch.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineDispatch.java index 665b008f881c..2e13ea7120e8 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineDispatch.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineDispatch.java @@ -141,12 +141,12 @@ public Context createContext(Object oreceiver, OutputStream out, OutputStream er boolean allowNativeAccess, boolean allowCreateThread, boolean allowHostIO, boolean allowHostClassLoading, boolean allowExperimentalOptions, Predicate classFilter, Map options, Map arguments, String[] onlyLanguages, FileSystem fileSystem, Object logHandlerOrStream, boolean allowCreateProcess, ProcessHandler processHandler, EnvironmentAccess environmentAccess, Map environment, ZoneId zone, Object limitsImpl, String currentWorkingDirectory, - ClassLoader hostClassLoader, boolean allowValueSharing) { + ClassLoader hostClassLoader, boolean allowValueSharing, boolean useSystemExit) { PolyglotEngineImpl receiver = (PolyglotEngineImpl) oreceiver; PolyglotContextImpl context = receiver.createContext(out, err, in, allowHostAccess, hostAccess, polyglotAccess, allowNativeAccess, allowCreateThread, allowHostIO, allowHostClassLoading, allowExperimentalOptions, classFilter, options, arguments, onlyLanguages, fileSystem, logHandlerOrStream, allowCreateProcess, processHandler, environmentAccess, environment, zone, limitsImpl, - currentWorkingDirectory, hostClassLoader, allowValueSharing); + currentWorkingDirectory, hostClassLoader, allowValueSharing, useSystemExit); return polyglot.getAPIAccess().newContext(polyglot.contextDispatch, context, context.engine.api); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java index 7445dfed8b22..7936693f072c 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java @@ -1393,12 +1393,12 @@ public void run() { } } - static void cancel(PolyglotContextImpl context, List> cancelationFutures) { - cancelOrInterrupt(context, cancelationFutures, 0, null); + static void cancelOrExit(PolyglotContextImpl context, List> cancelationFutures) { + cancelOrExitOrInterrupt(context, cancelationFutures, 0, null); } @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") - static boolean cancelOrInterrupt(PolyglotContextImpl context, List> futures, long startMillis, Duration timeout) { + static boolean cancelOrExitOrInterrupt(PolyglotContextImpl context, List> futures, long startMillis, Duration timeout) { try { synchronized (context) { assert context.singleThreaded || !context.isActive(Thread.currentThread()) : "Cancel while entered is only allowed for single-threaded contexts!"; @@ -1541,7 +1541,7 @@ public PolyglotContextImpl createContext(OutputStream configOut, OutputStream co boolean allowHostClassLoading, boolean allowExperimentalOptions, Predicate classFilter, Map options, Map arguments, String[] onlyLanguages, FileSystem fileSystem, Object logHandlerOrStream, boolean allowCreateProcess, ProcessHandler processHandler, EnvironmentAccess environmentAccess, Map environment, ZoneId zone, Object limitsImpl, String currentWorkingDirectory, ClassLoader hostClassLoader, - boolean allowValueSharing) { + boolean allowValueSharing, boolean useSystemExit) { PolyglotContextImpl context; boolean replayEvents; boolean contextAddedToEngine; @@ -1616,7 +1616,7 @@ public PolyglotContextImpl createContext(OutputStream configOut, OutputStream co PolyglotContextConfig config = new PolyglotContextConfig(this, useOut, useErr, useIn, allowHostLookup, polyglotAccess, allowNativeAccess, allowCreateThread, allowHostClassLoading, allowExperimentalOptions, classFilter, arguments, allowedLanguages, options, fs, internalFs, useHandler, allowCreateProcess, useProcessHandler, - environmentAccess, environment, zone, polyglotLimits, hostClassLoader, hostAccess, allowValueSharing); + environmentAccess, environment, zone, polyglotLimits, hostClassLoader, hostAccess, allowValueSharing, useSystemExit); context = loadPreinitializedContext(config); replayEvents = false; contextAddedToEngine = false; diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java index 99ccb20ea127..472d364ebcfa 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java @@ -40,6 +40,8 @@ */ package com.oracle.truffle.polyglot; +import static com.oracle.truffle.polyglot.PolyglotContextImpl.State.CLOSED_EXITED; + import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.PrintWriter; @@ -101,17 +103,17 @@ final class PolyglotExceptionImpl { private final Value guestObject; private final String message; - PolyglotExceptionImpl(PolyglotEngineImpl engine, PolyglotContextImpl.State polyglotContextState, boolean polyglotContextResourceExhausted, Throwable original) { - this(engine.impl, engine, polyglotContextState, polyglotContextResourceExhausted, null, original, false, false); + PolyglotExceptionImpl(PolyglotEngineImpl engine, PolyglotContextImpl.State polyglotContextState, boolean polyglotContextResourceExhausted, int exitCode, Throwable original) { + this(engine.impl, engine, polyglotContextState, polyglotContextResourceExhausted, exitCode, null, original, false, false); } // Exception coming from an instrument PolyglotExceptionImpl(PolyglotImpl polyglot, Throwable original) { - this(polyglot, null, null, false, null, original, true, false); + this(polyglot, null, null, false, 0, null, original, true, false); } @SuppressWarnings("deprecation") - PolyglotExceptionImpl(PolyglotImpl polyglot, PolyglotEngineImpl engine, PolyglotContextImpl.State polyglotContextState, boolean polyglotContextResourceExhausted, + PolyglotExceptionImpl(PolyglotImpl polyglot, PolyglotEngineImpl engine, PolyglotContextImpl.State polyglotContextState, boolean polyglotContextResourceExhausted, int exitCode, PolyglotLanguageContext languageContext, Throwable original, boolean allowInterop, @@ -185,25 +187,33 @@ final class PolyglotExceptionImpl { this.cancelled = cancelInducedTruffleOrInterruptException || (exception instanceof CancelExecution) || isLegacyTruffleExceptionCancelled(exception); this.resourceExhausted = resourceLimitError != null || (cancelInducedTruffleOrInterruptException && polyglotContextResourceExhausted); this.interrupted = interruptException && !this.cancelled; - this.internal = !interrupted && !cancelled && !resourceExhausted; this.syntaxError = false; this.incompleteSource = false; - if (allowInterop) { - this.exit = isLegacyTruffleExceptionExit(exception); - this.exitStatus = exit ? getLegacyTruffleExceptionExitStatus(exception) : 0; - this.guestObject = getLegacyTruffleExceptionGuestObject(languageContext, exception); - } else { - this.exit = false; - this.exitStatus = 0; + com.oracle.truffle.api.source.SourceSection location = null; + boolean exitInducedTruffleOrInterruptException = (polyglotContextState != null && + (polyglotContextState.isExiting() || polyglotContextState == CLOSED_EXITED) && + (interruptException || truffleException)); + if (exitInducedTruffleOrInterruptException || exception instanceof PolyglotContextImpl.ExitException) { + this.exit = true; + this.exitStatus = exception instanceof PolyglotContextImpl.ExitException ? ((PolyglotContextImpl.ExitException) exception).getExitCode() : exitCode; this.guestObject = null; + location = exception instanceof PolyglotContextImpl.ExitException ? ((PolyglotContextImpl.ExitException) exception).getSourceLocation() : null; + } else { + if (allowInterop) { + this.exit = isLegacyTruffleExceptionExit(exception); + this.exitStatus = exit ? getLegacyTruffleExceptionExitStatus(exception) : 0; + this.guestObject = getLegacyTruffleExceptionGuestObject(languageContext, exception); + } else { + this.exit = false; + this.exitStatus = 0; + this.guestObject = null; + } } - com.oracle.truffle.api.source.SourceSection location; + this.internal = !interrupted && !cancelled && !resourceExhausted && !exit; if (exception instanceof CancelExecution) { location = ((CancelExecution) exception).getSourceLocation(); } else if (allowInterop) { location = getLegacyTruffleExceptionSourceLocation(exception); - } else { - location = null; } this.sourceLocation = location != null ? newSourceSection(location) : null; } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java index 73327ca6c2b1..1d9e9bdf7903 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java @@ -494,10 +494,10 @@ static PolyglotException guestToHostException(PolyglotLang PolyglotExceptionImpl exceptionImpl; PolyglotContextImpl.State localContextState = context.state; if (localContextState.isInvalidOrClosed()) { - exceptionImpl = new PolyglotExceptionImpl(context.engine, localContextState, context.invalidResourceLimit, e); + exceptionImpl = new PolyglotExceptionImpl(context.engine, localContextState, context.invalidResourceLimit, context.exitCode, e); } else { try { - exceptionImpl = new PolyglotExceptionImpl(languageContext.getImpl(), languageContext.context.engine, localContextState, false, + exceptionImpl = new PolyglotExceptionImpl(languageContext.getImpl(), languageContext.context.engine, localContextState, false, 0, languageContext, e, true, entered); } catch (Throwable t) { /* @@ -505,7 +505,7 @@ static PolyglotException guestToHostException(PolyglotLang * Report the exception as an internal error. */ e.addSuppressed(t); - exceptionImpl = new PolyglotExceptionImpl(context.engine, localContextState, false, e); + exceptionImpl = new PolyglotExceptionImpl(context.engine, localContextState, false, 0, e); } } APIAccess access = getInstance().getAPIAccess(); @@ -517,7 +517,7 @@ static PolyglotException guestToHostException(PolyglotEngi PolyglotEngineException.rethrow(e); APIAccess access = engine.getAPIAccess(); - PolyglotExceptionImpl exceptionImpl = new PolyglotExceptionImpl(engine, null, false, e); + PolyglotExceptionImpl exceptionImpl = new PolyglotExceptionImpl(engine, null, false, 0, e); return access.newLanguageException(exceptionImpl.getMessage(), getInstance().exceptionDispatch, exceptionImpl); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java index 7e8e8a3d707e..63a2f2b0aeb1 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java @@ -70,6 +70,7 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.dsl.Cached; @@ -218,6 +219,7 @@ private void addDependentLanguages(PolyglotEngineImpl engine, Map builtin) EXTERNAL_BUILTINS.add(builtin); } + @Override + protected void exitContext(SLContext context, ExitMode exitMode, int exitCode) { + /* + * Runs shutdown hooks during explicit exit triggered by TruffleContext#closeExit(Node, int) + * or natural exit triggered during natural context close. + */ + context.runShutdownHooks(); + } } diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLExitBuiltin.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLExitBuiltin.java new file mode 100644 index 000000000000..6ad5f108aa9d --- /dev/null +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLExitBuiltin.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.sl.builtins; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.NodeInfo; +import com.oracle.truffle.sl.runtime.SLContext; +import com.oracle.truffle.sl.runtime.SLNull; + +/** + * Builtin function that performs context exit. + */ +@NodeInfo(shortName = "exit") +public abstract class SLExitBuiltin extends SLBuiltinNode { + + @Specialization + protected Object execute(long exitCode) { + SLContext.get(this).getEnv().getContext().closeExited(this, (int) exitCode); + return SLNull.SINGLETON; + } +} diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLRegisterShutdownHookBuiltin.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLRegisterShutdownHookBuiltin.java new file mode 100644 index 000000000000..06e012f5ab92 --- /dev/null +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLRegisterShutdownHookBuiltin.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.sl.builtins; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.NodeInfo; +import com.oracle.truffle.sl.runtime.SLContext; +import com.oracle.truffle.sl.runtime.SLFunction; +import com.oracle.truffle.sl.runtime.SLNull; + +/** + * Builtin function that registers a function as a shutdown hook. Only no-parameter functions are + * supported. + */ +@NodeInfo(shortName = "registerShutdownHook") +public abstract class SLRegisterShutdownHookBuiltin extends SLBuiltinNode { + + @Specialization + protected Object execute(SLFunction shutdownHook) { + SLContext.get(this).registerShutdownHook(shutdownHook); + return SLNull.SINGLETON; + } +} diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java index 7d3c92969a7a..e645cdf173e8 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java @@ -45,6 +45,7 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.List; import com.oracle.truffle.api.CallTarget; @@ -56,13 +57,18 @@ import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.dsl.NodeFactory; import com.oracle.truffle.api.instrumentation.AllocationReporter; +import com.oracle.truffle.api.interop.ArityException; +import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.sl.SLLanguage; import com.oracle.truffle.sl.builtins.SLBuiltinNode; import com.oracle.truffle.sl.builtins.SLDefineFunctionBuiltinFactory; import com.oracle.truffle.sl.builtins.SLEvalBuiltinFactory; +import com.oracle.truffle.sl.builtins.SLExitBuiltinFactory; import com.oracle.truffle.sl.builtins.SLGetSizeBuiltinFactory; import com.oracle.truffle.sl.builtins.SLHasSizeBuiltinFactory; import com.oracle.truffle.sl.builtins.SLHelloEqualsWorldBuiltinFactory; @@ -77,6 +83,7 @@ import com.oracle.truffle.sl.builtins.SLPrintlnBuiltinFactory; import com.oracle.truffle.sl.builtins.SLReadlnBuiltin; import com.oracle.truffle.sl.builtins.SLReadlnBuiltinFactory; +import com.oracle.truffle.sl.builtins.SLRegisterShutdownHookBuiltinFactory; import com.oracle.truffle.sl.builtins.SLStackTraceBuiltinFactory; import com.oracle.truffle.sl.builtins.SLTypeOfBuiltinFactory; import com.oracle.truffle.sl.builtins.SLWrapPrimitiveBuiltinFactory; @@ -98,6 +105,7 @@ public final class SLContext { private final PrintWriter output; private final SLFunctionRegistry functionRegistry; private final AllocationReporter allocationReporter; + private final List shutdownHooks = new ArrayList<>(); public SLContext(SLLanguage language, TruffleLanguage.Env env, List> externalBuiltins) { this.env = env; @@ -175,6 +183,8 @@ private void installBuiltins() { installBuiltin(SLTypeOfBuiltinFactory.getInstance()); installBuiltin(SLIsInstanceBuiltinFactory.getInstance()); installBuiltin(SLJavaTypeBuiltinFactory.getInstance()); + installBuiltin(SLExitBuiltinFactory.getInstance()); + installBuiltin(SLRegisterShutdownHookBuiltinFactory.getInstance()); } public void installBuiltin(NodeFactory factory) { @@ -237,4 +247,28 @@ public static SLContext get(Node node) { return REFERENCE.get(node); } + /** + * Register a function as a shutdown hook. Only no-parameter functions are supported. + * + * @param func no-parameter function to be registered as a shutdown hook + */ + @TruffleBoundary + public void registerShutdownHook(SLFunction func) { + shutdownHooks.add(func); + } + + /** + * Run registered shutdown hooks. This method is designed to be executed in + * {@link TruffleLanguage#exitContext(Object, TruffleLanguage.ExitMode, int)}. + */ + public void runShutdownHooks() { + InteropLibrary interopLibrary = InteropLibrary.getUncached(); + for (SLFunction shutdownHook : shutdownHooks) { + try { + interopLibrary.execute(shutdownHook); + } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) { + throw shouldNotReachHere("Shutdown hook is not executable!", e); + } + } + } } diff --git a/truffle/src/com.oracle.truffle.tck/snapshot.sigtest b/truffle/src/com.oracle.truffle.tck/snapshot.sigtest index 02179fd02eca..52484e1295ec 100644 --- a/truffle/src/com.oracle.truffle.tck/snapshot.sigtest +++ b/truffle/src/com.oracle.truffle.tck/snapshot.sigtest @@ -10,6 +10,7 @@ innr public abstract interface static Provider innr public abstract static ContextReference innr public abstract static LanguageReference innr public final static !enum ContextPolicy +innr public final static !enum ExitMode innr public final static Env innr public final static InlineParsingRequest innr public final static ParsingRequest @@ -53,6 +54,7 @@ meth protected static <%0 extends java.lang.Object, %1 extends com.oracle.truffl anno 0 java.lang.Deprecated() meth protected void disposeContext({com.oracle.truffle.api.TruffleLanguage%0}) meth protected void disposeThread({com.oracle.truffle.api.TruffleLanguage%0},java.lang.Thread) +meth protected void exitContext({com.oracle.truffle.api.TruffleLanguage%0},com.oracle.truffle.api.TruffleLanguage$ExitMode,int) meth protected void finalizeContext({com.oracle.truffle.api.TruffleLanguage%0}) meth protected void initializeContext({com.oracle.truffle.api.TruffleLanguage%0}) throws java.lang.Exception meth protected void initializeMultiThreading({com.oracle.truffle.api.TruffleLanguage%0}) From 3d971bf3919c4a5783f9dfd018457ec7b54e29da Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Thu, 30 Sep 2021 14:48:06 +0200 Subject: [PATCH 240/681] add empty line to javadoc --- .../src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java | 1 + 1 file changed, 1 insertion(+) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java index 56dc2c3c41db..beb6293c1b81 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java @@ -500,6 +500,7 @@ public interface JDWPContext { /** * Tests if the guest object is a member of the klass. + * * @param guestObject the guest object * @param klass the class * @return true is guest object is a member of the klass From 80693c29b949828aa16f8dac2f6bcb7549f11b5f Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 30 Sep 2021 13:45:17 +0200 Subject: [PATCH 241/681] Extract llvm.umin/umax operators into singletons --- .../parser/factories/BasicNodeFactory.java | 11 +- .../intrinsics/c/LLVMCMathsIntrinsics.java | 148 +++++++++--------- 2 files changed, 77 insertions(+), 82 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java index 84e227bb12b5..9f8b8db3bbeb 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java @@ -123,13 +123,14 @@ import com.oracle.truffle.llvm.runtime.nodes.func.LLVMLandingpadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.func.LLVMResumeNodeGen; import com.oracle.truffle.llvm.runtime.nodes.func.LLVMTypeIdForExceptionNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsics.LLVMUmaxOperator; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsics.LLVMUminOperator; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMAbsNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMFAbsNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMFAbsVectorNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMPowNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMUmaxVectorNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMUminVectorNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMUnsignedVectorMinMaxNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMTruffleGetArgCountNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMTruffleGetArgNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMAssumeNodeGen; @@ -1745,20 +1746,18 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV } if ("llvm.umax".equals(intrinsicName) && typeSuffix != null && typeSuffix.length != null) { - // format '.([vp]\d+)?[if]\d+)' try { int vectorLength = Integer.parseInt(typeSuffix.length); - return LLVMUmaxVectorNodeGen.create(args[1], args[2], vectorLength); + return LLVMUnsignedVectorMinMaxNodeGen.create(args[1], args[2], vectorLength, LLVMUmaxOperator.INSTANCE); } catch (NumberFormatException e) { // fall through } } if ("llvm.umin".equals(intrinsicName) && typeSuffix != null && typeSuffix.length != null) { - // format '.([vp]\d+)?[if]\d+)' try { int vectorLength = Integer.parseInt(typeSuffix.length); - return LLVMUminVectorNodeGen.create(args[1], args[2], vectorLength); + return LLVMUnsignedVectorMinMaxNodeGen.create(args[1], args[2], vectorLength, LLVMUminOperator.INSTANCE); } catch (NumberFormatException e) { // fall through } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java index 96af96fb6182..b31bd519c973 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/c/LLVMCMathsIntrinsics.java @@ -29,7 +29,6 @@ */ package com.oracle.truffle.llvm.runtime.nodes.intrinsics.c; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.NodeField; @@ -810,38 +809,91 @@ protected LLVM80BitFloat doLLVM80BitFloat(LLVM80BitFloat magnitude, LLVM80BitFlo } } - @NodeChild(type = LLVMExpressionNode.class) - @NodeChild(type = LLVMExpressionNode.class) - @NodeField(name = "vectorLength", type = int.class) - abstract static class LLVMUnsignedVectorMinMaxNode extends LLVMBuiltin { - protected abstract int getVectorLength(); + abstract static class LLVMUMinMaxOperator { + protected abstract boolean compare(boolean a, boolean b); + + protected abstract int compare(int a, int b); + + protected abstract long compare(long a, long b); + + protected abstract float compare(float a, float b); + protected abstract double compare(double a, double b); + } + + public static final class LLVMUmaxOperator extends LLVMUMinMaxOperator { + public static final LLVMUmaxOperator INSTANCE = new LLVMUmaxOperator(); + + @Override protected boolean compare(boolean a, boolean b) { - throw CompilerDirectives.shouldNotReachHere(); + return a || b; } - private byte compare(byte a, byte b) { - return (byte) compare((int) a, (int) b); + @Override + protected int compare(int a, int b) { + return Integer.compareUnsigned(a, b) >= 0 ? a : b; } - private short compare(short a, short b) { - return (short) compare((int) a, (int) b); + @Override + protected long compare(long a, long b) { + return Long.compareUnsigned(a, b) >= 0 ? a : b; + } + + @Override + protected float compare(float a, float b) { + return Math.max(a, b); + } + + @Override + protected double compare(double a, double b) { + return Math.max(a, b); } + } + + public static final class LLVMUminOperator extends LLVMUMinMaxOperator { + public static final LLVMUminOperator INSTANCE = new LLVMUminOperator(); + @Override + protected boolean compare(boolean a, boolean b) { + return a && b; + } + + @Override protected int compare(int a, int b) { - throw CompilerDirectives.shouldNotReachHere(); + return Integer.compareUnsigned(a, b) <= 0 ? a : b; } + @Override protected long compare(long a, long b) { - throw CompilerDirectives.shouldNotReachHere(); + return Long.compareUnsigned(a, b) <= 0 ? a : b; } + @Override protected float compare(float a, float b) { - throw CompilerDirectives.shouldNotReachHere(); + return Math.min(a, b); } + @Override protected double compare(double a, double b) { - throw CompilerDirectives.shouldNotReachHere(); + return Math.min(a, b); + } + } + + @NodeChild(type = LLVMExpressionNode.class) + @NodeChild(type = LLVMExpressionNode.class) + @NodeField(name = "vectorLength", type = int.class) + @NodeField(name = "operator", type = LLVMUMinMaxOperator.class) + public abstract static class LLVMUnsignedVectorMinMaxNode extends LLVMBuiltin { + protected abstract int getVectorLength(); + + protected abstract LLVMUMinMaxOperator getOperator(); + + private byte compare(byte a, byte b) { + return (byte) getOperator().compare(a, b); + } + + private short compare(short a, short b) { + return (short) getOperator().compare(a, b); } @Specialization @@ -851,7 +903,7 @@ protected LLVMI1Vector doI1Vector(LLVMI1Vector a, LLVMI1Vector b) { assert b.getLength() == getVectorLength(); boolean[] result = new boolean[getVectorLength()]; for (int i = 0; i < getVectorLength(); i++) { - result[i] = compare(a.getValue(i), b.getValue(i)); + result[i] = getOperator().compare(a.getValue(i), b.getValue(i)); } return LLVMI1Vector.create(result); } @@ -893,7 +945,7 @@ protected LLVMI32Vector doI32Vector(LLVMI32Vector a, LLVMI32Vector b) { for (int i = 0; i < getVectorLength(); i++) { int aValue = a.getValue(i); int bValue = b.getValue(i); - result[i] = compare(aValue, bValue); + result[i] = getOperator().compare(aValue, bValue); } return LLVMI32Vector.create(result); } @@ -907,7 +959,7 @@ protected LLVMI64Vector doI64Vector(LLVMI64Vector a, LLVMI64Vector b) { for (int i = 0; i < getVectorLength(); i++) { long aValue = a.getValue(i); long bValue = b.getValue(i); - result[i] = Long.compareUnsigned(aValue, bValue) >= 0 ? aValue : bValue; + result[i] = getOperator().compare(aValue, bValue) >= 0 ? aValue : bValue; } return LLVMI64Vector.create(result); } @@ -919,7 +971,7 @@ protected LLVMFloatVector doFloatVector(LLVMFloatVector a, LLVMFloatVector b) { assert b.getLength() == getVectorLength(); float[] result = new float[getVectorLength()]; for (int i = 0; i < getVectorLength(); i++) { - result[i] = compare(a.getValue(i), b.getValue(i)); + result[i] = getOperator().compare(a.getValue(i), b.getValue(i)); } return LLVMFloatVector.create(result); } @@ -931,65 +983,9 @@ protected LLVMDoubleVector doDoubleVector(LLVMDoubleVector a, LLVMDoubleVector b assert b.getLength() == getVectorLength(); double[] result = new double[getVectorLength()]; for (int i = 0; i < getVectorLength(); i++) { - result[i] = compare(a.getValue(i), b.getValue(i)); + result[i] = getOperator().compare(a.getValue(i), b.getValue(i)); } return LLVMDoubleVector.create(result); } } - - public abstract static class LLVMUmaxVectorNode extends LLVMUnsignedVectorMinMaxNode { - - @Override - protected final boolean compare(boolean a, boolean b) { - return a || b; - } - - @Override - protected final int compare(int a, int b) { - return Integer.compareUnsigned(a, b) >= 0 ? a : b; - } - - @Override - protected final long compare(long a, long b) { - return Long.compareUnsigned(a, b) >= 0 ? a : b; - } - - @Override - protected final float compare(float a, float b) { - return Math.max(a, b); - } - - @Override - protected final double compare(double a, double b) { - return Math.max(a, b); - } - } - - public abstract static class LLVMUminVectorNode extends LLVMUnsignedVectorMinMaxNode { - - @Override - protected final boolean compare(boolean a, boolean b) { - return a && b; - } - - @Override - protected final int compare(int a, int b) { - return Integer.compareUnsigned(a, b) <= 0 ? a : b; - } - - @Override - protected final long compare(long a, long b) { - return Long.compareUnsigned(a, b) <= 0 ? a : b; - } - - @Override - protected final float compare(float a, float b) { - return Math.min(a, b); - } - - @Override - protected final double compare(double a, double b) { - return Math.min(a, b); - } - } } From 02c961af4de1fa9852f732b03e71243067c5ce9a Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 21 Sep 2021 15:00:40 +0100 Subject: [PATCH 242/681] Generate graph data with collapsed recursive frames. --- .../tools/profiler/impl/SVGSamplerOutput.java | 380 +++++++++++++----- .../profiler/impl/resources/flamegraph.js | 16 +- .../profiler/impl/resources/graphowner.js | 70 ++-- .../profiler/impl/resources/histogram.js | 6 +- 4 files changed, 324 insertions(+), 148 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index 3019af47072f..f1b297e4e730 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.ArrayDeque; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -223,7 +224,7 @@ private static class GraphOwner implements SVGComponent { public int sourceCounter = 0; public final JSONArray sampleNames = new JSONArray(); public final JSONArray sourceNames = new JSONArray(); - public final JSONObject sampleData = new JSONObject(); + public final JSONArray sampleData = new JSONArray(); GraphOwner(StringBuilder output, Map data) { svg = new SVGSamplerOutput(output); @@ -295,19 +296,36 @@ public String script() { return result.toString(); } + private static final class Task { + final ProfilerNode sample; + final JSONArray siblings; + final long x; + final int parent; + + Task(ProfilerNode sample, JSONArray siblings, long x, int parent) { + this.sample = sample; + this.siblings = siblings; + this.x = x; + this.parent = parent; + } + } + private void buildSampleData() { - sampleData.put("n", nameCounter); - sampleData.put("f", sourceCounter); - sampleData.put("fl", 0); + ArrayDeque tasks = new ArrayDeque<>(); + JSONObject root = new JSONObject(); + sampleData.put(root); + root.put("n", nameCounter); + root.put("f", sourceCounter); + root.put("fl", 0); nameHash.put("", nameCounter++); sampleNames.put(""); sourceHash.put("", sourceCounter++); sourceNames.put(""); - sampleData.put("id", sampleId++); - sampleData.put("i", 0); - sampleData.put("c", 0); - sampleData.put("x", 0); - sampleData.put("l", GraphColorMap.GRAY.ordinal()); + root.put("id", sampleId++); + root.put("i", 0); + root.put("c", 0); + root.put("x", 0); + root.put("l", GraphColorMap.GRAY.ordinal()); long totalSamples = 0; JSONArray children = new JSONArray(); for (CPUSamplerData value : data.values()) { @@ -315,48 +333,200 @@ private void buildSampleData() { Thread thread = node.getKey(); // Output the thread node itself... // Optput the samples under that node... - List> samples = new ArrayList<>(node.getValue()); - children.put(threadSampelData(thread, samples, totalSamples)); - for (ProfilerNode sample : samples) { - totalSamples += sample.getPayload().getHitCount(); + totalSamples = threadSampleData(thread, node.getValue(), tasks, children, totalSamples); + } + } + root.put("h", totalSamples); + root.put("s", children); + + Task task = tasks.poll(); + while (task != null) { + processSample(task, tasks); + task = tasks.poll(); + } + buildColorData(); + buildRecursiveData(); + } + + private static final class SampleKey { + int nameId; + int sourceId; + int sourceLine; + + SampleKey(int nameId, int sourceId, int sourceLine) { + this.nameId = nameId; + this.sourceId = sourceId; + this.sourceLine = sourceLine; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + nameId; + result = prime * result + sourceId; + result = prime * result + sourceLine; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SampleKey other = (SampleKey) obj; + if (nameId != other.nameId) + return false; + if (sourceId != other.sourceId) + return false; + if (sourceLine != other.sourceLine) + return false; + return true; + } + } + + private HashMap> recursiveChildMap = new HashMap<>(); + + private HashMap childrenByKeyForSample(JSONObject sample) { + return recursiveChildMap.computeIfAbsent(sample.getInt("id"), k -> { + HashMap childMap = new HashMap<>(); + return childMap; + }); + } + + private static final class RecursivePositionTask { + JSONObject sample; + long x; + + public RecursivePositionTask(JSONObject sample, long x) { + this.sample = sample; + this.x = x; + } + } + + private void buildRecursiveData() { + // Merge all the collapsed recursive relationships and hit counts + for (Object sample : sampleData) { + calculateRecursiveData((JSONObject) sample); + } + // Work out the collapsed recursive x positions. + ArrayDeque tasks = new ArrayDeque<>(); + RecursivePositionTask task = new RecursivePositionTask(sampleDataForId(0), 0); + while (task != null) { + task.sample.put("rx", task.x); + if (task.sample.has("rs")) { + long offset = task.x + task.sample.getInt("ri") + task.sample.getInt("rc"); + for (Object childId : task.sample.getJSONArray("rs")) { + JSONObject child = sampleDataForId((Integer) childId); + tasks.add(new RecursivePositionTask(child, offset)); + offset += child.getInt("rh"); } } + task = tasks.poll(); } - sampleData.put("h", totalSamples); - sampleData.put("s", children); - buildColorData(sampleData); } - private JSONObject threadSampelData(Thread thread, List> samples, long x) { - JSONObject result = new JSONObject(); - result.put("n", nameHash.computeIfAbsent(thread.getName(), k -> { + private void calculateRecursiveData(JSONObject sample) { + if (sample.has("p")) { + JSONObject parent = sampleDataForId(sample.getInt("p")); + final JSONObject owner; + if (parent.has("ro")) { + owner = sampleDataForId(parent.getInt("ro")); + } else { + owner = parent; + } + if (parent.getInt("n") == sample.getInt("n")) { + mergeCounts(owner, sample, true); + } else { + HashMap siblings = childrenByKeyForSample(owner); + SampleKey key = new SampleKey(sample.getInt("n"), sample.getInt("f"), sample.getInt("fl")); + if (siblings.containsKey(key)) { + JSONObject sibling = siblings.get(key); + mergeCounts(sibling, sample, false); + } else { + siblings.put(key, sample); + addRecursiveChild(owner, sample); + } + sample.put("rp", owner.getInt("id")); + } + } else { + // The root sample needs rc, ri, and rh set. + sample.put("rc", sample.getInt("c")); + sample.put("ri", sample.getInt("i")); + sample.put("rh", sample.getInt("h")); + } + } + + private void addRecursiveChild(JSONObject sample, JSONObject child) { + final JSONArray children; + if (!sample.has("rs")) { + children = new JSONArray(); + sample.put("rs", children); + } else { + children = sample.getJSONArray("rs"); + } + children.put(child.getInt("id")); + child.put("rc", child.getInt("c")); + child.put("ri", child.getInt("i")); + child.put("rh", child.getInt("h")); + } + + private void mergeCounts(JSONObject a, JSONObject b, boolean child) { + int aRI = a.has("ri") ? a.getInt("ri") : a.getInt("i"); + int aRC = a.has("rc") ? a.getInt("rc") : a.getInt("c"); + int aRH = a.has("rh") ? a.getInt("rh") : a.getInt("h"); + aRI += b.getInt("i"); + aRC += b.getInt("c"); + // Siblings should have their hit counts combined, but + // children should not increase their parent's hit count. + if (!child) { + aRH += b.getInt("h"); + } + a.put("ri", aRI); + a.put("rc", aRC); + a.put("rh", aRH); + b.put("ro", a.getInt("id")); + } + + private long threadSampleData(Thread thread, Collection> samples, ArrayDeque tasks, JSONArray siblings, long x) { + JSONObject threadSample = new JSONObject(); + long totalSamples = x; + int id = sampleId++; + threadSample.put("n", nameHash.computeIfAbsent(thread.getName(), k -> { sampleNames.put(thread.getName()); return nameCounter++; })); - result.put("f", sourceHash.computeIfAbsent("", k -> { + threadSample.put("f", sourceHash.computeIfAbsent("", k -> { sourceNames.put(""); return sourceCounter++; })); - result.put("fl", 0); - result.put("id", sampleId++); - result.put("i", 0); - result.put("c", 0); - result.put("l", GraphColorMap.GRAY.ordinal()); - result.put("x", x); - long totalSamples = 0; + threadSample.put("fl", 0); + threadSample.put("id", id); + threadSample.put("p", 0); + sampleData.put(threadSample); + threadSample.put("i", 0); + threadSample.put("c", 0); + threadSample.put("l", GraphColorMap.GRAY.ordinal()); + threadSample.put("x", x); JSONArray children = new JSONArray(); + long childCount = 0; for (ProfilerNode sample : samples) { - children.put(sampleData(sample, totalSamples + x)); + tasks.addLast(new Task(sample, children, totalSamples, id)); totalSamples += sample.getPayload().getHitCount(); + childCount++; } - result.put("h", totalSamples); - if (children.length() > 0) { - result.put("s", children); + threadSample.put("h", totalSamples); + if (childCount > 0) { + threadSample.put("s", children); } - return result; + siblings.put(threadSample.getInt("id")); + return totalSamples; } - public String samples() { + private String samples() { StringBuilder result = new StringBuilder(); result.append("var profileNames = "); @@ -400,16 +570,16 @@ public String samples() { return result.toString(); } - public JSONObject sampleData(ProfilerNode sample, long x) { + private void processSample(Task task, ArrayDeque tasks) { JSONObject result = new JSONObject(); - final int nameId = nameHash.computeIfAbsent(sample.getRootName(), k -> { - sampleNames.put(sample.getRootName()); + final int nameId = nameHash.computeIfAbsent(task.sample.getRootName(), k -> { + sampleNames.put(task.sample.getRootName()); return nameCounter++; }); result.put("n", nameId); final String sourceName; int sourceLine = 0; - SourceSection section = sample.getSourceSection(); + SourceSection section = task.sample.getSourceSection(); if (section != null && section.isAvailable()) { sourceLine = section.getStartLine(); Source source = section.getSource(); @@ -431,62 +601,46 @@ public JSONObject sampleData(ProfilerNode sample, long x) { return sourceCounter++; })); result.put("fl", sourceLine); - result.put("id", sampleId++); - result.put("i", sample.getPayload().getTierSelfCount(0)); + int id = sampleId++; + result.put("id", id); + result.put("p", task.parent); + sampleData.put(result); + result.put("i", task.sample.getPayload().getTierSelfCount(0)); int compiledSelfHits = 0; - for (int i = 1; i < sample.getPayload().getNumberOfTiers(); i++) { - compiledSelfHits += sample.getPayload().getTierSelfCount(i); + for (int i = 1; i < task.sample.getPayload().getNumberOfTiers(); i++) { + compiledSelfHits += task.sample.getPayload().getTierSelfCount(i); } result.put("c", compiledSelfHits); - result.put("h", sample.getPayload().getHitCount()); - result.put("l", colorMapForLanguage(sample).ordinal()); - result.put("x", x); + result.put("h", task.sample.getPayload().getHitCount()); + result.put("l", colorMapForLanguage(task.sample).ordinal()); + result.put("x", task.x); JSONArray children = new JSONArray(); - long offset = sample.getPayload().getSelfHitCount(); - for (ProfilerNode child : sample.getChildren()) { - children.put(sampleData(child, x + offset)); + int childCount = 0; + long offset = task.sample.getPayload().getSelfHitCount(); + for (ProfilerNode child : task.sample.getChildren()) { + tasks.addLast(new Task(child, children, task.x + offset, id)); offset += child.getPayload().getHitCount(); + childCount++; } - if (children.length() > 0) { + if (childCount > 0) { result.put("s", children); } - return result; - } - - private JSONObject findSampleInTree(JSONObject tree, int id) { - if (tree.getInt("id") == id) { - return tree; - } else if (tree.has("s")) { - JSONArray children = tree.getJSONArray("s"); - JSONObject lastChild = null; - for (Object c : children) { - JSONObject child = (JSONObject) c; - if (child.getInt("id") == id) { - return child; - } else if (child.getInt("id") > id) { - return findSampleInTree(lastChild, id); - } else { - lastChild = child; - } - } - return findSampleInTree(lastChild, id); - } - return null; + task.siblings.put(result.getInt("id")); } protected JSONObject sampleDataForId(int id) { - return findSampleInTree(sampleData, id); + return (JSONObject) sampleData.get(id); } - private void buildColorData(JSONObject sample) { - colorForName(sample.getInt("n"), GraphColorMap.FLAME); - colorForName(sample.getInt("n"), GraphColorMap.values()[sample.getInt("l")]); - if (sample.has("s")) { - for (Object child : sample.getJSONArray("s")) { - buildColorData((JSONObject) child); - } + private void buildColorData() { + for (Object sample : sampleData) { + buildColorDataForSample((JSONObject) sample); } + } + private void buildColorDataForSample(JSONObject sample) { + colorForName(sample.getInt("n"), GraphColorMap.FLAME); + colorForName(sample.getInt("n"), GraphColorMap.values()[sample.getInt("l")]); } public String initFunction(String argName) { @@ -728,9 +882,9 @@ private static class SVGFlameGraph implements SVGComponent { this.owner = owner; this.bottomPadding = 2 * owner.fontSize() + 10; this.topPadding = 3 * owner.fontSize(); - this.sampleCount = owner.sampleData.getInt("h"); + this.sampleCount = owner.sampleDataForId(0).getInt("h"); widthPerTime = (width() - 2 * XPAD) / sampleCount; - maxDepth = maxDepth(owner.sampleData); + maxDepth = maxDepth(owner.sampleDataForId(0)); } private int maxDepth(JSONObject samples) { @@ -739,9 +893,9 @@ private int maxDepth(JSONObject samples) { return 0; } else { int childDepth = 0; - if (samples.has("s")) { - for (Object child : samples.getJSONArray("s")) { - childDepth = Integer.max(childDepth, maxDepth((JSONObject) child)); + if (samples.has("rs")) { + for (Object child : samples.getJSONArray("rs")) { + childDepth = Integer.max(childDepth, maxDepth(owner.sampleDataForId((Integer) child))); } } return childDepth + 1; @@ -801,22 +955,48 @@ public String drawCanvas(double x, double y) { private String drawTree() { StringBuilder output = new StringBuilder(); double baseY = -FRAMEHEIGHT - bottomPadding; - output.append(drawSample(baseY, owner.sampleData)); + output.append(drawSamples(baseY, owner.sampleDataForId(0))); return output.toString(); } private double sampleWidth(JSONObject sample) { - long hitCount = sample.getInt("h"); + long hitCount = sample.getInt("rh"); return widthPerTime * hitCount; } private double sampleX(JSONObject sample) { - long x = sample.getInt("x"); + long x = sample.getInt("rx"); return widthPerTime * x + XPAD; } - private String drawSample(double y, JSONObject sample) { + private static final class DrawTask { + final JSONObject sample; + final int depth; + + DrawTask(JSONObject sample, int depth) { + this.sample = sample; + this.depth = depth; + } + } + + private String drawSamples(double y, JSONObject root) { + ArrayDeque tasks = new ArrayDeque<>(); + StringBuilder output = new StringBuilder(); + DrawTask task = new DrawTask(root, 0); + while (task != null) { + output.append(drawSample(y, task, tasks)); + task = tasks.poll(); + } + return output.toString(); + } + + private String drawSample(double baseY, DrawTask task, ArrayDeque tasks) { + // Redesign this to use a task deque. + StringBuilder output = new StringBuilder(); + JSONObject sample = task.sample; + int depth = task.depth; + double y = baseY - depth * FRAMEHEIGHT; double width = sampleWidth(sample); double x = sampleX(sample); if (width < MINWIDTH) { @@ -851,10 +1031,11 @@ private String drawSample(double y, JSONObject sample) { output.append(ttfString(black(), owner.fontName(), owner.fontSize(), x + 3, y - 5 + FRAMEHEIGHT, owner.abbreviate(fullText, width), null, "")); output.append(endGroup(groupAttrs)); - if (sample.has("s")) { - JSONArray children = sample.getJSONArray("s"); - for (Object child : children) { - output.append(drawSample(y - FRAMEHEIGHT, (JSONObject) child)); + if (sample.has("rs")) { + JSONArray children = sample.getJSONArray("rs"); + for (Object childId : children) { + JSONObject child = owner.sampleDataForId((Integer) childId); + tasks.add(new DrawTask(child, depth + 1)); } } return output.toString(); @@ -903,7 +1084,7 @@ private static class SVGHistogram implements SVGComponent { this.titlePadding = owner.fontSize() * 3.0; this.bottomPadding = owner.fontSize() * 2 + 10.0; - histogram = buildHistogram(owner.sampleData); + histogram = buildHistogram(owner.sampleDataForId(0)); timeMax = histogram.get(0).getInt("i") + histogram.get(0).getInt("c"); widthPerTime = (width() - 2 * XPAD) / timeMax; double minTime = MINWIDTH / widthPerTime; @@ -917,13 +1098,20 @@ private static class SVGHistogram implements SVGComponent { private List buildHistogram(JSONObject sample) { Map bars = new HashMap<>(); - buildHistogram(sample, bars); + ArrayDeque samples = new ArrayDeque<>(); + + JSONObject next = sample; + while (next != null) { + buildHistogram(next, samples, bars); + next = samples.poll(); + } + ArrayList lines = new ArrayList<>(bars.values()); Collections.sort(lines, (a, b) -> Integer.compare(b.getInt("i") + b.getInt("c"), a.getInt("i") + a.getInt("c"))); return lines; } - private void buildHistogram(JSONObject sample, Map bars) { + private void buildHistogram(JSONObject sample, ArrayDeque samples, Map bars) { JSONObject bar = bars.computeIfAbsent(owner.sampleNames.getString(sample.getInt("n")), k -> { JSONObject entry = new JSONObject(); @@ -938,8 +1126,8 @@ private void buildHistogram(JSONObject sample, Map bars) { bar.put("c", bar.getInt("c") + sample.getInt("c")); if (sample.has("s")) { JSONArray children = sample.getJSONArray("s"); - for (Object child : children) { - buildHistogram((JSONObject) child, bars); + for (Object childId : children) { + samples.add(owner.sampleDataForId((Integer)childId)); } } } diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index 183deb9358c4..147741f9184b 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -31,8 +31,8 @@ function fg_init(evt) { flamegraph = document.getElementById("flamegraph"); search_matches = []; fg_xmin = 0; - fg_xmax = profileData.h; - fg_zoomed_sample = profileData; + fg_xmax = profileData[0].h; + fg_zoomed_sample = profileData[0]; var el = flamegraph.getElementsByTagName("g"); for(let i=0;i id) { - for (let j = 0; j < i - 1; j++) { - unrelated.push(children[j]); - } - for (let j = i; j < children.length; j++) { - unrelated.push(children[j]); - } - return find_sample_in_tree(children[i - 1], id, parents, unrelated); +function find_sample_in_tree(id, parents, unrelated) { + let result = profileData[id]; + let sample = result; + let parent = sample.p + while (parent != null) { + parents.push(profileData[parent]); + for (const sibling of profileData[parent].s) { + if (sibling != sample.id) { + unrelated.push(profileData[sibling]); } } - for (let j = 0; j < children.length - 1; j++) { - unrelated.push(children[j]); - } - return find_sample_in_tree(children[children.length - 1], id, parents, unrelated); + sample = profileData[parent]; + parent = sample.p; } - return null; + return result; } function validate_no_overlap(sample, parents, unrelated) { @@ -149,12 +133,12 @@ function validate_no_overlap(sample, parents, unrelated) { function sample_parents_and_unrelated_for_id(id) { let parents = []; let unrelated = []; - let result = [find_sample_in_tree(profileData, id, parents, unrelated), parents, unrelated]; + let result = [find_sample_in_tree(id, parents, unrelated), parents, unrelated]; return result } function sample_for_id(id) { - return find_sample_in_tree(profileData, id, [], []); + return profileData[id]; } function depth_for_id_in_tree(tree, id) { @@ -176,7 +160,7 @@ function depth_for_id_in_tree(tree, id) { function depth_for_sample(sample) { if (!sample.hasOwnProperty("depth")) { - sample.depth = depth_for_id_in_tree(profileData, sample.id); + sample.depth = depth_for_id_in_tree(profileData[0], sample.id); } return sample.depth; } @@ -191,16 +175,11 @@ function sample_and_children_depth_first(sample) { let result = stack.pop(); let rdepth = depth_for_sample(result); - if (result.hasOwnProperty("s")) { - let children = result.s.slice(); - children.reverse(); - - for(const child of children) { - if (!child.hasOwnProperty("depth")) { - child.depth = rdepth + 1; - } - stack.push(child); + for(const child of direct_children(result).reverse()) { + if (!child.hasOwnProperty("depth")) { + child.depth = rdepth + 1; } + stack.push(child); } return {value: result, done: false} } @@ -208,6 +187,17 @@ function sample_and_children_depth_first(sample) { } } +function direct_children(sample) { + let result = []; + if (sample.hasOwnProperty("s")) { + for (const childId of sample["s"]) { + let child = sample_for_id(childId); + result.push(child); + } + } + return result; +} + function title(e) { if (e.getAttribute("class") == "func_g") { return name_for_sample(sample_for_id(e.getAttribute("id").substring(2))); diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js index c667fc396646..fcd2a3a8a1f5 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js @@ -251,10 +251,8 @@ function calculate_histogram_bars(bars, sample) { } bar["i"] = bar["i"] + sample["i"]; bar["c"] = bar["c"] + sample["c"]; - if (sample.hasOwnProperty("s")) { - for (const child of sample["s"]) { - calculate_histogram_bars(bars, child); - } + for (const child of direct_children(sample)) { + calculate_histogram_bars(bars, child); } } From 632fcaaa5e0b3ed88ccea78a714d440fe1d22218 Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 28 Sep 2021 18:16:48 +0100 Subject: [PATCH 243/681] Implement zooming of graph with collapsed recursive calls.! --- .../profiler/impl/resources/flamegraph.js | 71 ++++++++++++++++--- .../profiler/impl/resources/graphowner.js | 66 ++++++++++++++++- .../profiler/impl/resources/histogram.js | 16 +++-- 3 files changed, 137 insertions(+), 16 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index 147741f9184b..acb84429a389 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -23,13 +23,14 @@ * questions. */ -var flamegraph, flamegraph_details, search_matches, fg_xmin, fg_xmax, fg_zoomed_sample, fg_max_depth, fg_svg; +var flamegraph, flamegraph_details, search_matches, fg_xmin, fg_xmax, fg_zoomed_sample, fg_max_depth, fg_svg, fg_collapsed; function fg_init(evt) { flamegraph_details = document.getElementById("details").firstChild; searchbtn = document.getElementById("search"); matchedtxt = document.getElementById("matched"); flamegraph = document.getElementById("flamegraph"); search_matches = []; + fg_collapsed = true; fg_xmin = 0; fg_xmax = profileData[0].h; fg_zoomed_sample = profileData[0]; @@ -49,7 +50,7 @@ function fg_element_for_sample(sample) { } function fg_create_element_for_sample(sample, width, x) { - let y = (depth_for_sample(sample) + 1) * -fg_frameheight - fg_bottom_padding; + let y = fg_y_for_sample(sample); let e = document.createElementNS("http://www.w3.org/2000/svg", "g"); e.className.baseVal = "func_g"; e.onmouseover = function(e) {s(this)}; @@ -89,10 +90,42 @@ function fg_create_element_for_sample(sample, width, x) { return e; } +function fg_x_for_sample(sample) { + if (fg_collapsed) { + return (sample.rx - fg_xmin) / (fg_xmax - fg_xmin) * (fg_width - 2 * xpad) + xpad; + } else { + return (sample.x - fg_xmin) / (fg_xmax - fg_xmin) * (fg_width - 2 * xpad) + xpad; + } +} + +function fg_y_for_sample(sample) { + if (fg_collapsed) { + return (collapsed_depth_for_sample(sample) + 1) * -fg_frameheight - fg_bottom_padding; + } else { + return (depth_for_sample(sample) + 1) * -fg_frameheight - fg_bottom_padding; + } +} + +function fg_sample_and_children_depth_first(sample) { + if (fg_collapsed) { + return collapsed_sample_and_children_depth_first(sample); + } else { + return sample_and_children_depth_first(sample); + } +} + +function fg_width_for_sample(sample) { + if (fg_collapsed) { + return sample.rh / (fg_xmax - fg_xmin) * (fg_width - 2 * xpad); + } else { + return sample.h / (fg_xmax - fg_xmin) * (fg_width - 2 * xpad); + } +} + // zoom function zoom_child(sample) { - let width = sample.h / (fg_xmax - fg_xmin) * (fg_width - 2 * xpad); - let x = (sample.x - fg_xmin) / (fg_xmax - fg_xmin) * (fg_width - 2 * xpad) + xpad; + let width = fg_width_for_sample(sample); + let x = fg_x_for_sample(sample); let e = fg_element_for_sample(sample); if (width < fg_min_width) { @@ -119,9 +152,22 @@ function zoom_child(sample) { let name = name_for_sample(sample); let source = source_for_sample(sample); + let compiled = 0; + let interpreted = 0; + let hits = 0; + if (fg_collapsed) { + compiled = sample.rc; + interpreted = sample.ri; + hits = sample.rh; + } else { + compiled = sample.c; + interpreted = sample.i; + hits = sample.h; + } + title.textContent = name + " (" + languageNames[sample.l] + ")\n" + - "Self samples: " + (sample.i + sample.c) + " (" + (100 * (sample.c + sample.i) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + - "Total samples: " + (sample.h) + " (" + (100 * (sample.h + sample.i) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + + "Self samples: " + (interpreted + compiled) + " (" + (100 * (compiled + interpreted) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + + "Total samples: " + (hits) + " (" + (100 * (hits) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + "Source location: " + source + ":" + sample.fl + "\n"; r.x.baseVal.value = x; @@ -162,8 +208,13 @@ function zoom(node) { let parents = data[1]; let unrelated = data[2]; fg_zoomed_sample = sample; - fg_xmin = sample.x; - fg_xmax = sample.x + sample.h; + if (fg_collapsed) { + fg_xmin = sample.rx; + fg_xmax = sample.rx + sample.rh; + } else { + fg_xmin = sample.x; + fg_xmax = sample.x + sample.h; + } fg_max_depth = 0; var unzoombtn = document.getElementById("unzoom"); @@ -191,7 +242,7 @@ function fg_canvas_resize() { function zoom_internal(sample, parents, unrelated) { for (const u of unrelated) { - let iter = sample_and_children_depth_first(u); + let iter = fg_sample_and_children_depth_first(u); let c = iter.next(); while (!c.done) { let e = fg_element_for_sample(c.value); @@ -204,7 +255,7 @@ function zoom_internal(sample, parents, unrelated) { for (const p of parents) { zoom_parent(p); } - let iter = sample_and_children_depth_first(sample); + let iter = fg_sample_and_children_depth_first(sample); let c = iter.next(); while (!c.done) { zoom_child(c.value); diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index 553e8bc00d4c..39a0bc08ed9d 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -35,8 +35,13 @@ function s(node) { // show let name = name_for_sample(sample) let details = name + " (" + languageNames[sample.l] + ") - "; if (sample.hasOwnProperty("h")) { - details = details + "(Self:" + (sample.i + sample.c) + " samples " + - "Total: " + (sample.h) + " samples)"; + if (fg_collapsed) { + details = details + "(Self:" + (sample.ri + sample.rc) + " samples " + + "Total: " + (sample.rh) + " samples)"; + } else { + details = details + "(Self:" + (sample.i + sample.c) + " samples " + + "Total: " + (sample.h) + " samples)"; + } } else { details = details + "(" + (sample.i + sample.c) + " samples)"; } @@ -158,6 +163,23 @@ function depth_for_id_in_tree(tree, id) { return -1; } +function collapsed_depth_for_id_in_tree(tree, id) { + if (tree.id == id) { + return 0; + } else if (tree.hasOwnProperty('ss')) { + let children = tree.rs; + for (let i = 0; i < children.length; i++) { + if (children[i].id == id) { + return 1; + } else if(children[i].id > id) { + return 1 + depth_for_id_in_tree(children[i - 1], id); + } + } + return 1 + depth_for_id_in_tree(children[children.length - 1], id); + } + return -1; +} + function depth_for_sample(sample) { if (!sample.hasOwnProperty("depth")) { sample.depth = depth_for_id_in_tree(profileData[0], sample.id); @@ -165,6 +187,13 @@ function depth_for_sample(sample) { return sample.depth; } +function collapsed_depth_for_sample(sample) { + if (!sample.hasOwnProperty("rdepth")) { + sample.depth = collapsed_depth_for_id_in_tree(profileData[0], sample.id); + } + return sample.depth; +} + function sample_and_children_depth_first(sample) { let stack = [sample]; return { @@ -187,6 +216,28 @@ function sample_and_children_depth_first(sample) { } } +function collapsed_sample_and_children_depth_first(sample) { + let stack = [sample]; + return { + next: function() { + if (stack.length == 0) { + return {value: null, done: true} + } else { + let result = stack.pop(); + + let rdepth = depth_for_sample(result); + for(const child of collapsed_children(result).reverse()) { + if (!child.hasOwnProperty("depth")) { + child.depth = rdepth + 1; + } + stack.push(child); + } + return {value: result, done: false} + } + } + } +} + function direct_children(sample) { let result = []; if (sample.hasOwnProperty("s")) { @@ -198,6 +249,17 @@ function direct_children(sample) { return result; } +function collapsed_children(sample) { + let result = []; + if (sample.hasOwnProperty("rs")) { + for (const childId of sample["rs"]) { + let child = sample_for_id(childId); + result.push(child); + } + } + return result; +} + function title(e) { if (e.getAttribute("class") == "func_g") { return name_for_sample(sample_for_id(e.getAttribute("id").substring(2))); diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js index fcd2a3a8a1f5..206d980a3285 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js @@ -249,10 +249,18 @@ function calculate_histogram_bars(bars, sample) { } else { bar = bars[sample["n"]]; } - bar["i"] = bar["i"] + sample["i"]; - bar["c"] = bar["c"] + sample["c"]; - for (const child of direct_children(sample)) { - calculate_histogram_bars(bars, child); + if (fg_collapsed) { + bar["i"] = bar["i"] + sample["ri"]; + bar["c"] = bar["c"] + sample["rc"]; + for (const child of collapsed_children(sample)) { + calculate_histogram_bars(bars, child); + } + } else { + bar["i"] = bar["i"] + sample["i"]; + bar["c"] = bar["c"] + sample["c"]; + for (const child of direct_children(sample)) { + calculate_histogram_bars(bars, child); + } } } From a04cb30c6c1cb810738109d64064f29c8535c5fc Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Wed, 29 Sep 2021 12:19:11 +0100 Subject: [PATCH 244/681] Add ability to toggle collapse of recursive calls. --- .../profiler/impl/resources/flamegraph.js | 36 +++++++++++ .../profiler/impl/resources/graphowner.js | 62 ++++++++----------- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index acb84429a389..948ca1d98831 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -90,6 +90,34 @@ function fg_create_element_for_sample(sample, width, x) { return e; } +function fg_toggle_collapse() { + // Hide all the existing elements + let iter = fg_sample_and_children_depth_first(profileData[0]); + let c = iter.next(); + while (!c.done) { + let e = fg_element_for_sample(c.value); + if (e != null) { + e.style["display"] = "none"; + } + c = iter.next(); + } + // Find the correct element to zoom to + let sample_to_zoom_to = fg_zoomed_sample; + if (!fg_collapsed && fg_zoomed_sample.hasOwnProperty("ro")) { + sample_to_zoom_to = profileData[fg_zoomed_sample.ro]; + } + + // Toggle fg_collapsed + fg_collapsed = !fg_collapsed; + + // Zoom to the correct element + if (sample_to_zoom_to == profileData[0]) { + unzoom(); + } else { + zoom(fg_element_for_sample(sample_to_zoom_to)); + } +} + function fg_x_for_sample(sample) { if (fg_collapsed) { return (sample.rx - fg_xmin) / (fg_xmax - fg_xmin) * (fg_width - 2 * xpad) + xpad; @@ -126,6 +154,7 @@ function fg_width_for_sample(sample) { function zoom_child(sample) { let width = fg_width_for_sample(sample); let x = fg_x_for_sample(sample); + let y = fg_y_for_sample(sample); let e = fg_element_for_sample(sample); if (width < fg_min_width) { @@ -171,7 +200,9 @@ function zoom_child(sample) { "Source location: " + source + ":" + sample.fl + "\n"; r.x.baseVal.value = x; + r.y.baseVal.value = y; t.x.baseVal[0].value = x + 3; + t.y.baseVal[0].value = y - 5 + fg_frameheight; r.width.baseVal.value = width; update_text_parts(e, r, t, width - 3, name); @@ -180,6 +211,7 @@ function zoom_child(sample) { function zoom_parent(sample) { let width = fg_width - 2 * xpad; let x = xpad; + let y = fg_y_for_sample(sample); let e = fg_element_for_sample(sample); if (e != null) { e.style["display"] = "block"; @@ -194,7 +226,9 @@ function zoom_parent(sample) { " Parent of displayed sample range.\n"; r.x.baseVal.value = x; + r.y.baseVal.value = y; t.x.baseVal[0].value = x + 3; + t.y.baseVal[0].value = y - 5 + fg_frameheight; r.width.baseVal.value = width; @@ -428,3 +462,5 @@ function fg_resize(new_width) { document.getElementById("search").setAttribute("x", new_width - xpad); } + +graph_register_handler("r", "Toggle collapse of recursive calls", fg_toggle_collapse); diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index 39a0bc08ed9d..9b7535609933 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -146,52 +146,40 @@ function sample_for_id(id) { return profileData[id]; } -function depth_for_id_in_tree(tree, id) { - if (tree.id == id) { - return 0; - } else if (tree.hasOwnProperty('s')) { - let children = tree.s; - for (let i = 0; i < children.length; i++) { - if (children[i].id == id) { - return 1; - } else if(children[i].id > id) { - return 1 + depth_for_id_in_tree(children[i - 1], id); - } - } - return 1 + depth_for_id_in_tree(children[children.length - 1], id); - } - return -1; -} - -function collapsed_depth_for_id_in_tree(tree, id) { - if (tree.id == id) { - return 0; - } else if (tree.hasOwnProperty('ss')) { - let children = tree.rs; - for (let i = 0; i < children.length; i++) { - if (children[i].id == id) { - return 1; - } else if(children[i].id > id) { - return 1 + depth_for_id_in_tree(children[i - 1], id); - } - } - return 1 + depth_for_id_in_tree(children[children.length - 1], id); - } - return -1; -} - function depth_for_sample(sample) { if (!sample.hasOwnProperty("depth")) { - sample.depth = depth_for_id_in_tree(profileData[0], sample.id); + let parent = profileData[sample.p]; + let depth = 0; + while (parent != null) { + if (parent.hasOwnProperty("depth")) { + depth += parent.depth + 1; + break; + } else { + depth += 1; + } + parent = profileData[sample.p]; + } + sample.depth = depth; } return sample.depth; } function collapsed_depth_for_sample(sample) { if (!sample.hasOwnProperty("rdepth")) { - sample.depth = collapsed_depth_for_id_in_tree(profileData[0], sample.id); + let parent = profileData[sample.rp]; + let depth = 0; + while (parent != null) { + if (parent.hasOwnProperty("rdepth")) { + depth += parent.rdepth + 1; + break; + } else { + depth += 1; + } + parent = profileData[sample.rp]; + } + sample.rdepth = depth; } - return sample.depth; + return sample.rdepth; } function sample_and_children_depth_first(sample) { From 1c86e4dd466618b336f6febf361b96d23ee6a949 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 30 Sep 2021 17:36:28 +0200 Subject: [PATCH 245/681] Fix bug in AArch64NodeMatchRules. --- .../core/aarch64/AArch64NodeMatchRules.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java index 4b5aab8615c5..dfcdd241c4b8 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java @@ -55,6 +55,7 @@ import org.graalvm.compiler.nodes.calc.AndNode; import org.graalvm.compiler.nodes.calc.BinaryNode; import org.graalvm.compiler.nodes.calc.FloatConvertNode; +import org.graalvm.compiler.nodes.calc.IntegerConvertNode; import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; import org.graalvm.compiler.nodes.calc.LeftShiftNode; import org.graalvm.compiler.nodes.calc.MulNode; @@ -152,6 +153,20 @@ protected AArch64Kind getMemoryKind(MemoryAccess access) { return (AArch64Kind) gen.getLIRKind(((ValueNode) access).stamp(NodeView.DEFAULT)).getPlatformKind(); } + private static boolean isSupportedExtendedAddSubShift(IntegerConvertNode node, int clampedShiftAmt) { + assert clampedShiftAmt >= 0; + if (clampedShiftAmt <= 4) { + switch (node.getInputBits()) { + case Byte.SIZE: + case Short.SIZE: + case Integer.SIZE: + case Long.SIZE: + return true; + } + } + return false; + } + private static ExtendType getZeroExtendType(int fromBits) { switch (fromBits) { case Byte.SIZE: @@ -300,7 +315,7 @@ private ComplexMatchResult emitExtendedAddSubShift(BinaryNode op, ValueNode x, V public ComplexMatchResult mergeSignExtendByShiftIntoAddSub(BinaryNode op, LeftShiftNode lshift, ValueNode ext, ValueNode x, ValueNode y) { assert isNumericInteger(lshift); int shiftAmt = getClampedShiftAmt(lshift); - if (shiftAmt > 4) { + if (!isSupportedExtendedAddSubShift((IntegerConvertNode) ext, shiftAmt)) { return null; } ExtendType extType; @@ -390,7 +405,7 @@ public ComplexMatchResult extendedPointerAddShift(AArch64PointerAddNode addP) { zeroExtend = (ZeroExtendNode) shift.getX(); shiftAmt = getClampedShiftAmt(shift); } - if (shiftAmt > 4) { + if (!isSupportedExtendedAddSubShift(zeroExtend, shiftAmt)) { return null; } @@ -849,6 +864,10 @@ public ComplexMatchResult mergeDowncastIntoAddSub(BinaryNode op, ValueNode x, Va @MatchRule("(Add=op x (ZeroExtend=ext y))") @MatchRule("(Sub=op x (ZeroExtend=ext y))") public ComplexMatchResult mergeSignExtendIntoAddSub(BinaryNode op, UnaryNode ext, ValueNode x, ValueNode y) { + if (!isSupportedExtendedAddSubShift((IntegerConvertNode) ext, 0)) { + return null; + } + ExtendType extType; if (ext instanceof SignExtendNode) { extType = getSignExtendType(((SignExtendNode) ext).getInputBits()); From 0597be9e2c78ff999008aee3151e0ec5fb962a31 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Thu, 30 Sep 2021 15:56:25 +0200 Subject: [PATCH 246/681] [GR-34118] Add a unique id into Message. --- truffle/CHANGELOG.md | 2 + .../truffle/api/dsl/test/MessageIdTest.java | 80 +++++++++++++++++++ .../snapshot.sigtest | 6 +- .../truffle/api/library/LibraryFactory.java | 8 +- .../oracle/truffle/api/library/Message.java | 29 ++++++- .../processor/library/LibraryGenerator.java | 9 ++- 6 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MessageIdTest.java diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 9271dad7a637..bdaab814aead 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -4,6 +4,8 @@ This changelog summarizes major changes between Truffle versions relevant to lan ## Version 22.0.0 * Truffle DSL generated code now inherits all annotations on constructor parameters to the static create factory method. +* Added a [Message#getId()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/library/Message.html#getId--) method returning a unique message id within a library. +* Added a [LibraryFactory#getMessages()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/library/LibraryFactory.html#getMessages--) method returning a list of messages that the library provides. * Changed behavior of `RootNode#getCallTarget()` such that it lazily initializes its call target. This enforces a one-to-one relationship between root nodes and call targets, which avoids several problems, for example, with regard to instrumentation. As a consequence, `RootNode.setCallTarget()` is deprecated and so will be `TruffleRuntime#createCallTarget()` soon. Please use `RootNode#getCallTarget()` to access the call target of a root node from now on. diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MessageIdTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MessageIdTest.java new file mode 100644 index 000000000000..6357cb9fa5f2 --- /dev/null +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MessageIdTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.api.dsl.test; + +import com.oracle.truffle.api.library.GenerateLibrary; +import com.oracle.truffle.api.library.Library; +import com.oracle.truffle.api.library.LibraryFactory; +import com.oracle.truffle.api.library.Message; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class MessageIdTest { + + @Test + public void testMessageIds() { + List messages = MessageIdTestLibrary.FACTORY.getMessages(); + assertEquals(5, messages.size()); + int id = 0; + for (Message message : messages) { + assertEquals(id++, message.getId()); + } + } + + @GenerateLibrary + public abstract static class MessageIdTestLibrary extends Library { + + static final LibraryFactory FACTORY = LibraryFactory.resolve(MessageIdTestLibrary.class); + + public abstract void m0(Object receiver); + + public abstract void m1(Object receiver); + + public abstract void m2(Object receiver); + + public abstract void m3(Object receiver); + + public abstract void m4(Object receiver); + } +} diff --git a/truffle/src/com.oracle.truffle.api.library/snapshot.sigtest b/truffle/src/com.oracle.truffle.api.library/snapshot.sigtest index 16c766e56f72..1e596bba3c92 100644 --- a/truffle/src/com.oracle.truffle.api.library/snapshot.sigtest +++ b/truffle/src/com.oracle.truffle.api.library/snapshot.sigtest @@ -146,6 +146,7 @@ meth protected static boolean isDelegated(com.oracle.truffle.api.library.Library meth protected static java.lang.Object readDelegate(com.oracle.truffle.api.library.Library,java.lang.Object) meth protected {com.oracle.truffle.api.library.LibraryFactory%0} createAssertions({com.oracle.truffle.api.library.LibraryFactory%0}) meth protected {com.oracle.truffle.api.library.LibraryFactory%0} createDelegate({com.oracle.truffle.api.library.LibraryFactory%0}) +meth public final java.util.List getMessages() meth public final {com.oracle.truffle.api.library.LibraryFactory%0} create(java.lang.Object) meth public final {com.oracle.truffle.api.library.LibraryFactory%0} createDispatched(int) meth public final {com.oracle.truffle.api.library.LibraryFactory%0} getUncached() @@ -157,10 +158,13 @@ hfds EMPTY_DEFAULT_EXPORT_ARRAY,LIBRARIES,UNSAFE,afterBuiltinDefaultExports,aot, hcls CachedAOTExports,ProxyExports,ResolvedDispatch CLSS public abstract com.oracle.truffle.api.library.Message +cons protected !varargs init(java.lang.Class,java.lang.String,int,java.lang.Class,java.lang.Class[]) cons protected !varargs init(java.lang.Class,java.lang.String,java.lang.Class,java.lang.Class[]) + anno 0 java.lang.Deprecated() meth protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException meth public final boolean equals(java.lang.Object) meth public final com.oracle.truffle.api.library.LibraryFactory getFactory() +meth public final int getId() meth public final int getParameterCount() meth public final int hashCode() meth public final java.lang.Class getLibraryClass() @@ -175,7 +179,7 @@ meth public final java.util.List> getParameterTypes() meth public static com.oracle.truffle.api.library.Message resolve(java.lang.Class,java.lang.String) meth public static com.oracle.truffle.api.library.Message resolve(java.lang.Class,java.lang.String,boolean) supr java.lang.Object -hfds hash,library,libraryClass,parameterCount,parameterTypes,parameterTypesArray,qualifiedName,returnType,simpleName +hfds hash,id,library,libraryClass,parameterCount,parameterTypes,parameterTypesArray,qualifiedName,returnType,simpleName CLSS public abstract com.oracle.truffle.api.library.ReflectionLibrary cons protected init() diff --git a/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/LibraryFactory.java b/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/LibraryFactory.java index 25bb275a75bf..3808e816f022 100644 --- a/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/LibraryFactory.java +++ b/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/LibraryFactory.java @@ -488,7 +488,13 @@ final Class getLibraryClass() { return libraryClass; } - final List getMessages() { + /** + * Returns an unmodifiable list of messages that this library provides. The returned list is + * ordered by {@link Message#getId() message ids}. + * + * @since 22.0 + */ + public final List getMessages() { return messages; } diff --git a/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/Message.java b/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/Message.java index 550b90236016..6b4ecc97e575 100644 --- a/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/Message.java +++ b/truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/Message.java @@ -72,6 +72,7 @@ public abstract class Message { private final String simpleName; private final String qualifiedName; + private final int id; private final int hash; private final Class returnType; private final Class libraryClass; @@ -82,9 +83,24 @@ public abstract class Message { /** * @since 19.0 + * @deprecated Use {@link #Message(Class, String, int, Class, Class[])}. */ - @SuppressWarnings("unchecked") + @Deprecated protected Message(Class libraryClass, String messageName, Class returnType, Class... parameterTypes) { + this(libraryClass, -1, messageName, returnType, parameterTypes); + } + + /** + * @since 22.0 + */ + protected Message(Class libraryClass, String messageName, int id, Class returnType, Class... parameterTypes) { + this(libraryClass, id, messageName, returnType, parameterTypes); + if (id < 0) { + throw new IllegalArgumentException("Id must be non-negative."); + } + } + + private Message(Class libraryClass, int id, String messageName, Class returnType, Class... parameterTypes) { Objects.requireNonNull(libraryClass); Objects.requireNonNull(messageName); Objects.requireNonNull(returnType); @@ -94,10 +110,21 @@ protected Message(Class libraryClass, String messageName, Cla this.parameterTypesArray = parameterTypes; this.parameterTypes = Collections.unmodifiableList(Arrays.asList(parameterTypes)); this.qualifiedName = (getLibraryName() + "." + simpleName).intern(); + this.id = id; this.parameterCount = parameterTypes.length; this.hash = qualifiedName.hashCode(); } + /** + * Returns a unique message id within a library. + * + * @return a non-negative message id or {@code -1} if the message is not assigned a unique id. + * @since 22.0 + */ + public final int getId() { + return id; + } + /** * Returns a qualified and unique name of this message. The qualified name is specified as * getLibraryName() + "." + getSimpleName(). The returned name is diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/LibraryGenerator.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/LibraryGenerator.java index 1b9fe1d02076..9bb8b16f04d2 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/LibraryGenerator.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/LibraryGenerator.java @@ -148,12 +148,13 @@ public List create(ProcessorContext context1, AnnotationProcess CodeTreeBuilder statics = staticsMethod.createBuilder(); List methods = new ArrayList<>(); - for (int messageIndex = 0; messageIndex < model.getMethods().size(); messageIndex++) { - LibraryMessage message = model.getMethods().get(messageIndex); + int messageIndex = 0; + for (LibraryMessage message : model.getMethods()) { if (message.hasErrors()) { continue; } - MessageObjects objects = new MessageObjects(message, messageIndex); + int useIndex = message.getName().equals(ACCEPTS) ? -1 : messageIndex++; + MessageObjects objects = new MessageObjects(message, useIndex); methods.add(objects); } @@ -208,7 +209,7 @@ public List create(ProcessorContext context1, AnnotationProcess messageConstructor.addParameter(new CodeVariableElement(context.getType(Class[].class), "parameters")); messageConstructor.setVarArgs(true); builder = messageConstructor.createBuilder(); - builder.startStatement().startSuperCall().staticReference(libraryClassLiteral).string("name").string("returnType").string("parameters").end().end(); + builder.startStatement().startSuperCall().staticReference(libraryClassLiteral).string("name").string("index").string("returnType").string("parameters").end().end(); builder.statement("this.index = index"); messageClass.add(messageConstructor); genClass.add(messageClass); From be876d6f8aa511fa16a2bb51bc5d2e2806a64605 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Thu, 30 Sep 2021 18:10:35 +0200 Subject: [PATCH 247/681] Replaced index by Message#getId(). --- .../dsl/processor/library/LibraryGenerator.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/LibraryGenerator.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/LibraryGenerator.java index 9bb8b16f04d2..f028fa0d27e0 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/LibraryGenerator.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/LibraryGenerator.java @@ -201,7 +201,6 @@ public List create(ProcessorContext context1, AnnotationProcess // class MessageImpl final CodeTypeElement messageClass = createClass(model, null, modifiers(PRIVATE, STATIC), "MessageImpl", types.Message); - messageClass.add(new CodeVariableElement(modifiers(FINAL), context.getType(int.class), "index")); CodeExecutableElement messageConstructor = new CodeExecutableElement(modifiers(), null, messageClass.getSimpleName().toString()); messageConstructor.addParameter(new CodeVariableElement(context.getType(String.class), "name")); messageConstructor.addParameter(new CodeVariableElement(context.getType(int.class), "index")); @@ -210,7 +209,6 @@ public List create(ProcessorContext context1, AnnotationProcess messageConstructor.setVarArgs(true); builder = messageConstructor.createBuilder(); builder.startStatement().startSuperCall().staticReference(libraryClassLiteral).string("name").string("index").string("returnType").string("parameters").end().end(); - builder.statement("this.index = index"); messageClass.add(messageConstructor); genClass.add(messageClass); @@ -353,7 +351,7 @@ public List create(ProcessorContext context1, AnnotationProcess builder.end().startBlock(); builder.startStatement(); - builder.string("bitSet.set(((").type(messageClass.asType()).string(") message).index)"); + builder.string("bitSet.set(message.getId())"); builder.end(); builder.end(); // for @@ -453,7 +451,7 @@ public List create(ProcessorContext context1, AnnotationProcess delegateIsAdoptable.createBuilder().startReturn().string("this.delegateLibrary.isAdoptable()").end(); delegateClass.add(delegateIsAdoptable); - genClass.add(createGenericDispatch(methods, messageClass)); + genClass.add(createGenericDispatch(methods)); // CachedToUncachedDispatchNode final CodeTypeElement cachedToUncached = createClass(model, null, modifiers(PRIVATE, STATIC, FINAL), "CachedToUncachedDispatch", libraryTypeMirror); @@ -872,7 +870,7 @@ private CodeAnnotationMirror createExplodeLoop() { return new CodeAnnotationMirror(types.ExplodeLoop); } - private CodeExecutableElement createGenericDispatch(List methods, CodeTypeElement messageClass) { + private CodeExecutableElement createGenericDispatch(List methods) { CodeTreeBuilder builder; CodeExecutableElement reflectionGenericDispatch = GeneratorUtils.override(types.LibraryFactory, "genericDispatch"); reflectionGenericDispatch.getParameters().set(0, new CodeVariableElement(types.Library, "library")); @@ -880,13 +878,12 @@ private CodeExecutableElement createGenericDispatch(List methods reflectionGenericDispatch.getModifiers().remove(ABSTRACT); builder = reflectionGenericDispatch.createBuilder(); builder.declaration(model.getTemplateType().asType(), "lib", builder.create().cast(model.getTemplateType().asType()).string("originalLib")); - builder.declaration(messageClass.asType(), "messageImpl", builder.create().cast(messageClass.asType()).string("message").build()); - builder.startIf().string("messageImpl.getParameterCount() - 1 != args.length - offset").end().startBlock(); + builder.startIf().string("message.getParameterCount() - 1 != args.length - offset").end().startBlock(); builder.startStatement().startStaticCall(types.CompilerDirectives, "transferToInterpreterAndInvalidate").end().end(); builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Invalid number of arguments.").end().end(); builder.end(); boolean uncheckedCast = false; - builder.startSwitch().string("messageImpl.index").end().startBlock(); + builder.startSwitch().string("message.getId()").end().startBlock(); for (MessageObjects message : methods) { if (message.model.getName().equals(ACCEPTS)) { continue; From 0bd2ac06f2c80779fe917e0d081e83601d561b1f Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Thu, 30 Sep 2021 18:14:01 +0200 Subject: [PATCH 248/681] Enforce that only CHA oracle can retrieve the leafTypeAssumption from ObjectKlass --- .../analysis/hierarchy/ClassHierarchyOracle.java | 5 +++++ .../hierarchy/DefaultClassHierarchyOracle.java | 4 ++-- .../hierarchy/NoOpClassHierarchyOracle.java | 4 +++- .../oracle/truffle/espresso/impl/ObjectKlass.java | 15 ++++++++++----- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java index 384aa24312d2..08024f645908 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java @@ -34,6 +34,11 @@ * The oracle is only valid within an {@link EspressoContext}. */ public interface ClassHierarchyOracle { + final class LeafTypeAssumptionAccessor { + protected LeafTypeAssumptionAccessor() { + } + } + /** * Must be called to initialize {@code leafTypeAssumption} of {@code newKlass}. * diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java index 09cf21c0ab2c..b4a5a210d7c6 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java @@ -50,8 +50,8 @@ public LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass) { @Override public void onClassInit(ObjectKlass newClass) { ObjectKlass currentParent = newClass.getSuperKlass(); - while (currentParent != null && currentParent.getLeafTypeAssumption().getAssumption().isValid()) { - currentParent.getLeafTypeAssumption().getAssumption().invalidate(); + while (currentParent != null && currentParent.getLeafTypeAssumption(assumptionAccessor).getAssumption().isValid()) { + currentParent.getLeafTypeAssumption(assumptionAccessor).getAssumption().invalidate(); currentParent = currentParent.getSuperKlass(); } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java index aad597b94058..2ce82a93b037 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java @@ -53,6 +53,8 @@ public Assumption getAssumption() { } } + protected static final LeafTypeAssumptionAccessor assumptionAccessor = new LeafTypeAssumptionAccessor(); + protected static final LeafTypeAssumption FinalIsAlwaysLeaf = new LeafTypeAssumptionImpl("final class is always a CHA leaf"); protected static final LeafTypeAssumption NotLeaf = LeafTypeAssumptionImpl.AlwaysInvalid; @@ -70,6 +72,6 @@ public void onClassInit(ObjectKlass newKlass) { @Override public LeafTypeAssumption isLeafClass(ObjectKlass klass) { - return klass.getLeafTypeAssumption(); + return klass.getLeafTypeAssumption(assumptionAccessor); } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java index 8cae9b3c347a..c109eec11332 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java @@ -36,6 +36,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.logging.Level; @@ -46,6 +47,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.espresso.analysis.hierarchy.ClassHierarchyOracle.LeafTypeAssumptionAccessor; import com.oracle.truffle.espresso.analysis.hierarchy.LeafTypeAssumption; import com.oracle.truffle.espresso.analysis.hierarchy.ClassHierarchyOracle; import com.oracle.truffle.espresso.classfile.ConstantPool; @@ -1406,12 +1408,15 @@ public void removeByRedefinition() { } /** - * @return the assumption, indicating if this class is a leaf in class hierarchy. This - * assumption must only be used by {@link ClassHierarchyOracle}, other users must use - * {@link ClassHierarchyOracle#isLeafClass(ObjectKlass)}. The assumption is stored in - * ObjectKlass for easy mapping between classes and corresponding assumptions. + * This getter must only be used by {@link ClassHierarchyOracle}, which is ensured by + * {@code assumptionAccessor}. The assumption is stored in ObjectKlass for easy mapping between + * classes and corresponding assumptions. + * + * @see ClassHierarchyOracle#isLeafClass(ObjectKlass) + * @return the assumption, indicating if this class is a leaf in class hierarchy. */ - public LeafTypeAssumption getLeafTypeAssumption() { + public LeafTypeAssumption getLeafTypeAssumption(LeafTypeAssumptionAccessor assumptionAccessor) { + Objects.requireNonNull(assumptionAccessor); return leafTypeAssumption; } From 7c810c82f05efe198b9fd3143b2aeedc5831e3cf Mon Sep 17 00:00:00 2001 From: jovanstevanovic Date: Fri, 16 Jul 2021 13:38:38 +0200 Subject: [PATCH 249/681] Added support to register/access resource with trailing slash. --- .../com/oracle/svm/core/jdk/Resources.java | 29 +++++++++++++++---- .../resources/NativeImageResourcePath.java | 4 +-- .../jdk/resources/ResourceURLConnection.java | 2 +- .../oracle/svm/hosted/ResourcesFeature.java | 13 ++++++--- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java index 82c9f433d685..7a365e2666c0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java @@ -31,13 +31,12 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; -import com.oracle.svm.core.jdk.resources.ResourceStorageEntry; -import com.oracle.svm.core.jdk.resources.ResourceURLConnection; import org.graalvm.collections.EconomicMap; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; @@ -45,6 +44,9 @@ import org.graalvm.nativeimage.hosted.Feature; import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.jdk.resources.NativeImageResourcePath; +import com.oracle.svm.core.jdk.resources.ResourceStorageEntry; +import com.oracle.svm.core.jdk.resources.ResourceURLConnection; import com.oracle.svm.core.util.ImageHeapMap; import com.oracle.svm.core.util.VMError; @@ -57,6 +59,8 @@ */ public final class Resources { + public static final char RESOURCES_INTERNAL_PATH_SEPARATOR = '/'; + public static Resources singleton() { return ImageSingletons.lookup(Resources.class); } @@ -121,6 +125,15 @@ public static void registerDirectoryResource(String resourceDirName, String cont addEntry(resourceDirName, true, content.getBytes()); } + /** + * Avoid pulling native file system by using {@link NativeImageResourcePath} implementation to + * convert resourceName to canonical variant. + */ + public static String toCanonicalForm(String resourceName) { + NativeImageResourcePath path = new NativeImageResourcePath(null, resourceName.getBytes(StandardCharsets.UTF_8), true); + return new String(NativeImageResourcePath.getResolved(path)); + } + public static ResourceStorageEntry get(String name) { return singleton().resources.get(name); } @@ -144,7 +157,8 @@ public static URL createURL(String resourceName) { if (resourceName == null) { return null; } - Enumeration urls = createURLs(resourceName); + + Enumeration urls = createURLs(toCanonicalForm(resourceName)); return urls.hasMoreElements() ? urls.nextElement() : null; } @@ -153,7 +167,8 @@ public static InputStream createInputStream(String resourceName) { if (resourceName == null) { return null; } - ResourceStorageEntry entry = Resources.get(resourceName); + + ResourceStorageEntry entry = Resources.get(toCanonicalForm(resourceName)); if (entry == null) { return null; } @@ -165,14 +180,16 @@ public static Enumeration createURLs(String resourceName) { if (resourceName == null) { return null; } - ResourceStorageEntry entry = Resources.get(resourceName); + + String canonicalResourceName = toCanonicalForm(resourceName); + ResourceStorageEntry entry = Resources.get(canonicalResourceName); if (entry == null) { return Collections.emptyEnumeration(); } int numberOfResources = entry.getData().size(); List resourcesURLs = new ArrayList<>(numberOfResources); for (int index = 0; index < numberOfResources; index++) { - resourcesURLs.add(createURL(resourceName, index)); + resourcesURLs.add(createURL(canonicalResourceName, index)); } return Collections.enumeration(resourcesURLs); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/NativeImageResourcePath.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/NativeImageResourcePath.java index 3c7bccdd5bac..f3a3b4b4a0de 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/NativeImageResourcePath.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/NativeImageResourcePath.java @@ -603,13 +603,13 @@ private byte[] getResolved() { } for (byte c : path) { if (c == '.') { - return doGetResolved(this); + return getResolved(this); } } return path; } - private static byte[] doGetResolved(NativeImageResourcePath p) { + public static byte[] getResolved(NativeImageResourcePath p) { int nc = p.getNameCount(); byte[] path = p.path; int[] offsets = p.offsets; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/ResourceURLConnection.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/ResourceURLConnection.java index 3aa271c5f30d..8733cd70f25c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/ResourceURLConnection.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/ResourceURLConnection.java @@ -63,7 +63,7 @@ public void connect() { connected = true; String resourceName = resolveName(url.getPath()); - ResourceStorageEntry entry = Resources.get(resourceName); + ResourceStorageEntry entry = Resources.get(Resources.toCanonicalForm(resourceName)); if (entry != null) { List bytes = entry.getData(); if (index < bytes.size()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java index 606dbf6322a4..fbdaa447b084 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java @@ -25,6 +25,8 @@ package com.oracle.svm.hosted; +import static com.oracle.svm.core.jdk.Resources.RESOURCES_INTERNAL_PATH_SEPARATOR; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -48,6 +50,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.oracle.svm.core.util.VMError; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; @@ -268,7 +271,7 @@ private static void scanDirectory(DebugContext debugContext, Path root, Pattern[ /* Resources always use / as the separator, as do our resource inclusion patterns */ String relativeFilePath; if (entry != root) { - relativeFilePath = root.relativize(entry).toString().replace(File.separatorChar, '/'); + relativeFilePath = root.relativize(entry).toString().replace(File.separatorChar, RESOURCES_INTERNAL_PATH_SEPARATOR); allEntries.add(relativeFilePath); } else { relativeFilePath = ""; @@ -291,7 +294,7 @@ private static void scanDirectory(DebugContext debugContext, Path root, Pattern[ } for (String entry : allEntries) { - int last = entry.lastIndexOf('/'); + int last = entry.lastIndexOf(RESOURCES_INTERNAL_PATH_SEPARATOR); String key = last == -1 ? "" : entry.substring(0, last); List dirContent = matchedDirectoryResources.get(key); if (dirContent != null && !dirContent.contains(entry)) { @@ -328,14 +331,16 @@ private static void scanJar(DebugContext debugContext, Path jarPath, Pattern[] i } private static boolean matches(Pattern[] includePatterns, Pattern[] excludePatterns, String relativePath) { + VMError.guarantee(!relativePath.contains("\\"), "Resource path contains backslash!"); + String relativePathWithTrailingSlash = relativePath + RESOURCES_INTERNAL_PATH_SEPARATOR; for (Pattern p : excludePatterns) { - if (p.matcher(relativePath).matches()) { + if (p.matcher(relativePath).matches() || p.matcher(relativePathWithTrailingSlash).matches()) { return false; } } for (Pattern p : includePatterns) { - if (p.matcher(relativePath).matches()) { + if (p.matcher(relativePath).matches() || p.matcher(relativePathWithTrailingSlash).matches()) { return true; } } From 684008e7ba9c0aac12fb719918cbbe4070ed0b2a Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Fri, 1 Oct 2021 10:33:03 +0200 Subject: [PATCH 250/681] Control CHA with a commandline flag. Disabled by default. --- .../com/oracle/truffle/espresso/EspressoOptions.java | 4 ++++ .../truffle/espresso/runtime/EspressoContext.java | 11 +++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java index cf2631d04a72..65b72e205d82 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java @@ -236,6 +236,10 @@ public VerifyMode apply(String s) { category = OptionCategory.EXPERT, stability = OptionStability.STABLE) // public static final OptionKey LivenessAnalysis = new OptionKey<>(false); + @Option(help = "Enable Class Hierarchy Analysis, which optimizes instanceof checks and virtual method calls by keeping track of descendants of a given class or interface.", // + category = OptionCategory.EXPERT, stability = OptionStability.EXPERIMENTAL) // + public static final OptionKey EnableCHA = new OptionKey<>(false); + private static final OptionType JDWP_OPTIONS_OPTION_TYPE = new OptionType<>("JDWPOptions", new Function() { diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java index 23257795d668..8de0949cdec3 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java @@ -44,6 +44,8 @@ import java.util.logging.Level; import java.util.stream.Collectors; +import com.oracle.truffle.espresso.analysis.hierarchy.DefaultClassHierarchyOracle; +import com.oracle.truffle.espresso.analysis.hierarchy.NoOpClassHierarchyOracle; import org.graalvm.options.OptionMap; import org.graalvm.polyglot.Engine; @@ -67,7 +69,6 @@ import com.oracle.truffle.espresso.EspressoOptions; import com.oracle.truffle.espresso.FinalizationSupport; import com.oracle.truffle.espresso.analysis.hierarchy.ClassHierarchyOracle; -import com.oracle.truffle.espresso.analysis.hierarchy.NoOpClassHierarchyOracle; import com.oracle.truffle.espresso.descriptors.Names; import com.oracle.truffle.espresso.descriptors.Signatures; import com.oracle.truffle.espresso.descriptors.Symbol; @@ -171,6 +172,7 @@ public final class EspressoContext { public final boolean InlineMethodHandle; public final boolean SplitMethodHandles; public final boolean livenessAnalysis; + public final boolean EnableClassHierarchyAnalysis; // Behavior control public final boolean EnableManagement; @@ -272,6 +274,7 @@ public EspressoContext(TruffleLanguage.Env env, EspressoLanguage language) { this.EnableSignals = env.getOptions().get(EspressoOptions.EnableSignals); this.SpecCompliancyMode = env.getOptions().get(EspressoOptions.SpecCompliancy); this.livenessAnalysis = env.getOptions().get(EspressoOptions.LivenessAnalysis); + this.EnableClassHierarchyAnalysis = env.getOptions().get(EspressoOptions.EnableCHA); this.EnableManagement = env.getOptions().get(EspressoOptions.EnableManagement); this.EnableAgents = getEnv().getOptions().get(EspressoOptions.EnableAgents); this.TrivialMethodSize = getEnv().getOptions().get(EspressoOptions.TrivialMethodSize); @@ -296,7 +299,11 @@ public EspressoContext(TruffleLanguage.Env env, EspressoLanguage language) { this.vmArguments = buildVmArguments(); this.jdwpContext = new JDWPContextImpl(this); - this.classHierarchyOracle = new NoOpClassHierarchyOracle(); + if (this.EnableClassHierarchyAnalysis) { + this.classHierarchyOracle = new DefaultClassHierarchyOracle(); + } else { + this.classHierarchyOracle = new NoOpClassHierarchyOracle(); + } } private static Set knownSingleThreadedLanguages(TruffleLanguage.Env env) { From efb986f45f1205f82afafb4d568cc573829f0e38 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Fri, 1 Oct 2021 10:40:22 +0200 Subject: [PATCH 251/681] [GR-34130] Log handler should not try to lock special files. --- .../src/org/graalvm/launcher/Launcher.java | 68 ++++++++++--------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/Launcher.java b/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/Launcher.java index 1b02e4cce29c..1cd0b502973a 100644 --- a/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/Launcher.java +++ b/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/Launcher.java @@ -1623,41 +1623,47 @@ protected static OutputStream newLogStream(Path path) throws IOException { Path usedPath = path; Path fileNamePath = path.getFileName(); String fileName = fileNamePath == null ? "" : fileNamePath.toString(); - Path lockFile = null; - FileChannel lockFileChannel = null; - for (int unique = 0;; unique++) { - StringBuilder lockFileNameBuilder = new StringBuilder(fileName); - if (unique > 0) { - lockFileNameBuilder.append(unique); - usedPath = path.resolveSibling(lockFileNameBuilder.toString()); - } - lockFileNameBuilder.append(".lck"); - lockFile = path.resolveSibling(lockFileNameBuilder.toString()); - Pair openResult = openChannel(lockFile); - if (openResult != null) { - lockFileChannel = openResult.getLeft(); - if (lock(lockFileChannel, openResult.getRight())) { - break; - } else { - // Close and try next name - lockFileChannel.close(); + OutputStream outputStream; + if (Files.exists(path) && !Files.isRegularFile(path)) { + // Don't try to lock device or named pipe. + outputStream = new BufferedOutputStream(Files.newOutputStream(usedPath, WRITE, CREATE, APPEND)); + } else { + Path lockFile = null; + FileChannel lockFileChannel = null; + for (int unique = 0;; unique++) { + StringBuilder lockFileNameBuilder = new StringBuilder(fileName); + if (unique > 0) { + lockFileNameBuilder.append(unique); + usedPath = path.resolveSibling(lockFileNameBuilder.toString()); + } + lockFileNameBuilder.append(".lck"); + lockFile = path.resolveSibling(lockFileNameBuilder.toString()); + Pair openResult = openChannel(lockFile); + if (openResult != null) { + lockFileChannel = openResult.getLeft(); + if (lock(lockFileChannel, openResult.getRight())) { + break; + } else { + // Close and try next name + lockFileChannel.close(); + } } } - } - assert lockFile != null && lockFileChannel != null; - boolean success = false; - try { - OutputStream stream = new LockableOutputStream( - new BufferedOutputStream(Files.newOutputStream(usedPath, WRITE, CREATE, APPEND)), - lockFile, - lockFileChannel); - success = true; - return stream; - } finally { - if (!success) { - LockableOutputStream.unlock(lockFile, lockFileChannel); + assert lockFile != null && lockFileChannel != null; + boolean success = false; + try { + outputStream = new LockableOutputStream( + new BufferedOutputStream(Files.newOutputStream(usedPath, WRITE, CREATE, APPEND)), + lockFile, + lockFileChannel); + success = true; + } finally { + if (!success) { + LockableOutputStream.unlock(lockFile, lockFileChannel); + } } } + return outputStream; } private static Pair openChannel(Path path) throws IOException { From d73b454f731bf0cd7dede04b9668a0c5d8a2c46c Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Thu, 30 Sep 2021 14:40:03 +0300 Subject: [PATCH 252/681] Test modifiers in ptype for substituted methods and fields --- substratevm/mx.substratevm/testhello.py | 171 ++++++++++-------- .../com.oracle.svm.test/src/hello/Hello.java | 6 + .../Target_hello_Hello_DefaultGreeter.java | 11 +- 3 files changed, 107 insertions(+), 81 deletions(-) diff --git a/substratevm/mx.substratevm/testhello.py b/substratevm/mx.substratevm/testhello.py index 32346d942bd3..5f7361a816b7 100644 --- a/substratevm/mx.substratevm/testhello.py +++ b/substratevm/mx.substratevm/testhello.py @@ -170,10 +170,21 @@ def test(): execute("set pagination off") # enable pretty printing of structures execute("set print pretty on") + + # Print DefaultGreeter and check the modifiers of its methods and fields + exec_string = execute("ptype 'hello.Hello$DefaultGreeter'") + rexp = [r"type = class hello\.Hello\$DefaultGreeter : public hello\.Hello\$Greeter {", + r"%spublic:"%spaces_pattern, + r"%svoid greet\(\);"%spaces_pattern, + r"%sint hashCode\(\);"%spaces_pattern, + r"}"] + checker = Checker("ptype 'hello.Hello$DefaultGreeter'", rexp) + checker.check(exec_string) + # set a break point at hello.Hello::main - # expect "Breakpoint 1 at 0x[0-9a-f]+: file hello.Hello.java, line 70." + # expect "Breakpoint 1 at 0x[0-9a-f]+: file hello.Hello.java, line 76." exec_string = execute("break hello.Hello::main") - rexp = r"Breakpoint 1 at %s: file hello/Hello\.java, line 70\."%address_pattern + rexp = r"Breakpoint 1 at %s: file hello/Hello\.java, line 76\."%address_pattern checker = Checker('break main', rexp) checker.check(exec_string) @@ -182,17 +193,17 @@ def test(): execute("delete breakpoints") # list the line at the breakpoint - # expect "70 Greeter greeter = Greeter.greeter(args);" + # expect "76 Greeter greeter = Greeter.greeter(args);" exec_string = execute("list") - checker = Checker(r"list bp 1", "70%sGreeter greeter = Greeter\.greeter\(args\);"%spaces_pattern) + checker = Checker(r"list bp 1", "76%sGreeter greeter = Greeter\.greeter\(args\);"%spaces_pattern) checker.check(exec_string, skip_fails=False) # run a backtrace - # expect "#0 hello.Hello.main(java.lang.String[] *).* at hello.Hello.java:70" + # expect "#0 hello.Hello.main(java.lang.String[] *).* at hello.Hello.java:76" # expect "#1 0x[0-9a-f]+ in com.oracle.svm.core.code.IsolateEnterStub.JavaMainWrapper_run_.* at [a-z/]+/JavaMainWrapper.java:[0-9]+" exec_string = execute("backtrace") checker = Checker("backtrace hello.Hello::main", - [r"#0%shello\.Hello::main\(java\.lang\.String\[\] \*\)%s at hello/Hello\.java:70"%(spaces_pattern, wildcard_pattern), + [r"#0%shello\.Hello::main\(java\.lang\.String\[\] \*\)%s at hello/Hello\.java:76"%(spaces_pattern, wildcard_pattern), r"#1%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::runCore%s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, wildcard_pattern, package_pattern), r"#2%s com\.oracle\.svm\.core\.JavaMainWrapper::run%s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, wildcard_pattern, package_pattern), r"#3%s%s in com\.oracle\.svm\.core\.code\.IsolateEnterStub::JavaMainWrapper_run_%s%s"%(spaces_pattern, address_pattern, hex_digits_pattern, wildcard_pattern) @@ -386,7 +397,7 @@ def test(): exec_string = execute("backtrace") checker = Checker("backtrace hello.Hello.Greeter::greeter", [r"#0%shello\.Hello\$Greeter::greeter\(java\.lang\.String\[\] \*\)%s at hello/Hello\.java:37"%(spaces_pattern, wildcard_pattern), - r"#1%s%s in hello\.Hello::main\(java\.lang\.String\[\] \*\)%s at hello/Hello\.java:70"%(spaces_pattern, address_pattern, wildcard_pattern), + r"#1%s%s in hello\.Hello::main\(java\.lang\.String\[\] \*\)%s at hello/Hello\.java:76"%(spaces_pattern, address_pattern, wildcard_pattern), r"#2%s%s in com\.oracle\.svm\.core\.JavaMainWrapper::runCore%s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, address_pattern, wildcard_pattern, package_pattern), r"#3%scom\.oracle\.svm\.core\.JavaMainWrapper::run%s at %sJavaMainWrapper\.java:[0-9]+"%(spaces_pattern, wildcard_pattern, package_pattern), r"#4%s%s in com\.oracle\.svm\.core\.code\.IsolateEnterStub::JavaMainWrapper_run_%s%s"%(spaces_pattern, address_pattern, hex_digits_pattern, wildcard_pattern) @@ -430,11 +441,11 @@ def test(): # expect "#0 java.io.PrintStream::println(java.lang.String).* at java.base/java/io/PrintStream.java:[0-9]+" exec_string = execute("backtrace 6") rexp = [r"#0%sjava\.io\.PrintStream::println\(java\.lang\.String \*\)%s at %sjava/io/PrintStream.java:%s"%(spaces_pattern, wildcard_pattern, wildcard_pattern, digits_pattern), - r"#1%s%s in hello\.SubstituteHelperClass::nestedGreet\(void\) \(\) at hello/Target_hello_Hello_DefaultGreeter\.java:59"%(spaces_pattern, address_pattern), - r"#2%s%s in hello\.SubstituteHelperClass::staticInlineGreet \(\) at hello/Target_hello_Hello_DefaultGreeter\.java:53"%(spaces_pattern, address_pattern), - r"#3%s hello\.SubstituteHelperClass::inlineGreet \(\) at hello/Target_hello_Hello_DefaultGreeter\.java:48"%(spaces_pattern), - r"#4%s hello\.Hello\$DefaultGreeter::greet\(void\) \(\) at hello/Target_hello_Hello_DefaultGreeter\.java:40"%(spaces_pattern), - r"#5%s%s in hello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:71"%(spaces_pattern, address_pattern)] + r"#1%s%s in hello\.SubstituteHelperClass::nestedGreet\(void\) \(\) at hello/Target_hello_Hello_DefaultGreeter\.java:68"%(spaces_pattern, address_pattern), + r"#2%s%s in hello\.SubstituteHelperClass::staticInlineGreet \(\) at hello/Target_hello_Hello_DefaultGreeter\.java:62"%(spaces_pattern, address_pattern), + r"#3%s hello\.SubstituteHelperClass::inlineGreet \(\) at hello/Target_hello_Hello_DefaultGreeter\.java:57"%(spaces_pattern), + r"#4%s hello\.Hello\$DefaultGreeter::greet\(void\) \(\) at hello/Target_hello_Hello_DefaultGreeter\.java:49"%(spaces_pattern), + r"#5%s%s in hello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:77"%(spaces_pattern, address_pattern)] checker = Checker("backtrace PrintStream::println", rexp) checker.check(exec_string) @@ -535,7 +546,7 @@ def test(): # list inlineMee and inlineMoo and check that the listing maps to the inlined code instead of the actual code, # although not ideal this is how GDB treats inlined code in C/C++ as well - rexp = [r"109%sSystem\.out\.println\(\"This is a cow\"\);"%spaces_pattern] + rexp = [r"115%sSystem\.out\.println\(\"This is a cow\"\);"%spaces_pattern] checker = Checker('list inlineMee', rexp) checker.check(execute("list inlineMee")) checker = Checker('list inlineMoo', rexp) @@ -551,134 +562,134 @@ def test(): exec_string = execute("info break 4") # The breakpoint will be set to the inlined code instead of the actual code, # although not ideal this is how GDB treats inlined code in C/C++ as well - rexp = [r"4.1%sy%s%s in hello\.Hello::inlineMee at hello/Hello\.java:109"%(spaces_pattern, spaces_pattern, address_pattern), - r"4.2%sy%s%s in hello\.Hello::inlineMee at hello/Hello\.java:109"%(spaces_pattern, spaces_pattern, address_pattern), - r"4.3%sy%s%s in hello\.Hello::inlineMee at hello/Hello\.java:109"%(spaces_pattern, spaces_pattern, address_pattern)] + rexp = [r"4.1%sy%s%s in hello\.Hello::inlineMee at hello/Hello\.java:115"%(spaces_pattern, spaces_pattern, address_pattern), + r"4.2%sy%s%s in hello\.Hello::inlineMee at hello/Hello\.java:115"%(spaces_pattern, spaces_pattern, address_pattern), + r"4.3%sy%s%s in hello\.Hello::inlineMee at hello/Hello\.java:115"%(spaces_pattern, spaces_pattern, address_pattern)] checker = Checker('info break inlineMee', rexp) checker.check(exec_string) execute("continue") exec_string = execute("list") - rexp = [r"104%sinlineMoo\(\);"%spaces_pattern] + rexp = [r"110%sinlineMoo\(\);"%spaces_pattern] checker = Checker('hit break at inlineMee', rexp) checker.check(exec_string, skip_fails=False) execute("step") exec_string = execute("list") - rexp = [r"109%sSystem\.out\.println\(\"This is a cow\"\);"%spaces_pattern] + rexp = [r"115%sSystem\.out\.println\(\"This is a cow\"\);"%spaces_pattern] checker = Checker('step in inlineMee', rexp) checker.check(exec_string, skip_fails=False) exec_string = execute("backtrace 4") - rexp = [r"#0%shello\.Hello::inlineMoo \(\) at hello/Hello\.java:109"%spaces_pattern, - r"#1%shello\.Hello::inlineMee \(\) at hello/Hello\.java:104"%spaces_pattern, - r"#2%shello\.Hello::noInlineFoo\(void\) \(\) at hello/Hello\.java:94"%spaces_pattern, - r"#3%s%s in hello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:85"%(spaces_pattern, address_pattern)] + rexp = [r"#0%shello\.Hello::inlineMoo \(\) at hello/Hello\.java:115"%spaces_pattern, + r"#1%shello\.Hello::inlineMee \(\) at hello/Hello\.java:110"%spaces_pattern, + r"#2%shello\.Hello::noInlineFoo\(void\) \(\) at hello/Hello\.java:100"%spaces_pattern, + r"#3%s%s in hello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:91"%(spaces_pattern, address_pattern)] checker = Checker('backtrace inlineMee', rexp) checker.check(exec_string, skip_fails=False) execute("continue") exec_string = execute("list") - rexp = [r"104%sinlineMoo\(\);"%spaces_pattern] + rexp = [r"110%sinlineMoo\(\);"%spaces_pattern] checker = Checker('hit break at inlineMee', rexp) checker.check(exec_string, skip_fails=False) execute("step") exec_string = execute("list") - rexp = [r"109%sSystem\.out\.println\(\"This is a cow\"\);"%spaces_pattern] + rexp = [r"115%sSystem\.out\.println\(\"This is a cow\"\);"%spaces_pattern] checker = Checker('step in inlineMee', rexp) checker.check(exec_string, skip_fails=False) exec_string = execute("backtrace 4") - rexp = [r"#0%shello\.Hello::inlineMoo \(\) at hello/Hello\.java:109"%spaces_pattern, - r"#1%shello\.Hello::inlineMee \(\) at hello/Hello\.java:104"%spaces_pattern, - r"#2%shello\.Hello::inlineCallChain \(\) at hello/Hello\.java:99"%spaces_pattern, - r"#3%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:86"%spaces_pattern] + rexp = [r"#0%shello\.Hello::inlineMoo \(\) at hello/Hello\.java:115"%spaces_pattern, + r"#1%shello\.Hello::inlineMee \(\) at hello/Hello\.java:110"%spaces_pattern, + r"#2%shello\.Hello::inlineCallChain \(\) at hello/Hello\.java:105"%spaces_pattern, + r"#3%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:92"%spaces_pattern] checker = Checker('backtrace inlineMee 2', rexp) checker.check(exec_string, skip_fails=False) execute("delete breakpoints") exec_string = execute("break hello.Hello::noInlineTest") - rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 129\."%(digits_pattern, address_pattern) + rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 135\."%(digits_pattern, address_pattern) checker = Checker('break noInlineTest', rexp) checker.check(exec_string, skip_fails=False) execute("continue") exec_string = execute("list") - rexp = r"129%sSystem.out.println\(\"This is a test\"\);"%spaces_pattern + rexp = r"135%sSystem.out.println\(\"This is a test\"\);"%spaces_pattern checker = Checker('hit breakpoint in noInlineTest', rexp) checker.check(exec_string, skip_fails=False) exec_string = execute("backtrace 5") - rexp = [r"#0%shello\.Hello::noInlineTest\(void\) \(\) at hello/Hello\.java:129"%(spaces_pattern), - r"#1%s%s in hello\.Hello::inlineA \(\) at hello/Hello\.java:124"%(spaces_pattern, address_pattern), - r"#2%shello\.Hello::inlineIs \(\) at hello/Hello\.java:119"%(spaces_pattern), - r"#3%shello\.Hello::noInlineThis\(void\) \(\) at hello/Hello\.java:114"%(spaces_pattern), - r"#4%s%s in hello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:87"%(spaces_pattern, address_pattern)] + rexp = [r"#0%shello\.Hello::noInlineTest\(void\) \(\) at hello/Hello\.java:135"%(spaces_pattern), + r"#1%s%s in hello\.Hello::inlineA \(\) at hello/Hello\.java:130"%(spaces_pattern, address_pattern), + r"#2%shello\.Hello::inlineIs \(\) at hello/Hello\.java:125"%(spaces_pattern), + r"#3%shello\.Hello::noInlineThis\(void\) \(\) at hello/Hello\.java:120"%(spaces_pattern), + r"#4%s%s in hello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:93"%(spaces_pattern, address_pattern)] checker = Checker('backtrace in inlineMethod', rexp) checker.check(exec_string, skip_fails=False) execute("delete breakpoints") - exec_string = execute("break Hello.java:149") - rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 149\."%(digits_pattern, address_pattern) - checker = Checker('break Hello.java:149', rexp) + exec_string = execute("break Hello.java:155") + rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 155\."%(digits_pattern, address_pattern) + checker = Checker('break Hello.java:155', rexp) checker.check(exec_string) execute("continue 5") exec_string = execute("backtrace 14") - rexp = [r"#0%shello\.Hello::inlineMixTo \(\) at hello/Hello\.java:149"%(spaces_pattern), - r"#1%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:141"%(spaces_pattern), - r"#2%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:147"%(spaces_pattern, address_pattern), - r"#3%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:141"%(spaces_pattern), - r"#4%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:147"%(spaces_pattern, address_pattern), - r"#5%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:141"%(spaces_pattern), - r"#6%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:147"%(spaces_pattern, address_pattern), - r"#7%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:141"%(spaces_pattern), - r"#8%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:147"%(spaces_pattern, address_pattern), - r"#9%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:141"%(spaces_pattern), - r"#10%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:147"%(spaces_pattern, address_pattern), - r"#11%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:141"%(spaces_pattern), - r"#12%s%s in hello\.Hello::inlineFrom \(\) at hello/Hello\.java:134"%(spaces_pattern, address_pattern), - r"#13%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:88"%(spaces_pattern)] + rexp = [r"#0%shello\.Hello::inlineMixTo \(\) at hello/Hello\.java:155"%(spaces_pattern), + r"#1%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), + r"#2%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), + r"#3%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), + r"#4%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), + r"#5%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), + r"#6%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), + r"#7%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), + r"#8%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), + r"#9%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), + r"#10%s%s in hello\.Hello::inlineMixTo \(\) at hello/Hello\.java:153"%(spaces_pattern, address_pattern), + r"#11%shello\.Hello::noInlineHere\(int\) \(\) at hello/Hello\.java:147"%(spaces_pattern), + r"#12%s%s in hello\.Hello::inlineFrom \(\) at hello/Hello\.java:140"%(spaces_pattern, address_pattern), + r"#13%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:94"%(spaces_pattern)] checker = Checker('backtrace in recursive inlineMixTo', rexp) checker.check(exec_string, skip_fails=False) execute("delete breakpoints") - exec_string = execute("break Hello.java:162") - rexp = r"Breakpoint %s at %s: Hello\.java:162\. \(2 locations\)"%(digits_pattern, address_pattern) - checker = Checker('break Hello.java:162', rexp) + exec_string = execute("break Hello.java:168") + rexp = r"Breakpoint %s at %s: Hello\.java:168\. \(2 locations\)"%(digits_pattern, address_pattern) + checker = Checker('break Hello.java:168', rexp) checker.check(exec_string) execute("continue 5") exec_string = execute("backtrace 14") - rexp = [r"#0%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:162"%(spaces_pattern), - r"#1%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:154"%(spaces_pattern, address_pattern), - r"#2%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:160"%(spaces_pattern), - r"#3%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:154"%(spaces_pattern, address_pattern), - r"#4%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:160"%(spaces_pattern), - r"#5%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:154"%(spaces_pattern, address_pattern), - r"#6%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:160"%(spaces_pattern), - r"#7%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:154"%(spaces_pattern, address_pattern), - r"#8%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:160"%(spaces_pattern), - r"#9%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:154"%(spaces_pattern, address_pattern), - r"#10%shello\.Hello::inlineTo \(\) at hello/Hello\.java:160"%(spaces_pattern), - r"#11%shello\.Hello::inlineHere \(\) at hello/Hello\.java:154"%(spaces_pattern), - r"#12%shello\.Hello::inlineFrom \(\) at hello/Hello\.java:135"%(spaces_pattern), - r"#13%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:88"%(spaces_pattern)] + rexp = [r"#0%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:168"%(spaces_pattern), + r"#1%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), + r"#2%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:166"%(spaces_pattern), + r"#3%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), + r"#4%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:166"%(spaces_pattern), + r"#5%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), + r"#6%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:166"%(spaces_pattern), + r"#7%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), + r"#8%shello\.Hello::inlineTo\(int\) \(\) at hello/Hello\.java:166"%(spaces_pattern), + r"#9%s%s in hello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern, address_pattern), + r"#10%shello\.Hello::inlineTo \(\) at hello/Hello\.java:166"%(spaces_pattern), + r"#11%shello\.Hello::inlineHere \(\) at hello/Hello\.java:160"%(spaces_pattern), + r"#12%shello\.Hello::inlineFrom \(\) at hello/Hello\.java:141"%(spaces_pattern), + r"#13%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:94"%(spaces_pattern)] checker = Checker('backtrace in recursive inlineTo', rexp) checker.check(exec_string, skip_fails=False) execute("delete breakpoints") - exec_string = execute("break Hello.java:168") - rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 168\."%(digits_pattern, address_pattern) - checker = Checker('break Hello.java:168', rexp) + exec_string = execute("break Hello.java:174") + rexp = r"Breakpoint %s at %s: file hello/Hello\.java, line 174\."%(digits_pattern, address_pattern) + checker = Checker('break Hello.java:174', rexp) checker.check(exec_string) execute("continue 5") exec_string = execute("backtrace 8") - rexp = [r"#0%shello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:168"%(spaces_pattern), - r"#1%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:171"%(spaces_pattern, address_pattern), - r"#2%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:171"%(spaces_pattern, address_pattern), - r"#3%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:171"%(spaces_pattern, address_pattern), - r"#4%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:171"%(spaces_pattern, address_pattern), - r"#5%s%s in hello\.Hello::inlineTailRecursion \(\) at hello/Hello\.java:171"%(spaces_pattern, address_pattern), - r"#6%shello\.Hello::inlineFrom \(\) at hello/Hello\.java:136"%(spaces_pattern), - r"#7%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:88"%(spaces_pattern)] + rexp = [r"#0%shello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:174"%(spaces_pattern), + r"#1%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), + r"#2%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), + r"#3%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), + r"#4%s%s in hello\.Hello::inlineTailRecursion\(int\) \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), + r"#5%s%s in hello\.Hello::inlineTailRecursion \(\) at hello/Hello\.java:177"%(spaces_pattern, address_pattern), + r"#6%shello\.Hello::inlineFrom \(\) at hello/Hello\.java:142"%(spaces_pattern), + r"#7%shello\.Hello::main\(java\.lang\.String\[\] \*\) \(\) at hello/Hello\.java:94"%(spaces_pattern)] checker = Checker('backtrace in recursive inlineTo', rexp) checker.check(exec_string, skip_fails=False) diff --git a/substratevm/src/com.oracle.svm.test/src/hello/Hello.java b/substratevm/src/com.oracle.svm.test/src/hello/Hello.java index e70d133ee8ea..be7f6ab8c567 100644 --- a/substratevm/src/com.oracle.svm.test/src/hello/Hello.java +++ b/substratevm/src/com.oracle.svm.test/src/hello/Hello.java @@ -47,6 +47,12 @@ static Greeter greeter(String[] args) { } public static class DefaultGreeter extends Greeter { + + @Override + public int hashCode() { + return 42; + } + @Override public void greet() { System.out.println("Hello, world!"); diff --git a/substratevm/src/com.oracle.svm.test/src/hello/Target_hello_Hello_DefaultGreeter.java b/substratevm/src/com.oracle.svm.test/src/hello/Target_hello_Hello_DefaultGreeter.java index 1fee4b7e22ca..3ae0d2cc9dd5 100644 --- a/substratevm/src/com.oracle.svm.test/src/hello/Target_hello_Hello_DefaultGreeter.java +++ b/substratevm/src/com.oracle.svm.test/src/hello/Target_hello_Hello_DefaultGreeter.java @@ -30,12 +30,21 @@ import com.oracle.svm.core.annotate.NeverInline; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.TargetElement; @TargetClass(value = Hello.DefaultGreeter.class) final class Target_hello_Hello_DefaultGreeter { + + @SuppressWarnings("static-method") + @Substitute() + @TargetElement(name = "hashCode") + private int hashCodeSubst() { + return 24; + } + @SuppressWarnings("static-method") @Substitute - public void greet() { + private void greet() { SubstituteHelperClass substituteHelperClass = new SubstituteHelperClass(); substituteHelperClass.inlineGreet(); } From 1722528eace0abb5659cc46f46d0b2e1baf4872b Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Thu, 30 Sep 2021 16:49:18 +0300 Subject: [PATCH 253/681] Debug info: Get modifiers of original method/field for DW_AT_ACCESSIBILITY --- substratevm/mx.substratevm/testhello.py | 9 +++++++- .../image/NativeImageDebugInfoProvider.java | 21 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/substratevm/mx.substratevm/testhello.py b/substratevm/mx.substratevm/testhello.py index 5f7361a816b7..59a33639eb62 100644 --- a/substratevm/mx.substratevm/testhello.py +++ b/substratevm/mx.substratevm/testhello.py @@ -354,10 +354,17 @@ def test(): rexp = [r"type = class java\.lang\.Object : public _objhdr {", r"%spublic:"%(spaces_pattern), r"%svoid Object\(void\);"%(spaces_pattern), + r"%sprotected:"%(spaces_pattern), + r"%sjava\.lang\.Object \* clone\(void\);"%(spaces_pattern), + r"%spublic:"%(spaces_pattern), r"%sboolean equals\(java\.lang\.Object \*\);"%(spaces_pattern), - r"%sprivate:"%(spaces_pattern), r"%sint hashCode\(void\);"%(spaces_pattern), + r"%svoid notify\(void\);"%(spaces_pattern), + r"%svoid notifyAll\(void\);"%(spaces_pattern), r"%sjava\.lang\.String \* toString\(void\);"%(spaces_pattern), + r"%svoid wait\(void\);"%(spaces_pattern), + r"%svoid wait\(long\);"%(spaces_pattern), + r"%svoid wait\(long, int\);"%(spaces_pattern), r"}"] checker = Checker('ptype Object', rexp) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java index 4997385e88af..ccd75a00f104 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java @@ -70,6 +70,7 @@ import com.oracle.svm.hosted.meta.HostedPrimitiveType; import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.substitute.InjectedFieldsType; +import com.oracle.svm.hosted.substitute.SubstitutionField; import com.oracle.svm.hosted.substitute.SubstitutionMethod; import com.oracle.svm.hosted.substitute.SubstitutionType; @@ -229,6 +230,16 @@ private static ResolvedJavaType getOriginal(HostedType hostedType) { return javaType; } + private static int getOriginalModifiers(HostedMethod hostedMethod) { + ResolvedJavaMethod targetMethod = hostedMethod.getWrapped().getWrapped(); + if (targetMethod instanceof SubstitutionMethod) { + targetMethod = ((SubstitutionMethod) targetMethod).getOriginal(); + } else if (targetMethod instanceof CustomSubstitutionMethod) { + targetMethod = ((CustomSubstitutionMethod) targetMethod).getOriginal(); + } + return targetMethod.getModifiers(); + } + private static String toJavaName(JavaType javaType) { if (javaType instanceof HostedType) { return getDeclaringClass((HostedType) javaType, true).toJavaName(); @@ -608,7 +619,11 @@ public int size() { @Override public int modifiers() { - return field.getModifiers(); + ResolvedJavaField targetField = field.wrapped.wrapped; + if (targetField instanceof SubstitutionField) { + targetField = ((SubstitutionField) targetField).getOriginal(); + } + return targetField.getModifiers(); } private boolean isStatic() { @@ -683,7 +698,7 @@ public boolean isDeoptTarget() { @Override public int modifiers() { - return hostedMethod.getModifiers(); + return getOriginalModifiers(hostedMethod); } } } @@ -963,7 +978,7 @@ public List paramNames() { @Override public int modifiers() { - return hostedMethod.getModifiers(); + return getOriginalModifiers(hostedMethod); } } From 551bb52747f1cb2eeb919668e30172a581010bf8 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Fri, 1 Oct 2021 11:21:33 +0200 Subject: [PATCH 254/681] Invalidate leafTypeAssumption on child load rather than init --- .../hierarchy/ClassHierarchyOracle.java | 18 ++++++------------ .../hierarchy/DefaultClassHierarchyOracle.java | 12 ++++-------- .../hierarchy/NoOpClassHierarchyOracle.java | 6 +----- .../truffle/espresso/impl/ObjectKlass.java | 3 +-- 4 files changed, 12 insertions(+), 27 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java index 08024f645908..95cbb49fbc7c 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/ClassHierarchyOracle.java @@ -40,25 +40,19 @@ protected LeafTypeAssumptionAccessor() { } /** - * Must be called to initialize {@code leafTypeAssumption} of {@code newKlass}. + * Must be called to initialize {@code leafTypeAssumption} of {@code newKlass}. In addition, it + * communicates to the oracle that a new klass has been created and its ancestors are no longer + * leaves. * * @param newKlass -- newly created class * @return the assumption, indicating whether the class is a leaf in class hierarchy. */ - LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass); - - /** - * Must be called when {@code newKlass} is initialized. Communicates to the oracle that - * instances of this class might exist, which changes the class hierarchy. - * - * @param newKlass -- newly initialized class - */ - void onClassInit(ObjectKlass newKlass); + LeafTypeAssumption createAssumptionForNewKlass(ObjectKlass newKlass); /** * @return the assumption, valid iff {@code klass} is a leaf in class hierarchy. Automatically - * invalidated in {@link #onClassInit(ObjectKlass)} when a child of {@code klass} is - * initialized. + * invalidated in {@link #createAssumptionForNewKlass(ObjectKlass)} when a child of + * {@code klass} is created. */ LeafTypeAssumption isLeafClass(ObjectKlass klass); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java index b4a5a210d7c6..948c5222cac1 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/DefaultClassHierarchyOracle.java @@ -32,7 +32,9 @@ */ public class DefaultClassHierarchyOracle extends NoOpClassHierarchyOracle implements ClassHierarchyOracle { @Override - public LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass) { + public LeafTypeAssumption createAssumptionForNewKlass(ObjectKlass newKlass) { + markAncestorsAsNonLeaf(newKlass); + if (newKlass.isFinalFlagSet()) { return FinalIsAlwaysLeaf; } @@ -42,13 +44,7 @@ public LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass) { return new LeafTypeAssumptionImpl(newKlass); } - /** - * Marks all ancestors of {@code newClass} as non-leaf. - * - * @param newClass -- newly initialized class. - */ - @Override - public void onClassInit(ObjectKlass newClass) { + private static void markAncestorsAsNonLeaf(ObjectKlass newClass) { ObjectKlass currentParent = newClass.getSuperKlass(); while (currentParent != null && currentParent.getLeafTypeAssumption(assumptionAccessor).getAssumption().isValid()) { currentParent.getLeafTypeAssumption(assumptionAccessor).getAssumption().invalidate(); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java index 2ce82a93b037..bb6efadf2d26 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java @@ -59,17 +59,13 @@ public Assumption getAssumption() { protected static final LeafTypeAssumption NotLeaf = LeafTypeAssumptionImpl.AlwaysInvalid; @Override - public LeafTypeAssumption createAssumptionForClass(ObjectKlass newKlass) { + public LeafTypeAssumption createAssumptionForNewKlass(ObjectKlass newKlass) { if (newKlass.isFinalFlagSet()) { return FinalIsAlwaysLeaf; } return NotLeaf; } - @Override - public void onClassInit(ObjectKlass newKlass) { - } - @Override public LeafTypeAssumption isLeafClass(ObjectKlass klass) { return klass.getLeafTypeAssumption(assumptionAccessor); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java index c109eec11332..02d022cd91e5 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java @@ -235,7 +235,7 @@ public ObjectKlass(EspressoContext context, LinkedKlass linkedKlass, ObjectKlass initSelfReferenceInPool(); } - this.leafTypeAssumption = getContext().getClassHierarchyOracle().createAssumptionForClass(this); + this.leafTypeAssumption = getContext().getClassHierarchyOracle().createAssumptionForNewKlass(this); this.initState = LOADED; assert verifyTables(); } @@ -397,7 +397,6 @@ private void actualInit() { throw e; } checkErroneousInitialization(); - getContext().getClassHierarchyOracle().onClassInit(this); initState = INITIALIZED; assert isInitialized(); } From 38c25e7be1215cec7a0a4b8563b746e1b2a2b83a Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 30 Sep 2021 21:57:31 +0200 Subject: [PATCH 255/681] Print missed samples in CPUSampler. --- .../truffle/tools/profiler/test/ProfilerCLITest.java | 2 +- .../truffle/tools/profiler/impl/CPUSamplerCLI.java | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/ProfilerCLITest.java b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/ProfilerCLITest.java index 1f727c39fc57..9c4ef5ce1ea6 100644 --- a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/ProfilerCLITest.java +++ b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/ProfilerCLITest.java @@ -48,7 +48,7 @@ public class ProfilerCLITest { - public static final String SAMPLING_HISTOGRAM_REGEX = "Sampling Histogram. Recorded [0-9]* samples with period [0-9]*ms."; + public static final String SAMPLING_HISTOGRAM_REGEX = "Sampling Histogram. Recorded [0-9]* samples with period [0-9]*ms. Missed [0-9]* samples."; public static final int EXEC_COUNT = 10; public static final String NAME_REGEX = " [a-z]* +"; public static final String SEPARATOR_REGEX = "\\|"; diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java index 641a168be774..6c429f8058ca 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java @@ -284,8 +284,8 @@ private static JSONArray getSamplesRec(Collection tiers = new HashSet<>(); private Integer[] sortedTiers; private int maxNameLength = 10; @@ -383,6 +384,7 @@ private static final class SamplingHistogram { this.samplePeriod = options.get(SAMPLE_PERIOD); this.samplesTaken = data.getSamples(); Map perThreadSourceLocationPayloads = new HashMap<>(); + this.samplesMissed = data.missedSamples(); for (Thread thread : data.getThreadData().keySet()) { perThreadSourceLocationPayloads.put(thread, computeSourceLocationPayloads(data.getThreadData().get(thread))); } @@ -469,7 +471,7 @@ private static void computeSourceLocationPayloadsImpl(Collection> threadListEntry : histogram.entrySet()) { out.println(threadListEntry.getKey()); @@ -565,6 +567,7 @@ private static class SamplingCallTree { private final int[] showTiers; private final long samplePeriod; private final long samplesTaken; + private final long samplesMissed; private final String title; private final String format; private final Map> entries = new HashMap<>(); @@ -578,6 +581,7 @@ private static class SamplingCallTree { this.showTiers = options.get(ShowTiers); this.samplePeriod = options.get(SAMPLE_PERIOD); this.samplesTaken = data.getSamples(); + this.samplesMissed = data.missedSamples(); Map>> threadData = data.getThreadData(); makeEntries(threadData); calculateMaxValues(threadData); @@ -656,7 +660,7 @@ private CallTreeOutputEntry makeEntry(ProfilerNode node, int void print(PrintStream out) { String sep = repeat("-", title.length()); out.println(sep); - printLegend(out, "Call Tree", samplesTaken, samplePeriod, showTiers, sortedTiers); + printLegend(out, "Call Tree", samplesTaken, samplePeriod, samplesMissed, showTiers, sortedTiers); out.println(sep); out.println(title); out.println(sep); From 46c36c492edd3c16c7f188219e887cc96fc8208e Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 30 Sep 2021 19:07:46 +0200 Subject: [PATCH 256/681] Use fixed rate for cpu sampling. --- .../src/com/oracle/truffle/tools/profiler/CPUSampler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java index 71f16f20a3f0..f81afa05b38b 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java @@ -536,7 +536,7 @@ private void resetSampling() { } this.safepointStackSampler = new SafepointStackSampler(stackLimit, filter, period); this.samplerTask = new SamplingTimerTask(); - this.samplerThread.schedule(samplerTask, delay, period); + this.samplerThread.scheduleAtFixedRate(samplerTask, delay, period); } private void cleanup() { From 80b8185861c7a09a5b6589ee2567024d975fad83 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 30 Sep 2021 23:03:51 +0200 Subject: [PATCH 257/681] Improve accuracy of CPUSampler by processing in a separate thread. --- .../truffle/tools/profiler/CPUSampler.java | 114 ++++++++++++++---- 1 file changed, 90 insertions(+), 24 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java index f81afa05b38b..7dea7637d9ed 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java @@ -36,6 +36,7 @@ import java.util.Map.Entry; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.atomic.AtomicLong; import java.util.function.BiConsumer; import java.util.function.Function; @@ -133,9 +134,21 @@ public CPUSampler create(Env env) { private SourceSectionFilter filter = DEFAULT_FILTER; private Timer samplerThread; private SamplingTimerTask samplerTask; + private Thread processingThread; + private ResultProcessingRunnable processingThreadRunnable; + private volatile SafepointStackSampler safepointStackSampler = new SafepointStackSampler(stackLimit, filter, period); private boolean gatherSelfHitTimes = false; + /* + * The results queue will block if it exceeds the capacity. This is intentional as we do not + * want the sampling results to grow infinitely in the worst case. It is better if the sampling + * thread blocks at some point as well. However, it is very unlikely that processing takes such + * a long time that this actually happens, but situations like this might be more frequent when + * debugging. + */ + private final ArrayBlockingQueue resultsToProcess = new ArrayBlockingQueue<>(256); + CPUSampler(Env env) { this.env = env; @@ -531,12 +544,19 @@ private void resetSampling() { if (!collecting || closed) { return; } + if (processingThread == null) { + processingThreadRunnable = new ResultProcessingRunnable(); + processingThread = new Thread(processingThreadRunnable, "Sampling Processing Thread"); + processingThread.setDaemon(true); + } + this.processingThread.start(); if (samplerThread == null) { samplerThread = new Timer("Sampling thread", true); } this.safepointStackSampler = new SafepointStackSampler(stackLimit, filter, period); this.samplerTask = new SamplingTimerTask(); this.samplerThread.scheduleAtFixedRate(samplerTask, delay, period); + } private void cleanup() { @@ -549,6 +569,11 @@ private void cleanup() { samplerThread.cancel(); samplerThread = null; } + if (processingThread != null) { + processingThreadRunnable.cancelled = true; + processingThread.interrupt(); + processingThread = null; + } } private void enterChangeConfig() { @@ -742,34 +767,45 @@ void addSelfHitTime(Long time) { } } - private class SamplingTimerTask extends TimerTask { + /* + * Process samples in a separate thread to avoid further delays during sampling and increase + * accuracy. + */ + private class ResultProcessingRunnable implements Runnable { + + private volatile boolean cancelled; - @Override public void run() { - long taskStartTime = System.currentTimeMillis(); - for (TruffleContext context : contexts()) { - if (context.isClosed()) { - continue; + while (true) { + if (cancelled) { + return; } - List samples = safepointStackSampler.sample(env, context, activeContexts.get(context), !sampleContextInitialization); - synchronized (CPUSampler.this) { - if (!collecting) { - return; - } - if (context.isClosed()) { + SamplingResult result = null; + try { + result = resultsToProcess.take(); + } catch (InterruptedException e) { + // check for cancelled + } + if (cancelled) { + return; + } + if (result != null) { + if (result.context.isClosed()) { continue; } - final MutableSamplerData mutableSamplerData = activeContexts.get(context); - for (StackSample sample : samples) { - mutableSamplerData.biasStatistic.accept(sample.biasNs); - mutableSamplerData.durationStatistic.accept(sample.durationNs); - ProfilerNode threadNode = mutableSamplerData.threadData.computeIfAbsent(sample.thread, new Function>() { - @Override - public ProfilerNode apply(Thread thread) { - return new ProfilerNode<>(); - } - }); - record(sample, threadNode, taskStartTime, mutableSamplerData); + synchronized (CPUSampler.this) { + final MutableSamplerData mutableSamplerData = activeContexts.get(result.context); + for (StackSample sample : result.samples) { + mutableSamplerData.biasStatistic.accept(sample.biasNs); + mutableSamplerData.durationStatistic.accept(sample.durationNs); + ProfilerNode threadNode = mutableSamplerData.threadData.computeIfAbsent(sample.thread, new Function>() { + @Override + public ProfilerNode apply(Thread thread) { + return new ProfilerNode<>(); + } + }); + record(sample, threadNode, result.startTime, mutableSamplerData); + } } } } @@ -779,7 +815,6 @@ private void record(StackSample sample, ProfilerNode threadNode, long t if (sample.stack.size() == 0) { return; } - // now traverse the stack and insert the path into the tree ProfilerNode treeNode = threadNode; for (int i = sample.stack.size() - 1; i >= 0; i--) { StackTraceEntry location = sample.stack.get(i); @@ -817,6 +852,37 @@ private ProfilerNode addOrUpdateChild(ProfilerNode treeNode, S } return child; } + + } + + static class SamplingResult { + + final List samples; + final TruffleContext context; + final long startTime; + + SamplingResult(List samples, TruffleContext context, long startTime) { + this.samples = samples; + this.context = context; + this.startTime = startTime; + } + + } + + private class SamplingTimerTask extends TimerTask { + + @Override + public void run() { + long taskStartTime = System.currentTimeMillis(); + for (TruffleContext context : contexts()) { + if (context.isClosed()) { + continue; + } + List samples = safepointStackSampler.sample(env, context, activeContexts.get(context), !sampleContextInitialization); + resultsToProcess.add(new SamplingResult(samples, context, taskStartTime)); + } + } + } static class MutableSamplerData { From 8397aa5caf56de4766f1931d4da6d3ee450b2a67 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 30 Sep 2021 21:59:42 +0200 Subject: [PATCH 258/681] Move isActive check to takeSample API. --- .../src/com/oracle/truffle/tools/profiler/CPUSampler.java | 3 +++ .../oracle/truffle/tools/profiler/SafepointStackSampler.java | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java index 7dea7637d9ed..a69bbe8742bf 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java @@ -528,6 +528,9 @@ public Map> takeSample() { return Collections.emptyMap(); } TruffleContext context = activeContexts.keySet().iterator().next(); + if (context.isActive()) { + throw new IllegalArgumentException("Cannot sample a context that is currently active on the current thread."); + } Map> stacks = new HashMap<>(); List sample = safepointStackSampler.sample(env, context, activeContexts.get(context), !sampleContextInitialization); for (StackSample stackSample : sample) { diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/SafepointStackSampler.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/SafepointStackSampler.java index 6b8d29c53ac4..30dc8d15c16c 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/SafepointStackSampler.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/SafepointStackSampler.java @@ -80,9 +80,6 @@ private StackVisitor fetchStackVisitor() { } List sample(Env env, TruffleContext context, CPUSampler.MutableSamplerData mutableSamplerData, boolean useSyntheticFrames) { - if (context.isActive()) { - throw new IllegalArgumentException("Cannot sample a context that is currently active on the current thread."); - } if (context.isClosed()) { return Collections.emptyList(); } @@ -101,7 +98,7 @@ List sample(Env env, TruffleContext context, CPUSampler.MutableSamp return Collections.emptyList(); } try { - future.get(10 * period, TimeUnit.MILLISECONDS); + future.get(period * 10, TimeUnit.MILLISECONDS); } catch (InterruptedException | ExecutionException e) { env.getLogger(getClass()).log(Level.SEVERE, "Sampling failed", e); return null; From 926b8eafe161cce51b1afca3350ec7812bd614d5 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Fri, 1 Oct 2021 16:05:51 +0200 Subject: [PATCH 259/681] Fix broken recursive merging and replace it with a depth break. --- .../truffle/tools/profiler/ProfilerNode.java | 8 ++--- .../tools/profiler/impl/CPUSamplerCLI.java | 33 ++++++++++++++----- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/ProfilerNode.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/ProfilerNode.java index 781bd7efb669..2ee2d1e8f9fe 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/ProfilerNode.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/ProfilerNode.java @@ -91,17 +91,13 @@ public ProfilerNode getParent() { * @since 0.30 */ public boolean isRecursive() { - return isRecursiveImpl(this); - } - - private boolean isRecursiveImpl(ProfilerNode source) { if (parent.sourceLocation == null) { return false; } - if (parent.sourceLocation.equals(source.sourceLocation)) { + if (parent.sourceLocation.equals(this.sourceLocation)) { return true; } - return parent.isRecursiveImpl(source); + return false; } /** diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java index 6c429f8058ca..29b2833c8292 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java @@ -497,6 +497,8 @@ private static final class SourceLocationNodes { } private static class OutputEntry { + // break after 128 depth spaces to handle deep recursions + private static final int DEPTH_BREAK = 128; final SourceLocation location; int[] tierToSamples = new int[0]; int[] tierToSelfSamples = new int[0]; @@ -522,9 +524,26 @@ private static class OutputEntry { } } - String format(String format, int[] showTiers, long samplePeriod, int indent, long globalTotalSamples, Integer[] tiers) { + static int computeIndentSize(int depth) { + int indent = depth % DEPTH_BREAK; + if (indent != depth) { + indent += formatIndentBreakLabel(depth - indent).length(); + } + return indent; + } + + private static String formatIndentBreakLabel(int skippedDepth) { + return String.format("(\u21B3%s) ", skippedDepth); + } + + String format(String format, int[] showTiers, long samplePeriod, int depth, long globalTotalSamples, Integer[] tiers) { List args = new ArrayList<>(); - args.add(repeat(" ", indent) + location.getRootName()); + int indent = depth % DEPTH_BREAK; + if (indent != depth) { + args.add(formatIndentBreakLabel(depth - indent) + repeat(" ", indent) + location.getRootName()); + } else { + args.add(repeat(" ", indent) + location.getRootName()); + } args.add(totalSamples * samplePeriod); args.add(percent(totalSamples, globalTotalSamples)); maybeAddTiers(args, tierToSamples, totalSamples, showTiers, tiers); @@ -601,7 +620,7 @@ private void calculateMaxValues(Map node, int depth) { - maxNameLength = Math.max(maxNameLength, node.getRootName().length() + depth); + maxNameLength = Math.max(maxNameLength, node.getRootName().length() + OutputEntry.computeIndentSize(depth)); tiers.add(node.getPayload().getNumberOfTiers() - 1); for (ProfilerNode child : node.getChildren()) { if (!child.isRecursive()) { @@ -644,15 +663,11 @@ private void mergeEntry(List callTreeEntries, ProfilerNode< } private CallTreeOutputEntry makeEntry(ProfilerNode node, int depth) { - maxNameLength = Math.max(maxNameLength, node.getRootName().length() + depth); + maxNameLength = Math.max(maxNameLength, node.getRootName().length() + OutputEntry.computeIndentSize(depth)); tiers.add(node.getPayload().getNumberOfTiers() - 1); CallTreeOutputEntry entry = new CallTreeOutputEntry(node); for (ProfilerNode child : node.getChildren()) { - if (child.isRecursive()) { - entry.merge(child.getPayload()); - } else { - entry.children.add(makeEntry(child, depth + 1)); - } + entry.children.add(makeEntry(child, depth + 1)); } return entry; } From bd5d644fdbaf7d80e9587e78e0249e76f5e831d0 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Fri, 1 Oct 2021 14:09:34 +0200 Subject: [PATCH 260/681] Cancel safepoints when they exceed the period. --- .../oracle/truffle/tools/profiler/SafepointStackSampler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/SafepointStackSampler.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/SafepointStackSampler.java index 30dc8d15c16c..f71e7e2c5dd6 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/SafepointStackSampler.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/SafepointStackSampler.java @@ -98,7 +98,7 @@ List sample(Env env, TruffleContext context, CPUSampler.MutableSamp return Collections.emptyList(); } try { - future.get(period * 10, TimeUnit.MILLISECONDS); + future.get(period, TimeUnit.MILLISECONDS); } catch (InterruptedException | ExecutionException e) { env.getLogger(getClass()).log(Level.SEVERE, "Sampling failed", e); return null; From 49f3817457d3cbfdc33188cbb6fef4f236cc4a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Fri, 1 Oct 2021 15:49:58 +0200 Subject: [PATCH 261/681] Disable tautological-compare warnings in query code compilation on darwin --- .../com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java index b13d562b0b80..f2ddc74f7c7d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java @@ -308,6 +308,12 @@ protected void verify() { } } + @Override + protected List compileStrictOptions() { + List strictOptions = new ArrayList<>(super.compileStrictOptions()); + strictOptions.add("-Wno-tautological-compare"); + return strictOptions; + } } protected InputStream getCompilerErrorStream(Process compilingProcess) { From 36051ccd1e0eef81a1912c426d7b0e806dc8bffc Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Fri, 1 Oct 2021 17:22:12 +0200 Subject: [PATCH 262/681] Cleanup histogram output entry computation. --- .../tools/profiler/impl/CPUSamplerCLI.java | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java index 29b2833c8292..384cd16f6040 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java @@ -411,30 +411,27 @@ private OutputEntry histogramEntry(Map.Entry node : sourceLocationEntry.getValue()) { CPUSampler.Payload payload = node.getPayload(); - for (int i = 0; i < payload.getNumberOfTiers(); i++) { + + int numberOfTiers = payload.getNumberOfTiers(); + if (outputEntry.tierToSelfSamples.length < numberOfTiers) { + outputEntry.tierToSelfSamples = Arrays.copyOf(outputEntry.tierToSelfSamples, numberOfTiers); + } + if (outputEntry.tierToSamples.length < numberOfTiers) { + outputEntry.tierToSamples = Arrays.copyOf(outputEntry.tierToSamples, numberOfTiers); + } + + for (int i = 0; i < numberOfTiers; i++) { int selfHitCountsValue = payload.getTierSelfCount(i); outputEntry.totalSelfSamples += selfHitCountsValue; - if (outputEntry.tierToSelfSamples.length < i + 1) { - outputEntry.tierToSelfSamples = Arrays.copyOf(outputEntry.tierToSelfSamples, outputEntry.tierToSelfSamples.length + 1); - } outputEntry.tierToSelfSamples[i] += selfHitCountsValue; - tiers.add(i); - } - } - for (ProfilerNode node : sourceLocationEntry.getValue()) { - if (node.isRecursive()) { - continue; - } - CPUSampler.Payload payload = node.getPayload(); - for (int i = 0; i < payload.getNumberOfTiers(); i++) { + int hitCountsValue = payload.getTierTotalCount(i); outputEntry.totalSamples += hitCountsValue; - if (outputEntry.tierToSamples.length < i + 1) { - outputEntry.tierToSamples = Arrays.copyOf(outputEntry.tierToSamples, outputEntry.tierToSamples.length + 1); - } outputEntry.tierToSamples[i] += hitCountsValue; + tiers.add(i); } } @@ -623,9 +620,7 @@ private void calculateMaxValuesRec(ProfilerNode node, int de maxNameLength = Math.max(maxNameLength, node.getRootName().length() + OutputEntry.computeIndentSize(depth)); tiers.add(node.getPayload().getNumberOfTiers() - 1); for (ProfilerNode child : node.getChildren()) { - if (!child.isRecursive()) { - calculateMaxValuesRec(child, depth + 1); - } + calculateMaxValuesRec(child, depth + 1); } } From 827a987a630a787593b6ef6db6bca98a2715acb1 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Fri, 1 Oct 2021 16:17:01 +0200 Subject: [PATCH 263/681] Prevent SafeNodes from being canonicalized into IntegerDivRemNodes. --- .../AArch64HotSpotLoweringProvider.java | 5 ++++- .../compiler/nodes/calc/SignedDivNode.java | 20 +++++++++++++++---- .../compiler/nodes/calc/SignedRemNode.java | 13 +++++++++++- .../AArch64IntegerArithmeticSnippets.java | 17 +++++++++++++++- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java index b874472bdea4..a383b2e9eb02 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java @@ -67,7 +67,10 @@ public void initialize(OptionValues options, Iterable fact @Override public void lower(Node n, LoweringTool tool) { if (n instanceof IntegerDivRemNode) { - integerArithmeticSnippets.lower((IntegerDivRemNode) n, tool); + if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.LOW_TIER) { + // wait more precise stamp information + integerArithmeticSnippets.lower((IntegerDivRemNode) n, tool); + } } else if (n instanceof FloatConvertNode) { // AMD64 has custom lowerings for ConvertNodes, HotSpotLoweringProvider does not expect // to see a ConvertNode and throws an error, just do nothing here. diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java index 633a25f7dadb..e9b43c216697 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java @@ -28,12 +28,13 @@ import org.graalvm.compiler.core.common.type.PrimitiveStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -67,6 +68,16 @@ public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode for return canonical(this, forX, forY, getZeroCheck(), view); } + /** + * This is used as a hook to allow AArch64IntegerArithmeticSnippets's SafeSignedDivNode to be + * created during canonicalization. + */ + protected SignedDivNode createWithInputs(ValueNode forX, ValueNode forY, GuardingNode forZeroCheck, FrameState forStateBefore) { + SignedDivNode sd = new SignedDivNode(forX, forY, forZeroCheck); + sd.stateBefore = forStateBefore; + return sd; + } + public static ValueNode canonical(SignedDivNode self, ValueNode forX, ValueNode forY, GuardingNode zeroCheck, NodeView view) { Stamp predictedStamp = IntegerStamp.OPS.getDiv().foldStamp(forX.stamp(NodeView.DEFAULT), forY.stamp(NodeView.DEFAULT)); Stamp stamp = self != null ? self.stamp(view) : predictedStamp; @@ -92,9 +103,10 @@ public static ValueNode canonical(SignedDivNode self, ValueNode forX, ValueNode SignedRemNode integerRemNode = (SignedRemNode) integerSubNode.getY(); if (integerSubNode.stamp(view).isCompatible(stamp) && integerRemNode.stamp(view).isCompatible(stamp) && integerSubNode.getX() == integerRemNode.getX() && forY == integerRemNode.getY()) { - SignedDivNode sd = new SignedDivNode(integerSubNode.getX(), forY, zeroCheck); - sd.stateBefore = self != null ? self.stateBefore : null; - return sd; + if (self != null) { + return self.createWithInputs(integerSubNode.getX(), forY, zeroCheck, self.stateBefore); + } + return new SignedDivNode(integerSubNode.getX(), forY, zeroCheck); } } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java index 38c462072b57..2f23d2dc93e0 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java @@ -28,12 +28,12 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -70,6 +70,14 @@ public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode for return canonical(this, forX, forY, getZeroCheck(), stamp(view), view, tool); } + /** + * This is used as a hook to allow AArch64IntegerArithmeticSnippets's SafeSignedRemNode to be + * created during canonicalization. + */ + protected SignedRemNode createWithInputs(ValueNode forX, ValueNode forY, GuardingNode forZeroCheck) { + return new SignedRemNode(forX, forY, forZeroCheck); + } + private static ValueNode canonical(SignedRemNode self, ValueNode forX, ValueNode forY, GuardingNode zeroCheck, Stamp stamp, NodeView view, CanonicalizerTool tool) { if (forX.isConstant() && forY.isConstant()) { long y = forY.asJavaConstant().asLong(); @@ -114,6 +122,9 @@ private static ValueNode canonical(SignedRemNode self, ValueNode forX, ValueNode if (self != null && self.x == forX && self.y == forY) { return self; } else { + if (self != null) { + return self.createWithInputs(forX, forY, zeroCheck); + } return new SignedRemNode(forX, forY, zeroCheck); } } diff --git a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java index c8b115a9abf0..2a395da9119c 100644 --- a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.DeoptimizeNode; +import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -45,6 +46,7 @@ import org.graalvm.compiler.nodes.calc.UnsignedDivNode; import org.graalvm.compiler.nodes.calc.UnsignedRemNode; import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; +import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.options.OptionValues; @@ -61,7 +63,7 @@ /** * Division in AArch64 ISA does not generate a trap when dividing by zero, but instead sets the - * result to 0. These snippets throw an ArithmethicException if the denominator is 0 and otherwise + * result to 0. These snippets throw an ArithmeticException if the denominator is 0 and otherwise * forward to the LIRGenerator. */ public class AArch64IntegerArithmeticSnippets extends AbstractTemplates implements Snippets { @@ -236,6 +238,13 @@ protected SafeSignedDivNode(ValueNode x, ValueNode y) { super(TYPE, x, y, null); } + @Override + protected SignedDivNode createWithInputs(ValueNode forX, ValueNode forY, GuardingNode forZeroCheck, FrameState forStateBefore) { + assert forZeroCheck == null; + // note that stateBefore is irrelevant, as this "safe" variant will not deoptimize + return new SafeSignedDivNode(forX, forY); + } + @Override public void generate(NodeLIRBuilderTool gen) { // override to ensure we always pass a null frame state @@ -252,6 +261,12 @@ protected SafeSignedRemNode(ValueNode x, ValueNode y) { super(TYPE, x, y, null); } + @Override + protected SignedRemNode createWithInputs(ValueNode forX, ValueNode forY, GuardingNode forZeroCheck) { + assert forZeroCheck == null; + return new SafeSignedRemNode(forX, forY); + } + @Override public void generate(NodeLIRBuilderTool gen) { // override to ensure we always pass a null frame state From 686b4e9bb3b0873a4de0198c6a091edc62f33c06 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Fri, 1 Oct 2021 17:17:48 +0200 Subject: [PATCH 264/681] [GR-34140] Add dispatch object into ExecutionListener and ExecutionEvent. --- .../src/org/graalvm/polyglot/Engine.java | 60 --------- .../polyglot/impl/AbstractPolyglotImpl.java | 28 +++-- .../polyglot/management/ExecutionEvent.java | 29 +++-- .../management/ExecutionListener.java | 20 +-- .../polyglot/management/Management.java | 34 ++++- .../api/test/wrapper/HostEngineDispatch.java | 8 ++ .../test/wrapper/HostPolyglotDispatch.java | 5 - .../polyglot/PolyglotEngineDispatch.java | 113 +++++++++++++++++ .../oracle/truffle/polyglot/PolyglotImpl.java | 3 +- .../polyglot/PolyglotManagementDispatch.java | 116 +----------------- 10 files changed, 203 insertions(+), 213 deletions(-) diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java index 1f2171764020..f2eda02ec391 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java @@ -90,7 +90,6 @@ import org.graalvm.polyglot.io.ByteSequence; import org.graalvm.polyglot.io.FileSystem; import org.graalvm.polyglot.io.MessageTransport; -import org.graalvm.polyglot.management.ExecutionEvent; /** * An execution engine for Graal {@linkplain Language guest languages} that allows to inspect the @@ -909,65 +908,6 @@ public AbstractHostAccess createHostAccess() { throw noPolyglotImplementationFound(); } - @Override - public AbstractManagementDispatch getManagementDispatch() { - return new AbstractManagementDispatch(this) { - - @Override - public boolean isExecutionEventStatement(Object impl) { - return false; - } - - @Override - public boolean isExecutionEventRoot(Object impl) { - return false; - } - - @Override - public boolean isExecutionEventExpression(Object impl) { - return false; - } - - @Override - public String getExecutionEventRootName(Object impl) { - throw noPolyglotImplementationFound(); - } - - @Override - public PolyglotException getExecutionEventException(Object impl) { - throw noPolyglotImplementationFound(); - } - - @Override - public Value getExecutionEventReturnValue(Object impl) { - throw noPolyglotImplementationFound(); - } - - @Override - public SourceSection getExecutionEventLocation(Object impl) { - throw noPolyglotImplementationFound(); - } - - @Override - public List getExecutionEventInputValues(Object impl) { - throw noPolyglotImplementationFound(); - } - - @Override - public void closeExecutionListener(Object impl) { - throw noPolyglotImplementationFound(); - } - - @Override - public Object attachExecutionListener(Object engine, Consumer onEnter, Consumer onReturn, boolean expressions, boolean statements, - boolean roots, - Predicate sourceFilter, Predicate rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectErrors) { - throw noPolyglotImplementationFound(); - } - - }; - } - private static RuntimeException noPolyglotImplementationFound() { String suggestion; if (AOT) { diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java index 3dd202ce7013..840214089ea1 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java @@ -93,6 +93,7 @@ import org.graalvm.polyglot.io.MessageTransport; import org.graalvm.polyglot.io.ProcessHandler; import org.graalvm.polyglot.management.ExecutionEvent; +import org.graalvm.polyglot.management.ExecutionListener; /** * This class is intended to be used by polyglot implementations. Methods in this class are not @@ -114,8 +115,17 @@ protected ManagementAccess() { } } - public abstract ExecutionEvent newExecutionEvent(Object event); + public abstract ExecutionListener newExecutionListener(AbstractManagementDispatch dispatch, Object receiver); + public abstract ExecutionEvent newExecutionEvent(AbstractManagementDispatch dispatch, Object event); + + public abstract Object getReceiver(ExecutionListener executionListener); + + public abstract AbstractManagementDispatch getDispatch(ExecutionListener executionListener); + + public abstract Object getReceiver(ExecutionEvent executionEvent); + + public abstract AbstractManagementDispatch getDispatch(ExecutionEvent executionEvent); } public abstract static class IOAccess { @@ -288,8 +298,6 @@ public abstract Engine buildEngine(OutputStream out, OutputStream err, InputStre public abstract AbstractSourceSectionDispatch getSourceSectionDispatch(); - public abstract AbstractManagementDispatch getManagementDispatch(); - /** * Returns the default host dispatch of this polyglot abstraction. */ @@ -324,13 +332,6 @@ public final AbstractPolyglotImpl getPolyglotImpl() { public abstract void closeExecutionListener(Object impl); - public abstract Object attachExecutionListener(Object engine, Consumer onEnter, - Consumer onReturn, - boolean expressions, - boolean statements, - boolean roots, - Predicate sourceFilter, Predicate rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectExceptions); - public abstract PolyglotException getExecutionEventException(Object impl); } @@ -515,6 +516,13 @@ public abstract Context createContext(Object receiver, OutputStream out, OutputS public abstract String getVersion(Object receiver); + public abstract ExecutionListener attachExecutionListener(Object engine, Consumer onEnter, + Consumer onReturn, + boolean expressions, + boolean statements, + boolean roots, + Predicate sourceFilter, Predicate rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectExceptions); + } public abstract static class AbstractExceptionDispatch { diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/ExecutionEvent.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/ExecutionEvent.java index aae49f709069..29ba91416d65 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/ExecutionEvent.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/ExecutionEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -45,7 +45,8 @@ import org.graalvm.polyglot.PolyglotException; import org.graalvm.polyglot.SourceSection; import org.graalvm.polyglot.Value; -import static org.graalvm.polyglot.management.Management.IMPL; + +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractManagementDispatch; /** * An execution event object passed to an execution listener consumer. Execution event instances @@ -57,10 +58,12 @@ */ public final class ExecutionEvent { - private final Object impl; + final AbstractManagementDispatch dispatch; + final Object receiver; - ExecutionEvent(Object impl) { - this.impl = impl; + ExecutionEvent(AbstractManagementDispatch dispatch, Object receiver) { + this.dispatch = dispatch; + this.receiver = receiver; } /** @@ -70,7 +73,7 @@ public final class ExecutionEvent { * @since 19.0 */ public SourceSection getLocation() { - return IMPL.getExecutionEventLocation(impl); + return dispatch.getExecutionEventLocation(receiver); } /** @@ -81,7 +84,7 @@ public SourceSection getLocation() { * @since 19.0 */ public String getRootName() { - return IMPL.getExecutionEventRootName(impl); + return dispatch.getExecutionEventRootName(receiver); } /** @@ -97,7 +100,7 @@ public String getRootName() { * @since 19.0 */ public List getInputValues() { - return IMPL.getExecutionEventInputValues(impl); + return dispatch.getExecutionEventInputValues(receiver); } /** @@ -111,7 +114,7 @@ public List getInputValues() { * @since 19.0 */ public Value getReturnValue() { - return IMPL.getExecutionEventReturnValue(impl); + return dispatch.getExecutionEventReturnValue(receiver); } /** @@ -125,7 +128,7 @@ public Value getReturnValue() { * @since 19.0 */ public PolyglotException getException() { - return IMPL.getExecutionEventException(impl); + return dispatch.getExecutionEventException(receiver); } /** @@ -136,7 +139,7 @@ public PolyglotException getException() { * @since 19.0 */ public boolean isExpression() { - return IMPL.isExecutionEventExpression(impl); + return dispatch.isExecutionEventExpression(receiver); } /** @@ -147,7 +150,7 @@ public boolean isExpression() { * @since 19.0 */ public boolean isStatement() { - return IMPL.isExecutionEventStatement(impl); + return dispatch.isExecutionEventStatement(receiver); } /** @@ -158,7 +161,7 @@ public boolean isStatement() { * @since 19.0 */ public boolean isRoot() { - return IMPL.isExecutionEventRoot(impl); + return dispatch.isExecutionEventRoot(receiver); } /** diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/ExecutionListener.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/ExecutionListener.java index 03f479474f85..5020eae9a4bf 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/ExecutionListener.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/ExecutionListener.java @@ -47,6 +47,8 @@ import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.PolyglotException; import org.graalvm.polyglot.Source; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractManagementDispatch; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.APIAccess; /** * Execution listeners allow to instrument the execution of guest languages. For example, it is @@ -190,11 +192,13 @@ */ public final class ExecutionListener implements AutoCloseable { - private static final ExecutionListener EMPTY = new ExecutionListener(null); - private final Object impl; + private static final ExecutionListener EMPTY = new ExecutionListener(null, null); + final AbstractManagementDispatch dispatch; + final Object receiver; - private ExecutionListener(Object impl) { - this.impl = impl; + ExecutionListener(AbstractManagementDispatch dispatch, Object receiver) { + this.dispatch = dispatch; + this.receiver = receiver; } /** @@ -211,7 +215,7 @@ private ExecutionListener(Object impl) { * @since 19.0 */ public void close() { - Management.IMPL.closeExecutionListener(impl); + dispatch.closeExecutionListener(receiver); } /** @@ -422,9 +426,9 @@ public Builder collectExceptions(boolean enabled) { * @since 19.0 */ public ExecutionListener attach(Engine engine) { - return new ExecutionListener( - Management.IMPL.attachExecutionListener(Management.IMPL.getPolyglotImpl().getAPIAccess().getReceiver(engine), onEnter, onReturn, expressions, statements, roots, - sourceFilter, rootNameFilter, collectInputValues, collectReturnValues, collectExceptions)); + APIAccess apiAccess = Management.IMPL.getAPIAccess(); + return apiAccess.getDispatch(engine).attachExecutionListener(apiAccess.getReceiver(engine), onEnter, onReturn, expressions, statements, roots, + sourceFilter, rootNameFilter, collectInputValues, collectReturnValues, collectExceptions); } } diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/Management.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/Management.java index 957ec9ddb2c4..7770320f9cbe 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/Management.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/Management.java @@ -55,15 +55,15 @@ final class Management { private Management() { } - static final AbstractManagementDispatch IMPL = initImpl(); + static final AbstractPolyglotImpl IMPL = initImpl(); - private static AbstractManagementDispatch initImpl() { + private static AbstractPolyglotImpl initImpl() { try { Method method = Engine.class.getDeclaredMethod("getImpl"); method.setAccessible(true); AbstractPolyglotImpl impl = (AbstractPolyglotImpl) method.invoke(null); impl.setMonitoring(new ManagementAccessImpl()); - return impl.getManagementDispatch(); + return impl; } catch (Exception e) { throw new IllegalStateException("Failed to initialize execution listener class.", e); } @@ -72,10 +72,34 @@ private static AbstractManagementDispatch initImpl() { private static final class ManagementAccessImpl extends ManagementAccess { @Override - public ExecutionEvent newExecutionEvent(Object event) { - return new ExecutionEvent(event); + public ExecutionListener newExecutionListener(AbstractManagementDispatch dispatch, Object receiver) { + return new ExecutionListener(dispatch, receiver); } + @Override + public ExecutionEvent newExecutionEvent(AbstractManagementDispatch dispatch, Object event) { + return new ExecutionEvent(dispatch, event); + } + + @Override + public Object getReceiver(ExecutionListener executionListener) { + return executionListener.receiver; + } + + @Override + public AbstractManagementDispatch getDispatch(ExecutionListener executionListener) { + return executionListener.dispatch; + } + + @Override + public Object getReceiver(ExecutionEvent executionEvent) { + return executionEvent.receiver; + } + + @Override + public AbstractManagementDispatch getDispatch(ExecutionEvent executionEvent) { + return executionEvent.dispatch; + } } } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEngineDispatch.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEngineDispatch.java index f69d045ab454..44c3756960b9 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEngineDispatch.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostEngineDispatch.java @@ -45,6 +45,7 @@ import java.time.ZoneId; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Predicate; import org.graalvm.options.OptionDescriptors; @@ -60,6 +61,8 @@ import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractEngineDispatch; import org.graalvm.polyglot.io.FileSystem; import org.graalvm.polyglot.io.ProcessHandler; +import org.graalvm.polyglot.management.ExecutionEvent; +import org.graalvm.polyglot.management.ExecutionListener; public class HostEngineDispatch extends AbstractEngineDispatch { @@ -145,4 +148,9 @@ public String getVersion(Object receiver) { throw new UnsupportedOperationException(); } + @Override + public ExecutionListener attachExecutionListener(Object engine, Consumer onEnter, Consumer onReturn, boolean expressions, boolean statements, boolean roots, + Predicate sourceFilter, Predicate rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectExceptions) { + throw new UnsupportedOperationException(); + } } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java index ad433bbcb4f9..d915d23dd136 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java @@ -119,11 +119,6 @@ public AbstractSourceSectionDispatch getSourceSectionDispatch() { return getNext().getSourceSectionDispatch(); } - @Override - public AbstractManagementDispatch getManagementDispatch() { - return getNext().getManagementDispatch(); - } - @Override public Class loadLanguageClass(String className) { return getNext().loadLanguageClass(className); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineDispatch.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineDispatch.java index 665b008f881c..f82733796fc3 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineDispatch.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineDispatch.java @@ -43,10 +43,21 @@ import java.io.InputStream; import java.io.OutputStream; import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Predicate; +import com.oracle.truffle.api.instrumentation.EventBinding; +import com.oracle.truffle.api.instrumentation.EventContext; +import com.oracle.truffle.api.instrumentation.ExecutionEventNode; +import com.oracle.truffle.api.instrumentation.ExecutionEventNodeFactory; +import com.oracle.truffle.api.instrumentation.Instrumenter; +import com.oracle.truffle.api.instrumentation.SourceSectionFilter; +import com.oracle.truffle.api.instrumentation.StandardTags; +import com.oracle.truffle.api.instrumentation.Tag; import org.graalvm.options.OptionDescriptors; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Engine; @@ -57,10 +68,13 @@ import org.graalvm.polyglot.PolyglotAccess; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractEngineDispatch; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractManagementDispatch; import org.graalvm.polyglot.io.FileSystem; import org.graalvm.polyglot.io.ProcessHandler; import com.oracle.truffle.api.Truffle; +import org.graalvm.polyglot.management.ExecutionEvent; +import org.graalvm.polyglot.management.ExecutionListener; final class PolyglotEngineDispatch extends AbstractEngineDispatch { @@ -180,4 +194,103 @@ public String getVersion(Object oreceiver) { } } + @Override + public ExecutionListener attachExecutionListener(Object engineReceiver, Consumer onEnter, Consumer onReturn, boolean expressions, boolean statements, + boolean roots, + Predicate sourceFilter, Predicate rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectExceptions) { + PolyglotEngineImpl engine = (PolyglotEngineImpl) engineReceiver; + Instrumenter instrumenter = (Instrumenter) EngineAccessor.INSTRUMENT.getEngineInstrumenter(engine.instrumentationHandler); + + List> tags = new ArrayList<>(); + if (expressions) { + tags.add(StandardTags.ExpressionTag.class); + } + if (statements) { + tags.add(StandardTags.StatementTag.class); + } + if (roots) { + tags.add(StandardTags.RootTag.class); + } + + if (tags.isEmpty()) { + throw new IllegalArgumentException("No elements specified to listen to for execution listener. Need to specify at least one element kind: expressions, statements or roots."); + } + if (onReturn == null && onEnter == null) { + throw new IllegalArgumentException("At least one event consumer must be provided for onEnter or onReturn."); + } + + SourceSectionFilter.Builder filterBuilder = SourceSectionFilter.newBuilder().tagIs(tags.toArray(new Class[0])); + filterBuilder.includeInternal(false); + + AbstractManagementDispatch managementDispatch = polyglot.getManagementDispatch(); + PolyglotManagementDispatch.ListenerImpl config = new PolyglotManagementDispatch.ListenerImpl(managementDispatch, engine, onEnter, onReturn, collectInputValues, collectReturnValues, + collectExceptions); + + filterBuilder.sourceIs(new SourceSectionFilter.SourcePredicate() { + public boolean test(com.oracle.truffle.api.source.Source s) { + String language = s.getLanguage(); + if (language == null) { + return false; + } else if (!engine.idToLanguage.containsKey(language)) { + return false; + } else if (sourceFilter != null) { + try { + return sourceFilter.test(PolyglotImpl.getOrCreatePolyglotSource(polyglot, s)); + } catch (Throwable e) { + if (config.closing) { + // configuration is closing ignore errors. + return false; + } + throw engine.host.toHostException(null, e); + } + } else { + return true; + } + } + }); + + if (rootFilter != null) { + filterBuilder.rootNameIs(new Predicate() { + public boolean test(String s) { + try { + return rootFilter.test(s); + } catch (Throwable e) { + if (config.closing) { + // configuration is closing ignore errors. + return false; + } + throw engine.host.toHostException(null, e); + } + } + }); + } + + SourceSectionFilter filter = filterBuilder.build(); + EventBinding binding; + try { + boolean mayNeedInputValues = config.collectInputValues && config.onReturn != null; + boolean mayNeedReturnValue = config.collectReturnValues && config.onReturn != null; + boolean mayNeedExceptions = config.collectExceptions; + + if (mayNeedInputValues || mayNeedReturnValue || mayNeedExceptions) { + binding = instrumenter.attachExecutionEventFactory(filter, mayNeedInputValues ? filter : null, new ExecutionEventNodeFactory() { + public ExecutionEventNode create(EventContext context) { + return new PolyglotManagementDispatch.ProfilingNode(config, context); + } + }); + } else { + // fast path no collection of additional profiles + binding = instrumenter.attachExecutionEventFactory(filter, null, new ExecutionEventNodeFactory() { + public ExecutionEventNode create(EventContext context) { + return new PolyglotManagementDispatch.DefaultNode(config, context); + } + }); + } + } catch (Throwable t) { + throw PolyglotImpl.guestToHostException(engine, t); + } + config.binding = binding; + return polyglot.getManagement().newExecutionListener(managementDispatch, config); + } + } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java index 73327ca6c2b1..2cbefca6daf5 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java @@ -178,8 +178,7 @@ public AbstractSourceSectionDispatch getSourceSectionDispatch() { /** * Internal method do not use. */ - @Override - public AbstractManagementDispatch getManagementDispatch() { + AbstractManagementDispatch getManagementDispatch() { return executionListenerDispatch; } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotManagementDispatch.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotManagementDispatch.java index 47981ec2a223..9d29aa01c0a5 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotManagementDispatch.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotManagementDispatch.java @@ -41,13 +41,10 @@ package com.oracle.truffle.polyglot; import java.util.AbstractList; -import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; -import java.util.function.Predicate; import org.graalvm.polyglot.PolyglotException; -import org.graalvm.polyglot.Source; import org.graalvm.polyglot.SourceSection; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractManagementDispatch; @@ -61,10 +58,6 @@ import com.oracle.truffle.api.instrumentation.EventBinding; import com.oracle.truffle.api.instrumentation.EventContext; import com.oracle.truffle.api.instrumentation.ExecutionEventNode; -import com.oracle.truffle.api.instrumentation.ExecutionEventNodeFactory; -import com.oracle.truffle.api.instrumentation.Instrumenter; -import com.oracle.truffle.api.instrumentation.SourceSectionFilter; -import com.oracle.truffle.api.instrumentation.SourceSectionFilter.SourcePredicate; import com.oracle.truffle.api.instrumentation.StandardTags; import com.oracle.truffle.api.instrumentation.Tag; import com.oracle.truffle.api.nodes.RootNode; @@ -72,112 +65,13 @@ final class PolyglotManagementDispatch extends AbstractManagementDispatch { static final Object[] EMPTY_ARRAY = new Object[0]; - private final PolyglotImpl engineImpl; PolyglotManagementDispatch(PolyglotImpl engineImpl) { super(engineImpl); - this.engineImpl = engineImpl; } // implementation for org.graalvm.polyglot.management.ExecutionListener - @Override - public Object attachExecutionListener(Object engineReceiver, Consumer onEnter, Consumer onReturn, boolean expressions, boolean statements, - boolean roots, - Predicate sourceFilter, Predicate rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectExceptions) { - PolyglotEngineImpl engine = (PolyglotEngineImpl) engineReceiver; - Instrumenter instrumenter = (Instrumenter) EngineAccessor.INSTRUMENT.getEngineInstrumenter(engine.instrumentationHandler); - - List> tags = new ArrayList<>(); - if (expressions) { - tags.add(StandardTags.ExpressionTag.class); - } - if (statements) { - tags.add(StandardTags.StatementTag.class); - } - if (roots) { - tags.add(StandardTags.RootTag.class); - } - - if (tags.isEmpty()) { - throw new IllegalArgumentException("No elements specified to listen to for execution listener. Need to specify at least one element kind: expressions, statements or roots."); - } - if (onReturn == null && onEnter == null) { - throw new IllegalArgumentException("At least one event consumer must be provided for onEnter or onReturn."); - } - - SourceSectionFilter.Builder filterBuilder = SourceSectionFilter.newBuilder().tagIs(tags.toArray(new Class[0])); - filterBuilder.includeInternal(false); - - ListenerImpl config = new ListenerImpl(engine, onEnter, onReturn, collectInputValues, collectReturnValues, collectExceptions); - - filterBuilder.sourceIs(new SourcePredicate() { - public boolean test(com.oracle.truffle.api.source.Source s) { - String language = s.getLanguage(); - if (language == null) { - return false; - } else if (!engine.idToLanguage.containsKey(language)) { - return false; - } else if (sourceFilter != null) { - try { - return sourceFilter.test(PolyglotImpl.getOrCreatePolyglotSource(engineImpl, s)); - } catch (Throwable e) { - if (config.closing) { - // configuration is closing ignore errors. - return false; - } - throw engine.host.toHostException(null, e); - } - } else { - return true; - } - } - }); - - if (rootFilter != null) { - filterBuilder.rootNameIs(new Predicate() { - public boolean test(String s) { - try { - return rootFilter.test(s); - } catch (Throwable e) { - if (config.closing) { - // configuration is closing ignore errors. - return false; - } - throw engine.host.toHostException(null, e); - } - } - }); - } - - SourceSectionFilter filter = filterBuilder.build(); - EventBinding binding; - try { - boolean mayNeedInputValues = config.collectInputValues && config.onReturn != null; - boolean mayNeedReturnValue = config.collectReturnValues && config.onReturn != null; - boolean mayNeedExceptions = config.collectExceptions; - - if (mayNeedInputValues || mayNeedReturnValue || mayNeedExceptions) { - binding = instrumenter.attachExecutionEventFactory(filter, mayNeedInputValues ? filter : null, new ExecutionEventNodeFactory() { - public ExecutionEventNode create(EventContext context) { - return new ProfilingNode(config, context); - } - }); - } else { - // fast path no collection of additional profiles - binding = instrumenter.attachExecutionEventFactory(filter, null, new ExecutionEventNodeFactory() { - public ExecutionEventNode create(EventContext context) { - return new DefaultNode(config, context); - } - }); - } - } catch (Throwable t) { - throw wrapException(engine, t); - } - config.binding = binding; - return config; - } - @Override public void closeExecutionListener(Object impl) { try { @@ -258,6 +152,7 @@ private static RuntimeException wrapException(Object impl, Throwable t) { static class ListenerImpl { + final AbstractManagementDispatch managementDispatch; final PolyglotEngineImpl engine; final Consumer onEnter; final Consumer onReturn; @@ -269,11 +164,12 @@ static class ListenerImpl { volatile EventBinding binding; volatile boolean closing; - ListenerImpl(PolyglotEngineImpl engine, Consumer onEnter, + ListenerImpl(AbstractManagementDispatch managementDispatch, PolyglotEngineImpl engine, Consumer onEnter, Consumer onReturn, boolean collectInputValues, boolean collectReturnValues, boolean collectExceptions) { + this.managementDispatch = managementDispatch; this.engine = engine; this.onEnter = onEnter; this.onReturn = onReturn; @@ -479,7 +375,7 @@ private void invokeReturnAllocate(Object[] inputValues, Object result) { @TruffleBoundary(allowInlining = true) protected final void invokeExceptionAllocate(List inputValues, Throwable e) { PolyglotException ex = e != null ? PolyglotImpl.guestToHostException(language.getCurrentLanguageContext(), e, true) : null; - config.onReturn.accept(config.management.newExecutionEvent(new DynamicEvent(this, inputValues, null, ex))); + config.onReturn.accept(config.management.newExecutionEvent(config.managementDispatch, new DynamicEvent(this, inputValues, null, ex))); } } @@ -525,7 +421,7 @@ abstract static class AbstractNode extends ExecutionEventNode implements Event { this.config = config; this.context = context; this.location = PolyglotImpl.getPolyglotSourceSection(config.engine.impl, context.getInstrumentedSourceSection()); - this.cachedEvent = config.engine.impl.getManagement().newExecutionEvent(this); + this.cachedEvent = config.management.newExecutionEvent(config.managementDispatch, this); } public String getRootName() { @@ -574,7 +470,7 @@ protected final void invokeException() { @TruffleBoundary(allowInlining = true) protected final void invokeReturnAllocate(List inputValues, Value returnValue) { - config.onReturn.accept(config.management.newExecutionEvent(new DynamicEvent(this, inputValues, returnValue, null))); + config.onReturn.accept(config.management.newExecutionEvent(config.managementDispatch, new DynamicEvent(this, inputValues, returnValue, null))); } public final SourceSection getLocation() { From 2b3e1e4a4bf7e1fbc5f44d870f90b539065dc829 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Fri, 1 Oct 2021 17:48:15 +0200 Subject: [PATCH 265/681] Restore recursion detection for total sum. --- .../com/oracle/truffle/tools/profiler/ProfilerNode.java | 8 ++++++-- .../oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java | 8 +++++++- .../oracle/truffle/tools/profiler/impl/ProfilerCLI.java | 6 +++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/ProfilerNode.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/ProfilerNode.java index 2ee2d1e8f9fe..781bd7efb669 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/ProfilerNode.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/ProfilerNode.java @@ -91,13 +91,17 @@ public ProfilerNode getParent() { * @since 0.30 */ public boolean isRecursive() { + return isRecursiveImpl(this); + } + + private boolean isRecursiveImpl(ProfilerNode source) { if (parent.sourceLocation == null) { return false; } - if (parent.sourceLocation.equals(this.sourceLocation)) { + if (parent.sourceLocation.equals(source.sourceLocation)) { return true; } - return false; + return parent.isRecursiveImpl(source); } /** diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java index 384cd16f6040..6c987ea27115 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/CPUSamplerCLI.java @@ -427,12 +427,18 @@ private OutputEntry histogramEntry(Map.Entry Date: Fri, 1 Oct 2021 18:33:40 +0200 Subject: [PATCH 266/681] Remove link to non-existing image --- docs/tools/vscode/micronaut/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/tools/vscode/micronaut/README.md b/docs/tools/vscode/micronaut/README.md index d5e98099cd1b..8e8935c68048 100644 --- a/docs/tools/vscode/micronaut/README.md +++ b/docs/tools/vscode/micronaut/README.md @@ -112,8 +112,6 @@ For more details, continue reading to the [Micronaut documentation](https://guid The Micronaut support in VSCode also allows to build and deploy Docker image to a Docker Registry. Use action View > Command Palette > Micronaut: Deploy... and select **dockerPush** to deploy dockerized Micronaut application or **dockerPushNative** to build and push docker with a native executable of Micronaut application. -![Micronaut Deploy Commands](images/micronaut-deploy-commands.png) - Besides that, you can also push a Micronaut application or a native executable to a Docker Registry from the VS Code terminal window. A particular Docker Registry can be configured in the build, see the [Micronaut Deploying Application](https://micronaut-projects.github.io/micronaut-maven-plugin/latest/examples/deploy.html) documentation. ### Feedback From 30414c264e0bbd69439d3e201c36c227847bb580 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Fri, 1 Oct 2021 18:21:46 +0200 Subject: [PATCH 267/681] Fix links --- docs/examples/examples.md | 2 +- docs/reference-manual/java/README.md | 4 ++-- docs/reference-manual/languages.md | 8 ++++---- docs/tools/graalvm-insight.md | 2 +- truffle/README.md | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/examples/examples.md b/docs/examples/examples.md index 56add0222ed7..dc996a9ca382 100644 --- a/docs/examples/examples.md +++ b/docs/examples/examples.md @@ -20,5 +20,5 @@ Here you can also find an even more sophisticated example of polyglot native exe The [Java/Kotlin Native Image Example](java-kotlin-aot.md) demonstrates how to compile a Java and Kotlin application ahead-of-time, and illustrates the performance gain. -The [Oracle Database Example](examples/mle-oracle.md) contains instructions on how to run the Oracle Database Multilingual Engine (MLE) which is the integration of GraalVM in the Oracle +The [Oracle Database Example](mle-oracle.md) contains instructions on how to run the Oracle Database Multilingual Engine (MLE) which is the integration of GraalVM in the Oracle Database 21c. diff --git a/docs/reference-manual/java/README.md b/docs/reference-manual/java/README.md index 6dac35785069..a710012e773a 100644 --- a/docs/reference-manual/java/README.md +++ b/docs/reference-manual/java/README.md @@ -33,5 +33,5 @@ This mode allows you to [debug the GraalVM compiler with a Java debugger](Operat ## Interoperability -In addition to running JVM-based languages on GraalVM, you can also call any other language implemented with the [Truffle language implementation framework](../truffle-framework/README.md) directly from Java. -See the [Polyglot Programming](../polyglot-programming.md) and [Embedding Languages](../embed-languages.md) guides for more information about interoperability with other programming languages. +In addition to running JVM-based languages on GraalVM, you can also call any other language implemented with the [Truffle language implementation framework](../../../truffle/docs/README.md) directly from Java. +See the [Polyglot Programming](../polyglot-programming.md) and [Embedding Languages](../embedding/embed-languages.md) guides for more information about interoperability with other programming languages. diff --git a/docs/reference-manual/languages.md b/docs/reference-manual/languages.md index 061c9f85a505..9354047ae4b3 100644 --- a/docs/reference-manual/languages.md +++ b/docs/reference-manual/languages.md @@ -13,9 +13,9 @@ GraalVM's polyglot capabilities make it possible to mix multiple programming lan If you are mostly interested in GraalVM's support for a specific language, here you can find the most extensive documentation: * [Java](java/README.md) * [Java on Truffle](java-on-truffle/README.md) -* [JavaScript and Node.js](js/README.md) +* [JavaScript and Node.js](https://github.com/oracle/graaljs/blob/master/docs/user/README.md) * [LLVM Languages](llvm/README.md) -* [Python](python/README.md) -* [R](r/README.md) -* [Ruby](ruby/README.md) +* [Python](https://github.com/oracle/graalpython/blob/master/docs/user/README.md) +* [R](https://github.com/oracle/fastr/blob/master/documentation/user/README.md) +* [Ruby](https://github.com/oracle/truffleruby/blob/master/doc/user/README.md) * [WebAssembly](wasm/README.md) diff --git a/docs/tools/graalvm-insight.md b/docs/tools/graalvm-insight.md index daafa72079c7..752869b2375c 100644 --- a/docs/tools/graalvm-insight.md +++ b/docs/tools/graalvm-insight.md @@ -146,7 +146,7 @@ Hello from GraalVM Ruby! It is necessary to start the Ruby launcher with the `--polyglot` parameter, as the _source-tracing.js_ script remains written in JavaScript. A user can instrument any language on top of GraalVM, but also the Insight scripts can be -written in any of the GraalVM supported languages (implemented with the [Truffle language implementation framework](../graalvm-as-a-platform/truffle-framework/README.md)). +written in any of the GraalVM supported languages (implemented with the [Truffle language implementation framework](../../truffle/docs/README.md)). 1. Create the _source-tracing.rb_ Ruby file: ```ruby diff --git a/truffle/README.md b/truffle/README.md index cc3377380cfb..beb91687474d 100644 --- a/truffle/README.md +++ b/truffle/README.md @@ -17,7 +17,7 @@ Software of the Johannes Kepler University Linz. ## Using Truffle -If you are looking for documentation on how to use Truffle, please consult the documentation [here](../docs/truffle-framework/README.md) or [on the website](https://www.graalvm.org/graalvm-as-a-platform/language-implementation-framework/). +If you are looking for documentation on how to use Truffle, please consult the documentation [here](docs/README.md) or [on the website](https://www.graalvm.org/graalvm-as-a-platform/language-implementation-framework/). ## Hacking Truffle From 550296a4313d984bf053402e2070dd49c85ec98b Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Tue, 28 Sep 2021 16:09:52 -0700 Subject: [PATCH 268/681] Covariant return types in NodeInterface.asNode overrides are bad for code shape --- .../core/test/VerifyUpdateUsages.java | 7 ++-- .../src/org/graalvm/compiler/graph/Node.java | 11 +----- .../graalvm/compiler/graph/NodeInputList.java | 6 ---- .../org/graalvm/compiler/graph/NodeList.java | 21 ----------- .../meta/DefaultHotSpotLoweringProvider.java | 4 +-- .../hotspot/replacements/FastNotifyNode.java | 2 +- .../org/graalvm/compiler/nodes/FixedNode.java | 3 +- .../compiler/nodes/FixedNodeInterface.java | 6 ++-- .../compiler/nodes/FixedWithNextNode.java | 5 +-- .../nodes/FixedWithNextNodeInterface.java} | 11 +++--- .../graalvm/compiler/nodes/InliningLog.java | 30 +++++++--------- .../org/graalvm/compiler/nodes/Invokable.java | 19 +++++----- .../org/graalvm/compiler/nodes/Invoke.java | 4 +++ .../graalvm/compiler/nodes/InvokeNode.java | 5 --- .../nodes/InvokeWithExceptionNode.java | 5 --- .../org/graalvm/compiler/nodes/ValueNode.java | 7 +++- .../compiler/nodes/ValueNodeInterface.java | 24 ++++++++++--- .../compiler/nodes/calc/FloatingNode.java | 5 --- .../nodes/extended/ArrayRangeWrite.java | 8 ++--- .../nodes/gc/CardTableBarrierSet.java | 3 +- .../nodes/java/AbstractNewArrayNode.java | 10 ++++-- .../nodes/java/MethodCallTargetNode.java | 2 +- .../nodes/java/NewArrayInterface.java | 35 +++++++++++++++++++ .../compiler/nodes/memory/MemoryAccess.java | 4 +-- .../org/graalvm/compiler/nodes/spi/Proxy.java | 4 +-- .../compiler/phases/common/LoweringPhase.java | 5 --- .../common/ProfileCompiledMethodsPhase.java | 2 +- .../phases/common/inlining/InliningUtil.java | 10 +++--- .../info/MultiTypeGuardInlineInfo.java | 6 ++-- .../inlining/info/TypeGuardInlineInfo.java | 2 +- .../inlining/info/elem/InlineableGraph.java | 2 +- .../walker/CallsiteHolderExplorable.java | 2 +- .../walker/ComputeInliningRelevance.java | 4 +-- .../phases/graph/PostOrderNodeIterator.java | 2 +- .../phases/graph/SinglePassNodeIterator.java | 2 +- .../compiler/replacements/PEGraphDecoder.java | 10 +++--- .../replacements/nodes/MacroNode.java | 6 ---- .../nodes/MacroWithExceptionNode.java | 6 ---- .../pointsto/flow/MethodTypeFlowBuilder.java | 2 +- .../pointsto/phases/InlineBeforeAnalysis.java | 2 +- .../pointsto/results/StrengthenGraphs.java | 4 +-- .../oracle/svm/graal/hosted/GraalFeature.java | 2 +- .../hosted/phases/DevirtualizeCallsPhase.java | 4 +-- .../phases/HostedGraphBuilderPhase.java | 4 +-- .../phases/ImplicitAssertionsPhase.java | 4 +-- 45 files changed, 163 insertions(+), 159 deletions(-) rename compiler/src/{org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeInterface.java => org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedWithNextNodeInterface.java} (78%) create mode 100644 compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayInterface.java diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUpdateUsages.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUpdateUsages.java index e4fd9fc76940..de774d7e718d 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUpdateUsages.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUpdateUsages.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.Node.OptionalInput; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; @@ -43,7 +44,7 @@ /** * Try to ensure that methods which update {@link Input} or {@link OptionalInput} fields also - * include a call to {@link Node#updateUsages} or {@link Node#updateUsagesInterface}. + * include a call to {@link Node#updateUsages} or {@link ValueNode#updateUsagesInterface}. */ public class VerifyUpdateUsages extends VerifyPhase { @@ -92,9 +93,11 @@ protected void verify(StructuredGraph graph, CoreProviders context) { // Single input field update so just check for updateUsages // or updateUsagesInterface call ResolvedJavaType nodeType = context.getMetaAccess().lookupJavaType(Node.class); + ResolvedJavaType valueNodeType = context.getMetaAccess().lookupJavaType(ValueNode.class); for (MethodCallTargetNode call : graph.getNodes().filter(MethodCallTargetNode.class)) { ResolvedJavaMethod callee = call.targetMethod(); - if (callee.getDeclaringClass().equals(nodeType) && (callee.getName().equals("updateUsages") || callee.getName().equals("updateUsagesInterface"))) { + if ((callee.getDeclaringClass().equals(nodeType) && (callee.getName().equals("updateUsages"))) || + (callee.getDeclaringClass().equals(valueNodeType) && callee.getName().equals("updateUsagesInterface"))) { return; } } diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index b1e358b7a060..d2bbcf3cbf9c 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -82,7 +82,7 @@ * only performed if assertions are enabled. */ @NodeInfo -public abstract class Node implements Cloneable, Formattable, NodeInterface { +public abstract class Node implements Cloneable, Formattable { private static final Unsafe UNSAFE = getUnsafe(); @@ -304,11 +304,6 @@ final int id() { return id; } - @Override - public Node asNode() { - return this; - } - /** * Gets the graph context of this node. */ @@ -620,10 +615,6 @@ protected void updateUsages(Node oldInput, Node newInput) { } } - protected void updateUsagesInterface(NodeInterface oldInput, NodeInterface newInput) { - updateUsages(oldInput == null ? null : oldInput.asNode(), newInput == null ? null : newInput.asNode()); - } - /** * Updates the predecessor of the given nodes after a successor slot is changed from * oldSuccessor to newSuccessor: removes this node from oldSuccessor's predecessors and adds diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeInputList.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeInputList.java index bcad5f13e615..55ec72e6e3a3 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeInputList.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeInputList.java @@ -26,7 +26,6 @@ import static org.graalvm.compiler.graph.Edges.Type.Inputs; -import java.util.Collection; import java.util.List; import org.graalvm.compiler.graph.Edges.Type; @@ -51,11 +50,6 @@ public NodeInputList(Node self, List elements) { assert self.hasNoUsages(); } - public NodeInputList(Node self, Collection elements) { - super(self, elements); - assert self.hasNoUsages(); - } - @Override protected void update(T oldNode, T newNode) { self.updateUsages(oldNode, newNode); diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java index 05911e41673b..01d7fab4ee2c 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java @@ -110,27 +110,6 @@ private static void checkMaxSize(int value) { } } - protected NodeList(Node self, Collection elements) { - this.self = self; - if (elements == null || elements.isEmpty()) { - this.size = 0; - this.nodes = EMPTY_NODE_ARRAY; - this.initialSize = 0; - } else { - int newSize = elements.size(); - checkMaxSize(newSize); - this.size = newSize; - this.initialSize = newSize; - this.nodes = new Node[elements.size()]; - int i = 0; - for (NodeInterface n : elements) { - this.nodes[i] = n.asNode(); - assert this.nodes[i] == null || !this.nodes[i].isDeleted(); - i++; - } - } - } - /** * Removes {@code null} values from the list. */ diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 60da73af6d40..9beeae736586 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -615,7 +615,7 @@ private void lowerInvoke(Invoke invoke, LoweringTool tool, StructuredGraph graph if (!callTarget.isStatic()) { assert receiver != null : "non-static call must have a receiver"; if (receiver.stamp(NodeView.DEFAULT) instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { - ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool); + ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asFixedNode(), tool); parameters.set(0, nonNullReceiver); receiver = nonNullReceiver; } @@ -643,7 +643,7 @@ private void lowerInvoke(Invoke invoke, LoweringTool tool, StructuredGraph graph signature, callTarget.targetMethod(), HotSpotCallingConventionType.JavaCall, callTarget.invokeKind())); - graph.addBeforeFixed(invoke.asNode(), metaspaceMethod); + graph.addBeforeFixed(invoke.asFixedNode(), metaspaceMethod); graph.addAfterFixed(metaspaceMethod, compiledEntry); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/FastNotifyNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/FastNotifyNode.java index ac223e1a0fe1..f3d899f231b7 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/FastNotifyNode.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/FastNotifyNode.java @@ -81,7 +81,7 @@ public void setStateDuring(FrameState stateDuring) { @Override public void computeStateDuring(FrameState currentStateAfter) { - FrameState newStateDuring = currentStateAfter.duplicateModifiedDuringCall(bci, asNode().getStackKind()); + FrameState newStateDuring = currentStateAfter.duplicateModifiedDuringCall(bci, getStackKind()); setStateDuring(newStateDuring); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNode.java index 7bedd4f25f00..f9da728707db 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNode.java @@ -42,8 +42,9 @@ public boolean verify() { return super.verify(); } + /* This method is final to ensure that it can be de-virtualized and inlined. */ @Override - public FixedNode asNode() { + public final FixedNode asFixedNode() { return this; } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNodeInterface.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNodeInterface.java index b89d4497ac26..0fc06896f530 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNodeInterface.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedNodeInterface.java @@ -24,7 +24,9 @@ */ package org.graalvm.compiler.nodes; +/** + * See {@link ValueNodeInterface} for details about these node interfaces. + */ public interface FixedNodeInterface extends ValueNodeInterface { - @Override - FixedNode asNode(); + FixedNode asFixedNode(); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedWithNextNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedWithNextNode.java index a47b6ba926b2..7c4803771fdc 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedWithNextNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedWithNextNode.java @@ -33,7 +33,7 @@ * successor. */ @NodeInfo -public abstract class FixedWithNextNode extends FixedNode { +public abstract class FixedWithNextNode extends FixedNode implements FixedWithNextNodeInterface { public static final NodeClass TYPE = NodeClass.create(FixedWithNextNode.class); @Successor protected FixedNode next; @@ -51,8 +51,9 @@ public FixedWithNextNode(NodeClass c, Stamp stamp) super(c, stamp); } + /* This method is final to ensure that it can be de-virtualized and inlined. */ @Override - public FixedWithNextNode asNode() { + public final FixedWithNextNode asFixedWithNextNode() { return this; } } diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeInterface.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedWithNextNodeInterface.java similarity index 78% rename from compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeInterface.java rename to compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedWithNextNodeInterface.java index 6ed0030589d4..184265475c42 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeInterface.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedWithNextNodeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -22,8 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.graph; +package org.graalvm.compiler.nodes; -public interface NodeInterface { - Node asNode(); +/** + * See {@link ValueNodeInterface} for details about these node interfaces. + */ +public interface FixedWithNextNodeInterface extends FixedNodeInterface { + FixedWithNextNode asFixedWithNextNode(); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java index 0cb5688c0282..de002c0ce596 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java @@ -190,13 +190,13 @@ public void addDecision(Invokable invoke, boolean positive, String phase, Econom } MapCursor entries = calleeLog.leaves.getEntries(); while (entries.advance()) { - Invokable invokeFromCallee = entries.getKey(); + FixedNode invokeFromCallee = entries.getKey().asFixedNodeOrNull(); Callsite callsiteFromCallee = entries.getValue(); - if (invokeFromCallee.asFixedNode().isDeleted()) { + if (invokeFromCallee == null || invokeFromCallee.isDeleted()) { // Some invoke nodes could have been removed by optimizations. continue; } - Invokable inlinedInvokeFromCallee = (Invokable) replacements.get(invokeFromCallee.asFixedNode()); + Invokable inlinedInvokeFromCallee = (Invokable) replacements.get(invokeFromCallee); Callsite descendant = mapping.get(callsiteFromCallee); leaves.put(inlinedInvokeFromCallee, descendant); } @@ -219,13 +219,13 @@ public void addLog(UnmodifiableEconomicMap replacements, InliningLog } MapCursor entries = replacementLog.leaves.getEntries(); while (entries.advance()) { - Invokable replacementInvoke = entries.getKey(); + FixedNode replacementInvoke = entries.getKey().asFixedNodeOrNull(); Callsite replacementCallsite = entries.getValue(); - if (replacementInvoke.asFixedNode().isDeleted()) { + if (replacementInvoke == null || replacementInvoke.isDeleted()) { // Some invoke nodes could have been removed by optimizations. continue; } - Invokable invoke = (Invokable) replacements.get(replacementInvoke.asFixedNode()); + Invokable invoke = (Invokable) replacements.get(replacementInvoke); Callsite callsite = mapping.get(replacementCallsite); leaves.put(invoke, callsite); } @@ -247,10 +247,10 @@ public void replaceLog(UnmodifiableEconomicMap replacements, Inlinin copyTree(root, replacementLog.root, replacements, mapping); MapCursor replacementEntries = replacementLog.leaves.getEntries(); while (replacementEntries.advance()) { - Invokable replacementInvoke = replacementEntries.getKey(); + FixedNode replacementInvoke = replacementEntries.getKey().asFixedNodeOrNull(); Callsite replacementSite = replacementEntries.getValue(); - if (replacementInvoke.isAlive()) { - Invokable invoke = (Invokable) replacements.get((Node) replacementInvoke); + if (replacementInvoke != null && replacementInvoke.isAlive()) { + Invokable invoke = (Invokable) replacements.get(replacementInvoke); Callsite site = mapping.get(replacementSite); leaves.put(invoke, site); } @@ -261,7 +261,8 @@ private void copyTree(Callsite site, Callsite replacementSite, UnmodifiableEcono mapping.put(replacementSite, site); site.target = replacementSite.target; site.decisions.addAll(replacementSite.decisions); - site.invoke = replacementSite.invoke != null && replacementSite.invoke.isAlive() ? (Invokable) replacements.get(replacementSite.invoke.asFixedNode()) : null; + FixedNode replacementSiteInvoke = replacementSite.invoke != null ? replacementSite.invoke.asFixedNodeOrNull() : null; + site.invoke = replacementSiteInvoke != null && replacementSiteInvoke.isAlive() ? (Invokable) replacements.get(replacementSiteInvoke) : null; for (Callsite replacementChild : replacementSite.children) { Callsite child = new Callsite(site, null); site.children.add(child); @@ -435,13 +436,8 @@ public void setBci(int bci) { } @Override - public boolean isAlive() { - return false; - } - - @Override - public FixedNode asFixedNode() { - throw new UnsupportedOperationException("Parsed invokable is a placeholder, not a concrete node."); + public FixedNode asFixedNodeOrNull() { + return null; } @Override diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invokable.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invokable.java index 556fb494366e..97f0190f3700 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invokable.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invokable.java @@ -24,11 +24,12 @@ */ package org.graalvm.compiler.nodes; -import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; +import jdk.vm.ci.meta.ResolvedJavaMethod; + /** * A marker interface for nodes that represent calls to other methods. */ @@ -42,12 +43,13 @@ public interface Invokable extends DeoptBciSupplier { */ ResolvedJavaMethod getContextMethod(); - default boolean isAlive() { - return asFixedNode().isAlive(); + /** + * Returns the receiver cast to {@link FixedNode}, or null if this invokable is a placeholder. + */ + default FixedNode asFixedNodeOrNull() { + return this instanceof FixedNode ? (FixedNode) this : null; } - FixedNode asFixedNode(); - /** * Called on a {@link Invokable} node after it is registered with a graph. * @@ -73,15 +75,16 @@ default void updateInliningLogAfterRegister(StructuredGraph newGraph) { * updating logic by calling {@link InliningLog#openUpdateScope}. */ default void updateInliningLogAfterClone(Node other) { - if (GraalOptions.TraceInlining.getValue(asFixedNode().getOptions())) { + StructuredGraph graph = asFixedNodeOrNull().graph(); + if (GraalOptions.TraceInlining.getValue(graph.getOptions())) { // At this point, the invokable node was already added to the inlining log // in the call to updateInliningLogAfterRegister, so we need to remove it. - InliningLog log = asFixedNode().graph().getInliningLog(); + InliningLog log = graph.getInliningLog(); assert other instanceof Invokable; if (log.getUpdateScope() != null) { // InliningLog.UpdateScope determines how to update the log. log.getUpdateScope().accept((Invokable) other, this); - } else if (other.graph() == this.asFixedNode().graph()) { + } else if (other.graph() == graph) { // This node was cloned as part of duplication. // We need to add it as a sibling of the node other. assert log.containsLeafCallsite(this) : "Node " + this + " not contained in the log."; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java index 2fb76cfbc840..054e1f9978d0 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java @@ -65,6 +65,10 @@ public boolean allowSubstitution() { void setNext(FixedNode x); + default boolean isAlive() { + return asFixedNode().isAlive(); + } + CallTargetNode callTarget(); Node predecessor(); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java index d6b6dd778bc9..b45bee778cee 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java @@ -115,11 +115,6 @@ protected void afterClone(Node other) { updateInliningLogAfterClone(other); } - @Override - public FixedNode asFixedNode() { - return this; - } - @Override public CallTargetNode callTarget() { return callTarget; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java index 642d5fd15c40..141f756bfac4 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java @@ -84,11 +84,6 @@ protected void afterClone(Node other) { updateInliningLogAfterClone(other); } - @Override - public FixedNode asFixedNode() { - return this; - } - @Override public CallTargetNode callTarget() { return callTarget; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNode.java index adc74bf7db95..d94329f04f6d 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNode.java @@ -189,11 +189,16 @@ public final SerializableConstant asSerializableConstant() { } } + /* This method is final to ensure that it can be de-virtualized and inlined. */ @Override - public ValueNode asNode() { + public final ValueNode asNode() { return this; } + protected void updateUsagesInterface(ValueNodeInterface oldInput, ValueNodeInterface newInput) { + updateUsages(oldInput == null ? null : oldInput.asNode(), newInput == null ? null : newInput.asNode()); + } + @Override public boolean isAllowedUsageType(InputType type) { if (getStackKind() != JavaKind.Void && type == InputType.Value) { diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNodeInterface.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNodeInterface.java index 2452e2d43449..5cf79f509cf7 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNodeInterface.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueNodeInterface.java @@ -24,9 +24,25 @@ */ package org.graalvm.compiler.nodes; -import org.graalvm.compiler.graph.NodeInterface; - -public interface ValueNodeInterface extends NodeInterface { - @Override +/** + * When Graal {@link ValueNode} classes implement interfaces, it is frequently necessary to convert + * from an interface type back to a Node. This could be easily done using a cast, but casts come + * with a run time cost. Using a conversion method, which is implemented once on + * {@link ValueNode#asNode()}, avoids a cast. But it is faster only as long as the implementation + * method can be inlined. Therefore, it is important that only one implementation of the interface + * method exists, so that either single-implementor speculation (for JIT compilation) or static + * analysis results (for AOT compilation) allow the one implementation to be inlined. + * + * Subinterfaces like {@link FixedNodeInterface} provide a conversion method that has a more precise + * return type. Note that these sub-interfaces use a different method name like + * {@link FixedNodeInterface#asFixedNode()}, which then have another single implementation without a + * cast in {@link FixedNode#asFixedNode()}. + */ +public interface ValueNodeInterface { + /* + * This method is called `asNode` and not `asValueNode` partly for historic reasons, because + * originally the interface was called just `NodeInterface`. But since there are so many + * callers, we also want to keep the call sites as short as possible. + */ ValueNode asNode(); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatingNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatingNode.java index 8d348bd20fc9..13ca1b0bf764 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatingNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatingNode.java @@ -37,9 +37,4 @@ public abstract class FloatingNode extends ValueNode implements ValueNumberable public FloatingNode(NodeClass c, Stamp stamp) { super(c, stamp); } - - @Override - public FloatingNode asNode() { - return this; - } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java index 317277c80ac2..8f99a52dd0a3 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java @@ -24,14 +24,13 @@ */ package org.graalvm.compiler.nodes.extended; -import org.graalvm.compiler.graph.NodeInterface; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.FixedWithNextNodeInterface; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; -public interface ArrayRangeWrite extends NodeInterface { +public interface ArrayRangeWrite extends FixedWithNextNodeInterface { AddressNode getAddress(); /** @@ -53,9 +52,6 @@ public interface ArrayRangeWrite extends NodeInterface { int getElementStride(); - @Override - FixedAccessNode asNode(); - /** * Returns the place where a pre-write barrier should be inserted if one is necessary for this * node. The barrier should be added before the node returned by this method. diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java index f29782ba2981..e6d3f28975b8 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -211,7 +212,7 @@ private static boolean hasWriteBarrier(FixedAccessNode node) { } private static boolean hasWriteBarrier(ArrayRangeWrite write) { - FixedAccessNode node = write.asNode(); + FixedWithNextNode node = write.asFixedWithNextNode(); return node.next() instanceof SerialArrayRangeWriteBarrier && matches(write, (SerialArrayRangeWriteBarrier) node.next()); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewArrayNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewArrayNode.java index 1c2359e9bb5d..f0f351abc4a9 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewArrayNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewArrayNode.java @@ -24,7 +24,6 @@ */ package org.graalvm.compiler.nodes.java; -import jdk.vm.ci.meta.ConstantReflectionProvider; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -32,11 +31,13 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; +import jdk.vm.ci.meta.ConstantReflectionProvider; + /** * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations. */ @NodeInfo -public abstract class AbstractNewArrayNode extends AbstractNewObjectNode implements ArrayLengthProvider { +public abstract class AbstractNewArrayNode extends AbstractNewObjectNode implements ArrayLengthProvider, NewArrayInterface { public static final NodeClass TYPE = NodeClass.create(AbstractNewArrayNode.class); @Input protected ValueNode length; @@ -55,6 +56,11 @@ protected AbstractNewArrayNode(NodeClass c, Stam this.length = length; } + @Override + public final AbstractNewArrayNode asNewArrayNode() { + return this; + } + /** * The list of node which produce input for this instruction. */ diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java index 9c2268ab4e11..463ba585988b 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java @@ -179,7 +179,7 @@ public void simplify(SimplifierTool tool) { } if (invokeKind.isInterface()) { - MethodCallTargetNode result = tryDevirtualizeInterfaceCall(receiver(), targetMethod, profile, graph().getAssumptions(), contextType, this, invoke().asNode()); + MethodCallTargetNode result = tryDevirtualizeInterfaceCall(receiver(), targetMethod, profile, graph().getAssumptions(), contextType, this, invoke().asFixedNode()); assert result == this; } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayInterface.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayInterface.java new file mode 100644 index 000000000000..6bdb1d064a42 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayInterface.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 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 org.graalvm.compiler.nodes.java; + +import org.graalvm.compiler.nodes.FixedWithNextNodeInterface; +import org.graalvm.compiler.nodes.ValueNodeInterface; + +/** + * See {@link ValueNodeInterface} for details about these node interfaces. + */ +public interface NewArrayInterface extends FixedWithNextNodeInterface { + AbstractNewArrayNode asNewArrayNode(); +} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryAccess.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryAccess.java index c8e100d7e33a..24c5ad71cf97 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryAccess.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryAccess.java @@ -24,14 +24,14 @@ */ package org.graalvm.compiler.nodes.memory; -import org.graalvm.compiler.graph.NodeInterface; +import org.graalvm.compiler.nodes.ValueNodeInterface; import org.graalvm.word.LocationIdentity; /** * This interface marks nodes that access some memory location, and that have an edge to the last * node that kills this location. */ -public interface MemoryAccess extends NodeInterface { +public interface MemoryAccess extends ValueNodeInterface { LocationIdentity getLocationIdentity(); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Proxy.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Proxy.java index 05f7a196f050..d40518789adc 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Proxy.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Proxy.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.nodes.spi; import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeInterface; +import org.graalvm.compiler.nodes.ValueNodeInterface; /** * This interface marks nodes whose result is the same as one of their inputs. Such nodes are used @@ -33,7 +33,7 @@ * * For some algorithms it is necessary or advantageous to see through these proxies. */ -public interface Proxy extends NodeInterface { +public interface Proxy extends ValueNodeInterface { Node getOriginalNode(); diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java index c71b8c737046..416bc1cc15ab 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java @@ -111,11 +111,6 @@ public void setGuard(GuardingNode guard) { updateUsagesInterface(this.guard, guard); this.guard = guard; } - - @Override - public ValueNode asNode() { - return this; - } } @Override diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java index 95450a4bb237..ca34491f7699 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java @@ -122,7 +122,7 @@ protected void run(StructuredGraph graph) { for (Node node : graph.getNodes()) { if (node instanceof Invoke) { Invoke invoke = (Invoke) node; - DynamicCounterNode.addCounterBefore(GROUP_NAME_INVOKES, invoke.callTarget().targetName(), 1, true, invoke.asNode()); + DynamicCounterNode.addCounterBefore(GROUP_NAME_INVOKES, invoke.callTarget().targetName(), 1, true, invoke.asFixedNode()); } } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java index d5e3e746eb09..0da6acbe0091 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java @@ -372,7 +372,7 @@ public static UnmodifiableEconomicMap inline(Invoke invoke, Structur @SuppressWarnings("try") public static UnmodifiableEconomicMap inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod, String reason, String phase, InlineeReturnAction returnAction) { - FixedNode invokeNode = invoke.asNode(); + FixedNode invokeNode = invoke.asFixedNode(); StructuredGraph graph = invokeNode.graph(); final NodeInputList parameters = invoke.callTarget().arguments(); @@ -553,7 +553,7 @@ private static ValueNode finishInlining(Invoke invoke, StructuredGraph graph, Fi List processedReturns = inlineeReturnAction.processInlineeReturns(returnNodes); - FixedNode invokeNode = invoke.asNode(); + FixedNode invokeNode = invoke.asFixedNode(); FrameState stateAfter = invoke.stateAfter(); invokeNode.replaceAtPredecessor(firstNode); @@ -691,7 +691,7 @@ private static void fixFrameStates(StructuredGraph graph, MergeNode originalMerg @SuppressWarnings("try") private static void updateSourcePositions(Invoke invoke, StructuredGraph inlineGraph, UnmodifiableEconomicMap duplicates, boolean isSub, Mark mark) { - FixedNode invokeNode = invoke.asNode(); + FixedNode invokeNode = invoke.asFixedNode(); StructuredGraph invokeGraph = invokeNode.graph(); if (invokeGraph.trackNodeSourcePosition() && invoke.stateAfter() != null) { boolean isSubstitution = isSub || inlineGraph.isSubstitution(); @@ -926,7 +926,7 @@ public static FrameState handleMissingAfterExceptionFrameState(FrameState nonRep workList.add(usage); } else { StateSplit stateSplit = (StateSplit) usage; - FixedNode fixedStateSplit = stateSplit.asNode(); + FixedNode fixedStateSplit = stateSplit.asFixedNode(); if (fixedStateSplit instanceof AbstractMergeNode) { AbstractMergeNode merge = (AbstractMergeNode) fixedStateSplit; while (merge.isAlive()) { @@ -1030,7 +1030,7 @@ public static ValueNode nonNullReceiver(Invoke invoke) { LogicNode condition = graph.unique(IsNullNode.create(newReceiver)); FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, NullCheckException, InvalidateReprofile, true)); PiNode nonNullReceiver = graph.unique(new PiNode(newReceiver, StampFactory.objectNonNull(), fixedGuard)); - graph.addBeforeFixed(invoke.asNode(), fixedGuard); + graph.addBeforeFixed(invoke.asFixedNode(), fixedGuard); newReceiver = nonNullReceiver; } } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java index 20b28966641f..eb33785bd66b 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java @@ -343,7 +343,7 @@ private EconomicSet inlineSingleMethod(StructuredGraph graph, StampProvide AbstractBeginNode[] successors = new AbstractBeginNode[]{calleeEntryNode, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, false, stampProvider, constantReflection); - calleeEntryNode.setNext(invoke.asNode()); + calleeEntryNode.setNext(invoke.asFixedNode()); return inline(invoke, methodAt(0), inlineableElementAt(0), false, reason); } @@ -385,7 +385,7 @@ private static AbstractBeginNode createInvocationBlock(StructuredGraph graph, In PhiNode exceptionObjectPhi, boolean useForInlining) { Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining); AbstractBeginNode calleeEntryNode = graph.add(new BeginNode()); - calleeEntryNode.setNext(duplicatedInvoke.asNode()); + calleeEntryNode.setNext(duplicatedInvoke.asFixedNode()); EndNode endNode = graph.add(new EndNode()); duplicatedInvoke.setNext(endNode); @@ -465,7 +465,7 @@ private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, AbstractBeginNode[] successors = new AbstractBeginNode[]{invocationEntry, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, true, stampProvider, constantReflection); - invocationEntry.setNext(invoke.asNode()); + invocationEntry.setNext(invoke.asFixedNode()); ValueNode receiver = ((MethodCallTargetNode) invoke.callTarget()).receiver(); PiNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false); invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver); diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java index c8090b0b5803..fe2c4dbdf5da 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java @@ -130,7 +130,7 @@ private void createGuard(StructuredGraph graph, CoreProviders providers) { ValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, guard, type, nonNullReceiver, true); invoke.callTarget().replaceFirstInput(nonNullReceiver, anchoredReceiver); - graph.addBeforeFixed(invoke.asNode(), guard); + graph.addBeforeFixed(invoke.asFixedNode(), guard); } } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java index fc9bbf75c2f4..b98095956d63 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java @@ -224,7 +224,7 @@ public Iterable getInvokes() { @Override public double getProbability(Invoke invoke) { - return probabilites.applyAsDouble(invoke.asNode()); + return probabilites.applyAsDouble(invoke.asFixedNode()); } public StructuredGraph getGraph() { diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java index 7d8d482db5a8..01adf2d30fb9 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java @@ -207,7 +207,7 @@ public void computeProbabilities() { } public double invokeProbability(Invoke invoke) { - return probability * probabilities.applyAsDouble(invoke.asNode()); + return probability * probabilities.applyAsDouble(invoke.asFixedNode()); } public double invokeRelevance(Invoke invoke) { diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java index 0bbc31a1409e..5ab1b0f3479b 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java @@ -109,7 +109,7 @@ public double getRelevance(Invoke invoke) { return rootScope.computeInvokeRelevance(invoke); } assert nodeRelevances != null : "uninitialized relevance"; - return nodeRelevances.get(invoke.asNode()); + return nodeRelevances.get(invoke.asFixedNode()); } /** @@ -243,7 +243,7 @@ public void process(NodeWorkList workList) { * scope's fastPathMinProbability, adjusted by scopeRelevanceWithinParent. */ public double computeInvokeRelevance(Invoke invoke) { - double invokeProbability = nodeProbabilities.applyAsDouble(invoke.asNode()); + double invokeProbability = nodeProbabilities.applyAsDouble(invoke.asFixedNode()); assert !Double.isNaN(invokeProbability); double relevance = (invokeProbability / getFastPathMinProbability()) * Math.min(1.0, getScopeRelevanceWithinParent()); diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java index 43c857446256..7268ce52b7a7 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java @@ -237,7 +237,7 @@ protected Set controlSplit(ControlSplitNode controlSplit) { } protected void invoke(Invoke invoke) { - node(invoke.asNode()); + node(invoke.asFixedNode()); } protected void finished() { diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java index b70402ca65a4..9eb4df19d1d8 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java @@ -367,7 +367,7 @@ protected void controlSplit(ControlSplitNode controlSplit) { } protected void invoke(Invoke invoke) { - node(invoke.asNode()); + node(invoke.asFixedNode()); } /** diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java index 697faafb0032..1a83d8f51e9e 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java @@ -600,7 +600,7 @@ public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) appendInvoke(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData, callTarget); - lastInstr.setNext(invoke.asNode()); + lastInstr.setNext(invoke.asFixedNode()); if (invoke instanceof InvokeWithExceptionNode) { lastInstr = ((InvokeWithExceptionNode) invoke).next(); } else { @@ -944,7 +944,7 @@ protected MethodCallTargetNode trySimplifyCallTarget(PEMethodScope methodScope, if (callTarget.invokeKind().isInterface()) { Invoke invoke = invokeData.invoke; ResolvedJavaType contextType = methodScope.method.getDeclaringClass(); - return MethodCallTargetNode.tryDevirtualizeInterfaceCall(callTarget.receiver(), callTarget.targetMethod(), null, graph.getAssumptions(), contextType, callTarget, invoke.asNode()); + return MethodCallTargetNode.tryDevirtualizeInterfaceCall(callTarget.receiver(), callTarget.targetMethod(), null, graph.getAssumptions(), contextType, callTarget, invoke.asFixedNode()); } return callTarget; } @@ -1063,7 +1063,7 @@ protected boolean tryInvocationPlugin(PEMethodScope methodScope, LoopScope loopS } else { /* Intrinsification failed, restore original state: invoke is in Graph. */ - invokePredecessor.setNext(invoke.asNode()); + invokePredecessor.setNext(invoke.asFixedNode()); return false; } } @@ -1132,7 +1132,7 @@ protected LoopScope doInline(PEMethodScope methodScope, LoopScope loopScope, Inv } Invoke invoke = invokeData.invoke; - FixedNode invokeNode = invoke.asNode(); + FixedNode invokeNode = invoke.asFixedNode(); FixedWithNextNode predecessor = (FixedWithNextNode) invokeNode.predecessor(); invokeData.invokePredecessor = predecessor; invokeNode.replaceAtPredecessor(null); @@ -1188,7 +1188,7 @@ protected void finishInlining(MethodScope is) { LoopScope loopScope = inlineScope.callerLoopScope; InvokeData invokeData = inlineScope.invokeData; Invoke invoke = invokeData.invoke; - FixedNode invokeNode = invoke.asNode(); + FixedNode invokeNode = invoke.asFixedNode(); ValueNode exceptionValue = null; int returnNodeCount = 0; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java index 3f057960e741..84b884782a90 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java @@ -36,7 +36,6 @@ import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; -import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.Invoke; @@ -189,11 +188,6 @@ protected void afterClone(Node other) { updateInliningLogAfterClone(other); } - @Override - public FixedNode asFixedNode() { - return this; - } - @Override @SuppressWarnings("try") public Invoke replaceWithInvoke() { diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java index 2b0b9dccb2ac..6a5dce46af54 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroWithExceptionNode.java @@ -36,7 +36,6 @@ import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; -import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; @@ -117,11 +116,6 @@ protected void afterClone(Node other) { updateInliningLogAfterClone(other); } - @Override - public FixedNode asFixedNode() { - return this; - } - @Override @SuppressWarnings("try") public Invoke replaceWithInvoke() { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java index 1f2c7ec381ce..6513291c0751 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java @@ -1189,7 +1189,7 @@ protected void node(FixedNode n) { return cloneFlow; }); cloneBuilder.addObserverDependency(inputBuilder); - state.add(node.asNode(), cloneBuilder); + state.add(node.asFixedNode(), cloneBuilder); } else if (n instanceof MonitorEnterNode) { MonitorEnterNode node = (MonitorEnterNode) n; BytecodeLocation monitorLocation = BytecodeLocation.create(uniqueKey(node), methodFlow.getMethod()); 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 26a174339c99..5e6874405637 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 @@ -258,7 +258,7 @@ protected void finishInlining(MethodScope is) { } killControlFlowNodes(inlineScope, invokeData.invokePredecessor.next()); assert invokeData.invokePredecessor.next() == null : "Successor must have been a fixed node created in the aborted scope, which is deleted now"; - invokeData.invokePredecessor.setNext(invokeData.invoke.asNode()); + invokeData.invokePredecessor.setNext(invokeData.invoke.asFixedNode()); if (inlineScope.exceptionPlaceholderNode != null) { assert invokeData.invoke instanceof InvokeWithExceptionNode; 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 eed030e88e94..20ffe19ea353 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 @@ -283,7 +283,7 @@ public void simplify(Node n, SimplifierTool tool) { } private void handleInvoke(Invoke invoke, SimplifierTool tool) { - FixedNode node = invoke.asNode(); + FixedNode node = invoke.asFixedNode(); MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); InvokeTypeFlow invokeFlow = originalFlows.getInvokeFlow(invoke); @@ -390,7 +390,7 @@ private void unreachableInvoke(Invoke invoke, SimplifierTool tool) { InliningUtil.nonNullReceiver(invoke); } - makeUnreachable(invoke.asNode(), tool, () -> "method " + graph.method().format("%H.%n(%p)") + ", node " + invoke + + makeUnreachable(invoke.asFixedNode(), tool, () -> "method " + graph.method().format("%H.%n(%p)") + ", node " + invoke + ": empty list of callees for call to " + invoke.callTarget().targetMethod().format("%H.%n(%P)")); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java index 07ae77437477..31f4833af6b5 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java @@ -735,7 +735,7 @@ private static void removeUnreachableInvokes(CallTreeNode node) { InliningUtil.nonNullReceiver(invoke); } FixedGuardNode guard = new FixedGuardNode(LogicConstantNode.forBoolean(true, node.graph), DeoptimizationReason.UnreachedCode, DeoptimizationAction.None, true); - node.graph.addBeforeFixed(invoke.asNode(), node.graph.add(guard)); + node.graph.addBeforeFixed(invoke.asFixedNode(), node.graph.add(guard)); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/DevirtualizeCallsPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/DevirtualizeCallsPhase.java index c93bc3c9bc13..275e8d6219ef 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/DevirtualizeCallsPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/DevirtualizeCallsPhase.java @@ -111,7 +111,7 @@ private void unreachableInvoke(StructuredGraph graph, Invoke invoke, SubstrateMe String message = String.format("The call to %s is not reachable when called from %s.%n", targetMethod.format("%H.%n(%P)"), graph.method().format("%H.%n(%P)")); AnalysisSpeculation speculation = new AnalysisSpeculation(new AnalysisSpeculationReason(message)); FixedGuardNode node = new FixedGuardNode(LogicConstantNode.forBoolean(true, graph), DeoptimizationReason.UnreachedCode, DeoptimizationAction.None, speculation, true); - graph.addBeforeFixed(invoke.asNode(), graph.add(node)); + graph.addBeforeFixed(invoke.asFixedNode(), graph.add(node)); graph.getDebug().dump(DebugContext.VERY_DETAILED_LEVEL, graph, "After dead invoke %s", invoke); } @@ -136,7 +136,7 @@ private void singleCallee(HostedMethod singleCallee, StructuredGraph graph, Invo * anchor the receiver to the place of the original invoke. */ ValueAnchorNode anchor = graph.add(new ValueAnchorNode(null)); - graph.addBeforeFixed(invoke.asNode(), anchor); + graph.addBeforeFixed(invoke.asFixedNode(), anchor); Stamp anchoredReceiverStamp = StampFactory.object(TypeReference.createWithoutAssumptions(singleCallee.getDeclaringClass())); ValueNode anchoredReceiver = graph.unique(new PiNode(invoke.getReceiver(), anchoredReceiverStamp, anchor)); invoke.callTarget().replaceFirstInput(invoke.getReceiver(), anchoredReceiver); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/HostedGraphBuilderPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/HostedGraphBuilderPhase.java index 71dc12af52ee..bb44db0e02fd 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/HostedGraphBuilderPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/HostedGraphBuilderPhase.java @@ -212,7 +212,7 @@ private void insertDeoptNode(HostedBciBlockMapping.DeoptEntryInsertionPoint deop FrameState stateAfter = frameState.create(deopt.frameStateBci(), deoptNode); deoptNode.setStateAfter(stateAfter); if (lastInstr != null) { - lastInstr.setNext(deoptNode.asNode()); + lastInstr.setNext(deoptNode.asFixedNode()); } if (deopt.isProxy()) { @@ -261,7 +261,7 @@ private void insertDeoptNode(HostedBciBlockMapping.DeoptEntryInsertionPoint deop lastInstr = deoptEntryNode.next(); } - insertProxies(deoptNode.asNode(), frameState); + insertProxies(deoptNode.asFixedNode(), frameState); } private void insertProxies(FixedNode deoptTarget, FrameStateBuilder state) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/ImplicitAssertionsPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/ImplicitAssertionsPhase.java index dae23c897b7c..14169e0e815f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/ImplicitAssertionsPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/ImplicitAssertionsPhase.java @@ -130,14 +130,14 @@ private static void tryOptimize(StructuredGraph graph, Invoke constructorInvoke, } else if (usagesToDelete.contains(exceptionUsage)) { /* Frame state between constructor and allocation. */ } else if (exceptionUsage instanceof UnwindNode) { - if (!hasSimpleControlFlow(exceptionUsage, constructorInvoke.asNode(), null)) { + if (!hasSimpleControlFlow(exceptionUsage, constructorInvoke.asFixedNode(), null)) { /* No simple control flow path found to the UnwindNode. */ return; } } else if (exceptionUsage instanceof PhiNode) { PhiNode phi = (PhiNode) exceptionUsage; for (int i = 0; i < phi.valueCount(); i++) { - if (phi.valueAt(i) == exceptionAllocation && !hasSimpleControlFlow(phi.merge().phiPredecessorAt(i), constructorInvoke.asNode(), null)) { + if (phi.valueAt(i) == exceptionAllocation && !hasSimpleControlFlow(phi.merge().phiPredecessorAt(i), constructorInvoke.asFixedNode(), null)) { /* No simple control flow path found to the PhiNode. */ return; } From 0b9e43a676335a43091d6b5882284a467c4f43be Mon Sep 17 00:00:00 2001 From: Koutheir Attouchi Date: Fri, 1 Oct 2021 16:22:40 -0400 Subject: [PATCH 269/681] Truncation in JVM_GetNanoTimeAdjustment() on 32-bits archs The C `long` type is only 64-bits-wide on LP64 systems and the like. In 32-bits systems, `long` is usually 32-bits-wide. On such systems: - The constant `0x0100000000L` cannot be represented, and should be `0x0100000000LL` instead, in order to explicitly mark its type as a `long long`. - The Java `jlong` cannot be represented in a `long` and it can cause unintentional data loss (truncation). `jlong` always corresponds to `int64_t`. --- .../com.oracle.svm.native.jvm.posix/src/JvmFuncs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/substratevm/src/com.oracle.svm.native.jvm.posix/src/JvmFuncs.c b/substratevm/src/com.oracle.svm.native.jvm.posix/src/JvmFuncs.c index b9968f5286f2..33982e90dc09 100644 --- a/substratevm/src/com.oracle.svm.native.jvm.posix/src/JvmFuncs.c +++ b/substratevm/src/com.oracle.svm.native.jvm.posix/src/JvmFuncs.c @@ -257,19 +257,19 @@ JNIEXPORT jlong JNICALL JVM_NanoTime(void *env, void * ignored) { } JNIEXPORT jlong JNICALL JVM_GetNanoTimeAdjustment(void *env, void * ignored, jlong offset_secs) { - long maxDiffSecs = 0x0100000000L; - long minDiffSecs = -maxDiffSecs; + int64_t maxDiffSecs = 0x0100000000LL; + int64_t minDiffSecs = -maxDiffSecs; struct timeval time; int status = gettimeofday(&time, NULL); - long seconds = time.tv_sec; - long nanos = time.tv_usec * 1000; + int64_t seconds = time.tv_sec; + int64_t nanos = time.tv_usec * 1000; - long diff = seconds - offset_secs; + int64_t diff = seconds - offset_secs; if (diff >= maxDiffSecs || diff <= minDiffSecs) { return -1; } - return diff * 1000000000 + nanos; + return diff * 1000000000LL + nanos; } JNIEXPORT jlong JNICALL Java_jdk_internal_misc_VM_getNanoTimeAdjustment(void *env, void * ignored, jlong offset_secs) { From 36b3c958551d769dbb824195722849ec95b8f006 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Fri, 1 Oct 2021 15:01:40 -0700 Subject: [PATCH 270/681] Generalize FunctionPointerHolder. --- .../svm/core/FunctionPointerHolder.java | 41 +++++++++++++++++++ .../ClassInitializationInfo.java | 22 ++-------- .../svm/hosted/meta/UniverseBuilder.java | 4 +- 3 files changed, 46 insertions(+), 21 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/FunctionPointerHolder.java diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/FunctionPointerHolder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/FunctionPointerHolder.java new file mode 100644 index 000000000000..365cd0c2df15 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/FunctionPointerHolder.java @@ -0,0 +1,41 @@ +/* + * 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.core; + +import org.graalvm.nativeimage.c.function.CFunctionPointer; + +/** + * Isolates require that all function pointers to image methods are in immutable classes. This class + * can be used as an immutable indirection for mutable classes that need to store a function + * pointer. + */ +public class FunctionPointerHolder { + + public final CFunctionPointer functionPointer; + + public FunctionPointerHolder(CFunctionPointer functionPointer) { + this.functionPointer = functionPointer; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java index 02ca5909cc50..a69c0c4f9bb3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java @@ -34,6 +34,7 @@ import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.function.CFunctionPointer; +import com.oracle.svm.core.FunctionPointerHolder; import com.oracle.svm.core.annotate.InvokeJavaFunctionPointer; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.jdk.InternalVMMethod; @@ -91,28 +92,11 @@ interface ClassInitializerFunctionPointer extends CFunctionPointer { void invoke(); } - /** - * Isolates require that all function pointers to image methods are in immutable classes. - * {@link ClassInitializationInfo} is mutable, so we use this class as an immutable indirection. - */ - public static class ClassInitializerFunctionPointerHolder { - /** - * We cannot declare the field to have type {@link ClassInitializerFunctionPointer} because - * during image building the field refers to a wrapper object that cannot implement custom - * interfaces. - */ - final CFunctionPointer functionPointer; - - ClassInitializerFunctionPointerHolder(CFunctionPointer functionPointer) { - this.functionPointer = functionPointer; - } - } - /** * Function pointer to the class initializer, or null if the class does not have a class * initializer. */ - private final ClassInitializerFunctionPointerHolder classInitializer; + private final FunctionPointerHolder classInitializer; /** * The current initialization state. @@ -156,7 +140,7 @@ private ClassInitializationInfo(InitState initState) { @Platforms(Platform.HOSTED_ONLY.class) public ClassInitializationInfo(CFunctionPointer classInitializer) { - this.classInitializer = classInitializer == null || classInitializer.isNull() ? null : new ClassInitializerFunctionPointerHolder(classInitializer); + this.classInitializer = classInitializer == null || classInitializer.isNull() ? null : new FunctionPointerHolder(classInitializer); this.initState = InitState.Linked; this.initLock = new ReentrantLock(); this.hasInitializer = classInitializer != null; 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 4430e2cf2e0a..b4e1414aa82c 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 @@ -62,6 +62,7 @@ import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.results.AbstractAnalysisResultsBuilder; +import com.oracle.svm.core.FunctionPointerHolder; import com.oracle.svm.core.InvalidVTableEntryHandler; import com.oracle.svm.core.StaticFieldsSupport; import com.oracle.svm.core.SubstrateOptions; @@ -70,7 +71,6 @@ import com.oracle.svm.core.annotate.ExcludeFromReferenceMap; import com.oracle.svm.core.c.BoxedRelocatedPointer; import com.oracle.svm.core.c.function.CFunctionOptions; -import com.oracle.svm.core.classinitialization.ClassInitializationInfo.ClassInitializerFunctionPointerHolder; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.config.ObjectLayout; import com.oracle.svm.core.deopt.DeoptimizedFrame; @@ -367,7 +367,7 @@ private void buildProfilingInformation() { DynamicHub.class, CEntryPointLiteral.class, BoxedRelocatedPointer.class, - ClassInitializerFunctionPointerHolder.class, + FunctionPointerHolder.class, FillerObject.class)); static { From ae3ac2d9fb8384e62f3b23297c0778f460daabf9 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Sat, 2 Oct 2021 00:22:00 -0700 Subject: [PATCH 271/681] Fix AnalysisType.hasSubTypes(). --- .../src/com/oracle/graal/pointsto/meta/AnalysisType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 3e48a52596eb..ca169a1ccfe7 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 @@ -835,7 +835,8 @@ public ResolvedJavaType getElementalType() { } public boolean hasSubTypes() { - return subTypes.size() > 0; + /* subTypes always includes this type itself. */ + return subTypes.size() > 1; } @Override From 6ec46b0181a5c74ead65388c5f105874190f54eb Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Sun, 3 Oct 2021 18:34:00 +0200 Subject: [PATCH 272/681] Default renaissance to 0.11.0 until Native Image is compatible with 0.13.0 --- java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py | 3 ++- substratevm/mx.substratevm/mx_substratevm_benchmark.py | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py index fcdf2b39f391..a481655ebdb5 100644 --- a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py +++ b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py @@ -1870,7 +1870,8 @@ def version(self): return super(RenaissanceBenchmarkSuite, self).version() def defaultSuiteVersion(self): - return self.availableSuiteVersions()[-1] + # return self.availableSuiteVersions()[-1] + return "0.11.0" # stick to 0.11.0 for both JIT and AOT until Native Image is compatible with 0.13.0 (GR-34147) def availableSuiteVersions(self): return ["0.9.0", "0.10.0", "0.11.0", "0.12.0", "0.13.0"] diff --git a/substratevm/mx.substratevm/mx_substratevm_benchmark.py b/substratevm/mx.substratevm/mx_substratevm_benchmark.py index eb8a0e702f17..9c82d6cdf0ab 100644 --- a/substratevm/mx.substratevm/mx_substratevm_benchmark.py +++ b/substratevm/mx.substratevm/mx_substratevm_benchmark.py @@ -61,6 +61,12 @@ def list_jars(path): _RENAISSANCE_EXTRA_IMAGE_BUILD_ARGS = { + 'als' : [ + '--allow-incomplete-classpath', + '--report-unsupported-elements-at-runtime', + '--initialize-at-build-time=org.slf4j,org.apache.log4j,scala.runtime.LambdaDeserialize,scala.Symbol$', + '--initialize-at-run-time=io.netty.channel.unix.IovArray,io.netty.channel.epoll.EpollEventLoop,io.netty.channel.unix.Errors,io.netty.channel.unix.Socket,io.netty.channel.unix.Limits' + ], 'chi-square' : [ '--allow-incomplete-classpath', '--report-unsupported-elements-at-runtime', From 62ea8b3b90e13d5f1830797946aefc698820ebf8 Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Sun, 3 Oct 2021 19:02:24 +0200 Subject: [PATCH 273/681] Renaissance 0.13.0 --- compiler/ci_common/benchmark-builders.jsonnet | 8 ++++++-- compiler/ci_common/benchmark-suites.libsonnet | 13 +++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/compiler/ci_common/benchmark-builders.jsonnet b/compiler/ci_common/benchmark-builders.jsonnet index a7d2919aede3..8b6f657708bf 100644 --- a/compiler/ci_common/benchmark-builders.jsonnet +++ b/compiler/ci_common/benchmark-builders.jsonnet @@ -37,6 +37,8 @@ c.on_demand + hw.x52 + jdk8 + cc.jargraal + bench.specjbb2015_full_machine, c.weekly + hw.x52 + jdk8 + cc.libgraal + bench.renaissance_0_10, c.on_demand + hw.x52 + jdk8 + cc.jargraal + bench.renaissance_0_10, + c.weekly + hw.x52 + jdk8 + cc.libgraal + bench.renaissance_0_13, + c.on_demand + hw.x52 + jdk8 + cc.jargraal + bench.renaissance_0_13, c.daily + hw.x52 + jdk8 + cc.libgraal + bench.awfy, c.daily + hw.x52 + jdk8 + cc.jargraal + bench.awfy, c.daily + hw.x52 + jdk8 + cc.libgraal + bench.renaissance_legacy, @@ -74,6 +76,8 @@ c.on_demand + hw.x52 + jdk11 + cc.jargraal + bench.specjbb2015_full_machine, c.weekly + hw.x52 + jdk11 + cc.libgraal + bench.renaissance_0_10, c.on_demand + hw.x52 + jdk11 + cc.jargraal + bench.renaissance_0_10, + c.weekly + hw.x52 + jdk11 + cc.libgraal + bench.renaissance_0_13, + c.on_demand + hw.x52 + jdk11 + cc.jargraal + bench.renaissance_0_13, c.daily + hw.x52 + jdk11 + cc.libgraal + bench.awfy, c.daily + hw.x52 + jdk11 + cc.jargraal + bench.awfy, c.post_merge + hw.x52 + jdk11 + cc.libgraal + bench.renaissance_legacy, @@ -99,8 +103,8 @@ c.weekly + hw.x52 + jdk17 + cc.jargraal + bench.scala_dacapo_size_variants, c.weekly + hw.x52 + jdk17 + cc.libgraal + bench.scala_dacapo_timing, c.weekly + hw.x52 + jdk17 + cc.jargraal + bench.scala_dacapo_timing, - #c.post_merge + hw.x52 + jdk17 + cc.libgraal + bench.renaissance, - #c.daily + hw.x52 + jdk17 + cc.jargraal + bench.renaissance, + c.daily + hw.x52 + jdk17 + cc.libgraal + bench.renaissance_0_13, + c.weekly + hw.x52 + jdk17 + cc.jargraal + bench.renaissance_0_13, c.daily + hw.x52 + jdk17 + cc.libgraal + bench.specjvm2008, c.daily + hw.x52 + jdk17 + cc.jargraal + bench.specjvm2008, c.daily + hw.x52 + jdk17 + cc.libgraal + bench.specjbb2005, diff --git a/compiler/ci_common/benchmark-suites.libsonnet b/compiler/ci_common/benchmark-suites.libsonnet index aeb2e0c41fe0..b86d71213c52 100644 --- a/compiler/ci_common/benchmark-suites.libsonnet +++ b/compiler/ci_common/benchmark-suites.libsonnet @@ -11,13 +11,13 @@ legacy_and_secondary_suites:: std.set([$.renaissance_legacy, $.dacapo_size_variants, $.scala_dacapo_size_variants], keyF=uniq_key), jmh_micros_suites:: std.set([$.micros_graal_dist, $.micros_misc_graal_dist , $.micros_shootout_graal_dist], keyF=uniq_key), graal_internals_suites:: std.set([$.micros_graal_whitebox], keyF=uniq_key), - special_suites:: std.set([$.renaissance_0_10, $.specjbb2015_full_machine], keyF=uniq_key), + special_suites:: std.set([$.renaissance_0_10, $.renaissance_0_13, $.specjbb2015_full_machine], keyF=uniq_key), microservice_suites:: std.set([$.microservice_benchmarks], keyF=uniq_key), main_suites:: std.set(self.open_suites + self.spec_suites + self.legacy_and_secondary_suites, keyF=uniq_key), all_suites:: std.set(self.main_suites + self.jmh_micros_suites + self.special_suites + self.microservice_suites, keyF=uniq_key), - weekly_forks_suites:: self.main_suites, + weekly_forks_suites:: std.set([$.renaissance_0_13] + self.main_suites, keyF=uniq_key), profiled_suites:: std.setDiff(self.main_suites, [$.specjbb2015], keyF=uniq_key), }, @@ -142,6 +142,15 @@ max_jdk_version:: 11 }, + renaissance_0_13: self.renaissance + { + suite:: "renaissance-0-13", + environment+: { + "RENAISSANCE_VERSION": "0.13.0" + }, + min_jdk_version:: 8, + max_jdk_version:: null + }, + renaissance_legacy: cc.compiler_benchmark + c.heap.default + { suite:: "renaissance-legacy", downloads+: { From 7ac2c4d7f0734f0248239f06401a424b7e7c75da Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Sun, 3 Oct 2021 20:06:52 +0200 Subject: [PATCH 274/681] Reference renaissance issue numbers --- java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py index a481655ebdb5..15772f9af0ed 100644 --- a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py +++ b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py @@ -1843,7 +1843,7 @@ def renaissanceIterations(self): if mx.get_jdk().javaCompliance >= '17' and self.version() in ["0.9.0", "0.10.0", "0.11.0", "0.12.0"]: # JDK17 support for Spark benchmarks was added in 0.13.0 - # See: https://github.com/renaissance-benchmarks/renaissance/issues/295 + # See: renaissance-benchmarks/renaissance #295 del benchmarks["als"] del benchmarks["chi-square"] del benchmarks["dec-tree"] @@ -1855,7 +1855,7 @@ def renaissanceIterations(self): if mx.get_arch() != "amd64" or mx.get_jdk().javaCompliance >= '11': # GR-33879 - # JNA libraries needed are currently limited to amd64: https://github.com/renaissance-benchmarks/renaissance/issues/153 + # JNA libraries needed are currently limited to amd64: renaissance-benchmarks/renaissance #153 del benchmarks["db-shootout"] if self.version() in ["0.9.0", "0.10.0", "0.11.0"]: From a41ddd94972ebcf2fb42c17219e42119f91a8b81 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Tue, 21 Sep 2021 18:03:28 +0200 Subject: [PATCH 275/681] Use correct array types in JVM_AssertionStatusDirectives --- .../src/com/oracle/truffle/espresso/impl/Klass.java | 2 +- .../com/oracle/truffle/espresso/impl/PrimitiveKlass.java | 7 +++++++ .../src/com/oracle/truffle/espresso/vm/VM.java | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java index 1306ac952d91..2ce90c2eb6fb 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Klass.java @@ -29,10 +29,10 @@ import java.util.Comparator; import java.util.function.IntFunction; -import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.espresso.jdwp.api.ModuleRef; import org.graalvm.collections.EconomicSet; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/PrimitiveKlass.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/PrimitiveKlass.java index d9f129e43f3e..0760ccf94b86 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/PrimitiveKlass.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/PrimitiveKlass.java @@ -25,6 +25,7 @@ import java.lang.reflect.Modifier; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.espresso.classfile.ConstantPool; import com.oracle.truffle.espresso.descriptors.Symbol; import com.oracle.truffle.espresso.descriptors.Symbol.Name; @@ -36,6 +37,7 @@ import com.oracle.truffle.espresso.runtime.EspressoContext; import com.oracle.truffle.espresso.runtime.StaticObject; import com.oracle.truffle.espresso.substitutions.JavaType; +import com.oracle.truffle.espresso.vm.InterpreterToVM; /** * Implementation of {@link Klass} for primitive types. Primitive classes don't have a .class @@ -147,4 +149,9 @@ public String toString() { public int getClassModifiers() { return getModifiers(); } + + @CompilerDirectives.TruffleBoundary + public StaticObject allocatePrimitiveArray(int length) { + return InterpreterToVM.allocatePrimitiveArray((byte) getPrimitiveJavaKind().getBasicType(), length, getMeta()); + } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java index 0611052872ce..c6e342da3a22 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java @@ -2326,9 +2326,9 @@ public int JVM_GetArrayLength(@JavaType(Object.class) StaticObject array, @Injec StaticObject instance = meta.java_lang_AssertionStatusDirectives.allocateInstance(); meta.java_lang_AssertionStatusDirectives.lookupMethod(Name._init_, Signature._void).invokeDirect(instance); meta.java_lang_AssertionStatusDirectives_classes.set(instance, meta.java_lang_String.allocateReferenceArray(0)); - meta.java_lang_AssertionStatusDirectives_classEnabled.set(instance, meta._boolean.allocateReferenceArray(0)); + meta.java_lang_AssertionStatusDirectives_classEnabled.set(instance, meta._boolean.allocatePrimitiveArray(0)); meta.java_lang_AssertionStatusDirectives_packages.set(instance, meta.java_lang_String.allocateReferenceArray(0)); - meta.java_lang_AssertionStatusDirectives_packageEnabled.set(instance, meta._boolean.allocateReferenceArray(0)); + meta.java_lang_AssertionStatusDirectives_packageEnabled.set(instance, meta._boolean.allocatePrimitiveArray(0)); boolean ea = getContext().getEnv().getOptions().get(EspressoOptions.EnableAssertions); meta.java_lang_AssertionStatusDirectives_deflt.set(instance, ea); return instance; From 10e24ec9d1726adeabb33fda1df4b903a8923c76 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Wed, 22 Sep 2021 15:27:24 +0200 Subject: [PATCH 276/681] Initialize SVM in LibEspresso This ensure startup hooks are run and in particular it installs some critical signal handlers such as the one for SIGPIPE --- .../com/oracle/truffle/espresso/libespresso/LibEspresso.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/espresso/src/com.oracle.truffle.espresso.libespresso/src/com/oracle/truffle/espresso/libespresso/LibEspresso.java b/espresso/src/com.oracle.truffle.espresso.libespresso/src/com/oracle/truffle/espresso/libespresso/LibEspresso.java index 1be98ce24511..8818f8520fac 100644 --- a/espresso/src/com.oracle.truffle.espresso.libespresso/src/com/oracle/truffle/espresso/libespresso/LibEspresso.java +++ b/espresso/src/com.oracle.truffle.espresso.libespresso/src/com/oracle/truffle/espresso/libespresso/LibEspresso.java @@ -27,6 +27,7 @@ import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.ObjectHandle; import org.graalvm.nativeimage.ObjectHandles; +import org.graalvm.nativeimage.VMRuntime; import org.graalvm.nativeimage.c.function.CEntryPoint; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Value; @@ -61,6 +62,7 @@ static int createJavaVM(@SuppressWarnings("unused") IsolateThread thread, JNIJav if (result != JNIErrors.JNI_OK()) { return result; } + VMRuntime.initialize(); // Use the nuclear option for System.exit builder.option("java.ExitHost", "true"); builder.option("java.EnableSignals", "true"); From 93f084c4908d1ccd07a776a23d715f0396bd3555 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Wed, 22 Sep 2021 15:28:17 +0200 Subject: [PATCH 277/681] Fix JVM_FindClassFromCaller: don't use a protection domain for the BCL --- .../src/com/oracle/truffle/espresso/vm/VM.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java index c6e342da3a22..789f9a246ce8 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java @@ -1972,7 +1972,18 @@ private Symbol namePtrToInternal(TruffleObject namePtr) { if (Types.isPrimitive(type)) { result = null; } else { - result = meta.resolveSymbolOrNull(type, loader, JVM_GetProtectionDomain(caller)); + StaticObject protectionDomain; + // If loader is null, shouldn't call ClassLoader.checkPackageAccess; otherwise get + // NPE. Put it in another way, the bootstrap class loader has all permission and + // thus no checkPackageAccess equivalence in the VM class loader. + // The caller is also passed as NULL by the java code if there is no security + // manager to avoid the performance cost of getting the calling class. + if (!StaticObject.isNull(caller) && !StaticObject.isNull(loader)) { + protectionDomain = JVM_GetProtectionDomain(caller); + } else { + protectionDomain = StaticObject.NULL; + } + result = meta.resolveSymbolOrNull(type, loader, protectionDomain); } if (result == null) { throw meta.throwExceptionWithMessage(meta.java_lang_ClassNotFoundException, NativeUtils.interopPointerToString(namePtr)); From 3b2dd8f9ea93d5ee11686a4e98475d449ceb1b31 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Mon, 4 Oct 2021 16:44:08 +0300 Subject: [PATCH 278/681] Include yaml header for truffle/docs/exit.md doc --- truffle/docs/Exit.md | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/truffle/docs/Exit.md b/truffle/docs/Exit.md index e20630417ae2..db0023867bab 100644 --- a/truffle/docs/Exit.md +++ b/truffle/docs/Exit.md @@ -1,13 +1,20 @@ +--- +layout: docs +toc_group: truffle +link_title: Context Exit +permalink: /graalvm-as-a-platform/language-implementation-framework/Exit/ +--- + # Context Exit Different Truffle (guest) languages may use different mechanisms for exiting. This is not optimal as a Truffle language has no way to detect and handle an exit triggered by a different language. -As of 22.0 Truffle has support for polyglot context hard explicit exit triggered by guest languages using [TruffleContext.closeExited(Node,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleContext.html#closeExited-com.oracle.truffle.api.nodes.Node-int-). +As of 22.0 Truffle has support for polyglot context hard explicit exit triggered by guest languages using [TruffleContext.closeExited(Node,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleContext.html#closeExited-com.oracle.truffle.api.nodes.Node-int-). It provides a unified way for languages to trigger the exit of the underlying polyglot context. When triggered, all initialized guest languages are first notified using [TruffleLanguage.exitContext(C,ExitMode,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.html#exitContext-C-com.oracle.truffle.api.TruffleLanguage.ExitMode-int), then all context threads are stopped, and finally, the context is closed. -The hard explicit exit is simply referred to as "hard exit". +The hard explicit exit is simply referred to as "hard exit". -The hard exit is only one of the three types of exit in Truffle. There are the following types of exit. +The hard exit is only one of the three types of exit in Truffle. There are the following types of exit. * The new hard exit introduced above * Hard exit notifications are executed with `ExitMode.HARD` as the second parameter of `TruffleLanguage.exitContext(C,ExitMode,int)`. @@ -19,9 +26,9 @@ The hard exit is only one of the three types of exit in Truffle. There are the f * Explicit exit triggered by throwing a Truffle exception of the exception type `ExceptionType.EXIT`. * The exception is not automatically thrown in other threads by Truffle and it does not trigger exit notifications or context close on its own. * The context is still fully usable after a soft exit and the soft exit can be followed by either the natural or the hard exit. - + For completeness, a polyglot context can be also closed by cancelling it using `Context.close(true)`, `TruffleContext.closeCancelled(Node,String)`, or `TruffleContext.closeResourceExhausted(Node,String)`. -The cancel operation leads to immediate stopping of all context threads and closing the context without any exit notifications. +The cancel operation leads to immediate stopping of all context threads and closing the context without any exit notifications. ## Soft exit @@ -44,7 +51,7 @@ The natural exit occurs during a normal context close triggered by `Context.clos 3. All initialized languages are finalized. * `TruffleLanguage.finalizeContext(C)` is called for all initalized languages. * Guest code runs normally during finalization. - + 4. All languages are disposed. * `TruffleLanguage.disposeContext(C)` is called for all languages. @@ -66,13 +73,13 @@ a special `ThreadDeath` cancel exception depending on whether the hard exit or t 2. Exit notifications for all initialized languages are executed - [TruffleLanguage.exitContext(C,ExitMode,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.html#exitContext-C-com.oracle.truffle.api.TruffleLanguage.ExitMode-int), where `ExitMode.HARD` is used as the `ExitMode` parameter. * Guest code runs normally during exit notifications. * If the context is not cancelled during exit notifications (during step 2a) and reaches step 2b, the exit process proceeds with the next step. Otherwise, the exit notifications are interrupted and the context is immediately cancelled. - + 3. All context threads are forced to stop by throwing a special `ThreadDeath` exit exception from Truffle safepoints. * To exit threads reliably, languages need to ensure that `ThreadDeath` is always immediately rethrown and guest language exception handlers and finally blocks are not run. * The embedder threads eventually throw a `PolyglotException` to the host with `PolyglotException.isExit() == true` and `PolyglotException.getExitStatus()` being equal to the exit code originally specified as the second parameter to the first call to`TruffleContext.closeExited(Node,int)`. * Note that from step 3 the exit process is similar to the cancelling process as indicated by the figure, but the cancelling process uses a special `ThreadDeath` cancel exception - and the `PolyglotException` thrown to the host has `PolyglotException.isCancelled() == true` instead of `PolyglotException.isExit() == true`. + and the `PolyglotException` thrown to the host has `PolyglotException.isCancelled() == true` instead of `PolyglotException.isExit() == true`. 4. All initialized languages are finalized. * `TruffleLanguage.finalizeContext(C)` is called for all initalized languages. @@ -80,23 +87,23 @@ a special `ThreadDeath` cancel exception depending on whether the hard exit or t * Languages should skip any finalization that would require running guest code. A language can find out if it can run guest code in `TruffleLanguage.finalizeContext(C)` by checking if `TruffleLanguage.exitContext(C,ExitMode,int)` was previously called with ExitMode.NATURAL, or by checking that `TruffleContext.isClosed()` returns `false`. - + 5. All languages are disposed. * `TruffleLanguage.disposeContext(C)` is called for all languages. - + 6. The context is closed. ### Behavior if useSystemExit is enabled 1. The exit is triggered by [TruffleContext.closeExited(Node,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleContext.html#closeExited-com.oracle.truffle.api.nodes.Node-int-). * Same as with system exit disabled. - + 2. Exit notifications for all initialized languages are executed - [TruffleLanguage.exitContext(C,ExitMode,int)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.html#exitContext-C-com.oracle.truffle.api.TruffleLanguage.ExitMode-int), where `ExitMode.HARD` is used as the `ExitMode` parameter. * Same as with system exit disabled. - + 3. `System.exit(int)` is called to terminate the whole host application providing the fastest exit possible. * The exit code passed to `System.exit(int)` - is the one originally specified as the second parameter to the first call to`TruffleContext.closeExited(Node,int)`. + is the one originally specified as the second parameter to the first call to`TruffleContext.closeExited(Node,int)`. ## Example Usage @@ -104,4 +111,4 @@ The [SimpleLanguage](https://github.com/graalvm/simplelanguage) demonstrates the * [SLExitBuiltin](https://github.com/graalvm/simplelanguage/blob/master/language/src/main/java/com/oracle/truffle/sl/builtins/SLExitBuiltin.java) demonstrates triggering the context exit. * [SLRegisterShutdownHookBuiltin](https://github.com/graalvm/simplelanguage/blob/master/language/src/main/java/com/oracle/truffle/sl/builtins/SLRegisterShutdownHookBuiltin.java) demonstrates registration of shutdown hooks that are executed during the exit notification defined in [SLLanguage](https://github.com/graalvm/simplelanguage/blob/master/language/src/main/java/com/oracle/truffle/sl/SLLanguage.java). -* [SLExitTest](https://github.com/graalvm/simplelanguage/blob/master/language/src/test/java/com/oracle/truffle/sl/test/SLExitTest.java) demonstrates the usage of the builtins defined above. \ No newline at end of file +* [SLExitTest](https://github.com/graalvm/simplelanguage/blob/master/language/src/test/java/com/oracle/truffle/sl/test/SLExitTest.java) demonstrates the usage of the builtins defined above. From bcd289e89b2ef8b99cdb087bdc5e820ba65c8925 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 4 Oct 2021 13:52:28 +0000 Subject: [PATCH 279/681] [GR-21590] Update Python imports PullRequest: graalpython/1976 --- vm/mx.vm/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 0a15ae2d85d1..9bad7fbb8705 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -75,7 +75,7 @@ }, { "name": "graalpython", - "version": "4130a1090c486309114e8f773c39ed31a21c887b", + "version": "c6fc7c03df46b19bebe808bc67fc42a484473232", "dynamic": True, "urls": [ {"url": "https://github.com/graalvm/graalpython.git", "kind": "git"}, From d186790e4ef4eb806be38e653118f85136bd407a Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Mon, 27 Sep 2021 16:44:11 -0700 Subject: [PATCH 280/681] AbstractCompareAndSwapNode should kill any() by default --- .../compiler/nodes/java/AbstractCompareAndSwapNode.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java index 37ba1e32ad0d..4c1b321aa450 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java @@ -26,6 +26,7 @@ import static org.graalvm.compiler.nodeinfo.InputType.Memory; import static org.graalvm.compiler.nodeinfo.InputType.State; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.Stamp; @@ -105,6 +106,6 @@ public Stamp getAccessStamp(NodeView view) { @Override public LocationIdentity getKilledLocationIdentity() { - return getLocationIdentity(); + return any(); } } From 6fed128a9b8494c99698d4e03bcf60de2d9102d3 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Mon, 4 Oct 2021 20:25:43 +0000 Subject: [PATCH 281/681] [GR-23997] Periodic update of the graal import (2021-10-01). PullRequest: js/2175 --- vm/mx.vm/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 37c5ef5653c4..bf268b3be435 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -39,7 +39,7 @@ "name": "graal-nodejs", "subdir": True, "dynamic": True, - "version": "cfd51cdf034ed67678574ad99b957cb7cb752c31", + "version": "082c333db671f03aba82d15e6d572e196b3878ea", "urls" : [ {"url" : "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, @@ -49,7 +49,7 @@ "name": "graal-js", "subdir": True, "dynamic": True, - "version": "cfd51cdf034ed67678574ad99b957cb7cb752c31", + "version": "082c333db671f03aba82d15e6d572e196b3878ea", "urls": [ {"url": "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, From a870dbded033fb4b9c324bd22678acf10327e331 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Fri, 24 Sep 2021 19:37:12 +0200 Subject: [PATCH 282/681] Refactor and fix AArch64 patching logic. --- .../asm/aarch64/AArch64Assembler.java | 15 +++++--- .../asm/aarch64/AArch64MacroAssembler.java | 34 +++++++++---------- .../aarch64/AArch64NativeImagePatcher.java | 20 ++++++----- .../graal/amd64/AMD64NativeImagePatcher.java | 2 +- .../core/graal/code/NativeImagePatcher.java | 6 +++- .../svm/graal/meta/RuntimeCodeInstaller.java | 2 +- .../oracle/svm/hosted/code/HostedPatcher.java | 10 +++++- .../code/aarch64/AArch64HostedPatcher.java | 20 ++++++----- .../hosted/code/amd64/AMD64HostedPatcher.java | 2 +- .../hosted/image/LIRNativeImageCodeCache.java | 2 +- .../oracle/svm/hosted/image/NativeImage.java | 7 +++- 11 files changed, 75 insertions(+), 45 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java index 479122cbc938..1fdb94cb7808 100755 --- a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java +++ b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java @@ -3121,7 +3121,14 @@ public abstract static class PatchableCodeAnnotation extends CodeAnnotation { this.instructionPosition = instructionPosition; } - abstract void patch(int codePos, int relative, byte[] code); + /** + * Patch the code buffer. + * + * @param startAddress starting address for instruction sequence to patch + * @param relative pc-relative value + * @param code machine code generated for this method + */ + abstract void patch(long startAddress, int relative, byte[] code); } /** @@ -3275,9 +3282,9 @@ public String toString() { } @Override - public void patch(int codePos, int relative, byte[] code) { - // currently only BL instructions are being patched here - assert instruction == Instruction.BL : "trying to patch an unexpected instruction"; + public void patch(long startAddress, int relative, byte[] code) { + // currently, only BL instructions are being patched here + GraalError.guarantee(instruction == Instruction.BL, "trying to patch an unexpected instruction"); int curValue = relative; // BL is PC-relative assert (curValue & ((1 << shift) - 1)) == 0 : "relative offset has incorrect alignment"; diff --git a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java index 82e56e994a80..2f1544a40777 100755 --- a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java +++ b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java @@ -2057,16 +2057,15 @@ public String toString() { } @Override - public void patch(int codePos, int relative, byte[] code) { - int pos = instructionPosition; - long targetAddress = ((long) pos) + relative; - int relativePageDifference = PatcherUtil.computeRelativePageDifference(targetAddress, pos, 1 << 12); - int originalInst = PatcherUtil.readInstruction(code, pos); + public void patch(long startAddress, int relative, byte[] code) { + long targetAddress = startAddress + relative; + int relativePageDifference = PatcherUtil.computeRelativePageDifference(targetAddress, startAddress, 1 << 12); + int originalInst = PatcherUtil.readInstruction(code, instructionPosition); int newInst = PatcherUtil.patchAdrpHi21(originalInst, relativePageDifference & 0x1FFFFF); - PatcherUtil.writeInstruction(code, pos, newInst); - originalInst = PatcherUtil.readInstruction(code, pos + 4); + PatcherUtil.writeInstruction(code, instructionPosition, newInst); + originalInst = PatcherUtil.readInstruction(code, instructionPosition + 4); newInst = PatcherUtil.patchLdrLo12(originalInst, (int) targetAddress & 0xFFF, srcSize); - PatcherUtil.writeInstruction(code, pos + 4, newInst); + PatcherUtil.writeInstruction(code, instructionPosition + 4, newInst); } } @@ -2081,16 +2080,15 @@ public String toString() { } @Override - public void patch(int codePos, int relative, byte[] code) { - int pos = instructionPosition; - long targetAddress = ((long) pos) + relative; - int relativePageDifference = PatcherUtil.computeRelativePageDifference(targetAddress, pos, 1 << 12); - int originalInst = PatcherUtil.readInstruction(code, pos); + public void patch(long startAddress, int relative, byte[] code) { + long targetAddress = startAddress + relative; + int relativePageDifference = PatcherUtil.computeRelativePageDifference(targetAddress, startAddress, 1 << 12); + int originalInst = PatcherUtil.readInstruction(code, instructionPosition); int newInst = PatcherUtil.patchAdrpHi21(originalInst, relativePageDifference & 0x1FFFFF); - PatcherUtil.writeInstruction(code, pos, newInst); - originalInst = PatcherUtil.readInstruction(code, pos + 4); + PatcherUtil.writeInstruction(code, instructionPosition, newInst); + originalInst = PatcherUtil.readInstruction(code, instructionPosition + 4); newInst = PatcherUtil.patchAddLo12(originalInst, (int) targetAddress & 0xFFF); - PatcherUtil.writeInstruction(code, pos + 4, newInst); + PatcherUtil.writeInstruction(code, instructionPosition + 4, newInst); } } @@ -2128,13 +2126,13 @@ public String toString() { } @Override - public void patch(int codePos, int relative, byte[] code) { + public void patch(long startAddress, int relative, byte[] code) { /* * Each move has a 16 bit immediate operand. We use a series of shifted moves to * represent immediate values larger than 16 bits. */ // first retrieving the target address - long curValue = ((long) instructionPosition) + relative; + long curValue = startAddress + relative; int siteOffset = 0; boolean containsNegatedMov = false; for (MovAction include : includeSet) { diff --git a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/AArch64NativeImagePatcher.java b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/AArch64NativeImagePatcher.java index 6066e976f68b..cb07b0eadce8 100644 --- a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/AArch64NativeImagePatcher.java +++ b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/AArch64NativeImagePatcher.java @@ -96,8 +96,9 @@ public int getLength() { } @Override - public void patchCode(int relative, byte[] code) { - annotation.patch(annotation.instructionPosition, relative, code); + public void patchCode(long methodStartAddress, int relative, byte[] code) { + long startAddress = methodStartAddress + annotation.instructionPosition; + annotation.patch(startAddress, relative, code); } @Override @@ -115,8 +116,9 @@ class AdrpLdrMacroInstructionNativeImagePatcher extends CompilationResult.CodeAn } @Override - public void patchCode(int relative, byte[] code) { - macroInstruction.patch(macroInstruction.instructionPosition, relative, code); + public void patchCode(long methodStartAddress, int relative, byte[] code) { + long startAddress = methodStartAddress + macroInstruction.instructionPosition; + macroInstruction.patch(startAddress, relative, code); } @Override @@ -151,8 +153,9 @@ class AdrpAddMacroInstructionNativeImagePatcher extends CompilationResult.CodeAn } @Override - public void patchCode(int relative, byte[] code) { - macroInstruction.patch(macroInstruction.instructionPosition, relative, code); + public void patchCode(long methodStartAddress, int relative, byte[] code) { + long startAddress = methodStartAddress + macroInstruction.instructionPosition; + macroInstruction.patch(startAddress, relative, code); } @Override @@ -187,8 +190,9 @@ class MovSequenceNativeImagePatcher extends CompilationResult.CodeAnnotation imp } @Override - public void patchCode(int relative, byte[] code) { - annotation.patch(annotation.instructionPosition, relative, code); + public void patchCode(long methodStartAddress, int relative, byte[] code) { + long startAddress = methodStartAddress + annotation.instructionPosition; + annotation.patch(startAddress, relative, code); } @Override diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64NativeImagePatcher.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64NativeImagePatcher.java index 180be26992a8..50fce34fdb47 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64NativeImagePatcher.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64NativeImagePatcher.java @@ -75,7 +75,7 @@ public AMD64NativeImagePatcher(OperandDataAnnotation annotation) { } @Override - public void patchCode(int relative, byte[] code) { + public void patchCode(long methodStartAddress, int relative, byte[] code) { int curValue = relative - (annotation.nextInstructionPosition - annotation.instructionPosition); for (int i = 0; i < annotation.operandSize; i++) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/NativeImagePatcher.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/NativeImagePatcher.java index 1bbd5db4ad3c..884bd33930cb 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/NativeImagePatcher.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/NativeImagePatcher.java @@ -30,8 +30,12 @@ public interface NativeImagePatcher { /** * Patch directly in the code buffer with an offset relative to the start of this instruction. + * + * @param methodStartAddress address of method start within runtime installed code + * @param relative pc-relative offset + * @param code machine code generated for this method */ - void patchCode(int relative, byte[] code); + void patchCode(long methodStartAddress, int relative, byte[] code); /** * The position from the beginning of the method where the patch is applied. This offset is used diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/RuntimeCodeInstaller.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/RuntimeCodeInstaller.java index d643c805100d..d1d104b8e68d 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/RuntimeCodeInstaller.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/RuntimeCodeInstaller.java @@ -258,7 +258,7 @@ private void patchData(Map patcher, @SuppressWarnin if (dataPatch.reference instanceof DataSectionReference) { DataSectionReference ref = (DataSectionReference) dataPatch.reference; int pcDisplacement = dataOffset + ref.getOffset() - dataPatch.pcOffset; - patch.patchCode(pcDisplacement, compiledBytes); + patch.patchCode(code.rawValue(), pcDisplacement, compiledBytes); } else if (dataPatch.reference instanceof ConstantReference) { ConstantReference ref = (ConstantReference) dataPatch.reference; SubstrateObjectConstant refConst = (SubstrateObjectConstant) ref.getConstant(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedPatcher.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedPatcher.java index 2dc76df0eaef..862f2e12c3e1 100755 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedPatcher.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedPatcher.java @@ -34,11 +34,19 @@ public interface HostedPatcher { /** * Create relocation for the binary file. + * + * @param ref value instruction sequence should refer to + * @param relocs buffer of added relocation site information + * @param compStart codecache-relative starting position this method's machine code */ void relocate(Reference ref, RelocatableBuffer relocs, int compStart); /** * Patch the code buffer. + * + * @param compStart codecache-relative starting position this method's machine code + * @param relative pc-relative offset + * @param code machine code generated for this method */ - void patch(int codePos, int relative, byte[] code); + void patch(int compStart, int relative, byte[] code); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcher.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcher.java index fc2e551e4725..305bf88f262b 100755 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcher.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcher.java @@ -96,8 +96,9 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { @Uninterruptible(reason = ".") @Override - public void patch(int codePos, int relative, byte[] code) { - annotation.patch(codePos, relative, code); + public void patch(int compStart, int relative, byte[] code) { + long startAddress = ((long) compStart) + annotation.instructionPosition; + annotation.patch(startAddress, relative, code); } @Override @@ -145,8 +146,9 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { @Uninterruptible(reason = ".") @Override - public void patch(int codePos, int relative, byte[] code) { - macroInstruction.patch(codePos, relative, code); + public void patch(int compStart, int relative, byte[] code) { + long startAddress = ((long) compStart) + macroInstruction.instructionPosition; + macroInstruction.patch(startAddress, relative, code); } @Override @@ -175,8 +177,9 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { @Uninterruptible(reason = ".") @Override - public void patch(int codePos, int relative, byte[] code) { - macroInstruction.patch(codePos, relative, code); + public void patch(int compStart, int relative, byte[] code) { + long startAddress = ((long) compStart) + macroInstruction.instructionPosition; + macroInstruction.patch(startAddress, relative, code); } @Override @@ -241,8 +244,9 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { @Uninterruptible(reason = ".") @Override - public void patch(int codePos, int relative, byte[] code) { - annotation.patch(codePos, relative, code); + public void patch(int compStart, int relative, byte[] code) { + /* Patching a move sequence would hardcode an absolute value, not a pc-relative value. */ + throw VMError.shouldNotReachHere(); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcher.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcher.java index 270ac190569b..6d069ba7859d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcher.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcher.java @@ -86,7 +86,7 @@ public AMD64HostedPatcher(OperandDataAnnotation annotation) { @Uninterruptible(reason = ".") @Override - public void patch(int codePos, int relative, byte[] code) { + public void patch(int compStart, int relative, byte[] code) { int curValue = relative - (annotation.nextInstructionPosition - annotation.instructionPosition); for (int i = 0; i < annotation.operandSize; i++) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java index 27d4aebbb735..a1ae28bde450 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java @@ -188,7 +188,7 @@ public void patchMethods(DebugContext debug, RelocatableBuffer relocs, ObjectFil // Patch a PC-relative call. // This code handles the case of section-local calls only. int pcDisplacement = callTargetStart - (compStart + call.pcOffset); - patches.get(call.pcOffset).patch(call.pcOffset, pcDisplacement, compilation.getTargetCode()); + patches.get(call.pcOffset).patch(compStart, pcDisplacement, compilation.getTargetCode()); } } for (DataPatch dataPatch : compilation.getDataPatches()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java index 18d4f292a131..ef1f7597e74b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java @@ -675,9 +675,14 @@ private void markDataRelocationSiteFromText(RelocatableBuffer buffer, final Prog // validating patched value does not overflow operand switch (info.getRelocationKind()) { case AARCH64_R_MOVW_UABS_G0: + assert (targetValue & 0xFFFF_FFFF_FFFF_0000L) == 0 : "value to patch does not fit"; + break; case AARCH64_R_MOVW_UABS_G1: + assert (targetValue & 0xFFFF_FFFF_0000_0000L) == 0 : "value to patch does not fit"; + break; case AARCH64_R_MOVW_UABS_G2: - assert (patchValue & 0xFFFF) == patchValue : "value to patch does not fit"; + assert (targetValue & 0xFFFF_0000_0000_0000L) == 0 : "value to patch does not fit"; + break; } int originalInst = bufferBytes.getInt(offset); int newInst = AArch64Assembler.PatcherUtil.patchMov(originalInst, patchValue); From ec2ae057eb315aea7ab186020a5f6a15cb515c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C3=B6=20Barany?= Date: Mon, 4 Oct 2021 17:33:25 +0200 Subject: [PATCH 283/681] Move time of canonicalization when removing obsolete proxies --- .../phases/common/util/LoopUtility.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/LoopUtility.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/LoopUtility.java index 92c2942525ce..48d9637b74ba 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/LoopUtility.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/LoopUtility.java @@ -41,27 +41,34 @@ public class LoopUtility { /** * Remove loop proxies that became obsolete over time, i.e., they proxy a value that already * flowed out of a loop and dominates the loop now. + * + * @param canonicalizer must not be {@code null}, will be applied incrementally to nodes whose + * inputs changed */ + @SuppressWarnings("try") public static void removeObsoleteProxies(StructuredGraph graph, CoreProviders context, CanonicalizerPhase canonicalizer) { LoopsData loopsData = context.getLoopsDataProvider().getLoopsData(graph); - for (LoopEx loop : loopsData.loops()) { - removeObsoleteProxiesForLoop(loop, context, canonicalizer); + final EconomicSetNodeEventListener inputChanges = new EconomicSetNodeEventListener(EnumSet.of(NodeEvent.INPUT_CHANGED)); + try (NodeEventScope s = graph.trackNodeEvents(inputChanges)) { + for (LoopEx loop : loopsData.loops()) { + removeObsoleteProxiesForLoop(loop); + } } + canonicalizer.applyIncremental(graph, context, inputChanges.getNodes()); } - @SuppressWarnings("try") - public static void removeObsoleteProxiesForLoop(LoopEx loop, CoreProviders context, CanonicalizerPhase canonicalizer) { - StructuredGraph graph = loop.loopBegin().graph(); - final EconomicSetNodeEventListener inputChanges = new EconomicSetNodeEventListener(EnumSet.of(NodeEvent.INPUT_CHANGED)); - try (NodeEventScope s = graph.trackNodeEvents(inputChanges)) { - for (LoopExitNode lex : loop.loopBegin().loopExits()) { - for (ProxyNode proxy : lex.proxies().snapshot()) { - if (loop.isOutsideLoop(proxy.value())) { - proxy.replaceAtUsagesAndDelete(proxy.getOriginalNode()); - } + /** + * Remove obsolete proxies from one loop only. Unlike + * {@link #removeObsoleteProxies(StructuredGraph, CoreProviders, CanonicalizerPhase)}, this does + * not apply canonicalization. + */ + public static void removeObsoleteProxiesForLoop(LoopEx loop) { + for (LoopExitNode lex : loop.loopBegin().loopExits()) { + for (ProxyNode proxy : lex.proxies().snapshot()) { + if (loop.isOutsideLoop(proxy.value())) { + proxy.replaceAtUsagesAndDelete(proxy.getOriginalNode()); } } } - canonicalizer.applyIncremental(graph, context, inputChanges.getNodes()); } } From 9ece91589e41429f1c690e9d37fd429ad0a6980a Mon Sep 17 00:00:00 2001 From: Cosmin Basca Date: Tue, 5 Oct 2021 10:33:19 +0200 Subject: [PATCH 284/681] mx_vm_benchmark.py: hardcode vm field when measuring binary file sizes --- vm/mx.vm/mx_vm_benchmark.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vm/mx.vm/mx_vm_benchmark.py b/vm/mx.vm/mx_vm_benchmark.py index 9101e681b099..5482415a82d4 100644 --- a/vm/mx.vm/mx_vm_benchmark.py +++ b/vm/mx.vm/mx_vm_benchmark.py @@ -1072,12 +1072,13 @@ def runAndReturnStdOut(self, benchmarks, bmSuiteArgs): if isinstance(vm, mx_benchmark.GuestVm): host_vm = vm.host_vm() assert host_vm + name = 'graalvm-ee' if has_component('svmee') else 'graalvm-ce' dims = { - "vm": vm.name(), - # the host-vm is hardcoded to one of the accepted names of the field - "host-vm": 'graalvm-ee' if has_component('svmee') else 'graalvm-ce', + # the vm and host-vm fields are hardcoded to one of the accepted names of the field + "vm": name, + "host-vm": name, "host-vm-config": self.host_vm_config_name(host_vm, vm), - "guest-vm": vm.name() if host_vm else "none", + "guest-vm": name if host_vm else "none", "guest-vm-config": self.guest_vm_config_name(host_vm, vm), } From d3fceb5c3f5949d986779c863fc61a82c9b0910f Mon Sep 17 00:00:00 2001 From: Cosmin Basca Date: Tue, 5 Oct 2021 10:55:25 +0200 Subject: [PATCH 285/681] ci: record file sizes for installables (naming issue fixed) --- vm/ci_common/common.hocon | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/vm/ci_common/common.hocon b/vm/ci_common/common.hocon index 42cfe66a25ff..a6a41487be31 100644 --- a/vm/ci_common/common.hocon +++ b/vm/ci_common/common.hocon @@ -355,6 +355,8 @@ deploy_graalvm_linux_amd64: { ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}, graalvm-show] ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}, build] ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}] ${maven_deploy_sdk_components} + ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}] ${record_file_sizes} + ${upload_file_sizes} ] ${collect_profiles} [ ${mx_vm_common} ${vm_profiles} [graalvm-show] ${mx_vm_common} ${vm_profiles} [build] @@ -374,6 +376,8 @@ deploy_graalvm_linux_aarch64: { ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}, graalvm-show] ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}, build] ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}] ${maven_deploy_sdk_components} + ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}] ${record_file_sizes} + ${upload_file_sizes} ] ${collect_profiles} [ ${mx_vm_common} ${vm_profiles} [graalvm-show] ${mx_vm_common} ${vm_profiles} [build] @@ -404,6 +408,8 @@ deploy_graalvm_installables_darwin_amd64: { ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}, build] ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}] ${maven_deploy_sdk_components} ${notify-nexus-deploy} + ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components}] ${record_file_sizes} + ${upload_file_sizes} ${notify-releaser} ] timelimit: "3:00:00" @@ -429,6 +435,8 @@ deploy_graalvm_installables_windows_amd64: { ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components-windows}, build] ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components-windows}] ${maven_deploy_sdk_components} ${notify-nexus-deploy} + ${mx_vm_installables} [--dynamicimports, "${VM_EXTRA_SUITES}", "--exclude-components="${non-product-vm-components-windows}] ${record_file_sizes} + ${upload_file_sizes} ] timelimit: "1:30:00" } @@ -438,8 +446,6 @@ deploy_graalvm_plus_ruby: { [set-export, VM_ENV, "${VM_ENV}-ruby"] ${mx_vm_common} ${vm_profiles} [graalvm-show] ${mx_vm_common} ${vm_profiles} [build] - ${mx_vm_common} ${vm_profiles} ${record_file_sizes} - ${upload_file_sizes} ${mx_vm_common} ${vm_profiles} ${maven_deploy_sdk_base} ${notify-nexus-deploy} [set-export, GRAALVM_HOME, ${mx_vm_common} [--quiet, --no-warning, graalvm-home]] From 7992567acbd463e4fd80b9134833b74e94a3b4ca Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Mon, 27 Sep 2021 18:02:03 +0200 Subject: [PATCH 286/681] Fix build issue with OpenJDK 17.0.2-dev JDK-8271862 got backported to OpenJDK 17.0.2 (current jdk17u development tree). This patch accounts for those changes which introduce a new method: Reference.refersToImpl(T obj). Update Reference substitutions accordingly. Closes #3837 --- .../heap/Target_java_lang_ref_Reference.java | 5 +++ .../oracle/svm/core/jdk/JDK17_0_2OrLater.java | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK17_0_2OrLater.java diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java index 75ad1fed197e..79281b6269b3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java @@ -51,6 +51,7 @@ import com.oracle.svm.core.annotate.UnknownClass; import com.oracle.svm.core.jdk.JDK11OrLater; import com.oracle.svm.core.jdk.JDK16OrLater; +import com.oracle.svm.core.jdk.JDK17_0_2OrLater; import com.oracle.svm.core.jdk.JDK8OrEarlier; import com.oracle.svm.core.util.VMError; import com.oracle.svm.util.ReflectionUtil; @@ -138,6 +139,10 @@ private void clear0() { clear(); } + @KeepOriginal + @TargetElement(onlyWith = JDK17_0_2OrLater.class) + native boolean refersToImpl(T obj); + @KeepOriginal @TargetElement(onlyWith = JDK16OrLater.class) public native boolean refersTo(T obj); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK17_0_2OrLater.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK17_0_2OrLater.java new file mode 100644 index 000000000000..05a7fe4f401b --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK17_0_2OrLater.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.svm.core.jdk; + +import java.util.function.BooleanSupplier; + +import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; + +public class JDK17_0_2OrLater implements BooleanSupplier { + + @Override + public boolean getAsBoolean() { + return JavaVersionUtil.JAVA_SPEC > 17 || + (JavaVersionUtil.JAVA_SPEC == 17 && GraalServices.getJavaUpdateVersion() > 1); + } + +} From 7af0e63f5a6a9a3d3b61ffd497d65e5bbd7e976d Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Mon, 13 Sep 2021 14:38:52 +0200 Subject: [PATCH 287/681] Default to adaptive GC policy. --- .../src/com/oracle/svm/core/genscavenge/CollectionPolicy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java index feb0b4680fdd..581ea291de19 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java @@ -38,8 +38,8 @@ /** The interface for a garbage collection policy. All sizes are in bytes. */ public interface CollectionPolicy { final class Options { - @Option(help = "The garbage collection policy, either Adaptive or BySpaceAndTime (default).")// - public static final HostedOptionKey InitialCollectionPolicy = new HostedOptionKey<>("BySpaceAndTime"); + @Option(help = "The garbage collection policy, either Adaptive (default) or BySpaceAndTime.")// + public static final HostedOptionKey InitialCollectionPolicy = new HostedOptionKey<>("Adaptive"); } @Platforms(Platform.HOSTED_ONLY.class) From 31749933fb50b725881a4b2f702cb5c7f9a1a33f Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Tue, 5 Oct 2021 13:51:35 +0200 Subject: [PATCH 288/681] [GR-34181] Add dispatch object into Source and SourceSection. --- .../src/org/graalvm/polyglot/Context.java | 4 +- .../src/org/graalvm/polyglot/Engine.java | 170 +++------------- .../src/org/graalvm/polyglot/Source.java | 82 ++++---- .../org/graalvm/polyglot/SourceSection.java | 38 ++-- .../polyglot/impl/AbstractPolyglotImpl.java | 55 ++++-- .../api/test/polyglot/SourceAPITest.java | 58 +++++- .../api/test/wrapper/HostContextDispatch.java | 14 +- .../test/wrapper/HostPolyglotDispatch.java | 9 +- .../truffle/polyglot/EngineAccessor.java | 2 +- .../oracle/truffle/polyglot/FileSystems.java | 2 +- .../polyglot/PolyglotContextDispatch.java | 9 +- .../truffle/polyglot/PolyglotContextImpl.java | 16 +- .../polyglot/PolyglotExceptionFrame.java | 4 +- .../polyglot/PolyglotExceptionImpl.java | 4 +- .../oracle/truffle/polyglot/PolyglotImpl.java | 21 +- .../polyglot/PolyglotSourceDispatch.java | 133 +------------ .../polyglot/PolyglotSourceFactory.java | 184 ++++++++++++++++++ .../polyglot/PolyglotValueDispatch.java | 6 +- 18 files changed, 417 insertions(+), 394 deletions(-) create mode 100644 truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceFactory.java diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java index 584e5011e8c0..1379b19e3a0b 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Context.java @@ -396,7 +396,7 @@ public Engine getEngine() { * @since 19.0 */ public Value eval(Source source) { - return dispatch.eval(receiver, source.getLanguage(), source.receiver); + return dispatch.eval(receiver, source.getLanguage(), source); } /** @@ -477,7 +477,7 @@ public Value eval(String languageId, CharSequence source) { * @since 20.2 */ public Value parse(Source source) throws PolyglotException { - return dispatch.parse(receiver, source.getLanguage(), source.receiver); + return dispatch.parse(receiver, source.getLanguage(), source); } /** diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java index f2eda02ec391..e9d2ec661849 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java @@ -44,7 +44,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.Reader; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Executable; import java.lang.reflect.Method; @@ -85,9 +84,10 @@ import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractExceptionDispatch; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractInstrumentDispatch; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractLanguageDispatch; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceDispatch; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceSectionDispatch; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractStackFrameImpl; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractValueDispatch; -import org.graalvm.polyglot.io.ByteSequence; import org.graalvm.polyglot.io.FileSystem; import org.graalvm.polyglot.io.MessageTransport; @@ -624,13 +624,13 @@ public Value newValue(AbstractValueDispatch dispatch, Object context, Object rec } @Override - public Source newSource(Object receiver) { - return new Source(receiver); + public Source newSource(AbstractSourceDispatch dispatch, Object receiver) { + return new Source(dispatch, receiver); } @Override - public SourceSection newSourceSection(Source source, Object receiver) { - return new SourceSection(source, receiver); + public SourceSection newSourceSection(Source source, AbstractSourceSectionDispatch dispatch, Object receiver) { + return new SourceSection(source, dispatch, receiver); } @Override @@ -653,6 +653,16 @@ public AbstractEngineDispatch getDispatch(Engine engine) { return engine.dispatch; } + @Override + public AbstractSourceDispatch getDispatch(Source source) { + return source.dispatch; + } + + @Override + public AbstractSourceSectionDispatch getDispatch(SourceSection sourceSection) { + return sourceSection.dispatch; + } + @Override public ResourceLimitEvent newResourceLimitsEvent(Context context) { return new ResourceLimitEvent(context); @@ -668,6 +678,16 @@ public Object getReceiver(ResourceLimits value) { return value.receiver; } + @Override + public Object getReceiver(Source source) { + return source.receiver; + } + + @Override + public Object getReceiver(SourceSection sourceSection) { + return sourceSection.receiver; + } + @Override public PolyglotException newLanguageException(String message, AbstractExceptionDispatch dispatch, Object receiver) { return new PolyglotException(message, dispatch, receiver); @@ -859,7 +879,7 @@ static Iterator createInvalidPolyglotImpl() { private static class PolyglotInvalid extends AbstractPolyglotImpl { - private final EmptySource source = new EmptySource(this); + private final EmptySourceFactory sourceFactory = new EmptySourceFactory(this); /** * Forces ahead-of-time initialization. @@ -919,13 +939,8 @@ private static RuntimeException noPolyglotImplementationFound() { } @Override - public AbstractSourceDispatch getSourceDispatch() { - return source; - } - - @Override - public AbstractSourceSectionDispatch getSourceSectionDispatch() { - throw new UnsupportedOperationException(); + public AbstractSourceFactory getSourceFactory() { + return sourceFactory; } @Override @@ -956,10 +971,10 @@ public FileSystem newDefaultFileSystem() { throw noPolyglotImplementationFound(); } - static class EmptySource extends AbstractSourceDispatch { + static class EmptySourceFactory extends AbstractSourceFactory { - protected EmptySource(AbstractPolyglotImpl engineImpl) { - super(engineImpl); + EmptySourceFactory(AbstractPolyglotImpl polyglot) { + super(polyglot); } @Override @@ -968,11 +983,6 @@ public Source build(String language, Object origin, URI uri, String name, String throw noPolyglotImplementationFound(); } - @Override - public String getLanguage(Object impl) { - throw new UnsupportedOperationException(); - } - @Override public String findLanguage(File file) throws IOException { return null; @@ -993,126 +1003,10 @@ public String findMimeType(URL url) throws IOException { return null; } - @Override - public String getMimeType(Object impl) { - throw new UnsupportedOperationException(); - } - @Override public String findLanguage(String mimeType) { return null; } - - @Override - public String getName(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public String getPath(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isInteractive(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public URL getURL(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public URI getURI(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public Reader getReader(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public InputStream getInputStream(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public int getLength(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public CharSequence getCharacters(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public CharSequence getCharacters(Object impl, int lineNumber) { - throw new UnsupportedOperationException(); - } - - @Override - public int getLineCount(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public int getLineNumber(Object impl, int offset) { - throw new UnsupportedOperationException(); - } - - @Override - public int getColumnNumber(Object impl, int offset) { - throw new UnsupportedOperationException(); - } - - @Override - public int getLineStartOffset(Object impl, int lineNumber) { - throw new UnsupportedOperationException(); - } - - @Override - public int getLineLength(Object impl, int lineNumber) { - throw new UnsupportedOperationException(); - } - - @Override - public String toString(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public int hashCode(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean equals(Object impl, Object otherImpl) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isInternal(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public ByteSequence getBytes(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean hasCharacters(Object impl) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean hasBytes(Object impl) { - throw new UnsupportedOperationException(); - } - } @Override diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Source.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Source.java index 6479250dd04b..190e9783c3d8 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Source.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Source.java @@ -52,6 +52,7 @@ import java.util.Objects; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceDispatch; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceFactory; import org.graalvm.polyglot.io.ByteSequence; /** @@ -130,24 +131,25 @@ */ public final class Source { - private static volatile AbstractSourceDispatch DISPATCH; + private static volatile AbstractSourceFactory FACTORY; - static AbstractSourceDispatch getReceiver() { - if (DISPATCH == null) { + static AbstractSourceFactory getFactory() { + if (FACTORY == null) { synchronized (Engine.class) { - if (DISPATCH == null) { - DISPATCH = Engine.getImpl().getSourceDispatch(); - SourceSection.DISPATCH = Engine.getImpl().getSourceSectionDispatch(); + if (FACTORY == null) { + FACTORY = Engine.getImpl().getSourceFactory(); } } } - return DISPATCH; + return FACTORY; } + final AbstractSourceDispatch dispatch; final Object receiver; - Source(Object impl) { - this.receiver = impl; + Source(AbstractSourceDispatch dispatch, Object receiver) { + this.dispatch = dispatch; + this.receiver = receiver; } /** @@ -157,7 +159,7 @@ static AbstractSourceDispatch getReceiver() { * @since 19.0 */ public String getLanguage() { - return getReceiver().getLanguage(receiver); + return dispatch.getLanguage(receiver); } /** @@ -170,7 +172,7 @@ public String getLanguage() { * @since 19.0 */ public String getName() { - return getReceiver().getName(receiver); + return dispatch.getName(receiver); } /** @@ -182,7 +184,7 @@ public String getName() { * @since 19.0 */ public String getPath() { - return getReceiver().getPath(receiver); + return dispatch.getPath(receiver); } /** @@ -192,7 +194,7 @@ public String getPath() { * @since 19.0 */ public URL getURL() { - return getReceiver().getURL(receiver); + return dispatch.getURL(receiver); } /** @@ -206,7 +208,7 @@ public URL getURL() { * @since 19.0 */ public URI getURI() { - return getReceiver().getURI(receiver); + return dispatch.getURI(receiver); } /** @@ -221,7 +223,7 @@ public URI getURI() { * @since 19.0 */ public boolean isInteractive() { - return getReceiver().isInteractive(receiver); + return dispatch.isInteractive(receiver); } /** @@ -240,7 +242,7 @@ public boolean isInteractive() { * @since 19.0 */ public boolean isInternal() { - return getReceiver().isInternal(receiver); + return dispatch.isInternal(receiver); } /** @@ -252,7 +254,7 @@ public boolean isInternal() { * @since 19.0 */ public Reader getReader() { - return getReceiver().getReader(receiver); + return dispatch.getReader(receiver); } /** @@ -263,7 +265,7 @@ public Reader getReader() { */ @Deprecated public InputStream getInputStream() { - return getReceiver().getInputStream(receiver); + return dispatch.getInputStream(receiver); } /** @@ -272,7 +274,7 @@ public InputStream getInputStream() { * @since 19.0 */ public int getLength() { - return getReceiver().getLength(receiver); + return dispatch.getLength(receiver); } /** @@ -283,7 +285,7 @@ public int getLength() { * @since 19.0 */ public CharSequence getCharacters() { - return getReceiver().getCharacters(receiver); + return dispatch.getCharacters(receiver); } /** @@ -307,7 +309,7 @@ public CharSequence getCharacters() { * @since 19.0 */ public String getMimeType() { - return getReceiver().getMimeType(receiver); + return dispatch.getMimeType(receiver); } /** @@ -320,7 +322,7 @@ public String getMimeType() { * @since 19.0 */ public CharSequence getCharacters(int lineNumber) { - return getReceiver().getCharacters(receiver, lineNumber); + return dispatch.getCharacters(receiver, lineNumber); } /** @@ -332,7 +334,7 @@ public CharSequence getCharacters(int lineNumber) { * @since 19.0 */ public ByteSequence getBytes() { - return getReceiver().getBytes(receiver); + return dispatch.getBytes(receiver); } /** @@ -355,7 +357,7 @@ public ByteSequence getBytes() { * @since 19.0 */ public boolean hasCharacters() { - return getReceiver().hasCharacters(receiver); + return dispatch.hasCharacters(receiver); } /** @@ -369,7 +371,7 @@ public boolean hasCharacters() { * @since 19.0 */ public boolean hasBytes() { - return getReceiver().hasBytes(receiver); + return dispatch.hasBytes(receiver); } /** @@ -382,7 +384,7 @@ public boolean hasBytes() { * @since 19.0 */ public int getLineCount() { - return getReceiver().getLineCount(receiver); + return dispatch.getLineCount(receiver); } /** @@ -395,7 +397,7 @@ public int getLineCount() { * @since 19.0 */ public int getLineNumber(int offset) throws IllegalArgumentException { - return getReceiver().getLineNumber(receiver, offset); + return dispatch.getLineNumber(receiver, offset); } /** @@ -408,7 +410,7 @@ public int getLineNumber(int offset) throws IllegalArgumentException { * @since 19.0 */ public int getColumnNumber(int offset) throws IllegalArgumentException { - return getReceiver().getColumnNumber(receiver, offset); + return dispatch.getColumnNumber(receiver, offset); } /** @@ -420,7 +422,7 @@ public int getColumnNumber(int offset) throws IllegalArgumentException { * @since 19.0 */ public int getLineStartOffset(int lineNumber) throws IllegalArgumentException { - return getReceiver().getLineStartOffset(receiver, lineNumber); + return dispatch.getLineStartOffset(receiver, lineNumber); } /** @@ -433,7 +435,7 @@ public int getLineStartOffset(int lineNumber) throws IllegalArgumentException { * @since 19.0 */ public int getLineLength(int lineNumber) throws IllegalArgumentException { - return getReceiver().getLineLength(receiver, lineNumber); + return dispatch.getLineLength(receiver, lineNumber); } /** @@ -443,7 +445,7 @@ public int getLineLength(int lineNumber) throws IllegalArgumentException { */ @Override public String toString() { - return getReceiver().toString(receiver); + return dispatch.toString(receiver); } /** @@ -453,7 +455,7 @@ public String toString() { */ @Override public int hashCode() { - return getReceiver().hashCode(receiver); + return dispatch.hashCode(receiver); } /** @@ -469,7 +471,7 @@ public boolean equals(Object obj) { } else { return false; } - return getReceiver().equals(receiver, otherImpl); + return dispatch.equals(receiver, otherImpl); } /** @@ -591,7 +593,7 @@ public static Source create(String language, CharSequence source) { * @since 19.0 */ public static String findLanguage(File file) throws IOException { - return getReceiver().findLanguage(file); + return getFactory().findLanguage(file); } /** @@ -612,7 +614,7 @@ public static String findLanguage(File file) throws IOException { * @since 19.0 */ public static String findLanguage(URL url) throws IOException { - return getReceiver().findLanguage(url); + return getFactory().findLanguage(url); } /** @@ -625,7 +627,7 @@ public static String findLanguage(URL url) throws IOException { * @since 19.0 */ public static String findMimeType(File file) throws IOException { - return getReceiver().findMimeType(file); + return getFactory().findMimeType(file); } /** @@ -640,7 +642,7 @@ public static String findMimeType(File file) throws IOException { * @since 19.0 */ public static String findMimeType(URL url) throws IOException { - return getReceiver().findMimeType(url); + return getFactory().findMimeType(url); } /** @@ -652,7 +654,7 @@ public static String findMimeType(URL url) throws IOException { * @since 19.0 */ public static String findLanguage(String mimeType) { - return getReceiver().findLanguage(mimeType); + return getFactory().findLanguage(mimeType); } @SuppressWarnings({"unchecked", "unused"}) @@ -677,7 +679,7 @@ private static IllegalArgumentException invalidMimeType(String mimeType) { return new IllegalArgumentException(String.format("Invalid MIME type '%s' provided. A MIME type consists of a type and a subtype separated by '/'.", mimeType)); } - private static final Source EMPTY = new Source(null); + private static final Source EMPTY = new Source(null, null); /** * Represents a builder to build {@link Source} objects. @@ -915,7 +917,7 @@ public Builder encoding(Charset encoding) { * @since 19.0 */ public Source build() throws IOException { - Source source = getReceiver().build(language, origin, uri, name, mimeType, content, interactive, internal, cached, fileEncoding); + Source source = getFactory().build(language, origin, uri, name, mimeType, content, interactive, internal, cached, fileEncoding); // make sure origin is not consumed again if builder is used twice if (source.hasBytes()) { diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/SourceSection.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/SourceSection.java index 8e6a3b19f17b..3e4c0a357460 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/SourceSection.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/SourceSection.java @@ -54,13 +54,13 @@ */ public final class SourceSection { - static volatile AbstractSourceSectionDispatch DISPATCH; - final Source source; + final AbstractSourceSectionDispatch dispatch; final Object receiver; - SourceSection(Source source, Object receiver) { + SourceSection(Source source, AbstractSourceSectionDispatch dispatch, Object receiver) { this.source = source; + this.dispatch = dispatch; this.receiver = receiver; } @@ -73,7 +73,7 @@ public final class SourceSection { * @since 19.0 */ public boolean isAvailable() { - return DISPATCH.isAvailable(receiver); + return dispatch.isAvailable(receiver); } /** @@ -85,7 +85,7 @@ public boolean isAvailable() { * @since 19.0 */ public boolean hasLines() { - return DISPATCH.hasLines(receiver); + return dispatch.hasLines(receiver); } /** @@ -98,7 +98,7 @@ public boolean hasLines() { * @since 19.0 */ public boolean hasColumns() { - return DISPATCH.hasColumns(receiver); + return dispatch.hasColumns(receiver); } /** @@ -111,7 +111,7 @@ public boolean hasColumns() { * @since 19.0 */ public boolean hasCharIndex() { - return DISPATCH.hasCharIndex(receiver); + return dispatch.hasCharIndex(receiver); } /** @@ -134,7 +134,7 @@ public Source getSource() { * @since 19.0 */ public int getStartLine() { - return DISPATCH.getStartLine(receiver); + return dispatch.getStartLine(receiver); } /** @@ -147,7 +147,7 @@ public int getStartLine() { * @since 19.0 */ public int getStartColumn() { - return DISPATCH.getStartColumn(receiver); + return dispatch.getStartColumn(receiver); } /** @@ -160,7 +160,7 @@ public int getStartColumn() { * @since 19.0 */ public int getEndLine() { - return DISPATCH.getEndLine(receiver); + return dispatch.getEndLine(receiver); } /** @@ -173,7 +173,7 @@ public int getEndLine() { * @since 19.0 */ public int getEndColumn() { - return DISPATCH.getEndColumn(receiver); + return dispatch.getEndColumn(receiver); } /** @@ -187,7 +187,7 @@ public int getEndColumn() { * @since 19.0 */ public int getCharIndex() { - return DISPATCH.getCharIndex(receiver); + return dispatch.getCharIndex(receiver); } /** @@ -201,7 +201,7 @@ public int getCharIndex() { * @since 19.0 */ public int getCharLength() { - return DISPATCH.getCharLength(receiver); + return dispatch.getCharLength(receiver); } /** @@ -215,7 +215,7 @@ public int getCharLength() { * @since 19.0 */ public int getCharEndIndex() { - return DISPATCH.getCharEndIndex(receiver); + return dispatch.getCharEndIndex(receiver); } /** @@ -224,7 +224,7 @@ public int getCharEndIndex() { */ @Deprecated public CharSequence getCode() { - return DISPATCH.getCode(receiver); + return dispatch.getCode(receiver); } /** @@ -235,7 +235,7 @@ public CharSequence getCode() { * @since 19.0 */ public CharSequence getCharacters() { - return DISPATCH.getCode(receiver); + return dispatch.getCode(receiver); } /** @@ -247,13 +247,13 @@ public CharSequence getCharacters() { */ @Override public String toString() { - return DISPATCH.toString(receiver); + return dispatch.toString(receiver); } /** @since 19.0 or earlier */ @Override public int hashCode() { - return DISPATCH.hashCode(receiver); + return dispatch.hashCode(receiver); } /** @since 19.0 or earlier */ @@ -267,7 +267,7 @@ public boolean equals(Object obj) { if (otherImpl instanceof SourceSection) { otherImpl = ((SourceSection) obj).receiver; } - return DISPATCH.equals(receiver, otherImpl); + return dispatch.equals(receiver, otherImpl); } } diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java index c622d019e26c..e6c1adc78a0c 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java @@ -161,9 +161,9 @@ protected APIAccess() { public abstract Value newValue(AbstractValueDispatch dispatch, Object context, Object receiver); - public abstract Source newSource(Object receiver); + public abstract Source newSource(AbstractSourceDispatch dispatch, Object receiver); - public abstract SourceSection newSourceSection(Source source, Object receiver); + public abstract SourceSection newSourceSection(Source source, AbstractSourceSectionDispatch dispatch, Object receiver); public abstract PolyglotException newLanguageException(String message, AbstractExceptionDispatch dispatch, Object receiver); @@ -179,6 +179,10 @@ protected APIAccess() { public abstract Object getReceiver(ResourceLimits value); + public abstract Object getReceiver(Source source); + + public abstract Object getReceiver(SourceSection sourceSection); + public abstract AbstractValueDispatch getDispatch(Value value); public abstract Object getContext(Value value); @@ -193,6 +197,10 @@ protected APIAccess() { public abstract AbstractContextDispatch getDispatch(Context context); + public abstract AbstractSourceDispatch getDispatch(Source source); + + public abstract AbstractSourceSectionDispatch getDispatch(SourceSection sourceSection); + public abstract ResourceLimitEvent newResourceLimitsEvent(Context context); public abstract StackFrame newPolyglotStackTraceElement(AbstractStackFrameImpl dispatch, Object receiver); @@ -294,9 +302,7 @@ public abstract Engine buildEngine(OutputStream out, OutputStream err, InputStre public abstract void resetPreInitializedEngine(); - public abstract AbstractSourceDispatch getSourceDispatch(); - - public abstract AbstractSourceSectionDispatch getSourceSectionDispatch(); + public abstract AbstractSourceFactory getSourceFactory(); /** * Returns the default host dispatch of this polyglot abstraction. @@ -336,11 +342,11 @@ public final AbstractPolyglotImpl getPolyglotImpl() { } - public abstract static class AbstractSourceDispatch { + public abstract static class AbstractSourceFactory { protected final AbstractPolyglotImpl engineImpl; - protected AbstractSourceDispatch(AbstractPolyglotImpl engineImpl) { + protected AbstractSourceFactory(AbstractPolyglotImpl engineImpl) { Objects.requireNonNull(engineImpl); this.engineImpl = engineImpl; } @@ -348,6 +354,27 @@ protected AbstractSourceDispatch(AbstractPolyglotImpl engineImpl) { public abstract Source build(String language, Object origin, URI uri, String name, String mimeType, Object content, boolean interactive, boolean internal, boolean cached, Charset encoding) throws IOException; + public abstract String findLanguage(File file) throws IOException; + + public abstract String findLanguage(URL url) throws IOException; + + public abstract String findLanguage(String mimeType); + + public abstract String findMimeType(File file) throws IOException; + + public abstract String findMimeType(URL url) throws IOException; + + } + + public abstract static class AbstractSourceDispatch { + + protected final AbstractPolyglotImpl engineImpl; + + protected AbstractSourceDispatch(AbstractPolyglotImpl engineImpl) { + Objects.requireNonNull(engineImpl); + this.engineImpl = engineImpl; + } + public abstract String getName(Object impl); public abstract String getPath(Object impl); @@ -386,16 +413,6 @@ public abstract Source build(String language, Object origin, URI uri, String nam public abstract boolean isInternal(Object impl); - public abstract String findLanguage(File file) throws IOException; - - public abstract String findLanguage(URL url) throws IOException; - - public abstract String findLanguage(String mimeType); - - public abstract String findMimeType(File file) throws IOException; - - public abstract String findMimeType(URL url) throws IOException; - public abstract ByteSequence getBytes(Object impl); public abstract boolean hasCharacters(Object impl); @@ -454,9 +471,9 @@ protected AbstractContextDispatch(AbstractPolyglotImpl impl) { public abstract boolean initializeLanguage(Object receiver, String languageId); - public abstract Value eval(Object receiver, String language, Object sourceImpl); + public abstract Value eval(Object receiver, String language, Source source); - public abstract Value parse(Object receiver, String language, Object sourceImpl); + public abstract Value parse(Object receiver, String language, Source source); public abstract void close(Object receiver, boolean cancelIfExecuting); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITest.java index 6ac3f2d5e479..1ea0419d2589 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITest.java @@ -40,6 +40,13 @@ */ package com.oracle.truffle.api.test.polyglot; +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.test.OSUtils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -69,9 +76,14 @@ import java.util.zip.ZipOutputStream; import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Source.Builder; import org.graalvm.polyglot.SourceSection; +import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceSectionDispatch; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceDispatch; import org.graalvm.polyglot.io.ByteSequence; import org.junit.Assert; import org.junit.Test; @@ -660,10 +672,12 @@ public void throwsErrorIfLangIsNull3() throws MalformedURLException { @Test @SuppressWarnings("rawtypes") public void testNoContentSource() { + AbstractPolyglotImpl polyglot = (AbstractPolyglotImpl) ReflectionUtils.invokeStatic(Engine.class, "getImpl"); com.oracle.truffle.api.source.Source truffleSource = com.oracle.truffle.api.source.Source.newBuilder(ProxyLanguage.ID, "x", "name").content( com.oracle.truffle.api.source.Source.CONTENT_NONE).build(); - Class[] sourceConstructorTypes = new Class[]{Object.class}; - Source source = ReflectionUtils.newInstance(Source.class, sourceConstructorTypes, truffleSource); + Class[] sourceConstructorTypes = new Class[]{AbstractSourceDispatch.class, Object.class}; + Source source = ReflectionUtils.newInstance(Source.class, sourceConstructorTypes, + polyglot.getAPIAccess().getDispatch(Source.create(ProxyLanguage.ID, "")), truffleSource); assertFalse(source.hasCharacters()); assertFalse(source.hasBytes()); try { @@ -679,8 +693,9 @@ public void testNoContentSource() { // O.K. } com.oracle.truffle.api.source.SourceSection truffleSection = truffleSource.createSection(1, 2, 3, 4); - Class[] sectionConstructorTypes = new Class[]{Source.class, Object.class}; - SourceSection section = ReflectionUtils.newInstance(SourceSection.class, sectionConstructorTypes, source, truffleSection); + Class[] sectionConstructorTypes = new Class[]{Source.class, AbstractSourceSectionDispatch.class, Object.class}; + SourceSection section = ReflectionUtils.newInstance(SourceSection.class, sectionConstructorTypes, source, + getSourceSectionDispatch(polyglot), truffleSection); assertFalse(section.hasCharIndex()); assertTrue(section.hasLines()); assertTrue(section.hasColumns()); @@ -688,6 +703,41 @@ public void testNoContentSource() { assertTrue(truffleSource.getURI().toString().contains("name")); } + private static AbstractSourceSectionDispatch getSourceSectionDispatch(AbstractPolyglotImpl polyglot) { + ProxyLanguage.setDelegate(new ProxyLanguage() { + @Override + protected CallTarget parse(ParsingRequest request) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(new SourceSectionProvider(request.getSource()))); + } + }); + try (Context context = Context.create(ProxyLanguage.ID)) { + Value res = context.eval(Source.create(ProxyLanguage.ID, "")); + SourceSection sourceSection = res.getSourceLocation(); + return polyglot.getAPIAccess().getDispatch(sourceSection); + } + } + + @ExportLibrary(InteropLibrary.class) + static final class SourceSectionProvider implements TruffleObject { + + private final com.oracle.truffle.api.source.Source source; + + SourceSectionProvider(com.oracle.truffle.api.source.Source source) { + this.source = source; + } + + @ExportMessage + @SuppressWarnings("static-method") + public boolean hasSourceLocation() { + return true; + } + + @ExportMessage + public com.oracle.truffle.api.source.SourceSection getSourceLocation() { + return source.createSection(0, 0); + } + } + @Test public void testNonResolvableURL() throws IOException { Assume.assumeFalse("Query parameters are not supported by file URLConnection on Windows", OSUtils.isWindows()); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostContextDispatch.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostContextDispatch.java index 5b2533441e6f..a61a4a99e6e7 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostContextDispatch.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostContextDispatch.java @@ -43,7 +43,9 @@ import java.time.Duration; import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceDispatch; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.APIAccess; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractContextDispatch; @@ -77,11 +79,13 @@ public boolean initializeLanguage(Object receiver, String languageId) { } @Override - public Value eval(Object receiver, String language, Object sourceImpl) { + public Value eval(Object receiver, String language, Source source) { HostContext context = (HostContext) receiver; - - String languageId = polyglot.getSourceDispatch().getLanguage(sourceImpl); - String characters = polyglot.getSourceDispatch().getCharacters(sourceImpl).toString(); + APIAccess apiAccess = polyglot.getAPIAccess(); + AbstractSourceDispatch sourceDispatch = apiAccess.getDispatch(source); + Object sourceImpl = apiAccess.getReceiver(source); + String languageId = sourceDispatch.getLanguage(sourceImpl); + String characters = sourceDispatch.getCharacters(sourceImpl).toString(); long remoteValue = hostToGuest.remoteEval(context.remoteContext, languageId, characters); return context.localContext.asValue(new HostGuestValue(hostToGuest, context.remoteContext, remoteValue)); @@ -105,7 +109,7 @@ public Value getBindings(Object receiver, String language) { } @Override - public Value parse(Object receiver, String language, Object sourceImpl) { + public Value parse(Object receiver, String language, Source source) { throw new UnsupportedOperationException(); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java index d915d23dd136..e60efa30cc1e 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java @@ -110,13 +110,8 @@ public void resetPreInitializedEngine() { } @Override - public AbstractSourceDispatch getSourceDispatch() { - return getNext().getSourceDispatch(); - } - - @Override - public AbstractSourceSectionDispatch getSourceSectionDispatch() { - return getNext().getSourceSectionDispatch(); + public AbstractSourceFactory getSourceFactory() { + return getNext().getSourceFactory(); } @Override diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java index 156a05f6ae48..19a8c0fd24d7 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java @@ -120,7 +120,7 @@ import com.oracle.truffle.polyglot.PolyglotLocals.InstrumentContextThreadLocal; import com.oracle.truffle.polyglot.PolyglotLocals.LanguageContextLocal; import com.oracle.truffle.polyglot.PolyglotLocals.LanguageContextThreadLocal; -import com.oracle.truffle.polyglot.PolyglotSourceDispatch.EmbedderFileSystemContext; +import com.oracle.truffle.polyglot.PolyglotSourceFactory.EmbedderFileSystemContext; import com.oracle.truffle.polyglot.PolyglotThread.ThreadSpawnRootNode; final class EngineAccessor extends Accessor { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/FileSystems.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/FileSystems.java index 637c5122ad4c..6b6165e384ce 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/FileSystems.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/FileSystems.java @@ -74,7 +74,7 @@ import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.nodes.LanguageInfo; -import com.oracle.truffle.polyglot.PolyglotSourceDispatch.EmbedderFileSystemContext; +import com.oracle.truffle.polyglot.PolyglotSourceFactory.EmbedderFileSystemContext; import java.nio.charset.Charset; import org.graalvm.nativeimage.ImageInfo; diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextDispatch.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextDispatch.java index ea3f7e9508e3..60c13c37c77a 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextDispatch.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextDispatch.java @@ -43,6 +43,7 @@ import java.time.Duration; import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractContextDispatch; @@ -58,13 +59,13 @@ public boolean initializeLanguage(Object receiver, String languageId) { } @Override - public Value eval(Object receiver, String language, Object sourceImpl) { - return ((PolyglotContextImpl) receiver).eval(language, sourceImpl); + public Value eval(Object receiver, String language, Source source) { + return ((PolyglotContextImpl) receiver).eval(language, source); } @Override - public Value parse(Object receiver, String language, Object sourceImpl) { - return ((PolyglotContextImpl) receiver).parse(language, sourceImpl); + public Value parse(Object receiver, String language, Source source) { + return ((PolyglotContextImpl) receiver).parse(language, source); } @Override diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java index f39903316827..8f412af30d23 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java @@ -1253,16 +1253,16 @@ public boolean initializeLanguage(String languageId) { } } - public Value parse(String languageId, Object sourceImpl) { + public Value parse(String languageId, org.graalvm.polyglot.Source source) { PolyglotLanguageContext languageContext = lookupLanguageContext(languageId); assert languageContext != null; Object prev = hostEnter(languageContext); try { - Source source = (Source) sourceImpl; + Source truffleSource = (Source) getAPIAccess().getReceiver(source); languageContext.checkAccess(null); languageContext.ensureInitialized(null); - CallTarget target = languageContext.parseCached(null, source, null); - return languageContext.asValue(new PolyglotParsedEval(languageContext, source, target)); + CallTarget target = languageContext.parseCached(null, truffleSource, null); + return languageContext.asValue(new PolyglotParsedEval(languageContext, truffleSource, target)); } catch (Throwable e) { throw PolyglotImpl.guestToHostException(languageContext, e, true); } finally { @@ -1281,15 +1281,15 @@ private PolyglotLanguageContext lookupLanguageContext(String languageId) { return languageContext; } - public Value eval(String languageId, Object sourceImpl) { + public Value eval(String languageId, org.graalvm.polyglot.Source source) { PolyglotLanguageContext languageContext = lookupLanguageContext(languageId); assert languageContext != null; Object prev = hostEnter(languageContext); try { - Source source = (Source) sourceImpl; + Source truffleSource = (Source) getAPIAccess().getReceiver(source); languageContext.checkAccess(null); languageContext.ensureInitialized(null); - CallTarget target = languageContext.parseCached(null, source, null); + CallTarget target = languageContext.parseCached(null, truffleSource, null); Object result = target.call(PolyglotImpl.EMPTY_ARGS); Value hostValue; try { @@ -1297,7 +1297,7 @@ public Value eval(String languageId, Object sourceImpl) { } catch (NullPointerException | ClassCastException e) { throw new AssertionError(String.format("Language %s returned an invalid return value %s. Must be an interop value.", languageId, result), e); } - if (source.isInteractive()) { + if (truffleSource.isInteractive()) { printResult(languageContext, result); } return hostValue; diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionFrame.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionFrame.java index f7770a234426..d0a707749d69 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionFrame.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionFrame.java @@ -159,8 +159,8 @@ static PolyglotExceptionFrame createGuest(PolyglotExceptionImpl exception, Truff if (callNode != null) { com.oracle.truffle.api.source.SourceSection section = callNode.getEncapsulatingSourceSection(); if (section != null) { - Source source = engine.getAPIAccess().newSource(section.getSource()); - location = engine.getAPIAccess().newSourceSection(source, section); + Source source = engine.getAPIAccess().newSource(exception.polyglot.getSourceDispatch(), section.getSource()); + location = engine.getAPIAccess().newSourceSection(source, exception.polyglot.getSourceSectionDispatch(), section); } else { location = null; } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java index 472d364ebcfa..4068d212312c 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExceptionImpl.java @@ -306,8 +306,8 @@ private static Value getLegacyTruffleExceptionGuestObject(PolyglotLanguageContex private SourceSection newSourceSection(com.oracle.truffle.api.source.SourceSection section) { com.oracle.truffle.api.source.Source truffleSource = section.getSource(); - Source source = polyglot.getAPIAccess().newSource(truffleSource); - return polyglot.getAPIAccess().newSourceSection(source, section); + Source source = polyglot.getAPIAccess().newSource(polyglot.getSourceDispatch(), truffleSource); + return polyglot.getAPIAccess().newSourceSection(source, polyglot.getSourceSectionDispatch(), section); } @Override diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java index 510c8d0555a9..b127e39e8e5e 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java @@ -88,6 +88,7 @@ public final class PolyglotImpl extends AbstractPolyglotImpl { static final String OPTION_GROUP_ENGINE = "engine"; static final String PROP_ALLOW_EXPERIMENTAL_OPTIONS = OptionValuesImpl.SYSTEM_PROPERTY_PREFIX + OPTION_GROUP_ENGINE + ".AllowExperimentalOptions"; + private final PolyglotSourceFactory sourceFactory = new PolyglotSourceFactory(this); private final PolyglotSourceDispatch sourceDispatch = new PolyglotSourceDispatch(this); private final PolyglotSourceSectionDispatch sourceSectionDispatch = new PolyglotSourceSectionDispatch(this); private final PolyglotManagementDispatch executionListenerDispatch = new PolyglotManagementDispatch(this); @@ -163,15 +164,21 @@ public Object buildLimits(long statementLimit, Predicate polyglot.getAPIAccess().newSource(t)); + static org.graalvm.polyglot.Source getOrCreatePolyglotSource(PolyglotImpl polyglot, Source source) { + return EngineAccessor.SOURCE.getOrCreatePolyglotSource(source, (t) -> polyglot.getAPIAccess().newSource(polyglot.sourceDispatch, t)); } - static org.graalvm.polyglot.SourceSection getPolyglotSourceSection(AbstractPolyglotImpl polyglot, com.oracle.truffle.api.source.SourceSection sourceSection) { + static org.graalvm.polyglot.SourceSection getPolyglotSourceSection(PolyglotImpl polyglot, com.oracle.truffle.api.source.SourceSection sourceSection) { if (sourceSection == null) { return null; } org.graalvm.polyglot.Source polyglotSource = getOrCreatePolyglotSource(polyglot, sourceSection.getSource()); - return polyglot.getAPIAccess().newSourceSection(polyglotSource, sourceSection); + return polyglot.getAPIAccess().newSourceSection(polyglotSource, polyglot.sourceSectionDispatch, sourceSection); } /** diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceDispatch.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceDispatch.java index 39b9166d6f3d..67dfec744670 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceDispatch.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceDispatch.java @@ -40,33 +40,17 @@ */ package com.oracle.truffle.polyglot; -import static com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere; - import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.net.URI; import java.net.URL; -import java.nio.charset.Charset; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.function.Supplier; -import org.graalvm.polyglot.Source; import org.graalvm.polyglot.impl.AbstractPolyglotImpl; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceDispatch; import org.graalvm.polyglot.io.ByteSequence; -import org.graalvm.polyglot.io.FileSystem; - -import com.oracle.truffle.api.TruffleFile; -import com.oracle.truffle.api.source.Source.SourceBuilder; -class PolyglotSourceDispatch extends AbstractSourceDispatch { - - private volatile Object defaultFileSystemContext; +final class PolyglotSourceDispatch extends AbstractSourceDispatch { protected PolyglotSourceDispatch(AbstractPolyglotImpl engineImpl) { super(engineImpl); @@ -195,50 +179,6 @@ public String getLanguage(Object impl) { return source.getLanguage(); } - @Override - public String findLanguage(File file) throws IOException { - Objects.requireNonNull(file); - String mimeType = findMimeType(file); - if (mimeType != null) { - return findLanguage(mimeType); - } else { - return null; - } - } - - @Override - public String findLanguage(URL url) throws IOException { - String mimeType = findMimeType(url); - if (mimeType != null) { - return findLanguage(mimeType); - } else { - return null; - } - } - - @Override - public String findMimeType(File file) throws IOException { - Objects.requireNonNull(file); - TruffleFile truffleFile = EngineAccessor.LANGUAGE.getTruffleFile(file.toPath().toString(), getDefaultFileSystemContext()); - return truffleFile.detectMimeType(); - } - - @Override - public String findMimeType(URL url) throws IOException { - Objects.requireNonNull(url); - return EngineAccessor.SOURCE.findMimeType(url, getDefaultFileSystemContext()); - } - - @Override - public String findLanguage(String mimeType) { - Objects.requireNonNull(mimeType); - LanguageCache cache = LanguageCache.languageMimes().get(mimeType); - if (cache != null) { - return cache.getId(); - } - return null; - } - @Override public int hashCode(Object impl) { return impl.hashCode(); @@ -267,75 +207,4 @@ public boolean hasCharacters(Object impl) { return source.hasCharacters(); } - @Override - public Source build(String language, Object origin, URI uri, String name, String mimeType, Object content, boolean interactive, boolean internal, boolean cached, Charset encoding) - throws IOException { - assert language != null; - SourceBuilder builder; - if (origin instanceof File) { - builder = EngineAccessor.SOURCE.newBuilder(language, (File) origin); - } else if (origin instanceof CharSequence) { - builder = com.oracle.truffle.api.source.Source.newBuilder(language, ((CharSequence) origin), name); - } else if (origin instanceof ByteSequence) { - builder = com.oracle.truffle.api.source.Source.newBuilder(language, ((ByteSequence) origin), name); - } else if (origin instanceof Reader) { - builder = com.oracle.truffle.api.source.Source.newBuilder(language, (Reader) origin, name); - } else if (origin instanceof URL) { - builder = com.oracle.truffle.api.source.Source.newBuilder(language, (URL) origin); - } else { - throw shouldNotReachHere(); - } - - if (origin instanceof File || origin instanceof URL) { - EngineAccessor.SOURCE.setFileSystemContext(builder, getDefaultFileSystemContext()); - } - - if (content instanceof CharSequence) { - builder.content((CharSequence) content); - } else if (content instanceof ByteSequence) { - builder.content((ByteSequence) content); - } - - builder.uri(uri); - builder.name(name); - builder.internal(internal); - builder.interactive(interactive); - builder.mimeType(mimeType); - builder.cached(cached); - builder.encoding(encoding); - - try { - return PolyglotImpl.getOrCreatePolyglotSource(engineImpl, builder.build()); - } catch (IOException e) { - throw e; - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw shouldNotReachHere(e); - } - } - - private Object getDefaultFileSystemContext() { - Object res = defaultFileSystemContext; - if (res == null) { - synchronized (this) { - res = defaultFileSystemContext; - if (res == null) { - EmbedderFileSystemContext context = new EmbedderFileSystemContext(); - res = EngineAccessor.LANGUAGE.createFileSystemContext(context, context.fileSystem); - defaultFileSystemContext = res; - } - } - } - return res; - } - - static final class EmbedderFileSystemContext { - - final FileSystem fileSystem = FileSystems.newDefaultFileSystem(); - final Map cachedLanguages = LanguageCache.languages(); - final Supplier>> fileTypeDetectors = FileSystems.newFileTypeDetectorsSupplier(cachedLanguages.values()); - - } - } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceFactory.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceFactory.java new file mode 100644 index 000000000000..7b82b19d760e --- /dev/null +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceFactory.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.polyglot; + +import com.oracle.truffle.api.TruffleFile; +import org.graalvm.polyglot.Source; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceFactory; +import org.graalvm.polyglot.io.ByteSequence; +import org.graalvm.polyglot.io.FileSystem; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.net.URI; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.function.Supplier; + +import static com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere; + +final class PolyglotSourceFactory extends AbstractSourceFactory { + + private volatile Object defaultFileSystemContext; + + PolyglotSourceFactory(PolyglotImpl polyglot) { + super(polyglot); + } + + @Override + public String findLanguage(File file) throws IOException { + Objects.requireNonNull(file); + String mimeType = findMimeType(file); + if (mimeType != null) { + return findLanguage(mimeType); + } else { + return null; + } + } + + @Override + public String findLanguage(URL url) throws IOException { + String mimeType = findMimeType(url); + if (mimeType != null) { + return findLanguage(mimeType); + } else { + return null; + } + } + + @Override + public String findMimeType(File file) throws IOException { + Objects.requireNonNull(file); + TruffleFile truffleFile = EngineAccessor.LANGUAGE.getTruffleFile(file.toPath().toString(), getDefaultFileSystemContext()); + return truffleFile.detectMimeType(); + } + + @Override + public String findMimeType(URL url) throws IOException { + Objects.requireNonNull(url); + return EngineAccessor.SOURCE.findMimeType(url, getDefaultFileSystemContext()); + } + + @Override + public String findLanguage(String mimeType) { + Objects.requireNonNull(mimeType); + LanguageCache cache = LanguageCache.languageMimes().get(mimeType); + if (cache != null) { + return cache.getId(); + } + return null; + } + + @Override + public Source build(String language, Object origin, URI uri, String name, String mimeType, Object content, boolean interactive, boolean internal, boolean cached, Charset encoding) + throws IOException { + assert language != null; + com.oracle.truffle.api.source.Source.SourceBuilder builder; + if (origin instanceof File) { + builder = EngineAccessor.SOURCE.newBuilder(language, (File) origin); + } else if (origin instanceof CharSequence) { + builder = com.oracle.truffle.api.source.Source.newBuilder(language, ((CharSequence) origin), name); + } else if (origin instanceof ByteSequence) { + builder = com.oracle.truffle.api.source.Source.newBuilder(language, ((ByteSequence) origin), name); + } else if (origin instanceof Reader) { + builder = com.oracle.truffle.api.source.Source.newBuilder(language, (Reader) origin, name); + } else if (origin instanceof URL) { + builder = com.oracle.truffle.api.source.Source.newBuilder(language, (URL) origin); + } else { + throw shouldNotReachHere(); + } + + if (origin instanceof File || origin instanceof URL) { + EngineAccessor.SOURCE.setFileSystemContext(builder, getDefaultFileSystemContext()); + } + + if (content instanceof CharSequence) { + builder.content((CharSequence) content); + } else if (content instanceof ByteSequence) { + builder.content((ByteSequence) content); + } + + builder.uri(uri); + builder.name(name); + builder.internal(internal); + builder.interactive(interactive); + builder.mimeType(mimeType); + builder.cached(cached); + builder.encoding(encoding); + + try { + return PolyglotImpl.getOrCreatePolyglotSource((PolyglotImpl) engineImpl, builder.build()); + } catch (IOException e) { + throw e; + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw shouldNotReachHere(e); + } + } + + private Object getDefaultFileSystemContext() { + Object res = defaultFileSystemContext; + if (res == null) { + synchronized (this) { + res = defaultFileSystemContext; + if (res == null) { + EmbedderFileSystemContext context = new EmbedderFileSystemContext(); + res = EngineAccessor.LANGUAGE.createFileSystemContext(context, context.fileSystem); + defaultFileSystemContext = res; + } + } + } + return res; + } + + static final class EmbedderFileSystemContext { + + final FileSystem fileSystem = FileSystems.newDefaultFileSystem(); + final Map cachedLanguages = LanguageCache.languages(); + final Supplier>> fileTypeDetectors = FileSystems.newFileTypeDetectorsSupplier(cachedLanguages.values()); + + } +} diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValueDispatch.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValueDispatch.java index d91475da8fd3..bc388963e56b 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValueDispatch.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValueDispatch.java @@ -154,10 +154,10 @@ abstract class PolyglotValueDispatch extends AbstractValueDispatch { static final InteropLibrary UNCACHED_INTEROP = InteropLibrary.getFactory().getUncached(); - final AbstractPolyglotImpl impl; + final PolyglotImpl impl; final PolyglotEngineImpl engine; - PolyglotValueDispatch(AbstractPolyglotImpl impl, PolyglotEngineImpl engine) { + PolyglotValueDispatch(PolyglotImpl impl, PolyglotEngineImpl engine) { super(impl); this.impl = impl; this.engine = engine; @@ -2016,7 +2016,7 @@ static final class InteropValue extends PolyglotValueDispatch { final CallTarget asTypeLiteral; final Class receiverType; - InteropValue(AbstractPolyglotImpl polyglot, PolyglotLanguageInstance languageInstance, Object receiverObject, Class receiverType) { + InteropValue(PolyglotImpl polyglot, PolyglotLanguageInstance languageInstance, Object receiverObject, Class receiverType) { super(polyglot, languageInstance.getEngine()); this.receiverType = receiverType; this.asClassLiteral = createTarget(new AsClassLiteralNode(this)); From 24be5fefb46f3f711d25fe6b7908f4284bc4de92 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Tue, 5 Oct 2021 14:22:13 +0200 Subject: [PATCH 289/681] Avoid createCallTarget() in ContextInterruptCloseCancelOrExitTest. --- .../test/ContextInterruptCloseCancelOrExitTest.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseCancelOrExitTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseCancelOrExitTest.java index 0d71c92d1461..e51066ccbfdf 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseCancelOrExitTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ContextInterruptCloseCancelOrExitTest.java @@ -69,7 +69,6 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.EventContext; import com.oracle.truffle.api.instrumentation.ExecutionEventListener; @@ -271,7 +270,7 @@ public void testNestedExitOnHost() { new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) { - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { LanguageContext languageContext = LanguageContext.get(this); @@ -283,7 +282,7 @@ public Object execute(VirtualFrame frame) { } return 0; } - }); + }.getCallTarget(); } @Override @@ -377,14 +376,14 @@ private static ProxyLanguage getWaitOnExitLanguage(CountDownLatch signalWaitingS return new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) { - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { LanguageContext languageContext = LanguageContext.get(this); languageContext.getEnv().getContext().closeExited(this, 1); return 0; } - }); + }.getCallTarget(); } @Override @@ -556,14 +555,14 @@ public void testExitFromExitNotification() { setupEnv(Context.newBuilder(), new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) { - return Truffle.getRuntime().createCallTarget(new RootNode(languageInstance) { + return new RootNode(languageInstance) { @Override public Object execute(VirtualFrame frame) { LanguageContext languageContext = LanguageContext.get(this); languageContext.getEnv().getContext().closeExited(this, 1); return 0; } - }); + }.getCallTarget(); } @Override From bb02cec547fe00095959b9577182f6f6f9d4b7fb Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 1 Oct 2021 10:07:26 +0200 Subject: [PATCH 290/681] Deprecate TruffleRuntime#createCallTarget(RootNode). --- .../compiler/truffle/runtime/GraalTruffleRuntime.java | 2 ++ truffle/CHANGELOG.md | 1 + .../src/com/oracle/truffle/api/test/TruffleRuntimeTest.java | 1 + truffle/src/com.oracle.truffle.api/snapshot.sigtest | 1 + .../src/com/oracle/truffle/api/TruffleRuntime.java | 5 +++-- 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java index 5adb60c3040a..16ed9eb4e42f 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java @@ -695,6 +695,8 @@ public T getCapability(Class capability) { public abstract SpeculationLog createSpeculationLog(); @Override + @Deprecated + @SuppressWarnings("deprecation") public final RootCallTarget createCallTarget(RootNode rootNode) { return rootNode.getCallTarget(); } diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index b1ee61b1389c..52e95d5e5dfc 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -8,6 +8,7 @@ This changelog summarizes major changes between Truffle versions relevant to lan * Added a [LibraryFactory#getMessages()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/library/LibraryFactory.html#getMessages--) method returning a list of messages that the library provides. * Changed behavior of `RootNode#getCallTarget()` such that it lazily initializes its call target. This enforces a one-to-one relationship between root nodes and call targets, which avoids several problems, for example, with regard to instrumentation. As a consequence, `RootNode.setCallTarget()` is deprecated and so will be `TruffleRuntime#createCallTarget()` soon. Please use `RootNode#getCallTarget()` to access the call target of a root node from now on. +* Changed behavior of `RootNode#getCallTarget()` such that it lazily initializes its call target. This enforces a one-to-one relationship between root nodes and call targets, which avoids several problems, for example, with regard to instrumentation. As a consequence, `RootNode.setCallTarget()` and `TruffleRuntime#createCallTarget()` are deprecated now. Please use `RootNode#getCallTarget()` to access the call target of a root node from now on. * In `TruffleLanguage.finalizeContext(Object)`, there is a new requirement for leaving all remaining unclosed inner contexts created by the language on all threads where the contexts are still active. No active inner context is allowed after `TruffleLanguage.finalizeContext(Object)` returns. Not complying with this requirement will result in an internal error. Please note that inactive inner contexts are still closed implicitly by the parent context. * Added `TruffleContext.closeExited(Node, int)` to hard exit an entered truffle context. See [the documentation](https://github.com/oracle/graal/blob/master/truffle/docs/Exit.md). diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java index 2da778bf60d4..43a082e483db 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java @@ -109,6 +109,7 @@ public void test() { assertNotNull(runtime.getName()); } + @SuppressWarnings("deprecation") @Test public void testCreateCallTarget() { RootNode rootNode = createTestRootNode(null); diff --git a/truffle/src/com.oracle.truffle.api/snapshot.sigtest b/truffle/src/com.oracle.truffle.api/snapshot.sigtest index 239c38dffb90..b3ff7b35106a 100644 --- a/truffle/src/com.oracle.truffle.api/snapshot.sigtest +++ b/truffle/src/com.oracle.truffle.api/snapshot.sigtest @@ -681,6 +681,7 @@ meth public abstract com.oracle.truffle.api.Assumption createAssumption() meth public abstract com.oracle.truffle.api.Assumption createAssumption(java.lang.String) meth public abstract com.oracle.truffle.api.CompilerOptions createCompilerOptions() meth public abstract com.oracle.truffle.api.RootCallTarget createCallTarget(com.oracle.truffle.api.nodes.RootNode) + anno 0 java.lang.Deprecated() meth public abstract com.oracle.truffle.api.frame.FrameInstance getCallerFrame() meth public abstract com.oracle.truffle.api.frame.FrameInstance getCurrentFrame() meth public abstract com.oracle.truffle.api.frame.MaterializedFrame createMaterializedFrame(java.lang.Object[]) diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java index 526e7f2ac618..4cdfe83c2409 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java @@ -71,15 +71,16 @@ public interface TruffleRuntime { /** * Creates a new call target for a given root node if none exists. Otherwise, the existing call - * target is returned. Note that this method is only kept for backward compatibility and will - * soon be deprecated. Please use {@link RootNode#getCallTarget()} instead. + * target is returned. * * @param rootNode the root node whose * {@link RootNode#execute(com.oracle.truffle.api.frame.VirtualFrame)} method * represents the entry point * @return the new call target object * @since 0.8 or earlier + * @deprecated Use {@link RootNode#getCallTarget()}. */ + @Deprecated RootCallTarget createCallTarget(RootNode rootNode); /** From 97c741ff571dfd9eb922ea0a0bdc64f93d9ea735 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Tue, 5 Oct 2021 15:26:15 +0200 Subject: [PATCH 291/681] Fix problems and warnings found by the ECJ compiler with JDK 11 and 17; Add gate build runs with JDT for 11 and 17. --- common.json | 8 +-- .../core/test/ea/EscapeAnalysisTest.java | 16 +++--- .../hotspot/jdk16/test/ReferenceTest.java | 8 +-- .../replacements/test/MonitorTest.java | 3 +- .../serviceprovider/GraalUnsafeAccess.java | 1 + regex/ci.hocon | 2 +- .../src/org/graalvm/polyglot/Engine.java | 3 +- .../svm/core/containers/CgroupUtil.java | 2 + ...et_java_lang_ClassLoader_JDK11OrLater.java | 8 +-- .../Target_java_util_ResourceBundle.java | 4 +- .../oracle/svm/core/jdk/RandomAccessors.java | 1 + .../svm/core/jdk/SecuritySubstitutions.java | 16 ++++-- .../oracle/svm/hosted/ModuleLayerFeature.java | 51 +++++++++---------- .../ClassLoaderSupportImplJDK11OrLater.java | 4 +- ...veImageClassLoaderSupportJDK11OrLater.java | 4 +- .../oracle/svm/jfr/JfrSymbolRepository.java | 4 +- .../src/com/oracle/svm/jfr/SubstrateJVM.java | 1 - .../svm/jfr/Target_jdk_jfr_internal_JVM.java | 11 ++-- .../test/jdk11/AbstractServiceLoaderTest.java | 5 +- ...oProviderConstructorServiceLoaderTest.java | 8 +-- .../com/oracle/svm/test/StackTraceTests.java | 1 + tools/ci.hocon | 4 +- .../chromeinspector/InspectorDebugger.java | 1 + truffle/ci.hocon | 4 +- .../staticobject/ArrayBasedStaticShape.java | 2 + .../api/staticobject/StaticProperty.java | 3 +- .../oracle/truffle/host/HostClassLoader.java | 1 + 27 files changed, 91 insertions(+), 85 deletions(-) diff --git a/common.json b/common.json index 62e6ed004261..e2d8d4b23743 100644 --- a/common.json +++ b/common.json @@ -78,12 +78,8 @@ } }, "jdt": { - "downloads": { - "JDT": { - "name": "ecj", - "version": "4.14.0", - "platformspecific": false - } + "environment": { + "JDT": "builtin" } } }, diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java index 6e9d60e35cd7..b3d40e2393fd 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java @@ -89,10 +89,10 @@ public void testMonitor() { testEscapeAnalysis("testMonitorSnippet", JavaConstant.forInt(0), false); } - @SuppressWarnings({"deprecation", "synchronization"}) + @SuppressWarnings({"synchronized", "deprecation"}) public static int testMonitorSnippet() { - Integer x = new Integer(0); - Double y = new Double(0); + Object x = new Integer(0); + Object y = new Double(0); Object z = new Object(); synchronized (x) { synchronized (y) { @@ -101,7 +101,7 @@ public static int testMonitorSnippet() { } } } - return x.intValue(); + return ((Integer) x).intValue(); } @Test @@ -113,16 +113,16 @@ public void testMonitor2() { * This test case differs from the last one in that it requires inlining within a synchronized * region. */ - @SuppressWarnings({"deprecation", "synchronization"}) + @SuppressWarnings({"synchronized", "deprecation"}) public static int testMonitor2Snippet() { - Integer x = new Integer(0); - Double y = new Double(0); + Object x = new Integer(0); + Object y = new Double(0); Object z = new Object(); synchronized (x) { synchronized (y) { synchronized (z) { notInlineable(); - return x.intValue(); + return ((Integer) x).intValue(); } } } diff --git a/compiler/src/org.graalvm.compiler.hotspot.jdk16.test/src/org/graalvm/compiler/hotspot/jdk16/test/ReferenceTest.java b/compiler/src/org.graalvm.compiler.hotspot.jdk16.test/src/org/graalvm/compiler/hotspot/jdk16/test/ReferenceTest.java index 185dfd0b8309..c3600aa4d001 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.jdk16.test/src/org/graalvm/compiler/hotspot/jdk16/test/ReferenceTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.jdk16.test/src/org/graalvm/compiler/hotspot/jdk16/test/ReferenceTest.java @@ -62,10 +62,10 @@ static boolean snippet2(PhantomReference ref, Object o) { @Test public void testPhantomReference() { Object referent = new Object(); - test("snippet2", new PhantomReference(referent, new ReferenceQueue<>()), referent); - test("snippet2", new PhantomReference(referent, new ReferenceQueue<>()), null); - test("snippet2", new PhantomReference(null, new ReferenceQueue<>()), referent); - test("snippet2", new PhantomReference(null, new ReferenceQueue<>()), null); + test("snippet2", new PhantomReference<>(referent, new ReferenceQueue<>()), referent); + test("snippet2", new PhantomReference<>(referent, new ReferenceQueue<>()), null); + test("snippet2", new PhantomReference<>(null, new ReferenceQueue<>()), referent); + test("snippet2", new PhantomReference<>(null, new ReferenceQueue<>()), null); } @Override diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MonitorTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MonitorTest.java index 0c44fa8bc3fd..8f6d0f9b28e1 100644 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MonitorTest.java +++ b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MonitorTest.java @@ -212,9 +212,8 @@ public static String copyArr(char[] src, char[] dst, int n) { return new String(dst); } - @SuppressWarnings("synchronization") public static String lockBoxedLong(long value) { - Long lock = value; + Object lock = value; synchronized (lock) { return lock.toString(); } diff --git a/compiler/src/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalUnsafeAccess.java b/compiler/src/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalUnsafeAccess.java index 349913065235..2903f78d8d32 100644 --- a/compiler/src/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalUnsafeAccess.java +++ b/compiler/src/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalUnsafeAccess.java @@ -59,6 +59,7 @@ private static Unsafe initUnsafe() { * @throws SecurityException if a security manager is present and it denies * {@link RuntimePermission}("accessUnsafe") */ + @SuppressWarnings("deprecation") // checkPermission deprecated starting with JDK 17 public static Unsafe getUnsafe() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { diff --git a/regex/ci.hocon b/regex/ci.hocon index c6c9cb80c6d0..447db3f7e593 100644 --- a/regex/ci.hocon +++ b/regex/ci.hocon @@ -18,7 +18,7 @@ regexWeekly: ${regex-weekly-notifications} { builds += [ ${linux-amd64} ${oraclejdk8} ${regexCommon} ${eclipse} ${jdt} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-regex-8"}, - ${linux-amd64} ${oraclejdk11} ${regexCommon} ${eclipse} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-regex-oraclejdk-11"}, + ${linux-amd64} ${oraclejdk11} ${regexCommon} ${eclipse} ${jdt} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-regex-oraclejdk-11"}, ${darwin-amd64} ${oraclejdk8} ${gateLite} ${regexWeekly} { name: "gate-regex-mac-lite-8" } diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java index 1f2171764020..7bab5eb0b55a 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java @@ -787,7 +787,7 @@ public String validatePolyglotAccess(PolyglotAccess access, UnmodifiableEconomic private static final boolean JDK8_OR_EARLIER = System.getProperty("java.specification.version").compareTo("1.9") < 0; - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "deprecation"}) private static AbstractPolyglotImpl initEngineImpl() { return AccessController.doPrivileged(new PrivilegedAction() { public AbstractPolyglotImpl run() { @@ -870,6 +870,7 @@ private static class PolyglotInvalid extends AbstractPolyglotImpl { static boolean AOT; static { + @SuppressWarnings("deprecation") Boolean aot = AccessController.doPrivileged(new PrivilegedAction() { public Boolean run() { return Boolean.getBoolean("com.oracle.graalvm.isaot"); diff --git a/substratevm/src/com.oracle.svm.core.containers/src/com/oracle/svm/core/containers/CgroupUtil.java b/substratevm/src/com.oracle.svm.core.containers/src/com/oracle/svm/core/containers/CgroupUtil.java index 52edc2745138..30cfe6cceefe 100644 --- a/substratevm/src/com.oracle.svm.core.containers/src/com/oracle/svm/core/containers/CgroupUtil.java +++ b/substratevm/src/com.oracle.svm.core.containers/src/com/oracle/svm/core/containers/CgroupUtil.java @@ -51,6 +51,7 @@ static void unwrapIOExceptionAndRethrow(PrivilegedActionException pae) throws IO throw (Error) x; } + @SuppressWarnings({"deprecation"}) // doPrivileged is deprecated on JDK 17 static String readStringValue(CgroupSubsystemController controller, String param) throws IOException { PrivilegedExceptionAction pea = () -> new BufferedReader(new InputStreamReader(new FileInputStream(Paths.get(controller.path(), param).toString()), StandardCharsets.UTF_8)); @@ -63,6 +64,7 @@ static String readStringValue(CgroupSubsystemController controller, String param } } + @SuppressWarnings({"deprecation"}) // doPrivileged is deprecated on JDK 17 public static List readAllLinesPrivileged(Path path) throws IOException { PrivilegedExceptionAction pea = () -> new BufferedReader(new InputStreamReader(new FileInputStream(path.toString()), StandardCharsets.UTF_8)); diff --git a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/Target_java_lang_ClassLoader_JDK11OrLater.java b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/Target_java_lang_ClassLoader_JDK11OrLater.java index 335d7feedad6..33b5b3c8cfd1 100644 --- a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/Target_java_lang_ClassLoader_JDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/Target_java_lang_ClassLoader_JDK11OrLater.java @@ -41,11 +41,10 @@ public final class Target_java_lang_ClassLoader_JDK11OrLater { /** * All ClassLoaderValue are reset at run time for now. See also - * {@link Target_jdk_internal_loader_BootLoader_JDK11OrLater#CLASS_LOADER_VALUE_MAP} for resetting of the - * boot class loader. + * {@link Target_jdk_internal_loader_BootLoader_JDK11OrLater#CLASS_LOADER_VALUE_MAP} for + * resetting of the boot class loader. */ - @Alias - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClass = ConcurrentHashMap.class)// + @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClass = ConcurrentHashMap.class)// @TargetElement(onlyWith = JDK11OrLater.class)// ConcurrentHashMap classLoaderValueMap; @@ -53,6 +52,7 @@ public final class Target_java_lang_ClassLoader_JDK11OrLater { @TargetElement(onlyWith = JDK11OrLater.class) native Stream packages(); + @SuppressWarnings("static-method") @Substitute public Target_java_lang_Module_JDK11OrLater getUnnamedModule() { return ClassLoaderUtil.unnamedModuleReference.get(); diff --git a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/substitutions/Target_java_util_ResourceBundle.java b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/substitutions/Target_java_util_ResourceBundle.java index 7c5f36d0acd3..12a6b1459b19 100644 --- a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/substitutions/Target_java_util_ResourceBundle.java +++ b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/substitutions/Target_java_util_ResourceBundle.java @@ -44,12 +44,12 @@ public final class Target_java_util_ResourceBundle { */ @Substitute - private static ResourceBundle getBundle(String baseName, Target_java_lang_Module_JDK11OrLater module) { + private static ResourceBundle getBundle(String baseName, @SuppressWarnings("unused") Target_java_lang_Module_JDK11OrLater module) { return ImageSingletons.lookup(LocalizationSupport.class).asOptimizedSupport().getCached(baseName, Locale.getDefault()); } @Substitute - private static ResourceBundle getBundle(String baseName, Locale targetLocale, Target_java_lang_Module_JDK11OrLater module) { + private static ResourceBundle getBundle(String baseName, Locale targetLocale, @SuppressWarnings("unused") Target_java_lang_Module_JDK11OrLater module) { return ImageSingletons.lookup(LocalizationSupport.class).asOptimizedSupport().getCached(baseName, targetLocale); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RandomAccessors.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RandomAccessors.java index ebec57abff8d..1c3d3fd0c49d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RandomAccessors.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RandomAccessors.java @@ -39,6 +39,7 @@ public abstract class RandomAccessors { * the SecureRandom code is only reachable and included in the image when requested by the * application. */ + @SuppressWarnings("deprecation") // deprecated starting JDK 17 at least with ECJ private static final boolean SECURE_SEED = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @Override diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java index 428371a714b9..27325d3b6f01 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java @@ -532,30 +532,33 @@ private static PermissionCollection allPermissions() { } @Override + @SuppressWarnings("deprecation") // deprecated starting JDK 17 public PermissionCollection getPermissions(CodeSource codesource) { return allPermissions(); } @Override + @SuppressWarnings("deprecation") // deprecated starting JDK 17 public PermissionCollection getPermissions(ProtectionDomain domain) { return allPermissions(); } @Override + @SuppressWarnings("deprecation") // deprecated starting JDK 17 public boolean implies(ProtectionDomain domain, Permission permission) { return true; } } /** - * This class is instantiated indirectly from the {@link Policy#getInstance} methods via the + * This class is instantiated indirectly from the {@code Policy#getInstance} methods via the * {@link java.security.Security#getProviders security provider} abstractions. We could just - * substitute the {@link Policy#getInstance} methods to return - * {@link AllPermissionsPolicy#SINGLETON}, this version is more fool-proof in case someone manually - * registers security providers for reflective instantiation. + * substitute the Policy.getInstance methods to return {@link AllPermissionsPolicy#SINGLETON}, this + * version is more fool-proof in case someone manually registers security providers for reflective + * instantiation. */ @TargetClass(className = "sun.security.provider.PolicySpiFile") -@SuppressWarnings({"unused", "static-method"}) +@SuppressWarnings({"unused", "static-method", "deprecation"}) final class Target_sun_security_provider_PolicySpiFile { @Substitute @@ -563,16 +566,19 @@ private Target_sun_security_provider_PolicySpiFile(Policy.Parameters params) { } @Substitute + @SuppressWarnings("deprecation") // deprecated starting JDK 17 private PermissionCollection engineGetPermissions(CodeSource codesource) { return AllPermissionsPolicy.SINGLETON.getPermissions(codesource); } @Substitute + @SuppressWarnings("deprecation") // deprecated starting JDK 17 private PermissionCollection engineGetPermissions(ProtectionDomain d) { return AllPermissionsPolicy.SINGLETON.getPermissions(d); } @Substitute + @SuppressWarnings("deprecation") // deprecated starting JDK 17 private boolean engineImplies(ProtectionDomain d, Permission p) { return AllPermissionsPolicy.SINGLETON.implies(d, p); } diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 187c7037b11c..15cdecb526c2 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -56,14 +56,14 @@ /** * This feature: *
    - *
  • synthesizes the runtime boot module layer
  • - *
  • ensures that fields/methods from the {@link ClassLoader} class are reachable in order to - * make native methods of the {@link Module} class work
  • + *
  • synthesizes the runtime boot module layer
  • + *
  • ensures that fields/methods from the {@link ClassLoader} class are reachable in order to make + * native methods of the {@link Module} class work
  • *
*

- * This feature synthesizes the runtime boot module layer by using type reachability information. - * If a type is reachable, its module is also reachable and therefore should be included in the - * runtime boot module layer. + * This feature synthesizes the runtime boot module layer by using type reachability information. If + * a type is reachable, its module is also reachable and therefore should be included in the runtime + * boot module layer. *

*

* The configuration for the runtime boot module layer is resolved using the module reachability @@ -73,8 +73,8 @@ * We are purposefully avoiding public API for module layer creation, such as * {@link ModuleLayer#defineModulesWithOneLoader(Configuration, ClassLoader)}, because as a side * effect this will create a new class loader. Instead, we use a private constructor to construct - * the {@link ModuleLayer} instance, which we then patch using the module reachability data - * provided to us by the analysis. + * the {@link ModuleLayer} instance, which we then patch using the module reachability data provided + * to us by the analysis. *

*

* Because the result of this feature is dependant on the analysis results, and because this feature @@ -108,8 +108,8 @@ public void afterRegistration(AfterRegistrationAccess access) { public void beforeAnalysis(BeforeAnalysisAccess access) { FeatureImpl.BeforeAnalysisAccessImpl accessImpl = (FeatureImpl.BeforeAnalysisAccessImpl) access; Map baseModules = ModuleLayer.boot().modules() - .stream() - .collect(Collectors.toMap(Module::getName, m -> m)); + .stream() + .collect(Collectors.toMap(Module::getName, m -> m)); ModuleLayer runtimeBootLayer = synthesizeRuntimeBootLayer(accessImpl.imageClassLoader, baseModules); BootModuleLayerSupport.instance().setBootLayer(runtimeBootLayer); } @@ -120,12 +120,12 @@ public void afterAnalysis(AfterAnalysisAccess access) { AnalysisUniverse universe = accessImpl.getUniverse(); Map reachableModules = universe.getTypes() - .stream() - .filter(t -> t.isReachable() && !t.isArray()) - .map(t -> t.getJavaClass().getModule()) - .distinct() - .filter(m -> m.isNamed() && !m.getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) - .collect(Collectors.toMap(Module::getName, m -> m)); + .stream() + .filter(t -> t.isReachable() && !t.isArray()) + .map(t -> t.getJavaClass().getModule()) + .distinct() + .filter(m -> m.isNamed() && !m.getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) + .collect(Collectors.toMap(Module::getName, m -> m)); ModuleLayer runtimeBootLayer = synthesizeRuntimeBootLayer(accessImpl.imageClassLoader, reachableModules); BootModuleLayerSupport.instance().setBootLayer(runtimeBootLayer); @@ -144,7 +144,7 @@ private ModuleLayer synthesizeRuntimeBootLayer(ImageClassLoader cl, Map mp, Map reachableModules) { + private static Configuration synthesizeRuntimeBootLayerConfiguration(List mp, Map reachableModules) { ModuleFinder beforeFinder = new BootModuleLayerModuleFinder(); ModuleFinder afterFinder = ModuleFinder.of(mp.toArray(Path[]::new)); Set roots = reachableModules.keySet(); @@ -164,25 +164,24 @@ private void patchRuntimeBootLayer(ModuleLayer runtimeBootLayer, Map find(String name) { return ModuleLayer.boot() - .configuration() - .findModule(name) - .map(ResolvedModule::reference); + .configuration() + .findModule(name) + .map(ResolvedModule::reference); } @Override public Set findAll() { return ModuleLayer.boot() - .configuration() - .modules() - .stream() - .map(ResolvedModule::reference) - .collect(Collectors.toSet()); + .configuration() + .modules() + .stream() + .map(ResolvedModule::reference) + .collect(Collectors.toSet()); } } } diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/ClassLoaderSupportImplJDK11OrLater.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/ClassLoaderSupportImplJDK11OrLater.java index 3a6652ac4710..df7e017c0854 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/ClassLoaderSupportImplJDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/ClassLoaderSupportImplJDK11OrLater.java @@ -107,8 +107,8 @@ private static String packageName(String bundleName) { return bundleName.substring(0, classSep); } - private void buildPackageToModulesMap(NativeImageClassLoaderSupportJDK11OrLater classLoaderSupport) { - for (ModuleLayer layer : allLayers(classLoaderSupport.moduleLayerForImageBuild)) { + private void buildPackageToModulesMap(NativeImageClassLoaderSupportJDK11OrLater cls) { + for (ModuleLayer layer : allLayers(cls.moduleLayerForImageBuild)) { for (Module module : layer.modules()) { for (String packageName : module.getDescriptor().packages()) { addToPackageNameModules(module, packageName); diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java index 8fd5e7c4f666..f9c6c0b89886 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/NativeImageClassLoaderSupportJDK11OrLater.java @@ -93,7 +93,7 @@ private static ModuleLayer createModuleLayer(Path[] modulePaths, ClassLoader par return ModuleLayer.defineModulesWithOneLoader(configuration, List.of(ModuleLayer.boot()), parent).layer(); } - private void adjustBootLayerQualifiedExports(ModuleLayer layer) { + private static void adjustBootLayerQualifiedExports(ModuleLayer layer) { /* * For all qualified exports packages of modules in the the boot layer we check if layer * contains modules that satisfy such qualified exports. If we find a match we perform a @@ -129,7 +129,7 @@ private ClassLoader getSingleClassloader(ModuleLayer moduleLayer) { return singleClassloader; } - private void implAddReadsAllUnnamed(Module module) { + private static void implAddReadsAllUnnamed(Module module) { try { Method implAddReadsAllUnnamed = Module.class.getDeclaredMethod("implAddReadsAllUnnamed"); ModuleSupport.openModuleByClass(Module.class, NativeImageClassLoaderSupportJDK11OrLater.class); diff --git a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrSymbolRepository.java b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrSymbolRepository.java index a1f82973ebc7..56ebfe597881 100644 --- a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrSymbolRepository.java +++ b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrSymbolRepository.java @@ -125,7 +125,7 @@ public int write(JfrChunkWriter writer) { return 1; } - private void writeSymbol(JfrChunkWriter writer, JfrSymbol symbol) { + private static void writeSymbol(JfrChunkWriter writer, JfrSymbol symbol) { writer.writeCompressedLong(symbol.getId()); writer.writeByte(JfrChunkWriter.StringEncoding.UTF8_BYTE_ARRAY.byteValue); byte[] value = symbol.getValue().getBytes(StandardCharsets.UTF_8); @@ -136,7 +136,7 @@ private void writeSymbol(JfrChunkWriter writer, JfrSymbol symbol) { writer.writeBytes(value); } - private void replaceDotWithSlash(byte[] utf8String) { + private static void replaceDotWithSlash(byte[] utf8String) { for (int i = 0; i < utf8String.length; i++) { if (utf8String[i] == '.') { utf8String[i] = '/'; diff --git a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/SubstrateJVM.java b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/SubstrateJVM.java index 585932ec5494..68abedd6ca90 100644 --- a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/SubstrateJVM.java +++ b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/SubstrateJVM.java @@ -403,7 +403,6 @@ public boolean shouldRotateDisk() { } } - /** See {@link JVM#getChunkStartNanos}. */ public long getChunkStartNanos() { JfrChunkWriter chunkWriter = unlockedChunkWriter.lock(); try { diff --git a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/Target_jdk_jfr_internal_JVM.java b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/Target_jdk_jfr_internal_JVM.java index 2cf9121df458..b8f25658f94f 100644 --- a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/Target_jdk_jfr_internal_JVM.java +++ b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/Target_jdk_jfr_internal_JVM.java @@ -117,7 +117,7 @@ public static long getClassId(Class clazz) { return SubstrateJVM.get().getClassId(clazz); } - /** See {@link JVM#getClassIdNonIntrinsic}. */ + /** See JVM.getClassIdNonIntrinsic(Class). */ @Substitute @TargetElement(onlyWith = JDK16OrEarlier.class) public static long getClassIdNonIntrinsic(Class clazz) { @@ -286,14 +286,13 @@ public double getTimeConversionFactor() { return 1; } - /** See {@link JVM#getChunkStartNanos}. */ + /** See {@link SubstrateJVM#getChunkStartNanos}. */ @Substitute @TargetElement(onlyWith = JDK14OrLater.class) public long getChunkStartNanos() { return SubstrateJVM.get().getChunkStartNanos(); } - /** See {@link JVM#setHandler}. */ @Substitute @TargetElement(onlyWith = JDK15OrLater.class) public boolean setHandler(Class eventClass, EventHandler handler) { @@ -302,7 +301,7 @@ public boolean setHandler(Class eventClass, throw VMError.shouldNotReachHere("eventHandler does not exist for: " + eventClass); } - /** See {@link JVM#getHandler}. */ + /** See {@link SubstrateJVM#getHandler}. */ @Substitute @TargetElement(onlyWith = JDK15OrLater.class) public Object getHandler(Class eventClass) { @@ -385,21 +384,18 @@ public void flush() { // Temporarily do nothing. This is used for JFR streaming. } - /** See {@link JVM#include}. */ @Substitute @TargetElement(onlyWith = JDK14OrLater.class) // public void include(Thread thread) { // Temporarily do nothing. This is used for JFR streaming. } - /** See {@link JVM#exclude}. */ @Substitute @TargetElement(onlyWith = JDK14OrLater.class) // public void exclude(Thread thread) { // Temporarily do nothing. This is used for JFR streaming. } - /** See {@link JVM#isExcluded}. */ @Substitute @TargetElement(onlyWith = JDK14OrLater.class) // public boolean isExcluded(Thread thread) { @@ -407,7 +403,6 @@ public boolean isExcluded(Thread thread) { return false; } - /** See {@link JVM#markChunkFinal}. */ @Substitute @TargetElement(onlyWith = JDK14OrLater.class) // public void markChunkFinal() { diff --git a/substratevm/src/com.oracle.svm.test.jdk11/src/com/oracle/svm/test/jdk11/AbstractServiceLoaderTest.java b/substratevm/src/com.oracle.svm.test.jdk11/src/com/oracle/svm/test/jdk11/AbstractServiceLoaderTest.java index a99c4a9e0b5b..ec31c327a764 100644 --- a/substratevm/src/com.oracle.svm.test.jdk11/src/com/oracle/svm/test/jdk11/AbstractServiceLoaderTest.java +++ b/substratevm/src/com.oracle.svm.test.jdk11/src/com/oracle/svm/test/jdk11/AbstractServiceLoaderTest.java @@ -27,6 +27,7 @@ import java.util.HashSet; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; +import java.util.ServiceLoader.Provider; import java.util.Set; import java.util.stream.Collectors; @@ -41,8 +42,8 @@ * Tests a corner case with respect to an abstract class being registered as a * {@linkplain ServiceLoader service}. Although abstract service class cannot be instantiated, it is * possible to get its {@link Class} because {@link ServiceLoader#stream()} does not force - * instantiation as it is a {@link java.util.stream.Stream} of {@link ServiceLoader.Provider}. This - * is in contrast to {@link ServiceLoader#iterator()}, which iterates the instances. + * instantiation as it is a {@link java.util.stream.Stream} of {@link Provider}. This is in contrast + * to {@link ServiceLoader#iterator()}, which iterates the instances. */ public class AbstractServiceLoaderTest { diff --git a/substratevm/src/com.oracle.svm.test.jdk11/src/com/oracle/svm/test/jdk11/NoProviderConstructorServiceLoaderTest.java b/substratevm/src/com.oracle.svm.test.jdk11/src/com/oracle/svm/test/jdk11/NoProviderConstructorServiceLoaderTest.java index a70d41a3772f..aa50b328cb90 100644 --- a/substratevm/src/com.oracle.svm.test.jdk11/src/com/oracle/svm/test/jdk11/NoProviderConstructorServiceLoaderTest.java +++ b/substratevm/src/com.oracle.svm.test.jdk11/src/com/oracle/svm/test/jdk11/NoProviderConstructorServiceLoaderTest.java @@ -67,7 +67,7 @@ public abstract static class NoProviderConstructorService implements ServiceInte /** * Not a provider constructor. This violates the contract of {@link ServiceLoader}. */ - NoProviderConstructorService(Class clazz) { + NoProviderConstructorService(@SuppressWarnings("unused") Class clazz) { } } @@ -75,7 +75,7 @@ public abstract static class NoProviderConstructorService implements ServiceInte /** * This should actually throw an {@link ServiceConfigurationError}. - * + * * @see #testLazyStreamHotspot() */ @Test @@ -89,7 +89,7 @@ public void testLazyStreamNativeImage() { /** * This should actually throw an {@link ServiceConfigurationError}. - * + * * @see #testEagerStreamHotspot() */ @Test @@ -103,7 +103,7 @@ public void testEagerStreamNativeImage() { /** * This should actually throw an {@link ServiceConfigurationError}. - * + * * @see #testEagerIteratorHotspot() */ @Test diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/StackTraceTests.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/StackTraceTests.java index 136806e18c10..3d7f9537ccd3 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/StackTraceTests.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/StackTraceTests.java @@ -103,6 +103,7 @@ public static void a(Type type) { static final class SecurityManagerSubclass extends SecurityManager { @Override + @SuppressWarnings({"deprecation"}) // deprecated on JDK 17 protected Class[] getClassContext() { return super.getClassContext(); } diff --git a/tools/ci.hocon b/tools/ci.hocon index 0d225190d8f9..619f10fbbde4 100644 --- a/tools/ci.hocon +++ b/tools/ci.hocon @@ -43,8 +43,8 @@ toolsWeekly: ${tools-weekly-notifications} { builds += [ ${linux-amd64} ${oraclejdk8} ${toolsCommon} ${eclipse} ${jdt} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-tools-8"}, - ${linux-amd64} ${oraclejdk11} ${toolsCommon} ${eclipse} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-tools-oraclejdk-11"}, - ${linux-amd64} ${oraclejdk17} ${toolsCommon} ${eclipse} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-tools-oraclejdk-17"}, + ${linux-amd64} ${oraclejdk11} ${toolsCommon} ${eclipse} ${jdt} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-tools-oraclejdk-11"}, + ${linux-amd64} ${oraclejdk17} ${toolsCommon} ${eclipse} ${jdt} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-tools-oraclejdk-17"}, ${linux-amd64} ${oraclejdk8} ${toolsCommon} { run : [ ["mx", "build"], diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java index e4dda5c86d07..753cc5aabea7 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java @@ -1270,6 +1270,7 @@ private static class SchedulerThreadFactory implements ThreadFactory { private final ThreadGroup group; + @SuppressWarnings("deprecation") SchedulerThreadFactory() { SecurityManager s = System.getSecurityManager(); this.group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); diff --git a/truffle/ci.hocon b/truffle/ci.hocon index a96017701ee5..04a2516f95ba 100644 --- a/truffle/ci.hocon +++ b/truffle/ci.hocon @@ -103,12 +103,12 @@ builds += [ run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-truffle-8"}, - ${linux-amd64} ${oraclejdk11} ${truffleCommon} ${eclipse} { + ${linux-amd64} ${oraclejdk11} ${truffleCommon} ${eclipse} ${jdt} { environment: {DISABLE_DSL_STATE_BITS_TESTS: "true"}, run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-truffle-oraclejdk-11"}, - ${linux-amd64} ${oraclejdk17} ${truffleCommon} ${eclipse} { + ${linux-amd64} ${oraclejdk17} ${truffleCommon} ${eclipse} ${jdt} { environment: {DISABLE_DSL_STATE_BITS_TESTS: "true"}, run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], diff --git a/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java b/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java index a240bf156881..b8f1ea821b4b 100644 --- a/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java +++ b/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/ArrayBasedStaticShape.java @@ -87,6 +87,7 @@ static ArrayBasedStaticShape create(ArrayBasedShapeGenerator generator } @Override + @SuppressWarnings("cast") Object getStorage(Object obj, boolean primitive) { Object receiverObject = cast(obj, storageClass, false); if (safetyChecks) { @@ -125,6 +126,7 @@ Object getStorage(Object obj, boolean primitive) { } } + @SuppressWarnings("cast") private boolean checkShape(Object receiverObject) { ArrayBasedStaticShape receiverShape = cast(UNSAFE.getObject(receiverObject, (long) propertyLayout.generator.getShapeOffset()), ArrayBasedStaticShape.class, false); if (this != receiverShape && (receiverShape.superShapes.length < superShapes.length || receiverShape.superShapes[superShapes.length - 1] != this)) { diff --git a/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/StaticProperty.java b/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/StaticProperty.java index 087795e032e5..a15364cdd67c 100644 --- a/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/StaticProperty.java +++ b/truffle/src/com.oracle.truffle.api.staticobject/src/com/oracle/truffle/api/staticobject/StaticProperty.java @@ -71,6 +71,7 @@ * @see StaticShape.Builder#property(StaticProperty, Class, boolean). * @since 21.3.0 */ +@SuppressWarnings("cast") // make ecj happy public abstract class StaticProperty { private static final Unsafe UNSAFE = getUnsafe(); private static final byte STORE_AS_FINAL = (byte) (1 << 7); @@ -84,7 +85,7 @@ public abstract class StaticProperty { /** * Constructor for subclasses. - * + * * @since 21.3.0 */ protected StaticProperty() { diff --git a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassLoader.java b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassLoader.java index d6f5a7565cac..390e7c4f93cb 100644 --- a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassLoader.java +++ b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassLoader.java @@ -93,6 +93,7 @@ final class HostClassLoader extends ClassLoader implements Closeable { } @Override + @SuppressWarnings("deprecation") // security.checkPermission deprecated on JDK 17. public void close() throws IOException { SecurityManager security = System.getSecurityManager(); if (security != null) { From a77506678d9d40c50f29176dc7116d974d8fe980 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 30 Sep 2021 13:04:26 +0200 Subject: [PATCH 292/681] Use FASTR_CC env var. --- vm/ci_common/common.hocon | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vm/ci_common/common.hocon b/vm/ci_common/common.hocon index 42cfe66a25ff..9c3f9b8f76a0 100644 --- a/vm/ci_common/common.hocon +++ b/vm/ci_common/common.hocon @@ -128,6 +128,7 @@ fastr_linux: ${fastr} { PKG_INCLUDE_FLAGS_OVERRIDE : "-I/cm/shared/apps/zlib/1.2.11/include -I/cm/shared/apps/bzip2/1.0.6/include -I/cm/shared/apps/xz/5.2.2/include -I/cm/shared/apps/pcre2/10.37/include -I/cm/shared/apps/curl/7.50.1/include" PKG_LDFLAGS_OVERRIDE : "-L/cm/shared/apps/zlib/1.2.11/lib -L/cm/shared/apps/bzip2/1.0.6/lib -L/cm/shared/apps/xz/5.2.2/lib -L/cm/shared/apps/pcre2/10.37/lib -L/cm/shared/apps/curl/7.50.1/lib -L/cm/shared/apps/gcc/4.8.5/lib64" FASTR_FC: "/cm/shared/apps/gcc/4.8.5/bin/gfortran" + FASTR_CC: "/cm/shared/apps/gcc/4.8.5/bin/gcc" GNUR_HOME_BINARY: "/cm/shared/apps/gnur/4.0.3-gcc4.8.5-pcre2/lib64/R" } downloads: { @@ -142,6 +143,7 @@ fastr_darwin: ${fastr} { environment: { PATH : "/usr/local/bin:$JAVA_HOME/bin:$PATH" FASTR_FC: "/cm/shared/apps/gcc/8.3.0/bin/gfortran" + FASTR_CC: "/cm/shared/apps/gcc/8.3.0/bin/gcc" TZDIR: "/usr/share/zoneinfo" FASTR_LIBZ_VER: "1.2.11" PKG_INCLUDE_FLAGS_OVERRIDE : "-I/cm/shared/apps/pcre2/pcre2-10.37/include -I/cm/shared/apps/bzip2/1.0.6/include -I/cm/shared/apps/xz/5.2.2/include -I/cm/shared/apps/curl/7.50.1/include" From b607d8d835a1fb7204598cbd76bc18a98f9bd2ff Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Tue, 5 Oct 2021 15:56:18 +0200 Subject: [PATCH 293/681] Add long, double tests to MulNegateTest. --- .../compiler/core/test/MulNegateTest.java | 53 +++++++++++++++---- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java index d6bcfeedbf02..90d68978af95 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MulNegateTest.java @@ -29,7 +29,7 @@ public class MulNegateTest extends GraalCompilerTest { - public static final int[] INT_TEST_CASES = {0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE}; + public static final int[] INT_TEST_VALUES = {0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE}; public static int mulInt(int x, int y) { return -x * -y; @@ -39,27 +39,62 @@ public static int mulInt(int x, int y) { public void testInt() { assertTrue(getFinalGraph("mulInt").getNodes().filter(NegateNode.class).count() == 0); - for (int i : INT_TEST_CASES) { - for (int j : INT_TEST_CASES) { + for (int i : INT_TEST_VALUES) { + for (int j : INT_TEST_VALUES) { test("mulInt", i, j); } } } - public static final float[] FLOAT_TEST_CASES = {0.0f, -0.0f, 1.0f, -1.0f, Float.MIN_VALUE, Float.MIN_NORMAL, + public static final long[] LONG_TEST_VALUES = {0L, 1L, -1L, Long.MIN_VALUE, Long.MAX_VALUE}; + + public static long mulLong(long x, long y) { + return -x * -y; + } + + @Test + public void testLong() { + assertTrue(getFinalGraph("mulLong").getNodes().filter(NegateNode.class).count() == 0); + + for (long i : LONG_TEST_VALUES) { + for (long j : LONG_TEST_VALUES) { + test("mulLong", i, j); + } + } + } + + public static final float[] FLOAT_TEST_VALUES = {0.0f, -0.0f, 1.0f, -1.0f, Float.MIN_VALUE, Float.MIN_NORMAL, Float.MAX_VALUE, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Float.NaN}; - public static float mulFlt(float x, float y) { + public static float mulFloat(float x, float y) { return -x * -y; } @Test public void testFloat() { - assertTrue(getFinalGraph("mulFlt").getNodes().filter(NegateNode.class).count() == 0); + assertTrue(getFinalGraph("mulFloat").getNodes().filter(NegateNode.class).count() == 0); + + for (float i : FLOAT_TEST_VALUES) { + for (float j : FLOAT_TEST_VALUES) { + test("mulFloat", i, j); + } + } + } + + public static final double[] DOUBLE_TEST_VALUES = {0.0d, -0.0d, 1.0d, -1.0d, Double.MIN_VALUE, Double.MIN_NORMAL, + Double.MAX_VALUE, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NaN}; + + public static double mulDouble(double x, double y) { + return -x * -y; + } + + @Test + public void testDouble() { + assertTrue(getFinalGraph("mulDouble").getNodes().filter(NegateNode.class).count() == 0); - for (float i : FLOAT_TEST_CASES) { - for (float j : FLOAT_TEST_CASES) { - test("mulFlt", i, j); + for (double i : DOUBLE_TEST_VALUES) { + for (double j : DOUBLE_TEST_VALUES) { + test("mulDouble", i, j); } } } From 50e68742073d2f579a6e673900344479f1109311 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Tue, 5 Oct 2021 17:54:58 +0200 Subject: [PATCH 294/681] [GR-34181] Fixed review comments. --- .../src/org/graalvm/polyglot/Engine.java | 66 +++---- .../src/org/graalvm/polyglot/Source.java | 26 +-- .../polyglot/impl/AbstractPolyglotImpl.java | 37 ++-- .../test/wrapper/HostPolyglotDispatch.java | 40 +++- .../truffle/polyglot/EngineAccessor.java | 2 +- .../oracle/truffle/polyglot/FileSystems.java | 2 +- .../oracle/truffle/polyglot/PolyglotImpl.java | 136 ++++++++++++- .../polyglot/PolyglotSourceFactory.java | 184 ------------------ 8 files changed, 215 insertions(+), 278 deletions(-) delete mode 100644 truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceFactory.java diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java index e9d2ec661849..3967fbee45f0 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java @@ -879,8 +879,6 @@ static Iterator createInvalidPolyglotImpl() { private static class PolyglotInvalid extends AbstractPolyglotImpl { - private final EmptySourceFactory sourceFactory = new EmptySourceFactory(this); - /** * Forces ahead-of-time initialization. * @@ -938,11 +936,6 @@ private static RuntimeException noPolyglotImplementationFound() { return new IllegalStateException("No language and polyglot implementation was found on the classpath. " + suggestion); } - @Override - public AbstractSourceFactory getSourceFactory() { - return sourceFactory; - } - @Override public Class loadLanguageClass(String className) { return null; @@ -971,47 +964,40 @@ public FileSystem newDefaultFileSystem() { throw noPolyglotImplementationFound(); } - static class EmptySourceFactory extends AbstractSourceFactory { - - EmptySourceFactory(AbstractPolyglotImpl polyglot) { - super(polyglot); - } - - @Override - public Source build(String language, Object origin, URI uri, String name, String mimeType, Object content, boolean interactive, boolean internal, boolean cached, Charset encoding) - throws IOException { - throw noPolyglotImplementationFound(); - } + @Override + public Object newTargetTypeMapping(Class sourceType, Class targetType, Predicate acceptsValue, Function convertValue, TargetMappingPrecedence precedence) { + return new Object(); + } - @Override - public String findLanguage(File file) throws IOException { - return null; - } + @Override + public Source build(String language, Object origin, URI uri, String name, String mimeType, Object content, boolean interactive, boolean internal, boolean cached, Charset encoding) + throws IOException { + throw noPolyglotImplementationFound(); + } - @Override - public String findLanguage(URL url) throws IOException { - return null; - } + @Override + public String findLanguage(File file) throws IOException { + return null; + } - @Override - public String findMimeType(File file) throws IOException { - return null; - } + @Override + public String findLanguage(URL url) throws IOException { + return null; + } - @Override - public String findMimeType(URL url) throws IOException { - return null; - } + @Override + public String findMimeType(File file) throws IOException { + return null; + } - @Override - public String findLanguage(String mimeType) { - return null; - } + @Override + public String findMimeType(URL url) throws IOException { + return null; } @Override - public Object newTargetTypeMapping(Class sourceType, Class targetType, Predicate acceptsValue, Function convertValue, TargetMappingPrecedence precedence) { - return new Object(); + public String findLanguage(String mimeType) { + return null; } } diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Source.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Source.java index 190e9783c3d8..62ffc5c43039 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Source.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Source.java @@ -51,8 +51,8 @@ import java.nio.charset.Charset; import java.util.Objects; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl; import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceDispatch; -import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceFactory; import org.graalvm.polyglot.io.ByteSequence; /** @@ -131,17 +131,17 @@ */ public final class Source { - private static volatile AbstractSourceFactory FACTORY; + private static volatile AbstractPolyglotImpl IMPL; - static AbstractSourceFactory getFactory() { - if (FACTORY == null) { + static AbstractPolyglotImpl getImpl() { + if (IMPL == null) { synchronized (Engine.class) { - if (FACTORY == null) { - FACTORY = Engine.getImpl().getSourceFactory(); + if (IMPL == null) { + IMPL = Engine.getImpl(); } } } - return FACTORY; + return IMPL; } final AbstractSourceDispatch dispatch; @@ -593,7 +593,7 @@ public static Source create(String language, CharSequence source) { * @since 19.0 */ public static String findLanguage(File file) throws IOException { - return getFactory().findLanguage(file); + return getImpl().findLanguage(file); } /** @@ -614,7 +614,7 @@ public static String findLanguage(File file) throws IOException { * @since 19.0 */ public static String findLanguage(URL url) throws IOException { - return getFactory().findLanguage(url); + return getImpl().findLanguage(url); } /** @@ -627,7 +627,7 @@ public static String findLanguage(URL url) throws IOException { * @since 19.0 */ public static String findMimeType(File file) throws IOException { - return getFactory().findMimeType(file); + return getImpl().findMimeType(file); } /** @@ -642,7 +642,7 @@ public static String findMimeType(File file) throws IOException { * @since 19.0 */ public static String findMimeType(URL url) throws IOException { - return getFactory().findMimeType(url); + return getImpl().findMimeType(url); } /** @@ -654,7 +654,7 @@ public static String findMimeType(URL url) throws IOException { * @since 19.0 */ public static String findLanguage(String mimeType) { - return getFactory().findLanguage(mimeType); + return getImpl().findLanguage(mimeType); } @SuppressWarnings({"unchecked", "unused"}) @@ -917,7 +917,7 @@ public Builder encoding(Charset encoding) { * @since 19.0 */ public Source build() throws IOException { - Source source = getFactory().build(language, origin, uri, name, mimeType, content, interactive, internal, cached, fileEncoding); + Source source = getImpl().build(language, origin, uri, name, mimeType, content, interactive, internal, cached, fileEncoding); // make sure origin is not consumed again if builder is used twice if (source.hasBytes()) { diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java index e6c1adc78a0c..3da7f585210f 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java @@ -302,7 +302,18 @@ public abstract Engine buildEngine(OutputStream out, OutputStream err, InputStre public abstract void resetPreInitializedEngine(); - public abstract AbstractSourceFactory getSourceFactory(); + public abstract Source build(String language, Object origin, URI uri, String name, String mimeType, Object content, boolean interactive, boolean internal, boolean cached, Charset encoding) + throws IOException; + + public abstract String findLanguage(File file) throws IOException; + + public abstract String findLanguage(URL url) throws IOException; + + public abstract String findLanguage(String mimeType); + + public abstract String findMimeType(File file) throws IOException; + + public abstract String findMimeType(URL url) throws IOException; /** * Returns the default host dispatch of this polyglot abstraction. @@ -342,30 +353,6 @@ public final AbstractPolyglotImpl getPolyglotImpl() { } - public abstract static class AbstractSourceFactory { - - protected final AbstractPolyglotImpl engineImpl; - - protected AbstractSourceFactory(AbstractPolyglotImpl engineImpl) { - Objects.requireNonNull(engineImpl); - this.engineImpl = engineImpl; - } - - public abstract Source build(String language, Object origin, URI uri, String name, String mimeType, Object content, boolean interactive, boolean internal, boolean cached, Charset encoding) - throws IOException; - - public abstract String findLanguage(File file) throws IOException; - - public abstract String findLanguage(URL url) throws IOException; - - public abstract String findLanguage(String mimeType); - - public abstract String findMimeType(File file) throws IOException; - - public abstract String findMimeType(URL url) throws IOException; - - } - public abstract static class AbstractSourceDispatch { protected final AbstractPolyglotImpl engineImpl; diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java index e60efa30cc1e..5eda0ac9a828 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/wrapper/HostPolyglotDispatch.java @@ -40,8 +40,13 @@ */ package com.oracle.truffle.api.test.wrapper; +import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URI; +import java.net.URL; +import java.nio.charset.Charset; import java.util.Collection; import java.util.Map; import java.util.function.Consumer; @@ -109,11 +114,6 @@ public void resetPreInitializedEngine() { getNext().resetPreInitializedEngine(); } - @Override - public AbstractSourceFactory getSourceFactory() { - return getNext().getSourceFactory(); - } - @Override public Class loadLanguageClass(String className) { return getNext().loadLanguageClass(className); @@ -158,4 +158,34 @@ public int getPriority() { return Integer.MAX_VALUE; } + @Override + public Source build(String language, Object origin, URI uri, String name, String mimeType, Object content, boolean interactive, boolean internal, boolean cached, Charset encoding) + throws IOException { + return getNext().build(language, origin, uri, name, mimeType, content, interactive, internal, cached, encoding); + } + + @Override + public String findLanguage(File file) throws IOException { + return getNext().findLanguage(file); + } + + @Override + public String findLanguage(URL url) throws IOException { + return getNext().findLanguage(url); + } + + @Override + public String findMimeType(File file) throws IOException { + return getNext().findMimeType(file); + } + + @Override + public String findMimeType(URL url) throws IOException { + return getNext().findMimeType(url); + } + + @Override + public String findLanguage(String mimeType) { + return getNext().findLanguage(mimeType); + } } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java index 19a8c0fd24d7..f5ec7e834134 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java @@ -115,12 +115,12 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.polyglot.PolyglotImpl.EmbedderFileSystemContext; import com.oracle.truffle.polyglot.PolyglotImpl.VMObject; import com.oracle.truffle.polyglot.PolyglotLocals.InstrumentContextLocal; import com.oracle.truffle.polyglot.PolyglotLocals.InstrumentContextThreadLocal; import com.oracle.truffle.polyglot.PolyglotLocals.LanguageContextLocal; import com.oracle.truffle.polyglot.PolyglotLocals.LanguageContextThreadLocal; -import com.oracle.truffle.polyglot.PolyglotSourceFactory.EmbedderFileSystemContext; import com.oracle.truffle.polyglot.PolyglotThread.ThreadSpawnRootNode; final class EngineAccessor extends Accessor { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/FileSystems.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/FileSystems.java index 6b6165e384ce..000886d5d8c4 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/FileSystems.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/FileSystems.java @@ -74,7 +74,7 @@ import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.nodes.LanguageInfo; -import com.oracle.truffle.polyglot.PolyglotSourceFactory.EmbedderFileSystemContext; +import com.oracle.truffle.polyglot.PolyglotImpl.EmbedderFileSystemContext; import java.nio.charset.Charset; import org.graalvm.nativeimage.ImageInfo; diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java index b127e39e8e5e..9d9fae7dc235 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotImpl.java @@ -40,14 +40,22 @@ */ package com.oracle.truffle.polyglot; +import static com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere; import static com.oracle.truffle.polyglot.EngineAccessor.INSTRUMENT; +import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.Reader; import java.lang.reflect.Method; +import java.net.URI; +import java.net.URL; +import java.nio.charset.Charset; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Function; @@ -55,6 +63,7 @@ import java.util.function.Supplier; import java.util.logging.Handler; +import com.oracle.truffle.api.TruffleFile; import org.graalvm.options.OptionDescriptors; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Engine; @@ -63,6 +72,7 @@ import org.graalvm.polyglot.ResourceLimitEvent; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.impl.AbstractPolyglotImpl; +import org.graalvm.polyglot.io.ByteSequence; import org.graalvm.polyglot.io.FileSystem; import org.graalvm.polyglot.io.MessageTransport; import org.graalvm.polyglot.proxy.Proxy; @@ -88,7 +98,6 @@ public final class PolyglotImpl extends AbstractPolyglotImpl { static final String OPTION_GROUP_ENGINE = "engine"; static final String PROP_ALLOW_EXPERIMENTAL_OPTIONS = OptionValuesImpl.SYSTEM_PROPERTY_PREFIX + OPTION_GROUP_ENGINE + ".AllowExperimentalOptions"; - private final PolyglotSourceFactory sourceFactory = new PolyglotSourceFactory(this); private final PolyglotSourceDispatch sourceDispatch = new PolyglotSourceDispatch(this); private final PolyglotSourceSectionDispatch sourceSectionDispatch = new PolyglotSourceSectionDispatch(this); private final PolyglotManagementDispatch executionListenerDispatch = new PolyglotManagementDispatch(this); @@ -103,6 +112,7 @@ public final class PolyglotImpl extends AbstractPolyglotImpl { private final Map, PolyglotValueDispatch> primitiveValues = new HashMap<>(); Value hostNull; // effectively final private PolyglotValueDispatch disconnectedHostValue; + private volatile Object defaultFileSystemContext; private static volatile PolyglotImpl polyglotImpl; @@ -160,14 +170,6 @@ public Object buildLimits(long statementLimit, Predicate cachedLanguages = LanguageCache.languages(); + final Supplier>> fileTypeDetectors = FileSystems.newFileTypeDetectorsSupplier(cachedLanguages.values()); + + } + static org.graalvm.polyglot.Source getOrCreatePolyglotSource(PolyglotImpl polyglot, Source source) { return EngineAccessor.SOURCE.getOrCreatePolyglotSource(source, (t) -> polyglot.getAPIAccess().newSource(polyglot.sourceDispatch, t)); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceFactory.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceFactory.java deleted file mode 100644 index 7b82b19d760e..000000000000 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotSourceFactory.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * The Universal Permissive License (UPL), Version 1.0 - * - * Subject to the condition set forth below, permission is hereby granted to any - * person obtaining a copy of this software, associated documentation and/or - * data (collectively the "Software"), free of charge and under any and all - * copyright rights in the Software, and any and all patent rights owned or - * freely licensable by each licensor hereunder covering either (i) the - * unmodified Software as contributed to or provided by such licensor, or (ii) - * the Larger Works (as defined below), to deal in both - * - * (a) the Software, and - * - * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if - * one is included with the Software each a "Larger Work" to which the Software - * is contributed by such licensors), - * - * without restriction, including without limitation the rights to copy, create - * derivative works of, display, perform, and distribute the Software and make, - * use, sell, offer for sale, import, export, have made, and have sold the - * Software and the Larger Work(s), and to sublicense the foregoing rights on - * either these or other terms. - * - * This license is subject to the following condition: - * - * The above copyright notice and either this complete permission notice or at a - * minimum a reference to the UPL must be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.oracle.truffle.polyglot; - -import com.oracle.truffle.api.TruffleFile; -import org.graalvm.polyglot.Source; -import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractSourceFactory; -import org.graalvm.polyglot.io.ByteSequence; -import org.graalvm.polyglot.io.FileSystem; - -import java.io.File; -import java.io.IOException; -import java.io.Reader; -import java.net.URI; -import java.net.URL; -import java.nio.charset.Charset; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.function.Supplier; - -import static com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere; - -final class PolyglotSourceFactory extends AbstractSourceFactory { - - private volatile Object defaultFileSystemContext; - - PolyglotSourceFactory(PolyglotImpl polyglot) { - super(polyglot); - } - - @Override - public String findLanguage(File file) throws IOException { - Objects.requireNonNull(file); - String mimeType = findMimeType(file); - if (mimeType != null) { - return findLanguage(mimeType); - } else { - return null; - } - } - - @Override - public String findLanguage(URL url) throws IOException { - String mimeType = findMimeType(url); - if (mimeType != null) { - return findLanguage(mimeType); - } else { - return null; - } - } - - @Override - public String findMimeType(File file) throws IOException { - Objects.requireNonNull(file); - TruffleFile truffleFile = EngineAccessor.LANGUAGE.getTruffleFile(file.toPath().toString(), getDefaultFileSystemContext()); - return truffleFile.detectMimeType(); - } - - @Override - public String findMimeType(URL url) throws IOException { - Objects.requireNonNull(url); - return EngineAccessor.SOURCE.findMimeType(url, getDefaultFileSystemContext()); - } - - @Override - public String findLanguage(String mimeType) { - Objects.requireNonNull(mimeType); - LanguageCache cache = LanguageCache.languageMimes().get(mimeType); - if (cache != null) { - return cache.getId(); - } - return null; - } - - @Override - public Source build(String language, Object origin, URI uri, String name, String mimeType, Object content, boolean interactive, boolean internal, boolean cached, Charset encoding) - throws IOException { - assert language != null; - com.oracle.truffle.api.source.Source.SourceBuilder builder; - if (origin instanceof File) { - builder = EngineAccessor.SOURCE.newBuilder(language, (File) origin); - } else if (origin instanceof CharSequence) { - builder = com.oracle.truffle.api.source.Source.newBuilder(language, ((CharSequence) origin), name); - } else if (origin instanceof ByteSequence) { - builder = com.oracle.truffle.api.source.Source.newBuilder(language, ((ByteSequence) origin), name); - } else if (origin instanceof Reader) { - builder = com.oracle.truffle.api.source.Source.newBuilder(language, (Reader) origin, name); - } else if (origin instanceof URL) { - builder = com.oracle.truffle.api.source.Source.newBuilder(language, (URL) origin); - } else { - throw shouldNotReachHere(); - } - - if (origin instanceof File || origin instanceof URL) { - EngineAccessor.SOURCE.setFileSystemContext(builder, getDefaultFileSystemContext()); - } - - if (content instanceof CharSequence) { - builder.content((CharSequence) content); - } else if (content instanceof ByteSequence) { - builder.content((ByteSequence) content); - } - - builder.uri(uri); - builder.name(name); - builder.internal(internal); - builder.interactive(interactive); - builder.mimeType(mimeType); - builder.cached(cached); - builder.encoding(encoding); - - try { - return PolyglotImpl.getOrCreatePolyglotSource((PolyglotImpl) engineImpl, builder.build()); - } catch (IOException e) { - throw e; - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw shouldNotReachHere(e); - } - } - - private Object getDefaultFileSystemContext() { - Object res = defaultFileSystemContext; - if (res == null) { - synchronized (this) { - res = defaultFileSystemContext; - if (res == null) { - EmbedderFileSystemContext context = new EmbedderFileSystemContext(); - res = EngineAccessor.LANGUAGE.createFileSystemContext(context, context.fileSystem); - defaultFileSystemContext = res; - } - } - } - return res; - } - - static final class EmbedderFileSystemContext { - - final FileSystem fileSystem = FileSystems.newDefaultFileSystem(); - final Map cachedLanguages = LanguageCache.languages(); - final Supplier>> fileTypeDetectors = FileSystems.newFileTypeDetectorsSupplier(cachedLanguages.values()); - - } -} From 9c1be73f7f9e5b1c6570341332c7c5aaf05631ec Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 5 Oct 2021 12:49:28 +0100 Subject: [PATCH 295/681] Color samples with no self hits grey in compilation coloring. --- .../truffle/tools/profiler/impl/resources/color_change.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js index 97263e6a4cbf..5dfd541ca718 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js @@ -56,6 +56,10 @@ function color_for_name(language_index, name) { } function color_for_compilation(interpreted, compiled) { + if (interpreted + compiled == 0) { + let gray = 192.0 + return "rgb(" + gray.toFixed() + ", " + gray.toFixed() + ", " + gray.toFixed() + ")"; + } let total = compiled + interpreted; let h = total == 0 ? 0.0 : (2.0 / 3.0) * (interpreted / total); let h6 = h * 6; From cc8a112479b53e998ec515c9fa079ad7a7d9f0a2 Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 5 Oct 2021 12:49:51 +0100 Subject: [PATCH 296/681] Recalculate compilation coloring when collapsed state changes. --- .../truffle/tools/profiler/impl/resources/flamegraph.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index 948ca1d98831..ac5a94beeddd 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -116,6 +116,7 @@ function fg_toggle_collapse() { } else { zoom(fg_element_for_sample(sample_to_zoom_to)); } + fg_update_color(color_type) } function fg_x_for_sample(sample) { @@ -417,7 +418,7 @@ function fg_reset_search() { } function fg_update_color(color_type) { - let iter = sample_and_children_depth_first(profileData[0]); + let iter = fg_sample_and_children_depth_first(profileData[0]); let c = iter.next(); while (!c.done) { let sample = c.value; @@ -440,7 +441,11 @@ function fg_color_for_sample(color_type, sample) { } else if (color_type == "bl") { return color_for_name(sample.l, name_for_sample(sample)); } else if (color_type = "bc") { - return color_for_compilation(sample.i, sample.c); + if (fg_collapsed) { + return color_for_compilation(sample.ri, sample.rc); + } else { + return color_for_compilation(sample.i, sample.c); + } } } From 6e883d5244848c61ce7db91d5ee8c601e60d936b Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 5 Oct 2021 12:54:32 +0100 Subject: [PATCH 297/681] Add no samples compilation color to legend. --- .../truffle/tools/profiler/impl/resources/color_change.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js index 5dfd541ca718..7b5ddbbcc8b6 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js @@ -166,14 +166,15 @@ function color_create_legend() { } } } else if (color_type == "bc") { + color_legend_entry(e, 0, color_for_compilation(0, 0), "No self samples"); for (let i = 0; i <= 10; i++) { let color = color_for_compilation(10 - i, i); let text = (i * 10) + "% samples were compiled."; - color_legend_entry(e, i, color, text); + color_legend_entry(e, i + 1, color, text); } - entry_count = 11; + entry_count = 12; } r.height.baseVal.value = (fg_frameheight * 2.5) + (entry_count + 1) * fg_frameheight * 1.5; From 028cf056a02d88fbe3a5f510c9b2f2ce9d57616b Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 5 Oct 2021 13:09:23 +0100 Subject: [PATCH 298/681] Fix compilation coloring of histogram when recursive calls collapsed. --- .../tools/profiler/impl/resources/histogram.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js index 206d980a3285..123191d70c87 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js @@ -70,7 +70,7 @@ function h_reset_search() { if (e != null) { let color = bar.currentColor; if (color == undefined) { - color = fg_color_for_sample(color_type, bar); + color = h_color_for_sample(color_type, bar); } let r = e.children[1]; r.style.fill = color; @@ -126,7 +126,7 @@ function h_create_element_for_id(id, bar, width) { r.width.baseVal.value = width; r.height.baseVal.value = fg_frameheight - r.style.fill = fg_color_for_sample(color_type, bar); + r.style.fill = h_color_for_sample(color_type, bar); r.rx.baseVal.value = 2; r.ry.baseVal.vlaue = 2; @@ -168,7 +168,7 @@ function h_update_bar(id, bar) { (100 * (bar.c + bar.i) / (fg_xmax - fg_xmin)).toFixed(2) + "% of displayed samples.\n"; r.width.baseVal.value = width; - r.style.fill = fg_color_for_sample(color_type, bar); + r.style.fill = h_color_for_sample(color_type, bar); t.textContent = name; let t_width = t.textLength.baseVal.value; if (t_width < width - 6) { @@ -267,7 +267,7 @@ function calculate_histogram_bars(bars, sample) { function h_update_color(color_type) { for (let i = 0; i < histogramData.length; i++) { let bar = histogramData[i]; - let color = fg_color_for_sample(color_type, bar); + let color = h_color_for_sample(color_type, bar); bar.currentColor = color; if (bar.searchMatch != true) { let e = h_element_for_id(i); @@ -279,6 +279,16 @@ function h_update_color(color_type) { } } +function h_color_for_sample(color_type, sample) { + if (color_type == "fg") { + return color_for_name(0, name_for_sample(sample)); + } else if (color_type == "bl") { + return color_for_name(sample.l, name_for_sample(sample)); + } else if (color_type = "bc") { + return color_for_compilation(sample.i, sample.c); + } +} + function h_resize(new_width) { h_width = new_width let h_svg = histogram.parentElement; From 9e43e05f2d24f0638f74f4e171c783cf7786e6ec Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 5 Oct 2021 19:01:49 +0200 Subject: [PATCH 299/681] Cache leafTypeAssumption in the specialization of ConstantClass node --- .../truffle/espresso/nodes/bytecodes/InstanceOf.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InstanceOf.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InstanceOf.java index f6aaa7710323..7cda041fff6f 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InstanceOf.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InstanceOf.java @@ -30,6 +30,7 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.espresso.analysis.hierarchy.LeafTypeAssumption; import com.oracle.truffle.espresso.impl.ArrayKlass; import com.oracle.truffle.espresso.impl.Klass; import com.oracle.truffle.espresso.impl.ObjectKlass; @@ -222,11 +223,13 @@ boolean doFallback(Klass maybeSubtype) { abstract static class ConstantClass extends InstanceOf { private final ObjectKlass superType; - protected final Assumption superTypeIsLeaf; ConstantClass(ObjectKlass superType) { this.superType = superType; - this.superTypeIsLeaf = EspressoContext.get(this).getClassHierarchyOracle().isLeafClass(this.superType).getAssumption(); + } + + protected LeafTypeAssumption getLeafAssumption() { + return EspressoContext.get(this).getClassHierarchyOracle().isLeafClass(superType); } /** @@ -234,11 +237,12 @@ abstract static class ConstantClass extends InstanceOf { * {@code superType} iff it is equal to {@code superType}. */ @Specialization(assumptions = "superTypeIsLeaf") - public boolean doLeaf(ObjectKlass maybeSubtype) { + public boolean doLeaf(ObjectKlass maybeSubtype, + @SuppressWarnings("unused") @Cached("getLeafAssumption().getAssumption()") Assumption superTypeIsLeaf) { return superType == maybeSubtype; } - @Specialization(guards = "!superTypeIsLeaf.isValid()") + @Specialization(replaces = "doLeaf") public boolean doObjectKlass(ObjectKlass maybeSubtype) { return superType == maybeSubtype || superType.checkOrdinaryClassSubclassing(maybeSubtype); } From 61fb26b1851b6907190a65b56eb212bd93731769 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 5 Oct 2021 19:05:05 +0200 Subject: [PATCH 300/681] Rename EnableCHA commandline option to CHA --- .../src/com/oracle/truffle/espresso/EspressoOptions.java | 2 +- .../com/oracle/truffle/espresso/runtime/EspressoContext.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java index 65b72e205d82..a3569aa7cd9d 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java @@ -238,7 +238,7 @@ public VerifyMode apply(String s) { @Option(help = "Enable Class Hierarchy Analysis, which optimizes instanceof checks and virtual method calls by keeping track of descendants of a given class or interface.", // category = OptionCategory.EXPERT, stability = OptionStability.EXPERIMENTAL) // - public static final OptionKey EnableCHA = new OptionKey<>(false); + public static final OptionKey CHA = new OptionKey<>(false); private static final OptionType JDWP_OPTIONS_OPTION_TYPE = new OptionType<>("JDWPOptions", new Function() { diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java index 8de0949cdec3..3969bb1088c7 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java @@ -274,7 +274,7 @@ public EspressoContext(TruffleLanguage.Env env, EspressoLanguage language) { this.EnableSignals = env.getOptions().get(EspressoOptions.EnableSignals); this.SpecCompliancyMode = env.getOptions().get(EspressoOptions.SpecCompliancy); this.livenessAnalysis = env.getOptions().get(EspressoOptions.LivenessAnalysis); - this.EnableClassHierarchyAnalysis = env.getOptions().get(EspressoOptions.EnableCHA); + this.EnableClassHierarchyAnalysis = env.getOptions().get(EspressoOptions.CHA); this.EnableManagement = env.getOptions().get(EspressoOptions.EnableManagement); this.EnableAgents = getEnv().getOptions().get(EspressoOptions.EnableAgents); this.TrivialMethodSize = getEnv().getOptions().get(EspressoOptions.TrivialMethodSize); From 0472878e1967e0e07ea43b60990af688aad5b695 Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Tue, 5 Oct 2021 18:24:25 +0100 Subject: [PATCH 301/681] Store colour data based on keys rather than name strings. --- .../oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java | 2 +- .../truffle/tools/profiler/impl/resources/color_change.js | 4 ++-- .../truffle/tools/profiler/impl/resources/flamegraph.js | 4 ++-- .../truffle/tools/profiler/impl/resources/graphowner.js | 4 ++++ .../oracle/truffle/tools/profiler/impl/resources/histogram.js | 4 ++-- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index f1b297e4e730..9e6252a6b552 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -545,7 +545,7 @@ private String samples() { if (colorsForNames.containsKey(cm)) { JSONObject map = new JSONObject(); for (Map.Entry e : colorsForNames.get(cm).entrySet()) { - map.put(e.getKey(), e.getValue()); + map.put(nameHash.get(e.getKey()).toString(), e.getValue()); } colors.put(map); } else { diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js index 7b5ddbbcc8b6..11adcc846671 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js @@ -51,8 +51,8 @@ function update_color(color_type) { h_update_color(color_type); } -function color_for_name(language_index, name) { - return colorData[language_index][name]; +function color_for_key(language_index, key) { + return colorData[language_index][key]; } function color_for_compilation(interpreted, compiled) { diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index ac5a94beeddd..ee2a2647e14d 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -437,9 +437,9 @@ function fg_update_color(color_type) { function fg_color_for_sample(color_type, sample) { if (color_type == "fg") { - return color_for_name(0, name_for_sample(sample)); + return color_for_key(0, key_for_sample(sample)); } else if (color_type == "bl") { - return color_for_name(sample.l, name_for_sample(sample)); + return color_for_key(sample.l, key_for_sample(sample)); } else if (color_type = "bc") { if (fg_collapsed) { return color_for_compilation(sample.ri, sample.rc); diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index 9b7535609933..f9389854b638 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -258,6 +258,10 @@ function title(e) { } } +function key_for_sample(sample) { + return sample.n; +} + function name_for_sample(sample) { return profileNames[sample.n]; } diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js index 123191d70c87..b10e35847560 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js @@ -281,9 +281,9 @@ function h_update_color(color_type) { function h_color_for_sample(color_type, sample) { if (color_type == "fg") { - return color_for_name(0, name_for_sample(sample)); + return color_for_key(0, key_for_sample(sample)); } else if (color_type == "bl") { - return color_for_name(sample.l, name_for_sample(sample)); + return color_for_key(sample.l, key_for_sample(sample)); } else if (color_type = "bc") { return color_for_compilation(sample.i, sample.c); } From 8f1e20325417823527714ef6f86301af2b082628 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Tue, 5 Oct 2021 20:03:40 +0200 Subject: [PATCH 302/681] Rename AlwaysInvalid assumption to NeverValid --- .../analysis/hierarchy/NoOpClassHierarchyOracle.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java index bb6efadf2d26..a5d3489af394 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java @@ -34,9 +34,9 @@ public class NoOpClassHierarchyOracle implements ClassHierarchyOracle { protected static class LeafTypeAssumptionImpl implements LeafTypeAssumption { private final Assumption underlying; - static final LeafTypeAssumption AlwaysInvalid = new LeafTypeAssumptionImpl("invalid"); + static final LeafTypeAssumption NeverValidAssumption = new LeafTypeAssumptionImpl("invalid"); static { - AlwaysInvalid.getAssumption().invalidate(); + NeverValidAssumption.getAssumption().invalidate(); } private LeafTypeAssumptionImpl(String assumptionName) { @@ -56,7 +56,7 @@ public Assumption getAssumption() { protected static final LeafTypeAssumptionAccessor assumptionAccessor = new LeafTypeAssumptionAccessor(); protected static final LeafTypeAssumption FinalIsAlwaysLeaf = new LeafTypeAssumptionImpl("final class is always a CHA leaf"); - protected static final LeafTypeAssumption NotLeaf = LeafTypeAssumptionImpl.AlwaysInvalid; + protected static final LeafTypeAssumption NotLeaf = LeafTypeAssumptionImpl.NeverValidAssumption; @Override public LeafTypeAssumption createAssumptionForNewKlass(ObjectKlass newKlass) { From f5ba182fc82f926f89af5b86e5fed87bf50b308e Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 5 Oct 2021 23:54:12 +0300 Subject: [PATCH 303/681] Test docs/examples with GraalVM EE Java 11 21.3-dev --- .../architecture-overview.md | 5 +- docs/examples/java-kotlin-aot.md | 66 +++++++------ docs/examples/java-performance-examples.md | 84 ++++++++-------- docs/examples/java-simple-stream-benchmark.md | 59 ++++++------ docs/examples/native-image-examples.md | 95 ++++++++++--------- docs/examples/polyglot-javascript-java-r.md | 68 +++++++------ 6 files changed, 191 insertions(+), 186 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index 512e250d54ff..b2e5b935e791 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -56,11 +56,10 @@ Java on Trufle is an experimental technology in GraalVM, available as of version ## Available Distributions -GraalVM Enterprise distributions are based on Oracle JDK 8, 11, and 16. +GraalVM Enterprise distributions are based on Oracle JDK 8, 11, and 17. GraalVM Enterprise releases include all Oracle Java critical patch updates (CPUs), which are released on a regular schedule to remedy defects and known vulnerabilities. GraalVM Enterprise is available for Linux, macOS, and Windows platforms on x86 64-bit systems, and for Linux on ARM 64-bit system. -The GraalVM Enterprise distribution based on Oracle JDK 16 is experimental with [several known limitations](https://docs.oracle.com/en/graalvm/enterprise/21/docs/overview/known-issues/). Depending on the platform, the distributions are shipped as *.tar.gz* or *.zip* archives. ## Certified Platforms @@ -104,7 +103,7 @@ Tools/Utilities: Runtimes: -* [Node.js](/reference-manual/js/) -- the Node.js 14.16.1 runtime for JavaScript +* [Node.js](/reference-manual/js/) -- the Node.js 14.17.6 runtime for JavaScript * [Python](/reference-manual/python/) -- Python 3.8.5 compatible * [Ruby](/reference-manual/ruby/) -- Ruby 2.7.3 compatible * [R](/reference-manual/r/) -- GNU R 4.0.3 compatible diff --git a/docs/examples/java-kotlin-aot.md b/docs/examples/java-kotlin-aot.md index 725c4b71cf6f..e1d3e57feced 100644 --- a/docs/examples/java-kotlin-aot.md +++ b/docs/examples/java-kotlin-aot.md @@ -7,38 +7,43 @@ permalink: /examples/java-kotlin-aot/ # Build a Native Image of a Java and Kotlin Application -This example demonstrates how to compile a Java and Kotlin application -ahead-of-time into a native executable, and illustrates the advantages. +This example demonstrates how to compile a Java and Kotlin application ahead-of-time into a native executable, and illustrates the advantages. -### Preparation - -This example requires the [Maven](https://maven.apache.org/) build tool. +## Preparation 1. Download or clone the repository and navigate into the `java-kotlin-aot` directory: ```shell git clone https://github.com/graalvm/graalvm-demos cd graalvm-demos/java-kotlin-aot ``` -This is a simple Java and Kotlin application showing how easy it is to -interoperate between JVM-based languages. A Java method accesses a String from -Kotlin and calls a Kotlin function, which later accesses a String from a Java -class. Before running this example, you need to build the application. - -Note: You can use any JDK for building the application. However, `javac` from GraalVM -in the build script is used to simplify the prerequisites so another JDK does not need to be installed. - -2. Having installed GraalVM, export the home directory as `$GRAALVM_HOME` and add `$GRAALVM_HOME/bin` -to the path, using a command-line shell for Linux: -```shell -export GRAALVM_HOME=/home/${current_user}/path/to/graalvm +This is a simple Java and Kotlin application showing how easy it is to interoperate between JVM-based languages. +A Java method accesses a String from Kotlin and calls a Kotlin function, which later accesses a String from a Java class. +Before running this example, you need to build the application. + +Note: You can use any JDK for building the application. However, `javac` from GraalVM in the build script is used to simplify the prerequisites so another JDK does not need to be installed. + +2. [Download GraalVM](https://www.graalvm.org/downloads/), unzip the archive, export the GraalVM home directory as the `$JAVA_HOME` and add `$JAVA_HOME/bin` to the `PATH` environment variable: + On Linux: + ```bash + export JAVA_HOME=/home/${current_user}/path/to/graalvm + export PATH=$JAVA_HOME/bin:$PATH + ``` + On macOS: + ```bash + export JAVA_HOME=/Users/${current_user}/path/to/graalvm/Contents/Home + export PATH=$JAVA_HOME/bin:$PATH + ``` + On Windows: + ```bash + setx /M JAVA_HOME "C:\Progra~1\Java\" + setx /M PATH "C:\Progra~1\Java\\bin;%PATH%" + ``` + Note that your paths are likely to be different depending on the download location. + +3. [Install Native Image](../reference-manual/native-image/README.md/#install-native-image) by running. +```bash +gu install native-image ``` -For macOS, use: -```shell -export GRAALVM_HOME=/Users/${current_user}/path/to/graalvm/Contents/Home -``` -Note that your paths are likely to be different depending on the download location. - -3. [Install Native Image](../reference-manual/native-image/README.md/#install-native-image) to make use of the `native-image` utility. 4. Then execute: ```shell @@ -48,18 +53,17 @@ Note that your paths are likely to be different depending on the download locati Have a look at the `build.sh` script which creates a native executable from a Java class. The `native-image` utility compiles the application ahead-of-time for faster startup and lower general overhead at runtime. ```shell -$GRAALVM_HOME/bin/native-image -cp ./target/mixed-code-hello-world-1.0-SNAPSHOT.jar -H:Name=helloworld -H:Class=hello.JavaHello -H:+ReportUnsupportedElementsAtRuntime --allow-incomplete-classpath +$JAVA_HOME/bin/native-image --no-fallback -cp ./target/mixed-code-hello-world-1.0-SNAPSHOT-jar-with-dependencies.jar -H:Name=helloworld -H:Class=hello.JavaHello -H:+ReportUnsupportedElementsAtRuntime ``` -It takes a few parameters: the classpath, the main class of the application with -`-H:Class=...`, and the name of the resulting executable with `-H:Name=...`. +It takes a few parameters: the classpath, the main class of the application with `-H:Class=...`, and the name of the resulting executable with `-H:Name=...`. -After executing the `native-image` command, check the directory. It should have -produced the executable file, `helloworld`. +After executing the `native-image` command, check the directory. +It should have produced the executable file, `helloworld`. -### Running the Application +## Running the Application -To run the application, you need to execute the JAR file in the `target` dir. +To run the application, you need to execute the JAR file in the `target` directory. You can run it as a normal Java application using `java`. Or, since we have a native executable prepared, you can run that directly. The `run.sh` file executes both, and times them with the `time` utility: diff --git a/docs/examples/java-performance-examples.md b/docs/examples/java-performance-examples.md index b5bc2f71ddb0..fac22c279137 100644 --- a/docs/examples/java-performance-examples.md +++ b/docs/examples/java-performance-examples.md @@ -7,19 +7,17 @@ permalink: /examples/java-performance-examples/ # Java Performance Examples -The GraalVM compiler achieves excellent performance, especially for highly -abstracted programs, due to its versatile optimization techniques. Code using -more abstraction and modern Java features like Streams or Lambdas will see -greater speedups. The examples below demonstrate this. +The GraalVM compiler achieves excellent performance, especially for highly abstracted programs, due to its versatile optimization techniques. +Code using more abstraction and modern Java features like Streams or Lambdas will see greater speedups. +The examples below demonstrate this. -### Running Examples +## Running Examples -#### Streams API Example +### Streams API Example -A simple example based on the [Streams API](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html) -is used here to demonstrate performance gains when using the GraalVM compiler. -This example counts the number of uppercase characters in a body of text. To -simulate a large load, the same sentence is processed 10 million times: +A simple example based on the [Streams API](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html) is used here to demonstrate performance gains when using the GraalVM compiler. +This example counts the number of uppercase characters in a body of text. +To simulate a large load, the same sentence is processed 10 million times: 1. Save the following code snippet to a file named `CountUppercase.java`: @@ -49,62 +47,54 @@ public class CountUppercase { ```shell javac CountUppercase.java java CountUppercase In 2021 I would like to run ALL languages in one VM. -1 (297 ms) -2 (452 ms) -3 (136 ms) -4 (88 ms) -5 (107 ms) -6 (135 ms) -7 (88 ms) -8 (87 ms) -9 (78 ms) -total: 69999993 (1550 ms) +1 (319 ms) +2 (275 ms) +3 (164 ms) +4 (113 ms) +5 (100 ms) +6 (124 ms) +7 (86 ms) +8 (76 ms) +9 (77 ms) +total: 69999993 (1414 ms) ``` -The warmup time depends on numerous factors like the source code or how -many cores a machine has. If the performance profile of `CountUppercase` on your -machine does not match the above, run it for more iterations by adding -`-Diterations=N` just after `java` for some `N` greater than 1. +The warmup time depends on numerous factors like the source code or how many cores a machine has. +If the performance profile of `CountUppercase` on your machine does not match the above, run it for more iterations by adding `-Diterations=N` just after `java` for some `N` greater than 1. 3. Add the `-Dgraal.PrintCompilation=true` option to see statistics for the compilations: ```shell java -Dgraal.PrintCompilation=true CountUppercase In 2021 I would like to run ALL languages in one VM. ``` -This option prints a line after each compilation that shows the method -compiled, time taken, bytecodes processed (including inlined methods), size -of machine code produced, and amount of memory allocated during compilation. +This option prints a line after each compilation that shows the method compiled, time taken, bytecodes processed (including inlined methods), size of machine code produced, and amount of memory allocated during compilation. -4. Use the `-XX:-UseJVMCICompiler` option to disable the GraalVM compiler and -use the native top tier compiler in the VM to compare performance: +4. Use the `-XX:-UseJVMCICompiler` option to disable the GraalVM compiler and use the native top tier compiler in the VM to compare performance: ```shell java -XX:-UseJVMCICompiler CountUppercase In 2021 I would like to run ALL languages in one VM. -1 (747 ms) -2 (806 ms) -3 (640 ms) -4 (771 ms) -5 (606 ms) -6 (582 ms) -7 (623 ms) -8 (564 ms) -9 (682 ms) -total: 69999993 (6713 ms) +1 (492 ms) +2 (441 ms) +3 (443 ms) +4 (470 ms) +5 (422 ms) +6 (382 ms) +7 (407 ms) +8 (425 ms) +9 (343 ms) +total: 69999993 (4249 ms) ``` -The preceding example demonstrates the benefits of partial escape analysis (PEA) -and advanced inlining, which combine to significantly reduce heap allocation. +The preceding example demonstrates the benefits of partial escape analysis (PEA) and advanced inlining, which combine to significantly reduce heap allocation. The results were obtained using Oracle GraalVM Enterprise Edition. -The GraalVM Community Edition still has good performance compared to the native top-tier -compiler as shown below. You can simulate the Community Edition on the Enterprise Edition -by adding the option `-Dgraal.CompilerConfiguration=community`. +The GraalVM Community Edition still has good performance compared to the native top-tier compiler as shown below. +You can simulate the Community Edition on the Enterprise Edition by adding the option `-Dgraal.CompilerConfiguration=community`. -#### Sunflow Example +### Sunflow Example [Sunflow](http://sunflow.sourceforge.net) is an open source rendering engine. The following example is a simplified version of the Sunflow engine core code. -It performs calculations to blend various values for a point of light in a -rendered scene. +It performs calculations to blend various values for a point of light in a rendered scene. 1. Save the following code snippet to a file named `Blender.java`: ```java diff --git a/docs/examples/java-simple-stream-benchmark.md b/docs/examples/java-simple-stream-benchmark.md index c30306063bb3..881cc96a149c 100644 --- a/docs/examples/java-simple-stream-benchmark.md +++ b/docs/examples/java-simple-stream-benchmark.md @@ -7,49 +7,49 @@ permalink: /examples/java-simple-stream-benchmark/ # Simple Java Stream Benchmark -This application is a small benchmark of the Java Stream API. It demonstrates how -the GraalVM compiler can achieve better performance for highly -abstracted programs like those using Streams, Lambdas, or other Java features. - -### Preparation - -This example requires the [Maven](https://maven.apache.org/) build tool. - -1. Download or clone the repository and navigate into the `java-simple-stream-benchmark` directory: +This application is a small benchmark of the Java Stream API. It demonstrates how the GraalVM compiler can achieve better performance for highly abstracted programs like those using Streams, Lambdas, or other Java features. + +## Preparation + +1. [Download GraalVM](https://www.graalvm.org/downloads/), unzip the archive, export the GraalVM home directory as the `$JAVA_HOME` and add `$JAVA_HOME/bin` to the `PATH` environment variable: + On Linux: + ```bash + export JAVA_HOME=/home/${current_user}/path/to/graalvm + export PATH=$JAVA_HOME/bin:$PATH + ``` + On macOS: + ```bash + export JAVA_HOME=/Users/${current_user}/path/to/graalvm/Contents/Home + export PATH=$JAVA_HOME/bin:$PATH + ``` + On Windows: + ```bash + setx /M JAVA_HOME "C:\Progra~1\Java\" + setx /M PATH "C:\Progra~1\Java\\bin;%PATH%" + ``` + Note that your paths are likely to be different depending on the download location. + +2. Download or clone the repository and navigate into the `java-simple-stream-benchmark` directory: ```shell git clone https://github.com/graalvm/graalvm-demos cd graalvm-demos/java-simple-stream-benchmark ``` -2. Build the benchmark. You can manually execute `mvn package`, but there is also -a `build.sh` script included for your convenience: +3. Build the benchmark. You can manually execute `mvn package`, but there is also a `build.sh` script included for your convenience: ```shell ./build.sh ``` - -3. Export the GraalVM home directory as the `$GRAALVM_HOME` and add `$GRAALVM_HOME/bin` -to the path, using a command-line shell for Linux: -```shell -export GRAALVM_HOME=/path/to/graalvm -``` -For macOS: -```shell -export GRAALVM_HOME=/path/to/graalvm/Contents/Home -``` - Now you are all set to execute the benchmark and compare the results between different JVMs. -### Running the Benchmark +## Running the Benchmark To run the benchmark, you need to execute the `target/benchmarks.jar` file. You can run it with the following command: ```shell java -jar target/benchmarks.jar ``` -If you would like to run the benchmark on a different JVM, you can run it with -whatever `java` you have. However, if you just want to run it on the same JVM, -but without the GraalVM compiler, you may add the `-XX:-UseJVMCICompiler` option -into the same command: +If you would like to run the benchmark on a different JVM, you can run it with whatever `java` you have. +However, if you just want to run it on the same JVM, but without the GraalVM compiler, you may add the `-XX:-UseJVMCICompiler` option into the same command: ```shell java -XX:-UseJVMCICompiler -jar target/benchmarks.jar ``` @@ -58,7 +58,6 @@ This way, the GraalVM compiler will not be used as the JVMCI compiler and the JV ### Note about Results -The benchmark mode is `AverageTime` in nanoseconds per operation, which means -lower numbers are better. Note that the results you see can be influenced by the -hardware you are running this benchmark on, the CPU load, and other factors. +The benchmark mode is `AverageTime` in nanoseconds per operation, which means lower numbers are better. +Note that the results you see can be influenced by the hardware you are running this benchmark on, the CPU load, and other factors. Interpret them responsibly. diff --git a/docs/examples/native-image-examples.md b/docs/examples/native-image-examples.md index b1412280e053..413cdebd2500 100644 --- a/docs/examples/native-image-examples.md +++ b/docs/examples/native-image-examples.md @@ -7,38 +7,44 @@ permalink: /examples/native-image-examples/ # Ahead-of-Time Compilation of Java and Polyglot Applications -Below are sample applications illustrating GraalVM's unique -capabilities to create self-contained executable images which can run -incredibly fast. Here you will also find a more sophisticated example displaying -GraalVM's ability to create polyglot native executables. +Below are sample applications illustrating GraalVM's unique capabilities to create self-contained executable images which can run incredibly fast. +Here you will also find a more sophisticated example displaying GraalVM's ability to create polyglot native executables. -### Preparation +## Preparation 1. Download or clone the repository and navigate into the `native-list-dir` directory: ```shell git clone https://github.com/graalvm/graalvm-demos cd graalvm-demos/native-list-dir ``` -There are two Java classes, but you will start by building `ListDir.java` for the -purposes of this demo. You can manually execute `javac ListDir.java`, and there is -also a `build.sh` script included for your convenience. - -Note that you can use -any JDK for compiling the Java classes. However, we refer to `javac` from GraalVM -in the build script to simplify the prerequisites so another JDK does not need to be installed. - -2. Having installed GraalVM, export the home directory as `$GRAALVM_HOME` and add `$GRAALVM_HOME/bin` -to the path, using a command-line shell for Linux: -```shell -export GRAALVM_HOME=/home/${current_user}/path/to/graalvm +There are two Java classes, but you will start by building `ListDir.java` for the purposes of this demo. +You can manually execute `javac ListDir.java`, and there is also a `build.sh` script included for your convenience. + +Note that you can use any JDK for compiling the Java classes. +However, we refer to `javac` from GraalVM in the build script to simplify the prerequisites so another JDK does not need to be installed. + +2. [Download GraalVM](https://www.graalvm.org/downloads/), unzip the archive, export the GraalVM home directory as the `$JAVA_HOME` and add `$JAVA_HOME/bin` to the `PATH` environment variable: + On Linux: + ```bash + export JAVA_HOME=/home/${current_user}/path/to/graalvm + export PATH=$JAVA_HOME/bin:$PATH + ``` + On macOS: + ```bash + export JAVA_HOME=/Users/${current_user}/path/to/graalvm/Contents/Home + export PATH=$JAVA_HOME/bin:$PATH + ``` + On Windows: + ```bash + setx /M JAVA_HOME "C:\Progra~1\Java\" + setx /M PATH "C:\Progra~1\Java\\bin;%PATH%" + ``` + Note that your paths are likely to be different depending on the download location. + +3. [Install Native Image](../reference-manual/native-image/README.md/#install-native-image) by running. +```bash +gu install native-image ``` -For macOS, use: -```shell -export GRAALVM_HOME=/Users/${current_user}/path/to/graalvm/Contents/Home -``` -Note that your paths are likely to be different depending on the download location. - -3. [Install Native Image](../reference-manual/native-image/README.md/#install-native-image) to make use of the `native-image` utility. 4. Then execute: ```shell @@ -49,17 +55,14 @@ The `build.sh` script creates a native executable from the Java class. Look at it in more detail: ```shell -$GRAALVM_HOME/bin/native-image ListDir +$JAVA_HOME/bin/native-image ListDir ``` -The `native-image` utility ahead-of-time compiles the `ListDir` class into a -standalone binary in the current working directory. After running the -command, the executable file `listdir` should have been produced. +The `native-image` utility ahead-of-time compiles the `ListDir` class into a standalone binary in the current working directory. +After running the command, the executable file `listdir` should have been produced. -### Running the Application +## Running the Application -To run the application, you need to either execute the `ListDir` class -as a normal Java application using `java`, or since we have a native executable -prepared, run that directly. +To run the application, you need to either execute the `ListDir` class as a normal Java application using `java`, or since we have a native executable prepared, run that directly. The `run.sh` file executes both, and times them with the `time` utility: ```shell @@ -67,8 +70,7 @@ time java ListDir $1 time ./listdir $1 ``` -To make it more interesting, pass it to a parent directory: `./run.sh ..`, where `..` is -the parent of the current directory (the one containing all the demos). +To make it more interesting, pass it to a parent directory: `./run.sh ..`, where `..` is the parent of the current directory (the one containing all the demos). Depending on the directory content you pass this script for, the output will be different than this: ```shell @@ -89,35 +91,36 @@ sys 0m0.011s ``` The performance gain of the native version is largely due to the faster startup. -### Polyglot Capabilities +## Polyglot Capabilities -You can also experiment with a more sophisticated `ExtListDir` example, -which takes advantage of GraalVM's Java and JavaScript polyglot capabilities. +You can also experiment with a more sophisticated `ExtListDir` example, which takes advantage of GraalVM's Java and JavaScript polyglot capabilities. ```shell -$GRAALVM_HOME/bin/javac ExtListDir.java +$JAVA_HOME/bin/javac ExtListDir.java ``` Building the native executable command is similar to the one above, but since the example uses JavaScript, you need to inform the `native-image` utility about that by passing the `--language:js` option. Note that it takes a bit more time because it needs to include the JavaScript support. ```shell -$GRAALVM_HOME/bin/native-image --language:js ExtListDir +$JAVA_HOME/bin/native-image --language:js ExtListDir ``` The execution is the same as in the previous example: ```shell -$ time java ExtListDir $1 -$ time ./extlistdir $1 +time java ExtListDir $1 +time ./extlistdir $1 ``` -### Profile-Guided Optimizations for High Throughput +## Profile-Guided Optimizations for High Throughput -Oracle GraalVM Enterprise Edition offers extra benefits for building native executables. These are [profile-guided optimisations (PGO)](../reference-manual/native-image/PGOEnterprise.md). As an example, a [program demonstrating Java streams](https://github.com/graalvm/graalvm-demos/blob/master/scala-examples/streams/Streams.java) will be used. +Oracle GraalVM Enterprise Edition offers extra benefits for building native executables. +These are [profile-guided optimisations (PGO)](../reference-manual/native-image/PGOEnterprise.md). +As an example, a [program demonstrating Java streams](https://github.com/graalvm/graalvm-demos/blob/master/scala-examples/streams/Streams.java) will be used. 1. Run the application with `java` to see the output: ```shell javac Streams.java -$GRAALVM_HOME/bin/native-image Streams +$JAVA_HOME/bin/native-image Streams ./streams 1000000 200 ... Iteration 20 finished in 1955 milliseconds with checksum 6e36c560485cdc01 @@ -125,14 +128,14 @@ Iteration 20 finished in 1955 milliseconds with checksum 6e36c560485cdc01 2. Build an instrumented image and run it to collect profiles: ```shell -$GRAALVM_HOME/bin/native-image --pgo-instrument Streams +$JAVA_HOME/bin/native-image --pgo-instrument Streams ./streams 1000 200 ``` Profiles collected from this run are now stored in the `default.iprof` file. Note that the profiling now runs with a much smaller data size. 3. Use the profiles gathered at the previous step to build an optimized native executable: ```shell -$GRAALVM_HOME/bin/native-image --pgo Streams +$JAVA_HOME/bin/native-image --pgo Streams ``` 4. Run that optimized native executable: diff --git a/docs/examples/polyglot-javascript-java-r.md b/docs/examples/polyglot-javascript-java-r.md index 9dd251a389d9..78672a957f83 100644 --- a/docs/examples/polyglot-javascript-java-r.md +++ b/docs/examples/polyglot-javascript-java-r.md @@ -12,54 +12,64 @@ This page describes an example of a polyglot application you can run with GraalV ### Preparation 1. Download or clone the repository and navigate into the `polyglot-javascript-java-r` directory: -```shell -git clone https://github.com/graalvm/graalvm-demos -cd graalvm-demos/polyglot-javascript-java-r -``` - -2. [Install GraalVM](/docs/getting-started/#install-graalvm) on your platform. + ```bash + git clone https://github.com/graalvm/graalvm-demos + cd graalvm-demos/polyglot-javascript-java-r + ``` + +2. [Download GraalVM](https://www.graalvm.org/downloads/), unzip the archive, export the GraalVM home directory as the `$JAVA_HOME` and add `$JAVA_HOME/bin` to the `PATH` environment variable: + On Linux: + ```bash + export JAVA_HOME=/home/${current_user}/path/to/graalvm + export PATH=$JAVA_HOME/bin:$PATH + ``` + On macOS: + ```bash + export JAVA_HOME=/Users/${current_user}/path/to/graalvm/Contents/Home + export PATH=$JAVA_HOME/bin:$PATH + ``` + On Windows: + ```bash + setx /M JAVA_HOME "C:\Progra~1\Java\" + setx /M PATH "C:\Progra~1\Java\\bin;%PATH%" + ``` + Note that your paths are likely to be different depending on the download location. 3. To run the demo, you need to enable Node.js support in GraalVM: -```shell -gu install nodejs -``` + ```bash + gu install nodejs + ``` 4. This application contains R code. The R language support is not enabled by default in GraalVM and you should add it too: -```shell -gu install R -``` + ```bash + gu install R + ``` 5. Build the benchmark. You can manually execute `npm install`, but there is also a `build.sh` script included for your convenience: -```shell -./build.sh -``` + ```bash + ./build.sh + ``` Now you are all set to run the polyglot JavaScript, Java, R application. ### Running the Application To run the application, you need to execute the `server.js` file. You can run it with the following command (or run the `run.sh` script): -```shell -$GRAALVM_HOME/bin/node --polyglot --jvm server.js +```bash +$JAVA_HOME/bin/node --polyglot --jvm server.js ``` -If you would like to run the benchmark on a different instance of Node, -you can run it with whatever `node` you have. However, presumably, the polyglot -capability will not be supported. +If you would like to run the benchmark on a different instance of Node, you can run it with whatever `node` you have. However, presumably, the polyglot capability will not be supported. Open [localhost:3000](http://localhost:3000) and see the output of the polyglot app. -Play with the source code and restart the application to see what else -you can do with the mix of JavaScript, Java, and R. +Play with the source code and restart the application to see what else you can do with the mix of JavaScript, Java, and R. ### Debugging Polyglot Applications -GraalVM also supports debugging of polyglot applications and provides a built-in -implementation of the [Chrome DevTools Protocol](../tools/chrome-debugger.md). Add the `--inspect` parameter to the command line, open the URL the application -prints at the startup in the Chrome browser, and start debugging: set breakpoints, -evaluate expressions of this app in JavaScript and R code alike, and so on. +GraalVM also supports debugging of polyglot applications and provides a built-in implementation of the [Chrome DevTools Protocol](../tools/chrome-debugger.md). +Add the `--inspect` parameter to the command line, open the URL the application prints at the startup in the Chrome browser, and start debugging: set breakpoints, evaluate expressions of this app in JavaScript and R code alike, and so on. ### Note about the Application -For brevity, this sample application contains large snippets of code -inside the strings. This is not the best approach for structuring polyglot applications, -but it is the easiest way to demonstrate polyglot capabilities in a single file. +For brevity, this sample application contains large snippets of code inside the strings. +This is not the best approach for structuring polyglot applications, but it is the easiest way to demonstrate polyglot capabilities in a single file. From 1b0c4dee3ff6ffdc73e37f40f3403bdd1faad03c Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Wed, 6 Oct 2021 08:22:36 +0200 Subject: [PATCH 304/681] [GR-34181] Fixed deprecation warning. --- .../com/oracle/truffle/api/test/polyglot/SourceAPITest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITest.java index 1ea0419d2589..91bbd45507fc 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/SourceAPITest.java @@ -41,7 +41,6 @@ package com.oracle.truffle.api.test.polyglot; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; @@ -707,7 +706,7 @@ private static AbstractSourceSectionDispatch getSourceSectionDispatch(AbstractPo ProxyLanguage.setDelegate(new ProxyLanguage() { @Override protected CallTarget parse(ParsingRequest request) { - return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(new SourceSectionProvider(request.getSource()))); + return RootNode.createConstantNode(new SourceSectionProvider(request.getSource())).getCallTarget(); } }); try (Context context = Context.create(ProxyLanguage.ID)) { From 7134ac852273ef28c66ae2c8834d785dad20d252 Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Wed, 6 Oct 2021 08:26:24 +0200 Subject: [PATCH 305/681] Initialize missing Scala classes during build --- substratevm/mx.substratevm/mx_substratevm_benchmark.py | 2 +- .../src/com/oracle/svm/polyglot/scala/ScalaFeature.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/substratevm/mx.substratevm/mx_substratevm_benchmark.py b/substratevm/mx.substratevm/mx_substratevm_benchmark.py index 9c82d6cdf0ab..226ada438e2a 100644 --- a/substratevm/mx.substratevm/mx_substratevm_benchmark.py +++ b/substratevm/mx.substratevm/mx_substratevm_benchmark.py @@ -64,7 +64,7 @@ def list_jars(path): 'als' : [ '--allow-incomplete-classpath', '--report-unsupported-elements-at-runtime', - '--initialize-at-build-time=org.slf4j,org.apache.log4j,scala.runtime.LambdaDeserialize,scala.Symbol$', + '--initialize-at-build-time=org.slf4j,org.apache.log4j', # mis-initialized from netty '--initialize-at-run-time=io.netty.channel.unix.IovArray,io.netty.channel.epoll.EpollEventLoop,io.netty.channel.unix.Errors,io.netty.channel.unix.Socket,io.netty.channel.unix.Limits' ], 'chi-square' : [ diff --git a/substratevm/src/com.oracle.svm.polyglot/src/com/oracle/svm/polyglot/scala/ScalaFeature.java b/substratevm/src/com.oracle.svm.polyglot/src/com/oracle/svm/polyglot/scala/ScalaFeature.java index 8168795a2911..30e83cf26b5b 100644 --- a/substratevm/src/com.oracle.svm.polyglot/src/com/oracle/svm/polyglot/scala/ScalaFeature.java +++ b/substratevm/src/com.oracle.svm.polyglot/src/com/oracle/svm/polyglot/scala/ScalaFeature.java @@ -66,6 +66,9 @@ public boolean isInConfiguration(IsInConfigurationAccess access) { public void beforeAnalysis(BeforeAnalysisAccess access) { initializeScalaEnumerations(access); RuntimeClassInitialization.initializeAtBuildTime("scala.Symbol"); + RuntimeClassInitialization.initializeAtBuildTime("scala.Symbol$"); + /* Initialized through an invokedynamic in `scala.Option` */ + RuntimeClassInitialization.initializeAtBuildTime("scala.runtime.LambdaDeserialize"); } @Override From 1be861499d528af8cb72ca681881df2b2fc13206 Mon Sep 17 00:00:00 2001 From: Martin Entlicher Date: Wed, 6 Oct 2021 11:26:17 +0200 Subject: [PATCH 306/681] Prevent from NPEs from profiler when there are nodes without source sections. (GR-34094) --- .../chromeinspector/test/ProfilerTest.java | 168 ++++++++++++++++++ .../chromeinspector/InspectorDebugger.java | 6 +- .../chromeinspector/InspectorProfiler.java | 24 +-- .../chromeinspector/InspectorRuntime.java | 6 +- .../tools/chromeinspector/ScriptsHandler.java | 11 +- .../chromeinspector/types/StackTrace.java | 14 +- .../truffle/tools/profiler/CPUTracer.java | 7 +- 7 files changed, 201 insertions(+), 35 deletions(-) create mode 100644 tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/ProfilerTest.java diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/ProfilerTest.java b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/ProfilerTest.java new file mode 100644 index 000000000000..b01c882c147c --- /dev/null +++ b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/ProfilerTest.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 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.truffle.tools.chromeinspector.test; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.TruffleSafepoint; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.instrumentation.GenerateWrapper; +import com.oracle.truffle.api.instrumentation.InstrumentableNode; +import com.oracle.truffle.api.instrumentation.ProbeNode; +import com.oracle.truffle.api.instrumentation.StandardTags; +import com.oracle.truffle.api.instrumentation.Tag; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.api.test.polyglot.ProxyLanguage; +import com.oracle.truffle.tools.utils.json.JSONObject; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import org.graalvm.polyglot.Source; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import org.junit.Test; + +public class ProfilerTest { + + @Test + public void testNoSourceProfile() throws InterruptedException, IOException, ExecutionException { + ProxyLanguage.setDelegate(new TestNoSourceLanguage()); + InspectorTester tester = InspectorTester.start(false); + Source source = Source.newBuilder(ProxyLanguage.ID, "1", "NoSourceProfile").build(); + tester.sendMessage("{\"id\":1,\"method\":\"Runtime.enable\"}"); + assertEquals("{\"result\":{},\"id\":1}", tester.getMessages(true).trim()); + tester.sendMessage("{\"id\":2,\"method\":\"Profiler.enable\"}"); + assertEquals("{\"result\":{},\"id\":2}", tester.getMessages(true).trim()); + tester.sendMessage("{\"id\":3,\"method\":\"Profiler.setSamplingInterval\",\"params\":{\"interval\":1000}}"); + assertEquals("{\"result\":{},\"id\":3}", tester.getMessages(true).trim()); + tester.sendMessage("{\"id\":4,\"method\":\"Profiler.start\"}"); + assertEquals("{\"result\":{},\"id\":4}", tester.getMessages(true).trim()); + tester.eval(source).get(); + tester.sendMessage("{\"id\":5,\"method\":\"Profiler.stop\"}"); + JSONObject json = new JSONObject(tester.getMessages(true).trim()); + assertNotNull(json); + assertEquals(json.getInt("id"), 5); + JSONObject jsonResult = json.getJSONObject("result"); + assertNotNull(jsonResult); + JSONObject jsonProfile = jsonResult.getJSONObject("profile"); + assertNotNull(jsonProfile); + tester.sendMessage("{\"id\":6,\"method\":\"Profiler.disable\"}"); + assertEquals("{\"result\":{},\"id\":6}", tester.getMessages(true).trim()); + ProxyLanguage.setDelegate(new ProxyLanguage()); + tester.finish(); + } + + @Test + public void testNoSourceCoverage() throws InterruptedException, IOException, ExecutionException { + ProxyLanguage.setDelegate(new TestNoSourceLanguage()); + InspectorTester tester = InspectorTester.start(false); + Source source = Source.newBuilder(ProxyLanguage.ID, "1", "NoSourceProfile").build(); + tester.sendMessage("{\"id\":1,\"method\":\"Runtime.enable\"}"); + assertEquals("{\"result\":{},\"id\":1}", tester.getMessages(true).trim()); + tester.sendMessage("{\"id\":2,\"method\":\"Profiler.enable\"}"); + assertEquals("{\"result\":{},\"id\":2}", tester.getMessages(true).trim()); + tester.sendMessage("{\"id\":3,\"method\":\"Profiler.startPreciseCoverage\"}"); + assertEquals("{\"result\":{},\"id\":3}", tester.getMessages(true).trim()); + tester.eval(source).get(); + tester.sendMessage("{\"id\":5,\"method\":\"Profiler.takePreciseCoverage\"}"); + // No results in case of no source section + assertEquals("{\"result\":{\"result\":[]},\"id\":5}", tester.getMessages(true).trim()); + tester.sendMessage("{\"id\":7,\"method\":\"Profiler.stopPreciseCoverage\"}"); + assertEquals("{\"result\":{},\"id\":7}", tester.getMessages(true).trim()); + tester.sendMessage("{\"id\":6,\"method\":\"Profiler.disable\"}"); + assertEquals("{\"result\":{},\"id\":6}", tester.getMessages(true).trim()); + ProxyLanguage.setDelegate(new ProxyLanguage()); + tester.finish(); + } + + private static class TestNoSourceLanguage extends ProxyLanguage { + + @Override + protected final CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { + return Truffle.getRuntime().createCallTarget(new NoSourceRootNode(languageInstance)); + } + + private final class NoSourceRootNode extends RootNode { + + @Node.Child private NoSourceStatementNode statement; + + NoSourceRootNode(TruffleLanguage language) { + super(language); + statement = new NoSourceStatementNode(); + insert(statement); + } + + @Override + public Object execute(VirtualFrame frame) { + return statement.execute(frame); + } + + @Override + public String getName() { + return "1"; + } + + } + + } + + @GenerateWrapper + static class NoSourceStatementNode extends Node implements InstrumentableNode { + + NoSourceStatementNode() { + } + + @Override + public boolean isInstrumentable() { + return true; + } + + @Override + public InstrumentableNode.WrapperNode createWrapper(ProbeNode probe) { + return new NoSourceStatementNodeWrapper(this, probe); + } + + public Object execute(VirtualFrame frame) { + assert frame != null; + TruffleSafepoint.poll(this); + return 10; + } + + @Override + public SourceSection getSourceSection() { + return null; + } + + @Override + public boolean hasTag(Class tag) { + return StandardTags.StatementTag.class.equals(tag) || StandardTags.RootTag.class.equals(tag); + } + + } +} diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java index e4dda5c86d07..f58e65493ff5 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java @@ -429,11 +429,7 @@ private CallFrame[] createCallFrames(Iterable frames, SuspendAn // should not be, double-check continue; } - int scriptId = scriptsHandler.assureLoaded(source); - if (scriptId < 0) { - continue; - } - Script script = scriptsHandler.getScript(scriptId); + Script script = scriptsHandler.assureLoaded(source); List scopes = new ArrayList<>(); DebugScope dscope; try { diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorProfiler.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorProfiler.java index 19e66023cc75..4e08f437c49e 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorProfiler.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorProfiler.java @@ -198,9 +198,12 @@ private Params getCoverage(Collection payloads) { JSONObject json = new JSONObject(); Map>> sourceToRoots = new LinkedHashMap<>(); payloads.forEach(payload -> { - Map> rootsToPayloads = sourceToRoots.computeIfAbsent(payload.getSourceSection().getSource(), s -> new LinkedHashMap<>()); - Collection pls = rootsToPayloads.computeIfAbsent(payload.getRootName(), t -> new LinkedList<>()); - pls.add(payload); + SourceSection sourceSection = payload.getSourceSection(); + if (sourceSection != null) { + Map> rootsToPayloads = sourceToRoots.computeIfAbsent(sourceSection.getSource(), s -> new LinkedHashMap<>()); + Collection pls = rootsToPayloads.computeIfAbsent(payload.getRootName(), t -> new LinkedList<>()); + pls.add(payload); + } }); JSONArray result = new JSONArray(); sourceToRoots.entrySet().stream().map(sourceEntry -> { @@ -214,9 +217,8 @@ private Params getCoverage(Collection payloads) { } functions.add(new FunctionCoverage(rootEntry.getKey(), isBlockCoverage, ranges.toArray(new CoverageRange[ranges.size()]))); }); - int scriptId = slh.getScriptId(sourceEntry.getKey()); - Script script = scriptId < 0 ? null : slh.getScript(scriptId); - return new ScriptCoverage(script != null ? script.getId() : 0, script != null ? script.getUrl() : "", functions.toArray(new FunctionCoverage[functions.size()])); + Script script = slh.assureLoaded(sourceEntry.getKey()); + return new ScriptCoverage(script.getId(), script.getUrl(), functions.toArray(new FunctionCoverage[functions.size()])); }).forEachOrdered(scriptCoverage -> { result.put(scriptCoverage.toJSON()); }); @@ -248,10 +250,9 @@ private void fillChildren(ProfileNode node, Collection profile entries.add(new TypeProfileEntry(sectionProfile.getSourceSection().getCharEndIndex(), types.toArray(new TypeObject[types.size()]))); } }); - int scriptId = slh.getScriptId(entry.getKey()); - Script script = scriptId < 0 ? null : slh.getScript(scriptId); - result.put(new ScriptTypeProfile(script != null ? script.getId() : 0, script != null ? script.getUrl() : "", entries.toArray(new TypeProfileEntry[entries.size()])).toJSON()); + Script script = slh.assureLoaded(entry.getKey()); + result.put(new ScriptTypeProfile(script.getId(), script.getUrl(), entries.toArray(new TypeProfileEntry[entries.size()])).toJSON()); }); json.put("result", result); return new Params(json); diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorRuntime.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorRuntime.java index dde0b613ea3c..5a6843d6e00f 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorRuntime.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorRuntime.java @@ -213,10 +213,8 @@ public Boolean processException(DebugException ex) { exceptionText[0] = ""; } if (parsed && persistScript) { - int id = slh.assureLoaded(source); - if (id != -1) { - ret.put("scriptId", Integer.toString(id)); - } + int id = slh.assureLoaded(source).getId(); + ret.put("scriptId", Integer.toString(id)); } if (exceptionText[0] != null) { fillExceptionDetails(ret, exceptionText[0]); diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/ScriptsHandler.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/ScriptsHandler.java index 3b2536fdd654..b0eae06c11cb 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/ScriptsHandler.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/ScriptsHandler.java @@ -102,7 +102,7 @@ void removeLoadScriptListener(LoadScriptListener listener) { } } - public int assureLoaded(Source sourceLoaded) { + public Script assureLoaded(Source sourceLoaded) { DebuggerSession ds = debuggerSession; Source sourceResolved = sourceLoaded; if (ds != null) { @@ -110,14 +110,15 @@ public int assureLoaded(Source sourceLoaded) { } Source source = (sourceResolved != null) ? sourceResolved : sourceLoaded; Script scr; - int id; LoadScriptListener[] listenersToNotify; synchronized (sourceIDs) { Integer eid = sourceIDs.get(source); if (eid != null) { - return eid; + scr = scripts.get(eid); + assert scr != null : sourceLoaded; + return scr; } - id = scripts.size(); + int id = scripts.size(); String sourceUrl = getSourceURL(source); scr = new Script(id, sourceUrl, source, sourceLoaded); sourceIDs.put(source, id); @@ -128,7 +129,7 @@ public int assureLoaded(Source sourceLoaded) { for (LoadScriptListener l : listenersToNotify) { l.loadedScript(scr); } - return id; + return scr; } public String getSourceURL(Source source) { diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/types/StackTrace.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/types/StackTrace.java index bfeefd7e5037..ff662f46478a 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/types/StackTrace.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/types/StackTrace.java @@ -66,14 +66,12 @@ public StackTrace(InspectorExecutionContext context, List() { @Override public Payload apply(SourceSection section) { @@ -192,7 +193,11 @@ private synchronized void resetTracer() { this.activeBinding = env.getInstrumenter().attachExecutionEventFactory(f, new ExecutionEventNodeFactory() { @Override public ExecutionEventNode create(EventContext context) { - return new CounterNode(getCounter(context)); + if (context.getInstrumentedSourceSection() != null) { + return new CounterNode(getCounter(context)); + } else { + return null; + } } }); } From b43d8e3906f0e7c54d92a64f274a4ba85ac74c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C3=B6=20Barany?= Date: Wed, 6 Oct 2021 13:27:34 +0200 Subject: [PATCH 307/681] Allow querying the BarrierSet for the need for pre-write barriers --- .../src/org/graalvm/compiler/nodes/gc/BarrierSet.java | 9 +++++++++ .../graalvm/compiler/nodes/gc/CardTableBarrierSet.java | 5 +++++ .../src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java | 5 +++++ .../core/genscavenge/graal/SubstrateNoBarrierSet.java | 5 +++++ 4 files changed, 24 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/BarrierSet.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/BarrierSet.java index 78f687583b79..fa6ba10cad1a 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/BarrierSet.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/BarrierSet.java @@ -48,4 +48,13 @@ public interface BarrierSet { BarrierType arrayStoreBarrierType(JavaKind storageKind); BarrierType guessStoreBarrierType(ValueNode object, ValueNode value); + + /** + * Determine whether writes of the given {@code storageKind} may ever need a pre-write barrier. + * + * @return {@code false} if no writes of {@code storageKind} ever need a pre-write barrier; + * {@code true} if writes of {@code storageKind} may need a pre-write barrier at least + * under certain circumstances. + */ + boolean mayNeedPreWriteBarrier(JavaKind storageKind); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java index f29782ba2981..d1f16713d2b3 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java @@ -238,4 +238,9 @@ private static boolean matches(FixedAccessNode node, SerialWriteBarrier barrier) private static boolean matches(ArrayRangeWrite node, SerialArrayRangeWriteBarrier barrier) { return barrier.getAddress() == node.getAddress() && node.getLength() == barrier.getLength() && node.getElementStride() == barrier.getElementStride(); } + + @Override + public boolean mayNeedPreWriteBarrier(JavaKind storageKind) { + return false; + } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java index c3d35dd38eff..b5338cfd7c89 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java @@ -201,4 +201,9 @@ private static void addG1PostWriteBarrier(FixedAccessNode node, AddressNode addr private static boolean isObjectValue(ValueNode value) { return value.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp; } + + @Override + public boolean mayNeedPreWriteBarrier(JavaKind storageKind) { + return arrayStoreBarrierType(storageKind) != BarrierType.NONE; + } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateNoBarrierSet.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateNoBarrierSet.java index e814cb572969..39bd82093cca 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateNoBarrierSet.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateNoBarrierSet.java @@ -72,4 +72,9 @@ public BarrierType arrayStoreBarrierType(JavaKind storageKind) { public BarrierType guessStoreBarrierType(ValueNode object, ValueNode value) { return BarrierType.NONE; } + + @Override + public boolean mayNeedPreWriteBarrier(JavaKind storageKind) { + return false; + } } From 7973ae7cc0110b063c090249f54cf183986b7e00 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Wed, 6 Oct 2021 14:33:17 +0300 Subject: [PATCH 308/681] Test examples and update Gettins started pages --- .../graalvm-ce-container-images.md | 29 ++++++++++--------- .../get-started-graalvm-community.md | 21 ++++++++------ .../graalvm-community/linux-aarch64.md | 7 ++--- .../graalvm-community/linux.md | 12 ++++---- .../graalvm-community/macos.md | 17 +++++------ .../graalvm-community/windows.md | 17 ++++++----- .../get-started-graalvm-enterprise.md | 23 ++++++++------- .../installation-linux-aarch64.md | 7 ++--- .../graalvm-enterprise/installation-linux.md | 12 ++++---- .../graalvm-enterprise/installation-macos.md | 22 +++++--------- .../installation-windows.md | 19 ++++++------ 11 files changed, 89 insertions(+), 97 deletions(-) diff --git a/docs/getting-started/graalvm-community/container-images/graalvm-ce-container-images.md b/docs/getting-started/graalvm-community/container-images/graalvm-ce-container-images.md index a16a8e3b7014..4d3646e906f7 100644 --- a/docs/getting-started/graalvm-community/container-images/graalvm-ce-container-images.md +++ b/docs/getting-started/graalvm-community/container-images/graalvm-ce-container-images.md @@ -22,7 +22,7 @@ FROM ghcr.io/graalvm/graalvm-ce:latest There are different GraalVM Community container images provided depending on the architecture and the Java version. GraalVM binaries are built for Linux, macOS, and Windows platforms on x86 64-bit systems, and for Linux on ARM 64-bit systems. -The images are multi-arch (`aarch64` or `amd64` will be pulled depending on Docker host architecture), and named per a _platform-jdk-version_ naming scheme, for example, `ghcr.io/graalvm/graalvm-ce:latest:ol8-java11-21.2.0`. +The images are multi-arch (`aarch64` or `amd64` will be pulled depending on Docker host architecture), and named per a _platform-jdk-version_ naming scheme, for example, `ghcr.io/graalvm/graalvm-ce:latest:ol8-java11-21.3.0`. A complete list can be found on the [All versions](https://github.com/orgs/graalvm/packages/container/graalvm-ce/versions) page. The images are based on Oracle Linux and has GraalVM Community downloaded, unzipped and made available. @@ -30,23 +30,24 @@ It means that Java, JavaScript, Node.js and the LLVM runtime are available out o You can start a container and enter the `bash` session with the following run command: ```shell -docker run -it --rm ghcr.io/graalvm/graalvm-ce:21.2.0 bash +docker run -it --rm ghcr.io/graalvm/graalvm-ce:21.3.0 bash ``` Check that `java`, `js` and other commands work as expected. ```shell -→ docker run -it --rm ghcr.io/graalvm/graalvm-ce:21.2.0 bash +→ docker run -it --rm ghcr.io/graalvm/graalvm-ce:21.3.0 bash bash-4.4# java -version -openjdk version "11.0.12" 2021-07-20 -OpenJDK Runtime Environment GraalVM CE 21.2.0 (build 11.0.12+6-jvmci-21.2-b06) -OpenJDK 64-Bit Server VM GraalVM CE 21.2.0 (build 11.0.12+6-jvmci-21.2-b06, mixed mode, sharing) +openjdk version "17" 2021-09-14 +OpenJDK Runtime Environment GraalVM CE 21.3.0 (build 17+35-jvmci-21.3-b03) +OpenJDK 64-Bit Server VM GraalVM CE 21.3.0 (build 17+35-jvmci-21.3-b03, mixed mode, sharing) + bash-4.4# js -version -GraalVM JavaScript (GraalVM CE Native 21.2.0) +GraalVM JavaScript (GraalVM CE Native 21.3.0) > 1 + 1 2 > quit() +> bash-4.4# lli --version -LLVM 10.0.0 (GraalVM CE Native 21.2.0) -bash-4.4# +LLVM 12.0.1 (GraalVM CE Native 21.3.0) ``` Please note that the image contains only the components immediately available in the GraalVM Community core download. @@ -56,7 +57,7 @@ However, the [GraalVM Updater, `gu`](/reference-manual/graalvm-updater/), utilit For example, the following command installs the Ruby support (the output below is truncated for brevity): ```shell -docker run -it --rm ghcr.io/graalvm/graalvm-ce:21.2.0 bash +docker run -it --rm ghcr.io/graalvm/graalvm-ce:21.3.0 bash bash-4.4# gu install ruby Downloading: Component catalog Processing component archive: Component ruby @@ -68,13 +69,13 @@ Downloading: Component ruby Here is a sample command that maps the `/absolute/path/to/directory/no/trailing/slash` directory from the host system to the `/path/inside/container` inside the container. ```shell -docker run -it --rm -v /absolute/path/to/directory/no/trailing/slash:/path/inside/container ghcr.io/graalvm/graalvm-ce:21.2.0 bash +docker run -it --rm -v /absolute/path/to/directory/no/trailing/slash:/path/inside/container ghcr.io/graalvm/graalvm-ce:21.3.0 bash ``` -If you want to create Docker images that contain GraalVM with Ruby, R, or Python, you can use a Dockerfile like the example below, which uses `ghcr.io/graalvm/graalvm-ce:21.2.0` as the base image, installs the Ruby support using the `gu` utility, then creates and runs a sample Ruby program. +If you want to create Docker images that contain GraalVM with Ruby, R, or Python, you can use a Dockerfile like the example below, which uses `ghcr.io/graalvm/graalvm-ce:21.3.0` as the base image, installs the Ruby support using the `gu` utility, then creates and runs a sample Ruby program. ```shell -FROM ghcr.io/graalvm/graalvm-ce:21.2.0 +FROM ghcr.io/graalvm/graalvm-ce:21.3.0 RUN gu install ruby WORKDIR /workdir RUN echo 'puts "Hello from Ruby!\nVersion: #{RUBY_DESCRIPTION}"' > app.rb @@ -88,5 +89,5 @@ docker build -t ruby-demo . ... docker run -it --rm ruby-demo Hello from Ruby! -Version: truffleruby 21.2.0, like ruby 2.7.3, GraalVM CE Native [x86_64-darwin] +Version: truffleruby 21.3.0, like ruby 2.7.4, GraalVM CE Native [x86_64-darwin] ``` diff --git a/docs/getting-started/graalvm-community/get-started-graalvm-community.md b/docs/getting-started/graalvm-community/get-started-graalvm-community.md index f6142b394a12..35a16e43645d 100644 --- a/docs/getting-started/graalvm-community/get-started-graalvm-community.md +++ b/docs/getting-started/graalvm-community/get-started-graalvm-community.md @@ -42,14 +42,15 @@ GraalVM's `/bin` directory is similar to that of a standard JDK, but includes a Check the versions of the runtimes provided by default: ```shell java -version -openjdk version "11.0.12" 2021-07-20 -OpenJDK Runtime Environment GraalVM CE 21.2.0 (build 11.0.12+6-jvmci-21.2-b06) -OpenJDK 64-Bit Server VM GraalVM CE 21.2.0 (build 11.0.12+6-jvmci-21.2-b06, mixed mode, sharing) +openjdk version "17" 2021-09-14 +OpenJDK Runtime Environment GraalVM CE 21.3.0 (build 17+35-jvmci-21.3-b03) +OpenJDK 64-Bit Server VM GraalVM CE 21.3.0 (build 17+35-jvmci-21.3-b03, mixed mode, sharing) + js -version -GraalVM JavaScript (GraalVM CE Native 21.2.0) +GraalVM JavaScript (GraalVM CE Native 21.3.0) lli --version -LLVM 10.0.0 (GraalVM CE Native 21.2.0) +LLVM 12.0.1 (GraalVM CE Native 21.3.0) ``` Further below you will find information on how to add other optionally available GraalVM runtimes including Node.js, Ruby, R, Python, and WebAssembly. @@ -91,8 +92,10 @@ GraalVM also supports running Node.js applications. Node.js support is not installed by default, but can be easily added with GraalVM Updater: ```shell gu install nodejs -node -v -v14.16.1 +``` +```shell +$JAVA_HOME/bin/node -v +v14.17.6 ``` More than 100,000 npm packages are regularly tested and are compatible with GraalVM, including modules like express, react, async, request, browserify, grunt, mocha, and underscore. @@ -101,7 +104,7 @@ The `npm` command is equivalent to the default Node.js command and supports all Install the `colors` and `ansispan` modules using `npm install`. After the modules are installed, you can use them from your application. ```shell -npm install colors ansispan +$JAVA_HOME/bin/npm install colors ansispan ``` Use the following code snippet and save it as the `app.js` file in the same directory where you installed the Node.js modules: @@ -120,7 +123,7 @@ setTimeout(function() { console.log("DONE!"); process.exit(); }, 2000); Run _app.js_ on GraalVM Enterprise using the `node` command: ```shell -node app.js +$JAVA_HOME/bin/node app.js ``` For more detailed documentation and information on compatibility with Node.js, diff --git a/docs/getting-started/graalvm-community/linux-aarch64.md b/docs/getting-started/graalvm-community/linux-aarch64.md index e4fb8d221c09..5119f7b654d9 100644 --- a/docs/getting-started/graalvm-community/linux-aarch64.md +++ b/docs/getting-started/graalvm-community/linux-aarch64.md @@ -7,15 +7,14 @@ permalink: /docs/getting-started/linux-aarch64/ # Installation on Linux ARM64 systems -As of version 21.0, we provide GraalVM Community Edition for Linux on ARM 64-bit system, based on OpenJDK 11 for AArch64 architecture. +As of version 21.0, we provide GraalVM Community Edition for Linux on ARM 64-bit system, based on OpenJDK 11 and OpenJDK 17 for AArch64 architecture. This distribution can be installed on Linux systems for AArch64 CPU architecture. -Note: The base GraalVM Community distribution including all components is **experimental** on Linux ARM 64-bit systems. - + You can install the GraalVM distribution for Linux ARM64 systems from an archive file (_.tar.gz_). This allows you to install GraalVM for the current user into any location, without affecting other JDK installations. -1. Navigate to the [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Depending on the workload, select Java 11 or 16 based distribution for the Linux AArch64 architecture, and download. +1. Navigate to the [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Select Java 11 or 17 based distribution for the Linux AArch64 architecture, and download. 2. Change the directory to the location where you want to install GraalVM, then move the _.tar.gz_ archive to it. 3. Unzip the archive: ```shell diff --git a/docs/getting-started/graalvm-community/linux.md b/docs/getting-started/graalvm-community/linux.md index 8b152d3abfda..a9800864d7d6 100644 --- a/docs/getting-started/graalvm-community/linux.md +++ b/docs/getting-started/graalvm-community/linux.md @@ -9,7 +9,7 @@ permalink: /docs/getting-started/linux/ Follow these steps to install GraalVM Community Edition on the Linux operating system. -1. Navigate to the [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Depending on the workload, select Java 11 based or Java 8 based distribution for the Linux AMD64 architecture, and download. +1. Navigate to the [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Select Java 11 based or Java 17 based distribution for the Linux AMD64 architecture, and download. 2. Change the directory to the location where you want to install GraalVM, then move the _.tar.gz_ archive to it. 3. Unzip the archive: ```shell @@ -41,15 +41,13 @@ Tools/Utilities: * [Java on Truffle](/reference-manual/java-on-truffle/) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible +* [Node.js](/reference-manual/js/) -- Node.js 14.17.6 compatible * [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.2 compatible +* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.4 compatible * [R](/reference-manual/r/) -- GNU R 4.0.3 compatible * [Wasm](/reference-manual/wasm/) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Community base distribution and must be installed separately. -To assist a user with installation, GraalVM includes -**GraalVM Updater**, a command line utility to install and manage additional -functionalities. Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} -to add any necessary language runtime or utility from above to GraalVM. +To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. +Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/getting-started/graalvm-community/macos.md b/docs/getting-started/graalvm-community/macos.md index 4828d64b6229..6ad5bb3d4cfa 100644 --- a/docs/getting-started/graalvm-community/macos.md +++ b/docs/getting-started/graalvm-community/macos.md @@ -10,14 +10,13 @@ permalink: /docs/getting-started/macos/ GraalVM Community Edition can be installed for a single user and administrator privileges are not required. However, if GraalVM is meant to become a default JDK, administrator privileges are required. -GraalVM Community Edition does not provide the installation wizard, unlike OpenJDK -distributions for macOS that come with the _.dmg_ download. +GraalVM Community Edition does not provide the installation wizard, unlike OpenJDK distributions for macOS that come with the _.dmg_ download. It can be installed from an archive file (_.tar.gz_). Note that in macOS, the JDK installation path is: `/Library/Java/JavaVirtualMachines//Contents/Home`. Follow these steps to install GraalVM Community on the macOS operating system: -1. Navigate to [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Depending on the workload, select Java 11 based or Java 8 based distribution for macOS, and download. +1. Navigate to [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Select Java 11 based or Java 17 based distribution for macOS, and download. 2. Unzip the archive. ```shell tar -xzf graalvm-ce-java-darvin-amd64-.tar.gz @@ -56,7 +55,7 @@ sudo xattr -r -d com.apple.quarantine /path/to/GRAALVM_HOME #### On JAVA_HOME Command The information property file, _Info.plist_, is in the top level _Contents_ folder. -This means that GraalVM Enterprise participates in the macOS-specific `/usr/libexec/java_home` mechanism. Depending on other JDK 8 installation(s) available, it is now possible that `/usr/libexec/java_home -v1.8` returns `/Library/Java/JavaVirtualMachines//Contents/Home`. +This means that GraalVM Enterprise participates in the macOS-specific `/usr/libexec/java_home` mechanism. Depending on other JDK installation(s) available, it is now possible that `/usr/libexec/java_home -v1.8` returns `/Library/Java/JavaVirtualMachines//Contents/Home`. You can run `/usr/libexec/java_home -v1.8 -V` to see the complete list of 1.8 JVMs available to the `java_home` command. This command sorts the JVMs in decreasing version order and chooses the top one as the default for the specified version. Within a specific version, the sort order appears to be stable but is unspecified. @@ -71,15 +70,13 @@ Tools/Utilities: * [Java on Truffle](/reference-manual/java-on-truffle/) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible +* [Node.js](/reference-manual/js/) -- Node.js 14.17.6 compatible * [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.2 compatible +* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.4 compatible * [R](/reference-manual/r/) -- GNU R 4.0.3 compatible * [Wasm](/reference-manual/wasm/) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Community base distribution and must be installed separately. -To assist a user with installation, GraalVM includes -**GraalVM Updater**, a command line utility to install and manage additional -functionalities. Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} -to add any necessary language runtime or utility from above to GraalVM. +To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. +Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/getting-started/graalvm-community/windows.md b/docs/getting-started/graalvm-community/windows.md index 75bd7134e958..ada076c6d2ee 100644 --- a/docs/getting-started/graalvm-community/windows.md +++ b/docs/getting-started/graalvm-community/windows.md @@ -10,7 +10,7 @@ permalink: /docs/getting-started/windows/ You can install GraalVM Community Edition on the Windows operating system from an archive file (_zip_). Follow these steps: -1. Navigate to the [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Depending on the workload, select Java 11 based or Java 8 based distribution for Windows, and download. +1. Navigate to the [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Select Java 11 based or Java 17 based distribution for Windows, and download. 2. Change the directory to the location where you want to install GraalVM, then move the _.zip_ archive file to it. 3. Unzip the archive to your file system. 4. There can be multiple JDKs installed on the machine. The next step is to configure the runtime environment. Setting environment variables via the command line will work the same way for Windows 7, 8 and 10. @@ -43,12 +43,13 @@ The GraalVM Community distribution for Windows platforms includes OpenJDK with t Currently, the GraalVM environment on Windows can be extended with [Native Image](/reference-manual/native-image/), [Java on Trufle](/reference-manual/java-on-truffle/), WebAssembly, and Node.js support. ## Prerequisites for Using Native Image on Windows -To make use of Native Image on Windows, observe the following recommendations. -The required Microsoft Visual C++ (MSVC) version depends on the JDK version that GraalVM is based on. -For GraalVM based on JDK 8, you will need MSVC 2010 SP1 version. The recommended installation method is using Microsoft Windows SDK 7.1: -1. Download the SDK file `GRMSDKX_EN_DVD.iso` for from [Microsoft](https://www.microsoft.com/en-gb/download). -2. Mount the image by opening `F:\Setup\SDKSetup.exe` directly. -For GraalVM distribution based on JDK 11, you will need MSVC 2017 15.5.5 or later version. +To start using Native Image on Windows, install Visual Studio Code and Microsoft Visual C++(MSVC). There are two installation options: + * Install the Visual Studio Code Build Tools with the Windows 10 SDK + * Install Visual Studio Code with the Windows 10 SDK -The last prerequisite, common for both distributions, is the proper [Developer Command Prompt](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt_shortcuts) for your version of [Visual Studio](https://visualstudio.microsoft.com/vs/). On Windows the `native-image` tool only works when it is executed from the **x64 Native Tools Command Prompt**. +You can use Visual Studio 2017 version 15.9 or later. + +Lastly, on Windows, the `native-image` builder will only work when it is executed from the **x64 Native Tools Command Prompt**. +The command for initiating an x64 Native Tools command prompt is different if you only have the Visual Studio Build Tools installed, versus if you have the full VS Code 2019 installed. +Check [this link](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311) for step-by-step instructions. diff --git a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md index 24c251a1b064..22198e511638 100644 --- a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md +++ b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md @@ -45,15 +45,15 @@ GraalVM Enterprise's `/bin` directory is similar to that of a standard JDK, but Check the versions of the runtimes provided by default: ```shell -java version "11.0.12" 2021-07-20 LTS -Java(TM) SE Runtime Environment GraalVM EE 21.2.0 (build 11.0.12+8-LTS-jvmci-21.2-b06) -Java HotSpot(TM) 64-Bit Server VM GraalVM EE 21.2.0 (build 11.0.12+8-LTS-jvmci-21.2-b06, mixed mode, sharing) +java version "11.0.13" 2021-10-19 LTS +Java(TM) SE Runtime Environment GraalVM EE 21.3.0 (build 11.0.13+9-LTS-jvmci-21.3-b03) +Java HotSpot(TM) 64-Bit Server VM GraalVM EE 21.3.0 (build 11.0.13+9-LTS-jvmci-21.3-b03, mixed mode, sharing) js -version -GraalVM JavaScript (GraalVM EE Native 21.2.0) +GraalVM JavaScript (GraalVM EE Native 21.3.0) lli --version -LLVM 10.0.0 (GraalVM EE Native 21.2.0) +LLVM 12.0.1 (GraalVM EE Native 21.3.0) ``` Further below you will find information on how to add other optionally available GraalVM Enterprise runtimes including Node.js, Ruby, R, Python, and WebAssembly. @@ -94,8 +94,10 @@ GraalVM Enterprise also supports running Node.js applications. Node.js support is not installed by default, but can be easily added with GraalVM Updater: ```shell gu install nodejs -node -v -v15.12.0 +``` +```shell +$JAVA_HOME/bin/node -v +v14.17.6 ``` More than 100,000 npm packages are regularly tested and are compatible with GraalVM Enterprise, including modules like express, react, async, request, browserify, grunt, mocha, and underscore. @@ -105,7 +107,7 @@ The `npm` command is equivalent to the default Node.js command and supports all Install the `colors` and `ansispan` modules using `npm install`. After the modules are installed, you can use them from your application. ```shell -npm install colors ansispan +$JAVA_HOME/bin/npm install colors ansispan ``` Use the following code snippet and save it as the `app.js` file in the same directory where you installed the Node.js modules: @@ -124,7 +126,7 @@ setTimeout(function() { console.log("DONE!"); process.exit(); }, 2000); Run _app.js_ on GraalVM Enterprise using the `node` command: ```shell -node app.js +$JAVA_HOME/bin/node app.js ``` For more detailed documentation and information on compatibility with Node.js, proceed to [JavaScript and Node.js](/reference-manual/js/). @@ -254,7 +256,8 @@ int main() { } ``` -Compile it using the most recent [Emscripten compiler frontend](https://emscripten.org/docs/tools_reference/emcc.html) version. It should produce a standalone _floyd.wasm_ file in the current working directory: +Compile it using the most recent [Emscripten compiler frontend](https://emscripten.org/docs/tools_reference/emcc.html) version. +It should produce a standalone _floyd.wasm_ file in the current working directory: ```shell emcc -o floyd.wasm floyd.c ``` diff --git a/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md b/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md index 320ef5e8a66d..2f0532cca051 100644 --- a/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md +++ b/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md @@ -5,16 +5,15 @@ permalink: /getting-started/installation-linux-aarch64/ # Installation on Linux ARM64 systems -As of version 21.0, Oracle provides GraalVM Enterprise distributions based on Oracle JDK11 AArch64. +As of version 21.0, Oracle provides GraalVM Enterprise distributions based on Oracle JDK11 and Oracle JDK17 for AArch64 architecture. 
This distribution can be installed on Oracle Linux and Red Hat Enterprise Linux(RHEL) systems for AArch64 CPU architecture. -Note: The core GraalVM Enterprise distribution including all components is **experimental** on Linux ARM 64-bit systems. - + You can install the GraalVM distribution for Linux ARM64 systems from an archive file (_.tar.gz_). This allows you to install GraalVM for the current user into any location, without affecting other JDK installations. 1. Navigate to [Oracle GraalVM Downloads](https://www.oracle.com/downloads/graalvm-downloads.html?selected_tab=21). -2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **11** or **16** for the Java version, **Linux** for the operating system, and **aarch64** for the architecture. +2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **11** or **17** for the Java version, **Linux** for the operating system, and **aarch64** for the architecture. 3. Click on the **GraalVM Enterprise Core** download link. Before you download a file, you must accept the [Oracle License Agreement](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) in the popup window. 4. When the download button becomes active, press it to start downloading **graalvm-ee-java11-linux-aarch64-.tar.gz**. 5. Change the directory to the location where you want to install GraalVM Enterprise, then move the _.tar.gz_ archive to it. diff --git a/docs/getting-started/graalvm-enterprise/installation-linux.md b/docs/getting-started/graalvm-enterprise/installation-linux.md index 84c9c4e1a3a2..d86e9beba9a2 100644 --- a/docs/getting-started/graalvm-enterprise/installation-linux.md +++ b/docs/getting-started/graalvm-enterprise/installation-linux.md @@ -8,7 +8,7 @@ permalink: /getting-started/installation-linux/ Follow these steps to install Oracle GraalVM Enterprise Edition on the Linux operating system: 1. Navigate to [Oracle GraalVM Downloads](https://www.oracle.com/downloads/graalvm-downloads.html?selected_tab=21). -2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **16** for the Java version, **Linux** for the operating system, and **amd64** for the architecture. +2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **17** for the Java version, **Linux** for the operating system, and **amd64** for the architecture. 3. Click on the **GraalVM Enterprise Core** download link. Before you download a file, you must accept the [Oracle License Agreement](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) in the popup window. 4. When the download button becomes active, press it to start downloading **graalvm-ee-java-linux-amd64-.tar.gz**. 5. Change the directory to the location where you want to install GraalVM Enterprise, then move the _.tar.gz_ archive to it. @@ -40,15 +40,13 @@ Tools/Utilities: * [Java on Truffle](/reference-manual/java-on-truffle/) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Enterprise Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible +* [Node.js](/reference-manual/js/) -- Node.js 14.17.6 compatible * [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.3 compatible +* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.4 compatible * [R](/reference-manual/r/) -- GNU R 4.0.3 compatible * [Wasm](/reference-manual/wasm/) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Enterprise base distribution and must be installed separately. -To assist a user with installation, GraalVM Enterprise includes -**GraalVM Updater**, a command line utility to install and manage additional -functionalities. Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} -to add any necessary language runtime or utility from above to the GraalVM Enterprise core. +To assist a user with installation, GraalVM Enterprise includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. +Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} to add any necessary language runtime or utility from above to the GraalVM Enterprise core. diff --git a/docs/getting-started/graalvm-enterprise/installation-macos.md b/docs/getting-started/graalvm-enterprise/installation-macos.md index 086dc63feb9d..9e493cb27ecc 100644 --- a/docs/getting-started/graalvm-enterprise/installation-macos.md +++ b/docs/getting-started/graalvm-enterprise/installation-macos.md @@ -5,19 +5,15 @@ permalink: /getting-started/installation-macos/ # Installation on macOS Platforms -GraalVM Enterprise can be installed for a single user and administrator -privileges are not required. However, if GraalVM Enterprise is meant to become a -default JDK, administrator privileges are required. +GraalVM Enterprise can be installed for a single user and administrator privileges are not required. However, if GraalVM Enterprise is meant to become a default JDK, administrator privileges are required. -GraalVM Enterprise does not provide the installation wizard, unlike Oracle JDK -distributions for macOS that come with the _.dmg_ download. Note that in macOS, -the JDK installation path is: -`/Library/Java/JavaVirtualMachines//Contents/Home`. +GraalVM Enterprise does not provide the installation wizard, unlike Oracle JDK distributions for macOS that come with the _.dmg_ download. +Note that in macOS, the JDK installation path is: `/Library/Java/JavaVirtualMachines//Contents/Home`. Follow these steps to install Oracle GraalVM Enterprise Edition on the macOS operating system: 1. Navigate to[ Oracle GraalVM Downloads](https://www.oracle.com/downloads/graalvm-downloads.html). -2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **16** for the Java version, and **macOS** for the operating system. +2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **17** for the Java version, and **macOS** for the operating system. 3. Click on the **GraalVM Enterprise Core** download link. Before you download a file, you must accept the [Oracle License Agreement](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) in the popup window. 4. When the download button becomes active, press it to start downloading **graalvm-ee-java-darvin-amd64-.tar.gz**. 5. Unzip the archive: @@ -71,15 +67,13 @@ Tools/Utilities: * [Java on Truffle](/reference-manual/java-on-truffle/) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Enterprise Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible +* [Node.js](/reference-manual/js/) -- Node.js 14.17.6 compatible * [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.3 compatible +* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.4 compatible * [R](/reference-manual/r/) -- GNU R 4.0.3 compatible * [Wasm](/reference-manual/wasm/) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Enterprise base distribution and must be installed separately. -To assist users with installation, GraalVM Enterprise includes -**GraalVM Updater**, a command line utility to install and manage additional -functionalities. Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} -to add any necessary language runtime or utility from above to the GraalVM Enterprise core. +To assist users with installation, GraalVM Enterprise includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. +Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} to add any necessary language runtime or utility from above to the GraalVM Enterprise core. diff --git a/docs/getting-started/graalvm-enterprise/installation-windows.md b/docs/getting-started/graalvm-enterprise/installation-windows.md index 0807a4a50643..06c444287c49 100644 --- a/docs/getting-started/graalvm-enterprise/installation-windows.md +++ b/docs/getting-started/graalvm-enterprise/installation-windows.md @@ -9,7 +9,7 @@ You can install Oracle GraalVM Enterprise Edition on the Windows operating syste Follow these steps: 1. Navigate to [Oracle GraalVM Downloads](https://www.oracle.com/downloads/graalvm-downloads.html). -2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **16** for the Java version, and **Windows** for the operating system. +2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **17** for the Java version, and **Windows** for the operating system. 3. Click on the **GraalVM Enterprise Core** download link. Before you download a file, you must accept the [Oracle License Agreement](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) in the popup window. 4. When the download button becomes active, press it to start downloading graalvm-ee-java-windows-amd64-.zip. 5. Change the directory to the location where you want to install GraalVM Enterprise, then move the _.zip_ archive to it. @@ -40,14 +40,13 @@ The GraalVM Enterprise distribution for Windows platforms includes Oracle JDK wi Currently, the GraalVM Enterprise environment on Windows can be extended with [Native Image](/reference-manual/native-image/), [Java on Trufle](/reference-manual/java-on-truffle/), WebAssembly, and Node.js support. ## Prerequisites for Using Native Image on Windows -To make use of Native Image on Windows, observe the following recommendations. The -required Microsoft Visual C++ (MSVC) version depends on the JDK version that -GraalVM is based on. For GraalVM Enterprise distribution based on JDK 8, you will need MSVC -2010 SP1 version. The recommended installation method is using Microsoft Windows -SDK 7.1: -1. Download the SDK file `GRMSDKX_EN_DVD.iso` for from [Microsoft](https://www.microsoft.com/en-gb/download). -2. Mount the image by opening `F:\Setup\SDKSetup.exe` directly. -For GraalVM Enterprise distribution based on JDK 11, you will need MSVC 2017 15.5.5 or later version. +To start using Native Image on Windows, install Visual Studio Code and Microsoft Visual C++(MSVC). There are two installation options: + * Install the Visual Studio Code Build Tools with the Windows 10 SDK + * Install Visual Studio Code with the Windows 10 SDK -The last prerequisite, common for both distributions, is the proper [Developer Command Prompt](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt_shortcuts) for your version of [Visual Studio](https://visualstudio.microsoft.com/vs/). On Windows the `native-image` tool only works when it is executed from the **x64 Native Tools Command Prompt**. +You can use Visual Studio 2017 version 15.9 or later. + +Lastly, on Windows, the `native-image` builder will only work when it is executed from the **x64 Native Tools Command Prompt**. +The command for initiating an x64 Native Tools command prompt is different if you only have the Visual Studio Build Tools installed, versus if you have the full VS Code 2019 installed. +Check [this link](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311) for step-by-step instructions. From 073bce2ce3f8d591eb8c9c80aee692fbb9333521 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Wed, 6 Oct 2021 15:36:38 +0300 Subject: [PATCH 309/681] Test and review Profiling.md --- .../get-started-graalvm-community.md | 5 +- .../get-started-graalvm-enterprise.md | 4 +- docs/introduction.md | 4 +- docs/tools/profiling.md | 85 ++++++++++--------- 4 files changed, 50 insertions(+), 48 deletions(-) diff --git a/docs/getting-started/graalvm-community/get-started-graalvm-community.md b/docs/getting-started/graalvm-community/get-started-graalvm-community.md index 35a16e43645d..77a7c8537146 100644 --- a/docs/getting-started/graalvm-community/get-started-graalvm-community.md +++ b/docs/getting-started/graalvm-community/get-started-graalvm-community.md @@ -102,9 +102,10 @@ More than 100,000 npm packages are regularly tested and are compatible with Graa To install a Node.js module, use the `npm` executable from the `/bin` folder, which is installed together with `node`. The `npm` command is equivalent to the default Node.js command and supports all Node.js APIs. -Install the `colors` and `ansispan` modules using `npm install`. After the modules are installed, you can use them from your application. +Install the modules `colors`, `ansispan`, and `express` using `npm install`. +After the modules are installed, you can use them from your application. ```shell -$JAVA_HOME/bin/npm install colors ansispan +$JAVA_HOME/bin/npm install colors ansispan express ``` Use the following code snippet and save it as the `app.js` file in the same directory where you installed the Node.js modules: diff --git a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md index 22198e511638..6bb021e65e3a 100644 --- a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md +++ b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md @@ -104,10 +104,10 @@ More than 100,000 npm packages are regularly tested and are compatible with Graa To install a Node.js module, use the `npm` executable from the `/bin` folder, which is installed together with `node`. The `npm` command is equivalent to the default Node.js command and supports all Node.js APIs. -Install the `colors` and `ansispan` modules using `npm install`. +Install the modules `colors`, `ansispan`, and `express` using `npm install`. After the modules are installed, you can use them from your application. ```shell -$JAVA_HOME/bin/npm install colors ansispan +$JAVA_HOME/bin/npm install colors ansispan express ``` Use the following code snippet and save it as the `app.js` file in the same directory where you installed the Node.js modules: diff --git a/docs/introduction.md b/docs/introduction.md index 65ddeb55c202..9309594c05b5 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -90,9 +90,9 @@ Tools/Utilities: Runtimes: -* [Node.js](/reference-manual/js/) -- the Node.js 14.16.1 runtime for JavaScript +* [Node.js](/reference-manual/js/) -- the Node.js 14.17.6 runtime for JavaScript * [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.3 compatible +* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.4 compatible * [R](/reference-manual/r/) -- GNU R 4.0.3 compatible * [GraalWasm](/reference-manual/wasm/) -- WebAssembly (Wasm) diff --git a/docs/tools/profiling.md b/docs/tools/profiling.md index f5cc19a9e5f3..9cf6222bf0cb 100644 --- a/docs/tools/profiling.md +++ b/docs/tools/profiling.md @@ -84,31 +84,31 @@ algorithm. js primes.js --cpusampler Computed 5000 prime numbers. The last 5 are 48563,48571,48589,48593,48611. - ---------------------------------------------------------------------------------------------------- - Sampling Histogram. Recorded 825 samples with period 10ms. + ---------------------------------------------------------------------------------------------- + Sampling Histogram. Recorded 250 samples with period 10ms. Self Time: Time spent on the top of the stack. Total Time: Time spent somewhere on the stack. - ---------------------------------------------------------------------------------------------------- + ---------------------------------------------------------------------------------------------- Thread[main,5,main] - Name | Total Time || Self Time || Location - ---------------------------------------------------------------------------------------------------- - accept | 7330ms 88.8% || 7330ms 88.8% || primes.js~13-22:191-419 - :program | 8250ms 100.0% || 420ms 5.1% || primes.js~1-46:0-982 - next | 7820ms 94.8% || 250ms 3.0% || primes.js~31-37:537-737 - DivisibleByFilter | 440ms 5.3% || 240ms 2.9% || primes.js~7-23:66-421 - AcceptFilter | 20ms 0.2% || 10ms 0.1% || primes.js~1-5:0-63 - Primes | 20ms 0.2% || 0ms 0.0% || primes.js~25-38:424-739 - ---------------------------------------------------------------------------------------------------- + Name || Total Time || Self Time || Location + ---------------------------------------------------------------------------------------------- + accept || 2150ms 86.0% || 2150ms 86.0% || primes.js~13-22:191-419 + next || 2470ms 98.8% || 320ms 12.8% || primes.js~31-37:537-737 + :program || 2500ms 100.0% || 30ms 1.2% || primes.js~1-46:0-982 + ---------------------------------------------------------------------------------------------- ``` + By default the sampler prints an execution time histogram for each JavaScript function. - You can produce a flame graph in SVG format by doing + You can produce a flame graph in SVG format by specifying that with the `--cpusampler.Output=flamegraph` option: + ```shell js primes.js --cpusampler --cpusampler.Output=flamegraph --cpusampler.OutputFile=primes.svg ``` - which should produce something like this - + + It should produce something like this: + ![](img/profiler_flamegraph.png) - + You can zoom into the graph by clicking on elements. By default, CPU sampling takes a sample every 10 milliseconds. From the @@ -129,28 +129,28 @@ algorithm. ``` Now use the CPU Tracer to collect execution counts of each statement: -4. Run `js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=*accept` +4. Run `js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=accept` to collect execution counts for all statements in methods ending with `accept`: ```shell - js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=*accept + js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=accept Computed 5000 prime numbers. The last 5 are 48563,48571,48589,48593,48611. ----------------------------------------------------------------------------------------- - Tracing Histogram. Counted a total of 351278226 element executions. + Tracing Histogram. Counted a total of 468336895 element executions. Total Count: Number of times the element was executed and percentage of total executions. Interpreted Count: Number of times the element was interpreted and percentage of total executions of this element. Compiled Count: Number of times the compiled element was executed and percentage of total executions of this element. ----------------------------------------------------------------------------------------- Name | Total Count | Interpreted Count | Compiled Count | Location ----------------------------------------------------------------------------------------- - accept | 117058669 33.3% | 63575 0.1% | 116995094 99.9% | primes.js~15:245-258 - accept | 117053670 33.3% | 63422 0.1% | 116990248 99.9% | primes.js~16-18:275-348 - accept | 117005061 33.3% | 61718 0.1% | 116943343 99.9% | primes.js~19:362-381 - accept | 53608 0.0% | 1857 3.5% | 51751 96.5% | primes.js~14:215-227 - accept | 53608 0.0% | 1857 3.5% | 51751 96.5% | primes.js~13-22:191-419 - accept | 48609 0.0% | 1704 3.5% | 46905 96.5% | primes.js~17:322-334 - accept | 4999 0.0% | 153 3.1% | 4846 96.9% | primes.js~21:409-412 + accept | 234117338 50.0% | 365660 0.2% | 233751678 99.8% | primes.js~15:245-258 + accept | 117053670 25.0% | 182582 0.2% | 116871088 99.8% | primes.js~16-18:275-348 + accept | 117005061 25.0% | 181001 0.2% | 116824060 99.8% | primes.js~19:362-381 + accept | 53608 0.0% | 1829 3.4% | 51779 96.6% | primes.js~14:211-227 + accept | 53608 0.0% | 1829 3.4% | 51779 96.6% | primes.js~13-22:191-419 + accept | 48609 0.0% | 1581 3.3% | 47028 96.7% | primes.js~17:322-334 + accept | 4999 0.0% | 248 5.0% | 4751 95.0% | primes.js~21:402-413 accept | 1 0.0% | 1 100.0% | 0 0.0% | primes.js~2-4:25-61 - accept | 1 0.0% | 1 100.0% | 0 0.0% | primes.js~3:52-55 + accept | 1 0.0% | 1 100.0% | 0 0.0% | primes.js~3:45-55 ----------------------------------------------------------------------------------------- ``` @@ -166,17 +166,16 @@ be preceded by the `--experimental-options` command line option. js primes.js --experimental-options --memtracer Computed 5000 prime numbers. The last 5 are 48563,48571,48589,48593,48611. ------------------------------------------------------------ - Location Histogram with Allocation Counts. Recorded a total of 5013 allocations. - Total Count: Number of allocations during the execution of this element. - Self Count: Number of allocations in this element alone (excluding sub calls). - ------------------------------------------------------------ - Name | Self Count | Total Count | Location - ------------------------------------------------------------ - next | 5000 99.7% | 5000 99.7% | primes.js~31-37:537-737 - :program | 11 0.2% | 5013 100.0% | primes.js~1-46:0-966 - Primes | 1 0.0% | 1 0.0% | primes.js~25-38:454-739 - ------------------------------------------------------------ - + Location Histogram with Allocation Counts. Recorded a total of 5007 allocations. + Total Count: Number of allocations during the execution of this element. + Self Count: Number of allocations in this element alone (excluding sub calls). + -------------------------------------------------------- + Name | Self Count | Total Count | Location + -------------------------------------------------------- + next | 5000 99.9% | 5000 99.9% | primes.js~31-37:537-737 + :program | 6 0.1% | 5007 100.0% | primes.js~1-46:0-982 + Primes | 1 0.0% | 1 0.0% | primes.js~25-38:424-739 + -------------------------------------------------------- ``` This output shows the number of allocations which were recorded per function. @@ -203,19 +202,20 @@ The current set of available options is as follows: file paths, for example, `*program*.sl`. The default is ∗. - `--cpusampler.FilterLanguage=`: profiles languages only with the matching mime-type, for example, `+`. The default is no filter. +- `--cpusampler.FilterMimeType=`: profiles languages with mime-type. There is no filter by default. - `--cpusampler.FilterRootName=`: applies a wildcard filter for program roots, for example, `Math.*`. The default is ∗. - `--cpusampler.GatherHitTimes`: saves a timestamp for each taken sample. The default is false. +- `--cpusampler.MinSamples=`: removes elements from output if they have less samples than this value (default is `0`). - `--cpusampler.Mode=`: describes the level of sampling detail. Please note that increased detail can lead to reduced accuracy. - `exclude_inlined_roots`: samples roots excluding inlined functions (enabled by default) - `roots`: samples roots including inlined functions - `statements`: samples all statements - `--cpusampler.Output=`: prints a `histogram`, `calltree`, `json`, or `flamegraph` as output. The default is `histogram`. +- `--cpusampler.OutputFile=`: saves output to the given file. Output is printed to output stream by default. - `--cpusampler.Period=`: specifies the period, in milliseconds, to sample the stack. -- `--cpusampler.SampleInternal`: captures internal elements. The default is -false. - `--cpusampler.StackLimit=`: specifies the maximum number of stack elements. - `--cpusampler.SummariseThreads `: prints sampling output as a summary of all `per thread` profiles. The default is false. @@ -227,11 +227,12 @@ elements. file paths, for example, `*program*.sl`. The default is ∗. - `--cputracer.FilterLanguage=`: profiles languages only with the matching mime-type, for example, `+`. The default is no filter. +- `--cputracer.FilterMimeType=`: profiles languages with mime-type. There is no filter by default. - `--cputracer.FilterRootName=`: applies a wildcard filter for program roots, for example, `Math.*`. The default is ∗. - `--cputracer.Output=` prints a `histogram` or `json` as output. The default is `histogram`. +- `--cpusampler.OutputFile=`: saves output to the given file. Output is printed to output stream by default. - `--cputracer.TraceCalls`: captures calls when tracing. The default is false. -- `--cputracer.TraceInternal`: traces internal elements. The default is false. - `--cputracer.TraceRoots=`: captures roots when tracing. The default is true. - `--cputracer.TraceStatements`: captures statements when tracing. The default @@ -244,10 +245,10 @@ The memory tracer tool is currently an experimental tool. Make sure to prepend t - `--memtracer`: enables the memory tracer. Disabled by default. - `--memtracer.FilterFile=`: applies a wildcard filter for source file paths, for example, `*program*.sl`. The default is ∗. - `--memtracer.FilterLanguage=`: profiles languages only with the matching mime-type, for example, `+`. The default is no filter. +- `--memtracer.FilterMimeType=`: profiles languages with mime-type. There is no filter by default. - `--memtracer.FilterRootName=`: applies a wildcard filter for program roots, for example, `Math.*`. The default is ∗. - `--memtracer.Output=`: prints a `typehistogram`, `histogram`, or `calltree` as output. The default is `histogram`. - `--memtracer.StackLimit=`: sets the maximum number of maximum stack elements. - `--memtracer.TraceCalls`: captures calls when tracing. The default is false. -- `--memtracer.TraceInternal`: captures internal elements. The default is false. - `--memtracer.TraceRoots=`: captures roots when tracing. The default is true. - `--memtracer.TraceStatements`: captures statements when tracing. The default is false. From 23989775a8b8457a6aa637da1684a7283fa2ade0 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Mon, 4 Oct 2021 08:56:16 +0200 Subject: [PATCH 310/681] Init context thread locals and notify thread initialization for the thread used in loading pre-initialized context on SVM. --- .../instrumentation/InstrumentAccessor.java | 6 +++ .../InstrumentationHandler.java | 4 ++ .../ContextPreInitializationTest.java | 41 +++++++++++++++++-- .../com/oracle/truffle/api/impl/Accessor.java | 2 + .../truffle/polyglot/PolyglotContextImpl.java | 9 ++++ .../truffle/polyglot/PolyglotEngineImpl.java | 23 +++++++++-- 6 files changed, 78 insertions(+), 7 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentAccessor.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentAccessor.java index bf11a06ce17e..d96d3671754f 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentAccessor.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentAccessor.java @@ -212,6 +212,12 @@ public boolean hasContextBindings(Object engine) { return instrumentationHandler.hasContextBindings(); } + @Override + public boolean hasThreadBindings(Object engine) { + InstrumentationHandler instrumentationHandler = (InstrumentationHandler) engineAccess().getInstrumentationHandler(engine); + return instrumentationHandler.hasThreadBindings(); + } + @Override @CompilerDirectives.TruffleBoundary public void notifyContextCreated(Object engine, TruffleContext context) { diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentationHandler.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentationHandler.java index 6defa6af3175..1ca9ec34bf1c 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentationHandler.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentationHandler.java @@ -960,6 +960,10 @@ boolean hasContextBindings() { return !contextsBindings.isEmpty(); } + boolean hasThreadBindings() { + return !threadsBindings.isEmpty(); + } + void notifyContextCreated(TruffleContext context) { for (EventBinding binding : contextsBindings) { binding.getElement().onContextCreated(context); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java index ea13b05bcd00..14d2b6988597 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java @@ -67,6 +67,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -110,6 +111,8 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.ContextsListener; import com.oracle.truffle.api.instrumentation.EventBinding; +import com.oracle.truffle.api.instrumentation.ThreadsActivationListener; +import com.oracle.truffle.api.instrumentation.ThreadsListener; import com.oracle.truffle.api.instrumentation.TruffleInstrument; import com.oracle.truffle.api.nodes.LanguageInfo; import com.oracle.truffle.api.nodes.RootNode; @@ -2566,6 +2569,8 @@ public abstract static class BaseInstrument extends TruffleInstrument implements private EventBinding verifyContextLocalBinding; final ContextLocal contextLocal = createContextLocal((c) -> c); + final ContextThreadLocal contextThreadLocal = createContextThreadLocal((c, t) -> c); + private final Set> initializedThreads = Collections.newSetFromMap(new ConcurrentHashMap<>()); @Override protected void onCreate(Env env) { @@ -2576,16 +2581,17 @@ protected void onCreate(Env env) { public void onLanguageContextInitialized(TruffleContext context, LanguageInfo language) { assertSame(context, contextLocal.get(context)); + assertSame(context, contextThreadLocal.get(context)); } public void onLanguageContextFinalized(TruffleContext context, LanguageInfo language) { assertSame(context, contextLocal.get(context)); - + assertSame(context, contextThreadLocal.get(context)); } public void onLanguageContextCreated(TruffleContext context, LanguageInfo language) { assertSame(context, contextLocal.get(context)); - + assertSame(context, contextThreadLocal.get(context)); } public void onContextCreated(TruffleContext context) { @@ -2594,15 +2600,43 @@ public void onContextCreated(TruffleContext context) { public void onLanguageContextDisposed(TruffleContext context, LanguageInfo language) { assertSame(context, contextLocal.get(context)); + assertSame(context, contextThreadLocal.get(context)); } public void onContextClosed(TruffleContext context) { assertSame(context, contextLocal.get(context)); - + assertSame(context, contextThreadLocal.get(context)); } }, false); performAction(null, null); } + env.getInstrumenter().attachThreadsActivationListener(new ThreadsActivationListener() { + @Override + public void onEnterThread(TruffleContext context) { + // tests that locals are initialized + contextLocal.get(context); + contextThreadLocal.get(context); + } + + @Override + public void onLeaveThread(TruffleContext context) { + // tests that locals are initialized + contextLocal.get(context); + contextThreadLocal.get(context); + } + }); + env.getInstrumenter().attachThreadsListener(new ThreadsListener() { + @Override + public void onThreadInitialized(TruffleContext context, Thread thread) { + assertTrue(initializedThreads.add(Pair.create(context, thread))); + } + + @Override + public void onThreadDisposed(TruffleContext context, Thread thread) { + // tests that onThreadInitialized was called + assertTrue(initializedThreads.contains(Pair.create(context, thread))); + } + }, true); } @Override @@ -2687,6 +2721,7 @@ protected OptionDescriptors getOptionDescriptors() { protected Map> getActions() { return actions; } + } @TruffleInstrument.Registration(id = ContextPreInitializationSecondInstrument.ID, name = ContextPreInitializationSecondInstrument.ID, services = Service.class) diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java index 1f7bb14dfd15..e8c5f01fd732 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java @@ -836,6 +836,8 @@ public final OutputStream getOut(DispatchOutputStream out) { public abstract boolean hasContextBindings(Object engine); + public abstract boolean hasThreadBindings(Object engine); + public abstract void notifyContextCreated(Object engine, TruffleContext context); public abstract void notifyContextClosed(Object engine, TruffleContext context); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java index f39903316827..7c086788c8cd 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java @@ -2616,6 +2616,14 @@ void initializeInstrumentContextLocals(Object[] locals) { } } + void initializeInstrumentContextThreadLocals() { + for (PolyglotInstrument instrument : engine.idToInstrument.values()) { + if (instrument.isCreated()) { + invokeContextThreadLocalFactory(instrument.contextThreadLocalLocations); + } + } + } + /** * Updates the current thread locals from {@link PolyglotThreadInfo#contextThreadLocals}. */ @@ -2758,6 +2766,7 @@ void initializeHostContext(PolyglotLanguageContext context, PolyglotContextConfi void replayInstrumentationEvents() { notifyContextCreated(); + EngineAccessor.INSTRUMENT.notifyThreadStarted(engine, creatorTruffleContext, Thread.currentThread()); for (PolyglotLanguageContext lc : contexts) { LanguageInfo language = lc.language.info; if (lc.eventsEnabled && lc.env != null) { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java index 7936693f072c..c067870b1239 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java @@ -1635,12 +1635,23 @@ public PolyglotContextImpl createContext(OutputStream configOut, OutputStream co throw PolyglotImpl.guestToHostException(this, t); } boolean hasContextBindings; + boolean hasThreadBindings; try { if (replayEvents) { // loaded context - // we might have new instruments to run with a preinitialized context + /* + * There might be new instruments to run with a preinitialized context and these + * instruments might define context locals and context thread locals. The + * instruments were created during the context loading before the context was added + * to the engine's contexts set, and so the instrument creation did not update the + * context's locals and thread locals. Since the context loading needs to enter the + * context on the current thread for patching, we need to update both the context + * locals and context thread locals. + */ synchronized (context) { context.resizeContextLocals(this.contextLocalLocations); context.initializeInstrumentContextLocals(context.contextLocals); + context.resizeContextThreadLocals(this.contextThreadLocalLocations); + context.initializeInstrumentContextThreadLocals(); } } else { // is new context try { @@ -1661,12 +1672,16 @@ public PolyglotContextImpl createContext(OutputStream configOut, OutputStream co } } hasContextBindings = EngineAccessor.INSTRUMENT.hasContextBindings(this); + hasThreadBindings = EngineAccessor.INSTRUMENT.hasThreadBindings(this); } catch (Throwable t) { throw PolyglotImpl.guestToHostException(context.getHostContext(), t, false); } - if (replayEvents && hasContextBindings) { - // replace events for preinitialized contexts - // events must be replayed without engine lock. + if (replayEvents && (hasContextBindings || hasThreadBindings)) { + /* + * Replay events for preinitialized contexts. Events must be replayed without engine + * lock. The events to replay are the context events and also the thread initialization + * event for the current thread which was initialized for context patching. + */ final Object[] prev; try { prev = enter(context); From d14b93a3eb4c866104afa22cb6865ce0f2a51cf0 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Wed, 6 Oct 2021 15:36:34 +0200 Subject: [PATCH 311/681] Change prefetch options to useful defaults. --- .../com/oracle/svm/core/SubstrateOptions.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) 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 cd99fbebf10f..6518ee812b57 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 @@ -278,7 +278,7 @@ public Boolean getValue(OptionValues values) { * Object and array allocation options. */ @Option(help = "Number of cache lines to load after the array allocation using prefetch instructions.")// - public static final HostedOptionKey AllocatePrefetchLines = new HostedOptionKey<>(3); + public static final HostedOptionKey AllocatePrefetchLines = new HostedOptionKey<>(4); @Option(help = "Number of cache lines to load after the object address using prefetch instructions.")// public static final HostedOptionKey AllocateInstancePrefetchLines = new HostedOptionKey<>(1); @@ -289,6 +289,14 @@ public Boolean getValue(OptionValues values) { @Option(help = "Sets the prefetch instruction to prefetch ahead of the allocation pointer. Possible values are from 0 to 3. The actual instructions behind the values depend on the platform.")// public static final HostedOptionKey AllocatePrefetchInstr = new HostedOptionKey<>(0); + @Option(help = "Sets the size (in bytes) of the prefetch distance for object allocation. " + + "Memory about to be written with the value of new objects is prefetched up to this distance starting from the address of the last allocated object. " + + "Each Java thread has its own allocation point.")// + public static final HostedOptionKey AllocatePrefetchDistance = new HostedOptionKey<>(192); + + @Option(help = "Sets the step size (in bytes) for sequential prefetch instructions.")// + public static final HostedOptionKey AllocatePrefetchStepSize = new HostedOptionKey<>(64); + /* * Isolate tear down options. */ @@ -307,17 +315,6 @@ public static final long getTearDownFailureNanos() { return TearDownFailureNanos.getValue().longValue(); } - /* - * The default value is derived by taking the common value from HotSpot configs. - */ - @Option(help = "Sets the size (in bytes) of the prefetch distance for object allocation. " + - "Memory about to be written with the value of new objects is prefetched up to this distance starting from the address of the last allocated object. " + - "Each Java thread has its own allocation point.")// - public static final HostedOptionKey AllocatePrefetchDistance = new HostedOptionKey<>(256); - - @Option(help = "Sets the step size (in bytes) for sequential prefetch instructions.")// - public static final HostedOptionKey AllocatePrefetchStepSize = new HostedOptionKey<>(16); - @Option(help = "Define the maximum number of stores for which the loop that zeroes out objects is unrolled.")// public static final HostedOptionKey MaxUnrolledObjectZeroingStores = new HostedOptionKey<>(8); From ab7e1d02b6ffc82273e1f383fda3ef715fef4e5e Mon Sep 17 00:00:00 2001 From: "thomas.garcia" Date: Wed, 6 Oct 2021 17:38:37 +0200 Subject: [PATCH 312/681] Move thread implementation around, and provide a new class for accessing threads --- .../truffle/espresso/descriptors/Symbol.java | 4 +- .../truffle/espresso/impl/ContextAccess.java | 7 +- .../espresso/impl/LinkedKlassFieldLayout.java | 4 +- .../oracle/truffle/espresso/meta/Meta.java | 8 +- .../truffle/espresso/nodes/BytecodeNode.java | 9 +- .../espresso/runtime/EspressoContext.java | 45 +- .../runtime/EspressoReferenceDrainer.java | 2 +- .../runtime/EspressoShutdownHandler.java | 28 +- .../espresso/runtime/JDWPContextImpl.java | 10 +- .../Target_java_lang_Thread.java | 417 ++---------------- .../substitutions/Target_sun_misc_Unsafe.java | 10 +- .../EspressoThreadRegistry.java} | 40 +- .../espresso/threads/GuestRunnable.java | 67 +++ .../truffle/espresso/threads/KillStatus.java | 49 ++ .../truffle/espresso/threads/State.java | 39 ++ .../truffle/espresso/threads/SuspendLock.java | 101 +++++ .../espresso/threads/ThreadsAccess.java | 379 ++++++++++++++++ .../truffle/espresso/vm/InterpreterToVM.java | 5 +- .../truffle/espresso/vm/Management.java | 11 +- .../com/oracle/truffle/espresso/vm/VM.java | 18 +- 20 files changed, 773 insertions(+), 480 deletions(-) rename espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/{runtime/EspressoThreadManager.java => threads/EspressoThreadRegistry.java} (91%) create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/GuestRunnable.java create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/KillStatus.java create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/State.java create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/SuspendLock.java create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/Symbol.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/Symbol.java index bd5065d04d3e..32f295559606 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/Symbol.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/Symbol.java @@ -503,11 +503,9 @@ public static void ensureInitialized() { // Thread public static final Symbol interrupted = StaticSymbols.putName("interrupted"); public static final Symbol interrupt = StaticSymbols.putName("interrupt"); - public static final Symbol HIDDEN_DEATH = StaticSymbols.putName("0HIDDEN_DEATH"); - public static final Symbol HIDDEN_DEATH_THROWABLE = StaticSymbols.putName("0HIDDEN_DEATH_THROWABLE"); + public static final Symbol HIDDEN_DEPRECATION_SUPPORT = StaticSymbols.putName("0HIDDEN_DEPRECATION_SUPPORT"); public static final Symbol HIDDEN_HOST_THREAD = StaticSymbols.putName("0HIDDEN_HOST_THREAD"); public static final Symbol HIDDEN_INTERRUPTED = StaticSymbols.putName("0HIDDEN_INTERRUPTED"); - public static final Symbol HIDDEN_SUSPEND_LOCK = StaticSymbols.putName("0HIDDEN_SUSPEND_LOCK"); public static final Symbol HIDDEN_THREAD_BLOCKED_OBJECT = StaticSymbols.putName("0HIDDEN_THREAD_BLOCKED_OBJECT"); public static final Symbol HIDDEN_THREAD_BLOCKED_COUNT = StaticSymbols.putName("0HIDDEN_THREAD_BLOCKED_COUNT"); public static final Symbol HIDDEN_THREAD_WAITED_COUNT = StaticSymbols.putName("0HIDDEN_THREAD_WAITED_COUNT"); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ContextAccess.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ContextAccess.java index c98a05eb2ed5..1c278f219b5e 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ContextAccess.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ContextAccess.java @@ -23,15 +23,16 @@ package com.oracle.truffle.espresso.impl; import com.oracle.truffle.espresso.EspressoLanguage; -import com.oracle.truffle.espresso.ffi.NativeAccess; import com.oracle.truffle.espresso.descriptors.Names; import com.oracle.truffle.espresso.descriptors.Signatures; import com.oracle.truffle.espresso.descriptors.Types; +import com.oracle.truffle.espresso.ffi.NativeAccess; import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.runtime.EspressoContext; import com.oracle.truffle.espresso.runtime.JavaVersion; import com.oracle.truffle.espresso.runtime.StringTable; import com.oracle.truffle.espresso.substitutions.Substitutions; +import com.oracle.truffle.espresso.threads.ThreadsAccess; import com.oracle.truffle.espresso.vm.InterpreterToVM; import com.oracle.truffle.espresso.vm.VM; @@ -62,6 +63,10 @@ default VM getVM() { return getContext().getVM(); } + default ThreadsAccess getThreadAccess() { + return getContext().getThreadAccess(); + } + default InterpreterToVM getInterpreterToVM() { return getContext().getInterpreterToVM(); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/LinkedKlassFieldLayout.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/LinkedKlassFieldLayout.java index 7b296f56ce86..f485582cdb55 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/LinkedKlassFieldLayout.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/LinkedKlassFieldLayout.java @@ -248,9 +248,7 @@ private static HiddenField[] getHiddenFieldsFull(Symbol holder) { return new HiddenField[]{ new HiddenField(Name.HIDDEN_INTERRUPTED, Type._boolean, VersionRange.lower(13)), new HiddenField(Name.HIDDEN_HOST_THREAD), - new HiddenField(Name.HIDDEN_DEATH), - new HiddenField(Name.HIDDEN_DEATH_THROWABLE), - new HiddenField(Name.HIDDEN_SUSPEND_LOCK), + new HiddenField(Name.HIDDEN_DEPRECATION_SUPPORT), // Only used for j.l.management bookkeeping. new HiddenField(Name.HIDDEN_THREAD_BLOCKED_OBJECT), diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java index 334df63f54bd..325a709d3d72 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java @@ -359,9 +359,7 @@ public Meta(EspressoContext context) { .field(higher(14), Name.interrupted, Type._boolean) // .maybeHiddenfield(java_lang_Thread); HIDDEN_HOST_THREAD = java_lang_Thread.requireHiddenField(Name.HIDDEN_HOST_THREAD); - HIDDEN_DEATH = java_lang_Thread.requireHiddenField(Name.HIDDEN_DEATH); - HIDDEN_DEATH_THROWABLE = java_lang_Thread.requireHiddenField(Name.HIDDEN_DEATH_THROWABLE); - HIDDEN_SUSPEND_LOCK = java_lang_Thread.requireHiddenField(Name.HIDDEN_SUSPEND_LOCK); + HIDDEN_DEPRECATION_SUPPORT = java_lang_Thread.requireHiddenField(Name.HIDDEN_DEPRECATION_SUPPORT); if (context.EnableManagement) { HIDDEN_THREAD_BLOCKED_OBJECT = java_lang_Thread.requireHiddenField(Name.HIDDEN_THREAD_BLOCKED_OBJECT); @@ -1171,9 +1169,7 @@ private DiffVersionLoadHelper diff() { public final Method java_lang_Thread_stop; public final Field HIDDEN_HOST_THREAD; public final Field HIDDEN_INTERRUPTED; - public final Field HIDDEN_DEATH; - public final Field HIDDEN_DEATH_THROWABLE; - public final Field HIDDEN_SUSPEND_LOCK; + public final Field HIDDEN_DEPRECATION_SUPPORT; public final Field HIDDEN_THREAD_BLOCKED_OBJECT; public final Field HIDDEN_THREAD_BLOCKED_COUNT; public final Field HIDDEN_THREAD_WAITED_COUNT; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/BytecodeNode.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/BytecodeNode.java index 6dd3394b3748..dfc308c92617 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/BytecodeNode.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/BytecodeNode.java @@ -257,11 +257,11 @@ import com.oracle.truffle.api.instrumentation.StandardTags.StatementTag; import com.oracle.truffle.api.instrumentation.Tag; import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.nodes.BytecodeOSRNode; import com.oracle.truffle.api.nodes.ControlFlowException; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.LoopNode; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.nodes.BytecodeOSRNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.espresso.analysis.liveness.LivenessAnalysis; @@ -339,7 +339,6 @@ import com.oracle.truffle.espresso.runtime.EspressoExitException; import com.oracle.truffle.espresso.runtime.ReturnAddress; import com.oracle.truffle.espresso.runtime.StaticObject; -import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread; import com.oracle.truffle.espresso.vm.InterpreterToVM; /** @@ -1783,7 +1782,7 @@ private int beforeJumpChecks(long[] primitives, Object[] refs, int curBCI, int t CompilerAsserts.partialEvaluationConstant(targetBCI); int nextStatementIndex = (instrument == null) ? 0 : instrument.getStatementIndexAfterJump(statementIndex, curBCI, targetBCI); if (targetBCI <= curBCI) { - checkStopping(); + checkDeprecation(); if (++loopCount[0] >= REPORT_LOOP_STRIDE) { LoopNode.reportLoopCount(this, REPORT_LOOP_STRIDE); loopCount[0] = 0; @@ -1814,9 +1813,9 @@ private int beforeJumpChecks(long[] primitives, Object[] refs, int curBCI, int t return nextStatementIndex; } - private void checkStopping() { + private void checkDeprecation() { if (getContext().shouldCheckDeprecationStatus()) { - Target_java_lang_Thread.checkDeprecatedState(getMeta(), getContext().getCurrentThread()); + getContext().getThreadAccess().checkDeprecation(); } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java index 70771e74d2e5..623c999921d0 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java @@ -89,7 +89,8 @@ import com.oracle.truffle.espresso.perf.TimerCollection; import com.oracle.truffle.espresso.redefinition.plugins.api.InternalRedefinitionPlugin; import com.oracle.truffle.espresso.substitutions.Substitutions; -import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread; +import com.oracle.truffle.espresso.threads.EspressoThreadRegistry; +import com.oracle.truffle.espresso.threads.ThreadsAccess; import com.oracle.truffle.espresso.vm.InterpreterToVM; import com.oracle.truffle.espresso.vm.UnsafeAccess; import com.oracle.truffle.espresso.vm.VM; @@ -132,7 +133,8 @@ public final class EspressoContext { // endregion Runtime // region Helpers - private final EspressoThreadManager threadManager; + private final EspressoThreadRegistry threadRegistry; + @CompilationFinal private ThreadsAccess threads; private final EspressoShutdownHandler shutdownManager; private final EspressoReferenceDrainer referenceDrainer; // endregion Helpers @@ -247,12 +249,12 @@ public EspressoContext(TruffleLanguage.Env env, EspressoLanguage language) { this.substitutions = new Substitutions(this); this.methodHandleIntrinsics = new MethodHandleIntrinsics(this); - this.threadManager = new EspressoThreadManager(this); + this.threadRegistry = new EspressoThreadRegistry(this); this.referenceDrainer = new EspressoReferenceDrainer(this); boolean softExit = env.getOptions().get(EspressoOptions.SoftExit); this.ExitHost = env.getOptions().get(EspressoOptions.ExitHost); - this.shutdownManager = new EspressoShutdownHandler(this, threadManager, referenceDrainer, softExit); + this.shutdownManager = new EspressoShutdownHandler(this, threadRegistry, referenceDrainer, softExit); this.timers = TimerCollection.create(env.getOptions().get(EspressoOptions.EnableTimers)); this.allocationReporter = env.lookup(AllocationReporter.class); @@ -477,6 +479,7 @@ private void spawnVM() { this.meta = new Meta(this); } this.metaInitialized = true; + this.threads = new ThreadsAccess(meta); this.interpreterToVM = new InterpreterToVM(this); @@ -499,7 +502,7 @@ private void spawnVM() { } // Create main thread as soon as Thread class is initialized. - threadManager.createMainThread(meta); + threadRegistry.createMainThread(meta); try (DebugCloseable knownClassInit = KNOWN_CLASS_INIT.scope(timers)) { initializeKnownClass(Type.java_lang_Object); @@ -775,15 +778,19 @@ public TruffleObject bindToAgent(Method method, String mangledName) { // region Thread management + public ThreadsAccess getThreadAccess() { + return threads; + } + /** * Creates a new guest thread from the host thread, and adds it to the main thread group. */ public StaticObject createThread(Thread hostThread) { - return threadManager.createGuestThreadFromHost(hostThread, meta, vm); + return threadRegistry.createGuestThreadFromHost(hostThread, meta, vm); } public StaticObject createThread(Thread hostThread, StaticObject group, String name) { - return threadManager.createGuestThreadFromHost(hostThread, meta, vm, name, group); + return threadRegistry.createGuestThreadFromHost(hostThread, meta, vm, name, group); } public void disposeThread(@SuppressWarnings("unused") Thread hostThread) { @@ -792,7 +799,7 @@ public void disposeThread(@SuppressWarnings("unused") Thread hostThread) { return; } if (hostThread != Thread.currentThread()) { - String guestName = Target_java_lang_Thread.getThreadName(meta, guestThread); + String guestName = threads.getThreadName(guestThread); getLogger().warning("unimplemented: disposeThread for non-current thread: " + hostThread + " / " + guestName); return; } @@ -802,47 +809,47 @@ public void disposeThread(@SuppressWarnings("unused") Thread hostThread) { } public StaticObject getGuestThreadFromHost(Thread host) { - return threadManager.getGuestThreadFromHost(host); + return threadRegistry.getGuestThreadFromHost(host); } public StaticObject getCurrentThread() { - return threadManager.getGuestThreadFromHost(Thread.currentThread()); + return threadRegistry.getGuestThreadFromHost(Thread.currentThread()); } /** * Returns the maximum number of alive (registered) threads at any point, since the VM started. */ public long getPeakThreadCount() { - return threadManager.peakThreadCount.get(); + return threadRegistry.peakThreadCount.get(); } /** * Returns the number of created threads since the VM started. */ public long getCreatedThreadCount() { - return threadManager.createdThreadCount.get(); + return threadRegistry.createdThreadCount.get(); } public StaticObject[] getActiveThreads() { - return threadManager.activeThreads(); + return threadRegistry.activeThreads(); } public void registerThread(Thread host, StaticObject self) { - threadManager.registerThread(host, self); + threadRegistry.registerThread(host, self); if (shouldReportVMEvents) { eventListener.threadStarted(self); } } public void unregisterThread(StaticObject self) { - threadManager.unregisterThread(self); + threadRegistry.unregisterThread(self); if (shouldReportVMEvents) { eventListener.threadDied(self); } } public void interruptThread(StaticObject guestThread) { - threadManager.interruptThread(guestThread); + threadRegistry.interruptThread(guestThread); } public void invalidateNoThreadStop(String message) { @@ -868,15 +875,15 @@ public boolean shouldCheckSuspend() { } public boolean isMainThreadCreated() { - return threadManager.isMainThreadCreated(); + return threadRegistry.isMainThreadCreated(); } public StaticObject getMainThread() { - return threadManager.getMainThread(); + return threadRegistry.getMainThread(); } public StaticObject getMainThreadGroup() { - return threadManager.getMainThreadGroup(); + return threadRegistry.getMainThreadGroup(); } // endregion Thread management diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoReferenceDrainer.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoReferenceDrainer.java index cf862476da4f..c1dddc5bfdb0 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoReferenceDrainer.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoReferenceDrainer.java @@ -207,7 +207,7 @@ public void run() { } } } finally { - Target_java_lang_Thread.terminate(context.getCurrentThread(), meta); + context.getThreadAccess().terminate(context.getCurrentThread()); if (context.isClosing()) { // Ignore exceptions that arise during closing. return; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoShutdownHandler.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoShutdownHandler.java index c5974e0936a6..5106a102a7c7 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoShutdownHandler.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoShutdownHandler.java @@ -26,15 +26,14 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.espresso.impl.ContextAccess; import com.oracle.truffle.espresso.meta.EspressoError; -import com.oracle.truffle.espresso.meta.Meta; -import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread; +import com.oracle.truffle.espresso.threads.EspressoThreadRegistry; class EspressoShutdownHandler implements ContextAccess { // region context private final EspressoContext context; - private final EspressoThreadManager threadManager; + private final EspressoThreadRegistry threadManager; private final EspressoReferenceDrainer referenceDrainer; private final boolean softExit; @@ -46,7 +45,7 @@ public EspressoContext getContext() { // endregion context EspressoShutdownHandler(EspressoContext context, - EspressoThreadManager threadManager, + EspressoThreadRegistry threadManager, EspressoReferenceDrainer referenceDrainer, boolean softExit) { this.context = context; this.threadManager = threadManager; @@ -110,9 +109,8 @@ Object getShutdownSynchronizer() { @TruffleBoundary void doExit(int code) { getContext().getLogger().fine(() -> { - Meta meta = getMeta(); StaticObject currentThread = getContext().getCurrentThread(); - String guestName = Target_java_lang_Thread.getThreadName(meta, currentThread); + String guestName = getThreadAccess().getThreadName(currentThread); return "doExit(" + code + ") from " + guestName; }); if (!isClosing()) { @@ -197,7 +195,7 @@ private void waitForClose() throws EspressoExitException { private boolean hasActiveNonDaemon(Thread initiating) { for (StaticObject guest : threadManager.activeThreads()) { - Thread host = Target_java_lang_Thread.getHostFromGuestThread(guest); + Thread host = getThreadAccess().getHost(guest); if (host != initiating && !host.isDaemon()) { if (host.isAlive()) { return true; @@ -262,10 +260,10 @@ private void teardown(boolean killThreads) { */ private void teardownPhase1(Thread initiatingThread) { for (StaticObject guest : threadManager.activeThreads()) { - Thread t = Target_java_lang_Thread.getHostFromGuestThread(guest); + Thread t = getThreadAccess().getHost(guest); if (t.isAlive() && t != initiatingThread) { if (t.isDaemon()) { - Target_java_lang_Thread.killThread(guest); + context.getThreadAccess().stop(guest, null); } threadManager.interruptThread(guest); } @@ -278,9 +276,9 @@ private void teardownPhase1(Thread initiatingThread) { */ private void teardownPhase2(Thread initiatingThread) { for (StaticObject guest : threadManager.activeThreads()) { - Thread t = Target_java_lang_Thread.getHostFromGuestThread(guest); + Thread t = getThreadAccess().getHost(guest); if (t.isAlive() && t != initiatingThread) { - Target_java_lang_Thread.killThread(guest); + context.getThreadAccess().stop(guest, null); threadManager.interruptThread(guest); } } @@ -293,14 +291,14 @@ private void teardownPhase2(Thread initiatingThread) { */ private void teardownPhase3(Thread initiatingThread) { for (StaticObject guest : threadManager.activeThreads()) { - Thread t = Target_java_lang_Thread.getHostFromGuestThread(guest); + Thread t = getThreadAccess().getHost(guest); if (t.isAlive() && t != initiatingThread) { /* * Currently, threads in native can not be killed in Espresso. This translates into * a polyglot-side java.lang.IllegalStateException: The language did not complete * all polyglot threads but should have. */ - Target_java_lang_Thread.forceKillThread(guest); + context.getThreadAccess().kill(guest); threadManager.interruptThread(guest); } } @@ -311,7 +309,7 @@ private void teardownPhase3(Thread initiatingThread) { */ private void teardownPhase4(Thread initiatingThread) { for (StaticObject guest : threadManager.activeThreads()) { - Thread t = Target_java_lang_Thread.getHostFromGuestThread(guest); + Thread t = getThreadAccess().getHost(guest); if (t.isAlive() && t != initiatingThread) { // TODO(garcia): Tell truffle to forget about this thread // Or @@ -334,7 +332,7 @@ private boolean waitSpin(Thread initiatingThread) { return false; } for (StaticObject guest : threadManager.activeThreads()) { - Thread t = Target_java_lang_Thread.getHostFromGuestThread(guest); + Thread t = getThreadAccess().getHost(guest); if (t != initiatingThread) { if (t.isAlive()) { continue spinLoop; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java index 8a9adc3a2b3d..40a15b291a04 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java @@ -75,7 +75,7 @@ import com.oracle.truffle.espresso.redefinition.RedefintionNotSupportedException; import com.oracle.truffle.espresso.redefinition.plugins.impl.RedefinitionPluginHandler; import com.oracle.truffle.espresso.runtime.dispatch.EspressoInterop; -import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread; +import com.oracle.truffle.espresso.threads.State; public final class JDWPContextImpl implements JDWPContext { @@ -129,7 +129,7 @@ public boolean isValidThread(Object thread, boolean checkTerminated) { if (context.getMeta().java_lang_Thread.isAssignableFrom(staticObject.getKlass())) { if (checkTerminated) { // check if thread has been terminated - return getThreadStatus(thread) != Target_java_lang_Thread.State.TERMINATED.value; + return getThreadStatus(thread) != State.TERMINATED.value; } return true; } @@ -252,7 +252,7 @@ public Object asGuestThread(Thread hostThread) { @Override public Thread asHostThread(Object thread) { - return Target_java_lang_Thread.getHostFromGuestThread((StaticObject) thread); + return context.getThreadAccess().getHost((StaticObject) thread); } @Override @@ -367,7 +367,7 @@ private static boolean isBoxedPrimitive(Class clazz) { @Override public String getThreadName(Object thread) { - return Target_java_lang_Thread.getThreadName(context.getMeta(), (StaticObject) thread); + return context.getThreadAccess().getThreadName((StaticObject) thread); } @Override @@ -543,7 +543,7 @@ public boolean isInstanceOf(Object object, KlassRef klass) { @Override public void stopThread(Object guestThread, Object guestThrowable) { - Target_java_lang_Thread.stop0((StaticObject) guestThread, (StaticObject) guestThrowable); + context.getThreadAccess().stop((StaticObject) guestThread, (StaticObject) guestThrowable); } @Override diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_Thread.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_Thread.java index a5586730767f..d4f9d3954653 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_Thread.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_Thread.java @@ -33,12 +33,11 @@ import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.espresso.impl.Field; import com.oracle.truffle.espresso.impl.Klass; -import com.oracle.truffle.espresso.meta.EspressoError; import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.runtime.EspressoContext; -import com.oracle.truffle.espresso.runtime.EspressoException; -import com.oracle.truffle.espresso.runtime.EspressoExitException; import com.oracle.truffle.espresso.runtime.StaticObject; +import com.oracle.truffle.espresso.threads.State; +import com.oracle.truffle.espresso.threads.ThreadsAccess; // @formatter:off /** @@ -82,74 +81,6 @@ public static long getThreadCounter(StaticObject thread, Field hiddenField) { return atomicCounter.get(); } - public enum State { - NEW(0), - RUNNABLE(4), - BLOCKED(1024), - WAITING(16), - TIMED_WAITING(32), - TERMINATED(2); - - public final int value; - - State(int value) { - this.value = value; - } - - } - - public static void fromRunnable(StaticObject self, Meta meta, State state) { - assert meta.java_lang_Thread_threadStatus.getInt(self) == State.RUNNABLE.value; - setState(self, meta, state); - checkDeprecatedState(meta, self); - } - - public static void toRunnable(StaticObject self, Meta meta, State state) { - assert state == State.RUNNABLE; - try { - checkDeprecatedState(meta, self); - } finally { - setState(self, meta, state); - } - } - - private static void setState(StaticObject self, Meta meta, State state) { - meta.java_lang_Thread_threadStatus.setInt(self, state.value); - } - - @TruffleBoundary - public static void checkDeprecatedState(Meta meta, StaticObject thread) { - EspressoContext context = meta.getContext(); - assert thread == context.getCurrentThread(); - if (context.shouldCheckStop()) { - KillStatus status = getKillStatus(thread); - switch (status) { - case NORMAL: - case EXITING: - case KILLED: - break; - case KILL: - if (context.isClosing()) { - // Give some leeway during closing. - setThreadStop(thread, KillStatus.KILLED); - } else { - setThreadStop(thread, KillStatus.NORMAL); - } - // check if death cause throwable is set, if not throw ThreadDeath - StaticObject deathThrowable = (StaticObject) getDeathThrowable(thread); - throw deathThrowable != null ? meta.throwException(deathThrowable) : meta.throwException(meta.java_lang_ThreadDeath); - case SHUTDOWN: - // This thread refuses to stop. Send a host exception. - // throw getMeta().throwEx(ThreadDeath.class); - assert context.isClosing(); - throw new EspressoExitException(context.getExitStatus()); - } - } - if (context.shouldCheckSuspend()) { - trySuspend(thread); - } - } - @Substitution(isTrivial = true) public static @JavaType(Thread.class) StaticObject currentThread(@Inject EspressoContext context) { return context.getCurrentThread(); @@ -182,72 +113,28 @@ abstract static class Start0 extends SubstitutionNode { @TruffleBoundary void doCached(@JavaType(Thread.class) StaticObject self, @Bind("getContext()") EspressoContext context, - @Cached("create(context.getMeta().java_lang_Thread_exit.getCallTarget())") DirectCallNode threadExit) { + @Cached("create(context.getMeta().java_lang_Thread_exit.getCallTarget())") DirectCallNode threadExit, + @Cached("create(context.getMeta().java_lang_Thread_dispatchUncaughtException.getCallTarget())") DirectCallNode dispatchUncaught) { Meta meta = context.getMeta(); + ThreadsAccess threadAccess = context.getThreadAccess(); if (context.multiThreadingEnabled()) { // Thread.start() is synchronized. - KillStatus killStatus = getKillStatus(self); - if (killStatus != null || context.isClosing()) { - - self.getLock().lock(); - try { - meta.java_lang_Thread_threadStatus.setInt(self, State.TERMINATED.value); - // Notify waiting threads you were terminated - self.getLock().signalAll(); - } finally { - self.getLock().unlock(); - } - + if (threadAccess.isStillborn(self)) { + threadAccess.terminateAndNotify(self); return; } - setThreadStop(self, KillStatus.NORMAL); - if (getSuspendLock(self) == null) { - initSuspendLock(self); - } - Thread hostThread = context.getEnv().createThread(new Runnable() { - @Override - public void run() { - try { - context.getVM().attachThread(Thread.currentThread()); - try { - // Execute the payload - self.getKlass().vtableLookup(meta.java_lang_Thread_run.getVTableIndex()).invokeDirect(self); - checkDeprecatedState(meta, self); - } catch (EspressoException uncaught) { - meta.java_lang_Thread_dispatchUncaughtException.invokeDirect(self, uncaught.getExceptionObject()); - } - } catch (EspressoExitException exit) { - /* Suppress */ - } finally { - terminate(self, threadExit, meta); - if (context.isClosing()) { - // Ignore exceptions that arise during closing. - return; - } - } - } - }); - - meta.HIDDEN_HOST_THREAD.setHiddenObject(self, hostThread); - hostThread.setDaemon(meta.java_lang_Thread_daemon.getBoolean(self)); - meta.java_lang_Thread_threadStatus.setInt(self, State.RUNNABLE.value); - hostThread.setPriority(meta.java_lang_Thread_priority.getInt(self)); - if (isInterrupted(self, false)) { - hostThread.interrupt(); - } - context.registerThread(hostThread, self); - String guestName = Target_java_lang_Thread.getThreadName(meta, self); + Thread hostThread = threadAccess.createJavaThread(self, threadExit, dispatchUncaught); context.getLogger().fine(() -> { - long guestId = Target_java_lang_Thread.getThreadId(meta, self); + String guestName = threadAccess.getThreadName(self); + long guestId = threadAccess.getThreadId(self); return String.format("Thread.start0: [HOST:%s, %d], [GUEST:%s, %d]", hostThread.getName(), hostThread.getId(), guestName, guestId); }); - hostThread.setName(guestName); hostThread.start(); } else { String reason = context.getMultiThreadingDisabledReason(); Klass threadKlass = self.getKlass(); EspressoContext.get(null).getLogger().warning(() -> { - String guestName = Target_java_lang_Thread.getThreadName(meta, self); + String guestName = threadAccess.getThreadName(self); String className = threadKlass.getExternalName(); return "Thread.start() called on " + className + " / " + guestName + " but thread support is disabled: " + reason; }); @@ -270,51 +157,6 @@ private static boolean isSystemInnocuousThread(StaticObject thread, Meta meta) { return true; } - public static void terminate(StaticObject thread, Meta meta) { - terminate(thread, null, meta); - } - - private static void terminate(@JavaType(Thread.class) StaticObject self, DirectCallNode threadExit, Meta meta) { - setThreadStop(self, KillStatus.EXITING); - try { - if (threadExit != null) { - threadExit.call(self); - } else { - meta.java_lang_Thread_exit.invokeDirect(self); - } - } catch (EspressoException | EspressoExitException e) { - // just drop it - } - self.getLock().lock(); - try { - meta.java_lang_Thread_threadStatus.setInt(self, State.TERMINATED.value); - // Notify waiting threads you are done working - self.getLock().signalAll(); - } finally { - self.getLock().unlock(); - } - - EspressoContext context = meta.getContext(); - // Cleanup. - context.unregisterThread(self); - } - - public static String getThreadName(Meta meta, StaticObject thread) { - if (thread == null) { - return ""; - } else { - return meta.toHostString(meta.java_lang_Thread_name.getObject(thread)); - } - } - - public static long getThreadId(Meta meta, StaticObject thread) { - if (thread == null) { - return -1; - } else { - return (long) meta.java_lang_Thread_tid.get(thread); - } - } - @TruffleBoundary @Substitution(isTrivial = true) public static void yield() { @@ -323,9 +165,10 @@ public static void yield() { @SuppressWarnings("unused") @Substitution(hasReceiver = true) - public static void setPriority0(@JavaType(Thread.class) StaticObject self, int newPriority) { + public static void setPriority0(@JavaType(Thread.class) StaticObject self, int newPriority, + @Inject EspressoContext context) { // Priority is set in the guest field in Thread.setPriority(). - Thread hostThread = getHostFromGuestThread(self); + Thread hostThread = context.getThreadAccess().getHost(self); if (hostThread == null) { return; } @@ -372,256 +215,70 @@ public static boolean holdsLock(@JavaType(Object.class) StaticObject object, @In public static void sleep(long millis, @Inject Meta meta) { StaticObject thread = meta.getContext().getCurrentThread(); try { - fromRunnable(thread, meta, State.TIMED_WAITING); + meta.getThreadAccess().fromRunnable(thread, State.TIMED_WAITING); Thread.sleep(millis); } catch (InterruptedException e) { - setInterrupt(thread, false); + meta.getThreadAccess().clearInterruptStatus(thread); throw meta.throwExceptionWithMessage(meta.java_lang_InterruptedException, e.getMessage()); } catch (IllegalArgumentException e) { throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, e.getMessage()); } finally { - toRunnable(thread, meta, State.RUNNABLE); + meta.getThreadAccess().toRunnable(thread); } } - public static void setInterrupt(StaticObject self, boolean value) { - self.getKlass().getMeta().HIDDEN_INTERRUPTED.setBoolean(self, value, true); - } - - static boolean checkInterrupt(StaticObject self) { - return self.getKlass().getMeta().HIDDEN_INTERRUPTED.getBoolean(self, true); - } - @TruffleBoundary @Substitution(hasReceiver = true) - public static void interrupt0(@JavaType(Object.class) StaticObject self) { - Thread hostThread = getHostFromGuestThread(self); - if (hostThread == null) { - return; - } - if (self.getKlass().getMeta().getJavaVersion().java13OrEarlier()) { - // Starting from JDK 14, the interrupted status is set in java code. - setInterrupt(self, true); - } - hostThread.interrupt(); + public static void interrupt0(@JavaType(Object.class) StaticObject self, + @Inject EspressoContext context) { + context.getThreadAccess().interrupt(self); } @Substitution - public static void clearInterruptEvent() { - Thread.interrupted(); // Clear host interruption + public static void clearInterruptEvent(@Inject EspressoContext context) { + context.getThreadAccess().clearInterruptStatus(); } @TruffleBoundary @Substitution(hasReceiver = true, versionFilter = VersionFilter.Java13OrEarlier.class) - public static boolean isInterrupted(@JavaType(Thread.class) StaticObject self, boolean clear) { - boolean result = checkInterrupt(self); - if (clear) { - Thread hostThread = getHostFromGuestThread(self); - EspressoError.guarantee(hostThread == Thread.currentThread(), "Thread#isInterrupted(true) is only supported for the current thread."); - if (hostThread != null && hostThread.isInterrupted()) { - Thread.interrupted(); - } - setInterrupt(self, false); - } - return result; + public static boolean isInterrupted(@JavaType(Thread.class) StaticObject self, boolean clear, + @Inject EspressoContext context) { + return context.getThreadAccess().isInterrupted(self, clear); } @TruffleBoundary @SuppressWarnings({"unused"}) @Substitution(hasReceiver = true) - public static void resume0(@JavaType(Object.class) StaticObject self) { - SuspendLock lock = getSuspendLock(self); - if (lock == null) { - return; - } - synchronized (lock) { - lock.shouldSuspend = false; - lock.notifyAll(); - } + public static void resume0(@JavaType(Object.class) StaticObject self, + @Inject EspressoContext context) { + context.getThreadAccess().resume(self); } @TruffleBoundary @SuppressWarnings({"unused"}) @Substitution(hasReceiver = true) - public static void suspend0(@JavaType(Object.class) StaticObject toSuspend) { + public static void suspend0(@JavaType(Object.class) StaticObject toSuspend, + @Inject EspressoContext context) { toSuspend.getKlass().getContext().invalidateNoSuspend("Calling Thread.suspend()"); - SuspendLock lock = getSuspendLock(toSuspend); - if (lock == null) { - if (!isAlive(toSuspend)) { - return; - } - lock = initSuspendLock(toSuspend); + if (!isAlive(toSuspend)) { + return; } - suspendHandshake(lock, toSuspend.getKlass().getMeta(), toSuspend); + context.getThreadAccess().suspend(toSuspend); } @TruffleBoundary @Substitution(hasReceiver = true) - public static void stop0(@JavaType(Object.class) StaticObject self, @JavaType(Object.class) StaticObject throwable) { + public static void stop0(@JavaType(Object.class) StaticObject self, @JavaType(Object.class) StaticObject throwable, + @Inject EspressoContext context) { self.getKlass().getContext().invalidateNoThreadStop("Calling thread.stop()"); - killThread(self); - setInterrupt(self, true); - setDeathThrowable(self, throwable); - Thread hostThread = getHostFromGuestThread(self); - if (hostThread == null) { - return; - } - hostThread.interrupt(); + context.getThreadAccess().stop(self, throwable); } @TruffleBoundary @Substitution(hasReceiver = true) public static void setNativeName(@JavaType(Object.class) StaticObject self, @JavaType(String.class) StaticObject name, @Inject Meta meta) { - Thread hostThread = getHostFromGuestThread(self); + Thread hostThread = meta.getThreadAccess().getHost(self); hostThread.setName(meta.toHostString(name)); } - - public static Thread getHostFromGuestThread(@JavaType(Object.class) StaticObject self) { - return (Thread) self.getKlass().getMeta().HIDDEN_HOST_THREAD.getHiddenObject(self); - } - - public static boolean checkThreadStatus(StaticObject thread, KillStatus status) { - KillStatus stop = (KillStatus) thread.getKlass().getMeta().HIDDEN_DEATH.getHiddenObject(thread); - return stop != null && stop == status; - } - - public static void setThreadStop(StaticObject thread, KillStatus value) { - thread.getKlass().getMeta().HIDDEN_DEATH.setHiddenObject(thread, value); - } - - /** - * Hints the thread that it should throw a ThreadDeath error whenever he can. - */ - public static void killThread(StaticObject thread) { - setThreadStop(thread, KillStatus.KILL); - } - - /** - * Forces the thread to stop execution at the next safepoint by throwing a host exit exception. - */ - public static void forceKillThread(StaticObject thread) { - setThreadStop(thread, KillStatus.SHUTDOWN); - } - - public static void setDeathThrowable(StaticObject self, Object deathThrowable) { - self.getKlass().getMeta().HIDDEN_DEATH_THROWABLE.setHiddenObject(self, deathThrowable); - } - - public static Object getDeathThrowable(StaticObject self) { - return self.getKlass().getMeta().HIDDEN_DEATH_THROWABLE.getHiddenObject(self); - } - - public static KillStatus getKillStatus(StaticObject thread) { - return (KillStatus) thread.getKlass().getMeta().HIDDEN_DEATH.getHiddenObject(thread); - } - - public enum KillStatus { - /** - * Normal state: no Thread.stop() called, or ThreadDeath has already been thrown. - */ - NORMAL, - /** - * Thread will throw an asynchronous ThreadDeath whenever possible. - */ - KILL, - /** - * Was killed, but we are in context closing. If the thread is alive for a while in that - * state, it will be considered uncooperative. - */ - KILLED, - /** - * Was killed, and is calling Thread.exit(). Ignore further kill signals. - */ - EXITING, - /** - * Thread is uncooperative: needs to be killed with a host exception. Very dangerous state - * to be in. - */ - SHUTDOWN - } - - public static class SuspendLock { - private Object notifier = new Object(); - - private volatile boolean shouldSuspend; - private volatile boolean threadSuspended; - - public boolean shouldSuspend() { - return shouldSuspend; - } - - public boolean targetThreadIsSuspended() { - return threadSuspended; - } - } - - private static SuspendLock getSuspendLock(@JavaType(Object.class) StaticObject self) { - return (SuspendLock) self.getKlass().getMeta().HIDDEN_SUSPEND_LOCK.getHiddenObject(self); - } - - /** - * Synchronizes on Target_ class to avoid deadlock when locking on thread object. - */ - private static synchronized SuspendLock initSuspendLock(@JavaType(Object.class) StaticObject self) { - SuspendLock lock = getSuspendLock(self); - if (lock == null) { - lock = new SuspendLock(); - self.getKlass().getMeta().HIDDEN_SUSPEND_LOCK.setHiddenObject(self, lock); - } - return lock; - } - - public static boolean isSuspended(StaticObject self) { - assert getSuspendLock(self) != null; - return getSuspendLock(self).shouldSuspend(); - } - - @TruffleBoundary - public static void trySuspend(StaticObject self) { - SuspendLock lock = getSuspendLock(self); - if (lock == null) { - return; - } - synchronized (lock) { - if (lock.shouldSuspend()) { - synchronized (lock.notifier) { - lock.threadSuspended = true; - lock.notifier.notifyAll(); - } - } - while (lock.shouldSuspend()) { - try { - lock.wait(); - - } catch (InterruptedException e) { - } - } - } - lock.threadSuspended = false; - } - - @TruffleBoundary - private static void suspendHandshake(SuspendLock lock, Meta meta, StaticObject toSuspend) { - Object notifier = lock.notifier; - boolean wasInterrupted = false; - while (!lock.targetThreadIsSuspended()) { - lock.shouldSuspend = true; - try { - synchronized (notifier) { - if (meta.java_lang_Thread_threadStatus.getInt(toSuspend) == State.RUNNABLE.value) { - notifier.wait(); - } else { - break; - } - } - } catch (InterruptedException e) { - /* Thread.suspend() is not supposed to be interrupted */ - wasInterrupted = true; - } - } - if (wasInterrupted) { - meta.getContext().interruptThread(meta.getContext().getCurrentThread()); - } - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_misc_Unsafe.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_misc_Unsafe.java index 99576877207c..790628c488db 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_misc_Unsafe.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_misc_Unsafe.java @@ -52,7 +52,7 @@ import com.oracle.truffle.espresso.meta.MetaUtil; import com.oracle.truffle.espresso.runtime.EspressoContext; import com.oracle.truffle.espresso.runtime.StaticObject; -import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread.State; +import com.oracle.truffle.espresso.threads.State; import com.oracle.truffle.espresso.vm.InterpreterToVM; import com.oracle.truffle.espresso.vm.UnsafeAccess; @@ -1376,12 +1376,12 @@ public static void park(@JavaType(Unsafe.class) StaticObject self, boolean isAbs EspressoContext context = meta.getContext(); StaticObject thread = context.getCurrentThread(); - if (Target_java_lang_Thread.checkInterrupt(thread)) { + if (meta.getThreadAccess().isInterrupted(thread, false)) { return; } Unsafe unsafe = UnsafeAccess.getIfAllowed(meta); - Target_java_lang_Thread.fromRunnable(thread, meta, time > 0 ? State.TIMED_WAITING : State.WAITING); + meta.getThreadAccess().fromRunnable(thread, time > 0 ? State.TIMED_WAITING : State.WAITING); Thread hostThread = Thread.currentThread(); Object blocker = LockSupport.getBlocker(hostThread); Field parkBlocker = meta.java_lang_Thread.lookupDeclaredField(Symbol.Name.parkBlocker, Type.java_lang_Object); @@ -1393,7 +1393,7 @@ public static void park(@JavaType(Unsafe.class) StaticObject self, boolean isAbs parkBoundary(self, isAbsolute, time, meta); - Target_java_lang_Thread.toRunnable(thread, meta, State.RUNNABLE); + meta.getThreadAccess().toRunnable(thread); unsafe.putObject(hostThread, PARK_BLOCKER_OFFSET, blocker); } @@ -1417,7 +1417,7 @@ public static void parkBoundary(@SuppressWarnings("unused") @JavaType(Unsafe.cla @Substitution(hasReceiver = true) public static void unpark(@SuppressWarnings("unused") @JavaType(Unsafe.class) StaticObject self, @JavaType(Object.class) StaticObject thread, @Inject Meta meta) { - Thread hostThread = (Thread) meta.HIDDEN_HOST_THREAD.getHiddenObject(thread); + Thread hostThread = (Thread) meta.getThreadAccess().getHost(thread); UnsafeAccess.getIfAllowed(meta).unpark(hostThread); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoThreadManager.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/EspressoThreadRegistry.java similarity index 91% rename from espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoThreadManager.java rename to espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/EspressoThreadRegistry.java index 49bc570f6253..87d238c1993a 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoThreadManager.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/EspressoThreadRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.espresso.runtime; +package com.oracle.truffle.espresso.threads; import java.util.ArrayList; import java.util.Collections; @@ -38,13 +38,15 @@ import com.oracle.truffle.espresso.impl.Method; import com.oracle.truffle.espresso.impl.SuppressFBWarnings; import com.oracle.truffle.espresso.meta.Meta; +import com.oracle.truffle.espresso.runtime.EspressoContext; +import com.oracle.truffle.espresso.runtime.StaticObject; import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread; import com.oracle.truffle.espresso.vm.VM; -class EspressoThreadManager implements ContextAccess { +public class EspressoThreadRegistry implements ContextAccess { private static final int DEFAULT_THREAD_ARRAY_SIZE = 8; - private final TruffleLogger logger = TruffleLogger.getLogger(EspressoLanguage.ID, EspressoThreadManager.class); + private final TruffleLogger logger = TruffleLogger.getLogger(EspressoLanguage.ID, EspressoThreadRegistry.class); private final EspressoContext context; private final Set activeThreads = Collections.newSetFromMap(new ConcurrentHashMap<>()); @@ -56,7 +58,7 @@ public EspressoContext getContext() { return context; } - EspressoThreadManager(EspressoContext context) { + public EspressoThreadRegistry(EspressoContext context) { this.context = context; } @@ -109,8 +111,8 @@ private void registerMainThread(Thread thread, StaticObject self) { activeThreads.add(self); } - final AtomicLong createdThreadCount = new AtomicLong(); - final AtomicLong peakThreadCount = new AtomicLong(); + public final AtomicLong createdThreadCount = new AtomicLong(); + public final AtomicLong peakThreadCount = new AtomicLong(); public void registerThread(Thread host, StaticObject guest) { activeThreads.add(guest); @@ -158,12 +160,12 @@ public long applyAsLong(long oldPeak) { @SuppressFBWarnings(value = "NN", justification = "Removing a thread from the active set is the state change we need.") public void unregisterThread(StaticObject thread) { logger.fine(() -> { - String guestName = Target_java_lang_Thread.getThreadName(getMeta(), thread); - long guestId = Target_java_lang_Thread.getThreadId(getMeta(), thread); + String guestName = getThreadAccess().getThreadName(thread); + long guestId = getThreadAccess().getThreadId(thread); return String.format("unregisterThread([GUEST:%s, %d])", guestName, guestId); }); activeThreads.remove(thread); - Thread hostThread = (Thread) getMeta().HIDDEN_HOST_THREAD.getHiddenObject(thread); + Thread hostThread = getThreadAccess().getHost(thread); int id = Math.toIntExact(hostThread.getId()); synchronized (activeThreadLock) { if (id == mainThreadId) { @@ -267,7 +269,6 @@ public StaticObject createGuestThreadFromHost(Thread hostThread, Meta meta, VM v // Allow guest Thread.currentThread() to work. meta.java_lang_Thread_priority.setInt(guestThread, Thread.NORM_PRIORITY); meta.HIDDEN_HOST_THREAD.setHiddenObject(guestThread, Thread.currentThread()); - meta.HIDDEN_DEATH.setHiddenObject(guestThread, Target_java_lang_Thread.KillStatus.NORMAL); // register the new guest thread registerThread(hostThread, guestThread); @@ -277,14 +278,14 @@ public StaticObject createGuestThreadFromHost(Thread hostThread, Meta meta, VM v } else { meta.java_lang_Thread_init_ThreadGroup_String.invokeDirect(guestThread, threadGroup, meta.toGuestString(name)); } - meta.java_lang_Thread_threadStatus.setInt(guestThread, Target_java_lang_Thread.State.RUNNABLE.value); + meta.java_lang_Thread_threadStatus.setInt(guestThread, State.RUNNABLE.value); // now add to the main thread group meta.java_lang_ThreadGroup_add.invokeDirect(threadGroup, guestThread); logger.fine(() -> { - String guestName = Target_java_lang_Thread.getThreadName(getMeta(), guestThread); - long guestId = Target_java_lang_Thread.getThreadId(getMeta(), guestThread); + String guestName = getThreadAccess().getThreadName(guestThread); + long guestId = getThreadAccess().getThreadId(guestThread); return String.format("createGuestThreadFromHost: [HOST:%s, %d], [GUEST:%s, %d]", hostThread.getName(), hostThread.getId(), guestName, guestId); }); @@ -306,7 +307,6 @@ public void createMainThread(Meta meta) { // Allow guest Thread.currentThread() to work. meta.java_lang_Thread_priority.setInt(mainThread, Thread.NORM_PRIORITY); meta.HIDDEN_HOST_THREAD.setHiddenObject(mainThread, hostThread); - meta.HIDDEN_DEATH.setHiddenObject(mainThread, Target_java_lang_Thread.KillStatus.NORMAL); mainThreadGroup = meta.java_lang_ThreadGroup.allocateInstance(); registerMainThread(hostThread, mainThread); @@ -323,15 +323,15 @@ public void createMainThread(Meta meta) { .invokeDirect(mainThread, /* group */ mainThreadGroup, /* name */ meta.toGuestString("main")); - meta.java_lang_Thread_threadStatus.setInt(mainThread, Target_java_lang_Thread.State.RUNNABLE.value); + meta.java_lang_Thread_threadStatus.setInt(mainThread, State.RUNNABLE.value); // Notify native backend about main thread. getNativeAccess().prepareThread(); mainThreadCreated = true; logger.fine(() -> { - String guestName = Target_java_lang_Thread.getThreadName(getMeta(), mainThread); - long guestId = Target_java_lang_Thread.getThreadId(getMeta(), mainThread); + String guestName = getThreadAccess().getThreadName(mainThread); + long guestId = getThreadAccess().getThreadId(mainThread); return String.format("createMainThread: [HOST:%s, %d], [GUEST:%s, %d]", hostThread.getName(), hostThread.getId(), guestName, guestId); }); } @@ -371,7 +371,7 @@ private void refactorGuestThreads(int id, StaticObject self) { if (oldThreads[i] != null) { StaticObject guestThread = (StaticObject) oldThreads[i]; if (Target_java_lang_Thread.isAlive(guestThread)) { - Thread hostThread = Target_java_lang_Thread.getHostFromGuestThread(guestThread); + Thread hostThread = getThreadAccess().getHost(guestThread); int hostID = (int) hostThread.getId(); if (hostID < minID) { minID = hostID; @@ -398,7 +398,7 @@ private void refactorGuestThreads(int id, StaticObject self) { int newOffset = minID - 1; newThreads[0] = newOffset; for (StaticObject guestThread : toRelocate) { - int hostId = (int) Target_java_lang_Thread.getHostFromGuestThread(guestThread).getId(); + int hostId = (int) context.getThreadAccess().getHost(guestThread).getId(); newThreads[hostId - newOffset] = guestThread; } newThreads[id - newOffset] = self; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/GuestRunnable.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/GuestRunnable.java new file mode 100644 index 000000000000..57acf7030f55 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/GuestRunnable.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020, 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. + * + * 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.truffle.espresso.threads; + +import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.espresso.runtime.EspressoContext; +import com.oracle.truffle.espresso.runtime.EspressoException; +import com.oracle.truffle.espresso.runtime.EspressoExitException; +import com.oracle.truffle.espresso.runtime.StaticObject; + +public final class GuestRunnable implements Runnable { + private final EspressoContext context; + private final StaticObject thread; + private final DirectCallNode exit; + private final DirectCallNode dispatchUncaught; + + public GuestRunnable(EspressoContext context, StaticObject thread, DirectCallNode exit, DirectCallNode dispatchUncaught) { + this.context = context; + this.thread = thread; + this.exit = exit; + this.dispatchUncaught = dispatchUncaught; + } + + @Override + public void run() { + try { + context.getVM().attachThread(Thread.currentThread()); + try { + // Execute the payload + context.getThreadAccess().checkDeprecation(); + thread.getKlass().vtableLookup(context.getMeta().java_lang_Thread_run.getVTableIndex()).invokeDirect(thread); + context.getThreadAccess().checkDeprecation(); + } catch (EspressoException uncaught) { + dispatchUncaught.call(thread, uncaught.getExceptionObject()); + } + } catch (EspressoExitException exitException) { + /* Suppress */ + } finally { + context.getThreadAccess().terminate(thread, exit); + if (context.isClosing()) { + // Ignore exceptions that arise during closing. + return; + } + } + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/KillStatus.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/KillStatus.java new file mode 100644 index 000000000000..e0a0fcc491ed --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/KillStatus.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, 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. + * + * 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.truffle.espresso.threads; + +public enum KillStatus { + /** + * Normal state: no Thread.stop() called, or ThreadDeath has already been thrown. + */ + NORMAL, + /** + * Thread will throw an asynchronous ThreadDeath whenever possible. + */ + STOP, + /** + * Was killed, but we are in context closing. If the thread is alive for a while in that state, + * it will be considered uncooperative. + */ + KILLED, + /** + * Was killed, and is calling Thread.exit(). Ignore further kill signals. + */ + EXITING, + /** + * Thread is uncooperative: needs to be killed with a host exception. Very dangerous state to be + * in. + */ + KILL +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/State.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/State.java new file mode 100644 index 000000000000..1fdbe55abc01 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/State.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, 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. + * + * 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.truffle.espresso.threads; + +public enum State { + NEW(0), + RUNNABLE(4), + BLOCKED(1024), + WAITING(16), + TIMED_WAITING(32), + TERMINATED(2); + + public final int value; + + State(int value) { + this.value = value; + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/SuspendLock.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/SuspendLock.java new file mode 100644 index 000000000000..4d89a4b15783 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/SuspendLock.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020, 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. + * + * 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.truffle.espresso.threads; + +import com.oracle.truffle.espresso.runtime.StaticObject; + +public class SuspendLock { + private Object handshakeLock = new Object() { + }; + + private volatile boolean shouldSuspend; + private volatile boolean threadSuspended; + + public boolean shouldSuspend() { + return shouldSuspend; + } + + public boolean isSuspended() { + return threadSuspended; + } + + public void suspend(ThreadsAccess threads, StaticObject thread) { + if (threads.getHost(thread) == Thread.currentThread()) { + // No need for handshake + shouldSuspend = true; + selfSuspend(); + } else { + suspendHandshake(threads, thread); + } + } + + private void suspendHandshake(ThreadsAccess threads, StaticObject thread) { + boolean wasInterrupted = false; + while (!isSuspended()) { + shouldSuspend = true; + try { + synchronized (handshakeLock) { + if (!threads.isAlive(thread)) { + // If thread terminates, we don't want to wait forever + handshakeLock.wait(100); + } else { + break; + } + } + } catch (InterruptedException e) { + /* Thread.suspend() is not supposed to be interrupted */ + wasInterrupted = true; + } + } + if (wasInterrupted) { + threads.getContext().interruptThread(threads.getContext().getCurrentThread()); + } + } + + public synchronized void selfSuspend() { + while (shouldSuspend()) { + notifySuspended(); + try { + wait(); + } catch (InterruptedException e) { + /* spin back */ + } + } + threadSuspended = false; + } + + private void notifySuspended() { + synchronized (handshakeLock) { + threadSuspended = true; + handshakeLock.notifyAll(); + } + } + + public synchronized void resume() { + if (shouldSuspend()) { + shouldSuspend = false; + notifyAll(); + } + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java new file mode 100644 index 000000000000..a9c8e7b2b388 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2020, 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. + * + * 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.truffle.espresso.threads; + +import static com.oracle.truffle.espresso.threads.KillStatus.EXITING; +import static com.oracle.truffle.espresso.threads.KillStatus.KILL; +import static com.oracle.truffle.espresso.threads.KillStatus.KILLED; +import static com.oracle.truffle.espresso.threads.KillStatus.NORMAL; +import static com.oracle.truffle.espresso.threads.KillStatus.STOP; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.espresso.impl.ContextAccess; +import com.oracle.truffle.espresso.meta.EspressoError; +import com.oracle.truffle.espresso.meta.Meta; +import com.oracle.truffle.espresso.runtime.EspressoContext; +import com.oracle.truffle.espresso.runtime.EspressoException; +import com.oracle.truffle.espresso.runtime.EspressoExitException; +import com.oracle.truffle.espresso.runtime.StaticObject; + +public final class ThreadsAccess implements ContextAccess { + + private final Meta meta; + private final EspressoContext context; + + public String getThreadName(StaticObject thread) { + if (thread == null) { + return ""; + } else { + return meta.toHostString(meta.java_lang_Thread_name.getObject(thread)); + } + } + + public long getThreadId(StaticObject thread) { + if (thread == null) { + return -1; + } else { + return (long) meta.java_lang_Thread_tid.get(thread); + } + } + + @Override + public EspressoContext getContext() { + return context; + } + + public ThreadsAccess(Meta meta) { + this.meta = meta; + this.context = meta.getContext(); + } + + public void fromRunnable(StaticObject self, State state) { + assert meta.java_lang_Thread_threadStatus.getInt(self) == State.RUNNABLE.value; + setState(self, state); + checkDeprecation(); + } + + public void toRunnable(StaticObject self) { + try { + checkDeprecation(); + } finally { + setState(self, State.RUNNABLE); + } + } + + private void setState(StaticObject self, State state) { + meta.java_lang_Thread_threadStatus.setInt(self, state.value); + } + + public Thread getHost(StaticObject guest) { + return (Thread) meta.HIDDEN_HOST_THREAD.getHiddenObject(guest); + } + + /** + * Implements support for thread deprecated methods ({@link Thread#stop()}, + * {@link Thread#suspend()}, {@link Thread#resume()}). + *

+ * The following performance concerns are to be considered: + *

    + *
  • If these deprecated methods are never called, this method should entirely fold.
  • + *
  • When called for the first time, a very large portion of the compiled code will be + * invalidated.
  • + *
  • After being called for the first time, in most cases, this method should amount to + * getting the current thread and reading a field
  • + *
+ */ + public void checkDeprecation() { + if (!context.shouldCheckDeprecationStatus()) { + return; + } + StaticObject current = context.getCurrentThread(); + DeprecationSupport support = getDeprecationSupport(current, false); + if (support == null) { + return; + } + if (context.shouldCheckStop()) { + support.handleStop(meta); + } + if (context.shouldCheckSuspend()) { + support.handleSuspend(); + } + } + + public boolean isInterrupted(StaticObject guest, boolean clear) { + boolean isInterrupted = meta.HIDDEN_INTERRUPTED.getBoolean(guest, true); + if (clear) { + Thread host = getHost(guest); + EspressoError.guarantee(host == Thread.currentThread(), "Thread#isInterrupted(true) is only supported for the current thread."); + if (host != null && host.isInterrupted()) { + Thread.interrupted(); + } + clearInterruptStatus(guest); + } + return isInterrupted; + } + + public void interrupt(StaticObject guest) { + if (context.getJavaVersion().java13OrEarlier()) { + meta.HIDDEN_INTERRUPTED.setBoolean(guest, true, true); + } + Thread host = getHost(guest); + if (host != null) { + host.interrupt(); + } + } + + public void clearInterruptStatus() { + StaticObject guest = context.getCurrentThread(); + if (context.getJavaVersion().java13OrEarlier()) { + clearInterruptStatus(guest); + } + Thread.interrupted(); + } + + public boolean isAlive(StaticObject guest) { + int state = meta.java_lang_Thread_threadStatus.getInt(guest); + return state != State.NEW.value && state != State.TERMINATED.value; + } + + /** + * Suspends a thread. On return, guarantees that the given thread has seen the suspend request. + */ + public void suspend(StaticObject guest) { + DeprecationSupport support = getDeprecationSupport(guest, true); + assert support != null; + support.suspend(this); + } + + /** + * Resumes a thread. Does nothing if the thread was not previously suspended. + */ + public void resume(StaticObject guest) { + DeprecationSupport support = getDeprecationSupport(guest, false); + if (support == null) { + return; + } + support.resume(); + } + + /** + * Notifies a thread to throw an asynchronous guest throwable whenever possible. + */ + public void stop(StaticObject guest, StaticObject throwable) { + DeprecationSupport support = getDeprecationSupport(guest, true); + assert support != null; + support.stop(throwable); + Thread host = getHost(guest); + interrupt(guest); + if (host != null) { + host.interrupt(); + } + } + + /** + * Notifies a thread to throw a host {@link EspressoExitException} whenever possible. + */ + public void kill(StaticObject guest) { + DeprecationSupport support = getDeprecationSupport(guest, true); + support.kill(); + } + + /** + * Creates a thread for the given guest thread. This thread will be ready to be started. + */ + public Thread createJavaThread(StaticObject guest, DirectCallNode exit, DirectCallNode dispatch) { + Thread host = context.getEnv().createThread(new GuestRunnable(context, guest, exit, dispatch)); + // Prepare + meta.HIDDEN_HOST_THREAD.setHiddenObject(guest, host); + host.setDaemon(meta.java_lang_Thread_daemon.getBoolean(guest)); + meta.java_lang_Thread_threadStatus.setInt(guest, State.RUNNABLE.value); + host.setPriority(meta.java_lang_Thread_priority.getInt(guest)); + if (isInterrupted(guest, false)) { + host.interrupt(); + } + context.registerThread(host, guest); + String guestName = context.getThreadAccess().getThreadName(guest); + host.setName(guestName); + return host; + } + + /** + * Termination of a threads works as follows: + *
    + *
  • Prevent other threads from {@linkplain #stop(StaticObject, StaticObject)} stopping} the + * given thread
  • + *
  • Invoke guest {@link Thread#exit()}
  • + *
  • Sets the status of this thread to {@link State.TERMINATED} and notifies other threads + * waiting on this thread's monitor
  • + *
  • Unregisters the thread
  • + *
+ */ + public void terminate(StaticObject thread) { + terminate(thread, null); + } + + public void terminate(StaticObject thread, DirectCallNode exit) { + DeprecationSupport support = getDeprecationSupport(thread, true); + support.exit(); + try { + if (exit == null) { + meta.java_lang_Thread_exit.invokeDirect(thread); + } else { + exit.call(thread); + } + } catch (EspressoException | EspressoExitException e) { + // just drop it + } + terminateAndNotify(thread); + context.unregisterThread(thread); + } + + public void terminateAndNotify(StaticObject guest) { + guest.getLock().lock(); + try { + meta.java_lang_Thread_threadStatus.setInt(guest, State.TERMINATED.value); + // Notify waiting threads you are done working + guest.getLock().signalAll(); + } finally { + guest.getLock().unlock(); + } + } + + /** + * returns true if this thread has been stopped before starting, or if the context is in + * closing. + */ + public boolean isStillborn(StaticObject guest) { + if (context.isClosing()) { + return true; + } + DeprecationSupport support = getDeprecationSupport(guest, false); + if (support != null) { + return support.status != NORMAL; + } + return false; + } + + public void clearInterruptStatus(StaticObject guest) { + meta.HIDDEN_INTERRUPTED.setBoolean(guest, false, true); + } + + private DeprecationSupport getDeprecationSupport(StaticObject guest, boolean initIfNull) { + DeprecationSupport support = (DeprecationSupport) meta.HIDDEN_DEPRECATION_SUPPORT.getHiddenObject(guest); + if (initIfNull && support == null) { + synchronized (guest) { + support = (DeprecationSupport) meta.HIDDEN_DEPRECATION_SUPPORT.getHiddenObject(guest, true); + if (support == null) { + support = new DeprecationSupport(guest); + meta.HIDDEN_DEPRECATION_SUPPORT.setHiddenObject(guest, support, true); + } + } + } + return support; + } + + private static final class DeprecationSupport { + + private final StaticObject thread; + + private volatile StaticObject throwable = null; + /* + * Non-volatile for general performance purposes. The cost is that the target thread might + * take longer to observe requests.; + */ + private KillStatus status = NORMAL; + private SuspendLock suspendLock = null; + + DeprecationSupport(StaticObject thread) { + this.thread = thread; + } + + void suspend(ThreadsAccess threads) { + SuspendLock lock = this.suspendLock; + if (lock == null) { + synchronized (this) { + lock = new SuspendLock(); + this.suspendLock = lock; + } + } + lock.suspend(threads, thread); + } + + void resume() { + SuspendLock lock = this.suspendLock; + if (lock == null) { + return; + } + lock.resume(); + } + + void stop(StaticObject death) { + // Writing the throwable must be done before the kill status can be observed + throwable = death; + status = STOP; + } + + void kill() { + status = KILL; + } + + void exit() { + status = EXITING; + } + + @TruffleBoundary + void handleSuspend() { + SuspendLock lock = this.suspendLock; + if (lock == null) { + return; + } + lock.selfSuspend(); + } + + @TruffleBoundary + void handleStop(Meta meta) { + switch (status) { + case NORMAL: + case EXITING: + case KILLED: + break; + case STOP: + if (meta.getContext().isClosing()) { + // Give some leeway during closing. + status = KILLED; + } else { + status = NORMAL; + } + // check if death cause throwable is set, if not throw ThreadDeath + StaticObject deathThrowable = throwable; + throw deathThrowable != null ? meta.throwException(deathThrowable) : meta.throwException(meta.java_lang_ThreadDeath); + case KILL: + // This thread refuses to stop. Send a host exception. + assert meta.getContext().isClosing(); + throw new EspressoExitException(meta.getContext().getExitStatus()); + } + } + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/InterpreterToVM.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/InterpreterToVM.java index d4a9904b9c71..691de20467d2 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/InterpreterToVM.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/InterpreterToVM.java @@ -60,6 +60,7 @@ import com.oracle.truffle.espresso.substitutions.JavaType; import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread; import com.oracle.truffle.espresso.substitutions.Throws; +import com.oracle.truffle.espresso.threads.State; public final class InterpreterToVM implements ContextAccess { @@ -399,7 +400,7 @@ public static void monitorEnter(@JavaType(Object.class) StaticObject obj, Meta m EspressoContext context = meta.getContext(); if (!monitorTryLock(lock)) { StaticObject thread = context.getCurrentThread(); - Target_java_lang_Thread.fromRunnable(thread, meta, Target_java_lang_Thread.State.BLOCKED); + meta.getThreadAccess().fromRunnable(thread, State.BLOCKED); if (context.EnableManagement) { // Locks bookkeeping. meta.HIDDEN_THREAD_BLOCKED_OBJECT.setHiddenObject(thread, obj); @@ -417,7 +418,7 @@ public static void monitorEnter(@JavaType(Object.class) StaticObject obj, Meta m if (context.EnableManagement) { meta.HIDDEN_THREAD_BLOCKED_OBJECT.setHiddenObject(thread, null); } - Target_java_lang_Thread.toRunnable(thread, meta, Target_java_lang_Thread.State.RUNNABLE); + meta.getThreadAccess().toRunnable(thread); } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/Management.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/Management.java index 2912967b66e0..6e0ad894a56d 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/Management.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/Management.java @@ -60,6 +60,7 @@ import com.oracle.truffle.espresso.substitutions.JavaType; import com.oracle.truffle.espresso.substitutions.SubstitutionProfiler; import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread; +import com.oracle.truffle.espresso.threads.State; @GenerateNativeEnv(target = ManagementImpl.class, prependEnv = true) public final class Management extends NativeEnv { @@ -297,7 +298,7 @@ public int GetThreadInfo(@JavaType(long[].class) StaticObject ids, int maxDepth, StaticObject thread = StaticObject.NULL; for (int j = 0; j < activeThreads.length; ++j) { - if (Target_java_lang_Thread.getThreadId(meta, activeThreads[j]) == id) { + if (getThreadAccess().getThreadId(activeThreads[j]) == id) { thread = activeThreads[j]; break; } @@ -310,7 +311,7 @@ public int GetThreadInfo(@JavaType(long[].class) StaticObject ids, int maxDepth, int threadStatus = meta.java_lang_Thread_threadStatus.getInt(thread); StaticObject lockObj = StaticObject.NULL; StaticObject lockOwner = StaticObject.NULL; - int mask = Target_java_lang_Thread.State.BLOCKED.value | Target_java_lang_Thread.State.WAITING.value | Target_java_lang_Thread.State.TIMED_WAITING.value; + int mask = State.BLOCKED.value | State.WAITING.value | State.TIMED_WAITING.value; if ((threadStatus & mask) != 0) { lockObj = (StaticObject) meta.HIDDEN_THREAD_BLOCKED_OBJECT.getHiddenObject(thread); if (lockObj == null) { @@ -567,7 +568,7 @@ public int GetVMGlobals(@JavaType(Object[].class) StaticObject names, /* jmmVMGl StaticObject[] activeThreads = getContext().getActiveThreads(); threadIds = InterpreterToVM.allocatePrimitiveArray((byte) JavaKind.Long.getBasicType(), activeThreads.length, getMeta()); for (int j = 0; j < activeThreads.length; ++j) { - long tid = Target_java_lang_Thread.getThreadId(getMeta(), activeThreads[j]); + long tid = getThreadAccess().getThreadId(activeThreads[j]); getInterpreterToVM().setArrayLong(tid, j, threadIds); } } @@ -586,7 +587,7 @@ public long GetOneThreadAllocatedMemory( StaticObject thread = StaticObject.NULL; for (int j = 0; j < activeThreads.length; ++j) { - if (Target_java_lang_Thread.getThreadId(getMeta(), activeThreads[j]) == threadId) { + if (getThreadAccess().getThreadId(activeThreads[j]) == threadId) { thread = activeThreads[j]; break; } @@ -620,7 +621,7 @@ public void GetThreadAllocatedMemory( StaticObject thread = StaticObject.NULL; for (int j = 0; j < activeThreads.length; ++j) { - if (Target_java_lang_Thread.getThreadId(meta, activeThreads[j]) == id) { + if (getThreadAccess().getThreadId(activeThreads[j]) == id) { thread = activeThreads[j]; break; } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java index 0611052872ce..36599b69517a 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java @@ -146,8 +146,8 @@ import com.oracle.truffle.espresso.substitutions.SubstitutionProfiler; import com.oracle.truffle.espresso.substitutions.Target_java_lang_System; import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread; -import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread.State; import com.oracle.truffle.espresso.substitutions.Target_java_lang_ref_Reference; +import com.oracle.truffle.espresso.threads.State; import com.oracle.truffle.espresso.vm.structs.JavaVMAttachArgs; import com.oracle.truffle.espresso.vm.structs.JdkVersionInfo; import com.oracle.truffle.espresso.vm.structs.Structs; @@ -800,7 +800,7 @@ public void JVM_MonitorWait(@JavaType(Object.class) StaticObject self, long time EspressoContext context = getContext(); StaticObject currentThread = context.getCurrentThread(); try { - Target_java_lang_Thread.fromRunnable(currentThread, meta, (timeout > 0 ? State.TIMED_WAITING : State.WAITING)); + meta.getThreadAccess().fromRunnable(currentThread, (timeout > 0 ? State.TIMED_WAITING : State.WAITING)); if (context.EnableManagement) { // Locks bookkeeping. meta.HIDDEN_THREAD_BLOCKED_OBJECT.setHiddenObject(currentThread, self); @@ -816,7 +816,7 @@ public void JVM_MonitorWait(@JavaType(Object.class) StaticObject self, long time } } catch (InterruptedException e) { profiler.profile(0); - Target_java_lang_Thread.setInterrupt(currentThread, false); + getThreadAccess().clearInterruptStatus(currentThread); throw meta.throwExceptionWithMessage(meta.java_lang_InterruptedException, e.getMessage()); } catch (IllegalMonitorStateException e) { profiler.profile(1); @@ -828,7 +828,7 @@ public void JVM_MonitorWait(@JavaType(Object.class) StaticObject self, long time if (context.EnableManagement) { meta.HIDDEN_THREAD_BLOCKED_OBJECT.setHiddenObject(currentThread, null); } - Target_java_lang_Thread.toRunnable(currentThread, meta, State.RUNNABLE); + meta.getThreadAccess().toRunnable(currentThread); } } @@ -1519,8 +1519,7 @@ public int DetachCurrentThread(@Inject EspressoContext context) { return JNI_OK; } getLogger().fine(() -> { - Meta meta = getMeta(); - String guestName = Target_java_lang_Thread.getThreadName(meta, currentThread); + String guestName = getThreadAccess().getThreadName(currentThread); return "DetachCurrentThread: " + guestName; }); // HotSpot will wait forever if the current VM this thread was attached to has exited @@ -1540,8 +1539,7 @@ public Method visitFrame(FrameInstance frameInstance) { if (lastJavaMethod != null) { // this thread is executing getLogger().warning(() -> { - Meta meta = getMeta(); - String guestName = Target_java_lang_Thread.getThreadName(meta, currentThread); + String guestName = getThreadAccess().getThreadName(currentThread); return "DetachCurrentThread called while thread is still executing Java code (" + guestName + ")"; }); return JNI_ERR; @@ -1555,12 +1553,12 @@ public Method visitFrame(FrameInstance frameInstance) { meta.java_lang_Thread_dispatchUncaughtException.invokeDirect(currentThread, pendingException); } - Target_java_lang_Thread.terminate(currentThread, meta); + getThreadAccess().terminate(currentThread); } catch (EspressoException e) { try { StaticObject ex = e.getExceptionObject(); String exception = ex.getKlass().getExternalName(); - String threadName = Target_java_lang_Thread.getThreadName(meta, currentThread); + String threadName = getThreadAccess().getThreadName(currentThread); context.getLogger().warning(String.format("Exception: %s thrown while terminating thread \"%s\"", exception, threadName)); Method printStackTrace = ex.getKlass().lookupMethod(Name.printStackTrace, Signature._void); printStackTrace.invokeDirect(ex); From 7ab1d17fb92c959cc8a591a97791b7a87c50abd0 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 6 Oct 2021 10:06:28 -0700 Subject: [PATCH 313/681] ResolvedJavaMethod.getCode() might not be == --- .../src/org/graalvm/compiler/nodes/FrameState.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java index 4a033b71f141..9134d04c84b0 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java @@ -34,6 +34,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -307,7 +308,7 @@ public ResolvedJavaMethod getMethod() { * latter has been subject to instrumentation. */ public boolean canProduceBytecodeFrame() { - return code != null && code.getCode() == code.getMethod().getCode(); + return code != null && Arrays.equals(code.getCode(), code.getMethod().getCode()); } public void addVirtualObjectMapping(EscapeObjectState virtualObject) { From 9e326a18094479a5c12b90b584e7c987bafacfc8 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Wed, 6 Oct 2021 22:51:29 +0300 Subject: [PATCH 314/681] Test demos with graalvm 21.3-dev and update documentation --- docs/reference-manual/compiler.md | 4 +- .../embedding/embed-languages.md | 89 +++++-------- .../embedding/sandbox-options.md | 80 +++++++----- docs/reference-manual/graalvm-updater.md | 121 +++++++----------- docs/reference-manual/polyglot-programming.md | 50 +++----- docs/security/security-guide.md | 11 +- docs/tools/chrome-debugger.md | 9 +- docs/tools/code-coverage.md | 69 ++++------ docs/tools/dap.md | 6 +- docs/tools/graalvm-insight.md | 106 ++++++--------- docs/tools/ideal-graph-visualizer.md | 78 +++++------ docs/tools/lsp.md | 2 +- 12 files changed, 260 insertions(+), 365 deletions(-) diff --git a/docs/reference-manual/compiler.md b/docs/reference-manual/compiler.md index 66da06569e70..0f0d0698cdd0 100644 --- a/docs/reference-manual/compiler.md +++ b/docs/reference-manual/compiler.md @@ -41,9 +41,7 @@ GraalVM also includes the [Truffle language implementation framework](/graalvm-a These languages can consequently benefit from the optimization possibilities of the GraalVM compiler. The pipeline for such compilation is: -* The Truffle framework code and data (Abstract Syntax Trees) is partially evaluated to -produce a compilation graph. When such an Abstract Syntax Tree (AST) is -hot (i.e., called many times), it is scheduled for compilation by the compiler. +* The Truffle framework code and data (Abstract Syntax Trees) is partially evaluated to produce a compilation graph. When such an Abstract Syntax Tree (AST) is hot (i.e., called many times), it is scheduled for compilation by the compiler. * The compilation graph is optimized by the GraalVM compiler to produce machine code. * JVMCI installs this machine code in the VM's code cache. * The AST will automatically redirect execution to the installed machine code once it is available. diff --git a/docs/reference-manual/embedding/embed-languages.md b/docs/reference-manual/embedding/embed-languages.md index 24bc455db339..04ba6569ef42 100644 --- a/docs/reference-manual/embedding/embed-languages.md +++ b/docs/reference-manual/embedding/embed-languages.md @@ -24,9 +24,8 @@ permalink: /reference-manual/embed-languages/ The GraalVM Polyglot API lets you embed and run code from guest languages in JVM-based host applications. -Throughout this section, you will learn how to create a host application in Java that -runs on GraalVM and directly calls a guest language. You can use the tabs -beneath each code example to choose between JavaScript, R, Ruby, and Python. +Throughout this section, you will learn how to create a host application in Java that runs on GraalVM and directly calls a guest language. +You can use the tabs beneath each code example to choose between JavaScript, R, Ruby, and Python. Ensure you set up GraalVM before you begin. @@ -34,9 +33,7 @@ Ensure you set up GraalVM before you begin. GraalVM can run polyglot applications written in any language implemented with the [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/). These languages are henceforth referenced as **guest languages**. -Complete the steps in this section to create a sample polyglot -application that runs on GraalVM and demonstrates programming language -interoperability. +Complete the steps in this section to create a sample polyglot application that runs on GraalVM and demonstrates programming language interoperability. 1. Create a `hello-polyglot` project directory. @@ -67,10 +64,8 @@ GraalVM. 4. Run `java HelloPolyglot` to run the application on GraalVM. -You now have a polyglot application that consists of a Java host application -and guest language code that run on GraalVM. You can use this application with -other code examples to demonstrate more advanced capabilities of the -Polyglot API. +You now have a polyglot application that consists of a Java host application and guest language code that run on GraalVM. +You can use this application with other code examples to demonstrate more advanced capabilities of the Polyglot API. To use other code examples in this section, you simply need to do the following: @@ -80,12 +75,9 @@ To use other code examples in this section, you simply need to do the following: ## Define Guest Language Functions as Java Values -Polyglot applications let you take values from one programming language and -use them with other languages. +Polyglot applications let you take values from one programming language and use them with other languages. -Use the code example in this section with your polyglot application to show -how the Polyglot API can return JavaScript, R, Ruby, or Python functions as -Java values. +Use the code example in this section with your polyglot application to show how the Polyglot API can return JavaScript, R, Ruby, or Python functions as Java values. {% include snippet-tabs @@ -106,12 +98,10 @@ executed. ## Access Guest Languages Directly from Java -Polyglot applications can readily access most language types and are not -limited to functions. Host languages, such as Java, can directly access guest -language values embedded in the polyglot application. +Polyglot applications can readily access most language types and are not limited to functions. +Host languages, such as Java, can directly access guest language values embedded in the polyglot application. -Use the code example in this section with your polyglot application to show -how the Polyglot API can access objects, numbers, strings, and arrays. +Use the code example in this section with your polyglot application to show how the Polyglot API can access objects, numbers, strings, and arrays. {% include snippet-tabs @@ -145,17 +135,13 @@ R where indices start with one. ## Access Java from Guest Languages -Polyglot applications offer bi-directional access between guest languages and -host languages. As a result, you can pass Java objects to guest languages. +Polyglot applications offer bi-directional access between guest languages and host languages. +As a result, you can pass Java objects to guest languages. -Use the code example in this section with your polyglot application to show how -guest languages can access primitive Java values, objects, arrays, and -functional interfaces. +Use the code example in this section with your polyglot application to show how guest languages can access primitive Java values, objects, arrays, and functional interfaces. -To permit guest languages to access any public method or field of a Java -object, set `allowAllAccess(true)` when the context is built. In this mode, the guest -language code must be fully trusted, as it can access other not explicitly exported Java methods -using reflection. +To permit guest languages to access any public method or field of a Java object, set `allowAllAccess(true)` when the context is built. +In this mode, the guest language code must be fully trusted, as it can access other not explicitly exported Java methods using reflection. {% include snippet-tabs @@ -193,11 +179,9 @@ that the script returns a `boolean` value of `true` as a result. ## Lookup Java Types from Guest Languages -In addition to passing Java objects to the guest language, it is possible -to allow the lookup of Java types in the guest language. +In addition to passing Java objects to the guest language, it is possible to allow the lookup of Java types in the guest language. -Use the code example in this section with your polyglot application to show how -guest languages lookup Java types and instantiate them. +Use the code example in this section with your polyglot application to show how guest languages lookup Java types and instantiate them. {% include snippet-tabs @@ -221,14 +205,11 @@ JavaScript using the `new` keyword. ## Computed Arrays Using Polyglot Proxies -The Polyglot API includes polyglot proxy interfaces that let you -customize Java interoperability by mimicking guest language types, such as -objects, arrays, native objects, or primitives. +The Polyglot API includes polyglot proxy interfaces that let you customize Java interoperability by mimicking guest language types, such as objects, arrays, native objects, or primitives. -Use the code example in this section with your polyglot application to see how -you can implement arrays that compute their values lazily. +Use the code example in this section with your polyglot application to see how you can implement arrays that compute their values lazily. -Note: The Polyglot API supports polyglot proxies either on the JVM or in Native Image. +> Note: The Polyglot API supports polyglot proxies either on the JVM or in Native Image. {% include snippet-tabs @@ -255,24 +236,20 @@ then returned. Note that array indices from 1-based languages such as R are converted to 0-based indices for proxy arrays. - The result of the language script is returned as a long value and verified. -For more information about the polyglot proxy interfaces, see the -[Polyglot API JavaDoc](http://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/package-summary.html). +For more information about the polyglot proxy interfaces, see the [Polyglot API JavaDoc](http://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/package-summary.html). ## Host Access The Polyglot API by default restricts access to certain critical functionality, such as file I/O. These restrictions can be lifted entirely by setting `allowAllAccess` to `true`. -Note: The access restrictions are currently only supported with JavaScript. +> Note: The access restrictions are currently only supported with JavaScript. ### Controlling Access to Host Functions It might be desireable to limit the access of guest applications to the host. -For example, if a Java method is exposed that calls `System.exit` then the guest -application will be able to exit the host process. -In order to avoid accidentally exposed methods, no host access is allowed by -default and every public method or field needs to be annotated with -`@HostAccess.Export` explicitly. +For example, if a Java method is exposed that calls `System.exit` then the guest application will be able to exit the host process. +In order to avoid accidentally exposed methods, no host access is allowed by default and every public method or field needs to be annotated with `@HostAccess.Export` explicitly. {% include snippet-tabs @@ -394,7 +371,7 @@ The following access parameters may be configured: * Allow access to native APIs using [`allowNativeAccess`](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/Context.Builder.html#allowNativeAccess-boolean-). * Allow access to IO using [`allowIO`](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/Context.Builder.html#allowIO-boolean-) and proxy file accesses using [`fileSystem`](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/Context.Builder.html#fileSystem-org.graalvm.polyglot.io.FileSystem-). -Note: Granting access to class loading, native APIs, or host I/O effectively grants all access, as these privileges can be used to bypass other access restrictions. +> Note: Granting access to class loading, native APIs, or host I/O effectively grants all access, as these privileges can be used to bypass other access restrictions. ## Build Native Images from Polyglot Applications @@ -493,7 +470,7 @@ Caching may be disabled explicitly by setting [cached(boolean cached)](https:// Consider the following code snippet as an example: -``` +```java public class Main { public static void main(String[] args) { try (Engine engine = Engine.create()) { @@ -543,12 +520,12 @@ public class Main { public static void main(String[] args) { try (Context outer = Context.newBuilder() .allowAllAccess(true) - .build()) { + .build()) { outer.eval("js", "inner = Java.type('org.graalvm.polyglot.Context').create()"); outer.eval("js", "value = inner.eval('js', '({data:42})')"); int result = outer.eval("js", "value.data").asInt(); outer.eval("js", "inner.close()"); - + System.out.println("Valid " + (result == 42)); } } @@ -566,8 +543,7 @@ In this code:
 ## Build a Shell for Many Languages -With just a few lines of code, the GraalVM Polyglot API lets you build -applications that integrate with any guest language supported by GraalVM. +With just a few lines of code, the GraalVM Polyglot API lets you build applications that integrate with any guest language supported by GraalVM. This shell implementation is agnostic to any particular guest language. @@ -600,12 +576,11 @@ for (;;) { } ``` - - ## Step Through with Execution Listeners -The GraalVM Polyglot API allows users to instrument the execution of guest languages through [ExecutionListener class](http://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/management/ExecutionListener.html). For example, it lets you attach an execution listener that is invoked for every statement of the guest language program. Execution listeners -are designed as simple API for polyglot embedders and may become handy in, e.g., single-stepping through the program. +The GraalVM Polyglot API allows users to instrument the execution of guest languages through [ExecutionListener class](http://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/management/ExecutionListener.html). +For example, it lets you attach an execution listener that is invoked for every statement of the guest language program. +Execution listeners are designed as simple API for polyglot embedders and may become handy in, e.g., single-stepping through the program. ```java import org.graalvm.polyglot.*; diff --git a/docs/reference-manual/embedding/sandbox-options.md b/docs/reference-manual/embedding/sandbox-options.md index 116e08e0aef6..9e1b0712c2e1 100644 --- a/docs/reference-manual/embedding/sandbox-options.md +++ b/docs/reference-manual/embedding/sandbox-options.md @@ -1,14 +1,14 @@ ## Enterprise Sandbox Resource Limits -The 20.3 release of GraalVM introduced the experimental Sandbox Resource Limits feature that allows for the limiting of resources used by guest applications. -These resource limits are not available in the community edition of GraalVM. -The following document describes how to configure sandbox resource limits using options in the polyglot API +GraalVM Enterprise provides the experimental Sandbox Resource Limits feature that allows for the limiting of resources used by guest applications. +These resource limits are not available in the Community Edition of GraalVM. +The following document describes how to configure sandbox resource limits using options in GraalVM Polyglot API. -In general all resource limit options are prefixed with `sandbox` option group and they can be listed using the help of any language launcher provided in GraalVM e.g. `js --help:tools`. +In general all resource limit options are prefixed with `sandbox` option group and they can be listed using the help of any language launcher provided in GraalVM, e.g., `js --help:tools`. Polyglot options can be provided through the language launcher, using the polyglot embedding API of the Graal SDK, or on the JVM using a system property. For better understanding of the examples it is recommended to read the [polyglot embedding guide](/reference-manual/embed-languages/) of the reference manual first. -Currently all sandbox options are experimental therefore in these examples it is assumed that experimental options are enabled (e.g. with `--experimental-options`). +Currently all sandbox options are experimental therefore in these examples it is assumed that experimental options are enabled (e.g., with `--experimental-options`). The options are a best effort approach to limiting resource usage of guest applications. The resource limits may be configured using the following options: @@ -31,7 +31,8 @@ The resource limits may be configured using the following options: Different configurations may be provided for each polyglot embedding `Context` instance. In addition to that the limits may be reset at any point of time during the execution. Resetting is only aplicable to `sandbox.MaxStatements` and `sandbox.MaxCPUTime`. -A guest language might choose to create an inner context within the outer execution context. The limits are applied to the outer context and all inner contexts it spawns. It is not possible to specify a separate limit for inner contexts and it is also not possible to escape any limit by creating an inner context. +A guest language might choose to create an inner context within the outer execution context. The limits are applied to the outer context and all inner contexts it spawns. +It is not possible to specify a separate limit for inner contexts and it is also not possible to escape any limit by creating an inner context. ## Limiting the active CPU time @@ -60,7 +61,7 @@ It is not allowed specify negative values or no time unit with CPU time limit op ### Example Usage -``` +```java try (Context context = Context.newBuilder("js") .allowExperimentalOptions(true) .option("sandbox.MaxCPUTime", "500ms") @@ -84,9 +85,10 @@ try (Context context = Context.newBuilder("js") Specifies the maximum number of statements a context may execute until the the context will be cancelled. After the statement limit was triggered for a context, it is no longer usable and every use of the context will throw a `PolyglotException` that returns `true` for `PolyglotException.isCancelled()`. The statement limit is independent of the number of threads executing and is applied per context. -It is also possible to specify this limit using the [ResourceLimits]() API of the polyglot embedding API. +It is also possible to specify this limit using the `[ResourceLimits]()` API of the polyglot embedding API. -By default there is no statement limit applied. The limit may be set to a negative number to disable it. +By default there is no statement limit applied. +The limit may be set to a negative number to disable it. Whether this limit is applied internal sources only can be configured using `sandbox.MaxStatementsIncludeInternal`. By default the limit does not include statements of sources that are marked internal. If a shared engine is used then the same internal configuration must be used for all contexts of an engine. @@ -100,8 +102,7 @@ The complexity of a single statement may not be constant time depending on the g For example, statements that execute JavaScript builtins, like `Array.sort`, may account for a single statement, but its execution time is dependent on the size of the array. The statement count limit is therefore not suitable to perform time boxing and must be combined with other more reliable measures like the CPU time limit. - -``` +```java try (Context context = Context.newBuilder("js") .allowExperimentalOptions(true) .option("sandbox.MaxStatements", "2") @@ -144,20 +145,21 @@ If used together with the AST depth limit it can be used to estimate total stack Limits the number of threads that can be used by a context at the same point in time. By default, an arbitary number of threads can be used. -If a set limit is exceeded, entering the context fails with a PolyglotException and the polyglot context is canceled. +If a set limit is exceeded, entering the context fails with a `PolyglotException` and the polyglot context is canceled. Resetting resource limits does not affect thread limits. ## Limiting the maximum heap memory The `sandbox.MaxHeapMemory` option allows you to specify the maximum heap memory the application is allowed to retain during its run. -`sandbox.MaxHeapMemory` must be positive. This option is only supported on a HotSpot-based VM. Enabling this option in AOT mode will result in PolyglotException. +`sandbox.MaxHeapMemory` must be positive. This option is only supported on a HotSpot-based VM. +Enabling this option in AOT mode will result in PolyglotException. When exceeding of the limit is detected, the corresponding context is automatically cancelled and then closed. The efficacy of this option (also) depends on the garbage collector used. #### Example Usage -``` +```java try (Context context = Context.newBuilder("js") .allowExperimentalOptions(true) .option("sandbox.MaxHeapMemory", "100MB") @@ -177,43 +179,53 @@ try (Context context = Context.newBuilder("js") #### Implementation details and expert options -The limit is checked by retained size computation triggered either based on [allocated](https://docs.oracle.com/en/java/javase/11/docs/api/jdk.management/com/sun/management/ThreadMXBean.html#getThreadAllocatedBytes\(long\)) bytes or on -[low memory notification](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/MemoryMXBean.html). +The limit is checked by retained size computation triggered either based on [allocated](https://docs.oracle.com/en/java/javase/11/docs/api/jdk.management/com/sun/management/ThreadMXBean.html#getThreadAllocatedBytes\(long\)) bytes or on [low memory notification](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/MemoryMXBean.html). -The allocated bytes are checked by a separate high-priority thread that will be woken regularly. There is one such thread for each memory-limited context (one with `sandbox.MaxHeapMemory` set). -The retained bytes computation is done by yet another high-priority thread that is started from the allocated bytes checking thread as needed. The retained bytes computation thread also cancels the context if the heap memory limit is exeeded. Additionaly, when low memory trigger is invoked, -all contexts on engines with at least one memory-limited context are paused together with their allocation checkers. All individual retained size computations are cancelled. -Retained bytes in the heap for each memory-limited context are computed by a single high-priority thread. Contexts exceeding their limits are cancelled, and then the execution is resumed. +The allocated bytes are checked by a separate high-priority thread that will be woken regularly. +There is one such thread for each memory-limited context (one with `sandbox.MaxHeapMemory` set). +The retained bytes computation is done by yet another high-priority thread that is started from the allocated bytes checking thread as needed. +The retained bytes computation thread also cancels the context if the heap memory limit is exeeded. +Additionaly, when low memory trigger is invoked, all contexts on engines with at least one memory-limited context are paused together with their allocation checkers. +All individual retained size computations are cancelled. +Retained bytes in the heap for each memory-limited context are computed by a single high-priority thread. +Contexts exceeding their limits are cancelled, and then the execution is resumed. The main goal of the heap memory limits is to prevent heap memory depletion related errors in most cases and thus enable the host VM to run smoothly even in the presence of misbehaving contexts. -The implementation is best effort. This means that there is no guarantee on the accuracy of the heap memory limit. There is also no guarantee that setting a heap memory limit will prevent the context from causing `OutOfMemory` errors. +The implementation is best effort. This means that there is no guarantee on the accuracy of the heap memory limit. +There is also no guarantee that setting a heap memory limit will prevent the context from causing `OutOfMemory` errors. Guest applications that allocate many objects in quick succession have a lower accuracy than applications which allocate objects rarely. -The guest code execution will only be paused if the host heap memory is exhausted and a low memory trigger of the host VM is invoked. Note that the scope of the pause is an engine, so a context without the `sandbox.MaxHeapMemory` option set is also paused in case it shares the engine with other context that is memory-limited. +The guest code execution will only be paused if the host heap memory is exhausted and a low memory trigger of the host VM is invoked. +Note that the scope of the pause is an engine, so a context without the `sandbox.MaxHeapMemory` option set is also paused in case it shares the engine with other context that is memory-limited. Also note that if one context is cancelled other contexts with the same explicit engine may be slowed down. How the size retained by a context is computed can be customized using the expert options `sandbox.AllocatedBytesCheckInterval`, `sandbox.AllocatedBytesCheckEnabled`, `sandbox.AllocatedBytesCheckFactor`, `sandbox.RetainedBytesCheckInterval`, `sandbox.RetainedBytesCheckFactor`, and `sandbox.UseLowMemoryTrigger` described below. -Retained size computation for a context is triggered when a retained bytes estimate exceeds a certain factor of specified `sandbox.MaxHeapMemory`. The estimate is based on heap memory +Retained size computation for a context is triggered when a retained bytes estimate exceeds a certain factor of specified `sandbox.MaxHeapMemory`. +The estimate is based on heap memory [allocated](https://docs.oracle.com/en/java/javase/11/docs/api/jdk.management/com/sun/management/ThreadMXBean.html#getThreadAllocatedBytes\(long\)) by threads where the context has been active. More precisely, the estimate is the result of previous retained bytes computation, if available, plus bytes allocated since the start of the previous computation. -By default the factor of `sandbox.MaxHeapMemory` is 1.0 and it can be customized by the `sandbox.AllocatedBytesCheckFactor` option. The factor must be positive. -For example, let `sandbox.MaxHeapMemory` be 100MB and `sandbox.AllocatedBytesCheckFactor` be 0.5. The retained size computation is first triggered when allocated bytes reach 50MB. +By default the factor of `sandbox.MaxHeapMemory` is 1.0 and it can be customized by the `sandbox.AllocatedBytesCheckFactor` option. +The factor must be positive. +For example, let `sandbox.MaxHeapMemory` be 100MB and `sandbox.AllocatedBytesCheckFactor` be 0.5. +The retained size computation is first triggered when allocated bytes reach 50MB. Let the computed retained size be 25MB, then the next retained size computation is triggered when additional 25MB is allocated, etc. -By default, allocated bytes are checked every 10 milliseconds. This can be configured by `sandbox.AllocatedBytesCheckInterval`. The smallest possible interval is 1ms. Any smaller value is interpreted as 1ms. +By default, allocated bytes are checked every 10 milliseconds. This can be configured by `sandbox.AllocatedBytesCheckInterval`. +The smallest possible interval is 1ms. Any smaller value is interpreted as 1ms. The beginnings of two retained size computations of the same context must be by default at least 10 milliseconds apart. This can be configured by the `sandbox.RetainedBytesCheckInterval` option. The interval must be positive. -The allocated bytes checking for a context can be disabled by the `sandbox.AllocatedBytesCheckEnabled` option. By default it is enabled ("true"). If disabled ("false"), -retained size checking for the context can be triggered only by the low memory trigger. +The allocated bytes checking for a context can be disabled by the `sandbox.AllocatedBytesCheckEnabled` option. +By default it is enabled ("true"). If disabled ("false"), retained size checking for the context can be triggered only by the low memory trigger. When the total number of bytes allocated in the heap for the whole host VM exceeds a certain factor of the total heap memory of the VM, [low memory notification](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/MemoryMXBean.html) is invoked and initiates the following process. -The execution for all engines with at least one execution context which has the `sandbox.MaxHeapMemory` option set is paused, -retained bytes in the heap for each memory-limited context are computed, contexts exceeding their limits are cancelled, and then the execution is resumed. -The default factor is 0.7. This can be configuted by the `sandbox.RetainedBytesCheckFactor` option. The factor must be between 0.0 and 1.0. All contexts using the `sandbox.MaxHeapMemory` option must use the same value for `sandbox.RetainedBytesCheckFactor`. +The execution for all engines with at least one execution context which has the `sandbox.MaxHeapMemory` option set is paused, retained bytes in the heap for each memory-limited context are computed, contexts exceeding their limits are cancelled, and then the execution is resumed. +The default factor is 0.7. This can be configuted by the `sandbox.RetainedBytesCheckFactor` option. +The factor must be between 0.0 and 1.0. All contexts using the `sandbox.MaxHeapMemory` option must use the same value for `sandbox.RetainedBytesCheckFactor`. -The described low memory trigger can be disabled by the `sandbox.UseLowMemoryTrigger` option. By default it is enabled ("true"). If disabled ("false"), -retained size checking for the execution context can be triggered only by the allocated bytes checker. All contexts using the `sandbox.MaxHeapMemory` option must use the same value for `sandbox.UseLowMemoryTrigger`. +The described low memory trigger can be disabled by the `sandbox.UseLowMemoryTrigger` option. +By default it is enabled ("true"). If disabled ("false"), retained size checking for the execution context can be triggered only by the allocated bytes checker. +All contexts using the `sandbox.MaxHeapMemory` option must use the same value for `sandbox.UseLowMemoryTrigger`. If exceeding of the heap memory limit is detected then the polyglot context is cancelled and the execution stops by throwing a [`PolyglotException`](https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/PolyglotException.html) which returns `true` for `isResourceExhausted()`. As soon as the memory limit is triggered, no further application code can be executed with this context. @@ -234,7 +246,7 @@ This can be useful if a known and trusted initialization script should be exclud ### Example Usage -``` +```java try (Context context = Context.newBuilder("js") .allowExperimentalOptions(true) .option("sandbox.MaxCPUTime", "500ms") diff --git a/docs/reference-manual/graalvm-updater.md b/docs/reference-manual/graalvm-updater.md index abf06080ab1a..c005f0711b05 100644 --- a/docs/reference-manual/graalvm-updater.md +++ b/docs/reference-manual/graalvm-updater.md @@ -7,15 +7,6 @@ permalink: /reference-manual/graalvm-updater/ # GraalVM Updater -GraalVM Updater, `gu`, is a command-line utility to install and manage optional GraalVM language runtimes and utilities. -Each of these language runtimes and utilities must be downloaded and installed separately. -To assist you with the installation, these are pre-packaged as JAR files and referenced in the documentation as "components". -As of version 21.0.0, GraalVM Updater has become more efficient, and can be used to update your local GraalVM installation to a newer version or upgrade from a Community to Enterprise Edition. -Read more in [Upgrade GraalVM](#upgrade-graalvm). - -GraalVM Updater is included in the base GraalVM distribution and can be used with the `/bin/gu` launcher. -The source code of GraalVM Updater is located in the `/lib/installer` folder. - * [Component Installation](#component-installation) * [Component Uninstallation](#component-uninstallation) * [Upgrade GraalVM](#upgrade-graalvm) @@ -25,6 +16,15 @@ The source code of GraalVM Updater is located in the `/lib/installer` f * [Configure Proxies](#configure-proxies) * [Replace Components and Files](#replace-components-and-files) +GraalVM Updater, `gu`, is a command-line utility to install and manage optional GraalVM language runtimes and utilities. +Each of these language runtimes and utilities must be downloaded and installed separately. +To assist you with the installation, they are pre-packaged as JAR files and referenced in the documentation as "components". +GraalVM Updater can be also used to update your local GraalVM installation to a newer version or upgrade from a Community to Enterprise Edition. +Read more in [Upgrade GraalVM](#upgrade-graalvm). + +GraalVM Updater is included in the base GraalVM distribution and can be used with the `/bin/gu` launcher. +The source code of GraalVM Updater is located in the `/lib/installer` folder. + ## Component Installation The following GraalVM language runtimes and utilities are available for installation. @@ -36,10 +36,10 @@ Tools/Utilities: * [Java on Truffle](/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible -* [Python](/python/README.md) -- Python 3.8.5-compatible -* [Ruby](/ruby/README.md) -- Ruby 2.7.3-compatible -* [R](/r/README.md) -- GNU R 4.0.3-compatible +* [Node.js](/reference-manual/js/) -- Node.js 14.17.6 compatible +* [Python](/python/README.md) -- Python 3.8.5 compatible +* [Ruby](/ruby/README.md) -- Ruby 2.7.4 compatible +* [R](/r/README.md) -- GNU R 4.0.3 compatible * [Wasm](/wasm/README.md) -- WebAssembly (Wasm) GraalVM Updater verifies whether or not the version of a component is appropriate for the current GraalVM installation. @@ -63,21 +63,15 @@ gu available ```shell gu install ruby ``` -GraalVM Updater first downloads the list of components, then uses the -information in the list to download the actual component package, then installs -it. To see more verbose output during the installation, like the download -progress bar, print versions, and dependency information, use the `-v` -(`--verbose`) switch. - -If a component being installed depends on another component, GraalVM Updater will -search the catalog to find an appropriate dependency and install it as well. If -the required components cannot be found, installation will fail. - -When using custom catalog URLs, it is possible, for a convenience, to set -the environment variable `GRAALVM_CATALOG` pointing to the custom catalog's URL. -GraalVM Updater will use the URL defined by `GRAALVM_CATALOG` in preference to -the builtin ones. You may setup the environment variable in startup or profile -scripts. +GraalVM Updater first downloads the list of components, then uses the information in the list to download the actual component package, then installs it. +To see more verbose output during the installation, like the download progress bar, print versions, and dependency information, use the `-v` (`--verbose`) switch. + +If a component being installed depends on another component, GraalVM Updater will search the catalog to find an appropriate dependency and install it as well. +If the required components cannot be found, installation will fail. + +When using custom catalog URLs, it is possible, for a convenience, to set the environment variable `GRAALVM_CATALOG` pointing to the custom catalog's URL. +GraalVM Updater will use the URL defined by `GRAALVM_CATALOG` in preference to the builtin ones. +You may setup the environment variable in startup or profile scripts. Note: If you need, for some reason to set the `GRAALVM_HOME` environment variable, it may affect `gu` operation. If it is set, it should point to the intended GraalVM installation, same as `JAVA_HOME` and `PATH`. @@ -92,7 +86,7 @@ gu -L install component.jar ``` For example, to install Native Image for Java 11 GraalVM Enterprise distribution on macOS, run: ```shell -gu -L install native-image-installable-svm-java11-darwin-amd64-.jar +gu -L install native-image-installable-svm-svmee-java11-darwin-amd64-.jar ``` The `-L` option, equivalent to `--local-file` or `--file`, installs a component from a downloaded JAR. @@ -112,12 +106,11 @@ GraalVM Updater can then use that folder instead of the catalog: gu install -C /path/to/downloads/directory ComponentId ``` -Specify the directory to use for the components collection. It is possible to type -a component's name (like `ruby`) instead of a filename. GraalVM Updater will also -attempt to find required dependencies in the local component collection. +Specify the directory to use for the components collection. +It is possible to type a component's name (like `ruby`) instead of a filename. +GraalVM Updater will also attempt to find required dependencies in the local component collection. -When installing components from a given directory, you can allow installing all -components which have the correct version number for GraalVM using wildcards: +When installing components from a given directory, you can allow installing all components which have the correct version number for GraalVM using wildcards: ```shell ./gu install -C ~/Download/Components/ native* ``` @@ -243,9 +236,8 @@ GraalVM Updater common options: * `-v, --verbose`: enable verbose output. Print versions and dependency information * `--version`: print version -Oracle GraalVM Enterprise Edition users might need to pass an -additional verification step to login to the Oracle components repository. GraalVM -Updater tool provides options for that: +Oracle GraalVM Enterprise Edition users might need to pass an additional verification step to login to the Oracle components repository. +GraalVM Updater tool provides options for that: * `--public-key / -k `: set the path to a custom GPG public key path * `--username/-U`: enter a username @@ -260,34 +252,24 @@ Runtime options: ## Configure Proxies -If GraalVM Updater needs to reach the component catalog, or download a component -package, it may need to pass through the HTTP/HTTPS proxy, if the network uses one. On -_macOS_, the proxy settings are automatically obtained from the OS. On _Linux_, -ensure that the `http_proxy` and `https_proxy` environment variables are set -appropriately before launching the `gu` tool. Refer to the distribution -and/or desktop environment documentation for the details. +If GraalVM Updater needs to reach the component catalog, or download a component package, it may need to pass through the HTTP/HTTPS proxy, if the network uses one. +On _macOS_, the proxy settings are automatically obtained from the OS. +On _Linux_, ensure that the `http_proxy` and `https_proxy` environment variables are set appropriately before launching the `gu` tool. +Refer to the distribution and/or desktop environment documentation for the details. -GraalVM Updater intentionally does not support an option to disable certificate -or hostname verification, for security reasons. A user may try to add a proxy's -certificate to the GraalVM default security trust store. A user can also -download a component manually to a folder, and then use `gu -L install /path/to/file` or `gu -C /path/to/download/dir install component` to install from a local filesystem. +GraalVM Updater intentionally does not support an option to disable certificate or hostname verification, for security reasons. +A user may try to add a proxy's certificate to the GraalVM default security trust store. +A user can also download a component manually to a folder, and then use `gu -L install /path/to/file` or `gu -C /path/to/download/dir install component` to install from a local filesystem. ### Working without Internet Access -If your machine cannot access and download the catalog and components from -the Internet, either because it is behind a proxy, or for security reasons, -GraalVM Updater can install components from a local directory, or a directory on -a network share accessible on the target machine. +If your machine cannot access and download the catalog and components from the Internet, either because it is behind a proxy, or for security reasons, GraalVM Updater can install components from a local directory, or a directory on a network share accessible on the target machine. -You need to prepare a directory, download all components that you want to install -and their dependencies (in case they require other GraalVM components to work) into -that directory. +You need to prepare a directory, download all components that you want to install and their dependencies (in case they require other GraalVM components to work) into that directory. -Then you can use `gu -L install /path/to/file` (where the `-L` option instructs to use local files, -equivalent to `--local-file` or `--file`). Adding the `-D` option will instruct GraalVM Updater -to look for potential dependencies in the directory next to the -installable file. Additionally, `gu -C /path/to/download/dir install component` can be used, with the specified -directory contents acting as a catalog of components. +Then you can use `gu -L install /path/to/file` (where the `-L` option instructs to use local files, equivalent to `--local-file` or `--file`). +Adding the `-D` option will instruct GraalVM Updater to look for potential dependencies in the directory next to the installable file. +Additionally, `gu -C /path/to/download/dir install component` can be used, with the specified directory contents acting as a catalog of components. Note that with `gu -L` you need to specify the component's file name, while when using `gu -C `, the component name must be used: ```shell @@ -300,13 +282,10 @@ gu -C /tmp/instalables install ruby ## Replace Components and Files -A component may be only installed once. GraalVM Updater refuses to install a -component if a component with the same ID is already installed. However, the -installed component can be replaced. GraalVM Updater first uninstalls the -component and then installs a new package. +A component may be only installed once. GraalVM Updater refuses to install a component if a component with the same ID is already installed. +However, the installed component can be replaced. GraalVM Updater first uninstalls the component and then installs a new package. -To replace a component, use the `-r` -option, and the `-L` (`--local-file` or `--file`) option to treat parameters as local filename of a packaged component: +To replace a component, use the `-r` option, and the `-L` (`--local-file` or `--file`) option to treat parameters as local filename of a packaged component: ```shell gu install -L -r component.jar gu install -r ruby @@ -314,18 +293,16 @@ gu install -r ruby The process is the same as if `gu remove` is run first and `gu install` next. -GraalVM Updater also refuses to overwrite existing files if the -to-be-installed and existing versions differ. There are cases when refreshing -file contents may be needed, such as if they were modified or damaged. In this case, use the `-o` option: +GraalVM Updater also refuses to overwrite existing files if the to-be-installed and existing versions differ. +There are cases when refreshing file contents may be needed, such as if they were modified or damaged. +In this case, use the `-o` option: ```shell gu install -L -o component.jar gu install -o ruby ``` -GraalVM Updater will then instruct the user to replace the contained files of a -component. By default, it will not alter anything. Alternatively, use the `-f` -(`--force`) option, which disables most of the checks, and allows the user to -install non-matching versions. +GraalVM Updater will then instruct the user to replace the contained files of a component. +By default, it will not alter anything. Alternatively, use the `-f` (`--force`) option, which disables most of the checks, and allows the user to install non-matching versions. ### Troubleshooting diff --git a/docs/reference-manual/polyglot-programming.md b/docs/reference-manual/polyglot-programming.md index fb8074f062cc..cf52b542691c 100644 --- a/docs/reference-manual/polyglot-programming.md +++ b/docs/reference-manual/polyglot-programming.md @@ -22,12 +22,10 @@ When writing a language interpreter with Truffle, it will automatically use the By having access to this framework, a Ruby application, for example, can run on the same JVM as a Java application. Also, a host JVM-based language and a guest language can directly interoperate with each other and pass data back and forth in the same memory space. -In order to provide foreign polyglot values in the languages implemented with Truffle, the so-called _polyglot interoperability protocol_ has been developed. This -interoperability protocol consists of a set of standardized messages that every -language implements and uses for foreign polyglot values. The protocol allows -GraalVM to support interoperability between any combination of languages without -requiring them to know of each other. For more details, proceed to the -[High-Performance Cross-Language Interoperability in a Multi-Language Runtime](http://dx.doi.org/10.1145/2816707.2816714) paper. +In order to provide foreign polyglot values in the languages implemented with Truffle, the so-called _polyglot interoperability protocol_ has been developed. +This interoperability protocol consists of a set of standardized messages that every language implements and uses for foreign polyglot values. +The protocol allows GraalVM to support interoperability between any combination of languages without requiring them to know of each other. +For more details, proceed to the [High-Performance Cross-Language Interoperability in a Multi-Language Runtime](http://dx.doi.org/10.1145/2816707.2816714) paper. Throughout this section you learn how to combine multiple languages using GraalVM Polyglot APIs. @@ -44,12 +42,10 @@ The below examples work: It might be required to [rebuild images](/reference-manual/graalvm-updater/#rebuild-images) to access languages installed with `gu`. * with native executables (e.g., `native-image --language:js`). -For native launchers and native executables using Java as a Target Language -and accessing classes other than Java arrays, it is required to recompile the image and provide +For native launchers and native executables using Java as a Target Language and accessing classes other than Java arrays, it is required to recompile the image and provide a [reflection configuration file](/reference-manual/native-image/Reflection/). -Note: To start an application with LLVM as a Target Language, make sure -to precompile the _polyglot.c_ file provided below. +Note: To start an application with LLVM as a Target Language, make sure to precompile the _polyglot.c_ file provided below. ### Start from JavaScript / Node.js @@ -134,7 +130,6 @@ graalpython --polyglot --jvm polyglot.py 42 ``` - ### Start Language Java Create the file `Polyglot.java`: @@ -169,9 +164,8 @@ tab4type="c" tab4id="c_to_python" tab4name="Python" tab4path="polyglot_ref/c_to_ tab5type="c" tab5id="c_to_java" tab5name="Java" tab5path="polyglot_ref/c_to_java.c" %} -The example C code has to be compiled to LLVM bitcode using the LLVM frontend -such as `clang`. A user can use `clang` shipped with GraalVM by installing a -pre-built LLVM toolchain support: +The example C code has to be compiled to LLVM bitcode using the LLVM frontend such as `clang`. +A user can use `clang` shipped with GraalVM by installing a pre-built LLVM toolchain support: ```shell gu install llvm-toolchain @@ -187,12 +181,10 @@ lli --polyglot polyglot ## Polyglot Launcher -With polyglot applications it is often impossible to decide what the primary -language of an application is. Therefore, an experimental new -launcher, called `polyglot`, has been added to GraalVM. For the moment, this launcher runs code -for JavaScript, Ruby, and R without requiring the selection of a primary -language. The polyglot launcher does not require the `--polyglot` option; it is -enabled by default. +With polyglot applications it is often impossible to decide what the primary language of an application is. +Therefore, an experimental new launcher, called `polyglot`, has been added to GraalVM. +For the moment, this launcher runs code for JavaScript, Ruby, and R without requiring the selection of a primary language. +The polyglot launcher does not require the `--polyglot` option; it is enabled by default. This is how you can run a polyglot application by using the examples from above: @@ -210,20 +202,20 @@ polyglot --jvm --shell If you have installed all optional languages packs to the core GraalVM installation, then the Polyglot Shell will look like: ```shell -GraalVM MultiLanguage Shell 21.2.0 +GraalVM MultiLanguage Shell 21.3.0 Copyright (c) 2013-2021, Oracle and/or its affiliates Java version 1.8|11 -JavaScript version 21.2.0 +JavaScript version 21.3.0 Python version 3.8.5 R version 4.0.3 -Ruby version 2.7.3 +Ruby version 2.7.4 Usage: - Use Ctrl+n to switch language and Ctrl+d to exit. + Use Ctrl+n to switch language and Ctrl+d to exit. Enter -usage to get a list of available commands. js> ``` -Note: The `polyglot` launcher and the _Polyglot Shell_ are experimental features in GraalVM. +> Note: The `polyglot` launcher and the _Polyglot Shell_ are experimental features in GraalVM. ## Polyglot Options @@ -243,8 +235,7 @@ You can configure a language engine for better throughput or startup. ## Passing Options for Language Launchers Every language launcher has been extended with a set of so called _polyglot options_. -Polyglot options allow users of any language launcher to access the -options of other languages supported by GraalVM (implemented with the Truffle language implementation framework). +Polyglot options allow users of any language launcher to access theoptions of other languages supported by GraalVM (implemented with the Truffle language implementation framework). The format is: `--.=`. For example, the `R` launcher also supports the `--js.atomics=true` JavaScript option. @@ -294,8 +285,7 @@ javac OptionsTest.java java OptionsTest ``` -Note: Tools options can be passed in the same way. -Options cannot be modified after the context was created. +> Note: Tools options can be passed in the same way. Options cannot be modified after the context was created. ## Passing Options Using JVM Arguments @@ -327,4 +317,4 @@ javac SystemPropertiesTest.java java -Dpolyglot.js.strict=true SystemPropertiesTest ``` -Note: System properties are read once when the polyglot context is created. Subsequent changes have no effect. +> Note: System properties are read once when the polyglot context is created. Subsequent changes have no effect. diff --git a/docs/security/security-guide.md b/docs/security/security-guide.md index a1b65bd0b2c0..3d4f12fe4593 100644 --- a/docs/security/security-guide.md +++ b/docs/security/security-guide.md @@ -109,14 +109,9 @@ This can either result in sensitive data ending up in the snapshot or fixing ini Developers can request static initializers that process sensitive information to be instead executed at runtime by either specifying the `--initialize-at-run-time` CLI parameter when building a native image, or making use of the `RuntimeClassInitialization` API. -Native-image provides multiple ways to specify the certificate file used to -define the default TrustStore. While the default behavior for native-image is -to capture and use the default TrustStore from the buildtime host environment, -this can be changed at runtime by setting the "javax.net.ssl.trustStore\*" -system properties. Please see the -[documentation](/reference-manual/native-image/CertificateManagement/) for more -details. - +Native-image provides multiple ways to specify the certificate file used to define the default TrustStore. +While the default behavior for native-image is to capture and use the default TrustStore from the buildtime host environment, this can be changed at runtime by setting the "javax.net.ssl.trustStore\*" system properties. +Please see the [documentation](/reference-manual/native-image/CertificateManagement/) for more details. In addition, developers can run the native image builder in a dedicated environment, such as a container, that does not contain any sensitive information in the first place. diff --git a/docs/tools/chrome-debugger.md b/docs/tools/chrome-debugger.md index 5d87871181d2..7cfa1048d521 100644 --- a/docs/tools/chrome-debugger.md +++ b/docs/tools/chrome-debugger.md @@ -26,11 +26,10 @@ console.log("Server running at http://localhost:8000/"); 1. Save this program as `HelloWorld.js` and then run: ```shell -node --inspect --jvm HelloWorld.js -Debugger listening on port 9229. -To start debugging, open the following URL in Chrome: - devtools://devtools/bundled/js_app.html?ws=127.0.1.1:9229/76fcb6dd-35267eb09c3 -Server running at http://localhost:8000/ +$JAVA_HOME/bin/node --inspect --jvm HelloWorld.js +Debugger listening on ws://127.0.0.1:9229/SBqxI5YIqtREaDrXkFr8hLE0HL1AfKx8TjkI8qPMq2s +For help, see: https://www.graalvm.org/tools/chrome-debugger +E.g. in Chrome open: devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/SBqxI5YIqtREaDrXkFr8hLE0HL1AfKx8TjkI8qPMq2s ``` 2. Navigate to `http://localhost:8000/` in your browser to launch the node application. diff --git a/docs/tools/code-coverage.md b/docs/tools/code-coverage.md index 5367925cbe33..a4935a6d73be 100644 --- a/docs/tools/code-coverage.md +++ b/docs/tools/code-coverage.md @@ -7,17 +7,10 @@ permalink: /tools/code-coverage/ # Code Coverage Command Line Tool -As of version 19.3.0, GraalVM provides a **code coverage command line tool** -that lets users record and analyze the source code coverage of a particular execution -of code. +GraalVM provides a **code coverage command line tool** that lets users record and analyze the source code coverage of a particular execution of code. -Code coverage, as a percentage of source code lines, functions, or statements -covered, is an important metric for understanding a particular source code -execution, and is commonly associated with test quality (test coverage). -Providing a visual coverage overview for individual lines of code shows the -developer which code paths are covered and which are not, giving insight into -the character of the execution which can, for example, inform further testing -efforts. +Code coverage, as a percentage of source code lines, functions, or statements covered, is an important metric for understanding a particular source code execution, and is commonly associated with test quality (test coverage). +Providing a visual coverage overview for individual lines of code shows the developer which code paths are covered and which are not, giving insight into the character of the execution which can, for example, inform further testing efforts. The example application below will be used to demonstrate GraalVM's code coverage capabilities. This application defines a @@ -96,11 +89,10 @@ Shows what percent of each element was covered during execution /path/to/primes.js | 20.69% | 26.67% | 22.22% -------------------------------------------------------- ``` -The tracer prints a coverage histogram for each source file. You can see that -statement coverage is roughly 20%, line coverage is roughly 26%, and root coverage (the -term "root" covers functions, methods, etc.) is 22.22%. This tells your that our -simple tests are not particularly good at exercising the source code. Next you -will figure out which parts of the code are not covered. +The tracer prints a coverage histogram for each source file. +You can see that statement coverage is roughly 20%, line coverage is roughly 26%, and root coverage (the term "root" covers functions, methods, etc.) is 22.22%. +This tells your that our simple tests are not particularly good at exercising the source code. +Next you will figure out which parts of the code are not covered. 4. Run `js primes.js --coverage --coverage.Output=detailed`. Prepare for a somewhat verbose output. Specifying the output as `detailed` will print all the source code lines with a @@ -175,21 +167,16 @@ p if (n > cache.length) { return calculatePrime(n); } -------------------------------------------------------- ``` -As the legend at the beginning of the output explains, lines that are covered by -the execution are preceded with a `+`. Lines not covered by the execution are -preceded with a `-`. Lines that are covered partially are preceded with `p` (e.g., when an `if` -statement is covered but only one branch is taken, consider the other bench -to be incidentally covered). +As the legend at the beginning of the output explains, lines that are covered by the execution are preceded with a `+`. +Lines not covered by the execution are preceded with a `-`. +Lines that are covered partially are preceded with `p` (e.g., when an `if` statement is covered but only one branch is taken, consider the other bench to be incidentally covered). -Looking at the output you can see that the `calculatePrime` function and all its -calls are never executed. Looking again at the assertions and the `getPrime` -function, it becomes clear that our tests always hit the cache. Thus most of the -code is never executed. You can improve on that. +Looking at the output you can see that the `calculatePrime` function and all its calls are never executed. Looking again at the assertions and the `getPrime` +function, it becomes clear that our tests always hit the cache. +Thus most of the code is never executed. You can improve on that. -5. Add `console.assert(getPrime(30) == 113);` to the end of the `primes.js` file -and run `js primes.js --coverage`. Since the new assertion added calls -`getPrime` with 30 (our cache only has 20 entries) the coverage will look like -this: +5. Add `console.assert(getPrime(30) == 113);` to the end of the `primes.js` file and run `js primes.js --coverage`. Since the new assertion added calls +`getPrime` with 30 (our cache only has 20 entries) the coverage will look like this: ```shell js primes.js --coverage @@ -205,11 +192,9 @@ Code coverage histogram. ## Integrating with Other Tools -The code coverage tool provides ways to integrate with other tools. Running -with `--coverage.Output=lcov` produces output in the commonly used -[lcov](https://linux.die.net/man/1/lcov) format which is used by multiple tools -(e.g., `genhtml`) to display coverage data. Take a look at the next example that -shows how to visualise coverage of a Node.js app with Visual Studio Code. +The code coverage tool provides ways to integrate with other tools. +Running with `--coverage.Output=lcov` produces output in the commonly used [lcov](https://linux.die.net/man/1/lcov) format which is used by multiple tools (e.g., `genhtml`) to display coverage data. +Take a look at the next example that shows how to visualise coverage of a Node.js app with Visual Studio Code. 1. Copy the following code into a new file named `nodeapp.js`: @@ -232,29 +217,27 @@ app.get('/shutdown', (req, res) => { app.listen(port, () => console.log(`Example app listening on port ${port}!`)) ``` -2. Install the express module dependency: `npm install express`. +2. Install the express module dependency: +```shell +$JAVA_HOME/bin/npm install express +``` 3. Launch Visual Studio Code and install a code coverage plugin that supports _lcov_. The [Code Coverage Highlighter](https://marketplace.visualstudio.com/items?itemName=brainfit.vscode-coverage-highlighter) is used for this example, but other plugins should work similarly. 4. Run the _nodeapp.js_ file with coverage enabled and configured: ```shell -node --coverage --coverage.Output=lcov \ +$JAVA_HOME/bin/node --coverage --coverage.Output=lcov \ --coverage.OutputFile=coverage/lcov.info \ nodeapp.js ``` -Note that the Code Coverage Highlighter plugin looks for the `lcov.info` file in -the `coverage` directory by default, so direct the output of the code -coverage tool there. +Note that the Code Coverage Highlighter plugin looks for the `lcov.info` file in the `coverage` directory by default, so direct the output of the code coverage tool there. 5. Visit [localhost:3000/](http://localhost:3000/) in your browser, then visit [localhost:3000/shutdown](http://localhost:3000/shutdown) to close the app. -6. Open Visual Studio Code, then open the folder containing the `nodeapp.js` file -and `coverage` directory and you should be greeted with an image similar to the following: +6. Open Visual Studio Code, then open the folder containing the `nodeapp.js` file and `coverage` directory and you should be greeted with an image similar to the following: ![](img/vscode-coverage.png) -If you wish to integrate the data gathered by the GraalVM code coverage tool -with your own visualisation, the `--coverage.Output=json` option results in -the output being a JSON file with the raw data gathered by the tracker. +If you wish to integrate the data gathered by the GraalVM code coverage tool with your own visualisation, the `--coverage.Output=json` option results in the output being a JSON file with the raw data gathered by the tracker. diff --git a/docs/tools/dap.md b/docs/tools/dap.md index c890f7b60aea..838e7a37a080 100644 --- a/docs/tools/dap.md +++ b/docs/tools/dap.md @@ -7,7 +7,7 @@ permalink: /tools/dap/ # Debug Adapter Protocol -GraalVM supports debugging of guest language applications, written in any of the supported languages, i.e., JavaScript/TypeScript, Python R, Ruby, and provides a built-in implementation of the [Debug Adapter Protocol (DAP)](https://microsoft.github.io/debug-adapter-protocol/). +GraalVM supports debugging of guest language applications, written in any of the supported languages, i.e., JavaScript/TypeScript, Python, R, Ruby, and provides a built-in implementation of the [Debug Adapter Protocol (DAP)](https://microsoft.github.io/debug-adapter-protocol/). By definition, Debug Adapter Protocol is to standardize the "communication" between the debugging component and a concrete debugger or runtime. This allows you to attach compatible debuggers such as Visual Studio Code (VS Code) to GraalVM. @@ -41,12 +41,12 @@ app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 2. Install the `express` module dependency in the directory where you saved the file: ```shell -npm install express +$JAVA_HOME/bin/npm install express ``` 3. Run the application with DAP enabled: ```shell -node --dap App.js +$JAVA_HOME/bin/node --dap App.js [Graal DAP] Starting server and listening on localhost/127.0.0.1:4711 ``` diff --git a/docs/tools/graalvm-insight.md b/docs/tools/graalvm-insight.md index 752869b2375c..39e95e1c6aef 100644 --- a/docs/tools/graalvm-insight.md +++ b/docs/tools/graalvm-insight.md @@ -7,22 +7,16 @@ permalink: /tools/graalvm-insight/ # GraalVM Insight -GraalVM Insight is a multipurpose, flexible tool for writing reliable -microservices solutions that traces program runtime behavior and gathers insights. +GraalVM Insight is a multipurpose, flexible tool for writing reliable microservices solutions that traces program runtime behavior and gathers insights. -The dynamic nature of the tool helps users to selectively apply tracing pointcuts on -already running applications with no loss of performance. Insight -also provides detailed access to runtime behavior of a program, allowing users to -inspect values and types at invocation or allocation sites. GraalVM Insight further permits users to -modify computed values, interrupt execution, and quickly experiment with -behavioral changes without modifying the application code. +The dynamic nature of the tool helps users to selectively apply tracing pointcuts on already running applications with no loss of performance. +Insight also provides detailed access to runtime behavior of a program, allowing users to inspect values and types at invocation or allocation sites. +GraalVM Insight further permits users to modify computed values, interrupt execution, and quickly experiment with behavioral changes without modifying the application code. This page provides information on GraalVM Insight as of the 20.1 version. To learn about Insight on versions 20.0 and 19.3, proceed [here](https://github.com/oracle/graal/blob/release/graal-vm/20.0/tools/docs/T-Trace.md). -Note: The GraalVM Insight tool is offered as a technology preview and requires the user to -pass the `--experimental-options` option in order to enable the `--insight` -instrument. +Note: The GraalVM Insight tool is offered as a technology preview and requires the user to pass the `--experimental-options` option in order to enable the `--insight` instrument. ## Start Using GraalVM Insight @@ -32,30 +26,25 @@ insight.on('source', function(ev) { print(`Loading ${ev.characters.length} characters from ${ev.name}`); }); ``` -2. Having set `JAVA_HOME` to the GraalVM home directory, start the `node` launcher with -the `--insight` tool and observe what scripts are being loaded and -evaluated: +2. Having set `JAVA_HOME` to the GraalVM home directory, start the `node` launcher with the `--insight` tool and observe what scripts are being loaded and evaluated: ```shell $JAVA_HOME/bin/node --experimental-options --insight=source-tracing.js --js.print -e "print('The result: ' + 6 * 7)" | tail -n 10 -Loading 29938 characters from url.js -Loading 345 characters from internal/idna.js -Loading 12642 characters from punycode.js -Loading 33678 characters from internal/modules/cjs/loader.js -Loading 13058 characters from vm.js -Loading 52408 characters from fs.js -Loading 15920 characters from internal/fs/utils.js -Loading 505 characters from [eval]-wrapper +Loading 215 characters from internal/modules/esm/transform_source.js +Loading 12107 characters from internal/modules/esm/translators.js +Loading 1756 characters from internal/modules/esm/create_dynamic_module.js +Loading 12930 characters from internal/vm/module.js +Loading 2710 characters from internal/modules/run_main.js +Loading 308 characters from module.js +Loading 10844 characters from internal/source_map/source_map.js +Loading 170 characters from [eval]-wrapper Loading 29 characters from [eval] The result: 42 ``` -The _source-tracing.js_ script used the provided `insight` object to -attach a source listener to the runtime. Whenever the script was loaded, the -listener got notified of it and could take an action -- printing the length and -name of the processed script. +The _source-tracing.js_ script used the provided `insight` object to attach a source listener to the runtime. +Whenever the script was loaded, the listener got notified of it and could take an action -- printing the length and name of the processed script. The Insight information can be collected to a print statement or a histogram. -The following _function-histogram-tracing.js_ script counts all method invocations -and dumps the most frequent ones when the execution of a program is over: +The following _function-histogram-tracing.js_ script counts all method invocations and dumps the most frequent ones when the execution of a program is over: ```javascript var map = new Map(); @@ -90,39 +79,31 @@ insight.on('enter', function(ev) { insight.on('close', dumpHistogram); ``` -The `map` is a global variable shared inside of the Insight script that allows the -code to share data between the `insight.on('enter')` function and the `dumpHistogram` -function. The latter is executed when the node process execution is over -(registered via `insight.on('close', dumpHistogram`). Invoke it as: +The `map` is a global variable shared inside of the Insight script that allows the code to share data between the `insight.on('enter')` function and the `dumpHistogram` +function. +The latter is executed when the node process execution is over (registered via `insight.on('close', dumpHistogram`). +Invoke it as: ```shell $JAVA_HOME/bin/node --experimental-options --insight=function-histogram-tracing.js --js.print -e "print('The result: ' + 6 * 7)" The result: 42 -=== Histogram === -543 calls to isPosixPathSeparator -211 calls to E -211 calls to makeNodeErrorWithCode -205 calls to NativeModule -198 calls to uncurryThis -154 calls to :=> -147 calls to nativeModuleRequire -145 calls to NativeModule.compile - 55 calls to internalBinding - 53 calls to :anonymous - 49 calls to :program - 37 calls to getOptionValue - 24 calls to copyProps +==== Histogram ==== +328 calls to isPosixPathSeparator +236 calls to E +235 calls to makeNodeErrorWithCode +137 calls to :=> + 64 calls to :program + 64 calls to :anonymous + 45 calls to getOptionValue + 45 calls to getOptionsFromBinding + 26 calls to hideStackFrames 18 calls to validateString - 13 calls to copyPrototype - 13 calls to hideStackFrames - 13 calls to addReadOnlyProcessAlias -================= + 12 calls to defineColorAlias +=================== ``` ## Polyglot Tracing -The previous examples were written in JavaScript, but due to GraalVM's polyglot -nature, you can take the same instrument and use it in a program written in, -e.g., the Ruby language. +The previous examples were written in JavaScript, but due to GraalVM's polyglot nature, you can take the same instrument and use it in a program written in, e.g., the Ruby language. 1. Create the _source-trace.js_ file: ```javascript @@ -145,8 +126,7 @@ Hello from GraalVM Ruby! ``` It is necessary to start the Ruby launcher with the `--polyglot` parameter, as the _source-tracing.js_ script remains written in JavaScript. -A user can instrument any language on top of GraalVM, but also the Insight scripts can be -written in any of the GraalVM supported languages (implemented with the [Truffle language implementation framework](../../truffle/docs/README.md)). +A user can instrument any language on top of GraalVM, but also the Insight scripts can be written in any of the GraalVM supported languages (implemented with the [Truffle language implementation framework](../../truffle/docs/README.md)). 1. Create the _source-tracing.rb_ Ruby file: ```ruby @@ -178,10 +158,9 @@ With Ruby: 42 ## Inspecting Values -GraalVM Insight not only allows one to trace where the program execution is happening, -it also offers access to values of local variables and function arguments during -program execution. You can, for example, write an instrument that shows the value of -argument `n` in the function `fib`: +GraalVM Insight not only allows one to trace where the program execution is happening, it also offers access to values of local variables and function arguments during +program execution. +You can, for example, write an instrument that shows the value of argument `n` in the function `fib`: ```javascript insight.on('enter', function(ctx, frame) { print('fib for ' + frame.n); @@ -191,9 +170,8 @@ insight.on('enter', function(ctx, frame) { }); ``` -This instrument uses the second function argument, `frame`, to get access to values of -local variables inside every instrumented function. The above script -also uses `rootNameFilter` to apply its hook only to the function named `fib`: +This instrument uses the second function argument, `frame`, to get access to values of local variables inside every instrumented function. +The above script also uses `rootNameFilter` to apply its hook only to the function named `fib`: ```javascript function fib(n) { if (n < 1) return 0; @@ -203,9 +181,7 @@ function fib(n) { print("Two is the result " + fib(3)); ``` -When the instrument is stored in a `fib-trace.js` file and the actual code is in -`fib.js`, invoking the following command yields detailed information about the -program execution and parameters passed between function invocations: +When the instrument is stored in a `fib-trace.js` file and the actual code is in `fib.js`, invoking the following command yields detailed information about the program execution and parameters passed between function invocations: ```shell $JAVA_HOME/bin/node --experimental-options --insight=fib-trace.js --js.print fib.js fib for 3 diff --git a/docs/tools/ideal-graph-visualizer.md b/docs/tools/ideal-graph-visualizer.md index 8c2ab3321b41..da869ba73575 100644 --- a/docs/tools/ideal-graph-visualizer.md +++ b/docs/tools/ideal-graph-visualizer.md @@ -7,13 +7,13 @@ permalink: /tools/igv/ # Ideal Graph Visualizer -Ideal Graph Visualizer (IGV) is a developer tool allowing users to analyze compilation -graphs and investigate performance issues. The tool is essential for any -language implementers building on top of **Oracle GraalVM Enterprise Edition**. It is -available as a separate download on [Oracle Technology Network](https://www.oracle.com/technetwork/oracle-labs/program-languages/downloads/index.html) and requires accepting the Oracle Technology Network Developer License. +Ideal Graph Visualizer (IGV) is a developer tool allowing users to analyze compilation graphs and investigate performance issues. +The tool is essential for any language implementers building on top of **Oracle GraalVM Enterprise Edition**. +It is available as a separate download on [Oracle Technology Network](https://www.oracle.com/downloads/graalvm-downloads.html) and requires accepting the Oracle Technology Network Developer License. IGV is developed to view and inspect intermediate representation graphs -- a language-independent intermediate representation (IR) between the source -language and the machine code, generated by the compiler. See [Dumping Graphs](/tools/igv/#dumping-graphs) below. +language and the machine code, generated by the compiler. +See [Dumping Graphs](/tools/igv/#dumping-graphs) below. 1. Unzip the downloaded package and enter `bin` directory: ```shell @@ -40,13 +40,13 @@ puts js_obj[:msg] puts js_obj[:payload].join(' ') ``` -4. From another console window, make sure the `ruby` runtime is available in GraalVM Enterprise, -and connect the `Test.rb` script to the running IGV: +4. From another console window, make sure the `ruby` runtime is available in GraalVM Enterprise, and connect the `Test.rb` script to the running IGV: ```shell gu list ruby --jvm --polyglot --vm.Dgraal.Dump=:1 --vm.Dgraal.PrintGraph=Network Test.rb ``` -This causes GraalVM Enterprise to dump compiler graphs in the IGV format over the network to an IGV process listening on `127.0.0.1:4445`. Once the connection is made, you are able to see the graphs in the Outline window. +This causes GraalVM Enterprise to dump compiler graphs in the IGV format over the network to an IGV process listening on `127.0.0.1:4445`. +Once the connection is made, you are able to see the graphs in the Outline window. Find, e.g., the `java.lang.String.char(int)` folder and open its After Parsing graph by double-clicking. If the node has `sourceNodePosition` property, then the Processing window will attempt to display its location and the entire stacktrace. @@ -58,57 +58,47 @@ Select a node in the graph and press the Go to Source button in the Stack View w ![](img/IGV_add_source.png) -Graphs navigation is also available from the Context menu, enabled by focusing -and right-clicking a specific graph node. The Extract Nodes option will re-render -a graph and display only the selected nodes and their neighbors. +Graphs navigation is also available from the Context menu, enabled by focusing and right-clicking a specific graph node. +The Extract Nodes option will re-render a graph and display only the selected nodes and their neighbors. ![](img/IGV_context_menu.png) -If the graph is larger than the screen, manipulate with the Satellite view button -in the main toolbar to move the viewport rectangle. +If the graph is larger than the screen, manipulate with the Satellite view button in the main toolbar to move the viewport rectangle. ![](img/IGV_satellite_view.png) -For user preference, the graph color scheme is adjustable by editing -the Coloring filter, enabled by default in the left sidebar. +For user preference, the graph color scheme is adjustable by editing the Coloring filter, enabled by default in the left sidebar. ## Viewing Source Code -Source code views can be opened in manual and assisted modes. Once you select a node -in the graph view, the Processing view will open. If the IGV knows where the source code -for the current frame is, the green Go to Source arrow is enabled. If the IGV does not -know where the source is, the line is greyed out and a Looking Glass button appears. +Source code views can be opened in manual and assisted modes. Once you select a node in the graph view, the Processing view will open. +If the IGV knows where the source code for the current frame is, the green Go to Source arrow is enabled. +If the IGV does not know where the source is, the line is greyed out and a Looking Glass button appears. ![](img/IGV_add_source.png) Press it and select Locate in Java project to locate the correct project in the dialog. The IGV hides projects which do not contain the required source file. The Source Collections serves to display the stand alone roots added by "Add root of sources" general action. -If the source is located using the preferred method (i.e., from a Java project), -its project can be later managed on the Project tab. That one is initially hidden, -but you can display the list of opened projects using Window -> Projects. +If the source is located using the preferred method (i.e., from a Java project), its project can be later managed on the Project tab. +That one is initially hidden, but you can display the list of opened projects using Window -> Projects. ## Dumping Graphs -The IGV tool is developed to allow GraalVM Enterprise language implementers -to optimize their languages assembled with the [Language Implentation Framework](/graalvm-as-a-platform/language-implementation-framework/). As a development -tool it should not be installed to production environments. - -To dump the GraalVM compiler graphs from an embedded Java application to the IGV, -you need to add options to GraalVM-based processes. Depending on the language/VM -used, you may need to prefix the options by `--vm`. See the particular -language's documentation for the details. The main option to add is -`-Dgraal.Dump=:1`. This will dump graphs in an IGV readable format to the local -file system. To send the dumps directly to the IGV over the network, add -`-Dgraal.PrintGraph=Network` when starting a GraalVM instance. Optionally a -port can be specified. Then dumps are sent to the IGV from the running GraalVM on -localhost. If the IGV does not listen on localhost, Options -> Ideal Graph Settings| -Accept Data From Network can be checked. If there is not an IGV instance -listening on `127.0.0.1` or it cannot be connected to, the dumps will be -redirected to the local file system. The file system location is `graal_dumps/` -under the current working directory of the process and can be changed with the -`-Dgraal.DumpPath` option. - -In case an older GraalVM Enterprise is used, you may need to explicitly request that dumps -include the `nodeSourcePosition` property. This is done by adding the -`-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints` options. +The IGV tool is developed to allow GraalVM Enterprise language implementers to optimize their languages assembled with the [Language Implentation Framework](/graalvm-as-a-platform/language-implementation-framework/). +As a development tool it should not be installed to production environments. + +To dump the GraalVM compiler graphs from an embedded Java application to the IGV, you need to add options to GraalVM-based processes. +Depending on the language/VM used, you may need to prefix the options by `--vm`. +See the particular language's documentation for the details. +The main option to add is `-Dgraal.Dump=:1`. +This will dump graphs in an IGV readable format to the local file system. +To send the dumps directly to the IGV over the network, add `-Dgraal.PrintGraph=Network` when starting a GraalVM instance. +Optionally, a port can be specified. +Then dumps are sent to the IGV from the running GraalVM on localhost. +If the IGV does not listen on localhost, Options -> Ideal Graph Settings and Accept Data From Network can be checked. +If there is not an IGV instance listening on `127.0.0.1` or it cannot be connected to, the dumps will be redirected to the local file system. +The file system location is `graal_dumps/` under the current working directory of the process and can be changed with the `-Dgraal.DumpPath` option. + +In case an older GraalVM Enterprise is used, you may need to explicitly request that dumps include the `nodeSourcePosition` property. +This is done by adding the `-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints` options. diff --git a/docs/tools/lsp.md b/docs/tools/lsp.md index f831f89238ad..bd75d6d6430f 100644 --- a/docs/tools/lsp.md +++ b/docs/tools/lsp.md @@ -16,7 +16,7 @@ Note: The GraalVM Language Server is offered as a technology preview and require user to pass the `--experimental-options` option for its activation. ```shell -node --experimental-options --lsp app.js +$JAVA_HOME/bin/node --experimental-options --lsp app.js [Graal LSP] Starting server and listening on localhost/127.0.0.1:8123 Example app listening on port 3000! ``` From 89dea1135f3087963766765f39b9f9a375e5d670 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Tue, 5 Oct 2021 15:13:48 +0200 Subject: [PATCH 315/681] Include a native-image-configure script launcher in native-image installables. --- substratevm/mx.substratevm/mx_substratevm.py | 3 +++ vm/ci_includes/vm.hocon | 4 ++-- vm/mx.vm/ce-complete | 4 ++-- vm/mx.vm/ce-no_native | 2 +- vm/mx.vm/mx_vm.py | 4 ++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index bfed15e9a0be..16e87119beb3 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -1032,6 +1032,9 @@ def _native_image_configure_extra_jvm_args(): ) ], jlink=False, + installable_id='native-image', + installable=True, + priority=10, )) diff --git a/vm/ci_includes/vm.hocon b/vm/ci_includes/vm.hocon index fd8cbd37a019..efc29712ed17 100644 --- a/vm/ci_includes/vm.hocon +++ b/vm/ci_includes/vm.hocon @@ -30,9 +30,9 @@ custom_vm_darwin: {} vm_profiles: [] collect_profiles: [] -non-product-vm-components: "nju,nic,dis,pbm,llmulrl,elau" +non-product-vm-components: "nju,dis,pbm,llmulrl,elau" non-product-vm-components-windows: ${non-product-vm-components}",llp" -non-product-native-launchers: "RMain,polybench" +non-product-native-launchers: "RMain,polybench,native-image-configure" vm_setup: { short_name: ce diff --git a/vm/mx.vm/ce-complete b/vm/mx.vm/ce-complete index 29f1021891a8..0e9a641bf322 100644 --- a/vm/mx.vm/ce-complete +++ b/vm/mx.vm/ce-complete @@ -1,5 +1,5 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-nodejs,truffleruby,graalpython,/wasm,/espresso DISABLE_INSTALLABLES=true -EXCLUDE_COMPONENTS=nju,njucp,nic,dis,pbm,pmh,llmulrl,elau -FORCE_BASH_LAUNCHERS=polyglot +EXCLUDE_COMPONENTS=nju,njucp,dis,pbm,pmh,llmulrl,elau +FORCE_BASH_LAUNCHERS=polyglot,native-image-configure SKIP_LIBRARIES=polyglot diff --git a/vm/mx.vm/ce-no_native b/vm/mx.vm/ce-no_native index 8372159778ee..4edb3c961621 100644 --- a/vm/mx.vm/ce-no_native +++ b/vm/mx.vm/ce-no_native @@ -2,4 +2,4 @@ DYNAMIC_IMPORTS=/substratevm,/tools,/sulong,/graal-js DISABLE_INSTALLABLES=ni,nil FORCE_BASH_LAUNCHERS=true SKIP_LIBRARIES=true -EXCLUDE_COMPONENTS=nju,njucp,nic,llp,lg,dis,pbm,pmh,llmulrl +EXCLUDE_COMPONENTS=nju,njucp,llp,lg,dis,pbm,pmh,llmulrl diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index 23527feb4938..e956eb4630c5 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -129,11 +129,11 @@ # pylint: disable=line-too-long ce_components = ['bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'poly', 'polynative', 'pro', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] -ce_complete_components = ['bpolyglot', 'cmp', 'cov', 'dap', 'ejvm', 'gu', 'gvm', 'gwa', 'ins', 'insight', 'insightheap', 'java', 'js', 'lg', 'libpoly', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nil', 'njs', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rby', 'rbyl', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] +ce_complete_components = ['bpolyglot', 'bnative-image-configure', 'cmp', 'cov', 'dap', 'ejvm', 'gu', 'gvm', 'gwa', 'ins', 'insight', 'insightheap', 'java', 'js', 'lg', 'libpoly', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nic', 'nil', 'njs', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rby', 'rbyl', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] ce_ruby_components = ['cmp', 'cov', 'dap', 'gvm', 'ins', 'insight', 'insightheap', 'lg', 'llp', 'llrc', 'llrn', 'lsp', 'nfi', 'pro', 'rby', 'rbyl', 'rgx', 'sdk', 'svm', 'svmnfi', 'tfl', 'tflm', 'vvm'] ce_python_components = ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgu', 'bjs', 'blli', 'bllimul', 'bnative-image', 'bnative-image-configure', 'bpolybench', 'bpolyglot', 'cmp', 'cov', 'dap', 'dis', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llmulrl', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nic', 'nil', 'nju', 'njucp', 'pbm', 'pmh', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svml', 'svmnfi', 'tfl', 'tflm', 'vvm'] ce_fastr_components = ce_components + ['R', 'llp', 'bRMain'] -ce_no_native_components = ['bgu', 'bjs', 'blli', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgraalvm-native-binutil', 'bnative-image', 'bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lsp', 'nfi', 'ni', 'nil', 'polynative', 'pro', 'rgx', 'sdk', 'llrc', 'llrn', 'llrl', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'libpoly', 'poly', 'vvm'] +ce_no_native_components = ['bgu', 'bjs', 'blli', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgraalvm-native-binutil', 'bnative-image', 'bnative-image-configure', 'bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lsp', 'nfi', 'ni', 'nic', 'nil', 'polynative', 'pro', 'rgx', 'sdk', 'llrc', 'llrn', 'llrl', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'libpoly', 'poly', 'vvm'] mx_sdk_vm.register_vm_config('ce', ['insight', 'insightheap', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'js', 'lg', 'libpoly', 'lsp', 'nfi', 'poly', 'bpolyglot', 'polynative', 'pro', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'tfl', 'tflm', 'vvm'], _suite, env_file='ce-win') mx_sdk_vm.register_vm_config('ce', ce_components, _suite, env_file='ce-aarch64') From 913217ca01ec1821fdc94e773df68e812b8e8f15 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Wed, 6 Oct 2021 22:38:32 +0200 Subject: [PATCH 316/681] Drop explicit designation of bash launchers in installables. --- sdk/mx.sdk/mx_sdk_vm_impl.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index d17455695618..4c2b3a9748c7 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -2265,10 +2265,6 @@ def create_archive(path, **_kw_args): other_involved_components += [c for c in registered_graalvm_components(stage1=True) if c.short_name in ('svm', 'svmee')] name = '{}_INSTALLABLE'.format(component.installable_id.replace('-', '_').upper()) - if other_involved_components: - for launcher_config in launcher_configs: - if _force_bash_launchers(launcher_config): - name += '_B' + basename(launcher_config.destination).upper() for library_config in library_configs: if _skip_libraries(library_config): name += '_S' + basename(library_config.destination).upper() From 11a0e683e2da457db90a0ebfddf6c81e149af47c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Tue, 14 Sep 2021 18:23:19 +0200 Subject: [PATCH 317/681] Switch SVM gates from JDK 8 to JDK 17 --- substratevm/ci_includes/gate.hocon | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/substratevm/ci_includes/gate.hocon b/substratevm/ci_includes/gate.hocon index 4f2577c9ba32..9d6b1b86e61b 100644 --- a/substratevm/ci_includes/gate.hocon +++ b/substratevm/ci_includes/gate.hocon @@ -18,11 +18,11 @@ gate-svm-js: { } builds += [ - ${oraclejdk8} ${svm-common-linux-gate} ${gate-svm-js} ${svm-capabilities-base} { + ${labsjdk-ce-17} ${svm-common-linux-gate} ${gate-svm-js} ${svm-capabilities-base} { name: "gate-svm-js" timelimit: "35:00" } - ${oraclejdk8} ${svm-common-darwin-gate} ${gate-svm-js} { + ${labsjdk-ce-17} ${svm-common-darwin-gate} ${gate-svm-js} { name: "gate-svm-darwin-js" } ${labsjdk-ce-11} ${svm-common-linux-gate} ${linux-deploy} { @@ -49,7 +49,7 @@ builds += [ ${svm-cmd-gate} ["build,hellomodule,test"] ] } - ${oraclejdk8} ${svm-common-linux-gate} ${eclipse} ${jdt} ${linux-deploy} { + ${labsjdk-ce-17} ${svm-common-linux-gate} ${eclipse} ${jdt} ${linux-deploy} { name: "gate-svm-style-fullbuild" timelimit: "45:00" environment : { @@ -60,7 +60,7 @@ builds += [ ${svm-cmd-gate} ["style,fullbuild,helloworld,test,svmjunit,maven"] ] } - ${oraclejdk8} ${svm-common-gate} ${svm-common-windows-oraclejdk8} { + ${labsjdk-ce-17} ${svm-common-gate} ${svm-common-windows-jdk17} { name: "gate-svm-windows-basics" environment: { PATH : "$MVN_HOME;$PATH" # workaround until GR-10735 is resolved From 7321664adfe7187de125e5fc1fd508d8d5977c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Wed, 15 Sep 2021 11:15:56 +0200 Subject: [PATCH 318/681] Canonicalize com.oracle.svm.core.jdk15 deps --- substratevm/mx.substratevm/suite.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index a4e9499d6de6..a5d6c42463ab 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -247,10 +247,7 @@ "com.oracle.svm.core.jdk15": { "subDir": "src", "sourceDirs": ["src"], - "dependencies": [ - "com.oracle.svm.core", - "com.oracle.svm.core.jdk11" - ], + "dependencies": ["com.oracle.svm.core.jdk11"], "requiresConcealed" : { "java.base" : [ "jdk.internal.loader", From 05bea07f8c96a3e36845a0ef9325c85da77fdd13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Wed, 15 Sep 2021 11:44:22 +0200 Subject: [PATCH 319/681] Fix formatting --- .../JavaLangSubstitutions_JDK11OrLater.java | 6 ++--- .../com/oracle/svm/core/jdk11/ModuleUtil.java | 24 +++++++++---------- .../Target_java_lang_Module_JDK15OrLater.java | 2 +- .../src/com/oracle/svm/jfr/JfrEnabled.java | 1 + 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/JavaLangSubstitutions_JDK11OrLater.java b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/JavaLangSubstitutions_JDK11OrLater.java index c9fd579dcd7d..520459e893d0 100644 --- a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/JavaLangSubstitutions_JDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/JavaLangSubstitutions_JDK11OrLater.java @@ -54,7 +54,7 @@ final class Target_jdk_internal_loader_BootLoader_JDK11OrLater { static Package getDefinedPackage(String name) { if (name != null) { Target_java_lang_Package pkg = new Target_java_lang_Package(name, null, null, null, - null, null, null, null, null); + null, null, null, null, null); return SubstrateUtil.cast(pkg, Package.class); } else { return null; @@ -90,8 +90,8 @@ private static boolean hasClassPath() { /** * All ClassLoaderValue are reset at run time for now. See also - * {@link Target_java_lang_ClassLoader_JDK11OrLater#classLoaderValueMap} for resetting of individual class - * loaders. + * {@link Target_java_lang_ClassLoader_JDK11OrLater#classLoaderValueMap} for resetting of + * individual class loaders. */ // Checkstyle: stop @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClass = ConcurrentHashMap.class)// diff --git a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/ModuleUtil.java b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/ModuleUtil.java index fc8cb07c709a..91926780de73 100644 --- a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/ModuleUtil.java +++ b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/ModuleUtil.java @@ -105,7 +105,7 @@ public static void checkIsPackageContainedInModule(String pn, Module module) { Module actualModule = namedPackage.module; if (!actualModule.equals(module)) { throw new IllegalArgumentException("Package " + pn + " found in module " + actualModule.getName() + - ", not in module: " + module.getName()); + ", not in module: " + module.getName()); } } if (!module.getPackages().contains(pn)) { @@ -115,23 +115,23 @@ public static void checkIsPackageContainedInModule(String pn, Module module) { public static List getPackagesDefinedToLoader(ClassLoader loader) { return getDefinedModules().getOrDefault(loader, Set.of()) - .stream() - .flatMap(m -> m.getPackages().stream()) - .collect(Collectors.toUnmodifiableList()); + .stream() + .flatMap(m -> m.getPackages().stream()) + .collect(Collectors.toUnmodifiableList()); } public static Object getModuleContainingPackage(ClassLoader loader, String pn) { return getDefinedModules().getOrDefault(loader, Set.of()) - .stream() - .filter(m -> m.getPackages().contains(pn)) - .findFirst().orElse(null); + .stream() + .filter(m -> m.getPackages().contains(pn)) + .findFirst().orElse(null); } public static boolean bootLayerContainsModule(String name) { return ModuleLayer.boot().modules().stream().anyMatch(m -> m.getName().equals(name)); } - //Checkstyle: allow synchronization + // Checkstyle: allow synchronization public static void defineModule(Module module, boolean isOpen, List pns) { if (Objects.isNull(module)) { throw new NullPointerException("Null module object"); @@ -178,7 +178,7 @@ public static void defineModule(Module module, boolean isOpen, List pns) if (loader != ClassLoader.getPlatformClassLoader() && ModuleUtil.isPackageNameForbidden(pn)) { throw new IllegalArgumentException("Class loader (instance of): " + loader.getClass().getName() + - " tried to define prohibited package name: " + pn); + " tried to define prohibited package name: " + pn); } } @@ -202,11 +202,9 @@ public static void defineModule(Module module, boolean isOpen, List pns) } else if (Objects.nonNull(definedPackage)) { Module moduleContainingDefinedPackage = SubstrateUtil.cast(ModuleUtil.getModuleContainingPackage(loader, definedPackage), Module.class); if (moduleContainingDefinedPackage.isNamed()) { - throw new IllegalStateException("Package " + definedPackage + " is already in another module, " - + moduleContainingDefinedPackage.getName() + ", defined to the class loader"); + throw new IllegalStateException("Package " + definedPackage + " is already in another module, " + moduleContainingDefinedPackage.getName() + ", defined to the class loader"); } else { - throw new IllegalStateException("Package " + definedPackage - + " is already in the unnamed module defined to the class loader"); + throw new IllegalStateException("Package " + definedPackage + " is already in the unnamed module defined to the class loader"); } } diff --git a/substratevm/src/com.oracle.svm.core.jdk15/src/com/oracle/svm/core/jdk15/Target_java_lang_Module_JDK15OrLater.java b/substratevm/src/com.oracle.svm.core.jdk15/src/com/oracle/svm/core/jdk15/Target_java_lang_Module_JDK15OrLater.java index 94a0719002f1..f4ca16397f9e 100644 --- a/substratevm/src/com.oracle.svm.core.jdk15/src/com/oracle/svm/core/jdk15/Target_java_lang_Module_JDK15OrLater.java +++ b/substratevm/src/com.oracle.svm.core.jdk15/src/com/oracle/svm/core/jdk15/Target_java_lang_Module_JDK15OrLater.java @@ -38,7 +38,7 @@ @TargetClass(value = Module.class, onlyWith = JDK15OrLater.class) public final class Target_java_lang_Module_JDK15OrLater { - //Checkstyle: allow synchronization + // Checkstyle: allow synchronization @Substitute private static void defineModule0(Module module, boolean isOpen, String version, String location, Object[] pns) { if (Arrays.stream(pns).anyMatch(Objects::isNull)) { diff --git a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrEnabled.java b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrEnabled.java index cfa97353c7a0..35101f3a104b 100644 --- a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrEnabled.java +++ b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrEnabled.java @@ -47,6 +47,7 @@ public static boolean get() { private static boolean jvmVersionSupported() { return JavaVersionUtil.JAVA_SPEC == 11 || JavaVersionUtil.JAVA_SPEC == 16 || JavaVersionUtil.JAVA_SPEC == 17; } + private static boolean osSupported() { return OS.getCurrent() == OS.LINUX || OS.getCurrent() == OS.DARWIN; } From a6a3134f6e910976eac882788404099ff4781d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Wed, 15 Sep 2021 13:16:23 +0200 Subject: [PATCH 320/681] Fix copyright header --- ...Target_jdk_internal_platform_CgroupMetrics_JDK17OrLater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core.jdk17/src/com/oracle/svm/core/jdk17/Target_jdk_internal_platform_CgroupMetrics_JDK17OrLater.java b/substratevm/src/com.oracle.svm.core.jdk17/src/com/oracle/svm/core/jdk17/Target_jdk_internal_platform_CgroupMetrics_JDK17OrLater.java index fcc653fdb16d..5f1ba4730b17 100644 --- a/substratevm/src/com.oracle.svm.core.jdk17/src/com/oracle/svm/core/jdk17/Target_jdk_internal_platform_CgroupMetrics_JDK17OrLater.java +++ b/substratevm/src/com.oracle.svm.core.jdk17/src/com/oracle/svm/core/jdk17/Target_jdk_internal_platform_CgroupMetrics_JDK17OrLater.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * 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 From 7a4fae237e35b7bdb969be705fdf55ae9bb61bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Wed, 15 Sep 2021 14:51:18 +0200 Subject: [PATCH 321/681] Fix JVMFuncFallbackTest on JDK 17 --- .../src/com/oracle/svm/test/JVMFuncFallbackTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/JVMFuncFallbackTest.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/JVMFuncFallbackTest.java index a49e77573ed0..45b27e497c5e 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/JVMFuncFallbackTest.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/JVMFuncFallbackTest.java @@ -40,10 +40,10 @@ public class JVMFuncFallbackTest { public void testImageCodeMethods() { if (Boolean.getBoolean("never.be.true.but.compiler.doesn't.know")) { /* - * Cause image to link to JVM_Clone. This will trigger a linker error if libjvm.a does - * not contain the autogenerated JVM_* fallbacks. + * Cause image to link to JVM_IHashCode. This will trigger a linker error if libjvm.a + * does not contain the autogenerated JVM_* fallbacks. */ - Jvm.JVM_Clone(WordFactory.nullPointer()); + Jvm.JVM_IHashCode(WordFactory.nullPointer()); } } } @@ -52,5 +52,5 @@ public void testImageCodeMethods() { @CLibrary(value = "jvm", requireStatic = true) class Jvm { @CFunction(transition = CFunction.Transition.NO_TRANSITION) - public static native int JVM_Clone(Pointer jni); + public static native int JVM_IHashCode(Pointer jni); } From b0d20e7a155a4063f0e0e2e17255bd669ecebcc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Thu, 30 Sep 2021 15:19:59 +0200 Subject: [PATCH 322/681] Disable tests that fail with --builder-on-modulepath enabled on JDK 17 --- substratevm/mx.substratevm/mx_substratevm.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index bfed15e9a0be..af87cf361230 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -443,6 +443,12 @@ def native_unittests_task(): '-H:AdditionalSecurityServiceTypes=com.oracle.svm.test.SecurityServiceTest$JCACompliantNoOpService' ] + if svm_java_compliance() == '17': + # The following tests fail with --builder-on-modulepath enabled (GR-34117) + mx_unittest.add_global_ignore_glob('com.oracle.svm.test.jdk11.jfr.*') + if mx.is_windows(): + mx_unittest.add_global_ignore_glob('com.oracle.svm.test.SecurityServiceTest') + native_unittest(['--builder-on-modulepath', '--build-args', _native_unittest_features] + additional_build_args) From e78183c709d2ea9940f9f6a0cee3bed50f3a80f1 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 7 Oct 2021 10:17:11 +0200 Subject: [PATCH 323/681] Improve GC-specific forced inlining. --- .../svm/core/genscavenge/GCAccounting.java | 2 +- .../svm/core/genscavenge/HeapChunk.java | 2 +- .../core/genscavenge/ObjectHeaderImpl.java | 2 ++ .../oracle/svm/core/genscavenge/Space.java | 30 +++++++++++-------- .../remset/AlignedChunkRememberedSet.java | 2 +- .../remset/CardTableBasedRememberedSet.java | 1 + .../genscavenge/remset/FirstObjectTable.java | 4 +++ .../heap/InstanceReferenceMapDecoder.java | 3 +- .../oracle/svm/core/hub/LayoutEncoding.java | 14 ++++++++- 9 files changed, 43 insertions(+), 17 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java index 0533458c1cf6..e18aaad24b3b 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java @@ -148,7 +148,7 @@ void beforeCollection() { /** Called after an object has been promoted from the young generation to the old generation. */ @AlwaysInline("GC performance") void onObjectTenured(Object result, boolean survivorOverflow) { - UnsignedWord size = LayoutEncoding.getSizeFromObject(result); + UnsignedWord size = LayoutEncoding.getSizeFromObjectInline(result); tenuredObjectBytes = tenuredObjectBytes.add(size); if (survivorOverflow) { survivorOverflowObjectBytes = survivorOverflowObjectBytes.add(size); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunk.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunk.java index 424e4e2df3b3..0055d2d28982 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunk.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunk.java @@ -288,7 +288,7 @@ public static boolean walkObjectsFromInline(Header that, Pointer startOffset, if (!visitor.visitObjectInline(obj)) { return false; } - offset = offset.add(LayoutEncoding.getSizeFromObject(obj)); + offset = offset.add(LayoutEncoding.getSizeFromObjectInline(obj)); } return true; } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ObjectHeaderImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ObjectHeaderImpl.java index 36fa275c4cb6..a838fab7673d 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ObjectHeaderImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ObjectHeaderImpl.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.genscavenge; +import com.oracle.svm.core.annotate.AlwaysInline; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.CompressEncoding; @@ -327,6 +328,7 @@ static Object getForwardedObject(Pointer ptr, UnsignedWord header) { } /** In an Object, install a forwarding pointer to a different Object. */ + @AlwaysInline("GC performance") static void installForwardingPointer(Object original, Object copy) { assert !isPointerToForwardedObject(Word.objectToUntrackedPointer(original)); UnsignedWord forwardHeader; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/Space.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/Space.java index d47b6d0bd869..35c5d98133c9 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/Space.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/Space.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; +import com.oracle.svm.core.annotate.AlwaysInline; import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -172,25 +173,28 @@ public Log report(Log log, boolean traceHeapChunks) { /** * Allocate memory from an AlignedHeapChunk in this Space. - * - * This is "slow-path" memory allocation. */ + @AlwaysInline("GC performance") private Pointer allocateMemory(UnsignedWord objectSize) { Pointer result = WordFactory.nullPointer(); - /* First try allocating in the last chunk. */ + /* Fast-path: try allocating in the last chunk. */ AlignedHeapChunk.AlignedHeader oldChunk = getLastAlignedHeapChunk(); if (oldChunk.isNonNull()) { result = AlignedHeapChunk.allocateMemory(oldChunk, objectSize); } - /* If oldChunk did not provide, try allocating a new chunk for the requested memory. */ - if (result.isNull()) { - AlignedHeapChunk.AlignedHeader newChunk = requestAlignedHeapChunk(); - if (newChunk.isNonNull()) { - /* Allocate the Object within the new chunk. */ - result = AlignedHeapChunk.allocateMemory(newChunk, objectSize); - } + if (result.isNonNull()) { + return result; } - return result; + /* Slow-path: try allocating a new chunk for the requested memory. */ + return allocateInNewChunk(objectSize); + } + + private Pointer allocateInNewChunk(UnsignedWord objectSize) { + AlignedHeapChunk.AlignedHeader newChunk = requestAlignedHeapChunk(); + if (newChunk.isNonNull()) { + return AlignedHeapChunk.allocateMemory(newChunk, objectSize); + } + return WordFactory.nullPointer(); } public void releaseChunks(ChunkReleaser chunkReleaser) { @@ -352,6 +356,7 @@ private void setLastUnalignedHeapChunk(UnalignedHeapChunk.UnalignedHeader chunk) } /** Promote an aligned Object to this Space. */ + @AlwaysInline("GC performance") Object promoteAlignedObject(Object original, Space originalSpace) { assert ObjectHeaderImpl.isAlignedObject(original); assert this != originalSpace && originalSpace.isFromSpace(); @@ -363,11 +368,12 @@ Object promoteAlignedObject(Object original, Space originalSpace) { return copy; } + @AlwaysInline("GC performance") private Object copyAlignedObject(Object originalObj) { assert VMOperation.isGCInProgress(); assert ObjectHeaderImpl.isAlignedObject(originalObj); - UnsignedWord size = LayoutEncoding.getSizeFromObject(originalObj); + UnsignedWord size = LayoutEncoding.getSizeFromObjectInline(originalObj); Pointer copyMemory = allocateMemory(size); if (probability(VERY_SLOW_PATH_PROBABILITY, copyMemory.isNull())) { return null; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/AlignedChunkRememberedSet.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/AlignedChunkRememberedSet.java index 786ee8d82642..902eb59b5dec 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/AlignedChunkRememberedSet.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/AlignedChunkRememberedSet.java @@ -145,7 +145,7 @@ public static void walkDirtyObjects(AlignedHeader chunk, GreyToBlackObjectVisito while (ptr.belowThan(walkLimit)) { Object obj = ptr.toObject(); visitor.visitObjectInline(obj); - ptr = LayoutEncoding.getObjectEnd(obj); + ptr = LayoutEncoding.getObjectEndInline(obj); } } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java index 251992239f3e..a3e2b060212b 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java @@ -96,6 +96,7 @@ public void enableRememberedSetForChunk(UnalignedHeader chunk) { } @Override + @AlwaysInline("GC performance") public void enableRememberedSetForObject(AlignedHeader chunk, Object obj) { AlignedChunkRememberedSet.enableRememberedSetForObject(chunk, obj); } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/FirstObjectTable.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/FirstObjectTable.java index 42130392da61..bfca620613c1 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/FirstObjectTable.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/FirstObjectTable.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.genscavenge.remset; +import com.oracle.svm.core.annotate.AlwaysInline; import org.graalvm.word.Pointer; import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; @@ -177,6 +178,7 @@ private static boolean doInitializeTable(Pointer table, UnsignedWord size) { return true; } + @AlwaysInline("GC performance") public static void setTableForObject(Pointer table, UnsignedWord startOffset, UnsignedWord endOffset) { assert startOffset.belowThan(endOffset); UnsignedWord startIndex = memoryOffsetToIndex(startOffset); @@ -229,6 +231,7 @@ public static void setTableForObject(Pointer table, UnsignedWord startOffset, Un * not at the address of the reference). So, we must skip over the first object if it starts * outside the current card. */ + @AlwaysInline("GC performance") public static Pointer getFirstObjectImprecise(Pointer tableStart, Pointer objectsStart, Pointer objectsLimit, UnsignedWord index) { Pointer result; Pointer firstObject = getFirstObject(tableStart, objectsStart, objectsLimit, index); @@ -246,6 +249,7 @@ public static Pointer getFirstObjectImprecise(Pointer tableStart, Pointer object return result; } + @AlwaysInline("GC performance") private static Pointer getFirstObject(Pointer tableStart, Pointer objectsStart, Pointer objectsLimit, UnsignedWord index) { UnsignedWord currentIndex = index; int currentEntry = getEntryAtIndex(tableStart, currentIndex); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/InstanceReferenceMapDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/InstanceReferenceMapDecoder.java index b5741e274894..c7df8969cf54 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/InstanceReferenceMapDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/InstanceReferenceMapDecoder.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.heap; +import com.oracle.svm.core.thread.JavaContinuations; import org.graalvm.word.Pointer; import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; @@ -42,7 +43,7 @@ public static boolean walkOffsetsFromPointer(Pointer baseAddress, NonmovableArra assert ReferenceMapIndex.denotesValidReferenceMap(referenceMapIndex); assert referenceMapEncoding.isNonNull(); - if (referenceMapIndex == ReferenceMapIndex.STORED_CONTINUATION) { + if (JavaContinuations.useLoom() && referenceMapIndex == ReferenceMapIndex.STORED_CONTINUATION) { return StoredContinuationImpl.walkStoredContinuationFromPointer(baseAddress, visitor, holderObject); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/LayoutEncoding.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/LayoutEncoding.java index 9388cd6dcf01..bae520de89a6 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/LayoutEncoding.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/LayoutEncoding.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.hub; +import com.oracle.svm.core.annotate.AlwaysInline; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.calc.UnsignedMath; import org.graalvm.compiler.nodes.java.ArrayLengthNode; @@ -210,6 +211,12 @@ public static UnsignedWord getArraySize(int encoding, int length) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static UnsignedWord getSizeFromObject(Object obj) { + return getSizeFromObjectInline(obj); + } + + @AlwaysInline("GC performance") + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static UnsignedWord getSizeFromObjectInline(Object obj) { int encoding = KnownIntrinsics.readHub(obj).getLayoutEncoding(); if (isArray(encoding)) { return getArraySize(encoding, ArrayLengthNode.arrayLength(obj)); @@ -222,11 +229,16 @@ public static UnsignedWord getSizeFromObject(Object obj) { /** Returns the end of the Object when the call started, e.g., for logging. */ public static Pointer getObjectEnd(Object obj) { + return getObjectEndInline(obj); + } + + @AlwaysInline("GC performance") + public static Pointer getObjectEndInline(Object obj) { // TODO: This assumes that the object starts at obj. // - In other universes obj could point to the hub in the middle of, // for example, a butterfly object. final Pointer objStart = Word.objectToUntrackedPointer(obj); - final UnsignedWord objSize = getSizeFromObject(obj); + final UnsignedWord objSize = getSizeFromObjectInline(obj); return objStart.add(objSize); } From a6f17ebcd80599dd1c29ee591bd483b592e261e2 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 7 Oct 2021 12:46:52 +0300 Subject: [PATCH 324/681] Review and update docs/graalvm-as-a-platform --- .../implement-instrument.md | 98 ++++++++++--------- .../implement-language.md | 94 +++++++----------- 2 files changed, 85 insertions(+), 107 deletions(-) diff --git a/docs/graalvm-as-a-platform/implement-instrument.md b/docs/graalvm-as-a-platform/implement-instrument.md index 1a2eb62b6290..0c7cc1d9a527 100644 --- a/docs/graalvm-as-a-platform/implement-instrument.md +++ b/docs/graalvm-as-a-platform/implement-instrument.md @@ -14,22 +14,18 @@ Instruments can track very fine-grained, VM-level runtime events to profile, ins ## Simple Tool -To provide an easier starting point for tool developers we have created a -[Simple Tool](https://github.com/graalvm/simpletool) example project. This is a -javadoc-rich Maven project which implements a simple code coverage tool. +To provide an easier starting point for tool developers we have created a [Simple Tool](https://github.com/graalvm/simpletool) example project. +This is a javadoc-rich Maven project which implements a simple code coverage tool. -We recommend cloning the repository and exploring the source code as a starting -point for tool development. The following sections will provide a guided tour of -the steps needed to build and run a GraalVM tool, using Simple Tool source code -as the running example. These sections do not cover all of the features of the -[Instrument API](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/package-summary.html) so we encourage you to check the javadoc for more details. +We recommend cloning the repository and exploring the source code as a starting point for tool development. +The following sections will provide a guided tour of the steps needed to build and run a GraalVM tool, using Simple Tool source code as the running example. +These sections do not cover all of the features of the [Instrument API](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/package-summary.html) so we encourage you to check the javadoc for more details. ### Requirements -As mentioned before, Simple Tool is a code coverage tool. Ultimately, it -should provide the developer with information on what percentage of source code -lines was executed, as well as exactly which lines were executed. With that in -mind, we can define some high-level requirements from our tool: +As mentioned before, Simple Tool is a code coverage tool. +Ultimately, it should provide the developer with information on what percentage of source code lines was executed, as well as exactly which lines were executed. +With that in mind, we can define some high-level requirements from our tool: 1. The tool keeps track of loaded source code. 2. The tool keeps track of executed source code. @@ -40,14 +36,10 @@ mind, we can define some high-level requirements from our tool: The main starting point for tools is subclassing the [TruffleInstrument](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/TruffleInstrument.html) class. Unsurprisingly, the simple tool code base does exactly this, creating the [SimpleCoverageInstrument](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L84) class. -The -[Registration](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/TruffleInstrument.Registration.html) -annotation on the class ensures that the newly created instrument is registered -with the Instrument API, i.e., that it will be automatically -discovered by the framework. It also provides some metadata about the -instrument: ID, name, version, which services the instrument provides, and -whether the instrument is internal or not. In order for this annotation to be -effective the DSL processor needs to process this class. This is, in the case of Simple Tool, done automatically by having the DSL processor as a dependency in the [Maven configuration](https://github.com/graalvm/simpletool/blob/master/pom.xml#L83). +The [Registration](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/TruffleInstrument.Registration.html) annotation on the class ensures that the newly created instrument is registered with the Instrument API, i.e., that it will be automatically discovered by the framework. +It also provides some metadata about the instrument: ID, name, version, which services the instrument provides, and whether the instrument is internal or not. +In order for this annotation to be effective the DSL processor needs to process this class. +This is, in the case of Simple Tool, done automatically by having the DSL processor as a dependency in the [Maven configuration](https://github.com/graalvm/simpletool/blob/master/pom.xml#L83). Now we will look back at the implementation of the `SimpleCoverageInstrument` class, namely which methods from `TruffleInstrument` it overrides. These are [onCreate](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L130), [onDispose](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L182), and [getOptionDescriptors](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L245). @@ -89,22 +81,13 @@ The instrument keeps a mapping from each `Source` to a [Coverage](https://github ### Execution Event Node Guest languages are implemented as Abstract Syntax Tree (AST) interpreters. -The language implementers annotate certain nodes with tags, which allows us to -select which nodes we are interested in, by using the aforementioned -`SourceSectionFilter`, in a language-agnostic manner. - -The main power of the Instrument API lies in its ability to insert specialised -nodes in the AST which "wrap" the nodes of interest. These nodes are built using -the same infrastructure that the language developers use, and are, from the -perspective of the runtime, indistinguishable from the language nodes. This -means that all of the techniques used to optimize guest languages into such high -performing language implementations are available to the tool developers as -well. +The language implementers annotate certain nodes with tags, which allows us to select which nodes we are interested in, by using the aforementioned `SourceSectionFilter`, in a language-agnostic manner. + +The main power of the Instrument API lies in its ability to insert specialised nodes in the AST which "wrap" the nodes of interest. +These nodes are built using the same infrastructure that the language developers use, and are, from the perspective of the runtime, indistinguishable from the language nodes. This means that all of the techniques used to optimize guest languages into such high performing language implementations are available to the tool developers as well. More information about these techniques is available in the [language implementation documentation](https://github.com/oracle/graal/tree/master/truffle/docs). -Suffice it to say that for Simple Tool to meet its second requirement, we need to -instrument all expressions with our own node that will notify us when that -expression is executed. +Suffice it to say that for Simple Tool to meet its second requirement, we need to instrument all expressions with our own node that will notify us when that expression is executed. For this task we use the [CoverageNode](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/CoverageNode.java). It is a subclass of [ExecutionEventNode](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/ExecutionEventNode.html) which, as the name implies, is used to instrument events during execution. @@ -121,8 +104,7 @@ The factory is the [CoverageEventFactory](https://github.com/graalvm/simpletool/ This class just ensures that each `CoverageNode` knows the `SourceSection` it is instrumenting by looking it up in the provided [EventContext](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/EventContext.html). Finally, when we are [enabling the instrument](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L173), -we tell the instrumenter to use our factory to "wrap" the nodes selected by our -filter. +we tell the instrumenter to use our factory to "wrap" the nodes selected by our filter. ### Interaction Between Users and Instruments @@ -237,14 +219,18 @@ The following examples are intended to show common use-cases that can be solved ### Instrumentation Event Listeners -The Instrument API is defined in the `com.oracle.truffle.api.instrumentation` package. Instrumentation agents can be developed by extending the `TruffleInstrument` class, and can be attached to a running GraalVM instance using the `Instrumenter` class. Once attached to a running language runtime, instrumentation agents remain usable as long as the language runtime is not disposed. Instrumentation agents on GraalVM can monitor a variety of VM-level runtime events, including any of the following: +The Instrument API is defined in the `com.oracle.truffle.api.instrumentation` package. +Instrumentation agents can be developed by extending the `TruffleInstrument` class, and can be attached to a running GraalVM instance using the `Instrumenter` class. +Once attached to a running language runtime, instrumentation agents remain usable as long as the language runtime is not disposed. +Instrumentation agents on GraalVM can monitor a variety of VM-level runtime events, including any of the following: 1. _Source code-related events_: The agent can be notified every time a new [Source](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/source/Source.html) or [SourceSection](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/source/SourceSection.html) element is loaded by the monitored language runtime. 2. _Allocation events_: The agent can be notified every time a new object is allocated in the memory space of the monitored language runtime. 3. _Language runtime and thread creation events_: The agent can be notified as soon as a new [execution context](http://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Context.html) or a new thread for a monitored language runtime is created. 4. _Application execution events_: The agent gets notified every time a monitored application executes a specific set of language operations. Examples of such operations include language statements and expressions, thus allowing an instrumentation agent to inspect running applications with very high precision. -For each execution event, instrumentation agents can define _filtering_ criteria that will be used by the GraalVM instrumentation runtime to monitor only the relevant execution events. Currently, GraalVM instruments accept one of the following two filter types: +For each execution event, instrumentation agents can define _filtering_ criteria that will be used by the GraalVM instrumentation runtime to monitor only the relevant execution events. +Currently, GraalVM instruments accept one of the following two filter types: 1. `AllocationEventFilter` to filter allocation events by allocation type. 2. `SourceSectionFilter` to filter source code locations in an application. @@ -258,9 +244,12 @@ SourceSectionFilter.newBuilder() .build() ``` -The filter in the example can be used to monitor the execution of all JavaScript statements in a given application. Other filtering options such as line numbers or file extensions can also be provided. +The filter in the example can be used to monitor the execution of all JavaScript statements in a given application. +Other filtering options such as line numbers or file extensions can also be provided. -Source section filters like the one in the example can use _Tags_ to specify a set of execution events to be monitored. Language-agnostic tags such as statements and expressions are defined in the [`com.oracle.truffle.api.instrumentation.Tag`](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/Tag.html) class, and are supported by all GraalVM languages. In addition to standard tags, GraalVM languages may provide other, language-specific, tags to enable fine-grained profiling of language-specific events. (As an example, the GraalVM JavaScript engine provides JavaScript-specific tags to track the usages of ECMA builtin objects such as `Array`, `Map`, or `Math`.) +Source section filters like the one in the example can use _Tags_ to specify a set of execution events to be monitored. Language-agnostic tags such as statements and expressions are defined in the [`com.oracle.truffle.api.instrumentation.Tag`](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/Tag.html) class, and are supported by all GraalVM languages. +In addition to standard tags, GraalVM languages may provide other, language-specific, tags to enable fine-grained profiling of language-specific events. +(As an example, the GraalVM JavaScript engine provides JavaScript-specific tags to track the usages of ECMA builtin objects such as `Array`, `Map`, or `Math`.) ### Monitoring Execution Events @@ -271,7 +260,8 @@ Application execution events enable very precise and detailed monitoring. GraalV ### Simple Instrumentation Agent -A simple example of a custom instrumentation agent used to perform runtime code coverage can be found in the `CoverageExample` class. What follows is an overview of the agent, its design, and its capabilities. +A simple example of a custom instrumentation agent used to perform runtime code coverage can be found in the `CoverageExample` class. +What follows is an overview of the agent, its design, and its capabilities. All instruments extend the `TruffleInstrument` abstract class and are registered in the GraalVM runtime through the `@Registration` annotation: @@ -287,7 +277,9 @@ public final class CoverageExample extends TruffleInstrument { } ``` -Instruments override the `onCreate(Env env)` method to perform custom operations at instrument loading time. Typically, an instrument would use this method to register itself in the existing GraalVM execution environment. As an example, an instrument using AST nodes can be registered in the following way: +Instruments override the `onCreate(Env env)` method to perform custom operations at instrument loading time. +Typically, an instrument would use this method to register itself in the existing GraalVM execution environment. +As an example, an instrument using AST nodes can be registered in the following way: ```java @Override @@ -325,7 +317,10 @@ Execution event nodes can implement certain callback methods to intercept runtim 2. `onReturnValue`: executed after a source code element returns a value. 3. `onReturnExceptional`: executed in case the filtered source code element throws an exception. -Execution event nodes are created on a _per code location_ basis. Therefore, they can be used to store data specific to a given source code location in the instrumented application. As an example, an instrumentation node can simply keep track of all code locations that have already been visited using a node-local flag. Such a node-local `boolean` flag can be used to track the execution of AST nodes in the following way: +Execution event nodes are created on a _per code location_ basis. +Therefore, they can be used to store data specific to a given source code location in the instrumented application. +As an example, an instrumentation node can simply keep track of all code locations that have already been visited using a node-local flag. +Such a node-local `boolean` flag can be used to track the execution of AST nodes in the following way: ```java // To keep track of all source code locations executed @@ -349,7 +344,9 @@ public ExecutionEventNode create(final EventContext ec) { } ``` -As the above code shows, an `ExecutionEventNode` is a valid AST node. This implies that the instrumentation code will be optimized by the GraalVM runtime together with the instrumented application, resulting in minimal instrumentation overhead. Furthermore, this allows instrument developers to use the [Truffle framework compiler directives](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/CompilerDirectives.html) directly from instrumentation nodes. In the example, compiler directives are used to inform the GraalVM compiler that `visited` can be considered compilation-final. +As the above code shows, an `ExecutionEventNode` is a valid AST node. +This implies that the instrumentation code will be optimized by the GraalVM runtime together with the instrumented application, resulting in minimal instrumentation overhead. Furthermore, this allows instrument developers to use the [Truffle framework compiler directives](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/CompilerDirectives.html) directly from instrumentation nodes. +In the example, compiler directives are used to inform the GraalVM compiler that `visited` can be considered compilation-final. Each instrumentation node is bound to a specific code location. Such locations can be accessed by the agent using the provided [`EventContext`](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/EventContext.html) object. The context object gives instrumentation nodes access to a variety of information about the current AST nodes being executed. Examples of query APIs available to instrumentation agents through `EventContext` include: @@ -376,7 +373,9 @@ SourceSectionFilter inputGeneratingLocations = SourceSectionFilter.newBuilder() instrumenter.attachExecutionEventFactory(sourceSectionFilter, inputGeneratingLocations, factory); ``` -The first source section filter (`sourceSectionFilter`, in the example) is a normal filter equivalent to other filters described before, and is used to identify the source code locations to be monitored. The second section filter, `inputGeneratingLocations`, is used by the agent to specify the _intermediate values_ that should be monitored for a certain source section. Intermediate values correspond to _all_ observable values that are involved in the execution of a monitored code element, and are reported to the instrumentation agent by means of the `onInputValue` callback. As an example, let us assume an agent needs to profile all _operand_ values provided to sum operations (i.e., `+`) in JavaScript: +The first source section filter (`sourceSectionFilter`, in the example) is a normal filter equivalent to other filters described before, and is used to identify the source code locations to be monitored. +The second section filter, `inputGeneratingLocations`, is used by the agent to specify the _intermediate values_ that should be monitored for a certain source section. Intermediate values correspond to _all_ observable values that are involved in the execution of a monitored code element, and are reported to the instrumentation agent by means of the `onInputValue` callback. +As an example, let us assume an agent needs to profile all _operand_ values provided to sum operations (i.e., `+`) in JavaScript: ```javascript var a = 3; @@ -421,11 +420,16 @@ onEnter - VariableWrite onReturnValue - VariableWrite ``` -The `onInputValue` method can be used in combination with source section filters to intercept very fine-grained execution events such as intermediate values used by language expressions. The intermediate values that are accessible to the Instrumentation framework greatly depend on the instrumentation support provided by each language. Moreover, languages may provide additional metadata associated with language-specific `Tag` classes. +The `onInputValue` method can be used in combination with source section filters to intercept very fine-grained execution events such as intermediate values used by language expressions. +The intermediate values that are accessible to the Instrumentation framework greatly depend on the instrumentation support provided by each language. +Moreover, languages may provide additional metadata associated with language-specific `Tag` classes. ### Altering the Execution Flow of an Application -The instrumentation capabilities that we have presented so far enable users to _observe_ certain aspects of a running application. In addition to passive monitoring of an application's behavior, the Instrument API features support for actively _altering_ the behavior of an application at runtime. Such capabilities can be used to write complex instrumentation agents that affect the behavior of a running application to achieve specific runtime semantics. For example, one could alter the semantics of a running application to ensure that certain methods or functions are never executed (e.g., by throwing an exception when they are called). +The instrumentation capabilities that we have presented so far enable users to _observe_ certain aspects of a running application. +In addition to passive monitoring of an application's behavior, the Instrument API features support for actively _altering_ the behavior of an application at runtime. +Such capabilities can be used to write complex instrumentation agents that affect the behavior of a running application to achieve specific runtime semantics. +For example, one could alter the semantics of a running application to ensure that certain methods or functions are never executed (e.g., by throwing an exception when they are called). Instrumentation agents with such capabilities can be implemented by leveraging the `onUnwind` callback in execution event listeners and factories. As an example, let's consider the following JavaScript code: diff --git a/docs/graalvm-as-a-platform/implement-language.md b/docs/graalvm-as-a-platform/implement-language.md index 28c182776fc9..7657a0cedd10 100644 --- a/docs/graalvm-as-a-platform/implement-language.md +++ b/docs/graalvm-as-a-platform/implement-language.md @@ -109,21 +109,17 @@ Then attach a Java remote debugger (like Eclipse) on port 8000. Languages implemented with the [Truffle framework](https://github.com/oracle/graal/tree/master/truffle) can be packaged as _components_ which later can be installed into GraalVM using the [GraalVM Updater](../reference-manual/graalvm-updater.md) tool. Running `mvn package` in the SimpleLanguage folder also builds a `sl-component.jar`. -This file is the SimpleLanguage component for GraalVM and can be installed by -running: +This file is the SimpleLanguage component for GraalVM and can be installed by running: ```shell gu -L install /path/to/sl-component.jar ``` ## SimpleLanguage Native Image -A language built with Truffle can be AOT compiled using [Native Image](../reference-manual/native-image/README.md). Running -`mvn package` in the SimpleLanguage folder also builds a `slnative` executable -in the `native` directory. This executable is the full SimpleLanguage -implementation as a single native application, and has no need for GraalVM in -order to execute SimpleLanguage code. Besides this, a big advantage of using the -native executable when compared to running on GraalVM is the greatly faster -startup time as shown bellow: +A language built with Truffle can be AOT compiled using [Native Image](../reference-manual/native-image/README.md). +Running `mvn package` in the SimpleLanguage folder also builds a `slnative` executable in the `native` directory. +This executable is the full SimpleLanguage implementation as a single native application, and has no need for GraalVM in order to execute SimpleLanguage code. +Besides this, a big advantage of using the native executable when compared to running on GraalVM is the greatly faster startup time as shown bellow: ```shell time ./sl language/tests/HelloWorld.sl == running on org.graalvm.polyglot.Engine@2db0f6b2 @@ -143,23 +139,16 @@ user 0m0.000s sys 0m0.000s ``` -This snipped shows a timed execution of a "Hello World" program using the `sl` -launcher script, which runs SimpleLanguage on GraalVM, using Native -Image. We can see that when running on GraalVM the execution takes 405ms. Since -our SimpleLanguage program does just one print statement, we can conclude that -almost all of this time is spent starting up GraalVM and initializing the -language itself. When using the native executable we see that the execution takes -only 4ms, showing two orders of magnitude faster startup than running on -GraalVM. +This snipped shows a timed execution of a "Hello World" program using the `sl` launcher script, which runs SimpleLanguage on GraalVM, using Native Image. +We can see that when running on GraalVM the execution takes 405ms. +Since our SimpleLanguage program does just one print statement, we can conclude that almost all of this time is spent starting up GraalVM and initializing the language itself. When using the native executable we see that the execution takes only 4ms, showing two orders of magnitude faster startup than running on GraalVM. For more information on the `native-image` tool consider reading the [reference manual](../reference-manual/native-image/README.md). ### Disable SimpleLanguage Native Image Build -Building the native executable through Maven is attached to the Maven `package` -phase. Since the native executable build can take a bit of time, we provide the -option to skip this build by setting the `SL_BUILD_NATIVE` environment variable -to `false` like so: +Building the native executable through Maven is attached to the Maven `package` phase. +Since the native executable build can take a bit of time, we provide the option to skip this build by setting the `SL_BUILD_NATIVE` environment variable to `false` like so: ```shell export SL_BUILD_NATIVE=false @@ -178,12 +167,11 @@ Skipping the native image build because SL_BUILD_NATIVE is set to false. ... ``` -## Run SimpleLanguage with the Newest Compiler 21.2.0 +## Run SimpleLanguage with the Newest Compiler 21.3.0 -In the outstanding case that you need to execute SimpleLanguage with the newest -version of the GraalVM compiler, please follow these instructions: +In the outstanding case that you need to execute SimpleLanguage with the newest version of the GraalVM compiler, please follow these instructions: -1. Download the latest [JVMCI JDK 8](https://github.com/graalvm/graal-jvmci-8/releases/) and point JAVA_HOME at it: +1. Download the latest [JVMCI JDK 8](https://github.com/graalvm/graal-jvmci-8/releases/) and point `JAVA_HOME` at it: ```shell export JAVA_HOME=/path/to/openjdk-8u292-jvmci-21.1-b04 ``` @@ -210,61 +198,52 @@ mx build ``` 7. Run SimpleLanguage using the mx command: ```shell -mx -v --jdk=jvmci vm -cp /path/to/simplelanguage/launcher/target/launcher-21.2.0-SNAPSHOT.jar:/path/to/simplelanguage/language/target/simplelanguage.jar com.oracle.truffle.sl.launcher.SLMain /path/to/simplelanguage/language/tests/SlScript.sl +mx -v --jdk=jvmci vm -cp /path/to/simplelanguage/launcher/target/launcher-21.3.0-SNAPSHOT.jar:/path/to/simplelanguage/language/target/simplelanguage.jar com.oracle.truffle.sl.launcher.SLMain /path/to/simplelanguage/language/tests/SlScript.sl ``` ## Run SimpleLanguage Using Command Line -Executing SimpleLanguage code is normally done with the `sl` script which sets -up the necessary command line depending on whether `JAVA_HOME` points to -GraalVM or another JVM installation. The following subsections describe the -command line for both cases. +Executing SimpleLanguage code is normally done with the `sl` script which sets up the necessary command line depending on whether `JAVA_HOME` points to GraalVM or another JVM installation. +The following subsections describe the command line for both cases. ### Run SimpleLanguage with GraalVM as JAVA_HOME -Assuming `JAVA_HOME` points to the GraalVM installation and that the current -working directory is the `simplelanguage` directory, to run SimpleLanguage one -should execute the following command: +Assuming `JAVA_HOME` points to the GraalVM installation and that the current working directory is the `simplelanguage` directory, to run SimpleLanguage one should execute the following command: ```shell $JAVA_HOME/bin/java \ - -cp launcher/target/launcher-21.2.0-SNAPSHOT.jar \ + -cp launcher/target/launcher-21.3.0-SNAPSHOT.jar \ -Dtruffle.class.path.append=language/target/simplelanguage.jar \ com.oracle.truffle.sl.launcher.SLMain language/tests/Add.sl ``` -In short, we place the launcher JAR on the class path and execute its main -class, but we inform GraalVM of the presence of SimpleLanguage by using the -`-Dtruffle.class.path.append` option and providing it the path to the fat -language JAR. Having the language on a separate class path ensures a strong -separation between the language implementation and its embedding context (in -this case, the launcher). +In short, we place the launcher JAR on the class path and execute its main class, but we inform GraalVM of the presence of SimpleLanguage by using the `-Dtruffle.class.path.append` option and providing it the path to the fat language JAR. +Having the language on a separate class path ensures a strong separation between the language implementation and its embedding context (in this case, the launcher). #### Disable Class Path Separation *NOTE! This should only be used during development.* -For development purposes it is useful to disable the class path separation and enable having the -language implementation on the application class path (for example, for testing +For development purposes it is useful to disable the class path separation and enable having the language implementation on the application class path (for example, for testing the internals of the language). -For the GraalVM distribution based on JDK 8, you can add the `-XX:-UseJVMCIClassLoader` -option. This disables the class path isolation, enabling the language -implementation to be placed on the application class path. The command line can -be as follows: +For the GraalVM distribution based on JDK 8, you can add the `-XX:-UseJVMCIClassLoader` option. +This disables the class path isolation, enabling the language implementation to be placed on the application class path. +The command line can be as follows: ```shell $JAVA_HOME/bin/java \ -XX:-UseJVMCIClassLoader -Dgraalvm.locatorDisabled=true \ - -cp launcher/target/launcher-21.2.0-SNAPSHOT.jar:language/target/simplelanguage.jar \ + -cp launcher/target/launcher-21.3.0-SNAPSHOT.jar:language/target/simplelanguage.jar \ com.oracle.truffle.sl.launcher.SLMain language/tests/Add.sl ``` -For the JDK 11-based distribution of GraalVM, the `-XX:-UseJVMCIClassLoader` option -is not valid. The Java Module System isolation is used. You can achieve the same behavior -using `--add-exports` or `--upgrade-module-path`. The latter is preferable. +For the JDK 11-based distribution of GraalVM, the `-XX:-UseJVMCIClassLoader` option is not valid. +The Java Module System isolation is used. You can achieve the same behavior using `--add-exports` or `--upgrade-module-path`. +The latter is preferable. -The Language API JAR on Maven Central exports all API packages in its module-info. Apply the `--upgrade-module-path` option together with `-Dgraalvm.locatorDisabled=true` and this JAR to export Language API packages: +The Language API JAR on Maven Central exports all API packages in its module-info. +Apply the `--upgrade-module-path` option together with `-Dgraalvm.locatorDisabled=true` and this JAR to export Language API packages: ```shell -Dgraalvm.locatorDisabled=true --module-path=:${truffle.dir} --upgrade-module-path=${truffle.dir}/truffle-api.jar ``` @@ -273,18 +252,13 @@ A sample POM using `--upgrade-module-path` to export Language API packages can b ### Other JVM Implementations -Unlike GraalVM, which includes all the dependencies needed to run a language -implemented with [Truffle](/graalvm-as-a-platform/language-implementation-framework/), other JVM implementations need additional -JARs to be present on the class path. These are the Language API and GraalVM SDK -JARs available from Maven Central. +Unlike GraalVM, which includes all the dependencies needed to run a language implemented with [Truffle](/graalvm-as-a-platform/language-implementation-framework/), other JVM implementations need additional JARs to be present on the class path. +These are the Language API and GraalVM SDK JARs available from Maven Central. -Assuming `JAVA_HOME` points to a stock JDK installation, and that the current -working directory is the `simplelanguage` directory and the Language API and -GraalVM SDK JARs are present in that directory, one can execute SimpleLanguage -with the following command: +Assuming `JAVA_HOME` points to a stock JDK installation, and that the current working directory is the `simplelanguage` directory and the Language API and GraalVM SDK JARs are present in that directory, one can execute SimpleLanguage with the following command: ```shell $JAVA_HOME/bin/java \ - -cp graal-sdk-21.2.0.jar:truffle-api-21.2.0.jar:launcher/target/launcher-21.2.0-SNAPSHOT.jar:language/target/simplelanguage.jar \ + -cp graal-sdk-21.3.0.jar:truffle-api-21.3.0.jar:launcher/target/launcher-21.3.0-SNAPSHOT.jar:language/target/simplelanguage.jar \ com.oracle.truffle.sl.launcher.SLMain language/tests/Add.sl ``` From 96e9a9246e1b0aed3ccfda2506809772aae3fd83 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 7 Oct 2021 13:11:10 +0300 Subject: [PATCH 325/681] Review and update java and java on truffle reference docs --- .../reference-manual/java-on-truffle/Demos.md | 3 +- docs/reference-manual/java-on-truffle/FAQ.md | 9 +- .../java-on-truffle/Interoperability.md | 2 +- .../java-on-truffle/README.md | 14 +-- docs/reference-manual/java/Operations.md | 119 ++++++------------ docs/reference-manual/java/Options.md | 2 +- 6 files changed, 55 insertions(+), 94 deletions(-) diff --git a/docs/reference-manual/java-on-truffle/Demos.md b/docs/reference-manual/java-on-truffle/Demos.md index 16f73280241d..dbf6bf341cf7 100644 --- a/docs/reference-manual/java-on-truffle/Demos.md +++ b/docs/reference-manual/java-on-truffle/Demos.md @@ -144,11 +144,10 @@ It is a REPL capable of evaluating Java code and consists of two parts: This design naturally fits the point we are trying to illustrate. We can build a native executable of the JShell's UI part, and make it include Java on Truffle to run the code dynamically specified at run time. Prerequisites: -* [GraalVM 21.0](/downloads/) +* [GraalVM 21.3](/downloads/) * [Native Image](/reference-manual/native-image/#install-native-image) * [Java on Truffle](/reference-manual/java-on-truffle/#install-java-on-truffle) - 1. Clone the [project](https://github.com/graalvm/graalvm-demos) with the demo applications and navigate to the `espresso-jshell` directory: ``` diff --git a/docs/reference-manual/java-on-truffle/FAQ.md b/docs/reference-manual/java-on-truffle/FAQ.md index b54113ff9670..449d10b50e70 100644 --- a/docs/reference-manual/java-on-truffle/FAQ.md +++ b/docs/reference-manual/java-on-truffle/FAQ.md @@ -10,7 +10,7 @@ permalink: /reference-manual/java-on-truffle/faq/ ### Does Java running on Truffle implement the Java language running as a Truffle interpreter? Not quite: it implements the Java Virtual Machine running as a Truffle interpreter. -That means it can only run a Java program once it has been compiled to Java bytecode (classes, JARs, etc.) with your favorite Java compiler (e.g., javac) or a build tool (Maven, Gradle, etc.). +That means it can only run a Java program once it has been compiled to Java bytecode (classes, JARs, etc.) with your favorite Java compiler (e.g., `javac`) or a build tool (Maven, Gradle, etc.). In the GraalVM family, this is similar to WebAssembly or the LLVM interpreter: while both can run C programs, they have to be complied by a C compiler first. ### Does Java running on Truffle run on HotSpot too? @@ -20,7 +20,7 @@ We plan to extend this capability to macOS and Windows platforms also. ### Does running Java on Truffle require HotSpot? No, it doesn't, it works fine as a native image. -Java on Truffle does require a standard core Java library (the `rt.jar` library for Java 8 or the `lib/modules` file for Java 11 as well as the associated native libraries: `libjava`, `libnio`, etc.) +Java on Truffle does require a standard core Java library (the `rt.jar` library for Java 8 or the `lib/modules` file for Java 11 and Java 17 as well as the associated native libraries: `libjava`, `libnio`, etc.) ### Running Java on GraalVM already brings the highest level of optimization, what benefits will Java on Truffle give me? - Java on Truffle will inherit the extensive tooling provided by the Truffle framework. This means that for the things like code coverage and profiling you would no longer need to rely on external tools. @@ -32,9 +32,8 @@ Java on Truffle does require a standard core Java library (the `rt.jar` library Java on Truffle is an implementation of the Java Virtual Machine. It is open source and is offered as free software under the [GNU General Public License version two (GPLv2)](https://github.com/oracle/graal/blob/master/tools/LICENSE). ### Can I run Java on Truffle in production? - Running in production is not recommended. -While Java on Truffle already passes the Java Compatibility Kit (JCK or TCK for Java SE) 8 and 11 runtimes, it is still an early prototype and experimental feature in GraalVM. +While Java on Truffle already passes the Java Compatibility Kit (JCK or TCK for Java SE) 8, 11 and 17 runtimes, it is still an early prototype and experimental feature in GraalVM. It may undergo significant improvements before being considered production-ready. ### What performance can I expect from executing Java on Truffle? @@ -43,7 +42,7 @@ It does not match the speed offered by GraalVM yet for sure, but having created ### Can I embed Java running on Truffle in my application? Yes, you can use [GraalVM's Polyglot API](https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/package-summary.html) to run Java bytecodes in a separate context from the host Java VM. -You can even embed a Java 8 context in a Java 11 application! +You can even embed a Java 8 context in a Java 11 or Java 17 application! ### Why do I see "Unrecognized option: -javaagent:.../idea_rt.jar..." when I try to run my app from the IDE? Java on Truffle does not yet support attaching Java agents. For the time being add: `-XX:+IgnoreUnrecognizedVMOptions` to the VM options too. diff --git a/docs/reference-manual/java-on-truffle/Interoperability.md b/docs/reference-manual/java-on-truffle/Interoperability.md index 4c4e24b27587..ba0336acce36 100644 --- a/docs/reference-manual/java-on-truffle/Interoperability.md +++ b/docs/reference-manual/java-on-truffle/Interoperability.md @@ -21,7 +21,7 @@ How this type is attached to foreign objects is an implementation detail. ## Polyglot -Java on Truffle provides a guest Java Polyglot API, described in [`polyglot.jar`](#). +Java on Truffle provides a guest Java Polyglot API, described in `polyglot.jar`. This JAR is automatically injected on guest Java contexts but can be excluded with `--java.Polyglot=false`. You can import the `Polyglot` class to interact with other guest languages: diff --git a/docs/reference-manual/java-on-truffle/README.md b/docs/reference-manual/java-on-truffle/README.md index 6dfe6681fbc4..94257a1b9ce5 100644 --- a/docs/reference-manual/java-on-truffle/README.md +++ b/docs/reference-manual/java-on-truffle/README.md @@ -18,7 +18,7 @@ The Java on Truffle execution mode runs Java via a Java bytecode interpreter, im Now Java can be executed by the same principle as other languages in the GraalVM ecosystem (JavaScript, Ruby, Python, R), directly interoperate with those languages, and pass data back and forth in the same memory space. Besides complete language interoperability, with Java on Truffle you can: -- run Java bytecodes in a separate context from the host Java VM. It can run either a Java 8 or Java 11 guest or host JVM. In other words, you can embed a Java 8 context in a Java 11 application, by using [GraalVM’s Polyglot API](https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/package-summary.html). +- run Java bytecodes in a separate context from the host Java VM. It can run either a Java 8, Java 11, Java 17 guest or host JVM. In other words, you can embed a Java 8 context in a Java 11 application, by using [GraalVM’s Polyglot API](https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/package-summary.html). - leverage the whole stack of tools provided by the Truffle framework, not previously available for Java. - have an improved isolation of the host Java VM and the Java program running on Truffle, so you can run less trusted guest code. - run in the context of a native image while still allowing dynamically-loaded bytecodes. @@ -90,13 +90,13 @@ This might be important for options such as `MaxDirectMemorySize` which can be s #### From Command Line -For the purpose of this guide, GraalVM Enterprise 21.2.0 distribution, based on Java 11 for macOS, is used. +For the purpose of this guide, GraalVM Enterprise 21.3.0 distribution, based on Java 11 for macOS, is used. To ensure you have successfully installed Java on Truffle, verify its version: ```shell java -truffle -version -java version "11.0.12" 2021-07-20 LTS -Java(TM) SE Runtime Environment GraalVM EE 21.2.0 (build 11.0.12+8-LTS-jvmci-21.2-b06) -Espresso 64-Bit VM GraalVM EE 21.2.0 (build 11-espresso-21.2.0, mixed mode) +java version "11.0.13" 2021-10-19 LTS +Java(TM) SE Runtime Environment GraalVM EE 21.3.0 (build 11.0.13+9-LTS-jvmci-21.3-b03) +Espresso 64-Bit VM GraalVM EE 21.3.0 (build 11-espresso-21.3.0, mixed mode) ``` Taking this `HelloWorld.java` example, compile it and run from the command line: @@ -109,8 +109,8 @@ public class HelloWorld { ``` ```shell -/bin/javac HelloWorld.java -/bin/java -truffle HelloWorld +$JAVA_HOME/bin/javac HelloWorld.java +$JAVA_HOME/bin/java -truffle HelloWorld HelloWorld.java! ``` diff --git a/docs/reference-manual/java/Operations.md b/docs/reference-manual/java/Operations.md index d295a86b7e84..8954db4ac771 100644 --- a/docs/reference-manual/java/Operations.md +++ b/docs/reference-manual/java/Operations.md @@ -9,21 +9,16 @@ permalink: /reference-manual/java/operations/ ## Running the GraalVM Compiler in Native Image vs on the JVM -When running the GraalVM compiler on the JVM, it goes through the same warm-up phase that the -rest of the Java application does. That is, it is first interpreted before -its hot methods are compiled. This can translate into slightly longer times -until the application reaches peak performance when compared to the native compilers -in the JVM such as C1 and C2. - -To address the issue of taking longer to reach to peak performance, **libgraal** -was introduced -- a shared library, produced using [Native Image](../native-image/README.md) to ahead-of-time compile the compiler itself. That means the GraalVM Enterprise -compiler is deployed as a native shared library. - -In this mode, the -compiler uses memory separate from the HotSpot heap, and it runs compiled from -the start. Therefore it has execution properties similar to other native HotSpot -compilers such as C1 and C2. Currently, this is the **default mode** of -operation. It can be disabled with `-XX:-UseJVMCINativeLibrary`. +When running the GraalVM compiler on the JVM, it goes through the same warm-up phase that the rest of the Java application does. +That is, it is first interpreted before its hot methods are compiled. +This can translate into slightly longer times until the application reaches peak performance when compared to the native compilers in the JVM such as C1 and C2. + +To address the issue of taking longer to reach to peak performance, **libgraal** was introduced -- a shared library, produced using [Native Image](../native-image/README.md) to ahead-of-time compile the compiler itself. +That means the GraalVM Enterprise compiler is deployed as a native shared library. + +In this mode, the compiler uses memory separate from the HotSpot heap, and it runs compiled from the start. +Therefore it has execution properties similar to other native HotSpot compilers such as C1 and C2. +Currently, this is the **default mode** of operation. It can be disabled with `-XX:-UseJVMCINativeLibrary`. ## Measuring Performance @@ -37,47 +32,32 @@ when the compiler is initialized: Using Graal compiler configuration 'community' provided by org.graalvm.compiler.hotspot.CommunityCompilerConfigurationFactory loaded from jar:file:/Users/dsimon/graal/graal/compiler/mxbuild/dists/graal.jar!/org/graalvm/compiler/hotspot/CommunityCompilerConfigurationFactory.class ``` -Note: The GraalVM compiler is only initialized on the first top-tier JIT compilation request -so if your application is short-lived, you may not see this output. +> Note: The GraalVM compiler is only initialized on the first top-tier JIT compilation request so if your application is short-lived, you may not see this output. -Optimizing JVM-based applications is a science in itself. The compilation may not -even be a factor in the case of poor performance as the problem may -lie in any other part of the VM (I/O, garbage collection, threading, etc), or in -a poorly written application or 3rd party library code. For this reason, it's -worth utilizing the [JDK Mission Control](https://www.oracle.com/java/technologies/jdk-mission-control.html) tool chain to -diagnose the application behavior. +Optimizing JVM-based applications is a science in itself. +The compilation may not even be a factor in the case of poor performance as the problem may lie in any other part of the VM (I/O, garbage collection, threading, etc), or in +a poorly written application or 3rd party library code. For this reason, it is worth utilizing the [JDK Mission Control](https://www.oracle.com/java/technologies/jdk-mission-control.html) tool chain to diagnose the application behavior. -You can also compare performance against the native top-tier compiler in the JVM by -adding `-XX:-UseJVMCICompiler` to the command line. +You can also compare performance against the native top-tier compiler in the JVM by adding `-XX:-UseJVMCICompiler` to the command line. -If you observe a significant performance regression when using the GraalVM compiler, please -open an issue on GitHub. Attaching a Java Flight Recorder log and instructions -to reproduce the issue makes investigation easier and thus the -chances of a fix higher. Even better is if you can submit a [JMH](http://openjdk.java.net/projects/code-tools/jmh/) -benchmark that represents the hottest parts of your application (as identified -by a profiler). This allows us to very quickly pinpoint missing optimization -opportunities or to offer suggestions on how to restructure the code to -avoid or reduce performance bottlenecks. +If you observe a significant performance regression when using the GraalVM compiler, please open an issue on GitHub. +Attaching a Java Flight Recorder log and instructions to reproduce the issue makes investigation easier and thus the chances of a fix higher. +Even better is if you can submit a [JMH](http://openjdk.java.net/projects/code-tools/jmh/) benchmark that represents the hottest parts of your application (as identified by a profiler). +This allows us to very quickly pinpoint missing optimization opportunities or to offer suggestions on how to restructure the code to avoid or reduce performance bottlenecks. ## Troubleshooting the GraalVM Compiler -Like all software, the GraalVM compiler is not guaranteed to be bug free so it is useful to -know how to diagnose and submit useful bug reports if you encounter issues. +Like all software, the GraalVM compiler is not guaranteed to be bug free so it is useful to know how to diagnose and submit useful bug reports if you encounter issues. -If you spot a security vulnerability, please do **not** report it via GitHub Issues or the public mailing lists, -but via the process outlined at [Reporting Vulnerabilities guide](https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html). +If you spot a security vulnerability, please do **not** report it via GitHub Issues or the public mailing lists, but via the process outlined at [Reporting Vulnerabilities guide](https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html). ### Compilation Exceptions -One advantage of the compiler being written in Java is that runtime exceptions during -compilation are not fatal VM errors. Instead, each compilation has an exception -handler that takes action based on the `graal.CompilationFailureAction` -property. +One advantage of the compiler being written in Java is that runtime exceptions during compilation are not fatal VM errors. +Instead, each compilation has an exception handler that takes action based on the `graal.CompilationFailureAction` property. -The default value is `Silent`. Specifying `Diagnose` causes failing compilations to be retried -with extra diagnostics enabled. In this case, just before the VM exits, all diagnostic output -captured during retried compilations is written to a `.zip` file and its location -is printed on the console: +The default value is `Silent`. Specifying `Diagnose` causes failing compilations to be retried with extra diagnostics enabled. +In this case, just before the VM exits, all diagnostic output captured during retried compilations is written to a `.zip` file and its location is printed on the console: ```shell Graal diagnostic output saved in /Users/demo/graal-dumps/1499768882600/graal_diagnostics_64565.zip ``` @@ -92,11 +72,8 @@ are also supported: ### Code Generation Errors The other type of error you might encounter with compilers is the production of incorrect machine code. -This error can cause a VM crash, which should produce a file that starts with -`hs_err_pid` in the current working directory of the VM process. In most cases, -there is a section in the file that shows the stack at the time of the crash, -including the type of code for each frame in the stack, as in the following -example: +This error can cause a VM crash, which should produce a file that starts with `hs_err_pid` in the current working directory of the VM process. +In most cases, there is a section in the file that shows the stack at the time of the crash, including the type of code for each frame in the stack, as in the following example: ```shell Stack: [0x00007000020b1000,0x00007000021b1000], sp=0x00007000021af7a0, free space=1017k @@ -106,16 +83,14 @@ j org.graalvm.compiler.core.gen.NodeLIRBuilder.doBlock(Lorg/graalvm/compiler/no j org.graalvm.compiler.core.LIRGenerationPhase.emitBlock(Lorg/graalvm/compiler/nodes/spi/NodeLIRBuilderTool;Lorg/graalvm/compiler/lir/gen/LIRGenerationResult;Lorg/graalvm/compiler/nodes/cfg/Block;Lorg/graalvm/compiler/nodes/StructuredGraph;Lorg/graalvm/compiler/core/common/cfg/BlockMap;)V+65 ``` -This example shows that the top frame was compiled (J) by the JVMCI compiler, -which is the GraalVM compiler. The crash occurred at offset 0x141 in the machine -code produced for: +This example shows that the top frame was compiled (J) by the JVMCI compiler, which is the GraalVM compiler. +The crash occurred at offset 0x141 in the machine code produced for: ```shell org.graalvm.compiler.core.gen.NodeLIRBuilder.matchComplexExpressions(Ljava/util/List;)V ``` -The next two frames in the stack were executed in the interpreter (j). The -location of the crash is also often indicated near the top of the file with -something like this: +The next two frames in the stack were executed in the interpreter (`j`). +The location of the crash is also often indicated near the top of the file with something like this: ```shell # Problematic frame: # J 761 JVMCI org.graalvm.compiler.core.gen.NodeLIRBuilder.matchComplexExpressions(Ljava/util/List;)V (299 bytes) @ 0x0000000108a2fc01 [0x0000000108a2fac0+0x141] (null) @@ -123,30 +98,22 @@ something like this: In this example, there is likely an error in the code produced by the GraalVM compiler for `NodeLIRBuilder.matchComplexExpressions`. -When filing an issue on [GitHub](https://github.com/oracle/graal/issues) -for such a crash, you should first attempt to reproduce the crash with extra -diagnostics enabled for the compilation of the problematic method. +When filing an issue on [GitHub](https://github.com/oracle/graal/issues) for such a crash, you should first attempt to reproduce the crash with extra diagnostics enabled for the compilation of the problematic method. In this example, you would add the following to your command line: ```shell -Dgraal.MethodFilter=NodeLIRBuilder.matchComplexExpressions, -Dgraal.Dump=:2 ``` These options are described in more detail [here](https://github.com/oracle/graal/blob/master/compiler/docs/Debugging.md). -In brief, these options tell the compiler to capture snapshots of the compiler state at -verbosity level 2 while compiling any method named `matchComplexExpressions` in -a class with a simple name of `NodeLIRBuilder`. The complete format of the -`MethodFilter` option is described in the output of `java -XX:+JVMCIPrintProperties`. +In brief, these options tell the compiler to capture snapshots of the compiler state at verbosity level 2 while compiling any method named `matchComplexExpressions` in a class with a simple name of `NodeLIRBuilder`. +The complete format of the `MethodFilter` option is described in the output of `java -XX:+JVMCIPrintProperties`. -Quite often, the crash location does not exist directly in the problematic method -mentioned in the crash log but comes from an inlined method. +Quite often, the crash location does not exist directly in the problematic method mentioned in the crash log but comes from an inlined method. -In such a case, simply filtering for the problematic method might not capture an -erroneous compilation causing a crash. +In such a case, simply filtering for the problematic method might not capture an erroneous compilation causing a crash. -To improve the likelihood of capturing an erroneous compilation, you need to -broaden the `MethodFilter` value. To guide this, add `-Dgraal.PrintCompilation=true` -when trying to reproduce the crash so you can see what was compiled just before -the crash. +To improve the likelihood of capturing an erroneous compilation, you need to broaden the `MethodFilter` value. +To guide this, add `-Dgraal.PrintCompilation=true` when trying to reproduce the crash so you can see what was compiled just before the crash. The following shows sample output from the console: ```shell @@ -166,19 +133,15 @@ HotSpotCompilation-1221 Lorg/graalvm/compiler/hotspot/amd64/AMD64HotSpotL # Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again ``` Here we see that the crash happened in a different method than the first crash. -As such, we expand the filter argument to be `-Dgraal.MethodFilter= -NodeLIRBuilder.matchComplexExpressions,AMD64HotSpotLIRGenerator.getResult` -and run again. +As such, we expand the filter argument to be `-Dgraal.MethodFilter= NodeLIRBuilder.matchComplexExpressions,AMD64HotSpotLIRGenerator.getResult` and run again. -When the VM crashes in this way, it does not execute the shutdown code that -archives the GraalVM compiler diagnostic output or delete the directory it was written to. +When the VM crashes in this way, it does not execute the shutdown code that archives the GraalVM compiler diagnostic output or delete the directory it was written to. This must be done manually after the crash. By default, the directory is `$PWD/graal-dumps/`; for example, `./graal-dumps/1499938817387`. However, you can set the directory with `-Dgraal.DumpPath=`. -A message, such as the following, is printed to the console when this -directory is first used by the compiler: +A message, such as the following, is printed to the console when this directory is first used by the compiler: ```shell Dumping debug output in /Users/demo/graal-dumps/1499768882600 ``` diff --git a/docs/reference-manual/java/Options.md b/docs/reference-manual/java/Options.md index bae8f2e4eb38..e9bfc3744a2a 100644 --- a/docs/reference-manual/java/Options.md +++ b/docs/reference-manual/java/Options.md @@ -133,4 +133,4 @@ Becomes: js --jvm --vm.Dgraal.ShowConfiguration=info -version ``` -Note the `-D` prefix is replaced by `--vm.D`. +> Note the `-D` prefix is replaced by `--vm.D`. From 4c209e21aad6a0d8fd24216600294526598e2fb4 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 7 Oct 2021 13:27:38 +0300 Subject: [PATCH 326/681] Review and update LLVM reference docs --- docs/reference-manual/java-on-truffle/README.md | 2 +- docs/reference-manual/llvm/Compiling.md | 4 ++-- docs/reference-manual/llvm/Debugging.md | 6 +----- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/docs/reference-manual/java-on-truffle/README.md b/docs/reference-manual/java-on-truffle/README.md index 94257a1b9ce5..2397311f41aa 100644 --- a/docs/reference-manual/java-on-truffle/README.md +++ b/docs/reference-manual/java-on-truffle/README.md @@ -129,7 +129,7 @@ cd spring-petclinic 3. Then run it from the command line by selecting the `-truffle` runtime: ```java -java -truffle -jar target/spring-petclinic-2.4.2.jar +java -truffle -jar target/spring-petclinic--SNAPSHOT.jar ``` 4. When the application starts, access it on [localhost:8000](http://localhost:8080/). diff --git a/docs/reference-manual/llvm/Compiling.md b/docs/reference-manual/llvm/Compiling.md index 4c7d74b507b1..4ac85eee3d82 100644 --- a/docs/reference-manual/llvm/Compiling.md +++ b/docs/reference-manual/llvm/Compiling.md @@ -41,7 +41,7 @@ For GraalVM Enterprise users, the [manual installation](https://www.graalvm.org/ To get the location of the toolchain, use the `--print-toolchain-path` argument of `lli`: ```shell -export LLVM_TOOLCHAIN=$($GRAALVM_HOME/bin/lli --print-toolchain-path) +export LLVM_TOOLCHAIN=$($JAVA_HOME/bin/lli --print-toolchain-path) ``` See the content of the toolchain path for a list of available tools: @@ -66,7 +66,7 @@ $LLVM_TOOLCHAIN/clang hello.c -o hello The resulting executable, `hello`, can be executed on GraalVM using `lli`: ```shell -$GRAALVM_HOME/bin/lli hello +$JAVA_HOME/bin/lli hello ``` ## External Library Dependencies diff --git a/docs/reference-manual/llvm/Debugging.md b/docs/reference-manual/llvm/Debugging.md index 6cd9556f5273..81b498d643d9 100644 --- a/docs/reference-manual/llvm/Debugging.md +++ b/docs/reference-manual/llvm/Debugging.md @@ -12,13 +12,9 @@ This includes support for single-stepping, breakpoints, and inspection of local To use this feature, make sure to compile your program with debug information enabled by specifying the `-g` argument when compiling with `clang` (the LLVM toolchain shipped with GraalVM will automatically enable debug information). This gives you the ability to step through the program's source code and set breakpoints in it. -With GraalVM 20.0 and older, the option `--llvm.enableLVI=true` is needed for being able to inspect variables during debugging. -This option is not enabled by default as it decreases the program's run-time performance. -Starting with GraalVM 20.1, this option is not needed anymore and thus deprecated. - To start debugging, run `lli` with the `--inspect` option: ```shell -$GRAALVM_HOME/bin/lli --inspect +$JAVA_HOME/bin/lli --inspect ``` When launched, the inspector will suspend execution at the first instruction of the program and print a link to the console. From c7f525d18c508f4d46b8d2f63feafd0e9b4aea46 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 7 Oct 2021 13:31:57 +0300 Subject: [PATCH 327/681] Review and update NI README --- docs/getting-started/graalvm-community/windows.md | 2 +- .../graalvm-enterprise/installation-windows.md | 2 +- docs/reference-manual/native-image/README.md | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/getting-started/graalvm-community/windows.md b/docs/getting-started/graalvm-community/windows.md index ada076c6d2ee..51907d8cd8bd 100644 --- a/docs/getting-started/graalvm-community/windows.md +++ b/docs/getting-started/graalvm-community/windows.md @@ -44,7 +44,7 @@ Currently, the GraalVM environment on Windows can be extended with [Native Image ## Prerequisites for Using Native Image on Windows -To start using Native Image on Windows, install Visual Studio Code and Microsoft Visual C++(MSVC). There are two installation options: +To start using Native Image on Windows, install Visual Studio and Microsoft Visual C++(MSVC). There are two installation options: * Install the Visual Studio Code Build Tools with the Windows 10 SDK * Install Visual Studio Code with the Windows 10 SDK diff --git a/docs/getting-started/graalvm-enterprise/installation-windows.md b/docs/getting-started/graalvm-enterprise/installation-windows.md index 06c444287c49..d6f671a1abc4 100644 --- a/docs/getting-started/graalvm-enterprise/installation-windows.md +++ b/docs/getting-started/graalvm-enterprise/installation-windows.md @@ -41,7 +41,7 @@ Currently, the GraalVM Enterprise environment on Windows can be extended with [N ## Prerequisites for Using Native Image on Windows -To start using Native Image on Windows, install Visual Studio Code and Microsoft Visual C++(MSVC). There are two installation options: +To start using Native Image on Windows, install Visual Studio and Microsoft Visual C++(MSVC). There are two installation options: * Install the Visual Studio Code Build Tools with the Windows 10 SDK * Install Visual Studio Code with the Windows 10 SDK diff --git a/docs/reference-manual/native-image/README.md b/docs/reference-manual/native-image/README.md index f54ac4b42196..e435289c4172 100644 --- a/docs/reference-manual/native-image/README.md +++ b/docs/reference-manual/native-image/README.md @@ -49,7 +49,7 @@ Run this command to install Native Image: gu install native-image ``` After this additional step, the `native-image` executable will become available in -the `GRAALVM_HOME/bin` directory. +the `$JAVA_HOME/bin` directory. The above command will install Native Image from the GitHub catalog for GraalVM Community users. For GraalVM Enterprise users, the [manual installation](https://www.graalvm.org/reference-manual/graalvm-updater/#manual-installation) is required. @@ -80,10 +80,16 @@ xcode-select --install ``` #### Prerequisites for Using Native Image on Windows -Building native images on Windows requires a Microsoft Visual C++ (MSVC) that comes with Visual Studio 2017 15.5.5 or later. -In addition, a proper [Developer Command Prompt](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt_shortcuts) for your version of [Visual Studio](https://visualstudio.microsoft.com/vs/). -On Windows the `native-image` tool only works when it is executed from the **x64 Native Tools Command Prompt**. +To start using Native Image on Windows, install [Visual Studio](https://visualstudio.microsoft.com/vs/) and Microsoft Visual C++(MSVC). There are two installation options: + * Install the Visual Studio Code Build Tools with the Windows 10 SDK + * Install Visual Studio Code with the Windows 10 SDK + +You can use Visual Studio 2017 version 15.9 or later. + +Lastly, on Windows, the `native-image` builder will only work when it is executed from the **x64 Native Tools Command Prompt**. +The command for initiating an x64 Native Tools command prompt is different if you only have the Visual Studio Build Tools installed, versus if you have the full VS Code 2019 installed. +Check [this link](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311) for step-by-step instructions. ## Build a Native Image From 23925be228f1aa49daeda70b5a9cfb002ff5972e Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 7 Oct 2021 13:33:29 +0300 Subject: [PATCH 328/681] Update versions in truffle/docs --- truffle/docs/README.md | 4 ++-- truffle/docs/TraversingCompilationQueue.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/truffle/docs/README.md b/truffle/docs/README.md index cb063485ac24..8ef647671c92 100644 --- a/truffle/docs/README.md +++ b/truffle/docs/README.md @@ -17,12 +17,12 @@ The Truffle bits are uploaded to [Maven central](https://mvnrepository.com/artif org.graalvm.truffle truffle-api - 21.2.0 + 21.3.0 org.graalvm.truffle truffle-dsl-processor - 21.2.0 + 21.3.0 provided ``` diff --git a/truffle/docs/TraversingCompilationQueue.md b/truffle/docs/TraversingCompilationQueue.md index edc8d19a55b9..a8446eeea5a0 100644 --- a/truffle/docs/TraversingCompilationQueue.md +++ b/truffle/docs/TraversingCompilationQueue.md @@ -6,7 +6,7 @@ permalink: /graalvm-as-a-platform/language-implementation-framework/TraversingCo --- # Truffle Approach to the Compilation Queue -As of version 21.2.0 Truffle has a new approach to compilation queueing. +As of version 21.3.0 Truffle has a new approach to compilation queueing. This document gives motivation and an overview of this approach. ## What is a Compilation queue? @@ -70,7 +70,7 @@ This gives a priority boost to targets that are currently "very hot" when compar For performance reasons the weight for tasks is cached and reused for a period of 1ms. If the cached value is older than 1ms, it is recalculated. -The traversing compilation queue is on by default as of version 21.2.0 and can be disabled using `--engine.TraversingCompilationQueue=false`. +The traversing compilation queue is on by default as of version 21.3.0 and can be disabled using `--engine.TraversingCompilationQueue=false`. ## Dynamic Compilation Thresholds @@ -135,5 +135,5 @@ MinScale >|/ . . MinNormalLoad MaxNormalLoad ``` -The dynamic thresholds only work with the traversing compilation queue and are on by default as of version 21.2.0. +The dynamic thresholds only work with the traversing compilation queue and are on by default as of version 21.3.0. They can be disabled with `--engine.DynamicCompilationThresholds=false`. From 99c599d531c0070ad11a66cf20a36f83160f19b8 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Thu, 7 Oct 2021 12:41:49 +0200 Subject: [PATCH 329/681] Drop duplicated item from changelog. --- truffle/CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 52e95d5e5dfc..962c7f6eac5f 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -6,8 +6,6 @@ This changelog summarizes major changes between Truffle versions relevant to lan * Truffle DSL generated code now inherits all annotations on constructor parameters to the static create factory method. * Added a [Message#getId()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/library/Message.html#getId--) method returning a unique message id within a library. * Added a [LibraryFactory#getMessages()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/library/LibraryFactory.html#getMessages--) method returning a list of messages that the library provides. - -* Changed behavior of `RootNode#getCallTarget()` such that it lazily initializes its call target. This enforces a one-to-one relationship between root nodes and call targets, which avoids several problems, for example, with regard to instrumentation. As a consequence, `RootNode.setCallTarget()` is deprecated and so will be `TruffleRuntime#createCallTarget()` soon. Please use `RootNode#getCallTarget()` to access the call target of a root node from now on. * Changed behavior of `RootNode#getCallTarget()` such that it lazily initializes its call target. This enforces a one-to-one relationship between root nodes and call targets, which avoids several problems, for example, with regard to instrumentation. As a consequence, `RootNode.setCallTarget()` and `TruffleRuntime#createCallTarget()` are deprecated now. Please use `RootNode#getCallTarget()` to access the call target of a root node from now on. * In `TruffleLanguage.finalizeContext(Object)`, there is a new requirement for leaving all remaining unclosed inner contexts created by the language on all threads where the contexts are still active. No active inner context is allowed after `TruffleLanguage.finalizeContext(Object)` returns. Not complying with this requirement will result in an internal error. Please note that inactive inner contexts are still closed implicitly by the parent context. From 5463b06da871ae1202ff757ec3cd2c82cc86b95e Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 6 Oct 2021 00:05:45 +0200 Subject: [PATCH 330/681] remove Graal support for jaotc --- compiler/mx.compiler/mx_compiler.py | 2 - .../compiler/code/CompilationResult.java | 49 +- .../amd64/AMD64ArithmeticLIRGenerator.java | 3 +- .../core/amd64/AMD64LIRGenerator.java | 5 +- .../compiler/core/common/GraalOptions.java | 10 - .../core/test/CheckGraalInvariants.java | 7 +- .../compiler/core/gen/LIRCompilerBackend.java | 5 - .../compiler/core/phases/BaseTier.java | 12 +- .../phases/EconomyCompilerConfiguration.java | 6 +- .../compiler/core/phases/EconomyHighTier.java | 5 +- .../compiler/core/phases/EconomyLowTier.java | 5 +- .../compiler/core/phases/EconomyMidTier.java | 5 +- .../compiler/core/phases/HighTier.java | 2 +- .../graalvm/compiler/core/phases/LowTier.java | 2 +- .../graalvm/compiler/core/phases/MidTier.java | 2 +- .../aarch64/AArch64HotSpotBackend.java | 32 +- .../AArch64HotSpotDirectStaticCallOp.java | 2 +- .../AArch64HotSpotDirectVirtualCallOp.java | 2 +- .../aarch64/AArch64HotSpotLIRGenerator.java | 125 +--- .../aarch64/AArch64HotSpotLoadAddressOp.java | 10 +- .../AArch64HotSpotLoadConfigValueOp.java | 85 --- .../hotspot/aarch64/AArch64HotSpotMove.java | 37 +- .../aarch64/AArch64IndirectCallOp.java | 2 +- .../amd64/AMD64HotSpotAddressLowering.java | 37 +- .../hotspot/amd64/AMD64HotSpotBackend.java | 35 +- .../amd64/AMD64HotSpotBackendFactory.java | 2 +- .../amd64/AMD64HotSpotDirectStaticCallOp.java | 2 +- .../amd64/AMD64HotSpotLIRGenerator.java | 120 +--- .../amd64/AMD64HotSpotLoadConfigValueOp.java | 83 --- .../amd64/AMD64HotSpotLoweringProvider.java | 11 - .../hotspot/amd64/AMD64HotSpotMove.java | 21 +- .../amd64/AMD64HotSpotSafepointOp.java | 25 +- .../AMD64HotspotDirectVirtualCallOp.java | 2 +- .../hotspot/amd64/AMD64IndirectCallOp.java | 2 +- .../test/AheadOfTimeCompilationTest.java | 210 ------ ...inateRedundantInitializationPhaseTest.java | 226 ------- .../test/HotSpotInvokeDynamicPluginTest.java | 149 ----- .../test/HotSpotLazyInitializationTest.java | 77 --- .../test/LoadJavaMirrorWithKlassTest.java | 123 ---- .../test/ReplaceConstantNodesPhaseTest.java | 164 ----- .../hotspot/AOTGraalHotSpotVMConfig.java | 59 -- .../CompilerRuntimeHotSpotVMConfig.java | 46 -- .../compiler/hotspot/EncodedSnippets.java | 2 +- .../compiler/hotspot/HotSpotBackend.java | 41 -- .../hotspot/HotSpotCompiledCodeBuilder.java | 2 +- .../compiler/hotspot/HotSpotGraalRuntime.java | 3 +- .../compiler/hotspot/HotSpotLIRGenerator.java | 104 --- .../compiler/hotspot/HotSpotMarkId.java | 4 + .../meta/DefaultHotSpotLoweringProvider.java | 36 +- .../HotSpotAOTClassInitializationPlugin.java | 96 --- .../meta/HotSpotAOTProfilingPlugin.java | 81 --- .../HotSpotGraalConstantFieldProvider.java | 57 +- .../meta/HotSpotGraphBuilderPlugins.java | 61 +- .../meta/HotSpotHostForeignCallsProvider.java | 22 - .../meta/HotSpotInvocationPlugins.java | 28 - .../meta/HotSpotInvokeDynamicPlugin.java | 159 ----- .../hotspot/meta/HotSpotNodePlugin.java | 18 +- .../hotspot/meta/HotSpotProfilingPlugin.java | 108 ---- .../hotspot/meta/HotSpotSuitesProvider.java | 57 +- .../nodes/GraalHotSpotVMConfigNode.java | 178 ------ .../hotspot/nodes/aot/EncodedSymbolNode.java | 72 --- .../nodes/aot/InitializeKlassNode.java | 64 -- .../nodes/aot/InitializeKlassStubCall.java | 115 ---- .../aot/LoadConstantIndirectlyFixedNode.java | 109 ---- .../nodes/aot/LoadConstantIndirectlyNode.java | 105 --- .../aot/LoadMethodCountersIndirectlyNode.java | 87 --- .../nodes/aot/LoadMethodCountersNode.java | 67 -- .../nodes/aot/ResolveConstantNode.java | 69 -- .../nodes/aot/ResolveConstantStubCall.java | 117 ---- .../nodes/aot/ResolveDynamicConstantNode.java | 65 -- .../nodes/aot/ResolveDynamicStubCall.java | 116 ---- .../aot/ResolveMethodAndLoadCountersNode.java | 64 -- .../ResolveMethodAndLoadCountersStubCall.java | 95 --- .../nodes/profiling/ProfileBranchNode.java | 92 --- .../nodes/profiling/ProfileInvokeNode.java | 58 -- .../hotspot/nodes/profiling/ProfileNode.java | 149 ----- .../ProfileWithNotificationNode.java | 67 -- .../nodes/profiling/RandomSeedNode.java | 54 -- .../phases/AheadOfTimeVerificationPhase.java | 114 ---- .../phases/LoadJavaMirrorWithKlassPhase.java | 148 ----- .../hotspot/phases/aot/AOTInliningPolicy.java | 118 ---- ...EliminateRedundantInitializationPhase.java | 259 -------- .../phases/aot/ReplaceConstantNodesPhase.java | 603 ------------------ .../profiling/FinalizeProfileNodesPhase.java | 175 ----- .../HotSpotAllocationSnippets.java | 93 +-- .../HotSpotG1WriteBarrierSnippets.java | 7 +- .../replacements/HotSpotReplacementsUtil.java | 33 +- .../HotSpotSerialWriteBarrierSnippets.java | 3 +- .../hotspot/replacements/HubGetClassNode.java | 3 +- .../replacements/InstanceOfSnippets.java | 6 - .../aot/ResolveConstantSnippets.java | 232 ------- .../ProbabilisticProfileSnippets.java | 184 ------ .../profiling/ProfileSnippets.java | 166 ----- .../hotspot/stubs/ForeignCallSnippets.java | 8 +- .../graalvm/compiler/hotspot/stubs/Stub.java | 5 +- .../graalvm/compiler/java/BytecodeParser.java | 81 +-- .../compiler/lir/aarch64/AArch64Call.java | 25 +- .../compiler/lir/aarch64/AArch64Move.java | 14 +- .../graalvm/compiler/lir/amd64/AMD64Call.java | 5 +- .../graalvm/compiler/lir/amd64/AMD64Move.java | 14 +- .../lir/asm/CompilationResultBuilder.java | 6 +- .../lir/GraalCompilerState.java | 6 +- .../compiler/nodes/CompressionNode.java | 10 +- .../graalvm/compiler/nodes/EncodedGraph.java | 13 +- .../compiler/nodes/StructuredGraph.java | 54 -- .../compiler/nodes/calc/CompareNode.java | 11 +- .../compiler/nodes/extended/LoadHubNode.java | 33 +- .../nodes/extended/LoadHubOrNullNode.java | 25 +- .../GraphBuilderConfiguration.java | 20 - .../graphbuilderconf/InvokeDynamicPlugin.java | 84 --- .../graphbuilderconf/ProfilingPlugin.java | 41 -- .../nodes/java/DynamicNewArrayNode.java | 7 - .../nodes/java/DynamicNewInstanceNode.java | 7 - .../phases/common/inlining/InliningUtil.java | 6 - .../compiler/replacements/PEGraphDecoder.java | 5 - .../replacements/SnippetTemplate.java | 14 +- .../arraycopy/ArrayCopySnippets.java | 5 - .../replacements/nodes/AssertionNode.java | 12 +- .../nodes/IdentityHashCodeNode.java | 5 - ...fleCallBoundaryInstrumentationFactory.java | 2 +- .../aarch64/SubstrateAArch64Backend.java | 2 +- .../graal/amd64/SubstrateAMD64Backend.java | 2 +- .../svm/core/graal/llvm/NodeLLVMBuilder.java | 1 - .../graal/meta/SubstrateReplacements.java | 2 +- .../com/oracle/svm/graal/GraalSupport.java | 2 +- vm/mx.vm/mx_vm_gate.py | 80 +-- 126 files changed, 256 insertions(+), 6926 deletions(-) delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadConfigValueOp.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotLazyInitializationTest.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerRuntimeHotSpotVMConfig.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTClassInitializationPlugin.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvokeDynamicPlugin.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileBranchNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileInvokeNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/RandomSeedNode.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java delete mode 100644 compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvokeDynamicPlugin.java delete mode 100644 compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/ProfilingPlugin.java diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index f3fb32bb8dd1..e3475a4188d4 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -562,7 +562,6 @@ def compiler_gate_benchmark_runner(tasks, extraVMarguments=None, prefix=''): _g1VerificationFlags = ['-XX:-UseSerialGC', '-XX:+UseG1GC'] _exceptionFlags = ['-Dgraal.StressInvokeWithExceptionNode=true'] _registerPressureFlags = ['-Dgraal.RegisterPressure=' + _registers[mx.get_arch()]] -_immutableCodeFlags = ['-Dgraal.ImmutableCode=true'] graal_bootstrap_tests = [ BootstrapTest('BootstrapWithSystemAssertionsFullVerify', _defaultFlags + _assertionFlags + _verificationFlags + _graalErrorFlags, tags=GraalTags.bootstrapfullverify), @@ -573,7 +572,6 @@ def compiler_gate_benchmark_runner(tasks, extraVMarguments=None, prefix=''): BootstrapTest('BootstrapWithSystemAssertionsEconomy', _defaultFlags + _assertionFlags + _graalEconomyFlags + _graalErrorFlags, tags=GraalTags.bootstrap), BootstrapTest('BootstrapWithSystemAssertionsExceptionEdges', _defaultFlags + _assertionFlags + _exceptionFlags + _graalErrorFlags, tags=GraalTags.bootstrap), BootstrapTest('BootstrapWithSystemAssertionsRegisterPressure', _defaultFlags + _assertionFlags + _registerPressureFlags + _graalErrorFlags, tags=GraalTags.bootstrap), - BootstrapTest('BootstrapWithSystemAssertionsImmutableCode', _defaultFlags + _assertionFlags + _immutableCodeFlags + ['-Dgraal.VerifyPhases=true'] + _graalErrorFlags, tags=GraalTags.bootstrap) ] def _graal_gate_runner(args, tasks): diff --git a/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java b/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java index 81dcedc60999..3c422def1e3d 100644 --- a/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java +++ b/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java @@ -37,7 +37,6 @@ import java.util.function.Function; import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.graph.NodeSourcePosition; @@ -58,7 +57,6 @@ import jdk.vm.ci.code.site.Site; import jdk.vm.ci.meta.Assumptions.Assumption; import jdk.vm.ci.meta.InvokeTarget; -import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.SpeculationLog; @@ -239,33 +237,17 @@ public String toString() { */ private SpeculationLog speculationLog; - /** - * The list of fields that were accessed from the bytecodes. - */ - private ResolvedJavaField[] fields; - private int bytecodeSize; private boolean hasUnsafeAccess; - private boolean isImmutablePIC; - public CompilationResult(CompilationIdentifier compilationId) { - this(compilationId, null, false); + this(compilationId, null); } public CompilationResult(CompilationIdentifier compilationId, String name) { - this(compilationId, name, false); - } - - public CompilationResult(CompilationIdentifier compilationId, boolean isImmutablePIC) { - this(compilationId, null, isImmutablePIC); - } - - public CompilationResult(CompilationIdentifier compilationId, String name, boolean isImmutablePIC) { this.compilationId = compilationId; this.name = name; - this.isImmutablePIC = isImmutablePIC; } public CompilationResult(String name) { @@ -406,31 +388,6 @@ public SpeculationLog getSpeculationLog() { return speculationLog; } - /** - * Sets the fields that were referenced from the bytecodes that were used as input to the - * compilation. - * - * @param accessedFields the collected set of fields accessed during compilation - */ - public void setFields(EconomicSet accessedFields) { - if (accessedFields != null) { - fields = accessedFields.toArray(new ResolvedJavaField[accessedFields.size()]); - } - } - - /** - * Gets the fields that were referenced from bytecodes that were used as input to the - * compilation. - * - * The caller must not modify the contents of the returned array. - * - * @return {@code null} if the compilation did not record fields dependencies otherwise the - * fields that were accessed from bytecodes were used as input to the compilation. - */ - public ResolvedJavaField[] getFields() { - return fields; - } - public void setBytecodeSize(int bytecodeSize) { checkOpen(); this.bytecodeSize = bytecodeSize; @@ -475,10 +432,6 @@ public void setMaxInterpreterFrameSize(int maxInterpreterFrameSize) { this.maxInterpreterFrameSize = maxInterpreterFrameSize; } - public boolean isImmutablePIC() { - return this.isImmutablePIC; - } - /** * Sets the machine that has been generated by the compiler. * diff --git a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java index 5989749c0d67..ad9af381ee30 100644 --- a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java @@ -79,7 +79,6 @@ import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SD; import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SS; import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.WORD; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; @@ -1370,7 +1369,7 @@ public void emitCompareOp(AMD64Kind cmpKind, Variable left, Value right) { return; } else if (c instanceof VMConstant) { VMConstant vc = (VMConstant) c; - if (size == DWORD && !GeneratePIC.getValue(getOptions()) && getLIRGen().target().inlineObjects) { + if (size == DWORD && getLIRGen().target().inlineObjects) { getLIRGen().append(new AMD64BinaryConsumer.VMConstOp(CMP.getMIOpcode(DWORD, false), left, vc)); } else { getLIRGen().append(new AMD64BinaryConsumer.DataOp(CMP.getRMOpcode(size), size, left, vc)); diff --git a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java index c43fc61c27e5..baf0eb032138 100644 --- a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java @@ -33,7 +33,6 @@ import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PD; import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PS; import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; @@ -349,7 +348,7 @@ private void emitRawCompareBranch(OperandSize size, Variable left, Value right, return; } else if (c instanceof VMConstant) { VMConstant vc = (VMConstant) c; - if (size == DWORD && !GeneratePIC.getValue(getResult().getLIR().getOptions()) && target().inlineObjects) { + if (size == DWORD && target().inlineObjects) { append(new CmpConstBranchOp(DWORD, left, vc, null, cond, trueLabel, falseLabel, trueLabelProbability)); } else { append(new CmpDataBranchOp(size, left, vc, cond, trueLabel, falseLabel, trueLabelProbability)); @@ -573,7 +572,7 @@ public void emitMembar(int barriers) { @Override protected void emitForeignCallOp(ForeignCallLinkage linkage, Value targetAddress, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { long maxOffset = linkage.getMaxCallTargetOffset(); - if (maxOffset != (int) maxOffset && !GeneratePIC.getValue(getResult().getLIR().getOptions())) { + if (maxOffset != (int) maxOffset) { append(new AMD64Call.DirectFarForeignCallOp(linkage, result, arguments, temps, info)); } else { append(new AMD64Call.DirectNearForeignCallOp(linkage, result, arguments, temps, info)); diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java index 3f73efbfaa7d..02539c0d3c31 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java @@ -199,16 +199,6 @@ public final class GraalOptions { @Option(help = "", type = OptionType.Debug) public static final OptionKey CanOmitFrame = new OptionKey<>(true); - // Ahead of time compilation - @Option(help = "Try to avoid emitting code where patching is required", type = OptionType.Expert) - public static final OptionKey ImmutableCode = new OptionKey<>(false); - - @Option(help = "Generate position independent code", type = OptionType.Expert) - public static final OptionKey GeneratePIC = new OptionKey<>(false); - - @Option(help = "Generate verify oop checks in AOT code", type = OptionType.Expert) - public static final OptionKey AOTVerifyOops = new OptionKey<>(false); - // Runtime settings @Option(help = "", type = OptionType.Expert) public static final OptionKey SupportJsrBytecodes = new OptionKey<>(true); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java index bd0cc6fc1601..247d4727bb19 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java @@ -57,6 +57,7 @@ import org.graalvm.compiler.api.test.ModuleSupport; import org.graalvm.compiler.bytecode.BridgeMethodUtils; import org.graalvm.compiler.core.CompilerThreadFactory; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import org.graalvm.compiler.debug.DebugCloseable; @@ -533,7 +534,11 @@ private static void collectOptionFieldUsages(Map errors, Map> optionFieldUsages) { for (Map.Entry> e : optionFieldUsages.entrySet()) { if (e.getValue().isEmpty()) { - errors.add("No uses found for " + e.getKey().format("%H.%n")); + if (e.getKey().format("%H.%n").equals(GraalOptions.VerifyPhases.getDescriptor().getLocation())) { + // Special case: This option may only have downstream uses + } else { + errors.add("No uses found for " + e.getKey().format("%H.%n")); + } } } } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java index 66fa406fdee1..e6e17723389c 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java @@ -27,7 +27,6 @@ import java.util.Collection; import java.util.List; -import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.LIRGenerationPhase; import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext; @@ -67,7 +66,6 @@ import jdk.vm.ci.meta.Assumptions; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.VMConstant; @@ -91,7 +89,6 @@ public static void emitBackEnd(StructuredGraph gra graph.getAssumptions(), graph.method(), graph.getMethods(), - graph.getFields(), graph.getSpeculationLog(), bytecodeSize, lirGen, @@ -199,7 +196,6 @@ public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection inlinedMethods, - EconomicSet accessedFields, SpeculationLog speculationLog, int bytecodeSize, LIRGenerationResult lirGenRes, @@ -218,7 +214,6 @@ public static void emitCode(Backend backend, } if (rootMethod != null) { compilationResult.setMethods(rootMethod, inlinedMethods); - compilationResult.setFields(accessedFields); compilationResult.setBytecodeSize(bytecodeSize); } if (speculationLog != null) { diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/BaseTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/BaseTier.java index b577e522672a..ad9e6e57bf16 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/BaseTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/BaseTier.java @@ -24,8 +24,6 @@ */ package org.graalvm.compiler.core.phases; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - import org.graalvm.compiler.nodes.loop.DefaultLoopPolicies; import org.graalvm.compiler.nodes.loop.LoopPolicies; import org.graalvm.compiler.options.OptionValues; @@ -38,13 +36,7 @@ public LoopPolicies createLoopPolicies(@SuppressWarnings("unused") OptionValues return new DefaultLoopPolicies(); } - public CanonicalizerPhase createCanonicalizerPhase(OptionValues options) { - CanonicalizerPhase canonicalizer = null; - if (ImmutableCode.getValue(options)) { - canonicalizer = CanonicalizerPhase.createWithoutReadCanonicalization(); - } else { - canonicalizer = CanonicalizerPhase.create(); - } - return canonicalizer; + public CanonicalizerPhase createCanonicalizerPhase() { + return CanonicalizerPhase.create(); } } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java index 73ccbaca39a2..87fed39234b7 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java @@ -48,17 +48,17 @@ public class EconomyCompilerConfiguration implements CompilerConfiguration { @Override public PhaseSuite createHighTier(OptionValues options) { - return new EconomyHighTier(options); + return new EconomyHighTier(); } @Override public PhaseSuite createMidTier(OptionValues options) { - return new EconomyMidTier(options); + return new EconomyMidTier(); } @Override public PhaseSuite createLowTier(OptionValues options) { - return new EconomyLowTier(options); + return new EconomyLowTier(); } @Override diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java index a2a83f2a095e..4950478c89c8 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java @@ -25,15 +25,14 @@ package org.graalvm.compiler.core.phases; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; public class EconomyHighTier extends BaseTier { - public EconomyHighTier(OptionValues options) { - CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(options); + public EconomyHighTier() { + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); appendPhase(canonicalizer); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER, true)); } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java index b67add26ef31..4ef1d8ae2fe9 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java @@ -25,7 +25,6 @@ package org.graalvm.compiler.core.phases; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase; @@ -35,8 +34,8 @@ public class EconomyLowTier extends BaseTier { - public EconomyLowTier(OptionValues options) { - CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(options); + public EconomyLowTier() { + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER)); appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new ExpandLogicPhase())); appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS)); diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java index 3b6e136a7686..449032907ae9 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java @@ -25,7 +25,6 @@ package org.graalvm.compiler.core.phases; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; @@ -37,8 +36,8 @@ public class EconomyMidTier extends BaseTier { - public EconomyMidTier(OptionValues options) { - CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(options); + public EconomyMidTier() { + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); appendPhase(new RemoveValueProxyPhase()); appendPhase(new LoopSafepointInsertionPhase()); appendPhase(new GuardLoweringPhase()); diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java index f0090dcb2e26..8f764b74a58c 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java @@ -69,7 +69,7 @@ public static class Options { } public HighTier(OptionValues options) { - CanonicalizerPhase canonicalizer = createCanonicalizerPhase(options); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); appendPhase(canonicalizer); if (NodeCounterPhase.Options.NodeCounters.getValue(options)) { diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java index 67b8b0e5c0e3..9d48abf0ebd9 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java @@ -56,7 +56,7 @@ static class Options { } public LowTier(OptionValues options) { - CanonicalizerPhase canonicalizer = createCanonicalizerPhase(options); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); CanonicalizerPhase canonicalizerWithoutGVN = canonicalizer.copyWithoutGVN(); if (Options.ProfileCompiledMethods.getValue(options)) { diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java index 7227895cbae1..285cb3490f3b 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java @@ -66,7 +66,7 @@ public class MidTier extends BaseTier { public MidTier(OptionValues options) { - CanonicalizerPhase canonicalizer = createCanonicalizerPhase(options); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); appendPhase(new LockEliminationPhase()); diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index ce6b98a1f7c5..133ddbf5fd1e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -32,7 +32,6 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.IMMEDIATE_UNSIGNED_SCALED; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import org.graalvm.compiler.asm.Assembler; @@ -44,7 +43,6 @@ import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules; -import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.LIRGenerationProvider; @@ -55,7 +53,6 @@ import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotMarkId; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -83,7 +80,6 @@ import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.hotspot.HotSpotCallingConventionType; -import jdk.vm.ci.hotspot.HotSpotSentinelConstant; import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; @@ -136,8 +132,7 @@ public InstalledCode createInstalledCode(DebugContext debug, boolean isDefault, Object[] context) { boolean isStub = (method == null); - boolean isAOT = compilationResult.isImmutablePIC(); - if (!isStub && !isAOT) { + if (!isStub) { // Non-stub compilation results are installed into HotSpot as nmethods. As AArch64 has // a constraint that the instruction at nmethod verified entry point should be a nop or // jump, AArch64HotSpotBackend always generate a nop placeholder before the code body @@ -336,7 +331,7 @@ private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod ins Register klass = r10; if (config.useCompressedClassPointers) { masm.ldr(32, klass, klassAddress); - AArch64HotSpotMove.decodeKlassPointer(crb, masm, klass, klass, config.getKlassEncoding()); + AArch64HotSpotMove.decodeKlassPointer(masm, klass, klass, config.getKlassEncoding()); } else { masm.ldr(64, klass, klassAddress); } @@ -351,23 +346,6 @@ private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod ins masm.align(config.codeEntryAlignment); masm.bind(verifiedStub); crb.recordMark(crb.compilationResult.getEntryBCI() != -1 ? HotSpotMarkId.OSR_ENTRY : HotSpotMarkId.VERIFIED_ENTRY); - - if (GeneratePIC.getValue(crb.getOptions())) { - // Check for method state - HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; - if (!frameContext.isStub) { - crb.recordInlineDataInCodeWithNote(new HotSpotSentinelConstant(LIRKind.value(AArch64Kind.QWORD), JavaKind.Long), HotSpotConstantLoadAction.MAKE_NOT_ENTRANT); - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - masm.adrpAdd(scratch); - masm.ldr(64, scratch, AArch64Address.createBaseRegisterOnlyAddress(64, scratch)); - Label noCall = new Label(); - masm.cbz(64, scratch, noCall); - AArch64Call.directJmp(crb, masm, getForeignCalls().lookupForeignCall(WRONG_METHOD_HANDLER)); - masm.bind(noCall); - } - } - } } private static void emitCodeBody(CompilationResultBuilder crb, LIR lir, AArch64MacroAssembler masm) { @@ -382,10 +360,8 @@ private static void emitCodeBody(CompilationResultBuilder crb, LIR lir, AArch64M * @see "http://mail.openjdk.java.net/pipermail/aarch64-port-dev/2013-September/000273.html" */ public static void emitInvalidatePlaceholder(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - if (!GeneratePIC.getValue(crb.getOptions())) { - crb.blockComment("[nop for method invalidation]"); - masm.nop(); - } + crb.blockComment("[nop for method invalidation]"); + masm.nop(); } private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler masm, FrameMap frameMap) { diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectStaticCallOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectStaticCallOp.java index dd72b8837dbc..f0c3cdd34f78 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectStaticCallOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectStaticCallOp.java @@ -62,7 +62,7 @@ final class AArch64HotSpotDirectStaticCallOp extends DirectCallOp { @Override @SuppressWarnings("try") public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - try (CompilationResultBuilder.CallContext callContext = crb.openCallContext(invokeKind.isDirect())) { + try (CompilationResultBuilder.CallContext callContext = crb.openCallContext()) { // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. // For the first invocation this is set to a bitpattern that is guaranteed to never be a diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectVirtualCallOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectVirtualCallOp.java index 12a2cc9942d9..6c5ec7bfed5e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectVirtualCallOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectVirtualCallOp.java @@ -62,7 +62,7 @@ final class AArch64HotSpotDirectVirtualCallOp extends DirectCallOp { @Override @SuppressWarnings("try") public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - try (CompilationResultBuilder.CallContext callContext = crb.openCallContext(invokeKind.isDirect())) { + try (CompilationResultBuilder.CallContext callContext = crb.openCallContext()) { // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. // For the first invocation this is set to a bitpattern that is guaranteed to never be a diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java index 055299c07c09..b5d3f0abd766 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java @@ -26,15 +26,6 @@ package org.graalvm.compiler.hotspot.aarch64; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_DYNAMIC_INVOKE; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.INITIALIZE; -import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS; -import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE; import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; @@ -51,10 +42,8 @@ import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator; import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool; import org.graalvm.compiler.core.common.CompressEncoding; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.debug.GraalError; @@ -65,9 +54,7 @@ import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; -import org.graalvm.compiler.hotspot.HotSpotMarkId; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -85,11 +72,9 @@ import org.graalvm.compiler.lir.aarch64.AArch64Move; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp; -import org.graalvm.compiler.lir.aarch64.AArch64ReadTimestampCounter; import org.graalvm.compiler.lir.aarch64.AArch64RestoreRegistersOp; import org.graalvm.compiler.lir.aarch64.AArch64SaveRegistersOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; -import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.aarch64.AArch64; import jdk.vm.ci.aarch64.AArch64Kind; @@ -97,7 +82,6 @@ import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterValue; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; @@ -258,7 +242,6 @@ protected boolean emitCompare(PlatformKind cmpKind, Value a, Value b, Condition @Override public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { LIRKind inputKind = pointer.getValueKind(LIRKind.class); - LIRKindTool lirKindTool = getLIRKindTool(); assert inputKind.getPlatformKind() == AArch64Kind.QWORD; if (inputKind.isReference(0)) { // oop @@ -269,16 +252,8 @@ public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonN // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD)); AllocatableValue base = Value.ILLEGAL; - OptionValues options = getResult().getLIR().getOptions(); - if (encoding.hasBase() || GeneratePIC.getValue(options)) { - if (GeneratePIC.getValue(options)) { - Variable baseAddress = newVariable(lirKindTool.getWordKind()); - AArch64HotSpotMove.BaseMove move = new AArch64HotSpotMove.BaseMove(baseAddress); - append(move); - base = baseAddress; - } else { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); - } + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } append(new AArch64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -298,16 +273,8 @@ public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean no // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.QWORD)); AllocatableValue base = Value.ILLEGAL; - OptionValues options = getResult().getLIR().getOptions(); - if (encoding.hasBase() || GeneratePIC.getValue(options)) { - if (GeneratePIC.getValue(options)) { - Variable baseAddress = newVariable(LIRKind.value(AArch64Kind.QWORD)); - AArch64HotSpotMove.BaseMove move = new AArch64HotSpotMove.BaseMove(baseAddress); - append(move); - base = baseAddress; - } else { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); - } + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } append(new AArch64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -467,73 +434,6 @@ public void emitUnwind(Value exception) { append(new AArch64HotSpotUnwindOp(config, exceptionParameter)); } - @Override - public Value emitLoadObjectAddress(Constant constant) { - HotSpotObjectConstant objectConstant = (HotSpotObjectConstant) constant; - LIRKind kind = objectConstant.isCompressed() ? getLIRKindTool().getNarrowOopKind() : getLIRKindTool().getObjectKind(); - Variable result = newVariable(kind); - append(new AArch64HotSpotLoadAddressOp(result, constant, HotSpotConstantLoadAction.RESOLVE)); - return result; - } - - @Override - public Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) { - HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant; - LIRKind kind = metaspaceConstant.isCompressed() ? getLIRKindTool().getNarrowPointerKind() : getLIRKindTool().getWordKind(); - Variable result = newVariable(kind); - append(new AArch64HotSpotLoadAddressOp(result, constant, action)); - return result; - } - - private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, Object[] notes, Constant[] constants, AllocatableValue[] constantDescriptions, LIRFrameState frameState) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(foreignCall); - append(new AArch64HotSpotConstantRetrievalOp(constants, constantDescriptions, frameState, linkage, notes)); - AllocatableValue result = linkage.getOutgoingCallingConvention().getReturn(); - return emitMove(result); - } - - private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, HotSpotConstantLoadAction action, Constant constant, AllocatableValue[] constantDescriptions, LIRFrameState frameState) { - Constant[] constants = new Constant[]{constant}; - Object[] notes = new Object[]{action}; - return emitConstantRetrieval(foreignCall, notes, constants, constantDescriptions, frameState); - } - - @Override - public Value emitResolveDynamicInvoke(Constant appendix, LIRFrameState frameState) { - AllocatableValue[] constantDescriptions = new AllocatableValue[0]; - return emitConstantRetrieval(RESOLVE_DYNAMIC_INVOKE, INITIALIZE, appendix, constantDescriptions, frameState); - } - - @Override - public Value emitLoadConfigValue(HotSpotMarkId markId, LIRKind kind) { - Variable result = newVariable(kind); - append(new AArch64HotSpotLoadConfigValueOp(markId, result)); - return result; - } - - @Override - public Value emitRandomSeed() { - Variable result = newVariable(LIRKind.value(AArch64Kind.QWORD)); - AArch64ReadTimestampCounter timestamp = new AArch64ReadTimestampCounter(result); - append(timestamp); - return result; - } - - private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, HotSpotConstantLoadAction action, Constant constant, Value constantDescription, LIRFrameState frameState) { - AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(constantDescription)}; - return emitConstantRetrieval(foreignCall, action, constant, constantDescriptions, frameState); - } - - @Override - public Value emitObjectConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { - return emitConstantRetrieval(RESOLVE_STRING_BY_SYMBOL, RESOLVE, constant, constantDescription, frameState); - } - - @Override - public Value emitMetaspaceConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { - return emitConstantRetrieval(RESOLVE_KLASS_BY_SYMBOL, RESOLVE, constant, constantDescription, frameState); - } - @Override public void emitReturn(JavaKind kind, Value input) { AllocatableValue operand = Value.ILLEGAL; @@ -545,17 +445,6 @@ public void emitReturn(JavaKind kind, Value input) { append(new AArch64HotSpotReturnOp(operand, getStub() != null, config, thread, getResult().requiresReservedStackAccessCheck())); } - @Override - public Value emitKlassInitializationAndRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { - return emitConstantRetrieval(INITIALIZE_KLASS_BY_SYMBOL, INITIALIZE, constant, constantDescription, frameState); - } - - @Override - public Value emitResolveMethodAndLoadCounters(Constant method, Value klassHint, Value methodDescription, LIRFrameState frameState) { - AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(klassHint), asAllocatable(methodDescription)}; - return emitConstantRetrieval(RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, LOAD_COUNTERS, method, constantDescriptions, frameState); - } - /** * Gets the {@link Stub} this generator is generating code for or {@code null} if a stub is not * being generated. @@ -601,12 +490,6 @@ public void emitZeroMemory(Value address, Value length, boolean isAligned) { // Use DC ZVA if it's not prohibited and AArch64 HotSpot flag UseBlockZeroing is on. boolean useDcZva = !isDcZvaProhibited && flags.contains(AArch64.Flag.UseBlockZeroing); - // Set zva length negative (unknown at compile-time) for AOT compilation, since the value - // could be different on different AArch64 CPU implementations. - if (GraalOptions.ImmutableCode.getValue(getResult().getLIR().getOptions())) { - useDcZva = false; - } - emitZeroMemory(address, length, isAligned, useDcZva, zvaLength); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadAddressOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadAddressOp.java index 3b2c7adcb164..6e88abe2ed95 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadAddressOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadAddressOp.java @@ -27,11 +27,9 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import jdk.vm.ci.aarch64.AArch64Kind; -import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; -import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRInstructionClass; @@ -68,12 +66,6 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { default: throw GraalError.shouldNotReachHere("unexpected kind: " + kind); } - if (crb.compilationResult.isImmutablePIC()) { - Register dst = asRegister(result); - masm.adrpAdd(dst); - masm.ldr(size, dst, AArch64Address.createBaseRegisterOnlyAddress(size, dst)); - } else { - masm.ldr(size, asRegister(result), masm.getPlaceholder(-1)); - } + masm.ldr(size, asRegister(result), masm.getPlaceholder(-1)); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadConfigValueOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadConfigValueOp.java deleted file mode 100644 index 750cf8e0513b..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoadConfigValueOp.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, Red Hat Inc. 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 org.graalvm.compiler.hotspot.aarch64; - -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; - -import org.graalvm.compiler.asm.aarch64.AArch64Address; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.HotSpotMarkId; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; - -import jdk.vm.ci.aarch64.AArch64Kind; -import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.AllocatableValue; - -public final class AArch64HotSpotLoadConfigValueOp extends AArch64LIRInstruction { - - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64HotSpotLoadConfigValueOp.class); - - @Def({OperandFlag.REG}) protected AllocatableValue result; - private final HotSpotMarkId markId; - - public AArch64HotSpotLoadConfigValueOp(HotSpotMarkId markId, AllocatableValue result) { - super(TYPE); - this.result = result; - this.markId = markId; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - if (GeneratePIC.getValue(crb.getOptions())) { - AArch64Kind kind = (AArch64Kind) result.getPlatformKind(); - Register reg = asRegister(result); - masm.adrpAdd(reg); - switch (kind) { - case BYTE: - masm.ldrs(32, 8, reg, AArch64Address.createBaseRegisterOnlyAddress(8, reg)); - break; - case WORD: - masm.ldrs(32, 16, reg, AArch64Address.createBaseRegisterOnlyAddress(16, reg)); - break; - case DWORD: - masm.ldr(32, reg, AArch64Address.createBaseRegisterOnlyAddress(32, reg)); - break; - case QWORD: - masm.ldr(64, reg, AArch64Address.createBaseRegisterOnlyAddress(64, reg)); - break; - default: - throw GraalError.unimplemented(); - } - masm.nop(); - } else { - throw GraalError.unimplemented(); - } - crb.recordMark(markId); - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java index fe39dd2c4652..0e1862fdfbac 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java @@ -27,7 +27,6 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; @@ -137,9 +136,8 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register resultRegister = asRegister(result); Register ptr = asRegister(input); Register base = (isRegister(baseRegister) ? asRegister(baseRegister) : zr); - boolean pic = GeneratePIC.getValue(crb.getOptions()); // result = (ptr - base) >> shift - if (!pic && !encoding.hasBase()) { + if (!encoding.hasBase()) { if (encoding.hasShift()) { masm.lsr(64, resultRegister, ptr, encoding.getShift()); } else { @@ -188,8 +186,7 @@ public UncompressPointer(AllocatableValue result, AllocatableValue input, Alloca public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register inputRegister = asRegister(input); Register resultRegister = asRegister(result); - boolean pic = GeneratePIC.getValue(crb.getOptions()); - Register base = pic || encoding.hasBase() ? asRegister(baseRegister) : null; + Register base = encoding.hasBase() ? asRegister(baseRegister) : null; emitUncompressCode(masm, inputRegister, resultRegister, base, encoding.getShift(), nonNull); } @@ -220,34 +217,12 @@ public static void emitUncompressCode(AArch64MacroAssembler masm, Register input } } - // - // private static void decompressPointer(CompilationResultBuilder crb, ARMv8MacroAssembler masm, - // Register result, - // Register ptr, long base, int shift, int alignment) { - // assert base != 0 || shift == 0 || alignment == shift; - // // result = heapBase + ptr << alignment - // Register heapBase = ARMv8.heapBaseRegister; - // // if result == 0, we make sure that it will still be 0 at the end, so that it traps when - // // loading storing a value. - // masm.cmp(32, ptr, 0); - // masm.add(64, result, heapBase, ptr, ARMv8Assembler.ExtendType.UXTX, alignment); - // masm.cmov(64, result, result, ARMv8.zr, ARMv8Assembler.ConditionFlag.NE); - // } - - public static void decodeKlassPointer(CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, Register ptr, CompressEncoding encoding) { + public static void decodeKlassPointer(AArch64MacroAssembler masm, Register result, Register ptr, CompressEncoding encoding) { try (AArch64MacroAssembler.ScratchRegister sc = masm.getScratchRegister()) { Register scratch = sc.getRegister(); - boolean pic = GeneratePIC.getValue(crb.getOptions()); - if (pic || encoding.hasBase() || encoding.getShift() != 0) { - if (pic) { - masm.adrpAdd(scratch); - masm.ldr(64, scratch, AArch64Address.createBaseRegisterOnlyAddress(64, scratch)); - masm.add(64, result, scratch, ptr, AArch64Assembler.ExtendType.UXTX, encoding.getShift()); - crb.recordMark(HotSpotMarkId.NARROW_KLASS_BASE_ADDRESS); - } else { - masm.mov(scratch, encoding.getBase()); - masm.add(64, result, scratch, ptr, AArch64Assembler.ExtendType.UXTX, encoding.getShift()); - } + if (encoding.hasBase() || encoding.getShift() != 0) { + masm.mov(scratch, encoding.getBase()); + masm.add(64, result, scratch, ptr, AArch64Assembler.ExtendType.UXTX, encoding.getShift()); } } } diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64IndirectCallOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64IndirectCallOp.java index 0ccb9d2c8efe..bf21e69d4a7b 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64IndirectCallOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64IndirectCallOp.java @@ -67,7 +67,7 @@ final class AArch64IndirectCallOp extends IndirectCallOp { @Override @SuppressWarnings("try") public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - try (CompilationResultBuilder.CallContext callContext = crb.openCallContext(false)) { + try (CompilationResultBuilder.CallContext callContext = crb.openCallContext()) { crb.recordMark(HotSpotMarkId.INLINE_INVOKE); Register callReg = asRegister(targetAddress); assert !callReg.equals(METHOD); diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java index 7417b4ad3240..a1324d1b53dc 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java @@ -25,20 +25,14 @@ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; - import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.amd64.AMD64AddressNode; import org.graalvm.compiler.core.amd64.AMD64CompressAddressLowering; import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.type.IntegerStamp; -import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotMarkId; -import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; -import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.nodes.CompressionNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; @@ -57,10 +51,8 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoopsDataProvider; -import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.JavaKind; public class AMD64HotSpotAddressLowering extends AMD64CompressAddressLowering { @@ -69,14 +61,10 @@ public class AMD64HotSpotAddressLowering extends AMD64CompressAddressLowering { private final long heapBase; private final Register heapBaseRegister; - private final GraalHotSpotVMConfig config; - private final boolean generatePIC; - public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister, OptionValues options) { + public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister) { this.heapBase = config.getOopEncoding().getBase(); - this.config = config; - this.generatePIC = GeneratePIC.getValue(options); - if (heapBase == 0 && !generatePIC) { + if (heapBase == 0) { this.heapBaseRegister = null; } else { this.heapBaseRegister = heapBaseRegister; @@ -91,28 +79,17 @@ protected final boolean improveUncompression(AMD64AddressNode addr, CompressionN } if (heapBaseRegister != null && encoding.getBase() == heapBase) { - if ((!generatePIC || compression.stamp(NodeView.DEFAULT) instanceof ObjectStamp) && other == null) { - // With PIC it is only legal to do for oops since the base value may be - // different at runtime. + if (other == null) { ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister)); addr.setBase(base); } else { return false; } - } else if (encoding.getBase() != 0 || (generatePIC && compression.stamp(NodeView.DEFAULT) instanceof KlassPointerStamp)) { - if (generatePIC) { - if (other == null) { - ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, HotSpotMarkId.NARROW_KLASS_BASE_ADDRESS, JavaKind.Long)); - addr.setBase(base); - } else { - return false; - } + } else if (encoding.getBase() != 0) { + if (updateDisplacement(addr, encoding.getBase(), false)) { + addr.setBase(other); } else { - if (updateDisplacement(addr, encoding.getBase(), false)) { - addr.setBase(other); - } else { - return false; - } + return false; } } else { addr.setBase(other); diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java index 447ede6a1a0b..1055fde9a51d 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java @@ -30,7 +30,6 @@ import static jdk.vm.ci.amd64.AMD64.rsp; import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.core.common.GraalOptions.CanOmitFrame; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import org.graalvm.compiler.asm.amd64.AMD64Address; @@ -40,7 +39,6 @@ import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules; -import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.gen.LIRGenerationProvider; @@ -51,7 +49,6 @@ import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotMarkId; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -72,13 +69,11 @@ import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.amd64.AMD64; -import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.hotspot.HotSpotCallingConventionType; -import jdk.vm.ci.hotspot.HotSpotSentinelConstant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; @@ -282,18 +277,13 @@ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationRes if (config.useCompressedClassPointers) { Register register = r10; Register heapBase = providers.getRegisters().getHeapBaseRegister(); - AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, heapBase, src, config); - if (GeneratePIC.getValue(crb.getOptions())) { - asm.movq(heapBase, asm.getPlaceholder(-1)); - crb.recordMark(HotSpotMarkId.NARROW_OOP_BASE_ADDRESS); - } else { - if (config.narrowKlassBase != 0) { - // The heap base register was destroyed above, so restore it - if (config.narrowOopBase == 0L) { - asm.xorq(heapBase, heapBase); - } else { - asm.movq(heapBase, config.narrowOopBase); - } + AMD64HotSpotMove.decodeKlassPointer(asm, register, heapBase, src, config); + if (config.narrowKlassBase != 0) { + // The heap base register was destroyed above, so restore it + if (config.narrowOopBase == 0L) { + asm.xorq(heapBase, heapBase); + } else { + asm.movq(heapBase, config.narrowOopBase); } } before = asm.cmpqAndJcc(inlineCacheKlass, register, ConditionFlag.NotEqual, null, false); @@ -305,17 +295,6 @@ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationRes asm.align(config.codeEntryAlignment); crb.recordMark(crb.compilationResult.getEntryBCI() != -1 ? HotSpotMarkId.OSR_ENTRY : HotSpotMarkId.VERIFIED_ENTRY); - - if (GeneratePIC.getValue(crb.getOptions())) { - // Check for method state - HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; - if (!frameContext.isStub) { - crb.recordInlineDataInCodeWithNote(new HotSpotSentinelConstant(LIRKind.value(AMD64Kind.QWORD), JavaKind.Long), HotSpotConstantLoadAction.MAKE_NOT_ENTRANT); - asm.movq(AMD64.rax, asm.getPlaceholder(-1)); - int before = asm.testqAndJcc(AMD64.rax, AMD64.rax, ConditionFlag.NotZero, null, false); - AMD64Call.recordDirectCall(crb, asm, getForeignCalls().lookupForeignCall(WRONG_METHOD_HANDLER), before); - } - } } /** diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java index 4d9c705bdcb8..a38eb5084405 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java @@ -118,7 +118,7 @@ protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins, HotSpotRegistersProvider registers, HotSpotReplacementsImpl replacements, OptionValues options) { return new AddressLoweringHotSpotSuitesProvider(new AMD64SuitesCreator(compilerConfiguration, plugins), config, runtime, - new AddressLoweringPhase(new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options))); + new AddressLoweringPhase(new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister()))); } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDirectStaticCallOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDirectStaticCallOp.java index 5f81a014c748..3bbb9e0ab912 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDirectStaticCallOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDirectStaticCallOp.java @@ -59,7 +59,7 @@ final class AMD64HotSpotDirectStaticCallOp extends DirectCallOp { @Override @SuppressWarnings("try") public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - try (CompilationResultBuilder.CallContext callContext = crb.openCallContext(invokeKind.isDirect())) { + try (CompilationResultBuilder.CallContext callContext = crb.openCallContext()) { crb.recordMark(invokeKind == InvokeKind.Static ? HotSpotMarkId.INVOKESTATIC : HotSpotMarkId.INVOKESPECIAL); if (config.supportsMethodHandleDeoptimizationEntry() && config.isMethodHandleCall((HotSpotResolvedJavaMethod) callTarget) && invokeKind != InvokeKind.Static) { crb.setNeedsMHDeoptHandler(); diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index 3eeec699c038..f00df5dcc0ed 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -25,27 +25,16 @@ package org.graalvm.compiler.hotspot.amd64; import static jdk.vm.ci.amd64.AMD64.rbp; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_DYNAMIC_INVOKE; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.INITIALIZE; -import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS; -import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE; import java.util.ArrayList; import java.util.List; -import jdk.vm.ci.code.RegisterArray; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; import org.graalvm.compiler.core.amd64.AMD64LIRGenerator; import org.graalvm.compiler.core.amd64.AMD64MoveFactoryBase.BackupSlotProvider; import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.debug.DebugContext; @@ -57,9 +46,7 @@ import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; -import org.graalvm.compiler.hotspot.HotSpotMarkId; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.lir.LIR; @@ -78,7 +65,6 @@ import org.graalvm.compiler.lir.amd64.AMD64Move; import org.graalvm.compiler.lir.amd64.AMD64Move.MoveFromRegOp; import org.graalvm.compiler.lir.amd64.AMD64PrefetchOp; -import org.graalvm.compiler.lir.amd64.AMD64ReadTimestampCounter; import org.graalvm.compiler.lir.amd64.AMD64ReadTimestampCounterWithProcid; import org.graalvm.compiler.lir.amd64.AMD64RestoreRegistersOp; import org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp; @@ -86,19 +72,16 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGenerationResult; -import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterArray; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.RegisterValue; import jdk.vm.ci.code.StackSlot; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaConstant; @@ -425,83 +408,6 @@ public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, return result; } - @Override - public Value emitLoadObjectAddress(Constant constant) { - HotSpotObjectConstant objectConstant = (HotSpotObjectConstant) constant; - LIRKind kind = objectConstant.isCompressed() ? getLIRKindTool().getNarrowOopKind() : getLIRKindTool().getObjectKind(); - Variable result = newVariable(kind); - append(new AMD64HotSpotLoadAddressOp(result, constant, HotSpotConstantLoadAction.RESOLVE)); - return result; - } - - @Override - public Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) { - HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant; - LIRKind kind = metaspaceConstant.isCompressed() ? getLIRKindTool().getNarrowPointerKind() : getLIRKindTool().getWordKind(); - Variable result = newVariable(kind); - append(new AMD64HotSpotLoadAddressOp(result, constant, action)); - return result; - } - - private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, Object[] notes, Constant[] constants, AllocatableValue[] constantDescriptions, LIRFrameState frameState) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(foreignCall); - append(new AMD64HotSpotConstantRetrievalOp(constants, constantDescriptions, frameState, linkage, notes)); - AllocatableValue result = linkage.getOutgoingCallingConvention().getReturn(); - return emitMove(result); - } - - private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, HotSpotConstantLoadAction action, Constant constant, AllocatableValue[] constantDescriptions, LIRFrameState frameState) { - Constant[] constants = new Constant[]{constant}; - Object[] notes = new Object[]{action}; - return emitConstantRetrieval(foreignCall, notes, constants, constantDescriptions, frameState); - } - - private Value emitConstantRetrieval(ForeignCallDescriptor foreignCall, HotSpotConstantLoadAction action, Constant constant, Value constantDescription, LIRFrameState frameState) { - AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(constantDescription)}; - return emitConstantRetrieval(foreignCall, action, constant, constantDescriptions, frameState); - } - - @Override - public Value emitObjectConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { - return emitConstantRetrieval(RESOLVE_STRING_BY_SYMBOL, RESOLVE, constant, constantDescription, frameState); - } - - @Override - public Value emitMetaspaceConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { - return emitConstantRetrieval(RESOLVE_KLASS_BY_SYMBOL, RESOLVE, constant, constantDescription, frameState); - } - - @Override - public Value emitKlassInitializationAndRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) { - return emitConstantRetrieval(INITIALIZE_KLASS_BY_SYMBOL, INITIALIZE, constant, constantDescription, frameState); - } - - @Override - public Value emitResolveMethodAndLoadCounters(Constant method, Value klassHint, Value methodDescription, LIRFrameState frameState) { - AllocatableValue[] constantDescriptions = new AllocatableValue[]{asAllocatable(klassHint), asAllocatable(methodDescription)}; - return emitConstantRetrieval(RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, LOAD_COUNTERS, method, constantDescriptions, frameState); - } - - @Override - public Value emitResolveDynamicInvoke(Constant appendix, LIRFrameState frameState) { - AllocatableValue[] constantDescriptions = new AllocatableValue[0]; - return emitConstantRetrieval(RESOLVE_DYNAMIC_INVOKE, INITIALIZE, appendix, constantDescriptions, frameState); - } - - @Override - public Value emitLoadConfigValue(HotSpotMarkId markId, LIRKind kind) { - Variable result = newVariable(kind); - append(new AMD64HotSpotLoadConfigValueOp(markId, result)); - return result; - } - - @Override - public Value emitRandomSeed() { - AMD64ReadTimestampCounter timestamp = new AMD64ReadTimestampCounter(); - append(timestamp); - return emitMove(timestamp.getLowResult()); - } - @Override public void emitTailcall(Value[] args, Value address) { append(new AMD64TailcallOp(args, address)); @@ -611,16 +517,8 @@ public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonN // metaspace pointer Variable result = newVariable(lirKindTool.getNarrowPointerKind()); AllocatableValue base = Value.ILLEGAL; - OptionValues options = getResult().getLIR().getOptions(); - if (encoding.hasBase() || GeneratePIC.getValue(options)) { - if (GeneratePIC.getValue(options)) { - Variable baseAddress = newVariable(lirKindTool.getWordKind()); - AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress); - append(move); - base = baseAddress; - } else { - base = emitLoadConstant(lirKindTool.getWordKind(), JavaConstant.forLong(encoding.getBase())); - } + if (encoding.hasBase()) { + base = emitLoadConstant(lirKindTool.getWordKind(), JavaConstant.forLong(encoding.getBase())); } append(new AMD64Move.CompressPointerOp(result, asAllocatable(pointer), base, encoding, nonNull, getLIRKindTool())); return result; @@ -642,16 +540,8 @@ public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean no LIRKind uncompressedKind = lirKindTool.getWordKind(); Variable result = newVariable(uncompressedKind); AllocatableValue base = Value.ILLEGAL; - OptionValues options = getResult().getLIR().getOptions(); - if (encoding.hasBase() || GeneratePIC.getValue(options)) { - if (GeneratePIC.getValue(options)) { - Variable baseAddress = newVariable(uncompressedKind); - AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress); - append(move); - base = baseAddress; - } else { - base = emitLoadConstant(uncompressedKind, JavaConstant.forLong(encoding.getBase())); - } + if (encoding.hasBase()) { + base = emitLoadConstant(uncompressedKind, JavaConstant.forLong(encoding.getBase())); } append(new AMD64Move.UncompressPointerOp(result, asAllocatable(pointer), base, encoding, nonNull, lirKindTool)); return result; diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java deleted file mode 100644 index ef03d0713ff9..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2015, 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 org.graalvm.compiler.hotspot.amd64; - -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; - -import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.HotSpotMarkId; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; - -import jdk.vm.ci.amd64.AMD64Kind; -import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.AllocatableValue; - -public final class AMD64HotSpotLoadConfigValueOp extends AMD64LIRInstruction { - - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotLoadConfigValueOp.class); - - @Def({OperandFlag.REG}) protected AllocatableValue result; - private final HotSpotMarkId markId; - - public AMD64HotSpotLoadConfigValueOp(HotSpotMarkId markId, AllocatableValue result) { - super(TYPE); - this.result = result; - this.markId = markId; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue(crb.getOptions())) { - AMD64Kind kind = (AMD64Kind) result.getPlatformKind(); - Register reg = asRegister(result); - AMD64Address placeholder = masm.getPlaceholder(-1); - switch (kind) { - case BYTE: - masm.movsbl(reg, placeholder); - break; - case WORD: - masm.movswl(reg, placeholder); - break; - case DWORD: - masm.movl(reg, placeholder); - break; - case QWORD: - masm.movq(reg, placeholder); - break; - default: - throw GraalError.unimplemented(); - } - } else { - throw GraalError.unimplemented(); - } - crb.recordMark(markId); - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java index e8357ab01efc..b7f62fe38d1e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java @@ -24,7 +24,6 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import org.graalvm.compiler.core.amd64.AMD64LoweringProviderMixin; @@ -37,9 +36,7 @@ import org.graalvm.compiler.hotspot.meta.DefaultHotSpotLoweringProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; import org.graalvm.compiler.hotspot.replacements.HotSpotAllocationSnippets; -import org.graalvm.compiler.hotspot.replacements.profiling.ProbabilisticProfileSnippets; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; @@ -50,7 +47,6 @@ import org.graalvm.compiler.replacements.amd64.AMD64TruffleArrayUtilsWithMaskSnippets; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; -import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.TargetDescription; @@ -61,7 +57,6 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider implements AMD64LoweringProviderMixin { private AMD64ConvertSnippets.Templates convertSnippets; - private ProbabilisticProfileSnippets.Templates profileSnippets; private AMD64X87MathSnippets.Templates mathSnippets; public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, @@ -74,10 +69,6 @@ public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAcc public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config, HotSpotAllocationSnippets.Templates allocationSnippetTemplates) { convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - if (JavaVersionUtil.JAVA_SPEC >= 11 && GeneratePIC.getValue(options)) { - // AOT only introduced in JDK 9 - profileSnippets = new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()); - } mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); providers.getReplacements().registerSnippetTemplateCache( new AMD64TruffleArrayUtilsWithMaskSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget())); @@ -91,8 +82,6 @@ public void lower(Node n, LoweringTool tool) { } if (n instanceof FloatConvertNode) { convertSnippets.lower((FloatConvertNode) n, tool); - } else if (profileSnippets != null && n instanceof ProfileNode) { - profileSnippets.lower((ProfileNode) n, tool); } else if (n instanceof UnaryMathIntrinsicNode) { lowerUnaryMath((UnaryMathIntrinsicNode) n, tool); } else { diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java index 0c4536623010..a5a251fee577 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java @@ -27,7 +27,6 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; @@ -65,9 +64,6 @@ public HotSpotLoadObjectConstantOp(AllocatableValue result, HotSpotObjectConstan @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue(crb.getOptions())) { - throw GraalError.shouldNotReachHere("Object constant load should not be happening directly"); - } boolean compressed = input.isCompressed(); if (crb.target.inlineObjects) { crb.recordInlineDataInCode(input); @@ -142,9 +138,6 @@ public HotSpotLoadMetaspaceConstantOp(AllocatableValue result, HotSpotMetaspaceC @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue(crb.getOptions())) { - throw GraalError.shouldNotReachHere("Metaspace constant load should not be happening directly"); - } boolean compressed = input.isCompressed(); if (isRegister(result)) { if (compressed) { @@ -176,21 +169,15 @@ public AllocatableValue getResult() { } } - public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) { + public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) { CompressEncoding encoding = config.getKlassEncoding(); masm.movl(register, address); if (encoding.getShift() != 0) { masm.shlq(register, encoding.getShift()); } - boolean pic = GeneratePIC.getValue(crb.getOptions()); - if (pic || encoding.hasBase()) { - if (pic) { - masm.movq(scratch, masm.getPlaceholder(-1)); - crb.recordMark(HotSpotMarkId.NARROW_KLASS_BASE_ADDRESS); - } else { - assert encoding.getBase() != 0; - masm.movq(scratch, encoding.getBase()); - } + if (encoding.hasBase()) { + assert encoding.getBase() != 0; + masm.movq(scratch, encoding.getBase()); masm.addq(register, scratch); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java index 9a7bb160b773..ff7ae518cfc8 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java @@ -26,8 +26,6 @@ import static jdk.vm.ci.amd64.AMD64.rax; import static jdk.vm.ci.amd64.AMD64.rip; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.NumUtil.isInt; import org.graalvm.compiler.asm.amd64.AMD64Address; @@ -46,8 +44,6 @@ import jdk.vm.ci.code.RegisterValue; import jdk.vm.ci.code.site.InfopointReason; import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; /** @@ -68,7 +64,7 @@ public AMD64HotSpotSafepointOp(LIRFrameState state, GraalHotSpotVMConfig config, this.state = state; this.config = config; this.thread = thread; - if (config.useThreadLocalPolling || isPollingPageFar(config) || ImmutableCode.getValue(tool.getOptions())) { + if (config.useThreadLocalPolling || isPollingPageFar(config)) { temp = tool.getLIRGeneratorTool().newVariable(LIRKind.value(tool.getLIRGeneratorTool().target().arch.getWordKind())); } else { // Don't waste a register if it's unneeded @@ -100,24 +96,7 @@ private static boolean isPollingPageFar(GraalHotSpotVMConfig config) { private static void emitGlobalPoll(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { assert !atReturn || state == null : "state is unneeded at return"; - if (ImmutableCode.getValue(crb.getOptions())) { - JavaKind hostWordKind = JavaKind.Long; - int alignment = hostWordKind.getBitCount() / Byte.SIZE; - JavaConstant pollingPageAddress = JavaConstant.forIntegerKind(hostWordKind, config.safepointPollingAddress); - // This move will be patched to load the safepoint page from a data segment - // co-located with the immutable code. - if (GeneratePIC.getValue(crb.getOptions())) { - asm.movq(scratch, asm.getPlaceholder(-1)); - } else { - asm.movq(scratch, (AMD64Address) crb.recordDataReferenceInCode(pollingPageAddress, alignment)); - } - final int pos = asm.position(); - crb.recordMark(atReturn ? HotSpotMarkId.POLL_RETURN_FAR : HotSpotMarkId.POLL_FAR); - if (state != null) { - crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); - } - asm.testl(rax, new AMD64Address(scratch)); - } else if (isPollingPageFar(config)) { + if (isPollingPageFar(config)) { asm.movq(scratch, config.safepointPollingAddress); crb.recordMark(atReturn ? HotSpotMarkId.POLL_RETURN_FAR : HotSpotMarkId.POLL_FAR); final int pos = asm.position(); diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java index bc1dbe801729..f984ac60d7de 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java @@ -60,7 +60,7 @@ final class AMD64HotspotDirectVirtualCallOp extends DirectCallOp { @Override @SuppressWarnings("try") public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - try (CompilationResultBuilder.CallContext callContext = crb.openCallContext(invokeKind.isDirect())) { + try (CompilationResultBuilder.CallContext callContext = crb.openCallContext()) { // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. crb.recordMark(invokeKind == InvokeKind.Virtual ? HotSpotMarkId.INVOKEVIRTUAL : HotSpotMarkId.INVOKEINTERFACE); diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java index dd6363cfd86b..68cb3917ce4d 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java @@ -66,7 +66,7 @@ final class AMD64IndirectCallOp extends IndirectCallOp { @Override @SuppressWarnings("try") public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - try (CompilationResultBuilder.CallContext callContext = crb.openCallContext(false)) { + try (CompilationResultBuilder.CallContext callContext = crb.openCallContext()) { crb.recordMark(HotSpotMarkId.INLINE_INVOKE); Register callReg = asRegister(targetAddress); assert !callReg.equals(METHOD); diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java deleted file mode 100644 index e746eae5abe9..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2013, 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 org.graalvm.compiler.hotspot.test; - -import jdk.vm.ci.aarch64.AArch64; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.memory.FloatingReadNode; -import org.graalvm.compiler.nodes.memory.ReadNode; -import org.graalvm.compiler.options.OptionValues; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; - -/** - * use - * - *
- * mx unittest AheadOfTimeCompilationTest @-XX:CompileCommand='print,*AheadOfTimeCompilationTest.*'
- * 
- * - * to print disassembly. - */ -public class AheadOfTimeCompilationTest extends HotSpotGraalCompilerTest { - - public static final Object STATICFINALOBJECT = new Object(); - public static final String STATICFINALSTRING = "test string"; - - public static Object getStaticFinalObject() { - return AheadOfTimeCompilationTest.STATICFINALOBJECT; - } - - @Before - public void setUp() { - Assume.assumeFalse("skipping on AArch64", getTarget().arch instanceof AArch64); - } - - @Test - public void testStaticFinalObjectAOT() { - StructuredGraph result = compile("getStaticFinalObject", true); - assertDeepEquals(1, getConstantNodes(result).count()); - Stamp constantStamp = getConstantNodes(result).first().stamp(NodeView.DEFAULT); - Assert.assertTrue(constantStamp.toString(), constantStamp instanceof KlassPointerStamp); - int expected = runtime().getVMConfig().classMirrorIsHandle ? 3 : 2; - assertDeepEquals(expected, result.getNodes().filter(ReadNode.class).count()); - } - - @Test - public void testStaticFinalObject() { - StructuredGraph result = compile("getStaticFinalObject", false); - assertDeepEquals(1, getConstantNodes(result).count()); - assertDeepEquals(JavaKind.Object, getConstantNodes(result).first().getStackKind()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); - } - - public static Class getClassObject() { - return AheadOfTimeCompilationTest.class; - } - - @Test - public void testClassObjectAOT() { - StructuredGraph result = compile("getClassObject", true); - - NodeIterable filter = getConstantNodes(result); - assertDeepEquals(1, filter.count()); - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) getMetaAccess().lookupJavaType(AheadOfTimeCompilationTest.class); - assertDeepEquals(type.klass(), filter.first().asConstant()); - int expected = runtime().getVMConfig().classMirrorIsHandle ? 2 : 1; - assertDeepEquals(expected, result.getNodes().filter(ReadNode.class).count()); - } - - @Test - public void testClassObject() { - StructuredGraph result = compile("getClassObject", false); - - NodeIterable filter = getConstantNodes(result); - assertDeepEquals(1, filter.count()); - JavaConstant c = filter.first().asJavaConstant(); - Assert.assertEquals(getSnippetReflection().asObject(Class.class, c), AheadOfTimeCompilationTest.class); - - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); - } - - public static Class getPrimitiveClassObject() { - return int.class; - } - - @Test - public void testPrimitiveClassObjectAOT() { - StructuredGraph result = compile("getPrimitiveClassObject", true); - NodeIterable filter = getConstantNodes(result); - assertDeepEquals(1, filter.count()); - Stamp constantStamp = filter.first().stamp(NodeView.DEFAULT); - Assert.assertTrue(constantStamp instanceof KlassPointerStamp); - int expected = runtime().getVMConfig().classMirrorIsHandle ? 3 : 2; - assertDeepEquals(expected, result.getNodes().filter(ReadNode.class).count()); - } - - @Test - public void testPrimitiveClassObject() { - StructuredGraph result = compile("getPrimitiveClassObject", false); - NodeIterable filter = getConstantNodes(result); - assertDeepEquals(1, filter.count()); - JavaConstant c = filter.first().asJavaConstant(); - Assert.assertEquals(getSnippetReflection().asObject(Class.class, c), Integer.TYPE); - - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); - } - - public static String getStringObject() { - return AheadOfTimeCompilationTest.STATICFINALSTRING; - } - - @Test - public void testStringObjectAOT() { - // embedded strings are fine - testStringObjectCommon(true); - } - - @Test - public void testStringObject() { - testStringObjectCommon(false); - } - - private void testStringObjectCommon(boolean compileAOT) { - StructuredGraph result = compile("getStringObject", compileAOT); - - NodeIterable filter = getConstantNodes(result); - assertDeepEquals(1, filter.count()); - JavaConstant c = filter.first().asJavaConstant(); - Assert.assertEquals(getSnippetReflection().asObject(String.class, c), "test string"); - - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); - } - - public static Boolean getBoxedBoolean() { - return Boolean.valueOf(true); - } - - @Test - public void testBoxedBooleanAOT() { - StructuredGraph result = compile("getBoxedBoolean", true); - - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(PiNode.class).count()); - assertDeepEquals(1, getConstantNodes(result).count()); - ConstantNode constant = getConstantNodes(result).first(); - assertDeepEquals(JavaKind.Object, constant.getStackKind()); - - JavaConstant c = constant.asJavaConstant(); - Assert.assertEquals(getSnippetReflection().asObject(Boolean.class, c), Boolean.TRUE); - } - - @Test - public void testBoxedBoolean() { - StructuredGraph result = compile("getBoxedBoolean", false); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(PiNode.class).count()); - assertDeepEquals(1, getConstantNodes(result).count()); - ConstantNode constant = getConstantNodes(result).first(); - assertDeepEquals(JavaKind.Object, constant.getStackKind()); - - JavaConstant c = constant.asJavaConstant(); - Assert.assertEquals(getSnippetReflection().asObject(Boolean.class, c), Boolean.TRUE); - } - - @SuppressWarnings("try") - private StructuredGraph compile(String test, boolean compileAOT) { - OptionValues options = new OptionValues(getInitialOptions(), ImmutableCode, compileAOT); - StructuredGraph graph = parseEager(test, AllowAssumptions.YES, options); - compile(graph.method(), graph); - return graph; - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java deleted file mode 100644 index 8cd7dda273df..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2017, 2019, 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 org.graalvm.compiler.hotspot.test; - -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.hotspot.meta.HotSpotAOTClassInitializationPlugin; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.junit.Assert; -import org.junit.Test; - -public class EliminateRedundantInitializationPhaseTest extends GraalCompilerTest { - @Override - protected Plugins getDefaultGraphBuilderPlugins() { - Plugins plugins = super.getDefaultGraphBuilderPlugins(); - plugins.setClassInitializationPlugin(new HotSpotAOTClassInitializationPlugin()); - return plugins; - } - - public static class X { - public static int x; - public static int y; - public static int z; - } - - public static class Y extends X { - public static int a; - public static int b; - } - - public static void assignFields() { - X.x = 1; - X.y = 2; - X.z = 3; - } - - public static void assignFieldsConditionally(boolean choice) { - X.x = 1; - if (choice) { - X.y = 2; - } else { - X.z = 3; - } - } - - public static void assignFieldsSubclassDominates() { - Y.a = 1; - X.x = 2; - X.y = 3; - X.z = 4; - } - - public static void assignFieldsConditionallySubclassDominates(boolean choice) { - Y.a = 1; - if (choice) { - X.x = 2; - } else { - X.y = 3; - } - Y.z = 4; - } - - public static void assignFieldsSubclassPostdominates() { - X.x = 1; - Y.a = 2; - } - - public static void assignFieldsConditionallySubclassPostdominates(boolean choice) { - X.x = 1; - if (choice) { - X.y = 2; - } else { - X.z = 3; - } - Y.a = 4; - } - - public static void assignFieldsConditionallyMixed(boolean choice) { - X.x = 1; - if (choice) { - Y.a = 2; - } else { - X.z = 3; - } - Y.b = 4; - } - - public static void assignFieldsInLoop() { - X.x = 1; - for (int i = 0; i < 10; i++) { - X.y += X.z; - } - } - - public static void assignFieldsInBranches(boolean choice) { - if (choice) { - X.x = 1; - } else { - X.y = 2; - } - X.z = 3; - } - - public static void assignFieldsInBranchesMixed(boolean choice) { - if (choice) { - X.x = 1; - } else { - Y.a = 2; - } - X.z = 3; - } - - static class SomeClass { - @BytecodeParserNeverInline - static void method() { - } - - @BytecodeParserForceInline - static void inlinedMethod() { - } - } - - public static void invokestatic() { - SomeClass.method(); - } - - public static void invokestaticInlined() { - SomeClass.inlinedMethod(); - } - - private void test(String name, int initNodesAfterParse, int initNodesAfterOpt) { - StructuredGraph graph = parseEager(name, AllowAssumptions.NO); - Assert.assertEquals(initNodesAfterParse, graph.getNodes().filter(InitializeKlassNode.class).count()); - HighTierContext highTierContext = getDefaultHighTierContext(); - new EliminateRedundantInitializationPhase().apply(graph, highTierContext); - Assert.assertEquals(initNodesAfterOpt, graph.getNodes().filter(InitializeKlassNode.class).count()); - } - - @Test - public void test1() { - test("assignFields", 3, 1); - } - - @Test - public void test2() { - test("assignFieldsConditionally", 3, 1); - } - - @Test - public void test3() { - test("assignFieldsSubclassDominates", 4, 1); - } - - @Test - public void test4() { - test("assignFieldsConditionallySubclassDominates", 4, 1); - } - - @Test - public void test5() { - test("assignFieldsSubclassPostdominates", 2, 2); - } - - @Test - public void test6() { - test("assignFieldsConditionallySubclassPostdominates", 4, 2); - } - - @Test - public void test7() { - test("assignFieldsConditionallyMixed", 4, 3); - } - - @Test - public void test8() { - test("assignFieldsInLoop", 4, 1); - } - - @Test - public void test9() { - test("assignFieldsInBranches", 3, 2); - } - - @Test - public void test10() { - test("assignFieldsInBranchesMixed", 3, 2); - } - - @Test - public void test11() { - test("invokestatic", 1, 0); - } - - @Test - public void test12() { - // Force initialization of SomeClass - SomeClass.inlinedMethod(); - test("invokestaticInlined", 1, 1); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest.java deleted file mode 100644 index 0ea94340a7d2..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2017, 2019, 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 org.graalvm.compiler.hotspot.test; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.security.PrivilegedAction; -import java.util.function.IntPredicate; - -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.hotspot.meta.HotSpotAOTClassInitializationPlugin; -import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicStubCall; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo; -import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase; -import org.graalvm.compiler.phases.common.GuardLoweringPhase; -import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.tiers.MidTierContext; -import org.junit.Assert; -import org.junit.Test; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class HotSpotInvokeDynamicPluginTest extends HotSpotGraalCompilerTest { - @Override - protected Plugins getDefaultGraphBuilderPlugins() { - Plugins plugins = super.getDefaultGraphBuilderPlugins(); - plugins.setClassInitializationPlugin(new HotSpotAOTClassInitializationPlugin()); - plugins.setInvokeDynamicPlugin(new HotSpotInvokeDynamicPlugin() { - @Override - public boolean isResolvedDynamicInvoke(GraphBuilderContext builder, int index, int opcode) { - // Allow invokedynamic testing with older JVMCI - ResolvedJavaMethod m = builder.getMethod(); - if (m.getName().startsWith("invokeDynamic") && m.getDeclaringClass().getName().equals("Lorg/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest;")) { - return false; - } - return super.isResolvedDynamicInvoke(builder, index, opcode); - } - - @Override - public boolean supportsDynamicInvoke(GraphBuilderContext builder, int index, int opcode) { - // Allow invokehandle testing with older JVMCI - ResolvedJavaMethod m = builder.getMethod(); - if (m.getName().startsWith("invokeHandle") && m.getDeclaringClass().getName().equals("Lorg/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest;")) { - return true; - } - return super.supportsDynamicInvoke(builder, index, opcode); - } - }); - return plugins; - } - - @Override - protected InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION; - } - - private void test(String name, int expectedResolves, int expectedStubCalls) { - StructuredGraph graph = parseEager(name, AllowAssumptions.NO, new OptionValues(getInitialOptions(), GraalOptions.GeneratePIC, true)); - MidTierContext midTierContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); - - CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); - Assert.assertEquals(expectedResolves, graph.getNodes().filter(ResolveDynamicConstantNode.class).count()); - Assert.assertEquals(0, graph.getNodes().filter(ResolveDynamicStubCall.class).count()); - CoreProviders context = getProviders(); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - new GuardLoweringPhase().apply(graph, midTierContext); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context); - new FrameStateAssignmentPhase().apply(graph); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, context); - Assert.assertEquals(0, graph.getNodes().filter(ResolveDynamicConstantNode.class).count()); - Assert.assertEquals(expectedStubCalls, graph.getNodes().filter(ResolveDynamicStubCall.class).count()); - } - - public static IntPredicate invokeDynamic1() { - IntPredicate i = (v) -> v > 1; - return i; - } - - public static PrivilegedAction invokeDynamic2(String s) { - return s::length; - } - - static final MethodHandle objToStringMH; - - static { - MethodHandle mh = null; - try { - mh = MethodHandles.lookup().findVirtual(Object.class, "toString", MethodType.methodType(String.class)); - } catch (Exception e) { - } - objToStringMH = mh; - } - - // invokehandle - public static String invokeHandle1(Object o) throws Throwable { - return (String) objToStringMH.invokeExact(o); - } - - @Test - public void test1() { - test("invokeDynamic1", 1, 1); - } - - @Test - public void test2() { - test("invokeDynamic2", 1, 1); - } - - @Test - public void test3() { - test("invokeHandle1", 1, 1); - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotLazyInitializationTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotLazyInitializationTest.java deleted file mode 100644 index b8d2db0a0a2a..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotLazyInitializationTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2018, 2019, 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 org.graalvm.compiler.hotspot.test; - -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.hotspot.meta.HotSpotAOTClassInitializationPlugin; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Test; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class HotSpotLazyInitializationTest extends GraalCompilerTest { - - HotSpotAOTClassInitializationPlugin classInitPlugin = new HotSpotAOTClassInitializationPlugin(); - - @Override - protected Plugins getDefaultGraphBuilderPlugins() { - Plugins plugins = super.getDefaultGraphBuilderPlugins(); - plugins.setClassInitializationPlugin(classInitPlugin); - return plugins; - } - - static boolean initializerRun = false; - - static class X { - static { - initializerRun = true; - } - - static void foo() { - } - } - - public static void invokeStatic() { - X.foo(); - } - - // If constant pool can do eager resolve without eager initialization, then fail if the compiler - // causes the static initializer to run. - private void test(String name) { - ResolvedJavaMethod method = getResolvedJavaMethod(name); - Assume.assumeTrue("skipping for old JVMCI", classInitPlugin.supportsLazyInitialization(method.getConstantPool())); - parseEager(method, AllowAssumptions.NO); - Assert.assertFalse(initializerRun); - } - - @Test - public void test1() { - test("invokeStatic"); - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java deleted file mode 100644 index 44508199cc70..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2015, 2019, 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 org.graalvm.compiler.hotspot.test; - -import java.util.Objects; - -import org.junit.Test; - -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.tiers.Suites; - -import jdk.vm.ci.meta.JavaKind; - -public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { - - private static class Wrapper { - private Class clazz; - - @Override - public boolean equals(Object obj) { - if (obj instanceof Wrapper) { - return Objects.equals(this.clazz, ((Wrapper) obj).clazz); - } else { - return false; - } - } - - @Override - public int hashCode() { - return clazz.hashCode(); - } - - @Override - public String toString() { - return "Wrapper-" + clazz; - } - } - - @Override - @SuppressWarnings("try") - protected Suites createSuites(OptionValues options) { - return super.createSuites(getOptions()); - } - - private static OptionValues getOptions() { - return new OptionValues(getInitialOptions(), GraalOptions.ImmutableCode, true); - } - - @Override - protected void checkLowTierGraph(StructuredGraph graph) { - for (ConstantNode constantNode : graph.getNodes().filter(ConstantNode.class)) { - assert constantNode.asJavaConstant() == null || constantNode.asJavaConstant().getJavaKind() != JavaKind.Object || - constantNode.asJavaConstant().isDefaultForKind() : "Found unexpected object constant " + - constantNode + ", this should have been removed by the LoadJavaMirrorWithKlassPhase."; - } - } - - public static Class classConstant() { - return Wrapper.class; - } - - @Test - public void testClassConstant() { - test(getOptions(), "classConstant"); - } - - public static Class primitiveClassConstant() { - return int.class; - } - - @Test - public void testPrimitiveClassConstant() { - test(getOptions(), "primitiveClassConstant"); - } - - public static Wrapper compressedClassConstant(Wrapper w) { - w.clazz = Wrapper.class; - return w; - } - - @Test - public void testCompressedClassConstant() { - ArgSupplier arg = () -> new Wrapper(); - test(getOptions(), "compressedClassConstant", arg); - } - - public static Wrapper compressedPrimitiveClassConstant(Wrapper w) { - w.clazz = int.class; - return w; - } - - @Test - public void testCompressedPrimitiveClassConstant() { - ArgSupplier arg = () -> new Wrapper(); - test(getOptions(), "compressedPrimitiveClassConstant", arg); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java deleted file mode 100644 index 796abfceeda3..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2017, 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 org.graalvm.compiler.hotspot.test; - -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.meta.HotSpotAOTClassInitializationPlugin; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; -import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; -import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.junit.Assert; -import org.junit.Test; - -public class ReplaceConstantNodesPhaseTest extends HotSpotGraalCompilerTest { - private final GraalHotSpotVMConfig config = runtime().getVMConfig(); - - @Override - protected Plugins getDefaultGraphBuilderPlugins() { - Plugins plugins = super.getDefaultGraphBuilderPlugins(); - plugins.setClassInitializationPlugin(new HotSpotAOTClassInitializationPlugin()); - return plugins; - } - - public static class X { - public static int x; - public static int y; - public static int z; - public static Object o; - } - - public static class Y extends X { - public static int a; - public static int b; - } - - public static int a; - - public static void assignFields() { - X.x = 1; - X.y = 2; - X.z = 3; - } - - public static void assignFieldsInBranches(boolean x) { - if (x) { - X.y = 1; - } else { - X.z = 2; - } - } - - public static void assignFieldsWithDominatingInit(boolean x) { - X.x = 1; - if (x) { - X.y = 2; - } else { - X.z = 3; - } - } - - public static void assignString() { - X.o = "foo"; - } - - public static void assignToParentAndChild() { - Y.a = 1; - X.x = 2; - } - - public static void assignToThis() { - a = 1; - } - - public static void assignFieldsWithDominatingInitOfParent(boolean x) { - Y.a = 1; - if (x) { - X.y = 2; - } else { - X.z = 3; - } - Y.b = 4; - } - - private void test(String name, int expectedInits, int expectedResolves, int expectedLoads) { - StructuredGraph graph = parseEager(name, AllowAssumptions.NO, new OptionValues(getInitialOptions(), GraalOptions.GeneratePIC, true)); - HighTierContext highTierContext = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); - new EliminateRedundantInitializationPhase().apply(graph, highTierContext); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); - new LoadJavaMirrorWithKlassPhase(config).apply(graph, highTierContext); - new ReplaceConstantNodesPhase(true, false).apply(graph, highTierContext); - Assert.assertEquals(expectedInits, graph.getNodes().filter(InitializeKlassNode.class).count()); - Assert.assertEquals(expectedResolves, graph.getNodes().filter(ResolveConstantNode.class).count()); - Assert.assertEquals(expectedLoads, graph.getNodes().filter(LoadConstantIndirectlyNode.class).count()); - } - - @Test - public void test1() { - test("assignFields", 1, 0, 0); - } - - @Test - public void test2() { - test("assignFieldsWithDominatingInit", 1, 0, 0); - } - - @Test - public void test3() { - test("assignString", 1, 1, 0); - } - - @Test - public void test4() { - test("assignToParentAndChild", 1, 1, 0); - } - - @Test - public void test5() { - test("assignToThis", 0, 0, 1); - } - - @Test - public void test6() { - test("assignFieldsWithDominatingInitOfParent", 1, 1, 0); - } - - @Test - public void test7() { - test("assignFieldsInBranches", 2, 1, 0); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java deleted file mode 100644 index 4e28d14939d5..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2017, 2020, 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 org.graalvm.compiler.hotspot; - -import org.graalvm.compiler.core.common.CompressEncoding; - -import jdk.vm.ci.hotspot.HotSpotVMConfigStore; - -public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig { - private final CompressEncoding aotOopEncoding; - private final CompressEncoding aotKlassEncoding; - - public AOTGraalHotSpotVMConfig(HotSpotVMConfigStore store) { - super(store); - // AOT captures VM settings during compilation. For compressed oops this - // presents a problem for the case when the VM selects a zero-shift mode - // (i.e., when the heap is less than 4G). Compiling an AOT binary with - // zero-shift limits its usability. As such we force the shift to be - // always equal to alignment to avoid emitting zero-shift AOT code. - CompressEncoding vmOopEncoding = super.getOopEncoding(); - aotOopEncoding = new CompressEncoding(vmOopEncoding.getBase(), logMinObjAlignment()); - CompressEncoding vmKlassEncoding = super.getKlassEncoding(); - aotKlassEncoding = new CompressEncoding(vmKlassEncoding.getBase(), logKlassAlignment); - assert check(); - reportErrors(); - } - - @Override - public CompressEncoding getOopEncoding() { - return aotOopEncoding; - } - - @Override - public CompressEncoding getKlassEncoding() { - return aotKlassEncoding; - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerRuntimeHotSpotVMConfig.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerRuntimeHotSpotVMConfig.java deleted file mode 100644 index ba41bf7cd9e9..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerRuntimeHotSpotVMConfig.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot; - -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import jdk.vm.ci.hotspot.HotSpotVMConfigStore; - -/** - * Used to access native configuration details for static compilation support. - */ -public class CompilerRuntimeHotSpotVMConfig extends HotSpotVMConfigAccess { - - public CompilerRuntimeHotSpotVMConfig(HotSpotVMConfigStore store) { - super(store); - } - - public final long resolveStringBySymbol = getAddress("CompilerRuntime::resolve_string_by_symbol"); - public final long resolveDynamicInvoke = getAddress("CompilerRuntime::resolve_dynamic_invoke"); - public final long resolveKlassBySymbol = getAddress("CompilerRuntime::resolve_klass_by_symbol"); - public final long resolveMethodBySymbolAndLoadCounters = getAddress("CompilerRuntime::resolve_method_by_symbol_and_load_counters"); - public final long initializeKlassBySymbol = getAddress("CompilerRuntime::initialize_klass_by_symbol"); - public final long invocationEvent = getAddress("CompilerRuntime::invocation_event"); - public final long backedgeEvent = getAddress("CompilerRuntime::backedge_event"); -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java index b7da7658fcfc..6cfa8986e687 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java @@ -410,7 +410,7 @@ static class SymbolicEncodedGraph extends EncodedGraph { private final String originalMethod; SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass[] types, String originalMethod, ResolvedJavaType... accessingClasses) { - super(encoding, startOffset, objects, types, null, null, null, false, false); + super(encoding, startOffset, objects, types, null, null, false, false); this.accessingClasses = accessingClasses; this.originalMethod = originalMethod; } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java index ad8074b5c8d0..e512ced1529f 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java @@ -53,7 +53,6 @@ import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.VMErrorNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall; import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions; import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions; @@ -62,7 +61,6 @@ import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub; import org.graalvm.compiler.hotspot.word.KlassPointer; -import org.graalvm.compiler.hotspot.word.MethodCountersPointer; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRInstruction; @@ -352,45 +350,6 @@ private static native int counterModeAESCrypt(@ConstantNodeParameter ForeignCall public static final HotSpotForeignCallDescriptor NEW_INSTANCE_OR_NULL = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, TLAB_LOCATIONS, "new_instance_or_null", Object.class, KlassPointer.class); - /** - * @see ResolveConstantStubCall - */ - public static final HotSpotForeignCallDescriptor RESOLVE_STRING_BY_SYMBOL = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, TLAB_LOCATIONS, "resolve_string_by_symbol", Object.class, - Word.class, Word.class); - - /** - * @see ResolveConstantStubCall - */ - public static final HotSpotForeignCallDescriptor RESOLVE_DYNAMIC_INVOKE = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, any(), "resolve_dynamic_invoke", Object.class, Word.class); - - /** - * @see ResolveConstantStubCall - */ - public static final HotSpotForeignCallDescriptor RESOLVE_KLASS_BY_SYMBOL = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, any(), "resolve_klass_by_symbol", Word.class, Word.class, - Word.class); - - /** - * @see ResolveConstantStubCall - */ - public static final HotSpotForeignCallDescriptor INITIALIZE_KLASS_BY_SYMBOL = new HotSpotForeignCallDescriptor(SAFEPOINT, NOT_REEXECUTABLE, any(), "initialize_klass_by_symbol", Word.class, - Word.class, - Word.class); - - /** - * @see ResolveConstantStubCall - */ - public static final HotSpotForeignCallDescriptor RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS, - "resolve_method_by_symbol_and_load_counters", Word.class, Word.class, Word.class, - Word.class); - - /** - * Tiered support. - */ - public static final HotSpotForeignCallDescriptor INVOCATION_EVENT = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS, "invocation_event", void.class, - MethodCountersPointer.class); - public static final HotSpotForeignCallDescriptor BACKEDGE_EVENT = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS, "backedge_event", void.class, MethodCountersPointer.class, - int.class, int.class); - public HotSpotBackend(HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { super(providers); this.runtime = runtime; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java index d53f318a25a9..3a9d9fdf61bf 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java @@ -118,7 +118,7 @@ public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache int totalFrameSize = compResult.getTotalFrameSize(); StackSlot customStackArea = compResult.getCustomStackArea(); - boolean isImmutablePIC = compResult.isImmutablePIC(); + boolean isImmutablePIC = false; // Legacy API from jaotc that no longer does anything if (method instanceof HotSpotResolvedJavaMethod) { HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java index ebab48d38cb5..89cd0225c089 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java @@ -26,7 +26,6 @@ import static jdk.vm.ci.common.InitTimer.timer; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigAccess.JDK; @@ -163,7 +162,7 @@ public GlobalMetrics getMetricValues() { HotSpotGraalRuntime(String nameQualifier, HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) { this.runtimeName = getClass().getSimpleName() + ":" + nameQualifier; HotSpotVMConfigStore store = jvmciRuntime.getConfigStore(); - config = GeneratePIC.getValue(initialOptions) ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store); + config = new GraalHotSpotVMConfig(store); // Only set HotSpotPrintInlining if it still has its default value (false). if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java index dd8634bfaf05..dee520a5baee 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java @@ -24,26 +24,13 @@ */ package org.graalvm.compiler.hotspot; -import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; -import org.graalvm.compiler.hotspot.nodes.profiling.RandomSeedNode; -import org.graalvm.compiler.hotspot.replacements.EncodedSymbolConstant; -import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; /** @@ -74,97 +61,6 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool { */ void emitDeoptimizeWithExceptionInCaller(Value exception); - /** - * Emits code for a {@link LoadConstantIndirectlyNode}. - * - * @param constant - * @return value of loaded address in register - */ - Value emitLoadObjectAddress(Constant constant); - - /** - * Emits code for a {@link LoadConstantIndirectlyNode}. - * - * @param constant original constant - * @param action action to perform on the metaspace object - * @return Value of loaded address in register - */ - Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action); - - /** - * Emits code for a {@link GraalHotSpotVMConfigNode}. - * - * @param markId id of the value to load - * @param kind type of the value to load - * @return value of loaded global in register - */ - Value emitLoadConfigValue(HotSpotMarkId markId, LIRKind kind); - - /** - * Emits code for a {@link ResolveConstantNode} to resolve a {@link HotSpotObjectConstant}. - * - * @param constant original constant - * @param constantDescription a description of the string that need to be materialized (and - * interned) as java.lang.String, generated with {@link EncodedSymbolConstant} - * @param frameState frame state for the runtime call - * @return the address of the requested constant. - */ - Value emitObjectConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState); - - /** - * Emits code to resolve a dynamic constant. - * - * @param constant original constant - * @param frameState frame state for the runtime call - * @return the address of the requested constant. - */ - Value emitResolveDynamicInvoke(Constant constant, LIRFrameState frameState); - - /** - * Emits code for a {@link ResolveConstantNode} to resolve a {@link HotSpotMetaspaceConstant}. - * - * @param constant original constant - * @param constantDescription a symbolic description of the {@link HotSpotMetaspaceConstant} - * generated by {@link EncodedSymbolConstant} - * @param frameState frame state for the runtime call - * @return the address of the requested constant. - */ - Value emitMetaspaceConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState); - - /** - * Emits code for a {@link ResolveMethodAndLoadCountersNode} to resolve a - * {@link HotSpotMetaspaceConstant} that represents a {@link ResolvedJavaMethod} and return the - * corresponding MethodCounters object. - * - * @param method original constant - * @param klassHint a klass in which the method is declared - * @param methodDescription is symbolic description of the constant generated by - * {@link EncodedSymbolConstant} - * @param frameState frame state for the runtime call - * @return the address of the requested constant. - */ - Value emitResolveMethodAndLoadCounters(Constant method, Value klassHint, Value methodDescription, LIRFrameState frameState); - - /** - * Emits code for a {@link ResolveConstantNode} to resolve a klass - * {@link HotSpotMetaspaceConstant} and run static initializer. - * - * - * @param constant original constant - * @param constantDescription a symbolic description of the {@link HotSpotMetaspaceConstant} - * generated by {@link EncodedSymbolConstant} - * @param frameState frame state for the runtime call - * @return the address of the requested constant. - */ - Value emitKlassInitializationAndRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState); - - /** - * Emits code for a {@link RandomSeedNode}. - * - * @return value of the counter - */ - Value emitRandomSeed(); - /** * Gets a stack slot for a lock at a given lock nesting depth. */ diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java index 0be630905b4b..0319ebf3794e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java @@ -72,6 +72,10 @@ void setValue(Integer value) { this.value = value; } + public int getValue() { + return value; + } + @Override public String getName() { return name(); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 9beeae736586..ba5b53b14bb8 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -26,7 +26,6 @@ import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs; import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END; @@ -48,7 +47,6 @@ import java.util.Map; import org.graalvm.compiler.core.common.CompressEncoding; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallSignature; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; @@ -70,11 +68,6 @@ import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.KlassBeingInitializedCheckNode; import org.graalvm.compiler.hotspot.nodes.VMErrorNode; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; @@ -99,9 +92,7 @@ import org.graalvm.compiler.hotspot.replacements.StringToBytesSnippets; import org.graalvm.compiler.hotspot.replacements.UnsafeCopyMemoryNode; import org.graalvm.compiler.hotspot.replacements.UnsafeSnippets; -import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets; import org.graalvm.compiler.hotspot.replacements.arraycopy.HotSpotArraycopySnippets; -import org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets; import org.graalvm.compiler.hotspot.stubs.ForeignCallSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -255,8 +246,6 @@ public interface Extensions { protected LogSnippets.Templates logSnippets; protected ArrayCopySnippets.Templates arraycopySnippets; protected StringToBytesSnippets.Templates stringToBytesSnippets; - protected ResolveConstantSnippets.Templates resolveConstantSnippets; - protected ProfileSnippets.Templates profileSnippets; protected ObjectSnippets.Templates objectSnippets; protected UnsafeSnippets.Templates unsafeSnippets; protected ObjectCloneSnippets.Templates objectCloneSnippets; @@ -309,7 +298,6 @@ public void initialize(OptionValues options, Iterable fact stringToBytesSnippets = new StringToBytesSnippets.Templates(options, factories, providers, target); identityHashCodeSnippets = new IdentityHashCodeSnippets.Templates(new HotSpotHashCodeSnippets(), options, factories, providers, target, HotSpotReplacementsUtil.MARK_WORD_LOCATION); isArraySnippets = new IsArraySnippets.Templates(new HotSpotIsArraySnippets(), options, factories, providers, target); - resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target); objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target); foreignCallSnippets = new ForeignCallSnippets.Templates(options, factories, providers, target); registerFinalizerSnippets = new RegisterFinalizerSnippets.Templates(options, factories, providers, target); @@ -317,10 +305,6 @@ public void initialize(OptionValues options, Iterable fact objectSnippets = new ObjectSnippets.Templates(options, factories, providers, target); } unsafeSnippets = new UnsafeSnippets.Templates(options, factories, providers, target); - if (JavaVersionUtil.JAVA_SPEC >= 11 && GeneratePIC.getValue(options)) { - // AOT only introduced in JDK 9 - profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target); - } initializeExtensions(options, factories, providers, config); } @@ -492,24 +476,6 @@ private boolean lowerWithoutDelegation(Node n, LoweringTool tool) { lowerHubGetClassNode((HubGetClassNode) n, tool); } else if (n instanceof KlassLayoutHelperNode) { lowerKlassLayoutHelperNode((KlassLayoutHelperNode) n, tool); - } else if (n instanceof ResolveDynamicConstantNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - resolveConstantSnippets.lower((ResolveDynamicConstantNode) n, tool); - } - } else if (n instanceof ResolveConstantNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - resolveConstantSnippets.lower((ResolveConstantNode) n, tool); - } - } else if (n instanceof ResolveMethodAndLoadCountersNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool); - } - } else if (n instanceof InitializeKlassNode) { - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - resolveConstantSnippets.lower((InitializeKlassNode) n, tool); - } - } else if (n instanceof ProfileNode) { - profileSnippets.lower((ProfileNode) n, tool); } else if (n instanceof KlassBeingInitializedCheckNode) { getAllocationSnippets().lower((KlassBeingInitializedCheckNode) n, tool); } else if (n instanceof FastNotifyNode) { @@ -581,7 +547,7 @@ private void lowerHubGetClassNode(HubGetClassNode n, LoweringTool tool) { ValueNode hub = n.getHub(); GraalHotSpotVMConfig vmConfig = runtime.getVMConfig(); StructuredGraph graph = n.graph(); - assert !hub.isConstant() || GraalOptions.ImmutableCode.getValue(graph.getOptions()); + assert !hub.isConstant(); AddressNode mirrorAddress = createOffsetAddress(graph, hub, vmConfig.classMirrorOffset); FloatingReadNode read = graph.unique( new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, vmConfig.classMirrorIsHandle ? StampFactory.forKind(target.wordJavaKind) : n.stamp(NodeView.DEFAULT), diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTClassInitializationPlugin.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTClassInitializationPlugin.java deleted file mode 100644 index 62fb99d5f869..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTClassInitializationPlugin.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2015, 2019, 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 org.graalvm.compiler.hotspot.meta; - -import java.util.function.Supplier; - -import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; - -import jdk.vm.ci.hotspot.HotSpotConstantPool; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; - -public final class HotSpotAOTClassInitializationPlugin implements ClassInitializationPlugin { - private static boolean shouldApply(GraphBuilderContext builder, ResolvedJavaType type) { - if (!builder.parsingIntrinsic()) { - if (!type.isArray()) { - ResolvedJavaMethod method = builder.getGraph().method(); - ResolvedJavaType methodHolder = method.getDeclaringClass(); - // We can elide initialization nodes if type >=: methodHolder. - // The type is already initialized by either "new" or "invokestatic". - - // Emit initialization node if type is an interface since: - // JLS 12.4: Before a class is initialized, its direct superclass must be - // initialized, but interfaces implemented by the class are not - // initialized and a class or interface type T will be initialized - // immediately before the first occurrence of accesses listed - // in JLS 12.4.1. - - return !type.isAssignableFrom(methodHolder) || type.isInterface(); - } else if (!type.getComponentType().isPrimitive()) { - // Always apply to object array types - return true; - } - } - return false; - } - - @Override - public boolean apply(GraphBuilderContext builder, ResolvedJavaType type, Supplier frameState, ValueNode[] classInit) { - if (shouldApply(builder, type)) { - Stamp hubStamp = builder.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull()); - ConstantNode hub = builder.append(ConstantNode.forConstant(hubStamp, ((HotSpotResolvedObjectType) type).klass(), builder.getMetaAccess(), builder.getGraph())); - DeoptimizingFixedWithNextNode result = builder.append(type.isArray() ? new ResolveConstantNode(hub) : new InitializeKlassNode(hub)); - result.setStateBefore(frameState.get()); - if (classInit != null) { - classInit[0] = result; - } - return true; - } - return false; - } - - @Override - public boolean supportsLazyInitialization(ConstantPool cp) { - return true; - } - - @Override - public void loadReferencedType(GraphBuilderContext builder, ConstantPool cp, int cpi, int opcode) { - ((HotSpotConstantPool) cp).loadReferencedType(cpi, opcode, false); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java deleted file mode 100644 index ca67f1030e3f..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.meta; - -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -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 jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class HotSpotAOTProfilingPlugin extends HotSpotProfilingPlugin { - public static class Options { - @Option(help = "Do profiling and callbacks to tiered runtime", type = OptionType.User)// - public static final OptionKey TieredAOT = new OptionKey<>(false); - @Option(help = "Invocation notification frequency", type = OptionType.Expert)// - public static final OptionKey TierAInvokeNotifyFreqLog = new OptionKey<>(13); - @Option(help = "Inlinee invocation notification frequency (-1 means count, but do not notify)", type = OptionType.Expert)// - public static final OptionKey TierAInvokeInlineeNotifyFreqLog = new OptionKey<>(-1); - @Option(help = "Invocation profile probability", type = OptionType.Expert)// - public static final OptionKey TierAInvokeProfileProbabilityLog = new OptionKey<>(8); - @Option(help = "Backedge notification frequency", type = OptionType.Expert)// - public static final OptionKey TierABackedgeNotifyFreqLog = new OptionKey<>(16); - @Option(help = "Backedge profile probability", type = OptionType.Expert)// - public static final OptionKey TierABackedgeProfileProbabilityLog = new OptionKey<>(12); - } - - @Override - public boolean shouldProfile(GraphBuilderContext builder, ResolvedJavaMethod method) { - return super.shouldProfile(builder, method) && ((HotSpotResolvedObjectType) method.getDeclaringClass()).getFingerprint() != 0; - } - - @Override - public int invokeNotifyFreqLog(OptionValues options) { - return Options.TierAInvokeNotifyFreqLog.getValue(options); - } - - @Override - public int invokeInlineeNotifyFreqLog(OptionValues options) { - return Options.TierAInvokeInlineeNotifyFreqLog.getValue(options); - } - - @Override - public int invokeProfilePobabilityLog(OptionValues options) { - return Options.TierAInvokeProfileProbabilityLog.getValue(options); - } - - @Override - public int backedgeNotifyFreqLog(OptionValues options) { - return Options.TierABackedgeNotifyFreqLog.getValue(options); - } - - @Override - public int backedgeProfilePobabilityLog(OptionValues options) { - return Options.TierABackedgeProfileProbabilityLog.getValue(options); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java index e004c7f96432..33c9e3e05153 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java @@ -24,14 +24,6 @@ */ package org.graalvm.compiler.hotspot.meta; -import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; -import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - -import java.util.ArrayList; -import java.util.List; - -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.options.OptionValues; @@ -55,54 +47,7 @@ public HotSpotGraalConstantFieldProvider(GraalHotSpotVMConfig config, MetaAccess @Override protected boolean isStaticFieldConstant(ResolvedJavaField field, OptionValues options) { - return super.isStaticFieldConstant(field, options) && (!ImmutableCode.getValue(options) || isEmbeddableField(field)); - } - - /** - * The set of fields whose values cannot be constant folded in ImmutableCode mode. This is - * volatile to support double-checked locking lazy initialization. - */ - private volatile List nonEmbeddableFields; - - protected boolean isEmbeddableField(ResolvedJavaField field) { - if (!IS_IN_NATIVE_IMAGE && (IS_BUILDING_NATIVE_IMAGE || nonEmbeddableFields == null)) { - synchronized (this) { - if (nonEmbeddableFields == null) { - List fields = new ArrayList<>(); - try { - fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE"))); - fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE"))); - - Class characterCacheClass = Character.class.getDeclaredClasses()[0]; - assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName()); - fields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache"))); - - Class byteCacheClass = Byte.class.getDeclaredClasses()[0]; - assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName()); - fields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache"))); - - Class shortCacheClass = Short.class.getDeclaredClasses()[0]; - assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName()); - fields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache"))); - - Class integerCacheClass = Integer.class.getDeclaredClasses()[0]; - assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName()); - fields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache"))); - - Class longCacheClass = Long.class.getDeclaredClasses()[0]; - assert "java.lang.Long$LongCache".equals(longCacheClass.getName()); - fields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache"))); - - fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK"))); - fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL"))); - } catch (SecurityException | NoSuchFieldException e) { - throw new GraalError(e); - } - nonEmbeddableFields = fields; - } - } - } - return !nonEmbeddableFields.contains(field); + return super.isStaticFieldConstant(field, options); } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 9e77ca3fc861..26c8549899ee 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -25,14 +25,12 @@ package org.graalvm.compiler.hotspot.meta; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigAccess.JDK; import static org.graalvm.compiler.hotspot.HotSpotBackend.BASE64_ENCODE_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.CRC_TABLE_LOCATION; import static org.graalvm.compiler.hotspot.HotSpotBackend.GHASH_PROCESS_BLOCKS; import static org.graalvm.compiler.hotspot.HotSpotBackend.UPDATE_BYTES_CRC32; import static org.graalvm.compiler.hotspot.HotSpotBackend.UPDATE_BYTES_CRC32C; -import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_OOP_HANDLE_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION; import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; @@ -60,9 +58,7 @@ import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.HotSpotMarkId; import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode; -import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.hotspot.nodes.HotSpotLoadReservedReferenceNode; import org.graalvm.compiler.hotspot.nodes.HotSpotStoreReservedReferenceNode; import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; @@ -189,36 +185,25 @@ public static Plugins create(HotSpotGraalRuntimeProvider graalRuntime, plugins.appendTypePlugin(nodePlugin); plugins.appendNodePlugin(nodePlugin); } - if (!GeneratePIC.getValue(options)) { - plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), !config.supportsMethodHandleDeoptimizationEntry())); - } + plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), !config.supportsMethodHandleDeoptimizationEntry())); plugins.appendInlineInvokePlugin(replacements); if (InlineDuringParsing.getValue(options)) { plugins.appendInlineInvokePlugin(new InlineDuringParsingPlugin()); } - if (GeneratePIC.getValue(options)) { - plugins.setClassInitializationPlugin(new HotSpotAOTClassInitializationPlugin()); - if (TieredAOT.getValue(options)) { - plugins.setProfilingPlugin(new HotSpotAOTProfilingPlugin()); - } - } else { - if (config.instanceKlassInitThreadOffset != -1) { - plugins.setClassInitializationPlugin(new HotSpotJITClassInitializationPlugin()); - } + if (config.instanceKlassInitThreadOffset != -1) { + plugins.setClassInitializationPlugin(new HotSpotJITClassInitializationPlugin()); } invocationPlugins.defer(new Runnable() { @Override public void run() { - registerObjectPlugins(invocationPlugins, options, config, replacements); + registerObjectPlugins(invocationPlugins, config, replacements); registerClassPlugins(plugins, config, replacements); registerSystemPlugins(invocationPlugins); registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config, replacements); - if (!GeneratePIC.getValue(options)) { - registerCallSitePlugins(invocationPlugins); - } + registerCallSitePlugins(invocationPlugins); registerReflectionPlugins(invocationPlugins, replacements); registerAESPlugins(invocationPlugins, config, replacements); registerCRC32Plugins(invocationPlugins, config, replacements); @@ -287,29 +272,21 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } - private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, GraalHotSpotVMConfig config, Replacements replacements) { + private static void registerObjectPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { Registration r = new Registration(plugins, Object.class, replacements); - if (!GeneratePIC.getValue(options)) { - // FIXME: clone() requires speculation and requires a fix in here (to check that - // b.getAssumptions() != null), and in ReplacementImpl.getSubstitution() where there is - // an instantiation of IntrinsicGraphBuilder using a constructor that sets - // AllowAssumptions to YES automatically. The former has to inherit the assumptions - // settings from the root compile instead. So, for now, I'm disabling it for - // GeneratePIC. - r.register1("clone", Receiver.class, new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - ValueNode object = receiver.get(); - b.addPush(JavaKind.Object, new ObjectCloneNode(MacroParams.of(b, targetMethod, object))); - return true; - } + r.register1("clone", Receiver.class, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + ValueNode object = receiver.get(); + b.addPush(JavaKind.Object, new ObjectCloneNode(MacroParams.of(b, targetMethod, object))); + return true; + } - @Override - public boolean inlineOnly() { - return true; - } - }); - } + @Override + public boolean inlineOnly() { + return true; + } + }); r.register1("hashCode", Receiver.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { @@ -995,7 +972,7 @@ private static void registerCRC32Plugins(InvocationPlugins plugins, GraalHotSpot r.register2("update", int.class, int.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode crc, ValueNode arg) { - final ValueNode crcTableRawAddress = b.add(new GraalHotSpotVMConfigNode(config, HotSpotMarkId.CRC_TABLE_ADDRESS, JavaKind.Long)); + final ValueNode crcTableRawAddress = ConstantNode.forLong(config.crcTableAddress); ValueNode c = new XorNode(crc, ConstantNode.forInt(-1)); ValueNode index = new AndNode(new XorNode(arg, c), ConstantNode.forInt(0xff)); ValueNode offset = new LeftShiftNode(index, ConstantNode.forInt(2)); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 721104ea0a12..36243ca2a141 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -25,10 +25,8 @@ package org.graalvm.compiler.hotspot.meta; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM; -import static org.graalvm.compiler.hotspot.HotSpotBackend.BACKEDGE_EVENT; import static org.graalvm.compiler.hotspot.HotSpotBackend.BASE64_ENCODE_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.COUNTERMODE_IMPL_CRYPT; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT; @@ -40,8 +38,6 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; import static org.graalvm.compiler.hotspot.HotSpotBackend.GHASH_PROCESS_BLOCKS; import static org.graalvm.compiler.hotspot.HotSpotBackend.IC_MISS_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INVOCATION_EVENT; import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_MULTIPLY; import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_SQUARE; import static org.graalvm.compiler.hotspot.HotSpotBackend.MULTIPLY_TO_LEN; @@ -52,10 +48,6 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE_OR_NULL; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY_OR_NULL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_DYNAMIC_INVOKE; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS_MB; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS; @@ -66,7 +58,6 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER; import static org.graalvm.compiler.hotspot.HotSpotBackend.VECTORIZED_MISMATCH; import static org.graalvm.compiler.hotspot.HotSpotBackend.VM_ERROR; -import static org.graalvm.compiler.hotspot.HotSpotBackend.WRONG_METHOD_HANDLER; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.COMPUTES_REGISTERS_KILLED; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_ALL_CALLER_SAVE_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP; @@ -111,7 +102,6 @@ import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.ArrayIndexOfStub; -import org.graalvm.compiler.hotspot.CompilerRuntimeHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.replacements.arraycopy.CheckcastArrayCopyCallNode; @@ -516,18 +506,6 @@ public void initialize(HotSpotProviders providers, OptionValues options) { linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD); linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD); - if (GeneratePIC.getValue(options)) { - registerForeignCall(WRONG_METHOD_HANDLER, c.handleWrongMethodStub, NativeCall); - CompilerRuntimeHotSpotVMConfig cr = new CompilerRuntimeHotSpotVMConfig(HotSpotJVMCIRuntime.runtime().getConfigStore()); - linkForeignCall(options, providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD); - linkForeignCall(options, providers, RESOLVE_DYNAMIC_INVOKE, cr.resolveDynamicInvoke, PREPEND_THREAD); - linkForeignCall(options, providers, RESOLVE_KLASS_BY_SYMBOL, cr.resolveKlassBySymbol, PREPEND_THREAD); - linkForeignCall(options, providers, RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, cr.resolveMethodBySymbolAndLoadCounters, PREPEND_THREAD); - linkForeignCall(options, providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD); - linkForeignCall(options, providers, INVOCATION_EVENT, cr.invocationEvent, PREPEND_THREAD); - linkForeignCall(options, providers, BACKEDGE_EVENT, cr.backedgeEvent, PREPEND_THREAD); - } - linkForeignCall(options, providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD); registerArrayCopy(JavaKind.Byte, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java index 54175cfb416c..ea5c6c4cf0cf 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java @@ -31,23 +31,17 @@ import java.util.List; import java.util.function.Predicate; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.replacements.nodes.MacroInvokable; -import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -89,31 +83,9 @@ public void checkNewNodes(GraphBuilderContext b, InvocationPlugin plugin, NodeIt assert plugin.inlineOnly() : String.format("plugin that creates a %s (%s) must return true for inlineOnly(): %s", MacroInvokable.class.getSimpleName(), node, plugin); } } - if (GraalOptions.ImmutableCode.getValue(b.getOptions())) { - for (Node node : newNodes) { - if (node.hasUsages() && node instanceof ConstantNode) { - ConstantNode c = (ConstantNode) node; - if (c.getStackKind() == JavaKind.Object && AheadOfTimeVerificationPhase.isIllegalObjectConstant(c)) { - if (isClass(c)) { - // This will be handled later by LoadJavaMirrorWithKlassPhase - } else { - // Tolerate uses in unused FrameStates - if (node.usages().filter((n) -> !(n instanceof FrameState) || n.hasUsages()).isNotEmpty()) { - throw new AssertionError("illegal constant node in AOT: " + node); - } - } - } - } - } - } super.checkNewNodes(b, plugin, newNodes); } - private static boolean isClass(ConstantNode node) { - ResolvedJavaType type = StampTool.typeOrNull(node); - return type != null && "Ljava/lang/Class;".equals(type.getName()); - } - @Override public void registerIntrinsificationPredicate(Predicate predicate) { intrinsificationPredicates.add(predicate); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvokeDynamicPlugin.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvokeDynamicPlugin.java deleted file mode 100644 index 12d85d3bc6d5..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvokeDynamicPlugin.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2017, 2018, 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 org.graalvm.compiler.hotspot.meta; - -import org.graalvm.compiler.bytecode.Bytecodes; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicConstantNode; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; - -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -public class HotSpotInvokeDynamicPlugin implements InvokeDynamicPlugin { - - private static final Class hscp; - private static final MethodHandle isResolvedDynamicInvokeMH; - - static { - MethodHandle m = null; - Class c = null; - try { - c = Class.forName("jdk.vm.ci.hotspot.HotSpotConstantPool").asSubclass(ConstantPool.class); - m = MethodHandles.lookup().findVirtual(c, "isResolvedDynamicInvoke", MethodType.methodType(boolean.class, int.class, int.class)); - } catch (Exception e) { - } - isResolvedDynamicInvokeMH = m; - hscp = c; - } - - private static boolean isResolvedDynamicInvoke(ConstantPool constantPool, int index, int opcode) { - if (isResolvedDynamicInvokeMH != null) { - if (!hscp.isInstance(constantPool)) { - return false; - } - try { - return (boolean) isResolvedDynamicInvokeMH.invoke(constantPool, index, opcode); - } catch (Throwable t) { - throw GraalError.shouldNotReachHere(t); - } - } - throw GraalError.shouldNotReachHere("isResolvedDynamicInvokeMH not set"); - } - - private final DynamicTypeStore dynoStore; - private final boolean treatAppendixAsConstant; - - public HotSpotInvokeDynamicPlugin(DynamicTypeStore dynoStore, boolean treatAppendixAsConstant) { - this.dynoStore = dynoStore; - this.treatAppendixAsConstant = treatAppendixAsConstant; - } - - public HotSpotInvokeDynamicPlugin(DynamicTypeStore dynoStore) { - this(dynoStore, true); - } - - public HotSpotInvokeDynamicPlugin() { - this(null); - } - - // invokehandle support - @Override - public boolean isResolvedDynamicInvoke(GraphBuilderContext builder, int index, int opcode) { - ConstantPool constantPool = builder.getCode().getConstantPool(); - if (isResolvedDynamicInvokeMH == null) { - // If older JVMCI, but HotSpotInvokeDynamicPlugin is being - // used for testing, return true so that we continue along the - // plugin path. - return true; - } - return isResolvedDynamicInvoke(constantPool, index, opcode); - } - - @Override - public boolean supportsDynamicInvoke(GraphBuilderContext builder, int index, int opcode) { - return opcode == Bytecodes.INVOKEDYNAMIC || isResolvedDynamicInvokeMH != null; - } - - public DynamicTypeStore getDynamicTypeStore() { - return dynoStore; - } - - @Override - public void recordDynamicMethod(GraphBuilderContext builder, int index, int opcode, ResolvedJavaMethod target) { - assert supportsDynamicInvoke(builder, index, opcode); - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) builder.getMethod(); - HotSpotResolvedObjectType methodHolder = method.getDeclaringClass(); - - HotSpotResolvedJavaMethod adapter = (HotSpotResolvedJavaMethod) target; - if (dynoStore != null) { - dynoStore.recordAdapter(opcode, methodHolder, index, adapter); - } - } - - @Override - public ValueNode genAppendixNode(GraphBuilderContext builder, int index, int opcode, JavaConstant appendixConstant, FrameState frameState) { - JavaConstant appendix = appendixConstant; - assert supportsDynamicInvoke(builder, index, opcode); - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) builder.getMethod(); - HotSpotResolvedObjectType methodHolder = method.getDeclaringClass(); - - if (dynoStore != null) { - appendix = dynoStore.recordAppendix(opcode, methodHolder, index, appendix); - } - - ConstantNode appendixNode = ConstantNode.forConstant(appendix, builder.getMetaAccess(), builder.getGraph()); - - Stamp appendixStamp = appendixNode.stamp(NodeView.DEFAULT); - Stamp resolveStamp = treatAppendixAsConstant ? appendixStamp : appendixStamp.unrestricted(); - ResolveDynamicConstantNode resolveNode = new ResolveDynamicConstantNode(resolveStamp, appendixNode); - ResolveDynamicConstantNode added = builder.append(resolveNode); - assert added == resolveNode; - added.setStateBefore(frameState); - return resolveNode; - } - - public interface DynamicTypeStore { - - void recordAdapter(int opcode, HotSpotResolvedObjectType holder, int cpi, HotSpotResolvedJavaMethod adapter); - - JavaConstant recordAppendix(int opcode, HotSpotResolvedObjectType holder, int cpi, JavaConstant appendix); - - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java index 51338b6e8f44..11a1c06138ae 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java @@ -24,8 +24,6 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ValueNode; @@ -93,12 +91,10 @@ public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, Va @Override public boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { - if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { - if (object.isConstant()) { - JavaConstant asJavaConstant = object.asJavaConstant(); - if (tryReadField(b, field, asJavaConstant)) { - return true; - } + if (object.isConstant()) { + JavaConstant asJavaConstant = object.asJavaConstant(); + if (tryReadField(b, field, asJavaConstant)) { + return true; } } if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadField(b, object, field)) { @@ -109,10 +105,8 @@ public boolean handleLoadField(GraphBuilderContext b, ValueNode object, Resolved @Override public boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { - if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { - if (tryReadField(b, field, null)) { - return true; - } + if (tryReadField(b, field, null)) { + return true; } if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadStaticField(b, field)) { return true; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java deleted file mode 100644 index 221cef20885d..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2015, 2018, 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 org.graalvm.compiler.hotspot.meta; - -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileBranchNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileInvokeNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.LogicNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.ConditionalNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin; -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 jdk.vm.ci.meta.ResolvedJavaMethod; - -public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { - public static class Options { - @Option(help = "Emit profiling of invokes", type = OptionType.Expert)// - public static final OptionKey ProfileInvokes = new OptionKey<>(true); - @Option(help = "Emit profiling of backedges", type = OptionType.Expert)// - public static final OptionKey ProfileBackedges = new OptionKey<>(true); - } - - public abstract int invokeNotifyFreqLog(OptionValues options); - - public abstract int invokeInlineeNotifyFreqLog(OptionValues options); - - public abstract int invokeProfilePobabilityLog(OptionValues options); - - public abstract int backedgeNotifyFreqLog(OptionValues options); - - public abstract int backedgeProfilePobabilityLog(OptionValues options); - - @Override - public boolean shouldProfile(GraphBuilderContext builder, ResolvedJavaMethod method) { - return !builder.parsingIntrinsic(); - } - - @Override - public void profileInvoke(GraphBuilderContext builder, ResolvedJavaMethod method, FrameState frameState) { - assert shouldProfile(builder, method); - OptionValues options = builder.getOptions(); - if (Options.ProfileInvokes.getValue(options) && !method.isClassInitializer()) { - ProfileNode p = builder.append(new ProfileInvokeNode(method, invokeNotifyFreqLog(options), invokeProfilePobabilityLog(options))); - p.setStateBefore(frameState); - } - } - - @Override - public void profileGoto(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, int targetBci, FrameState frameState) { - assert shouldProfile(builder, method); - OptionValues options = builder.getOptions(); - if (Options.ProfileBackedges.getValue(options) && targetBci <= bci) { - ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), bci, targetBci)); - p.setStateBefore(frameState); - } - } - - @Override - public void profileIf(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, LogicNode condition, int trueBranchBci, int falseBranchBci, FrameState frameState) { - assert shouldProfile(builder, method); - OptionValues options = builder.getOptions(); - if (Options.ProfileBackedges.getValue(options) && (falseBranchBci <= bci || trueBranchBci <= bci)) { - boolean negate = false; - int targetBci = trueBranchBci; - if (falseBranchBci <= bci) { - assert trueBranchBci > bci; - negate = true; - targetBci = falseBranchBci; - } else { - assert trueBranchBci <= bci && falseBranchBci > bci; - } - ValueNode trueValue = builder.append(ConstantNode.forBoolean(!negate)); - ValueNode falseValue = builder.append(ConstantNode.forBoolean(negate)); - ConditionalNode branchCondition = builder.append(new ConditionalNode(condition, trueValue, falseValue)); - ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), branchCondition, bci, targetBci)); - p.setStateBefore(frameState); - } - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java index 2e362cc97d8c..b4a2de09526f 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java @@ -24,13 +24,6 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.core.common.GraalOptions.VerifyPhases; -import static org.graalvm.compiler.core.phases.HighTier.Options.Inline; - -import java.util.ListIterator; - import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; @@ -38,12 +31,6 @@ import org.graalvm.compiler.hotspot.HotSpotInstructionProfiling; import org.graalvm.compiler.hotspot.lir.HotSpotZapRegistersPhase; import org.graalvm.compiler.hotspot.lir.VerifyMaxRegisterSizePhase; -import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase; -import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; -import org.graalvm.compiler.hotspot.phases.aot.AOTInliningPolicy; -import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; -import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase; -import org.graalvm.compiler.hotspot.phases.profiling.FinalizeProfileNodesPhase; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.java.SuitesProviderBase; import org.graalvm.compiler.lir.phases.LIRSuites; @@ -56,12 +43,7 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.compiler.phases.tiers.LowTierContext; -import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.SuitesCreator; @@ -84,42 +66,7 @@ public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMC @Override public Suites createSuites(OptionValues options) { - Suites ret = defaultSuitesCreator.createSuites(options); - - if (ImmutableCode.getValue(options)) { - ListIterator> midTierLowering = ret.getMidTier().findPhase(LoweringPhase.class); - - // lowering introduces class constants, therefore it must be after lowering - midTierLowering.add(new LoadJavaMirrorWithKlassPhase(config)); - - if (VerifyPhases.getValue(options)) { - midTierLowering.add(new AheadOfTimeVerificationPhase()); - } - - if (GeneratePIC.getValue(options)) { - ListIterator> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); - highTierLowering.previous(); - highTierLowering.add(new EliminateRedundantInitializationPhase()); - if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) { - highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options))); - } - midTierLowering.add(new ReplaceConstantNodesPhase(true)); - - // Replace possible constants after GC barrier expansion. - ListIterator> lowTierLowering = ret.getLowTier().findPhase(LoweringPhase.class); - lowTierLowering.add(new ReplaceConstantNodesPhase(false)); - - // Replace inlining policy - if (Inline.getValue(options)) { - ListIterator> iter = ret.getHighTier().findPhase(InliningPhase.class); - InliningPhase inlining = (InliningPhase) iter.previous(); - CanonicalizerPhase canonicalizer = inlining.getCanonicalizer(); - iter.set(new InliningPhase(new AOTInliningPolicy(null), canonicalizer)); - } - } - } - - return ret; + return defaultSuitesCreator.createSuites(options); } protected PhaseSuite createGraphBuilderSuite() { @@ -144,7 +91,7 @@ protected void run(StructuredGraph graph, HighTierContext context) { StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), graph.getDebug(), AllowAssumptions.YES).method(graph.method()).trackNodeSourcePosition( graph.trackNodeSourcePosition()).build(); - SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context, !ImmutableCode.getValue(graph.getOptions())); + SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context, true); graphDecoder.decode(encodedGraph); } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java deleted file mode 100644 index 2ea6f9b7dd1f..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2015, 2020, 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 org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.AOTVerifyOops; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; - -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.HotSpotMarkId; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; - -/** - * Represents {@link GraalHotSpotVMConfig} values that may change after compilation. - */ -@NodeInfo(cycles = CYCLES_1, size = SIZE_1) -@NodeIntrinsicFactory -public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerable, Canonicalizable { - public static final NodeClass TYPE = NodeClass.create(GraalHotSpotVMConfigNode.class); - - private final GraalHotSpotVMConfig config; - protected final HotSpotMarkId markId; - - /** - * Constructor for node intrinsics below. - * - * @param config - * @param markId id of the config value - */ - public GraalHotSpotVMConfigNode(@InjectedNodeParameter Stamp stamp, @InjectedNodeParameter GraalHotSpotVMConfig config, HotSpotMarkId markId) { - super(TYPE, stamp); - this.config = config; - this.markId = markId; - assert markId != null; - } - - /** - * Constructor with explicit type specification. - * - * @param config - * @param markId id of the config value - * @param kind explicit type of the node - */ - public GraalHotSpotVMConfigNode(GraalHotSpotVMConfig config, HotSpotMarkId markId, JavaKind kind) { - super(TYPE, StampFactory.forKind(kind)); - this.config = config; - this.markId = markId; - assert markId != null; - } - - @Override - public void generate(NodeLIRBuilderTool generator) { - Value res = ((HotSpotLIRGenerator) generator.getLIRGeneratorTool()).emitLoadConfigValue(markId, generator.getLIRGeneratorTool().getLIRKind(stamp)); - generator.setResult(this, res); - } - - @NodeIntrinsic - private static native long loadLongConfigValue(@ConstantNodeParameter HotSpotMarkId markId); - - @NodeIntrinsic - private static native int loadIntConfigValue(@ConstantNodeParameter HotSpotMarkId markId); - - @NodeIntrinsic - private static native boolean loadBoolConfigValue(@ConstantNodeParameter HotSpotMarkId markId); - - public static long cardTableAddress() { - return loadLongConfigValue(HotSpotMarkId.CARD_TABLE_ADDRESS); - } - - public static long crcTableAddress() { - return loadLongConfigValue(HotSpotMarkId.CRC_TABLE_ADDRESS); - } - - public static int logOfHeapRegionGrainBytes() { - return loadIntConfigValue(HotSpotMarkId.LOG_OF_HEAP_REGION_GRAIN_BYTES); - } - - public static boolean verifyOops() { - return loadBoolConfigValue(HotSpotMarkId.VERIFY_OOPS); - } - - public static long verifyOopBits() { - return loadLongConfigValue(HotSpotMarkId.VERIFY_OOP_BITS); - } - - public static long verifyOopMask() { - return loadLongConfigValue(HotSpotMarkId.VERIFY_OOP_MASK); - } - - public static long verifyOopCounterAddress() { - return loadLongConfigValue(HotSpotMarkId.VERIFY_OOP_COUNT_ADDRESS); - } - - public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter GraalHotSpotVMConfig config, HotSpotMarkId mark) { - if (b.getReplacements().isEncodingSnippets()) { - // This plugin must be deferred so that these constants aren't embedded in libgraal - return false; - } - b.addPush(returnStamp.getStackKind(), new GraalHotSpotVMConfigNode(returnStamp, config, mark)); - return true; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - boolean generatePIC = GeneratePIC.getValue(tool.getOptions()); - boolean aotVerifyOops = AOTVerifyOops.getValue(tool.getOptions()); - if (!generatePIC || !markId.isAvailable()) { - if (markId == HotSpotMarkId.CARD_TABLE_ADDRESS) { - return ConstantNode.forLong(config.cardtableStartAddress); - } else if (markId == HotSpotMarkId.CRC_TABLE_ADDRESS) { - return ConstantNode.forLong(config.crcTableAddress); - } else if (markId == HotSpotMarkId.LOG_OF_HEAP_REGION_GRAIN_BYTES) { - return ConstantNode.forInt(config.logOfHRGrainBytes); - } else if (markId == HotSpotMarkId.VERIFY_OOPS) { - return ConstantNode.forBoolean(config.verifyOops); - } else if (markId == HotSpotMarkId.VERIFY_OOP_BITS) { - return ConstantNode.forLong(config.verifyOopBits); - } else if (markId == HotSpotMarkId.VERIFY_OOP_MASK) { - return ConstantNode.forLong(config.verifyOopMask); - } else if (markId == HotSpotMarkId.VERIFY_OOP_COUNT_ADDRESS) { - return ConstantNode.forLong(config.verifyOopCounterAddress); - } else { - throw GraalError.shouldNotReachHere(markId.toString()); - } - } else if (generatePIC && !aotVerifyOops) { - if (markId == HotSpotMarkId.VERIFY_OOPS) { - return ConstantNode.forBoolean(false); - } else if (markId == HotSpotMarkId.VERIFY_OOP_BITS) { - return ConstantNode.forLong(0L); - } else if (markId == HotSpotMarkId.VERIFY_OOP_MASK) { - return ConstantNode.forLong(0L); - } else if (markId == HotSpotMarkId.VERIFY_OOP_COUNT_ADDRESS) { - return ConstantNode.forLong(0L); - } - } - return this; - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java deleted file mode 100644 index 08d7d4b3d5eb..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2012, 2018, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; - -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.replacements.EncodedSymbolConstant; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Constant; - -@NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) -public final class EncodedSymbolNode extends FloatingNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(EncodedSymbolNode.class); - - @OptionalInput protected ValueNode value; - - public EncodedSymbolNode(@InjectedNodeParameter Stamp stamp, ValueNode value) { - super(TYPE, stamp); - assert value != null; - this.value = value; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - if (value != null) { - Constant constant = GraphUtil.foldIfConstantAndRemove(this, value); - if (constant != null) { - return new ConstantNode(new EncodedSymbolConstant(constant), StampFactory.pointer()); - } - } - return this; - } - - @NodeIntrinsic - public static native Word encode(Object constant); -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java deleted file mode 100644 index 53fddb8ae0c5..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2016, 2020, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.InputType.Memory; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; - -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.compiler.nodes.spi.Lowerable; -import org.graalvm.word.LocationIdentity; - -@NodeInfo(cycles = CYCLES_4, size = SIZE_16, allowedUsageTypes = {Memory}) -public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implements Lowerable, SingleMemoryKill { - public static final NodeClass TYPE = NodeClass.create(InitializeKlassNode.class); - - @Input ValueNode value; - - public InitializeKlassNode(ValueNode value) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - } - - public ValueNode value() { - return value; - } - - @Override - public boolean canDeoptimize() { - return true; - } - - @Override - public LocationIdentity getKilledLocationIdentity() { - return LocationIdentity.any(); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java deleted file mode 100644 index 82611d3b6a53..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2016, 2020, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; - -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.word.KlassPointer; -import org.graalvm.compiler.lir.LIRFrameState; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.DeoptimizingNode; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.word.Word; -import org.graalvm.word.LocationIdentity; - -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.Value; - -/** - * A call to the VM via a regular stub. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_16) -public class InitializeKlassStubCall extends AbstractMemoryCheckpoint implements LIRLowerable, Canonicalizable, DeoptimizingNode.DeoptBefore, SingleMemoryKill { - public static final NodeClass TYPE = NodeClass.create(InitializeKlassStubCall.class); - - @OptionalInput protected ValueNode value; - @Input protected ValueNode string; - @OptionalInput(InputType.State) protected FrameState stateBefore; - protected Constant constant; - - protected InitializeKlassStubCall(ValueNode value, ValueNode string) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - this.string = string; - } - - @NodeIntrinsic - public static native KlassPointer initializeKlass(KlassPointer value, Word string); - - @Override - public Node canonical(CanonicalizerTool tool) { - if (value != null) { - constant = GraphUtil.foldIfConstantAndRemove(this, value); - } - return this; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - assert constant != null : "Expected the value to fold: " + value; - Value stringValue = gen.operand(string); - LIRFrameState fs = gen.state(this); - assert fs != null : "Frame state should be set"; - assert constant instanceof HotSpotMetaspaceConstant; - Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitKlassInitializationAndRetrieval(constant, stringValue, fs); - gen.setResult(this, result); - } - - @Override - public boolean canDeoptimize() { - return true; - } - - @Override - public LocationIdentity getKilledLocationIdentity() { - return LocationIdentity.any(); - } - - @Override - public FrameState stateBefore() { - return stateBefore; - } - - @Override - public void setStateBefore(FrameState f) { - updateUsages(stateBefore, f); - stateBefore = f; - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java deleted file mode 100644 index 494bccae4caa..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; - -import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; -import org.graalvm.compiler.hotspot.word.KlassPointer; -import org.graalvm.compiler.hotspot.word.MethodPointer; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.nodes.util.GraphUtil; - -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.Value; - -@NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public class LoadConstantIndirectlyFixedNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LoadConstantIndirectlyFixedNode.class); - - @OptionalInput protected ValueNode value; - protected Constant constant; - protected HotSpotConstantLoadAction action; - - public LoadConstantIndirectlyFixedNode(ValueNode value) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - this.constant = null; - this.action = HotSpotConstantLoadAction.RESOLVE; - } - - public LoadConstantIndirectlyFixedNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - this.constant = null; - this.action = action; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - if (value != null) { - constant = GraphUtil.foldIfConstantAndRemove(this, value); - } - return this; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - assert constant != null : "Expected the value to fold: " + value; - Value result; - if (constant instanceof HotSpotObjectConstant) { - result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadObjectAddress(constant); - } else if (constant instanceof HotSpotMetaspaceConstant) { - result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadMetaspaceAddress(constant, action); - } else { - throw new PermanentBailoutException("Unsupported constant type: " + constant); - } - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native KlassPointer loadKlass(KlassPointer klassPointer, @ConstantNodeParameter HotSpotConstantLoadAction action); - - @NodeIntrinsic - public static native KlassPointer loadKlass(KlassPointer klassPointer); - - @NodeIntrinsic - public static native MethodPointer loadMethod(MethodPointer klassPointer); - - @NodeIntrinsic - public static native Object loadObject(Object object); - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java deleted file mode 100644 index 44421747b93d..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; - -import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; -import org.graalvm.compiler.hotspot.word.KlassPointer; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.nodes.util.GraphUtil; - -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.Value; - -@NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public class LoadConstantIndirectlyNode extends FloatingNode implements Canonicalizable, LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LoadConstantIndirectlyNode.class); - - @OptionalInput protected ValueNode value; - protected Constant constant; - protected HotSpotConstantLoadAction action; - - public LoadConstantIndirectlyNode(ValueNode value) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - this.constant = null; - this.action = HotSpotConstantLoadAction.RESOLVE; - } - - public LoadConstantIndirectlyNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - this.constant = null; - this.action = action; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - if (value != null) { - constant = GraphUtil.foldIfConstantAndRemove(this, value); - } - return this; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - assert constant != null : "Expected the value to fold: " + value; - Value result; - if (constant instanceof HotSpotObjectConstant) { - result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadObjectAddress(constant); - } else if (constant instanceof HotSpotMetaspaceConstant) { - result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadMetaspaceAddress(constant, action); - } else { - throw new PermanentBailoutException("Unsupported constant type: " + constant); - } - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native KlassPointer loadKlass(KlassPointer klassPointer, @ConstantNodeParameter HotSpotConstantLoadAction action); - - @NodeIntrinsic - public static native KlassPointer loadKlass(KlassPointer klassPointer); - - @NodeIntrinsic - public static native Object loadObject(Object object); - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java deleted file mode 100644 index 9e3dec055fb8..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; - -import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; -import org.graalvm.compiler.hotspot.nodes.type.MethodCountersPointerStamp; -import org.graalvm.compiler.hotspot.word.MethodCountersPointer; -import org.graalvm.compiler.hotspot.word.MethodPointer; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.nodes.util.GraphUtil; - -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.Value; - -@NodeInfo(cycles = CYCLES_4, size = SIZE_4) -public class LoadMethodCountersIndirectlyNode extends FloatingNode implements Canonicalizable, LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LoadMethodCountersIndirectlyNode.class); - - @OptionalInput protected ValueNode value; - protected Constant constant; - - public LoadMethodCountersIndirectlyNode(ValueNode value) { - super(TYPE, MethodCountersPointerStamp.methodCounters()); - this.value = value; - this.constant = null; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - if (value != null) { - constant = GraphUtil.foldIfConstantAndRemove(this, value); - } - return this; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - assert constant != null : "Expected the value to fold: " + value; - Value result; - if (constant instanceof HotSpotMetaspaceConstant) { - result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadMetaspaceAddress(constant, HotSpotConstantLoadAction.LOAD_COUNTERS); - } else { - throw new PermanentBailoutException("Unsupported constant type: " + constant); - } - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native MethodCountersPointer loadMethodCounters(MethodPointer methodPointer); -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java deleted file mode 100644 index c5f13e5aa6b5..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; - -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.hotspot.nodes.type.MethodCountersPointerStamp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@NodeInfo(cycles = CYCLES_4, size = SIZE_4) -public class LoadMethodCountersNode extends FloatingNode implements LIRLowerable { - public static final NodeClass TYPE = NodeClass.create(LoadMethodCountersNode.class); - - ResolvedJavaMethod method; - - public LoadMethodCountersNode(ResolvedJavaMethod method) { - super(TYPE, MethodCountersPointerStamp.methodCountersNonNull()); - this.method = method; - } - - public ResolvedJavaMethod getMethod() { - return method; - } - - public static NodeIterable getLoadMethodCountersNodes(StructuredGraph graph) { - return graph.getNodes().filter(LoadMethodCountersNode.class); - } - - @Override - public void generate(NodeLIRBuilderTool generator) { - // TODO: With AOT we don't need this, as this node will be replaced. - // Implement later when profiling is needed in the JIT mode. - throw GraalError.unimplemented(); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java deleted file mode 100644 index b10cb7e15ce4..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; - -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.Lowerable; - -@NodeInfo(cycles = CYCLES_4, size = SIZE_16) -public class ResolveConstantNode extends DeoptimizingFixedWithNextNode implements Lowerable { - public static final NodeClass TYPE = NodeClass.create(ResolveConstantNode.class); - - @Input ValueNode value; - protected HotSpotConstantLoadAction action; - - public ResolveConstantNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - this.action = action; - } - - public ResolveConstantNode(ValueNode value) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - this.action = HotSpotConstantLoadAction.RESOLVE; - } - - public ValueNode value() { - return value; - } - - public HotSpotConstantLoadAction action() { - return action; - } - - @Override - public boolean canDeoptimize() { - return true; - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java deleted file mode 100644 index fc0e2dcfb33a..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; - -import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; -import org.graalvm.compiler.hotspot.nodes.DeoptimizingStubCall; -import org.graalvm.compiler.hotspot.word.KlassPointer; -import org.graalvm.compiler.lir.LIRFrameState; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.Value; - -/** - * A call to the VM via a regular stub. - */ -@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_16) -public class ResolveConstantStubCall extends DeoptimizingStubCall implements Canonicalizable, LIRLowerable { - public static final NodeClass TYPE = NodeClass.create(ResolveConstantStubCall.class); - - @OptionalInput protected ValueNode value; - @Input protected ValueNode string; - protected Constant constant; - protected HotSpotConstantLoadAction action; - - public ResolveConstantStubCall(ValueNode value, ValueNode string) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - this.string = string; - this.action = HotSpotConstantLoadAction.RESOLVE; - } - - public ResolveConstantStubCall(ValueNode value, ValueNode string, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - this.string = string; - this.action = action; - } - - @NodeIntrinsic - public static native Object resolveObject(Object value, Object symbol); - - @NodeIntrinsic - public static native KlassPointer resolveKlass(KlassPointer value, Word symbol); - - @NodeIntrinsic - public static native KlassPointer resolveKlass(KlassPointer value, Word symbol, @ConstantNodeParameter HotSpotConstantLoadAction action); - - @Override - public Node canonical(CanonicalizerTool tool) { - if (value != null) { - constant = GraphUtil.foldIfConstantAndRemove(this, value); - } - return this; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - assert constant != null : "Expected the value to fold: " + value; - Value stringValue = gen.operand(string); - Value result; - LIRFrameState fs = gen.state(this); - assert fs != null : "The stateAfter is null"; - if (constant instanceof HotSpotObjectConstant) { - result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitObjectConstantRetrieval(constant, stringValue, fs); - } else if (constant instanceof HotSpotMetaspaceConstant) { - if (action == HotSpotConstantLoadAction.RESOLVE) { - result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitMetaspaceConstantRetrieval(constant, stringValue, fs); - } else { - assert action == HotSpotConstantLoadAction.INITIALIZE; - result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitKlassInitializationAndRetrieval(constant, stringValue, fs); - } - } else { - throw new PermanentBailoutException("Unsupported constant type: " + constant); - } - gen.setResult(this, result); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java deleted file mode 100644 index 677882aca627..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017, 2020, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; - -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.compiler.nodes.spi.Lowerable; -import org.graalvm.word.LocationIdentity; - -@NodeInfo(cycles = CYCLES_4, size = SIZE_16, allowedUsageTypes = {InputType.Memory}) -public class ResolveDynamicConstantNode extends DeoptimizingFixedWithNextNode implements Lowerable, SingleMemoryKill { - public static final NodeClass TYPE = NodeClass.create(ResolveDynamicConstantNode.class); - - @Input ValueNode value; - - public ResolveDynamicConstantNode(Stamp valueStamp, ValueNode value) { - super(TYPE, valueStamp); - this.value = value; - } - - public ValueNode value() { - return value; - } - - @Override - public boolean canDeoptimize() { - return true; - } - - @Override - public LocationIdentity getKilledLocationIdentity() { - return LocationIdentity.any(); - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java deleted file mode 100644 index 6d4b1d81881a..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2017, 2020, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; - -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.LIRFrameState; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.DeoptimizingNode; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.word.LocationIdentity; - -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.Value; - -/** - * A call to the VM via a regular stub. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_16) -public class ResolveDynamicStubCall extends AbstractMemoryCheckpoint implements LIRLowerable, Canonicalizable, DeoptimizingNode.DeoptBefore, SingleMemoryKill { - public static final NodeClass TYPE = NodeClass.create(ResolveDynamicStubCall.class); - - @OptionalInput protected ValueNode value; - @OptionalInput(InputType.State) protected FrameState stateBefore; - protected Constant constant; - - public ResolveDynamicStubCall(ValueNode value) { - super(TYPE, value.stamp(NodeView.DEFAULT)); - this.value = value; - } - - @NodeIntrinsic - public static native Object resolveInvoke(Object value); - - @Override - public Node canonical(CanonicalizerTool tool) { - if (value != null) { - constant = GraphUtil.foldIfConstantAndRemove(this, value); - } - return this; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - assert constant != null : "Expected the value to fold: " + value; - Value result; - LIRFrameState fs = gen.state(this); - assert fs != null : "The stateAfter is null"; - result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitResolveDynamicInvoke(constant, fs); - gen.setResult(this, result); - } - - @Override - public boolean canDeoptimize() { - return true; - } - - @Override - public LocationIdentity getKilledLocationIdentity() { - return LocationIdentity.any(); - } - - @Override - public FrameState stateBefore() { - return stateBefore; - } - - @Override - public void setStateBefore(FrameState f) { - updateUsages(stateBefore, f); - stateBefore = f; - } - - @Override - public void markDeleted() { - throw GraalError.shouldNotReachHere("ResolveDynamicStubCall node deleted"); - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java deleted file mode 100644 index 4937a94f97c1..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; - -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.nodes.type.MethodCountersPointerStamp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.Lowerable; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@NodeInfo(cycles = CYCLES_4, size = SIZE_16) -public class ResolveMethodAndLoadCountersNode extends DeoptimizingFixedWithNextNode implements Lowerable { - public static final NodeClass TYPE = NodeClass.create(ResolveMethodAndLoadCountersNode.class); - - ResolvedJavaMethod method; - @Input ValueNode hub; - - public ResolveMethodAndLoadCountersNode(ResolvedJavaMethod method, ValueNode hub) { - super(TYPE, MethodCountersPointerStamp.methodCountersNonNull()); - this.method = method; - this.hub = hub; - } - - public ResolvedJavaMethod getMethod() { - return method; - } - - public ValueNode getHub() { - return hub; - } - - @Override - public boolean canDeoptimize() { - return true; - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java deleted file mode 100644 index a880291aa278..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.aot; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; - -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.nodes.DeoptimizingStubCall; -import org.graalvm.compiler.hotspot.nodes.type.MethodCountersPointerStamp; -import org.graalvm.compiler.hotspot.word.KlassPointer; -import org.graalvm.compiler.hotspot.word.MethodCountersPointer; -import org.graalvm.compiler.hotspot.word.MethodPointer; -import org.graalvm.compiler.lir.LIRFrameState; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.Value; - -/** - * A call to the VM via a regular stub. - */ -@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_16) -public class ResolveMethodAndLoadCountersStubCall extends DeoptimizingStubCall implements Canonicalizable, LIRLowerable { - public static final NodeClass TYPE = NodeClass.create(ResolveMethodAndLoadCountersStubCall.class); - - @OptionalInput protected ValueNode method; - @Input protected ValueNode klassHint; - @Input protected ValueNode methodDescription; - protected Constant methodConstant; - - public ResolveMethodAndLoadCountersStubCall(ValueNode method, ValueNode klassHint, ValueNode methodDescription) { - super(TYPE, MethodCountersPointerStamp.methodCountersNonNull()); - this.klassHint = klassHint; - this.method = method; - this.methodDescription = methodDescription; - } - - @NodeIntrinsic - public static native MethodCountersPointer resolveMethodAndLoadCounters(MethodPointer method, KlassPointer klassHint, Word methodDescription); - - @Override - public Node canonical(CanonicalizerTool tool) { - if (method != null) { - methodConstant = GraphUtil.foldIfConstantAndRemove(this, method); - } - return this; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - assert methodConstant != null : "Expected method to fold: " + method; - - Value methodDescriptionValue = gen.operand(methodDescription); - Value klassHintValue = gen.operand(klassHint); - LIRFrameState fs = gen.state(this); - assert fs != null : "The stateAfter is null"; - - Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitResolveMethodAndLoadCounters(methodConstant, klassHintValue, methodDescriptionValue, fs); - - gen.setResult(this, result); - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileBranchNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileBranchNode.java deleted file mode 100644 index 55e059ebd1ac..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileBranchNode.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.profiling; - -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.ConditionalNode; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@NodeInfo -public class ProfileBranchNode extends ProfileWithNotificationNode { - public static final NodeClass TYPE = NodeClass.create(ProfileBranchNode.class); - - @OptionalInput ValueNode branchCondition; - protected int bci; - protected int targetBci; - - public ProfileBranchNode(ResolvedJavaMethod method, int freqLog, int probabilityLog, ConditionalNode branchCondition, int bci, int targetBci) { - super(TYPE, method, freqLog, probabilityLog); - assert targetBci <= bci; - this.branchCondition = branchCondition; - this.bci = bci; - this.targetBci = targetBci; - } - - public ProfileBranchNode(ResolvedJavaMethod method, int freqLog, int probabilityLog, int bci, int targetBci) { - super(TYPE, method, freqLog, probabilityLog); - assert targetBci <= bci; - this.branchCondition = null; - this.bci = bci; - this.targetBci = targetBci; - } - - public int bci() { - return bci; - } - - public int targetBci() { - return targetBci; - } - - public ValueNode branchCondition() { - return branchCondition; - } - - public boolean hasCondition() { - return branchCondition != null; - } - - @Override - protected boolean canBeMergedWith(ProfileNode p) { - if (p instanceof ProfileBranchNode) { - ProfileBranchNode that = (ProfileBranchNode) p; - return this.method.equals(that.method) && this.bci == that.bci; - } - return false; - } - - /** - * Gathers all the {@link ProfileBranchNode}s that are inputs to the - * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph. - */ - public static NodeIterable getProfileBranchNodes(StructuredGraph graph) { - return graph.getNodes().filter(ProfileBranchNode.class); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileInvokeNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileInvokeNode.java deleted file mode 100644 index 40c8999b17d0..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileInvokeNode.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.profiling; - -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.StructuredGraph; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@NodeInfo -public class ProfileInvokeNode extends ProfileWithNotificationNode { - public static final NodeClass TYPE = NodeClass.create(ProfileInvokeNode.class); - - public ProfileInvokeNode(ResolvedJavaMethod method, int freqLog, int probabilityLog) { - super(TYPE, method, freqLog, probabilityLog); - } - - @Override - protected boolean canBeMergedWith(ProfileNode p) { - if (p instanceof ProfileInvokeNode) { - ProfileInvokeNode that = (ProfileInvokeNode) p; - return this.method.equals(that.method); - } - return false; - } - - /** - * Gathers all the {@link ProfileInvokeNode}s that are inputs to the - * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph. - */ - public static NodeIterable getProfileInvokeNodes(StructuredGraph graph) { - return graph.getNodes().filter(ProfileInvokeNode.class); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java deleted file mode 100644 index 1141991169fb..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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 org.graalvm.compiler.hotspot.nodes.profiling; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; -import static org.graalvm.compiler.nodes.util.GraphUtil.removeFixedWithUnusedInputs; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.nodes.spi.Simplifiable; -import org.graalvm.compiler.nodes.spi.SimplifierTool; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.AbstractMergeNode; -import org.graalvm.compiler.nodes.ControlSplitNode; -import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.compiler.nodes.spi.Lowerable; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.word.LocationIdentity; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@NodeInfo(cycles = CYCLES_IGNORED, cyclesRationale = "profiling should be ignored", size = SIZE_IGNORED, sizeRationale = "profiling should be ignored") -public abstract class ProfileNode extends DeoptimizingFixedWithNextNode implements SingleMemoryKill, Simplifiable, Lowerable { - public static class Options { - @Option(help = "Control probabilistic profiling on AMD64", type = OptionType.Expert)// - public static final OptionKey ProbabilisticProfiling = new OptionKey<>(true); - } - - public static final NodeClass TYPE = NodeClass.create(ProfileNode.class); - - protected ResolvedJavaMethod method; - - // Only used if ProbabilisticProfiling == true and may be ignored by lowerer. - @OptionalInput protected ValueNode random; - - // Logarithm base 2 of the profile probability. - protected int probabilityLog; - - // Step value to add to the profile counter. - protected int step; - - protected ProfileNode(NodeClass c, ResolvedJavaMethod method, int probabilityLog) { - super(c, StampFactory.forVoid()); - this.method = method; - this.probabilityLog = probabilityLog; - this.step = 1; - } - - public ProfileNode(ResolvedJavaMethod method, int probabilityLog) { - this(TYPE, method, probabilityLog); - } - - @Override - public boolean canDeoptimize() { - return true; - } - - public ResolvedJavaMethod getProfiledMethod() { - return method; - } - - public ValueNode getRandom() { - return random; - } - - public void setRandom(ValueNode r) { - updateUsages(random, r); - this.random = r; - } - - public int getStep() { - return step; - } - - public void setStep(int s) { - step = s; - } - - /** - * Get the logarithm base 2 of the profile probability. - */ - public int getProbabilityLog() { - return probabilityLog; - } - - /** - * Gathers all the {@link ProfileNode}s that are inputs to the - * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph. - */ - public static NodeIterable getProfileNodes(StructuredGraph graph) { - return graph.getNodes().filter(ProfileNode.class); - } - - protected abstract boolean canBeMergedWith(ProfileNode p); - - @Override - public void simplify(SimplifierTool tool) { - for (Node p = predecessor(); p != null; p = p.predecessor()) { - // Terminate search when we hit a control split or merge. - if (p instanceof ControlSplitNode || p instanceof AbstractMergeNode) { - break; - } - if (p instanceof ProfileNode) { - ProfileNode that = (ProfileNode) p; - if (this.canBeMergedWith(that)) { - that.setStep(this.getStep() + that.getStep()); - removeFixedWithUnusedInputs(this); - tool.addToWorkList(that); - break; - } - } - } - } - - @Override - public LocationIdentity getKilledLocationIdentity() { - return LocationIdentity.any(); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java deleted file mode 100644 index 078f242878f4..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.profiling; - -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.NodeInfo; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@NodeInfo -public abstract class ProfileWithNotificationNode extends ProfileNode { - public static final NodeClass TYPE = NodeClass.create(ProfileWithNotificationNode.class); - - protected int freqLog; - - protected ProfileWithNotificationNode(NodeClass c, ResolvedJavaMethod method, int freqLog, int probabilityLog) { - super(c, method, probabilityLog); - this.freqLog = freqLog; - } - - public ProfileWithNotificationNode(ResolvedJavaMethod method, int freqLog, int probabilityLog) { - super(TYPE, method, probabilityLog); - this.freqLog = freqLog; - } - - /** - * Get the logarithm base 2 of the notification frequency. - */ - public int getNotificationFreqLog() { - return freqLog; - } - - /** - * Set the logarithm base 2 of the notification frequency. - */ - public void setNotificationFreqLog(int freqLog) { - assert freqLog < 32; - this.freqLog = freqLog; - } - - public void setNotificationOff() { - setNotificationFreqLog(-1); - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/RandomSeedNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/RandomSeedNode.java deleted file mode 100644 index 48258b541e30..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/RandomSeedNode.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.nodes.profiling; - -import jdk.vm.ci.meta.Value; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -@NodeInfo(cycles = CYCLES_1, size = SIZE_1) -public class RandomSeedNode extends FloatingNode implements LIRLowerable { - public static final NodeClass TYPE = NodeClass.create(RandomSeedNode.class); - - public RandomSeedNode() { - super(TYPE, StampFactory.intValue()); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitRandomSeed(); - gen.setResult(this, result); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java deleted file mode 100644 index 29e96a7a78f8..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2013, 2019, 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 org.graalvm.compiler.hotspot.phases; - -import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; - -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.nodes.type.StampTool; -import org.graalvm.compiler.phases.VerifyPhase; - -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.meta.JavaKind; - -/** - * Checks for {@link #isIllegalObjectConstant(ConstantNode) illegal} object constants in a graph - * processed for AOT compilation. - * - * @see LoadJavaMirrorWithKlassPhase - */ -public class AheadOfTimeVerificationPhase extends VerifyPhase { - - @Override - protected void verify(StructuredGraph graph, CoreProviders context) { - for (ConstantNode node : getConstantNodes(graph)) { - if (isIllegalObjectConstant(node)) { - throw new VerificationError("illegal object constant: " + node); - } - } - } - - public static boolean isIllegalObjectConstant(ConstantNode node) { - return isObject(node) && - !isNullReference(node) && - !isInternedString(node) && - !isDirectMethodHandle(node) && - !isBoundMethodHandle(node) && - !isVarHandle(node); - } - - private static boolean isObject(ConstantNode node) { - return node.getStackKind() == JavaKind.Object; - } - - private static boolean isNullReference(ConstantNode node) { - return isObject(node) && node.isNullConstant(); - } - - private static boolean isDirectMethodHandle(ConstantNode node) { - String typeName = StampTool.typeOrNull(node).getName(); - if (!isObject(node)) { - return false; - } - - switch (typeName) { - case "Ljava/lang/invoke/DirectMethodHandle;": - case "Ljava/lang/invoke/DirectMethodHandle$StaticAccessor;": - case "Ljava/lang/invoke/DirectMethodHandle$Accessor;": - case "Ljava/lang/invoke/DirectMethodHandle$Constructor;": - case "Ljava/lang/invoke/DirectMethodHandle$Special;": - case "Ljava/lang/invoke/DirectMethodHandle$Interface;": - return true; - default: - return false; - } - } - - private static boolean isBoundMethodHandle(ConstantNode node) { - if (!isObject(node)) { - return false; - } - return StampTool.typeOrNull(node).getName().startsWith("Ljava/lang/invoke/BoundMethodHandle"); - } - - private static boolean isVarHandle(ConstantNode node) { - if (!isObject(node)) { - return false; - } - String name = StampTool.typeOrNull(node).getName(); - return name.equals("Ljava/lang/invoke/VarHandle$AccessDescriptor;"); - } - - private static boolean isInternedString(ConstantNode node) { - if (!isObject(node)) { - return false; - } - - HotSpotObjectConstant c = (HotSpotObjectConstant) node.asConstant(); - return c.isInternedString(); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java deleted file mode 100644 index 70657aff2e98..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2013, 2019, 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 org.graalvm.compiler.hotspot.phases; - -import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; -import static org.graalvm.compiler.nodes.NamedLocationIdentity.FINAL_LOCATION; - -import org.graalvm.compiler.core.common.CompressEncoding; -import org.graalvm.compiler.core.common.type.AbstractObjectStamp; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.core.common.type.TypeReference; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; -import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; -import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; -import org.graalvm.compiler.hotspot.replacements.HubGetClassNode; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.FloatingReadNode; -import org.graalvm.compiler.nodes.memory.address.AddressNode; -import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; -import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.common.LoweringPhase; - -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.hotspot.HotSpotResolvedPrimitiveType; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaType; - -/** - * For AOT compilation we aren't allowed to use a {@link Class} reference ({@code javaMirror}) - * directly. Instead the {@link Class} reference should be obtained from the {@code Klass} object. - * The reason for this is, that in Class Data Sharing (CDS) a {@code Klass} object is mapped to a - * fixed address in memory, but the {@code javaMirror} is not (which lives in the Java heap). - * - * Lowering can introduce new {@link ConstantNode}s containing a {@link Class} reference, thus this - * phase must be applied after {@link LoweringPhase}. - * - * @see AheadOfTimeVerificationPhase - */ -public class LoadJavaMirrorWithKlassPhase extends BasePhase { - - private final CompressEncoding oopEncoding; - - public LoadJavaMirrorWithKlassPhase(GraalHotSpotVMConfig config) { - this.oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null; - } - - private ValueNode getClassConstantReplacement(StructuredGraph graph, CoreProviders context, JavaConstant constant) { - if (constant instanceof HotSpotObjectConstant) { - ConstantReflectionProvider constantReflection = context.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(constant); - if (type != null) { - MetaAccessProvider metaAccess = context.getMetaAccess(); - Stamp stamp = StampFactory.objectNonNull(TypeReference.createExactTrusted(metaAccess.lookupJavaType(Class.class))); - - if (type instanceof HotSpotResolvedObjectType) { - ConstantNode klass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) type).klass(), metaAccess, graph); - ValueNode getClass = graph.unique(new HubGetClassNode(metaAccess, klass)); - - if (((HotSpotObjectConstant) constant).isCompressed()) { - return HotSpotCompressionNode.compress(getClass, oopEncoding); - } else { - return getClass; - } - } else { - /* - * Primitive classes are more difficult since they don't have a corresponding - * Klass* so get them from Class.TYPE for the java box type. - */ - HotSpotResolvedPrimitiveType primitive = (HotSpotResolvedPrimitiveType) type; - ResolvedJavaType boxingClass = metaAccess.lookupJavaType(primitive.getJavaKind().toBoxedJavaClass()); - ConstantNode clazz = ConstantNode.forConstant(context.getConstantReflection().asJavaClass(boxingClass), metaAccess, graph); - HotSpotResolvedJavaField[] a = (HotSpotResolvedJavaField[]) boxingClass.getStaticFields(); - HotSpotResolvedJavaField typeField = null; - for (HotSpotResolvedJavaField f : a) { - if (f.getName().equals("TYPE")) { - typeField = f; - break; - } - } - if (typeField == null) { - throw new GraalError("Can't find TYPE field in class"); - } - - if (oopEncoding != null) { - stamp = HotSpotNarrowOopStamp.compressed((AbstractObjectStamp) stamp, oopEncoding); - } - AddressNode address = graph.unique(new OffsetAddressNode(clazz, ConstantNode.forLong(typeField.getOffset(), graph))); - ValueNode read = graph.unique(new FloatingReadNode(address, FINAL_LOCATION, null, stamp)); - - if (oopEncoding == null || ((HotSpotObjectConstant) constant).isCompressed()) { - return read; - } else { - return HotSpotCompressionNode.uncompress(read, oopEncoding); - } - } - } - } - return null; - } - - @Override - protected void run(StructuredGraph graph, CoreProviders context) { - for (ConstantNode node : getConstantNodes(graph)) { - JavaConstant constant = node.asJavaConstant(); - ValueNode freadNode = getClassConstantReplacement(graph, context, constant); - if (freadNode != null) { - node.replace(graph, freadNode); - } - } - } - - @Override - public float codeSizeIncrease() { - return 2.5f; - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java deleted file mode 100644 index 95e57ba1143d..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2016, 2020, 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 org.graalvm.compiler.hotspot.phases.aot; - -import static org.graalvm.compiler.core.common.GraalOptions.InlineEverything; -import static org.graalvm.compiler.core.common.GraalOptions.TrivialInliningSize; - -import java.util.Map; - -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.nodes.Invoke; -import org.graalvm.compiler.nodes.spi.Replacements; -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 org.graalvm.compiler.phases.common.inlining.InliningUtil; -import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; -import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy; -import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy; -import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation; - -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; - -public class AOTInliningPolicy extends GreedyInliningPolicy { - public static class Options { - // @formatter:off - @Option(help = "", type = OptionType.Expert) - public static final OptionKey AOTInliningDepthToSizeRate = new OptionKey<>(2.5); - @Option(help = "", type = OptionType.Expert) - public static final OptionKey AOTInliningSizeMaximum = new OptionKey<>(300); - @Option(help = "", type = OptionType.Expert) - public static final OptionKey AOTInliningSizeMinimum = new OptionKey<>(50); - // @formatter:on - } - - public AOTInliningPolicy(Map hints) { - super(hints); - } - - protected double maxInliningSize(int inliningDepth, OptionValues options) { - return Math.max(Options.AOTInliningSizeMaximum.getValue(options) / (inliningDepth * Options.AOTInliningDepthToSizeRate.getValue(options)), Options.AOTInliningSizeMinimum.getValue(options)); - } - - @Override - public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) { - OptionValues options = calleeInfo.graph().getOptions(); - final boolean isTracing = GraalOptions.TraceInlining.getValue(options) || calleeInfo.graph().getDebug().hasCompilationListener(); - - final InlineInfo info = invocation.callee(); - - for (int i = 0; i < info.numberOfMethods(); ++i) { - HotSpotResolvedObjectType t = (HotSpotResolvedObjectType) info.methodAt(i).getDeclaringClass(); - if (t.getFingerprint() == 0) { - return InliningPolicy.Decision.NO.withReason(isTracing, "missing fingerprint"); - } - } - - final double probability = invocation.probability(); - final double relevance = invocation.relevance(); - - if (InlineEverything.getValue(options)) { - InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything"); - return InliningPolicy.Decision.YES.withReason(isTracing, "inline everything"); - } - - if (isIntrinsic(replacements, info)) { - InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic"); - return InliningPolicy.Decision.YES.withReason(isTracing, "intrinsic"); - } - - if (info.shouldInline()) { - InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining"); - return InliningPolicy.Decision.YES.withReason(isTracing, "forced inlining"); - } - - double inliningBonus = getInliningBonus(info); - int nodes = info.determineNodeCount(); - - if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) { - InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes); - return InliningPolicy.Decision.YES.withReason(isTracing, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes); - } - - double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth, options) * inliningBonus)); - if (nodes <= maximumNodes) { - InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus, - nodes, maximumNodes); - return InliningPolicy.Decision.YES.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus, - nodes, maximumNodes); - } - - InliningUtil.traceNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes); - return InliningPolicy.Decision.NO.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java deleted file mode 100644 index eb8d222f0ce0..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2016, 2019, 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 org.graalvm.compiler.hotspot.phases.aot; - -import static org.graalvm.util.CollectionsUtil.anyMatch; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.graalvm.collections.EconomicSet; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.nodes.AbstractMergeNode; -import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.Invoke; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.graph.MergeableState; -import org.graalvm.compiler.phases.graph.PostOrderNodeIterator; - -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ResolvedJavaType; - -public class EliminateRedundantInitializationPhase extends BasePhase { - /** - * Find each {@link Invoke} that has a corresponding {@link InitializeKlassNode}. These - * {@link InitializeKlassNode} are redundant and are removed. - */ - private static void removeInitsAtStaticCalls(StructuredGraph graph) { - for (Invoke invoke : graph.getInvokes()) { - Node classInit = invoke.classInit(); - if (classInit != null) { - classInit.replaceAtUsages(null); - graph.removeFixed((FixedWithNextNode) classInit); - } - } - } - - /** - * Remove redundant {@link InitializeKlassNode} or {@link ResolveConstantNode} instances from - * the graph. - * - * @param graph the program graph - */ - private static void removeRedundantInits(StructuredGraph graph) { - // Find and remove redundant nodes from the graph. - List redundantNodes = findRedundantInits(graph); - for (FixedWithNextNode n : redundantNodes) { - graph.removeFixed(n); - } - } - - /** - * Find {@link InitializeKlassNode} and {@link ResolveConstantNode} instances that can be - * removed because there is an existing dominating node. - * - * @param graph the program graph - */ - private static List findRedundantInits(StructuredGraph graph) { - EliminateRedundantInitializationIterator i = new EliminateRedundantInitializationIterator(graph.start(), new InitializedTypes()); - i.apply(); - return i.getRedundantNodes(); - } - - /** - * State for {@link EliminateRedundantInitializationIterator}. - */ - private static class InitializedTypes extends MergeableState implements Cloneable { - private EconomicSet types; - - InitializedTypes() { - types = EconomicSet.create(); - } - - private InitializedTypes(EconomicSet types) { - this.types = types; - } - - @Override - public InitializedTypes clone() { - return new InitializedTypes(EconomicSet.create(types)); - } - - public boolean contains(ResolvedJavaType type) { - if (type.isInterface() || type.isArray()) { - // Check for exact match for interfaces - return types.contains(type); - } - // For other types see if there is the same type or a subtype - return anyMatch(types, t -> type.isAssignableFrom(t)); - } - - public void add(ResolvedJavaType type) { - types.add(type); - } - - /** - * Merge two given types. Interfaces and arrays have to be the same to merge successfully. - * For other types the answer is the LCA. - * - * @param a initialized type - * @param b initialized type - * @return lowest common type that is initialized if either a or b are initialized, null if - * no such type exists. - */ - private static ResolvedJavaType merge(ResolvedJavaType a, ResolvedJavaType b) { - // We want exact match for interfaces or arrays - if (a.isInterface() || b.isInterface() || a.isArray() || b.isArray()) { - if (a.equals(b)) { - return a; - } else { - return null; - } - } else { - // And LCA for other types - ResolvedJavaType c = a.findLeastCommonAncestor(b); - if (c.isJavaLangObject()) { - // Not a very useful type, always initialized, don't pollute the sets. - return null; - } - return c; - } - } - - /** - * Merge two sets of types. Essentially a computation of the LCA for each element of the - * cartesian product of the input sets. Interfaces have to match exactly. - * - * @param a set of initialized types - * @param b set of initialized types - * @return set of common types that would be initialized if types in either a or b are - * initialized - */ - private static EconomicSet merge(EconomicSet a, EconomicSet b) { - EconomicSet c = EconomicSet.create(); - for (ResolvedJavaType ta : a) { - for (ResolvedJavaType tb : b) { - ResolvedJavaType tc = merge(ta, tb); - if (tc != null) { - c.add(tc); - if (tc.isInterface() || tc.isArray()) { - // Interfaces and arrays are not going merge with anything else, so bail - // out early. - break; - } - } - } - } - return c; - } - - @Override - public boolean merge(AbstractMergeNode merge, List withStates) { - for (InitializedTypes ts : withStates) { - types = merge(types, ts.types); - } - return true; - } - - protected static String toString(EconomicSet types) { - StringBuilder b = new StringBuilder(); - b.append("["); - Iterator i = types.iterator(); - while (i.hasNext()) { - ResolvedJavaType t = i.next(); - b.append(t.toString()); - if (i.hasNext()) { - b.append(","); - } - } - b.append("]"); - return b.toString(); - } - - @Override - public String toString() { - return toString(types); - } - } - - /** - * Do data flow analysis of class initializations and array resolutions. Collect redundant - * nodes. - */ - private static class EliminateRedundantInitializationIterator extends PostOrderNodeIterator { - private List redundantNodes = new ArrayList<>(); - - public List getRedundantNodes() { - return redundantNodes; - } - - EliminateRedundantInitializationIterator(FixedNode start, InitializedTypes initialState) { - super(start, initialState); - } - - private void processType(FixedWithNextNode node, Constant c) { - HotSpotMetaspaceConstant klass = (HotSpotMetaspaceConstant) c; - ResolvedJavaType t = klass.asResolvedJavaType(); - if (t != null) { - if (state.contains(t)) { - redundantNodes.add(node); - } else { - state.add(t); - } - } - } - - @Override - protected void node(FixedNode node) { - if (node instanceof InitializeKlassNode) { - InitializeKlassNode i = (InitializeKlassNode) node; - if (i.value().isConstant()) { - processType(i, i.value().asConstant()); - } - } else if (node instanceof ResolveConstantNode) { - ResolveConstantNode r = (ResolveConstantNode) node; - if (r.hasNoUsages()) { - if (r.value().isConstant()) { - processType(r, r.value().asConstant()); - } - } - } - } - - } - - @Override - protected void run(StructuredGraph graph, CoreProviders context) { - removeInitsAtStaticCalls(graph); - removeRedundantInits(graph); - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java deleted file mode 100644 index a41598fae333..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java +++ /dev/null @@ -1,603 +0,0 @@ -/* - * 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 org.graalvm.compiler.hotspot.phases.aot; - -import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates; -import static org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode.getLoadMethodCountersNodes; -import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; - -import java.lang.ref.Reference; -import java.util.HashSet; -import java.util.List; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.Equivalence; -import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeMap; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; -import org.graalvm.compiler.nodes.AbstractBeginNode; -import org.graalvm.compiler.nodes.AbstractMergeNode; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.LoopBeginNode; -import org.graalvm.compiler.nodes.LoopExitNode; -import org.graalvm.compiler.nodes.StateSplit; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.Block; -import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; -import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; -import org.graalvm.compiler.phases.schedule.SchedulePhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; - -import jdk.vm.ci.code.BytecodeFrame; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaType; - -public class ReplaceConstantNodesPhase extends BasePhase { - - private final boolean verifyFingerprints; - private final boolean allowResolution; - - static Class characterCacheClass = Character.class.getDeclaredClasses()[0]; - static Class byteCacheClass = Byte.class.getDeclaredClasses()[0]; - static Class shortCacheClass = Short.class.getDeclaredClasses()[0]; - static Class integerCacheClass = Integer.class.getDeclaredClasses()[0]; - static Class longCacheClass = Long.class.getDeclaredClasses()[0]; - - static class ClassInfo { - - private ResolvedJavaType stringType; - private ResolvedJavaType referenceType; - private final HashSet builtIns = new HashSet<>(); - - ClassInfo(MetaAccessProvider metaAccessProvider) { - builtIns.add(metaAccessProvider.lookupJavaType(Boolean.class)); - - assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName()); - builtIns.add(metaAccessProvider.lookupJavaType(characterCacheClass)); - - assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName()); - builtIns.add(metaAccessProvider.lookupJavaType(byteCacheClass)); - - assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName()); - builtIns.add(metaAccessProvider.lookupJavaType(shortCacheClass)); - - assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName()); - builtIns.add(metaAccessProvider.lookupJavaType(integerCacheClass)); - - assert "java.lang.Long$LongCache".equals(longCacheClass.getName()); - builtIns.add(metaAccessProvider.lookupJavaType(longCacheClass)); - - stringType = metaAccessProvider.lookupJavaType(String.class); - referenceType = metaAccessProvider.lookupJavaType(Reference.class); - } - } - - private static boolean isReplacementNode(Node n) { - // @formatter:off - return n instanceof LoadConstantIndirectlyNode || - n instanceof LoadConstantIndirectlyFixedNode || - n instanceof ResolveDynamicConstantNode || - n instanceof ResolveConstantNode || - n instanceof InitializeKlassNode; - // @formatter:on - } - - private static boolean anyUsagesNeedReplacement(ConstantNode node) { - return node.usages().filter(n -> !isReplacementNode(n)).isNotEmpty(); - } - - private static boolean anyUsagesNeedReplacement(LoadMethodCountersNode node) { - return node.usages().filter(n -> !(n instanceof ResolveMethodAndLoadCountersNode)).isNotEmpty(); - } - - private static boolean checkForBadFingerprint(HotSpotResolvedJavaType type) { - if (type.isArray()) { - if (type.getElementalType().isPrimitive()) { - return false; - } - return ((HotSpotResolvedObjectType) (type.getElementalType())).getFingerprint() == 0; - } - return ((HotSpotResolvedObjectType) type).getFingerprint() == 0; - } - - /** - * Insert the replacement node into the graph. We may need to insert it into a place different - * than the original {@link FloatingNode} since we need to make sure that replacement will have - * a valid state assigned. - * - * @param graph - * @param stateMapper - * @param node - * @param replacement - */ - private static void insertReplacement(StructuredGraph graph, FrameStateMapperClosure stateMapper, FloatingNode node, FixedWithNextNode replacement) { - FixedWithNextNode insertionPoint = findInsertionPoint(graph, stateMapper, node); - graph.addAfterFixed(insertionPoint, replacement); - stateMapper.addState(replacement, stateMapper.getState(insertionPoint)); - } - - /** - * Find a good place to insert a stateful fixed node that is above the given node. A good - * insertion point should have a valid FrameState reaching it. - * - * @param graph - * @param stateMapper - * @param node start search from this node up - * @return an insertion point - */ - private static FixedWithNextNode findInsertionPoint(StructuredGraph graph, FrameStateMapperClosure stateMapper, FloatingNode node) { - FixedWithNextNode fixed = findFixedBeforeFloating(graph, node); - FixedWithNextNode result = findFixedWithValidState(graph, stateMapper, fixed); - return result; - } - - /** - * Find the first {@link FixedWithNextNode} that is currently scheduled before the given - * floating node. - * - * @param graph - * @param node start search from this node up - * @return the first {@link FixedWithNextNode} - */ - private static FixedWithNextNode findFixedBeforeFloating(StructuredGraph graph, FloatingNode node) { - ScheduleResult schedule = graph.getLastSchedule(); - NodeMap nodeToBlock = schedule.getNodeToBlockMap(); - Block block = nodeToBlock.get(node); - BlockMap> blockToNodes = schedule.getBlockToNodesMap(); - FixedWithNextNode result = null; - for (Node n : blockToNodes.get(block)) { - if (n.equals(node)) { - break; - } - if (n instanceof FixedWithNextNode) { - result = (FixedWithNextNode) n; - } - } - assert result != null; - return result; - } - - /** - * Find first dominating {@link FixedWithNextNode} that has a valid state reaching it starting - * from the given node. - * - * @param graph - * @param stateMapper - * @param node - * @return {@link FixedWithNextNode} that we can use as an insertion point - */ - private static FixedWithNextNode findFixedWithValidState(StructuredGraph graph, FrameStateMapperClosure stateMapper, FixedWithNextNode node) { - ScheduleResult schedule = graph.getLastSchedule(); - NodeMap nodeToBlock = schedule.getNodeToBlockMap(); - Block block = nodeToBlock.get(node); - - Node n = node; - do { - if (isFixedWithValidState(stateMapper, n)) { - return (FixedWithNextNode) n; - } - while (n != block.getBeginNode()) { - n = n.predecessor(); - if (isFixedWithValidState(stateMapper, n)) { - return (FixedWithNextNode) n; - } - } - block = block.getDominator(); - if (block != null) { - n = block.getEndNode(); - } - } while (block != null); - - return graph.start(); - } - - private static boolean isFixedWithValidState(FrameStateMapperClosure stateMapper, Node n) { - if (n instanceof FixedWithNextNode) { - FixedWithNextNode fixed = (FixedWithNextNode) n; - assert stateMapper.getState(fixed) != null; - if (!BytecodeFrame.isPlaceholderBci(stateMapper.getState(fixed).bci)) { - return true; - } - } - return false; - } - - /** - * Compute frame states for all fixed nodes in the graph. - */ - private static class FrameStateMapperClosure extends NodeIteratorClosure { - private NodeMap reachingStates; - - @Override - protected FrameState processNode(FixedNode node, FrameState previousState) { - FrameState currentState = previousState; - if (node instanceof StateSplit) { - StateSplit stateSplit = (StateSplit) node; - FrameState stateAfter = stateSplit.stateAfter(); - if (stateAfter != null) { - currentState = stateAfter; - } - } - reachingStates.put(node, currentState); - return currentState; - } - - @Override - protected FrameState merge(AbstractMergeNode merge, List states) { - FrameState singleFrameState = singleFrameState(states); - FrameState currentState = singleFrameState == null ? merge.stateAfter() : singleFrameState; - reachingStates.put(merge, currentState); - return currentState; - } - - @Override - protected FrameState afterSplit(AbstractBeginNode node, FrameState oldState) { - return oldState; - } - - @Override - protected EconomicMap processLoop(LoopBeginNode loop, FrameState initialState) { - return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates; - } - - private static FrameState singleFrameState(List states) { - FrameState singleState = states.get(0); - for (int i = 1; i < states.size(); ++i) { - if (states.get(i) != singleState) { - return null; - } - } - return singleState; - } - - FrameStateMapperClosure(StructuredGraph graph) { - reachingStates = new NodeMap<>(graph); - } - - public FrameState getState(Node n) { - return reachingStates.get(n); - } - - public void addState(Node n, FrameState s) { - reachingStates.setAndGrow(n, s); - } - } - - /** - * Try to find dominating node doing the resolution that can be reused. - * - * @param graph - * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs - * resolution. - * @return return true if all usages of the node have been replaced - */ - private static boolean tryToReplaceWithExisting(StructuredGraph graph, ConstantNode node) { - boolean allUsagesReplaced = true; - ScheduleResult schedule = graph.getLastSchedule(); - NodeMap nodeToBlock = schedule.getNodeToBlockMap(); - BlockMap> blockToNodes = schedule.getBlockToNodesMap(); - - EconomicMap blockToExisting = EconomicMap.create(Equivalence.IDENTITY); - for (Node n : node.usages().filter(n -> isReplacementNode(n))) { - blockToExisting.put(nodeToBlock.get(n), n); - } - for (Node use : node.usages().filter(n -> !isReplacementNode(n)).snapshot()) { - boolean replaced = false; - Block b = nodeToBlock.get(use); - Node e = blockToExisting.get(b); - if (e != null) { - // There is an initialization or resolution in the same block as the use, look if - // the use is scheduled after it. - for (Node n : blockToNodes.get(b)) { - if (n.equals(use)) { - // Usage is before initialization, can't use it - break; - } - if (n.equals(e)) { - use.replaceFirstInput(node, e); - replaced = true; - break; - } - } - } - if (!replaced) { - // Look for dominating blocks that have existing nodes - for (Block d : blockToExisting.getKeys()) { - if (strictlyDominates(d, b)) { - use.replaceFirstInput(node, blockToExisting.get(d)); - replaced = true; - break; - } - } - } - if (!replaced && allUsagesReplaced) { - allUsagesReplaced = false; - } - } - return allUsagesReplaced; - } - - /** - * Replace the uses of a constant with {@link ResolveConstantNode}. - * - * @param graph - * @param stateMapper - * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs - * resolution. - */ - private static void replaceWithResolution(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node, ClassInfo classInfo) { - HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); - - FixedWithNextNode fixedReplacement; - if (classInfo.builtIns.contains(type)) { - // Special case of klass constants that come from {@link BoxingSnippets}. - fixedReplacement = graph.add(new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE)); - } else { - fixedReplacement = graph.add(new ResolveConstantNode(node)); - } - insertReplacement(graph, stateMapper, node, fixedReplacement); - node.replaceAtUsages(fixedReplacement, n -> !isReplacementNode(n)); - } - - /** - * Replace the uses of a constant with either {@link LoadConstantIndirectlyNode} if possible. - * - * @param graph - * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs - * resolution. - * @return return true if all usages of the node have been replaced - */ - private static boolean replaceWithLoad(StructuredGraph graph, ConstantNode node, ClassInfo classInfo) { - HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); - ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass(); - ValueNode replacement = null; - if ((type.isArray() && type.getComponentType().isPrimitive()) || type.equals(classInfo.referenceType)) { - // Special case for primitive arrays and j.l.ref.Reference. - // The AOT runtime pre-resolves them, so we may omit the resolution call. - replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node)); - } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) { - // If it's a supertype of or the same class that declares the top method, we are - // guaranteed to have it resolved already. If it's an interface, we just test for - // equality. - replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node)); - } - if (replacement != null) { - node.replaceAtUsages(replacement, n -> !isReplacementNode(n)); - return true; - } - return false; - } - - /** - * Verify that {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} has a valid - * fingerprint. - * - * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType}. - */ - private void verifyFingerprint(ConstantNode node) { - HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); - if (type != null) { - assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants"; - if (verifyFingerprints && checkForBadFingerprint(type)) { - throw new GraalError("Type with bad fingerprint: " + type); - } - } - } - - /** - * Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with indirection. - * - * @param graph - * @param stateMapper - * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs - * resolution. - */ - private static void handleHotSpotMetaspaceConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node, ClassInfo classInfo) { - HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); - if (type != null) { - if (!tryToReplaceWithExisting(graph, node) && !replaceWithLoad(graph, node, classInfo)) { - replaceWithResolution(graph, stateMapper, node, classInfo); - } - } else { - throw new GraalError("Unsupported metaspace constant type: " + type); - } - } - - /** - * Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with a load. This - * variant handles only constants that don't require resolution. - * - * @param graph - * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs - * resolution. - */ - private static void handleHotSpotMetaspaceConstantWithoutResolution(StructuredGraph graph, ConstantNode node, ClassInfo classInfo) { - HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); - if (type != null) { - replaceWithLoad(graph, node, classInfo); - } else { - throw new GraalError("Unsupported metaspace constant type: " + type); - } - } - - /** - * Replace an object constant with an indirect load {@link ResolveConstantNode}. Currently we - * support only strings. - * - * @param graph - * @param stateMapper - * @param node {@link ConstantNode} containing a {@link HotSpotObjectConstant} that needs - * resolution. - */ - private static void handleHotSpotObjectConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node, ClassInfo classInfo) { - HotSpotObjectConstant constant = (HotSpotObjectConstant) node.asJavaConstant(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType(); - if (type.equals(classInfo.stringType)) { - assert !constant.isCompressed() : "No support for replacing compressed oop constants"; - FixedWithNextNode replacement = graph.add(new ResolveConstantNode(node)); - insertReplacement(graph, stateMapper, node, replacement); - node.replaceAtUsages(replacement, n -> !(n instanceof ResolveConstantNode)); - } else { - throw new GraalError("Unsupported object constant type: " + type); - } - } - - /** - * Replace {@link LoadMethodCountersNode} with indirect load - * {@link ResolveMethodAndLoadCountersNode}, expose a klass constant of the holder. - * - * @param graph - * @param stateMapper - * @param node - * @param context - */ - private static void handleLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, LoadMethodCountersNode node, CoreProviders context) { - ResolvedJavaType type = node.getMethod().getDeclaringClass(); - Stamp hubStamp = context.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull()); - ConstantReflectionProvider constantReflection = context.getConstantReflection(); - ConstantNode klassHint = ConstantNode.forConstant(hubStamp, constantReflection.asObjectHub(type), context.getMetaAccess(), graph); - FixedWithNextNode replacement = graph.add(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint)); - insertReplacement(graph, stateMapper, node, replacement); - node.replaceAtUsages(replacement, n -> !(n instanceof ResolveMethodAndLoadCountersNode)); - } - - /** - * Replace {@link LoadMethodCountersNode} with {@link ResolveMethodAndLoadCountersNode}, expose - * klass constants. - * - * @param graph - * @param stateMapper - * @param context - */ - private static void replaceLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, CoreProviders context) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, context, false); - - for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) { - if (anyUsagesNeedReplacement(node)) { - handleLoadMethodCounters(graph, stateMapper, node, context); - } - } - } - - /** - * Replace object and klass constants with resolution nodes or reuse preceding initializations. - * - * @param graph - * @param stateMapper - * @param classInfo - * @param context - */ - private void replaceKlassesAndObjects(StructuredGraph graph, FrameStateMapperClosure stateMapper, ClassInfo classInfo, CoreProviders context) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, context, false); - - for (ConstantNode node : getConstantNodes(graph)) { - Constant constant = node.asConstant(); - if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) { - verifyFingerprint(node); - handleHotSpotMetaspaceConstant(graph, stateMapper, node, classInfo); - } else if (constant instanceof HotSpotObjectConstant && anyUsagesNeedReplacement(node)) { - handleHotSpotObjectConstant(graph, stateMapper, node, classInfo); - } - } - } - - /** - * Replace well-known klass constants with indirect loads. - * - * @param graph - * @param classInfo - */ - private static void replaceKlassesWithoutResolution(StructuredGraph graph, ClassInfo classInfo) { - for (ConstantNode node : getConstantNodes(graph)) { - Constant constant = node.asConstant(); - if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) { - handleHotSpotMetaspaceConstantWithoutResolution(graph, node, classInfo); - } - } - } - - @Override - protected void run(StructuredGraph graph, CoreProviders context) { - if (allowResolution) { - FrameStateMapperClosure stateMapper = new FrameStateMapperClosure(graph); - ReentrantNodeIterator.apply(stateMapper, graph.start(), null); - - // Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass - // constants. - replaceLoadMethodCounters(graph, stateMapper, context); - - // Replace object and klass constants (including the ones added in the previous pass) - // with resolution nodes. - replaceKlassesAndObjects(graph, stateMapper, new ClassInfo(context.getMetaAccess()), context); - } else { - replaceKlassesWithoutResolution(graph, new ClassInfo(context.getMetaAccess())); - } - } - - @Override - public boolean checkContract() { - return false; - } - - public ReplaceConstantNodesPhase(boolean allowResolution) { - this(allowResolution, true); - } - - public ReplaceConstantNodesPhase(boolean allowResolution, boolean verifyFingerprints) { - this.allowResolution = allowResolution; - this.verifyFingerprints = verifyFingerprints; - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java deleted file mode 100644 index dd6b956439c0..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2016, 2019, 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 org.graalvm.compiler.hotspot.phases.profiling; - -import static org.graalvm.compiler.hotspot.nodes.profiling.ProfileInvokeNode.getProfileInvokeNodes; -import static org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode.getProfileNodes; - -import java.util.HashMap; -import java.util.Map; - -import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileInvokeNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; -import org.graalvm.compiler.hotspot.nodes.profiling.RandomSeedNode; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.nodes.LoopBeginNode; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.PhiNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.ValuePhiNode; -import org.graalvm.compiler.nodes.calc.AddNode; -import org.graalvm.compiler.nodes.calc.MulNode; -import org.graalvm.compiler.nodes.cfg.Block; -import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; -import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.phases.BasePhase; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class FinalizeProfileNodesPhase extends BasePhase { - private int inlineeInvokeNotificationFreqLog; - - public static class Options { - @Option(help = "Profile simple methods", type = OptionType.Expert)// - public static final OptionKey ProfileSimpleMethods = new OptionKey<>(true); - @Option(help = "Maximum number of nodes in a graph for a simple method", type = OptionType.Expert)// - public static final OptionKey SimpleMethodGraphSize = new OptionKey<>(256); - @Option(help = "Maximum number of calls in a simple method", type = OptionType.Expert)// - public static final OptionKey SimpleMethodCalls = new OptionKey<>(1); - @Option(help = "Maximum number of indirect calls in a simple moethod", type = OptionType.Expert)// - public static final OptionKey SimpleMethodIndirectCalls = new OptionKey<>(0); - - } - - public FinalizeProfileNodesPhase(int inlineeInvokeNotificationFreqLog) { - this.inlineeInvokeNotificationFreqLog = inlineeInvokeNotificationFreqLog; - } - - private static void removeAllProfilingNodes(StructuredGraph graph) { - getProfileNodes(graph).forEach((n) -> GraphUtil.removeFixedWithUnusedInputs(n)); - } - - private void assignInlineeInvokeFrequencies(StructuredGraph graph) { - for (ProfileInvokeNode node : getProfileInvokeNodes(graph)) { - ResolvedJavaMethod profiledMethod = node.getProfiledMethod(); - if (!profiledMethod.equals(graph.method())) { - // Some inlinee, reassign the inlinee frequency - node.setNotificationFreqLog(inlineeInvokeNotificationFreqLog); - } - } - } - - // Hacky heuristic to determine whether we want any profiling in this method. - // The heuristic is applied after the graph is fully formed and before the first lowering. - private static boolean simpleMethodHeuristic(StructuredGraph graph) { - if (Options.ProfileSimpleMethods.getValue(graph.getOptions())) { - return false; - } - - // Check if the graph is smallish.. - if (graph.getNodeCount() > Options.SimpleMethodGraphSize.getValue(graph.getOptions())) { - return false; - } - - // Check if method has loops - if (graph.hasLoops()) { - return false; - } - - // Check if method has calls - if (graph.getNodes().filter(InvokeNode.class).count() > Options.SimpleMethodCalls.getValue(graph.getOptions())) { - return false; - } - - // Check if method has calls that need profiling - if (graph.getNodes().filter(InvokeNode.class).filter((n) -> ((InvokeNode) n).getInvokeKind().isIndirect()).count() > Options.SimpleMethodIndirectCalls.getDefaultValue()) { - return false; - } - - return true; - } - - private static void assignRandomSources(StructuredGraph graph) { - ValueNode seed = graph.unique(new RandomSeedNode()); - ControlFlowGraph cfg = ControlFlowGraph.compute(graph, false, true, false, false); - Map loopRandomValueCache = new HashMap<>(); - - for (ProfileNode node : getProfileNodes(graph)) { - ValueNode random; - Block block = cfg.blockFor(node); - Loop loop = block.getLoop(); - // Inject LCG - // pseudo-random number generator into the loop - if (loop != null) { - LoopBeginNode loopBegin = (LoopBeginNode) loop.getHeader().getBeginNode(); - random = loopRandomValueCache.get(loopBegin); - if (random == null) { - PhiNode phi = graph.addWithoutUnique(new ValuePhiNode(seed.stamp(NodeView.DEFAULT), loopBegin)); - phi.addInput(seed); - // X_{n+1} = a*X_n + c, using glibc-like constants - ValueNode a = ConstantNode.forInt(1103515245, graph); - ValueNode c = ConstantNode.forInt(12345, graph); - ValueNode next = graph.addOrUniqueWithInputs(new AddNode(c, new MulNode(phi, a))); - for (int i = 0; i < loopBegin.getLoopEndCount(); i++) { - phi.addInput(next); - } - random = phi; - loopRandomValueCache.put(loopBegin, random); - } - } else { - // Graal doesn't compile methods with irreducible loops. So all profile nodes that - // are not in a loop are guaranteed to be executed at most once. We feed the seed - // value to such nodes directly. - random = seed; - } - node.setRandom(random); - } - } - - @Override - protected void run(StructuredGraph graph, CoreProviders context) { - if (simpleMethodHeuristic(graph)) { - removeAllProfilingNodes(graph); - return; - } - - assignInlineeInvokeFrequencies(graph); - if (ProfileNode.Options.ProbabilisticProfiling.getValue(graph.getOptions())) { - assignRandomSources(graph); - } - } - - @Override - public boolean checkContract() { - return false; - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java index 1a54e1751168..e2b59546459c 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java @@ -27,7 +27,6 @@ import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; import static jdk.vm.ci.meta.DeoptimizationAction.None; import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.MinimalBulkZeroingSize; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_OPTIONVALUES; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; @@ -91,8 +90,6 @@ import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.nodes.KlassBeingInitializedCheckNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; @@ -176,21 +173,6 @@ public Object allocateArray(KlassPointer hub, return piArrayCastToSnippetReplaceeStamp(result, length); } - @Snippet - protected Object allocateInstancePIC(KlassPointer hub, - Word prototypeMarkWord, - @ConstantParameter long size, - @ConstantParameter boolean fillContents, - @ConstantParameter boolean emitMemoryBarrier, - @ConstantParameter HotSpotAllocationProfilingData profilingData) { - // Klass must be initialized by the time the first instance is allocated, therefore we can - // just load it from the corresponding cell and avoid the resolution check. We have to use a - // fixed load though, to prevent it from floating above the initialization. - KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); - Object result = allocateInstanceImpl(picHub.asWord(), prototypeMarkWord, WordFactory.unsigned(size), fillContents, emitMemoryBarrier, true, profilingData); - return piCastToSnippetReplaceeStamp(result); - } - @Snippet public Object allocateInstanceDynamic(@NonNullParameter Class type, @ConstantParameter boolean fillContents, @@ -238,44 +220,6 @@ private static Class validateNewInstanceClass(Class type, Class classCl return nonNullType; } - @Snippet - public Object allocatePrimitiveArrayPIC(KlassPointer hub, - Word prototypeMarkWord, - int length, - @ConstantParameter int arrayBaseOffset, - @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, - @ConstantParameter int fillStartOffset, - @ConstantParameter boolean emitMemoryBarrier, - @ConstantParameter boolean maybeUnroll, - @ConstantParameter boolean supportsBulkZeroing, - @ConstantParameter boolean supportsOptimizedFilling, - @ConstantParameter HotSpotAllocationProfilingData profilingData) { - // Primitive array types are eagerly pre-resolved. We can use a floating load. - KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub); - return allocateArrayImpl(picHub.asWord(), prototypeMarkWord, length, arrayBaseOffset, log2ElementSize, fillContents, fillStartOffset, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing, - supportsOptimizedFilling, profilingData); - } - - @Snippet - public Object allocateArrayPIC(KlassPointer hub, - Word prototypeMarkWord, - int length, - @ConstantParameter int arrayBaseOffset, - @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, - @ConstantParameter int fillStartOffset, - @ConstantParameter boolean emitMemoryBarrier, - @ConstantParameter boolean maybeUnroll, - @ConstantParameter boolean supportsBulkZeroing, - @ConstantParameter boolean supportsOptimizedFilling, - @ConstantParameter HotSpotAllocationProfilingData profilingData) { - // Array type would be resolved by dominating resolution. - KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); - return allocateArrayImpl(picHub.asWord(), prototypeMarkWord, length, arrayBaseOffset, log2ElementSize, fillContents, fillStartOffset, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing, - supportsOptimizedFilling, profilingData); - } - @Snippet public Object allocateArrayDynamic(Class elementType, Word prototypeMarkWord, @@ -338,13 +282,6 @@ protected Object newmultiarray(KlassPointer hub, @ConstantParameter int rank, @V return newMultiArrayImpl(hub.asWord(), rank, dimensions); } - @Snippet - private Object newmultiarrayPIC(KlassPointer hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) { - // Array type would be resolved by dominating resolution. - KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); - return newMultiArrayImpl(picHub.asWord(), rank, dimensions); - } - @Snippet private void verifyHeap() { Word tlabInfo = getTLABInfo(); @@ -614,15 +551,11 @@ public static class Templates extends AbstractTemplates { private HotSpotAllocationProfilingData profilingData; private final SnippetInfo allocateInstance; - private final SnippetInfo allocateInstancePIC; private final SnippetInfo allocateArray; - private final SnippetInfo allocateArrayPIC; - private final SnippetInfo allocatePrimitiveArrayPIC; private final SnippetInfo allocateArrayDynamic; private final SnippetInfo allocateInstanceDynamic; private final SnippetInfo validateNewInstanceClass; private final SnippetInfo newmultiarray; - private final SnippetInfo newmultiarrayPIC; private final SnippetInfo verifyHeap; private final SnippetInfo threadBeingInitializedCheck; @@ -636,11 +569,6 @@ public Templates(HotSpotAllocationSnippets receiver, OptionValues options, Itera allocateInstance = snippet(HotSpotAllocationSnippets.class, "allocateInstance", null, receiver, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION, PROTOTYPE_MARK_WORD_LOCATION); allocateArray = snippet(HotSpotAllocationSnippets.class, "allocateArray", null, receiver, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - allocateInstancePIC = snippet(HotSpotAllocationSnippets.class, "allocateInstancePIC", null, receiver, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION, - PROTOTYPE_MARK_WORD_LOCATION); - allocateArrayPIC = snippet(HotSpotAllocationSnippets.class, "allocateArrayPIC", null, receiver, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - allocatePrimitiveArrayPIC = snippet(HotSpotAllocationSnippets.class, "allocatePrimitiveArrayPIC", null, receiver, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, - TLAB_END_LOCATION); allocateArrayDynamic = snippet(HotSpotAllocationSnippets.class, "allocateArrayDynamic", null, receiver, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); allocateInstanceDynamic = snippet(HotSpotAllocationSnippets.class, "allocateInstanceDynamic", null, receiver, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, @@ -648,7 +576,6 @@ public Templates(HotSpotAllocationSnippets receiver, OptionValues options, Itera validateNewInstanceClass = snippet(HotSpotAllocationSnippets.class, "validateNewInstanceClass", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION, PROTOTYPE_MARK_WORD_LOCATION, CLASS_INIT_STATE_LOCATION); newmultiarray = snippet(HotSpotAllocationSnippets.class, "newmultiarray", null, receiver, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - newmultiarrayPIC = snippet(HotSpotAllocationSnippets.class, "newmultiarrayPIC", null, receiver, TLAB_TOP_LOCATION, TLAB_END_LOCATION); verifyHeap = snippet(HotSpotAllocationSnippets.class, "verifyHeap", null, receiver); threadBeingInitializedCheck = snippet(HotSpotAllocationSnippets.class, "threadBeingInitializedCheck", null, receiver); } @@ -677,8 +604,7 @@ public void lower(NewInstanceNode node, LoweringTool tool) { long size = instanceSize(type); OptionValues localOptions = graph.getOptions(); - SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? allocateInstancePIC : allocateInstance; - Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); + Arguments args = new Arguments(allocateInstance, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("prototypeMarkWord", type.prototypeMarkWord()); args.addConst("size", size); @@ -704,18 +630,7 @@ public void lower(NewArrayNode node, LoweringTool tool) { int log2ElementSize = CodeUtil.log2(tool.getMetaAccess().getArrayIndexScale(elementKind)); OptionValues localOptions = graph.getOptions(); - SnippetInfo snippet; - if (GeneratePIC.getValue(localOptions)) { - if (elementType.isPrimitive()) { - snippet = allocatePrimitiveArrayPIC; - } else { - snippet = allocateArrayPIC; - } - } else { - snippet = allocateArray; - } - - Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); + Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); assert arrayType.prototypeMarkWord() == lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord() : "all array types are assumed to have the same prototypeMarkWord"; args.add("prototypeMarkWord", arrayType.prototypeMarkWord()); @@ -738,7 +653,6 @@ public void lower(NewArrayNode node, LoweringTool tool) { public void lower(NewMultiArrayNode node, LoweringTool tool) { StructuredGraph graph = node.graph(); - OptionValues localOptions = graph.getOptions(); int rank = node.dimensionCount(); ValueNode[] dims = new ValueNode[rank]; for (int i = 0; i < node.dimensionCount(); i++) { @@ -747,8 +661,7 @@ public void lower(NewMultiArrayNode node, LoweringTool tool) { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) node.type(); ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), graph); - SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? newmultiarrayPIC : newmultiarray; - Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); + Arguments args = new Arguments(newmultiarray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.addConst("rank", rank); args.addVarargs("dimensions", int.class, StampFactory.forKind(JavaKind.Int), dims); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java index a1e4e7ff0fa2..aa6b42b0e1d5 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java @@ -38,7 +38,6 @@ import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; -import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.gc.G1ArrayRangePostWriteBarrier; @@ -129,14 +128,14 @@ protected byte youngCardValue() { @Override protected Word cardTableAddress(Pointer oop) { - Word cardTable = WordFactory.unsigned(GraalHotSpotVMConfigNode.cardTableAddress()); + Word cardTable = WordFactory.unsigned(HotSpotReplacementsUtil.cardTableStart(INJECTED_VMCONFIG)); int cardTableShift = HotSpotReplacementsUtil.cardTableShift(INJECTED_VMCONFIG); return cardTable.add(oop.unsignedShiftRight(cardTableShift)); } @Override protected int logOfHeapRegionGrainBytes() { - return GraalHotSpotVMConfigNode.logOfHeapRegionGrainBytes(); + return HotSpotReplacementsUtil.logOfHeapRegionGrainBytes(INJECTED_VMCONFIG); } @Override @@ -151,7 +150,7 @@ protected ForeignCallDescriptor postWriteBarrierCallDescriptor() { @Override protected boolean verifyOops() { - return GraalHotSpotVMConfigNode.verifyOops(); + return HotSpotReplacementsUtil.verifyOops(INJECTED_VMCONFIG); } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 0bca26b68f08..42c88a39b221 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -41,7 +41,6 @@ import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.CanonicalizableLocation; import org.graalvm.compiler.nodes.CompressionNode; @@ -640,6 +639,11 @@ public static int cardTableShift(@InjectedParameter GraalHotSpotVMConfig config) return config.cardtableShift; } + @Fold + public static long cardTableStart(@InjectedParameter GraalHotSpotVMConfig config) { + return config.cardtableStartAddress; + } + @Fold public static int g1CardQueueIndexOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.g1CardQueueIndexOffset; @@ -650,6 +654,11 @@ public static int g1CardQueueBufferOffset(@InjectedParameter GraalHotSpotVMConfi return config.g1CardQueueBufferOffset; } + @Fold + public static int logOfHeapRegionGrainBytes(@InjectedParameter GraalHotSpotVMConfig config) { + return config.logOfHRGrainBytes; + } + @Fold public static int g1SATBQueueMarkingOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.g1SATBQueueMarkingOffset; @@ -725,13 +734,33 @@ public static KlassPointer loadHub(Object object) { return loadHubIntrinsic(object); } + @Fold + public static boolean verifyOops(@InjectedParameter GraalHotSpotVMConfig config) { + return config.verifyOops; + } + public static Object verifyOop(Object object) { - if (GraalHotSpotVMConfigNode.verifyOops()) { + if (verifyOops(INJECTED_VMCONFIG)) { verifyOopStub(VERIFY_OOP, object); } return object; } + @Fold + public static long verifyOopBits(@InjectedParameter GraalHotSpotVMConfig config) { + return config.verifyOopBits; + } + + @Fold + public static long verifyOopMask(@InjectedParameter GraalHotSpotVMConfig config) { + return config.verifyOopMask; + } + + @Fold + public static long verifyOopCounterAddress(@InjectedParameter GraalHotSpotVMConfig config) { + return config.verifyOopCounterAddress; + } + @NodeIntrinsic(ForeignCallNode.class) private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotSerialWriteBarrierSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotSerialWriteBarrierSnippets.java index 6fd4241f0568..01b7955bb998 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotSerialWriteBarrierSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotSerialWriteBarrierSnippets.java @@ -28,7 +28,6 @@ import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.nodes.gc.SerialArrayRangeWriteBarrier; import org.graalvm.compiler.nodes.gc.SerialWriteBarrier; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -50,7 +49,7 @@ public HotSpotSerialWriteBarrierSnippets() { @Override public Word cardTableAddress() { - return WordFactory.unsigned(GraalHotSpotVMConfigNode.cardTableAddress()); + return WordFactory.unsigned(HotSpotReplacementsUtil.cardTableStart(INJECTED_VMCONFIG)); } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java index 128c29044168..bfd277389fe1 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java @@ -27,7 +27,6 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.graph.Node; @@ -74,7 +73,7 @@ public Node canonical(CanonicalizerTool tool) { return null; } else { MetaAccessProvider metaAccess = tool.getMetaAccess(); - if (metaAccess != null && hub.isConstant() && !GraalOptions.ImmutableCode.getValue(tool.getOptions())) { + if (metaAccess != null && hub.isConstant()) { ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asConstant()); if (exactType != null) { return ConstantNode.forConstant(tool.getConstantReflection().asJavaClass(exactType), metaAccess); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java index 49554a1b8ca4..b5e16370e046 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java @@ -26,7 +26,6 @@ import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; import static jdk.vm.ci.meta.DeoptimizationReason.OptimizedTypeCheckViolated; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PRIMARY_SUPERS_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.SECONDARY_SUPER_CACHE_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic; @@ -275,11 +274,6 @@ protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool OptionValues localOptions = instanceOf.getOptions(); JavaTypeProfile profile = instanceOf.profile(); - if (GeneratePIC.getValue(localOptions)) { - // FIXME: We can't embed constants in hints. We can't really load them from GOT - // either. Hard problem. - profile = null; - } TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), profile, assumptions, TypeCheckMinProfileHitProbability.getValue(localOptions), TypeCheckMaxHints.getValue(localOptions)); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type().getType(); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java deleted file mode 100644 index f4628bca004e..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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 org.graalvm.compiler.hotspot.replacements.aot; - -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; -import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; - -import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.debug.DebugHandlersFactory; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.aot.EncodedSymbolNode; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassStubCall; -import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersIndirectlyNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicStubCall; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersStubCall; -import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; -import org.graalvm.compiler.hotspot.word.KlassPointer; -import org.graalvm.compiler.hotspot.word.MethodCountersPointer; -import org.graalvm.compiler.hotspot.word.MethodPointer; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.replacements.SnippetTemplate; -import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; -import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; -import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; -import org.graalvm.compiler.replacements.Snippets; - -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.meta.Constant; - -public class ResolveConstantSnippets implements Snippets { - - @Snippet - public static Object resolveObjectConstant(Object constant) { - Object result = LoadConstantIndirectlyNode.loadObject(constant); - if (probability(VERY_SLOW_PATH_PROBABILITY, result == null)) { - result = ResolveConstantStubCall.resolveObject(constant, EncodedSymbolNode.encode(constant)); - } - return result; - } - - @Snippet - public static Object resolveDynamicConstant(Object constant) { - Object result = LoadConstantIndirectlyNode.loadObject(constant); - if (probability(VERY_SLOW_PATH_PROBABILITY, result == null)) { - result = ResolveDynamicStubCall.resolveInvoke(constant); - } - return result; - } - - @Snippet - public static KlassPointer resolveKlassConstant(KlassPointer constant) { - KlassPointer result = LoadConstantIndirectlyNode.loadKlass(constant); - if (probability(VERY_SLOW_PATH_PROBABILITY, result.isNull())) { - result = ResolveConstantStubCall.resolveKlass(constant, EncodedSymbolNode.encode(constant)); - } - return result; - } - - @Snippet - public static MethodCountersPointer resolveMethodAndLoadCounters(MethodPointer method, KlassPointer klassHint) { - MethodCountersPointer result = LoadMethodCountersIndirectlyNode.loadMethodCounters(method); - if (probability(VERY_SLOW_PATH_PROBABILITY, result.isNull())) { - result = ResolveMethodAndLoadCountersStubCall.resolveMethodAndLoadCounters(method, klassHint, EncodedSymbolNode.encode(method)); - } - return result; - } - - @Snippet - public static KlassPointer initializeKlass(KlassPointer constant) { - KlassPointer result = LoadConstantIndirectlyNode.loadKlass(constant, HotSpotConstantLoadAction.INITIALIZE); - if (probability(VERY_SLOW_PATH_PROBABILITY, result.isNull())) { - result = InitializeKlassStubCall.initializeKlass(constant, EncodedSymbolNode.encode(constant)); - } - return result; - } - - @Snippet - public static KlassPointer pureInitializeKlass(KlassPointer constant) { - KlassPointer result = LoadConstantIndirectlyNode.loadKlass(constant, HotSpotConstantLoadAction.INITIALIZE); - if (probability(VERY_SLOW_PATH_PROBABILITY, result.isNull())) { - result = ResolveConstantStubCall.resolveKlass(constant, EncodedSymbolNode.encode(constant), HotSpotConstantLoadAction.INITIALIZE); - } - return result; - } - - public static class Templates extends AbstractTemplates { - private final SnippetInfo resolveObjectConstant = snippet(ResolveConstantSnippets.class, "resolveObjectConstant"); - private final SnippetInfo resolveDynamicConstant = snippet(ResolveConstantSnippets.class, "resolveDynamicConstant"); - private final SnippetInfo resolveKlassConstant = snippet(ResolveConstantSnippets.class, "resolveKlassConstant"); - private final SnippetInfo resolveMethodAndLoadCounters = snippet(ResolveConstantSnippets.class, "resolveMethodAndLoadCounters"); - private final SnippetInfo initializeKlass = snippet(ResolveConstantSnippets.class, "initializeKlass"); - private final SnippetInfo pureInitializeKlass = snippet(ResolveConstantSnippets.class, "pureInitializeKlass"); - - public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { - super(options, factories, providers, providers.getSnippetReflection(), target); - } - - public void lower(ResolveDynamicConstantNode resolveConstantNode, LoweringTool tool) { - StructuredGraph graph = resolveConstantNode.graph(); - - ValueNode value = resolveConstantNode.value(); - assert value.isConstant() : "Expected a constant: " + value; - SnippetInfo snippet = resolveDynamicConstant; - - Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("constant", value); - - SnippetTemplate template = template(resolveConstantNode, args); - template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, args); - - assert resolveConstantNode.hasNoUsages(); - if (!resolveConstantNode.isDeleted()) { - GraphUtil.killWithUnusedFloatingInputs(resolveConstantNode); - } - } - - public void lower(ResolveConstantNode resolveConstantNode, LoweringTool tool) { - StructuredGraph graph = resolveConstantNode.graph(); - - ValueNode value = resolveConstantNode.value(); - assert value.isConstant() : "Expected a constant: " + value; - Constant constant = value.asConstant(); - SnippetInfo snippet = null; - - if (constant instanceof HotSpotMetaspaceConstant) { - HotSpotMetaspaceConstant hotspotMetaspaceConstant = (HotSpotMetaspaceConstant) constant; - if (hotspotMetaspaceConstant.asResolvedJavaType() != null) { - if (resolveConstantNode.action() == HotSpotConstantLoadAction.RESOLVE) { - snippet = resolveKlassConstant; - } else { - assert resolveConstantNode.action() == HotSpotConstantLoadAction.INITIALIZE; - snippet = pureInitializeKlass; - } - } - } else if (constant instanceof HotSpotObjectConstant) { - snippet = resolveObjectConstant; - HotSpotObjectConstant hotspotObjectConstant = (HotSpotObjectConstant) constant; - assert hotspotObjectConstant.isInternedString(); - } - if (snippet == null) { - throw new GraalError("Unsupported constant type: " + constant); - } - - Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("constant", value); - - SnippetTemplate template = template(resolveConstantNode, args); - template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, args); - - assert resolveConstantNode.hasNoUsages(); - if (!resolveConstantNode.isDeleted()) { - GraphUtil.killWithUnusedFloatingInputs(resolveConstantNode); - } - } - - public void lower(InitializeKlassNode initializeKlassNode, LoweringTool tool) { - StructuredGraph graph = initializeKlassNode.graph(); - - ValueNode value = initializeKlassNode.value(); - assert value.isConstant() : "Expected a constant: " + value; - Constant constant = value.asConstant(); - - if (constant instanceof HotSpotMetaspaceConstant) { - Arguments args = new Arguments(initializeKlass, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("constant", value); - - SnippetTemplate template = template(initializeKlassNode, args); - template.instantiate(providers.getMetaAccess(), initializeKlassNode, DEFAULT_REPLACER, args); - assert initializeKlassNode.hasNoUsages(); - if (!initializeKlassNode.isDeleted()) { - GraphUtil.killWithUnusedFloatingInputs(initializeKlassNode); - } - - } else { - throw new GraalError("Unsupported constant type: " + constant); - } - } - - public void lower(ResolveMethodAndLoadCountersNode resolveMethodAndLoadCountersNode, LoweringTool tool) { - StructuredGraph graph = resolveMethodAndLoadCountersNode.graph(); - ConstantNode method = ConstantNode.forConstant(MethodPointerStamp.methodNonNull(), resolveMethodAndLoadCountersNode.getMethod().getEncoding(), tool.getMetaAccess(), graph); - Arguments args = new Arguments(resolveMethodAndLoadCounters, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("method", method); - args.add("klassHint", resolveMethodAndLoadCountersNode.getHub()); - SnippetTemplate template = template(resolveMethodAndLoadCountersNode, args); - template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, args); - - assert resolveMethodAndLoadCountersNode.hasNoUsages(); - if (!resolveMethodAndLoadCountersNode.isDeleted()) { - GraphUtil.killWithUnusedFloatingInputs(resolveMethodAndLoadCountersNode); - } - } - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java deleted file mode 100644 index 2e36c480921c..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2016, 2020, 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 org.graalvm.compiler.hotspot.replacements.profiling; - -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.backedgeCounterOffset; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterIncrement; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterOffset; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterShift; -import static org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets.METHOD_COUNTERS; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; -import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; - -import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.debug.DebugHandlersFactory; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileBranchNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileInvokeNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; -import org.graalvm.compiler.hotspot.word.MethodCountersPointer; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.replacements.SnippetTemplate; -import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; -import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; -import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; -import org.graalvm.compiler.replacements.Snippets; - -import jdk.vm.ci.code.CodeUtil; -import jdk.vm.ci.code.TargetDescription; - -public class ProbabilisticProfileSnippets implements Snippets { - @Snippet - public static boolean shouldProfile(@ConstantParameter int probLog, int random) { - int probabilityMask = (1 << probLog) - 1; - return (random & probabilityMask) == 0; - } - - @Snippet - public static int notificationMask(int freqLog, int probLog, int stepLog) { - int frequencyMask = (1 << freqLog) - 1; - int stepMask = (1 << (stepLog + probLog)) - 1; - return frequencyMask & ~stepMask; - } - - @NodeIntrinsic(ForeignCallNode.class) - public static native void methodInvocationEvent(@ConstantNodeParameter ForeignCallDescriptor descriptor, MethodCountersPointer counters); - - @Snippet - public static void profileMethodEntryWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog, @ConstantParameter int probLog) { - if (probability(1.0 / (1 << probLog), shouldProfile(probLog, random))) { - int counterValue = counters.readInt(invocationCounterOffset(INJECTED_VMCONFIG), METHOD_COUNTERS) + ((invocationCounterIncrement(INJECTED_VMCONFIG) * step) << probLog); - counters.writeIntSideEffectFree(invocationCounterOffset(INJECTED_VMCONFIG), counterValue, METHOD_COUNTERS); - if (freqLog >= 0) { - int mask = notificationMask(freqLog, probLog, stepLog); - if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) { - methodInvocationEvent(HotSpotBackend.INVOCATION_EVENT, counters); - } - } - } - } - - @NodeIntrinsic(ForeignCallNode.class) - public static native void methodBackedgeEvent(@ConstantNodeParameter ForeignCallDescriptor descriptor, MethodCountersPointer counters, int bci, int targetBci); - - @Snippet - public static void profileBackedgeWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog, @ConstantParameter int probLog, int bci, - int targetBci) { - if (probability(1.0 / (1 << probLog), shouldProfile(probLog, random))) { - int counterValue = counters.readInt(backedgeCounterOffset(INJECTED_VMCONFIG), METHOD_COUNTERS) + ((invocationCounterIncrement(INJECTED_VMCONFIG) * step) << probLog); - counters.writeIntSideEffectFree(backedgeCounterOffset(INJECTED_VMCONFIG), counterValue, METHOD_COUNTERS); - int mask = notificationMask(freqLog, probLog, stepLog); - if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) { - methodBackedgeEvent(HotSpotBackend.BACKEDGE_EVENT, counters, bci, targetBci); - } - } - } - - @Snippet - public static void profileConditionalBackedgeWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog, - @ConstantParameter int probLog, boolean branchCondition, - int bci, int targetBci) { - if (branchCondition) { - profileBackedgeWithProbability(counters, random, step, stepLog, freqLog, probLog, bci, targetBci); - } - } - - public static class Templates extends AbstractTemplates { - private final SnippetInfo profileMethodEntryWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileMethodEntryWithProbability"); - private final SnippetInfo profileBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileBackedgeWithProbability"); - private final SnippetInfo profileConditionalBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileConditionalBackedgeWithProbability"); - - public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { - super(options, factories, providers, providers.getSnippetReflection(), target); - } - - public void lower(ProfileNode profileNode, LoweringTool tool) { - assert profileNode.getRandom() != null; - - StructuredGraph graph = profileNode.graph(); - LoadMethodCountersNode counters = graph.unique(new LoadMethodCountersNode(profileNode.getProfiledMethod())); - ConstantNode step = ConstantNode.forInt(profileNode.getStep(), graph); - ConstantNode stepLog = ConstantNode.forInt(CodeUtil.log2(profileNode.getStep()), graph); - - if (profileNode instanceof ProfileBranchNode) { - // Backedge event - ProfileBranchNode profileBranchNode = (ProfileBranchNode) profileNode; - SnippetInfo snippet = profileBranchNode.hasCondition() ? profileConditionalBackedgeWithProbability : profileBackedgeWithProbability; - Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); - ConstantNode bci = ConstantNode.forInt(profileBranchNode.bci(), graph); - ConstantNode targetBci = ConstantNode.forInt(profileBranchNode.targetBci(), graph); - - args.add("counters", counters); - args.add("random", profileBranchNode.getRandom()); - args.add("step", step); - args.add("stepLog", stepLog); - args.addConst("freqLog", profileBranchNode.getNotificationFreqLog()); - args.addConst("probLog", profileBranchNode.getProbabilityLog()); - if (profileBranchNode.hasCondition()) { - args.add("branchCondition", profileBranchNode.branchCondition()); - } - args.add("bci", bci); - args.add("targetBci", targetBci); - - SnippetTemplate template = template(profileNode, args); - template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); - } else if (profileNode instanceof ProfileInvokeNode) { - ProfileInvokeNode profileInvokeNode = (ProfileInvokeNode) profileNode; - // Method invocation event - Arguments args = new Arguments(profileMethodEntryWithProbability, graph.getGuardsStage(), tool.getLoweringStage()); - - args.add("counters", counters); - args.add("random", profileInvokeNode.getRandom()); - args.add("step", step); - args.add("stepLog", stepLog); - args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog()); - args.addConst("probLog", profileInvokeNode.getProbabilityLog()); - SnippetTemplate template = template(profileNode, args); - template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); - } else { - throw new GraalError("Unsupported profile node type: " + profileNode); - } - - assert profileNode.hasNoUsages(); - if (!profileNode.isDeleted()) { - GraphUtil.killWithUnusedFloatingInputs(profileNode); - } - } - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java deleted file mode 100644 index 3a5ad282d3ac..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2016, 2020, 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 org.graalvm.compiler.hotspot.replacements.profiling; - -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.backedgeCounterOffset; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterIncrement; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterOffset; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.invocationCounterShift; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; -import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; - -import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.debug.DebugHandlersFactory; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileBranchNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileInvokeNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; -import org.graalvm.compiler.hotspot.word.MethodCountersPointer; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.NamedLocationIdentity; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.replacements.SnippetTemplate; -import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; -import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; -import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; -import org.graalvm.compiler.replacements.Snippets; - -import jdk.vm.ci.code.CodeUtil; -import jdk.vm.ci.code.TargetDescription; -import org.graalvm.word.LocationIdentity; - -public class ProfileSnippets implements Snippets { - public static final LocationIdentity METHOD_COUNTERS = NamedLocationIdentity.mutable("MethodCounters"); - - @NodeIntrinsic(ForeignCallNode.class) - public static native void methodInvocationEvent(@ConstantNodeParameter ForeignCallDescriptor descriptor, MethodCountersPointer counters); - - @Snippet - protected static int notificationMask(int freqLog, int stepLog) { - int stepMask = (1 << stepLog) - 1; - int frequencyMask = (1 << freqLog) - 1; - return frequencyMask & ~stepMask; - } - - @Snippet - public static void profileMethodEntry(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog) { - int counterValue = counters.readInt(invocationCounterOffset(INJECTED_VMCONFIG), METHOD_COUNTERS) + invocationCounterIncrement(INJECTED_VMCONFIG) * step; - counters.writeIntSideEffectFree(invocationCounterOffset(INJECTED_VMCONFIG), counterValue, METHOD_COUNTERS); - if (freqLog >= 0) { - final int mask = notificationMask(freqLog, stepLog); - if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) { - methodInvocationEvent(HotSpotBackend.INVOCATION_EVENT, counters); - } - } - } - - @NodeIntrinsic(ForeignCallNode.class) - public static native void methodBackedgeEvent(@ConstantNodeParameter ForeignCallDescriptor descriptor, MethodCountersPointer counters, int bci, int targetBci); - - @Snippet - public static void profileBackedge(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog, int bci, int targetBci) { - int counterValue = counters.readInt(backedgeCounterOffset(INJECTED_VMCONFIG), METHOD_COUNTERS) + invocationCounterIncrement(INJECTED_VMCONFIG) * step; - counters.writeIntSideEffectFree(backedgeCounterOffset(INJECTED_VMCONFIG), counterValue, METHOD_COUNTERS); - final int mask = notificationMask(freqLog, stepLog); - if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << invocationCounterShift(INJECTED_VMCONFIG))) == 0)) { - methodBackedgeEvent(HotSpotBackend.BACKEDGE_EVENT, counters, bci, targetBci); - } - } - - @Snippet - public static void profileConditionalBackedge(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog, boolean branchCondition, int bci, int targetBci) { - if (branchCondition) { - profileBackedge(counters, step, stepLog, freqLog, bci, targetBci); - } - } - - public static class Templates extends AbstractTemplates { - private final SnippetInfo profileMethodEntry = snippet(ProfileSnippets.class, "profileMethodEntry"); - private final SnippetInfo profileBackedge = snippet(ProfileSnippets.class, "profileBackedge"); - private final SnippetInfo profileConditionalBackedge = snippet(ProfileSnippets.class, "profileConditionalBackedge"); - - public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { - super(options, factories, providers, providers.getSnippetReflection(), target); - } - - public void lower(ProfileNode profileNode, LoweringTool tool) { - StructuredGraph graph = profileNode.graph(); - LoadMethodCountersNode counters = graph.unique(new LoadMethodCountersNode(profileNode.getProfiledMethod())); - ConstantNode step = ConstantNode.forInt(profileNode.getStep(), graph); - ConstantNode stepLog = ConstantNode.forInt(CodeUtil.log2(profileNode.getStep()), graph); - - if (profileNode instanceof ProfileBranchNode) { - // Backedge event - ProfileBranchNode profileBranchNode = (ProfileBranchNode) profileNode; - SnippetInfo snippet = profileBranchNode.hasCondition() ? profileConditionalBackedge : profileBackedge; - Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); - ConstantNode bci = ConstantNode.forInt(profileBranchNode.bci(), graph); - ConstantNode targetBci = ConstantNode.forInt(profileBranchNode.targetBci(), graph); - args.add("counters", counters); - args.add("step", step); - args.add("stepLog", stepLog); - args.addConst("freqLog", profileBranchNode.getNotificationFreqLog()); - if (profileBranchNode.hasCondition()) { - args.add("branchCondition", profileBranchNode.branchCondition()); - } - args.add("bci", bci); - args.add("targetBci", targetBci); - - SnippetTemplate template = template(profileNode, args); - template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); - } else if (profileNode instanceof ProfileInvokeNode) { - ProfileInvokeNode profileInvokeNode = (ProfileInvokeNode) profileNode; - // Method invocation event - Arguments args = new Arguments(profileMethodEntry, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("counters", counters); - args.add("step", step); - args.add("stepLog", stepLog); - args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog()); - SnippetTemplate template = template(profileNode, args); - template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); - } else { - throw new GraalError("Unsupported profile node type: " + profileNode); - } - - assert profileNode.hasNoUsages(); - if (!profileNode.isDeleted()) { - GraphUtil.killWithUnusedFloatingInputs(profileNode); - } - } - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallSnippets.java index a094ee5f5890..b1446eedad72 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallSnippets.java @@ -38,7 +38,7 @@ import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.DeoptimizeCallerNode; -import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; +import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.PiNode; @@ -87,15 +87,15 @@ public static void handlePendingException(Word thread, boolean shouldClearExcept */ @Snippet public static Object verifyObject(Object object) { - if (GraalHotSpotVMConfigNode.verifyOops()) { - Word verifyOopCounter = WordFactory.unsigned(GraalHotSpotVMConfigNode.verifyOopCounterAddress()); + if (HotSpotReplacementsUtil.verifyOops(INJECTED_VMCONFIG)) { + Word verifyOopCounter = WordFactory.unsigned(HotSpotReplacementsUtil.verifyOopCounterAddress(INJECTED_VMCONFIG)); verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1); Pointer oop = Word.objectToTrackedPointer(object); if (object != null) { GuardingNode anchorNode = SnippetAnchorNode.anchor(); // make sure object is 'reasonable' - if (!oop.and(WordFactory.unsigned(GraalHotSpotVMConfigNode.verifyOopMask())).equal(WordFactory.unsigned(GraalHotSpotVMConfigNode.verifyOopBits()))) { + if (!oop.and(WordFactory.unsigned(HotSpotReplacementsUtil.verifyOopMask(INJECTED_VMCONFIG))).equal(WordFactory.unsigned(HotSpotReplacementsUtil.verifyOopBits(INJECTED_VMCONFIG)))) { fatal("oop not in heap: %p", oop.rawValue()); } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java index d7aa77d32cb0..289f6a4a250b 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java @@ -25,7 +25,6 @@ package org.graalvm.compiler.hotspot.stubs; import static org.graalvm.compiler.core.GraalCompiler.emitFrontEnd; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; import static org.graalvm.compiler.debug.DebugOptions.DebugStubsAndSnippets; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP; @@ -198,8 +197,6 @@ public synchronized InstalledCode getCode(final Backend backend) { try (DebugContext.Scope s = debug.scope("CodeInstall", compResult); DebugContext.Activation a = debug.activate()) { assert destroyedCallerRegisters != null; - // Add a GeneratePIC check here later, we don't want to install - // code if we don't have a corresponding VM global symbol. HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult, options); code = codeCache.installCode(null, compiledCode, null, null, false); } catch (Throwable e) { @@ -219,7 +216,7 @@ public synchronized InstalledCode getCode(final Backend backend) { private CompilationResult buildCompilationResult(DebugContext debug, final Backend backend) { CompilationIdentifier compilationId = getStubCompilationId(); final StructuredGraph graph = getGraph(debug, compilationId); - CompilationResult compResult = new CompilationResult(compilationId, toString(), GeneratePIC.getValue(options)); + CompilationResult compResult = new CompilationResult(compilationId, toString()); // Stubs cannot be recompiled so they cannot be compiled with assumptions assert graph.getAssumptions() == null; diff --git a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index 3eda28121872..2abb4da4d865 100644 --- a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -243,7 +243,6 @@ import static org.graalvm.compiler.bytecode.Bytecodes.TABLESWITCH; import static org.graalvm.compiler.bytecode.Bytecodes.nameOf; import static org.graalvm.compiler.core.common.GraalOptions.DeoptALot; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; import static org.graalvm.compiler.core.common.GraalOptions.PrintProfilingInformation; import static org.graalvm.compiler.core.common.GraalOptions.StressExplicitExceptionCode; @@ -409,9 +408,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; -import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; import org.graalvm.compiler.nodes.java.FinalFieldBarrierNode; @@ -1122,12 +1119,6 @@ protected void build(FixedWithNextNode startInstruction, FrameStateBuilder start genMonitorEnter(methodSynchronizedObject, bci()); } - ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - FrameState stateBefore = createCurrentFrameState(); - profilingPlugin.profileInvoke(this, method, stateBefore); - } - genInfoPointNode(InfopointReason.METHOD_START, null); } @@ -1487,12 +1478,6 @@ protected ValueNode genZeroExtend(ValueNode input, int bitCount) { } protected void genGoto() { - ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - FrameState stateBefore = createCurrentFrameState(); - int targetBci = currentBlock.getSuccessor(0).startBci; - profilingPlugin.profileGoto(this, method, bci(), targetBci, stateBefore); - } appendGoto(currentBlock.getSuccessor(0)); assert currentBlock.numNormalSuccessors() == 1; } @@ -1742,40 +1727,14 @@ protected void genInvokeVirtual(ResolvedJavaMethod resolvedTarget) { private boolean genDynamicInvokeHelper(ResolvedJavaMethod target, int cpi, int opcode) { assert opcode == INVOKEDYNAMIC || opcode == INVOKEVIRTUAL; - InvokeDynamicPlugin invokeDynamicPlugin = graphBuilderConfig.getPlugins().getInvokeDynamicPlugin(); - - if (opcode == INVOKEVIRTUAL && invokeDynamicPlugin != null && !invokeDynamicPlugin.isResolvedDynamicInvoke(this, cpi, opcode)) { - // regular invokevirtual, let caller handle it - return false; - } - - if (GeneratePIC.getValue(options) && (invokeDynamicPlugin == null || !invokeDynamicPlugin.supportsDynamicInvoke(this, cpi, opcode))) { - // bail out if static compiler and no dynamic type support - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - return true; - } - JavaConstant appendix = constantPool.lookupAppendix(cpi, opcode); ValueNode appendixNode = null; if (appendix != null) { - if (invokeDynamicPlugin != null) { - invokeDynamicPlugin.recordDynamicMethod(this, cpi, opcode, target); - - // Will perform runtime type checks and static initialization - FrameState stateBefore = createCurrentFrameState(); - appendixNode = invokeDynamicPlugin.genAppendixNode(this, cpi, opcode, appendix, stateBefore); - } else { - appendixNode = ConstantNode.forConstant(appendix, getMetaAccess(), graph); - } + appendixNode = ConstantNode.forConstant(appendix, getMetaAccess(), graph); frameState.push(JavaKind.Object, appendixNode); - } else if (GeneratePIC.getValue(options)) { - // Need to emit runtime guard and perform static initialization. - // Not implemented yet. - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - return true; } boolean hasReceiver = (opcode == INVOKEDYNAMIC) ? false : !target.isStatic(); @@ -3672,11 +3631,6 @@ protected void genIf(LogicNode conditionInput, BciBlock trueBlockInput, BciBlock BciBlock falseBlock = falseBlockInput; LogicNode condition = conditionInput; BranchProbabilityData profileData = originalProfileData; - FrameState stateBefore = null; - ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - stateBefore = createCurrentFrameState(); - } // Remove a logic negation node. if (condition instanceof LogicNegationNode) { @@ -3714,9 +3668,6 @@ protected void genIf(LogicNode conditionInput, BciBlock trueBlockInput, BciBlock } boolean negated = deoptBlock == trueBlock; if (!isPotentialCountedLoopExit(condition, deoptBlock)) { - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - profilingPlugin.profileGoto(this, method, bci(), noDeoptBlock.startBci, stateBefore); - } append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, negated, survivingSuccessorPosition)); appendGoto(noDeoptBlock); } else { @@ -3738,10 +3689,6 @@ protected void genIf(LogicNode conditionInput, BciBlock trueBlockInput, BciBlock return; } - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore); - } - int oldBci = stream.currentBCI(); int trueBlockInt = checkPositiveIntConstantPushed(trueBlock); if (trueBlockInt != -1) { @@ -3862,19 +3809,9 @@ private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, LogicN if (targetAtStart == Bytecodes.GOTO && nextBlock.getPredecessorCount() == 1) { // This is an empty block. Skip it. BciBlock successorBlock = nextBlock.successors.get(0); - ProfilingPlugin profilingPlugin = graphBuilderConfig.getPlugins().getProfilingPlugin(); - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - FrameState stateBefore = createCurrentFrameState(); - profilingPlugin.profileGoto(this, method, bci(), successorBlock.startBci, stateBefore); - } appendGoto(successorBlock); assert nextBlock.numNormalSuccessors() == 1; } else { - ProfilingPlugin profilingPlugin = graphBuilderConfig.getPlugins().getProfilingPlugin(); - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - FrameState stateBefore = createCurrentFrameState(); - profilingPlugin.profileGoto(this, method, bci(), nextBlock.startBci, stateBefore); - } appendGoto(nextBlock); } } @@ -4789,10 +4726,6 @@ private void genGetField(JavaField field, ValueNode receiverInput) { } private void genGetField(ResolvedJavaField resolvedField, ValueNode receiver) { - if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { - graph.recordField(resolvedField); - } - for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { if (plugin.handleLoadField(this, receiver, resolvedField)) { return; @@ -4886,10 +4819,6 @@ private void genPutField(JavaField field, ValueNode value) { ValueNode receiver = maybeEmitExplicitNullCheck(receiverInput); ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { - graph.recordField(resolvedField); - } - for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { if (plugin.handleStoreField(this, receiver, resolvedField, value)) { return; @@ -4916,10 +4845,6 @@ private void genGetStatic(JavaField field) { return; } - if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { - graph.recordField(resolvedField); - } - /* * Javac does not allow use of "$assertionsDisabled" for a field name but Eclipse does, in * which case a suffix is added to the generated field. @@ -5010,10 +4935,6 @@ protected void genPutStatic(JavaField field) { return; } - if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { - graph.recordField(resolvedField); - } - ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin(); ResolvedJavaType holder = resolvedField.getDeclaringClass(); if (classInitializationPlugin != null) { diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java index 087e3325af2d..2a9f6634db14 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java @@ -27,7 +27,6 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; @@ -208,16 +207,12 @@ public static void directCall(CompilationResultBuilder crb, AArch64MacroAssemble public static void directCall(CompilationResultBuilder crb, AArch64MacroAssembler masm, InvokeTarget callTarget, Register scratch, LIRFrameState info, Label label) { int before = masm.position(); if (scratch != null) { - if (GeneratePIC.getValue(crb.getOptions())) { - masm.bl(0); - } else { - /* - * Offset might not fit into a 28-bit immediate, generate an indirect call with a - * 64-bit immediate address which is fixed up by HotSpot. - */ - masm.movNativeAddress(scratch, 0L, true); - masm.blr(scratch); - } + /* + * Offset might not fit into a 28-bit immediate, generate an indirect call with a 64-bit + * immediate address which is fixed up by HotSpot. + */ + masm.movNativeAddress(scratch, 0L, true); + masm.blr(scratch); } else { // Address is fixed up by HotSpot. masm.bl(0); @@ -244,12 +239,8 @@ public static void indirectCall(CompilationResultBuilder crb, AArch64MacroAssemb public static void directJmp(CompilationResultBuilder crb, AArch64MacroAssembler masm, InvokeTarget callTarget) { try (AArch64MacroAssembler.ScratchRegister scratch = masm.getScratchRegister()) { int before = masm.position(); - if (GeneratePIC.getValue(crb.getOptions())) { - masm.jmp(); - } else { - masm.movNativeAddress(scratch.getRegister(), 0L); - masm.jmp(scratch.getRegister()); - } + masm.movNativeAddress(scratch.getRegister(), 0L); + masm.jmp(scratch.getRegister()); int after = masm.position(); crb.recordDirectCall(before, after, callTarget, null); masm.ensureUniquePC(); diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java index f2c3165df520..d68cc6521533 100755 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java @@ -33,7 +33,6 @@ import static jdk.vm.ci.code.ValueUtil.asStackSlot; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; @@ -64,7 +63,6 @@ import org.graalvm.compiler.lir.StandardOp.ValueMoveOp; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.code.MemoryBarriers; @@ -672,8 +670,8 @@ protected PointerCompressionOp(LIRInstructionClass ty protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register resultRegister = getResultRegister(); Register ptr = asRegister(getInput()); - Register base = getBaseRegister(crb); + Register base = getBaseRegister(); // result = (ptr - base) >> shift if (!encoding.hasBase()) { if (encoding.hasShift()) { @@ -759,7 +757,7 @@ private UncompressPointerOp(LIRInstructionClass protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register inputRegister = asRegister(getInput()); Register resultRegister = getResultRegister(); - Register base = encoding.hasBase() ? getBaseRegister(crb) : null; + Register base = encoding.hasBase() ? getBaseRegister() : null; // result = base + (ptr << shift) if (nonNull || base == null) { diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java index a4f19259ad29..77b3f11bf0f2 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java @@ -26,7 +26,6 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; @@ -196,7 +195,7 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { public static void directCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, InvokeTarget callTarget, Register scratch, boolean align, LIRFrameState info) { int before; - if (scratch != null && !GeneratePIC.getValue(crb.getOptions())) { + if (scratch != null) { assert !align; // offset might not fit a 32-bit immediate, generate an // indirect call with a 64-bit immediate @@ -215,7 +214,7 @@ public static void directCall(CompilationResultBuilder crb, AMD64MacroAssembler public static void directJmp(CompilationResultBuilder crb, AMD64MacroAssembler masm, InvokeTarget target, Register scratch) { int before; - if (scratch != null && !GeneratePIC.getValue(crb.getOptions())) { + if (scratch != null) { // offset might not fit a 32-bit immediate, generate an // indirect call with a 64-bit immediate before = masm.directJmp(0L, scratch); diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java index ce51b09f38b7..d4e16ac76f4f 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java @@ -31,7 +31,6 @@ import static jdk.vm.ci.code.ValueUtil.isStackSlot; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag.Equal; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag.NotEqual; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; @@ -63,7 +62,6 @@ import org.graalvm.compiler.lir.StandardOp.ValueMoveOp; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -834,8 +832,8 @@ protected PointerCompressionOp(LIRInstructionClass @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - Register baseReg = getBaseRegister(crb); + Register baseReg = getBaseRegister(); int shift = getShift(); Register resReg = getResultRegister(); if (nonNull && !baseReg.equals(Register.None) && getInput() instanceof RegisterValue) { diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java index d8bab3b08f7e..aa238727d126 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java @@ -737,14 +737,10 @@ void recordMark(CompilationResult.CodeMark m) { } } - public CallContext openCallContext(boolean direct) { + public CallContext openCallContext() { if (currentCallContext != null) { throw GraalError.shouldNotReachHere("Call context already open"); } - // Currently only AOT requires call context information and only for direct calls. - if (compilationResult.isImmutablePIC() && direct) { - currentCallContext = new CallContext(); - } return currentCallContext; } diff --git a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java index 2e003bb1ec33..6436a169062a 100644 --- a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java +++ b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java @@ -466,9 +466,9 @@ protected final void emitCode() { int bytecodeSize = request.graph.method() == null ? 0 : request.graph.getBytecodeSize(); SpeculationLog speculationLog = null; request.compilationResult.setHasUnsafeAccess(request.graph.hasUnsafeAccess()); - LIRCompilerBackend.emitCode(request.backend, request.graph.getAssumptions(), request.graph.method(), request.graph.getMethods(), request.graph.getFields(), - speculationLog, bytecodeSize, lirGenRes, - request.compilationResult, request.installedCodeOwner, request.factory); + LIRCompilerBackend.emitCode(request.backend, request.graph.getAssumptions(), request.graph.method(), request.graph.getMethods(), speculationLog, + bytecodeSize, lirGenRes, request.compilationResult, + request.installedCodeOwner, request.factory); } protected StructuredGraph graph() { diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java index ea45cb8d368a..38d05fec7840 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java @@ -24,7 +24,6 @@ */ package org.graalvm.compiler.nodes; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; @@ -33,18 +32,18 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.calc.ConvertNode; import org.graalvm.compiler.nodes.calc.UnaryNode; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.type.StampTool; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.Value; /** @@ -125,11 +124,6 @@ public CompressEncoding getEncoding() { @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { if (forValue.isConstant()) { - if (GeneratePIC.getValue(tool.getOptions())) { - // We always want uncompressed constants - return this; - } - ConstantNode constant = (ConstantNode) forValue; return ConstantNode.forConstant(stamp(NodeView.DEFAULT), convert(constant.getValue(), tool.getConstantReflection()), constant.getStableDimension(), constant.isDefaultStable(), tool.getMetaAccess()); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java index 147b980f2a27..5783821b9dc4 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java @@ -26,11 +26,9 @@ import java.util.List; -import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.graph.NodeClass; import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -47,7 +45,6 @@ public class EncodedGraph { private final Assumptions assumptions; private final List inlinedMethods; private final boolean trackNodeSourcePosition; - private final EconomicSet fields; private final boolean hasUnsafeAccess; /** @@ -57,12 +54,11 @@ public class EncodedGraph { protected int[] nodeStartOffsets; public EncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass[] types, StructuredGraph sourceGraph) { - this(encoding, startOffset, objects, types, sourceGraph.getAssumptions(), sourceGraph.getMethods(), sourceGraph.getFields(), sourceGraph.hasUnsafeAccess(), - sourceGraph.trackNodeSourcePosition()); + this(encoding, startOffset, objects, types, sourceGraph.getAssumptions(), sourceGraph.getMethods(), sourceGraph.hasUnsafeAccess(), sourceGraph.trackNodeSourcePosition()); } public EncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass[] types, Assumptions assumptions, List inlinedMethods, - EconomicSet fields, boolean hasUnsafeAccess, boolean trackNodeSourcePosition) { + boolean hasUnsafeAccess, boolean trackNodeSourcePosition) { this.encoding = encoding; this.startOffset = startOffset; this.objects = objects; @@ -70,7 +66,6 @@ public EncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClas this.assumptions = assumptions; this.inlinedMethods = inlinedMethods; this.trackNodeSourcePosition = trackNodeSourcePosition; - this.fields = fields; this.hasUnsafeAccess = hasUnsafeAccess; } @@ -110,10 +105,6 @@ public boolean trackNodeSourcePosition() { return trackNodeSourcePosition; } - public EconomicSet getFields() { - return fields; - } - public boolean hasUnsafeAccess() { return hasUnsafeAccess; } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 27e3a26e1b5f..4e0905ba1a90 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -39,7 +39,6 @@ import java.util.stream.Collectors; import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Equivalence; import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.api.replacements.MethodSubstitution; @@ -71,7 +70,6 @@ import jdk.vm.ci.meta.DefaultProfilingInfo; import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.ProfilingInfo; -import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.TriState; @@ -460,11 +458,6 @@ boolean implies(FrameStateVerificationFeature feature) { */ private final List methods; - /** - * Records the fields that were accessed while constructing this graph. - */ - private EconomicSet fields = null; - private enum UnsafeAccessState { NO_ACCESS, HAS_ACCESS, @@ -724,9 +717,6 @@ private StructuredGraph copy(String newName, ResolvedJavaMethod rootMethodForCop copy.setGuardsStage(getGuardsStage()); copy.stageFlags = EnumSet.copyOf(stageFlags); copy.trackNodeSourcePosition = trackNodeSourcePositionForCopy; - if (fields != null) { - copy.fields = createFieldSet(fields); - } EconomicMap replacements = EconomicMap.create(Equivalence.IDENTITY); replacements.put(start, copy.start); UnmodifiableEconomicMap duplicates; @@ -1111,15 +1101,6 @@ private boolean checkFrameStatesAgainstInlinedMethods() { return true; } - private static EconomicSet createFieldSet(EconomicSet init) { - // Multiple ResolvedJavaField objects can represent the same field so they - // need to be compared with equals(). - if (init != null) { - return EconomicSet.create(Equivalence.DEFAULT, init); - } - return EconomicSet.create(Equivalence.DEFAULT); - } - /** * Gets an unmodifiable view of the methods that were inlined while constructing this graph. */ @@ -1155,41 +1136,6 @@ public void updateMethods(StructuredGraph other) { } } - /** - * Gets an unmodifiable view of the fields that were accessed while constructing this graph. - * - * @return {@code null} if no field accesses were recorded - */ - public EconomicSet getFields() { - return fields; - } - - /** - * Records that {@code field} was accessed in this graph. - */ - public void recordField(ResolvedJavaField field) { - assert GraalOptions.GeneratePIC.getValue(getOptions()); - if (this.fields == null) { - this.fields = createFieldSet(null); - } - fields.add(field); - } - - /** - * Updates the {@linkplain #getFields() fields} of this graph with the accessed fields of - * another graph. - */ - public void updateFields(StructuredGraph other) { - assert this != other; - assert GraalOptions.GeneratePIC.getValue(getOptions()); - if (other.fields != null) { - if (this.fields == null) { - this.fields = createFieldSet(null); - } - this.fields.addAll(other.fields); - } - } - /** * Gets the input bytecode {@linkplain ResolvedJavaMethod#getCodeSize() size} from which this * graph is constructed. This ignores how many bytecodes in each constituent method are actually diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java index 0b58f353aadf..72eba3553023 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java @@ -24,7 +24,6 @@ */ package org.graalvm.compiler.nodes.calc; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import org.graalvm.compiler.core.common.PermanentBailoutException; @@ -223,7 +222,7 @@ protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider con } if (isConstantConversionSupported(convert, view, smallestCompareWidth)) { - ConstantNode newConstant = canonicalConvertConstant(constantReflection, metaAccess, options, condition, convert, constant, view); + ConstantNode newConstant = canonicalConvertConstant(constantReflection, metaAccess, condition, convert, constant, view); if (newConstant != null) { if (mirrored) { return duplicateModified(newConstant, convert.getValue(), unorderedIsTrue, view); @@ -253,15 +252,11 @@ private static boolean isConstantConversionSupported(ConvertNode convert, NodeVi return supported; } - private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, CanonicalCondition condition, - ConvertNode convert, Constant constant, NodeView view) { + private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, CanonicalCondition condition, ConvertNode convert, + Constant constant, NodeView view) { if (convert.preservesOrder(condition, constant, constantReflection)) { Constant reverseConverted = convert.reverse(constant, constantReflection); if (reverseConverted != null && convert.convert(reverseConverted, constantReflection).equals(constant)) { - if (GeneratePIC.getValue(options)) { - // We always want uncompressed constants - return null; - } return ConstantNode.forConstant(convert.getValue().stamp(view), reverseConverted, metaAccess); } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubNode.java index 810d0e748d20..d45628666477 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubNode.java @@ -24,7 +24,6 @@ */ package org.graalvm.compiler.nodes.extended; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; @@ -91,36 +90,30 @@ public LoadHubNode(Stamp stamp, ValueNode value) { @Override public ValueNode canonical(CanonicalizerTool tool) { - if (!GeneratePIC.getValue(tool.getOptions())) { - NodeView view = NodeView.from(tool); - MetaAccessProvider metaAccess = tool.getMetaAccess(); - ValueNode curValue = getValue(); - ValueNode newNode = findSynonym(curValue, stamp(view), metaAccess, tool.getConstantReflection()); - if (newNode != null) { - return newNode; - } + NodeView view = NodeView.from(tool); + MetaAccessProvider metaAccess = tool.getMetaAccess(); + ValueNode curValue = getValue(); + ValueNode newNode = findSynonym(curValue, stamp(view), metaAccess, tool.getConstantReflection()); + if (newNode != null) { + return newNode; } return this; } public static ValueNode findSynonym(ValueNode curValue, Stamp stamp, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { - if (!GeneratePIC.getValue(curValue.getOptions())) { - TypeReference type = StampTool.typeReferenceOrNull(curValue); - if (type != null && type.isExact()) { - return ConstantNode.forConstant(stamp, constantReflection.asObjectHub(type.getType()), metaAccess); - } + TypeReference type = StampTool.typeReferenceOrNull(curValue); + if (type != null && type.isExact()) { + return ConstantNode.forConstant(stamp, constantReflection.asObjectHub(type.getType()), metaAccess); } return null; } @Override public void virtualize(VirtualizerTool tool) { - if (!GeneratePIC.getValue(tool.getOptions())) { - ValueNode alias = tool.getAlias(getValue()); - TypeReference type = StampTool.typeReferenceOrNull(alias); - if (type != null && type.isExact()) { - tool.replaceWithValue(ConstantNode.forConstant(stamp(NodeView.DEFAULT), tool.getConstantReflection().asObjectHub(type.getType()), tool.getMetaAccess(), graph())); - } + ValueNode alias = tool.getAlias(getValue()); + TypeReference type = StampTool.typeReferenceOrNull(alias); + if (type != null && type.isExact()) { + tool.replaceWithValue(ConstantNode.forConstant(stamp(NodeView.DEFAULT), tool.getConstantReflection().asObjectHub(type.getType()), tool.getMetaAccess(), graph())); } } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubOrNullNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubOrNullNode.java index 40d71ad59aa2..7f509542d73c 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubOrNullNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubOrNullNode.java @@ -24,7 +24,6 @@ */ package org.graalvm.compiler.nodes.extended; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; @@ -91,14 +90,12 @@ public LoadHubOrNullNode(Stamp stamp, ValueNode value) { @Override public ValueNode canonical(CanonicalizerTool tool) { - if (!GeneratePIC.getValue(tool.getOptions())) { - NodeView view = NodeView.from(tool); - MetaAccessProvider metaAccess = tool.getMetaAccess(); - ValueNode curValue = getValue(); - ValueNode newNode = findSynonym(curValue, (AbstractPointerStamp) stamp(view), metaAccess, tool.getConstantReflection()); - if (newNode != null) { - return newNode; - } + NodeView view = NodeView.from(tool); + MetaAccessProvider metaAccess = tool.getMetaAccess(); + ValueNode curValue = getValue(); + ValueNode newNode = findSynonym(curValue, (AbstractPointerStamp) stamp(view), metaAccess, tool.getConstantReflection()); + if (newNode != null) { + return newNode; } return this; } @@ -112,12 +109,10 @@ public static ValueNode findSynonym(ValueNode curValue, AbstractPointerStamp sta @Override public void virtualize(VirtualizerTool tool) { - if (!GeneratePIC.getValue(tool.getOptions())) { - ValueNode alias = tool.getAlias(getValue()); - TypeReference type = StampTool.typeReferenceOrNull(alias); - if (type != null && type.isExact()) { - tool.replaceWithValue(ConstantNode.forConstant(stamp(NodeView.DEFAULT), tool.getConstantReflection().asObjectHub(type.getType()), tool.getMetaAccess(), graph())); - } + ValueNode alias = tool.getAlias(getValue()); + TypeReference type = StampTool.typeReferenceOrNull(alias); + if (type != null && type.isExact()) { + tool.replaceWithValue(ConstantNode.forConstant(stamp(NodeView.DEFAULT), tool.getConstantReflection().asObjectHub(type.getType()), tool.getMetaAccess(), graph())); } } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java index 4bf7c471c24e..97660444bc13 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java @@ -42,8 +42,6 @@ public static class Plugins { private TypePlugin[] typePlugins; private InlineInvokePlugin[] inlineInvokePlugins; private ClassInitializationPlugin classInitializationPlugin; - private InvokeDynamicPlugin invokeDynamicPlugin; - private ProfilingPlugin profilingPlugin; /** * Creates a copy of a given set of plugins. The {@link InvocationPlugins} in @@ -57,8 +55,6 @@ public Plugins(Plugins copyFrom, InvocationPlugins invocationPlugins) { this.typePlugins = copyFrom.typePlugins; this.inlineInvokePlugins = copyFrom.inlineInvokePlugins; this.classInitializationPlugin = copyFrom.classInitializationPlugin; - this.invokeDynamicPlugin = copyFrom.invokeDynamicPlugin; - this.profilingPlugin = copyFrom.profilingPlugin; } public Plugins(Plugins copyFrom) { @@ -167,22 +163,6 @@ public void setClassInitializationPlugin(ClassInitializationPlugin plugin) { this.classInitializationPlugin = plugin; } - public InvokeDynamicPlugin getInvokeDynamicPlugin() { - return invokeDynamicPlugin; - } - - public void setInvokeDynamicPlugin(InvokeDynamicPlugin plugin) { - this.invokeDynamicPlugin = plugin; - } - - public ProfilingPlugin getProfilingPlugin() { - return profilingPlugin; - } - - public void setProfilingPlugin(ProfilingPlugin plugin) { - this.profilingPlugin = plugin; - } - public StampPair getOverridingStamp(GraphBuilderTool b, JavaType type, boolean nonNull) { for (TypePlugin plugin : getTypePlugins()) { StampPair stamp = plugin.interceptType(b, type, nonNull); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvokeDynamicPlugin.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvokeDynamicPlugin.java deleted file mode 100644 index 11ebe26e02b3..000000000000 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvokeDynamicPlugin.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2017, 2018, 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 org.graalvm.compiler.nodes.graphbuilderconf; - -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.ValueNode; - -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.JavaConstant; - -/** - * {@link GraphBuilderPlugin} interface for static compilation mode, allowing references to dynamic - * types. - */ -public interface InvokeDynamicPlugin extends GraphBuilderPlugin { - - /** - * Checks for a resolved dynamic adapter method at the specified index, resulting from either a - * resolved invokedynamic or invokevirtual on a signature polymorphic MethodHandle method - * (HotSpot invokehandle). - * - * @param builder context for the invoke - * @param cpi the constant pool index - * @param opcode the opcode of the instruction for which the lookup is being performed - * @return {@code true} if a signature polymorphic method reference was found, otherwise - * {@code false} - */ - boolean isResolvedDynamicInvoke(GraphBuilderContext builder, int cpi, int opcode); - - /** - * Checks if this plugin instance supports the specified dynamic invoke. - * - * @param builder context for the invoke - * @param cpi the constant pool index - * @param opcode the opcode of the invoke instruction - * @return {@code true} if this dynamic invoke is supported - */ - boolean supportsDynamicInvoke(GraphBuilderContext builder, int cpi, int opcode); - - /** - * Notifies this object of the value and context of the dynamic method target (e.g., A HotSpot - * adapter method) for a resolved dynamic invoke. - * - * @param builder context for the invoke - * @param cpi the constant pool index - * @param opcode the opcode of the instruction for which the lookup is being performed - * @param target dynamic target method to record - */ - void recordDynamicMethod(GraphBuilderContext builder, int cpi, int opcode, ResolvedJavaMethod target); - - /** - * Notifies this object of the value and context of the dynamic appendix object for a resolved - * dynamic invoke. - * - * @param builder context for the invoke - * @param cpi the constant pool index - * @param opcode the opcode of the instruction for which the lookup is being performed - * @return {@link ValueNode} for appendix constant - */ - ValueNode genAppendixNode(GraphBuilderContext builder, int cpi, int opcode, JavaConstant appendix, FrameState frameState); - -} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/ProfilingPlugin.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/ProfilingPlugin.java deleted file mode 100644 index e1e132fd5712..000000000000 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/ProfilingPlugin.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2015, 2018, 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 org.graalvm.compiler.nodes.graphbuilderconf; - -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.LogicNode; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public interface ProfilingPlugin extends GraphBuilderPlugin { - boolean shouldProfile(GraphBuilderContext builder, ResolvedJavaMethod method); - - void profileInvoke(GraphBuilderContext builder, ResolvedJavaMethod method, FrameState frameState); - - void profileGoto(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, int targetBci, FrameState frameState); - - void profileIf(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, LogicNode condition, int trueBranchBci, int falseBranchBci, FrameState frameState); - -} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java index a4acb314df7f..c5de8e936b28 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java @@ -25,8 +25,6 @@ //JaCoCo Exclude package org.graalvm.compiler.nodes.java; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; - import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; @@ -100,11 +98,6 @@ public JavaKind getKnownElementKind() { @Override public Node canonical(CanonicalizerTool tool) { if (elementType.isConstant()) { - if (GeneratePIC.getValue(tool.getOptions())) { - // Can't fold for AOT, because the resulting NewArrayNode will be missing its - // ResolveConstantNode for the array class. - return this; - } ResolvedJavaType type = tool.getConstantReflection().asJavaType(elementType.asConstant()); if (type != null && !throwsIllegalArgumentException(type) && tool.getMetaAccessExtensionProvider().canConstantFoldDynamicAllocation(type.getArrayClass())) { return createNewArrayNode(type); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewInstanceNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewInstanceNode.java index 54e370269fe7..b8b47e310c48 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewInstanceNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewInstanceNode.java @@ -24,8 +24,6 @@ */ package org.graalvm.compiler.nodes.java; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; - import java.lang.reflect.Modifier; import org.graalvm.compiler.core.common.type.ObjectStamp; @@ -64,11 +62,6 @@ public ValueNode getInstanceType() { public static boolean canConvertToNonDynamic(ValueNode clazz, CanonicalizerTool tool) { if (clazz.isConstant()) { - if (GeneratePIC.getValue(tool.getOptions())) { - // Can't fold for AOT, because the resulting NewInstanceNode will be missing its - // InitializeKlassNode. - return false; - } ResolvedJavaType type = tool.getConstantReflection().asJavaType(clazz.asConstant()); if (type != null && !throwsInstantiationException(type, tool.getMetaAccess()) && tool.getMetaAccessExtensionProvider().canConstantFoldDynamicAllocation(type)) { return true; diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java index 0da6acbe0091..b9d984fc8035 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java @@ -41,7 +41,6 @@ import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; @@ -624,11 +623,6 @@ private static ValueNode finishInlining(Invoke invoke, StructuredGraph graph, Fi // Copy inlined methods from inlinee to caller graph.updateMethods(inlineGraph); - // Update the set of accessed fields - if (GraalOptions.GeneratePIC.getValue(graph.getOptions())) { - graph.updateFields(inlineGraph); - } - if (inlineGraph.hasUnsafeAccess()) { graph.markUnsafeAccess(); } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java index 1a83d8f51e9e..5c726a6b1de4 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java @@ -822,11 +822,6 @@ private void recordGraphElements(EncodedGraph encodedGraph) { } else { assert inlinedAssumptions == null : String.format("cannot inline graph (%s) which makes assumptions into a graph (%s) that doesn't", encodedGraph, graph); } - if (encodedGraph.getFields() != null) { - for (ResolvedJavaField field : encodedGraph.getFields()) { - graph.recordField(field); - } - } if (encodedGraph.hasUnsafeAccess()) { graph.markUnsafeAccess(); } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index 714b24388bd8..f553c5da39b3 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -884,12 +884,7 @@ protected SnippetTemplate(OptionValues options, DebugContext debug, final Provid fallbackInvoke = fallbackInvokes.get(0); } - CanonicalizerPhase canonicalizer; - if (GraalOptions.ImmutableCode.getValue(snippetCopy.getOptions())) { - canonicalizer = CanonicalizerPhase.createWithoutReadCanonicalization(); - } else { - canonicalizer = CanonicalizerPhase.create(); - } + CanonicalizerPhase canonicalizer = CanonicalizerPhase.create(); /*- * Mirror the behavior of normal compilations here (without aggressive optimizations @@ -1192,12 +1187,7 @@ public static void explodeLoops(final StructuredGraph snippetCopy, CoreProviders if (loopBegin != null) { LoopEx loop = providers.getLoopsDataProvider().getLoopsData(snippetCopy).loop(loopBegin); Mark mark = snippetCopy.getMark(); - CanonicalizerPhase canonicalizer = null; - if (GraalOptions.ImmutableCode.getValue(snippetCopy.getOptions())) { - canonicalizer = CanonicalizerPhase.createWithoutReadCanonicalization(); - } else { - canonicalizer = CanonicalizerPhase.create(); - } + CanonicalizerPhase canonicalizer = CanonicalizerPhase.create(); try { LoopTransformations.fullUnroll(loop, providers, canonicalizer); } catch (RetryableBailoutException e) { diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index 3aa0459427d2..52c8b0d31684 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -25,7 +25,6 @@ package org.graalvm.compiler.replacements.arraycopy; import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.DEOPT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; @@ -517,10 +516,6 @@ public void lower(ArrayCopyNode arraycopy, boolean mayExpandThisArraycopy, Lower snippetInfo = delayedGenericArraycopySnippet; // no need for additional type check to avoid duplicated work arrayTypeCheck = ArrayCopyTypeCheck.NO_ARRAY_TYPE_CHECK; - } else if (GeneratePIC.getValue(options)) { - // use generic copying for AOT compilation - snippetInfo = delayedGenericArraycopySnippet; - arrayTypeCheck = ArrayCopyTypeCheck.NO_ARRAY_TYPE_CHECK; } else if (srcComponentType != null && destComponentType != null) { if (!srcComponentType.isPrimitive() && !destComponentType.isPrimitive()) { // it depends on the array content if the copy succeeds - we need diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/AssertionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/AssertionNode.java index 843449ab0437..98a25eb2bed7 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/AssertionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/AssertionNode.java @@ -27,7 +27,6 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; @@ -104,22 +103,13 @@ public Node canonical(CanonicalizerTool tool) { @Override public void lower(LoweringTool tool) { if (!compileTimeAssertion) { - if (GraalOptions.ImmutableCode.getValue(getOptions())) { - // Snippet assertions are disabled for AOT - graph().removeFixed(this); - } else { - tool.getLowerer().lower(this, tool); - } + tool.getLowerer().lower(this, tool); } } @Override public void generate(NodeLIRBuilderTool generator) { assert compileTimeAssertion; - if (GraalOptions.ImmutableCode.getValue(getOptions())) { - // Snippet assertions are disabled for AOT - return; - } if (condition.isConstant()) { if (condition.asJavaConstant().asInt() == 0) { throw new GraalError("%s: failed compile-time assertion: %s", this, message); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/IdentityHashCodeNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/IdentityHashCodeNode.java index b2804437f2c4..1e95f7a8a239 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/IdentityHashCodeNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/IdentityHashCodeNode.java @@ -24,8 +24,6 @@ */ package org.graalvm.compiler.replacements.nodes; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; @@ -76,9 +74,6 @@ public Node canonical(CanonicalizerTool tool) { if (object.isConstant()) { assert object.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp; JavaConstant c = (JavaConstant) object.asConstant(); - if (ImmutableCode.getValue(tool.getOptions())) { - return this; - } int identityHashCode; if (c.isNull()) { diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.amd64/src/org/graalvm/compiler/truffle/compiler/hotspot/amd64/AMD64TruffleCallBoundaryInstrumentationFactory.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.amd64/src/org/graalvm/compiler/truffle/compiler/hotspot/amd64/AMD64TruffleCallBoundaryInstrumentationFactory.java index 1609955b730a..94f310b3d837 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.amd64/src/org/graalvm/compiler/truffle/compiler/hotspot/amd64/AMD64TruffleCallBoundaryInstrumentationFactory.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.amd64/src/org/graalvm/compiler/truffle/compiler/hotspot/amd64/AMD64TruffleCallBoundaryInstrumentationFactory.java @@ -80,7 +80,7 @@ protected void injectTailCallCode(int installedCodeOffset, int entryPointOffset) masm.movl(spillRegister, new AMD64Address(thisRegister, installedCodeOffset), true); assert masm.position() - pos >= AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; CompressEncoding encoding = config.getOopEncoding(); - Register heapBaseRegister = AMD64Move.UncompressPointerOp.hasBase(options, encoding) ? registers.getHeapBaseRegister() : Register.None; + Register heapBaseRegister = AMD64Move.UncompressPointerOp.hasBase(encoding) ? registers.getHeapBaseRegister() : Register.None; AMD64Move.UncompressPointerOp.emitUncompressCode(masm, spillRegister, encoding.getShift(), heapBaseRegister, true); } else { // First instruction must be at least 5 bytes long to be safe for diff --git a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java index 27dc89fc5e69..f710a2bccc67 100755 --- a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java @@ -901,7 +901,7 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { masm.adrpLdr(srcSize, resultReg, resultReg); } if (!constant.isCompressed()) { // the result is expected to be uncompressed - Register baseReg = getBaseRegister(crb); + Register baseReg = getBaseRegister(); assert !baseReg.equals(Register.None) || getShift() != 0 : "no compression in place"; masm.add(64, resultReg, baseReg, resultReg, ShiftType.LSL, getShift()); } diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java index d0c1672bf8c4..2d87bba507d3 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java @@ -983,7 +983,7 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { } } if (!constant.isCompressed()) { // the result is expected to be uncompressed - Register baseReg = getBaseRegister(crb); + Register baseReg = getBaseRegister(); boolean preserveFlagsRegister = true; emitUncompressWithBaseRegister(masm, resultReg, baseReg, getShift(), preserveFlagsRegister); } diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java index 0b2ea1f335e3..a1ca1fbd62c6 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java @@ -160,7 +160,6 @@ private static void setCompilationResultMethod(CompilationResult result, Structu ResolvedJavaMethod rootMethod = graph.method(); if (rootMethod != null) { result.setMethods(rootMethod, graph.getMethods()); - result.setFields(graph.getFields()); } result.setHasUnsafeAccess(graph.hasUnsafeAccess()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java index 0a7f1ddde179..d2d9d7e69566 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java @@ -211,7 +211,7 @@ public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), snippetReflection); } - EncodedGraph encodedGraph = new EncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, null, null, null, false, trackNodeSourcePosition); + EncodedGraph encodedGraph = new EncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, null, null, false, trackNodeSourcePosition); try (DebugContext debug = openDebugContext("SVMSnippet_", method, options)) { StructuredGraph result = new StructuredGraph.Builder(options, debug).method(method).trackNodeSourcePosition(trackNodeSourcePosition).setIsSubstitution(true).build(); PEGraphDecoder graphDecoder = new PEGraphDecoder(ConfigurationValues.getTarget().arch, result, providers, null, snippetInvocationPlugins, new InlineInvokePlugin[0], parameterPlugin, null, diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/GraalSupport.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/GraalSupport.java index 1c99945a3aa9..94af62be2e31 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/GraalSupport.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/GraalSupport.java @@ -293,7 +293,7 @@ public static EncodedGraph encodedGraph(SharedRuntimeMethod method, boolean trac if (startOffset == -1) { return null; } - return new EncodedGraph(get().graphEncoding, startOffset, get().graphObjects, get().graphNodeTypes, null, null, null, false, trackNodeSourcePosition); + return new EncodedGraph(get().graphEncoding, startOffset, get().graphObjects, get().graphNodeTypes, null, null, false, trackNodeSourcePosition); } public static StructuredGraph decodeGraph(DebugContext debug, String name, CompilationIdentifier compilationId, SharedRuntimeMethod method) { diff --git a/vm/mx.vm/mx_vm_gate.py b/vm/mx.vm/mx_vm_gate.py index 8f40d9227e61..6bdd62cb4542 100644 --- a/vm/mx.vm/mx_vm_gate.py +++ b/vm/mx.vm/mx_vm_gate.py @@ -96,49 +96,49 @@ def gate_body(args, tasks): '-jar', mx.library('DACAPO').get_path(True), 'avrora', '-n', '1']) # Ensure that fatal errors in libgraal route back to HotSpot - try: - vmargs = ['-XX:+UseJVMCICompiler', - '-XX:+UseJVMCINativeLibrary', - '-XX:+PrintFlagsFinal', - '-Dlibgraal.CrashAt=length,hashCode', - '-Dlibgraal.CrashAtIsFatal=true'] - cmd = ["dacapo:avrora", "--tracker=none", "--"] + vmargs + ["--", "--preserve"] - out = mx.OutputCapture() - exitcode, bench_suite, _ = mx_benchmark.gate_mx_benchmark(cmd, nonZeroIsFatal=False, out=out, err=out) - if exitcode == 0: - if 'CrashAtIsFatal: no fatalError function pointer installed' in out.data: - # Executing a VM that does not configure fatal errors handling - # in libgraal to route back through the VM. - pass - else: - mx.abort('Expected following benchmark to result in non-zero exit code: ' + ' '.join(cmd)) + vmargs = ['-XX:+UseJVMCICompiler', + '-XX:+UseJVMCINativeLibrary', + '-XX:+PrintFlagsFinal', + '-Dlibgraal.CrashAt=length,hashCode', + '-Dlibgraal.CrashAtIsFatal=true'] + cmd = ["dacapo:avrora", "--tracker=none", "--"] + vmargs + ["--", "--preserve"] + out = mx.OutputCapture() + exitcode, bench_suite, _ = mx_benchmark.gate_mx_benchmark(cmd, nonZeroIsFatal=False, out=out, err=out) + if exitcode == 0: + if 'CrashAtIsFatal: no fatalError function pointer installed' in out.data: + # Executing a VM that does not configure fatal errors handling + # in libgraal to route back through the VM. + pass else: - if len(bench_suite.scratchDirs()) == 0: - mx.abort("No scratch dir found despite error being expected!") - latest_scratch_dir = bench_suite.scratchDirs()[-1] - seen_libjvmci_log = False - hs_errs = glob.glob(join(latest_scratch_dir, 'hs_err_pid*.log')) - if not hs_errs: - mx.abort('Expected a file starting with "hs_err_pid" in test directory. Entries found=' + str(listdir(latest_scratch_dir))) - for hs_err in hs_errs: - mx.log("Verifying content of {}".format(join(latest_scratch_dir, hs_err))) - with open(join(latest_scratch_dir, hs_err)) as fp: - contents = fp.read() - if 'libjvmci' in hs_err: - seen_libjvmci_log = True - if 'Fatal error: Forced crash' not in contents: - mx.abort('Expected "Fatal error: Forced crash" to be in contents of ' + hs_err + ':' + linesep + contents) - else: - if 'Fatal error in JVMCI' not in contents: - mx.abort('Expected "Fatal error in JVMCI" to be in contents of ' + hs_err + ':' + linesep + contents) + mx.abort('Expected following benchmark to result in non-zero exit code: ' + ' '.join(cmd)) + else: + if len(bench_suite.scratchDirs()) == 0: + mx.abort("No scratch dir found despite error being expected!") + latest_scratch_dir = bench_suite.scratchDirs()[-1] + seen_libjvmci_log = False + hs_errs = glob.glob(join(latest_scratch_dir, 'hs_err_pid*.log')) + if not hs_errs: + mx.abort('Expected a file starting with "hs_err_pid" in test directory. Entries found=' + str(listdir(latest_scratch_dir))) + + for hs_err in hs_errs: + mx.log("Verifying content of {}".format(join(latest_scratch_dir, hs_err))) + with open(join(latest_scratch_dir, hs_err)) as fp: + contents = fp.read() + if 'libjvmci' in hs_err: + seen_libjvmci_log = True + if 'Fatal error: Forced crash' not in contents: + mx.abort('Expected "Fatal error: Forced crash" to be in contents of ' + hs_err + ':' + linesep + contents) + else: + if 'Fatal error in JVMCI' not in contents: + mx.abort('Expected "Fatal error in JVMCI" to be in contents of ' + hs_err + ':' + linesep + contents) - if 'JVMCINativeLibraryErrorFile' in out.data and not seen_libjvmci_log: - mx.abort('Expected a file matching "hs_err_pid*_libjvmci.log" in test directory. Entries found=' + str(listdir(latest_scratch_dir))) + if 'JVMCINativeLibraryErrorFile' in out.data and not seen_libjvmci_log: + mx.abort('Expected a file matching "hs_err_pid*_libjvmci.log" in test directory. Entries found=' + str(listdir(latest_scratch_dir))) - finally: - for scratch_dir in bench_suite.scratchDirs(): - mx.log("Cleaning up scratch dir after gate task completion: {}".format(scratch_dir)) - mx.rmtree(scratch_dir) + # Only clean up scratch dir on success + for scratch_dir in bench_suite.scratchDirs(): + mx.log("Cleaning up scratch dir after gate task completion: {}".format(scratch_dir)) + mx.rmtree(scratch_dir) with Task('LibGraal Compiler:CTW', tasks, tags=[VmGateTasks.libgraal]) as t: if t: From 7de65b0172eab29234b3ba675f0d2250a54b3bf1 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 7 Oct 2021 15:47:19 +0300 Subject: [PATCH 331/681] Follow Boris S. comment --- truffle/docs/TraversingCompilationQueue.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/truffle/docs/TraversingCompilationQueue.md b/truffle/docs/TraversingCompilationQueue.md index a8446eeea5a0..edc8d19a55b9 100644 --- a/truffle/docs/TraversingCompilationQueue.md +++ b/truffle/docs/TraversingCompilationQueue.md @@ -6,7 +6,7 @@ permalink: /graalvm-as-a-platform/language-implementation-framework/TraversingCo --- # Truffle Approach to the Compilation Queue -As of version 21.3.0 Truffle has a new approach to compilation queueing. +As of version 21.2.0 Truffle has a new approach to compilation queueing. This document gives motivation and an overview of this approach. ## What is a Compilation queue? @@ -70,7 +70,7 @@ This gives a priority boost to targets that are currently "very hot" when compar For performance reasons the weight for tasks is cached and reused for a period of 1ms. If the cached value is older than 1ms, it is recalculated. -The traversing compilation queue is on by default as of version 21.3.0 and can be disabled using `--engine.TraversingCompilationQueue=false`. +The traversing compilation queue is on by default as of version 21.2.0 and can be disabled using `--engine.TraversingCompilationQueue=false`. ## Dynamic Compilation Thresholds @@ -135,5 +135,5 @@ MinScale >|/ . . MinNormalLoad MaxNormalLoad ``` -The dynamic thresholds only work with the traversing compilation queue and are on by default as of version 21.3.0. +The dynamic thresholds only work with the traversing compilation queue and are on by default as of version 21.2.0. They can be disabled with `--engine.DynamicCompilationThresholds=false`. From 76aae7fd114cd4a2cd42f1b089692314a36147d6 Mon Sep 17 00:00:00 2001 From: "thomas.garcia" Date: Thu, 7 Oct 2021 13:53:23 +0200 Subject: [PATCH 332/681] Cleanups and documentation --- .../espresso/runtime/EspressoContext.java | 2 +- .../runtime/EspressoShutdownHandler.java | 6 +- .../Target_java_lang_Thread.java | 18 +- .../substitutions/Target_sun_misc_Unsafe.java | 2 +- .../threads/EspressoThreadRegistry.java | 15 +- .../truffle/espresso/threads/KillStatus.java | 10 +- .../truffle/espresso/threads/SuspendLock.java | 74 ++++--- .../espresso/threads/ThreadsAccess.java | 192 ++++++++++++------ 8 files changed, 192 insertions(+), 127 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java index 623c999921d0..394b70910170 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java @@ -849,7 +849,7 @@ public void unregisterThread(StaticObject self) { } public void interruptThread(StaticObject guestThread) { - threadRegistry.interruptThread(guestThread); + threads.interruptThread(guestThread); } public void invalidateNoThreadStop(String message) { diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoShutdownHandler.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoShutdownHandler.java index 5106a102a7c7..2a475e3c3d08 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoShutdownHandler.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoShutdownHandler.java @@ -265,7 +265,7 @@ private void teardownPhase1(Thread initiatingThread) { if (t.isDaemon()) { context.getThreadAccess().stop(guest, null); } - threadManager.interruptThread(guest); + context.getThreadAccess().interruptThread(guest); } } } @@ -279,7 +279,7 @@ private void teardownPhase2(Thread initiatingThread) { Thread t = getThreadAccess().getHost(guest); if (t.isAlive() && t != initiatingThread) { context.getThreadAccess().stop(guest, null); - threadManager.interruptThread(guest); + context.getThreadAccess().interruptThread(guest); } } } @@ -299,7 +299,7 @@ private void teardownPhase3(Thread initiatingThread) { * all polyglot threads but should have. */ context.getThreadAccess().kill(guest); - threadManager.interruptThread(guest); + context.getThreadAccess().interruptThread(guest); } } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_Thread.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_Thread.java index d4f9d3954653..5fb155777a77 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_Thread.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_java_lang_Thread.java @@ -119,8 +119,7 @@ void doCached(@JavaType(Thread.class) StaticObject self, ThreadsAccess threadAccess = context.getThreadAccess(); if (context.multiThreadingEnabled()) { // Thread.start() is synchronized. - if (threadAccess.isStillborn(self)) { - threadAccess.terminateAndNotify(self); + if (threadAccess.terminateIfStillborn(self)) { return; } Thread hostThread = threadAccess.createJavaThread(self, threadExit, dispatchUncaught); @@ -176,9 +175,9 @@ public static void setPriority0(@JavaType(Thread.class) StaticObject self, int n } @Substitution(hasReceiver = true) - public static boolean isAlive(@JavaType(Thread.class) StaticObject self) { - int state = self.getKlass().getMeta().java_lang_Thread_threadStatus.getInt(self); - return state != State.NEW.value && state != State.TERMINATED.value; + public static boolean isAlive(@JavaType(Thread.class) StaticObject self, + @Inject EspressoContext context) { + return context.getThreadAccess().isAlive(self); } @Substitution(hasReceiver = true) @@ -236,7 +235,7 @@ public static void interrupt0(@JavaType(Object.class) StaticObject self, @Substitution public static void clearInterruptEvent(@Inject EspressoContext context) { - context.getThreadAccess().clearInterruptStatus(); + context.getThreadAccess().clearInterruptEvent(); } @TruffleBoundary @@ -259,10 +258,7 @@ public static void resume0(@JavaType(Object.class) StaticObject self, @Substitution(hasReceiver = true) public static void suspend0(@JavaType(Object.class) StaticObject toSuspend, @Inject EspressoContext context) { - toSuspend.getKlass().getContext().invalidateNoSuspend("Calling Thread.suspend()"); - if (!isAlive(toSuspend)) { - return; - } + context.invalidateNoSuspend("Calling Thread.suspend()"); context.getThreadAccess().suspend(toSuspend); } @@ -270,7 +266,7 @@ public static void suspend0(@JavaType(Object.class) StaticObject toSuspend, @Substitution(hasReceiver = true) public static void stop0(@JavaType(Object.class) StaticObject self, @JavaType(Object.class) StaticObject throwable, @Inject EspressoContext context) { - self.getKlass().getContext().invalidateNoThreadStop("Calling thread.stop()"); + context.invalidateNoThreadStop("Calling thread.stop()"); context.getThreadAccess().stop(self, throwable); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_misc_Unsafe.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_misc_Unsafe.java index 790628c488db..d93a4247f92d 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_misc_Unsafe.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_misc_Unsafe.java @@ -1417,7 +1417,7 @@ public static void parkBoundary(@SuppressWarnings("unused") @JavaType(Unsafe.cla @Substitution(hasReceiver = true) public static void unpark(@SuppressWarnings("unused") @JavaType(Unsafe.class) StaticObject self, @JavaType(Object.class) StaticObject thread, @Inject Meta meta) { - Thread hostThread = (Thread) meta.getThreadAccess().getHost(thread); + Thread hostThread = meta.getThreadAccess().getHost(thread); UnsafeAccess.getIfAllowed(meta).unpark(hostThread); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/EspressoThreadRegistry.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/EspressoThreadRegistry.java index 87d238c1993a..90c12cc69cf7 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/EspressoThreadRegistry.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/EspressoThreadRegistry.java @@ -35,15 +35,13 @@ import com.oracle.truffle.espresso.EspressoLanguage; import com.oracle.truffle.espresso.descriptors.Symbol; import com.oracle.truffle.espresso.impl.ContextAccess; -import com.oracle.truffle.espresso.impl.Method; import com.oracle.truffle.espresso.impl.SuppressFBWarnings; import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.runtime.EspressoContext; import com.oracle.truffle.espresso.runtime.StaticObject; -import com.oracle.truffle.espresso.substitutions.Target_java_lang_Thread; import com.oracle.truffle.espresso.vm.VM; -public class EspressoThreadRegistry implements ContextAccess { +public final class EspressoThreadRegistry implements ContextAccess { private static final int DEFAULT_THREAD_ARRAY_SIZE = 8; private final TruffleLogger logger = TruffleLogger.getLogger(EspressoLanguage.ID, EspressoThreadRegistry.class); @@ -180,7 +178,7 @@ public void unregisterThread(StaticObject thread) { } else { Object[] threads = guestThreads; int threadIndex = getThreadIndex(id, threads); - if (Target_java_lang_Thread.isAlive(thread)) { + if (getThreadAccess().isAlive(thread)) { assert threads[threadIndex] == thread; threads[threadIndex] = null; } else { @@ -370,7 +368,7 @@ private void refactorGuestThreads(int id, StaticObject self) { for (int i = 1; i < oldThreads.length; i++) { if (oldThreads[i] != null) { StaticObject guestThread = (StaticObject) oldThreads[i]; - if (Target_java_lang_Thread.isAlive(guestThread)) { + if (getThreadAccess().isAlive(guestThread)) { Thread hostThread = getThreadAccess().getHost(guestThread); int hostID = (int) hostThread.getId(); if (hostID < minID) { @@ -409,11 +407,4 @@ private void refactorGuestThreads(int id, StaticObject self) { private static int getThreadIndex(int id, Object[] threads) { return id - (int) threads[0]; } - - public void interruptThread(StaticObject guestThread) { - assert guestThread != null && getMeta().java_lang_Thread.isAssignableFrom(guestThread.getKlass()); - Method interruptMethod = guestThread.getKlass().vtableLookup(getMeta().java_lang_Thread_interrupt.getVTableIndex()); - assert interruptMethod != null; - interruptMethod.invokeDirect(guestThread); - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/KillStatus.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/KillStatus.java index e0a0fcc491ed..4dd766925ead 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/KillStatus.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/KillStatus.java @@ -33,17 +33,11 @@ public enum KillStatus { */ STOP, /** - * Was killed, but we are in context closing. If the thread is alive for a while in that state, - * it will be considered uncooperative. - */ - KILLED, - /** - * Was killed, and is calling Thread.exit(). Ignore further kill signals. + * Thread is terminated, and is calling Thread.exit(). Ignore further stop signals. */ EXITING, /** - * Thread is uncooperative: needs to be killed with a host exception. Very dangerous state to be - * in. + * Thread is uncooperative: needs to be killed with a host exception. Unrecoverable state. */ KILL } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/SuspendLock.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/SuspendLock.java index 4d89a4b15783..cf132c5e3494 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/SuspendLock.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/SuspendLock.java @@ -25,38 +25,64 @@ import com.oracle.truffle.espresso.runtime.StaticObject; -public class SuspendLock { - private Object handshakeLock = new Object() { +public final class SuspendLock { + private final Object handshakeLock = new Object() { }; + private final ThreadsAccess access; + private final StaticObject thread; private volatile boolean shouldSuspend; private volatile boolean threadSuspended; - public boolean shouldSuspend() { - return shouldSuspend; - } - - public boolean isSuspended() { - return threadSuspended; + public SuspendLock(ThreadsAccess access, StaticObject thread) { + this.access = access; + this.thread = thread; } - public void suspend(ThreadsAccess threads, StaticObject thread) { - if (threads.getHost(thread) == Thread.currentThread()) { + public void suspend() { + if (access.getHost(thread) == Thread.currentThread()) { // No need for handshake shouldSuspend = true; selfSuspend(); } else { - suspendHandshake(threads, thread); + suspendHandshake(); + } + } + + public synchronized void selfSuspend() { + while (shouldSuspend()) { + notifySuspended(); + try { + wait(); + } catch (InterruptedException e) { + /* spin back */ + } + } + threadSuspended = false; + } + + public synchronized void resume() { + if (shouldSuspend()) { + shouldSuspend = false; + notifyAll(); } } - private void suspendHandshake(ThreadsAccess threads, StaticObject thread) { + private boolean shouldSuspend() { + return shouldSuspend; + } + + private boolean isSuspended() { + return threadSuspended; + } + + private void suspendHandshake() { boolean wasInterrupted = false; while (!isSuspended()) { shouldSuspend = true; try { synchronized (handshakeLock) { - if (!threads.isAlive(thread)) { + if (!access.isAlive(thread)) { // If thread terminates, we don't want to wait forever handshakeLock.wait(100); } else { @@ -69,20 +95,9 @@ private void suspendHandshake(ThreadsAccess threads, StaticObject thread) { } } if (wasInterrupted) { - threads.getContext().interruptThread(threads.getContext().getCurrentThread()); - } - } - - public synchronized void selfSuspend() { - while (shouldSuspend()) { - notifySuspended(); - try { - wait(); - } catch (InterruptedException e) { - /* spin back */ - } + // Re-interrupt ourselves + Thread.currentThread().interrupt(); } - threadSuspended = false; } private void notifySuspended() { @@ -91,11 +106,4 @@ private void notifySuspended() { handshakeLock.notifyAll(); } } - - public synchronized void resume() { - if (shouldSuspend()) { - shouldSuspend = false; - notifyAll(); - } - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java index a9c8e7b2b388..ad36f951cd5c 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java @@ -25,13 +25,13 @@ import static com.oracle.truffle.espresso.threads.KillStatus.EXITING; import static com.oracle.truffle.espresso.threads.KillStatus.KILL; -import static com.oracle.truffle.espresso.threads.KillStatus.KILLED; import static com.oracle.truffle.espresso.threads.KillStatus.NORMAL; import static com.oracle.truffle.espresso.threads.KillStatus.STOP; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.espresso.impl.ContextAccess; +import com.oracle.truffle.espresso.impl.Method; import com.oracle.truffle.espresso.meta.EspressoError; import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.runtime.EspressoContext; @@ -39,11 +39,24 @@ import com.oracle.truffle.espresso.runtime.EspressoExitException; import com.oracle.truffle.espresso.runtime.StaticObject; +/** + * Provides bridges to guest world thread implementation. + */ public final class ThreadsAccess implements ContextAccess { private final Meta meta; private final EspressoContext context; + public ThreadsAccess(Meta meta) { + this.meta = meta; + this.context = meta.getContext(); + } + + @Override + public EspressoContext getContext() { + return context; + } + public String getThreadName(StaticObject thread) { if (thread == null) { return ""; @@ -60,15 +73,15 @@ public long getThreadId(StaticObject thread) { } } - @Override - public EspressoContext getContext() { - return context; + /** + * Returns the host thread associated with this guest thread, or null if the guest thread has + * not yet been registered. + */ + public Thread getHost(StaticObject guest) { + return (Thread) meta.HIDDEN_HOST_THREAD.getHiddenObject(guest); } - public ThreadsAccess(Meta meta) { - this.meta = meta; - this.context = meta.getContext(); - } + // region thread state transition public void fromRunnable(StaticObject self, State state) { assert meta.java_lang_Thread_threadStatus.getInt(self) == State.RUNNABLE.value; @@ -88,13 +101,13 @@ private void setState(StaticObject self, State state) { meta.java_lang_Thread_threadStatus.setInt(self, state.value); } - public Thread getHost(StaticObject guest) { - return (Thread) meta.HIDDEN_HOST_THREAD.getHiddenObject(guest); - } + // endregion thread state transition + + // region thread control /** - * Implements support for thread deprecated methods ({@link Thread#stop()}, - * {@link Thread#suspend()}, {@link Thread#resume()}). + * Implements support for thread deprecated methods ({@code Thread#stop()}, + * {@code Thread#suspend()}, {@code Thread#resume()}). *

* The following performance concerns are to be considered: *

    @@ -106,6 +119,7 @@ public Thread getHost(StaticObject guest) { *
*/ public void checkDeprecation() { + // TODO: safepoints if (!context.shouldCheckDeprecationStatus()) { return; } @@ -122,6 +136,20 @@ public void checkDeprecation() { } } + /** + * Lookups and calls the guest Thread.interrupt() method. + */ + public void interruptThread(StaticObject guestThread) { + assert guestThread != null && getMeta().java_lang_Thread.isAssignableFrom(guestThread.getKlass()); + // Thread.interrupt is non-final. + Method interruptMethod = guestThread.getKlass().vtableLookup(getMeta().java_lang_Thread_interrupt.getVTableIndex()); + assert interruptMethod != null; + interruptMethod.invokeDirect(guestThread); + } + + /** + * Implementation of {@link Thread#isInterrupted()}. + */ public boolean isInterrupted(StaticObject guest, boolean clear) { boolean isInterrupted = meta.HIDDEN_INTERRUPTED.getBoolean(guest, true); if (clear) { @@ -135,8 +163,12 @@ public boolean isInterrupted(StaticObject guest, boolean clear) { return isInterrupted; } + /** + * Implementation of {@link Thread#interrupt()}. + */ public void interrupt(StaticObject guest) { if (context.getJavaVersion().java13OrEarlier()) { + // In JDK 13+, the interrupted status is set in java code. meta.HIDDEN_INTERRUPTED.setBoolean(guest, true, true); } Thread host = getHost(guest); @@ -145,23 +177,40 @@ public void interrupt(StaticObject guest) { } } - public void clearInterruptStatus() { - StaticObject guest = context.getCurrentThread(); - if (context.getJavaVersion().java13OrEarlier()) { - clearInterruptStatus(guest); - } + /** + * Implementation of {@code Thread.clearInterruptEvent} (JDK 13+) + */ + public void clearInterruptEvent() { + assert !context.getJavaVersion().java13OrEarlier(); Thread.interrupted(); } + /** + * Sets the interrupted field of the given thread to {@code false} + */ + public void clearInterruptStatus(StaticObject guest) { + meta.HIDDEN_INTERRUPTED.setBoolean(guest, false, true); + } + + /** + * Implementation of {@link Thread#isAlive()}. + */ public boolean isAlive(StaticObject guest) { int state = meta.java_lang_Thread_threadStatus.getInt(guest); return state != State.NEW.value && state != State.TERMINATED.value; } + // endregion thread control + + // region deprecated methods support + /** * Suspends a thread. On return, guarantees that the given thread has seen the suspend request. */ public void suspend(StaticObject guest) { + if (!isAlive(guest)) { + return; + } DeprecationSupport support = getDeprecationSupport(guest, true); assert support != null; support.suspend(this); @@ -205,17 +254,19 @@ public void kill(StaticObject guest) { */ public Thread createJavaThread(StaticObject guest, DirectCallNode exit, DirectCallNode dispatch) { Thread host = context.getEnv().createThread(new GuestRunnable(context, guest, exit, dispatch)); - // Prepare + // Link guest to host meta.HIDDEN_HOST_THREAD.setHiddenObject(guest, host); + // Prepare host thread host.setDaemon(meta.java_lang_Thread_daemon.getBoolean(guest)); meta.java_lang_Thread_threadStatus.setInt(guest, State.RUNNABLE.value); host.setPriority(meta.java_lang_Thread_priority.getInt(guest)); if (isInterrupted(guest, false)) { host.interrupt(); } - context.registerThread(host, guest); String guestName = context.getThreadAccess().getThreadName(guest); host.setName(guestName); + // Make the thread known to the context + context.registerThread(host, guest); return host; } @@ -224,8 +275,8 @@ public Thread createJavaThread(StaticObject guest, DirectCallNode exit, DirectCa *
    *
  • Prevent other threads from {@linkplain #stop(StaticObject, StaticObject)} stopping} the * given thread
  • - *
  • Invoke guest {@link Thread#exit()}
  • - *
  • Sets the status of this thread to {@link State.TERMINATED} and notifies other threads + *
  • Invoke guest {@code Thread.exit()}
  • + *
  • Sets the status of this thread to {@link State#TERMINATED} and notifies other threads * waiting on this thread's monitor
  • *
  • Unregisters the thread
  • *
@@ -234,7 +285,7 @@ public void terminate(StaticObject thread) { terminate(thread, null); } - public void terminate(StaticObject thread, DirectCallNode exit) { + void terminate(StaticObject thread, DirectCallNode exit) { DeprecationSupport support = getDeprecationSupport(thread, true); support.exit(); try { @@ -246,11 +297,25 @@ public void terminate(StaticObject thread, DirectCallNode exit) { } catch (EspressoException | EspressoExitException e) { // just drop it } - terminateAndNotify(thread); + setTerminateStatusAndNotify(thread); context.unregisterThread(thread); } - public void terminateAndNotify(StaticObject guest) { + /** + * returns true if this thread has been stopped before starting, or if the context is in + * closing. + *

+ * If this method returns true, the thread will have been terminated. + */ + public boolean terminateIfStillborn(StaticObject guest) { + if (isStillborn(guest)) { + setTerminateStatusAndNotify(guest); + return true; + } + return false; + } + + private void setTerminateStatusAndNotify(StaticObject guest) { guest.getLock().lock(); try { meta.java_lang_Thread_threadStatus.setInt(guest, State.TERMINATED.value); @@ -261,23 +326,21 @@ public void terminateAndNotify(StaticObject guest) { } } - /** - * returns true if this thread has been stopped before starting, or if the context is in - * closing. - */ - public boolean isStillborn(StaticObject guest) { + private boolean isStillborn(StaticObject guest) { if (context.isClosing()) { return true; } - DeprecationSupport support = getDeprecationSupport(guest, false); - if (support != null) { - return support.status != NORMAL; + /* + * A bit of a special case. We want to make sure we observe the stillborn status + * synchronously. + */ + synchronized (guest) { + DeprecationSupport support = (DeprecationSupport) meta.HIDDEN_DEPRECATION_SUPPORT.getHiddenObject(guest, true); + if (support != null) { + return support.status != NORMAL; + } + return false; } - return false; - } - - public void clearInterruptStatus(StaticObject guest) { - meta.HIDDEN_INTERRUPTED.setBoolean(guest, false, true); } private DeprecationSupport getDeprecationSupport(StaticObject guest, boolean initIfNull) { @@ -314,11 +377,11 @@ void suspend(ThreadsAccess threads) { SuspendLock lock = this.suspendLock; if (lock == null) { synchronized (this) { - lock = new SuspendLock(); + lock = new SuspendLock(threads, thread); this.suspendLock = lock; } } - lock.suspend(threads, thread); + lock.suspend(); } void resume() { @@ -329,18 +392,26 @@ void resume() { lock.resume(); } - void stop(StaticObject death) { - // Writing the throwable must be done before the kill status can be observed - throwable = death; - status = STOP; + synchronized void stop(StaticObject death) { + KillStatus s = status; + if (s == NORMAL || s == STOP) { + // Writing the throwable must be done before the kill status can be observed + throwable = death; + updateKillState(STOP); + } } - void kill() { - status = KILL; + synchronized void kill() { + updateKillState(KILL); } - void exit() { - status = EXITING; + synchronized void exit() { + updateKillState(EXITING); + } + + private void updateKillState(KillStatus state) { + assert Thread.holdsLock(this); + status = state; } @TruffleBoundary @@ -357,18 +428,21 @@ void handleStop(Meta meta) { switch (status) { case NORMAL: case EXITING: - case KILLED: - break; + return; case STOP: - if (meta.getContext().isClosing()) { - // Give some leeway during closing. - status = KILLED; - } else { - status = NORMAL; + synchronized (this) { + // synchronize to mqke sure we are still stopped. + KillStatus s = status; + if (s == STOP) { + updateKillState(NORMAL); + // check if death cause throwable is set, if not throw ThreadDeath + StaticObject deathThrowable = throwable; + throw deathThrowable != null ? meta.throwException(deathThrowable) : meta.throwException(meta.java_lang_ThreadDeath); + } else if (s != KILL) { + return; + } } - // check if death cause throwable is set, if not throw ThreadDeath - StaticObject deathThrowable = throwable; - throw deathThrowable != null ? meta.throwException(deathThrowable) : meta.throwException(meta.java_lang_ThreadDeath); + // fallthrough case KILL: // This thread refuses to stop. Send a host exception. assert meta.getContext().isClosing(); @@ -376,4 +450,6 @@ void handleStop(Meta meta) { } } } + + // region deprecated methods support } From 5596267356fdb99928364d27f9f641d322365680 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 7 Oct 2021 18:34:20 +0300 Subject: [PATCH 333/681] Add Alpine Linux to certified platforms list --- docs/enterprise-overview/architecture-overview.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index b2e5b935e791..8924085116d4 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -70,9 +70,12 @@ The following are the certified platforms for GraalVM Enterprise 21: |------------------------------------ |-------------- |-------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Oracle Linux | 7, 8 | x86 64-bit, ARM 64-bit | [Installation Guide for Linux](/getting-started/installation-linux/) | | Red Hat Enterprise Linux(RHEL) | 7, 8 | x86 64-bit | [Installation Guide for Linux](/getting-started/installation-linux/) | +| Alpine Linux | 7, 8 | x86 64-bit | [Static Native Images](../reference-manual/native-image/StaticImages.md) | | macOS | 10.14 (Mojave), 10.15 (Catalina) | x86 64-bit | [Installation Guide for macOS](/getting-started/installation-macos/) | | Microsoft Windows | Server 2016, 2019 | x86 64-bit | [Installation Guide for Windows](/getting-started/installation-windows/) | +> Note: Alpine Linux is only certified for running executables created with GraalVM Native Image and statically linked to `muslc`. + ## Distribution Components List GraalVM Enterprise consists of core and additional functionalities. From 5fa726229e32037b0aa99dcefe4211d006034bc5 Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Wed, 6 Oct 2021 17:00:36 +0100 Subject: [PATCH 334/681] Convert to using keys instead of names.. --- .../tools/profiler/impl/SVGSamplerOutput.java | 160 ++++++++++-------- .../profiler/impl/resources/flamegraph.js | 5 +- .../profiler/impl/resources/graphowner.js | 13 +- .../profiler/impl/resources/histogram.js | 17 +- 4 files changed, 109 insertions(+), 86 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index 9e6252a6b552..a835ae92bb5a 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -216,14 +216,18 @@ private static class GraphOwner implements SVGComponent { private ArrayList components; private Random random = new Random(); private Map languageColors; - private Map> colorsForNames = new HashMap<>(); + private Map> colorsForKeys = new HashMap<>(); private int sampleId; public final Map nameHash = new HashMap<>(); public final Map sourceHash = new HashMap<>(); + public final Map keyHash = new HashMap<>(); + public final ArrayList sampleKeys = new ArrayList<>(); public int nameCounter = 0; public int sourceCounter = 0; + public int keyCounter = 0; public final JSONArray sampleNames = new JSONArray(); public final JSONArray sourceNames = new JSONArray(); + public final JSONArray sampleJsonKeys = new JSONArray(); public final JSONArray sampleData = new JSONArray(); GraphOwner(StringBuilder output, Map data) { @@ -314,13 +318,7 @@ private void buildSampleData() { ArrayDeque tasks = new ArrayDeque<>(); JSONObject root = new JSONObject(); sampleData.put(root); - root.put("n", nameCounter); - root.put("f", sourceCounter); - root.put("fl", 0); - nameHash.put("", nameCounter++); - sampleNames.put(""); - sourceHash.put("", sourceCounter++); - sourceNames.put(""); + root.put("k", indexForSampleKey("Thread: ", "", 0)); root.put("id", sampleId++); root.put("i", 0); root.put("c", 0); @@ -388,6 +386,48 @@ public boolean equals(Object obj) { } } + private int indexForSampleKey(String name, SourceSection section) { + final String sourceName; + int sourceLine = 0; + if (section != null && section.isAvailable()) { + sourceLine = section.getStartLine(); + Source source = section.getSource(); + if (source != null) { + String path = source.getPath(); + if (path != null) { + sourceName = path; + } else { + sourceName = source.getName(); + } + } else { + sourceName = ""; + } + } else { + sourceName = ""; + } + return indexForSampleKey(name, sourceName, sourceLine); + } + + private int indexForSampleKey(String name, String sourceFile, int line) { + int nameId = nameHash.computeIfAbsent(name, k -> { + sampleNames.put(k); + return nameCounter++; + }); + int sourceId = sourceHash.computeIfAbsent(sourceFile, k -> { + sourceNames.put(k); + return sourceCounter++; + }); + return keyHash.computeIfAbsent(new SampleKey(nameId, sourceId, line), k -> { + sampleKeys.add(k); + JSONArray jsonKey = new JSONArray(); + jsonKey.put(k.nameId); + jsonKey.put(k.sourceId); + jsonKey.put(k.sourceLine); + sampleJsonKeys.put(jsonKey); + return keyCounter++; + }); + } + private HashMap> recursiveChildMap = new HashMap<>(); private HashMap childrenByKeyForSample(JSONObject sample) { @@ -438,11 +478,11 @@ private void calculateRecursiveData(JSONObject sample) { } else { owner = parent; } - if (parent.getInt("n") == sample.getInt("n")) { + if (parent.getInt("k") == sample.getInt("k")) { mergeCounts(owner, sample, true); } else { HashMap siblings = childrenByKeyForSample(owner); - SampleKey key = new SampleKey(sample.getInt("n"), sample.getInt("f"), sample.getInt("fl")); + SampleKey key = sampleKeys.get(sample.getInt("k")); if (siblings.containsKey(key)) { JSONObject sibling = siblings.get(key); mergeCounts(sibling, sample, false); @@ -495,15 +535,7 @@ private long threadSampleData(Thread thread, Collection { - sampleNames.put(thread.getName()); - return nameCounter++; - })); - threadSample.put("f", sourceHash.computeIfAbsent("", k -> { - sourceNames.put(""); - return sourceCounter++; - })); - threadSample.put("fl", 0); + threadSample.put("k", indexForSampleKey(thread.getName(), "", 0)); threadSample.put("id", id); threadSample.put("p", 0); sampleData.put(threadSample); @@ -535,6 +567,9 @@ private String samples() { result.append("var sourceNames = "); result.append(sourceNames.toString()); result.append(";\n"); + result.append("var sampleKeys = "); + result.append(sampleJsonKeys.toString()); + result.append(";\n"); result.append("var profileData = "); result.append(sampleData.toString()); result.append(";\n"); @@ -542,10 +577,10 @@ private String samples() { result.append("var colorData = "); JSONArray colors = new JSONArray(); for (GraphColorMap cm : GraphColorMap.values()) { - if (colorsForNames.containsKey(cm)) { + if (colorsForKeys.containsKey(cm)) { JSONObject map = new JSONObject(); - for (Map.Entry e : colorsForNames.get(cm).entrySet()) { - map.put(nameHash.get(e.getKey()).toString(), e.getValue()); + for (Map.Entry e : colorsForKeys.get(cm).entrySet()) { + map.put(keyHash.get(e.getKey()).toString(), e.getValue()); } colors.put(map); } else { @@ -572,35 +607,7 @@ private String samples() { private void processSample(Task task, ArrayDeque tasks) { JSONObject result = new JSONObject(); - final int nameId = nameHash.computeIfAbsent(task.sample.getRootName(), k -> { - sampleNames.put(task.sample.getRootName()); - return nameCounter++; - }); - result.put("n", nameId); - final String sourceName; - int sourceLine = 0; - SourceSection section = task.sample.getSourceSection(); - if (section != null && section.isAvailable()) { - sourceLine = section.getStartLine(); - Source source = section.getSource(); - if (source != null) { - String path = source.getPath(); - if (path != null) { - sourceName = path; - } else { - sourceName = source.getName(); - } - } else { - sourceName = ""; - } - } else { - sourceName = ""; - } - result.put("f", sourceHash.computeIfAbsent(sourceName, k -> { - sourceNames.put(k); - return sourceCounter++; - })); - result.put("fl", sourceLine); + result.put("k", indexForSampleKey(task.sample.getRootName(), task.sample.getSourceSection())); int id = sampleId++; result.put("id", id); result.put("p", task.parent); @@ -632,6 +639,11 @@ protected JSONObject sampleDataForId(int id) { return (JSONObject) sampleData.get(id); } + protected String nameForKeyId(int keyId) { + SampleKey key = sampleKeys.get(keyId); + return sampleNames.getString(key.nameId); + } + private void buildColorData() { for (Object sample : sampleData) { buildColorDataForSample((JSONObject) sample); @@ -639,8 +651,8 @@ private void buildColorData() { } private void buildColorDataForSample(JSONObject sample) { - colorForName(sample.getInt("n"), GraphColorMap.FLAME); - colorForName(sample.getInt("n"), GraphColorMap.values()[sample.getInt("l")]); + colorForKey(sample.getInt("k"), GraphColorMap.FLAME); + colorForKey(sample.getInt("k"), GraphColorMap.values()[sample.getInt("l")]); } public String initFunction(String argName) { @@ -706,21 +718,21 @@ public String drawCanvas(double x, double y) { return canvas.toString(); } - public Map colorsForType(GraphColorMap type) { - if (colorsForNames.containsKey(type)) { - return colorsForNames.get(type); + public Map colorsForType(GraphColorMap type) { + if (colorsForKeys.containsKey(type)) { + return colorsForKeys.get(type); } else { - Map colors = new HashMap<>(); - colorsForNames.put(type, colors); + Map colors = new HashMap<>(); + colorsForKeys.put(type, colors); return colors; } } - public String colorForName(int nameId, GraphColorMap type) { - String name = sampleNames.getString(nameId); - Map colors = colorsForType(type); - if (colors.containsKey(name)) { - return colors.get(name); + public String colorForKey(int keyId, GraphColorMap type) { + SampleKey key = sampleKeys.get(keyId); + Map colors = colorsForType(type); + if (colors.containsKey(key)) { + return colors.get(key); } double v1; @@ -780,7 +792,7 @@ public String colorForName(int nameId, GraphColorMap type) { b = r; } String color = allocateColor(r, g, b); - colors.put(name, color); + colors.put(key, color); return color; } @@ -1004,7 +1016,8 @@ private String drawSample(double baseY, DrawTask task, ArrayDeque task } HashMap groupAttrs = new HashMap<>(); int id = sample.getInt("id"); - String fullText = owner.sampleNames.getString(sample.getInt("n")); + String fullText = owner.nameForKeyId(sample.getInt("k")); + GraphOwner.SampleKey key = owner.sampleKeys.get(sample.getInt("k")); groupAttrs.put("class", "func_g"); groupAttrs.put("onclick", id == 0 ? "unzoom()" : "zoom(this)"); @@ -1021,13 +1034,13 @@ private String drawSample(double baseY, DrawTask task, ArrayDeque task double totalPercent = 100.0 * total / sampleCount; title.append(String.format("Self samples: %d (%.2f%%)\n", interpreted + compiled, percent)); title.append(String.format("total samples: %d (%.2f%%)\n", total, totalPercent)); - title.append(String.format("Source location: %s:%d\n", owner.sourceNames.get(sample.getInt("f")), sample.getInt("fl"))); + title.append(String.format("Source location: %s:%d\n", owner.sourceNames.get(key.sourceId), key.sourceLine)); groupAttrs.put("title", escape(title.toString())); output.append(startGroup(groupAttrs)); HashMap rectAttrs = new HashMap<>(); - output.append(fillRectangle(x, y, width, FRAMEHEIGHT, owner.colorForName(sample.getInt("n"), GraphColorMap.FLAME), "rx=\"2\" ry=\"2\"", rectAttrs)); + output.append(fillRectangle(x, y, width, FRAMEHEIGHT, owner.colorForKey(sample.getInt("k"), GraphColorMap.FLAME), "rx=\"2\" ry=\"2\"", rectAttrs)); output.append(ttfString(black(), owner.fontName(), owner.fontSize(), x + 3, y - 5 + FRAMEHEIGHT, owner.abbreviate(fullText, width), null, "")); output.append(endGroup(groupAttrs)); @@ -1097,7 +1110,7 @@ private static class SVGHistogram implements SVGComponent { } private List buildHistogram(JSONObject sample) { - Map bars = new HashMap<>(); + Map bars = new HashMap<>(); ArrayDeque samples = new ArrayDeque<>(); JSONObject next = sample; @@ -1111,15 +1124,15 @@ private List buildHistogram(JSONObject sample) { return lines; } - private void buildHistogram(JSONObject sample, ArrayDeque samples, Map bars) { - JSONObject bar = bars.computeIfAbsent(owner.sampleNames.getString(sample.getInt("n")), + private void buildHistogram(JSONObject sample, ArrayDeque samples, Map bars) { + JSONObject bar = bars.computeIfAbsent(owner.sampleKeys.get(sample.getInt("k")), k -> { JSONObject entry = new JSONObject(); entry.put("id", sample.getInt("id")); entry.put("i", 0); entry.put("c", 0); entry.put("l", sample.getInt("l")); - entry.put("n", sample.getInt("n")); + entry.put("k", sample.getInt("k")); return entry; }); bar.put("i", bar.getInt("i") + sample.getInt("i")); @@ -1181,8 +1194,7 @@ public String drawCanvas(double x, double y) { } private String drawElement(JSONObject bar, int position) { - int nameId = owner.sampleDataForId(bar.getInt("id")).getInt("n"); - String name = owner.sampleNames.getString(nameId); + String name = owner.nameForKeyId(bar.getInt("k")); long selfTime = bar.getInt("c") + bar.getInt("i"); double width = widthPerTime * selfTime; @@ -1212,7 +1224,7 @@ private String drawElement(JSONObject bar, int position) { HashMap rectAttrs = new HashMap<>(); - output.append(fillRectangle(x1, y1, width, FRAMEHEIGHT, owner.colorForName(nameId, GraphColorMap.FLAME), "rx=\"2\" ry=\"2\"", rectAttrs)); + output.append(fillRectangle(x1, y1, width, FRAMEHEIGHT, owner.colorForKey(bar.getInt("k"), GraphColorMap.FLAME), "rx=\"2\" ry=\"2\"", rectAttrs)); double afterWidth = IMAGEWIDTH - width - XPAD * 2; int textLength = (int) (width / (owner.fontSize() / owner.fontWidth())); int afterLength = (int) (afterWidth / (owner.fontSize() / owner.fontWidth())); diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index ee2a2647e14d..83b4d758ff72 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -181,6 +181,7 @@ function zoom_child(sample) { let t = e.lastElementChild; let name = name_for_sample(sample); let source = source_for_sample(sample); + let sourceLine = source_line_for_sample(sample); let compiled = 0; let interpreted = 0; @@ -198,7 +199,7 @@ function zoom_child(sample) { title.textContent = name + " (" + languageNames[sample.l] + ")\n" + "Self samples: " + (interpreted + compiled) + " (" + (100 * (compiled + interpreted) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + "Total samples: " + (hits) + " (" + (100 * (hits) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + - "Source location: " + source + ":" + sample.fl + "\n"; + "Source location: " + source + ":" + sourceLine + "\n"; r.x.baseVal.value = x; r.y.baseVal.value = y; @@ -296,7 +297,7 @@ function zoom_internal(sample, parents, unrelated) { zoom_child(c.value); c = iter.next(); } - fg_search_update(); + fg_search_update(search_matches); fg_canvas_resize(); rebuild_histogram(sample); } diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index f9389854b638..77d919e35e3c 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -259,15 +259,22 @@ function title(e) { } function key_for_sample(sample) { - return sample.n; + return sample.k; } function name_for_sample(sample) { - return profileNames[sample.n]; + let key = sampleKeys[sample.k]; + return profileNames[key[0]]; } function source_for_sample(sample) { - return sourceNames[sample.f]; + let key = sampleKeys[sample.k]; + return sourceNames[key[1]]; +} + +function source_line_for_sample(sample) { + let key = sampleKeys[sample.k]; + return sourceNames[key[2]]; } function function_name(e) { diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js index b10e35847560..46e49b6d8cec 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js @@ -162,10 +162,13 @@ function h_update_bar(id, bar) { let t = e.lastElementChild; let name = name_for_sample(bar); + let source = source_for_sample(bar); + let sourceLine = source_line_for_sample(bar); + let hits = bar.i + bar.c; - title.textContent = "Function: " + name + "\n" + - (bar.c + bar.i) + " samples (" + bar.i + " interpreted, " + bar.c + " compiled).\n" + - (100 * (bar.c + bar.i) / (fg_xmax - fg_xmin)).toFixed(2) + "% of displayed samples.\n"; + title.textContent = name + " (" + languageNames[bar.l] + ")\n" + + "Samples: " + (hits) + " (" + (100 * (hits) / (fg_xmax - fg_xmin)).toFixed(2) + "%)\n" + + "Source location: " + source + ":" + sourceLine + "\n"; r.width.baseVal.value = width; r.style.fill = h_color_for_sample(color_type, bar); @@ -238,16 +241,16 @@ function h_canvas_resize() { function calculate_histogram_bars(bars, sample) { let bar; - if (!bars.hasOwnProperty(sample["n"])) { + if (!bars.hasOwnProperty(sample.k)) { bar = []; bar["id"] = sample["id"]; bar["i"] = 0; bar["c"] = 0; bar["l"] = sample["l"]; - bar["n"] = sample["n"]; - bars[sample["n"]] = bar; + bar["k"] = sample["k"]; + bars[sample.k] = bar; } else { - bar = bars[sample["n"]]; + bar = bars[sample.k]; } if (fg_collapsed) { bar["i"] = bar["i"] + sample["ri"]; From 3e3fb2fc06aae9a6c09d2801401c470e344da3ca Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Thu, 7 Oct 2021 16:48:22 +0100 Subject: [PATCH 335/681] Update histogram highlighting code to be based on keys, not names. --- .../profiler/impl/resources/flamegraph.js | 26 +++--- .../profiler/impl/resources/graphowner.js | 2 +- .../profiler/impl/resources/histogram.js | 81 ++++++++++++------- 3 files changed, 69 insertions(+), 40 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index 83b4d758ff72..354a0b39f020 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -318,35 +318,39 @@ function unzoom() { function fg_search(term) { var re = new RegExp(term); - search_matches = [] + let search_matches = [] let iter = sample_and_children_depth_first(profileData[0]); let c = iter.next(); while (!c.done) { let sample = c.value; if (name_for_sample(sample).match(re)) { - sample.searchMatch = true; - search_matches.push(sample); - let e = fg_element_for_sample(sample); - if (e != null) { - let r = e.children[1]; - r.style.fill = searchColor; - } + fg_highlight_sample(search_matches, sample); } c = iter.next(); } + fg_search_update(search_matches); + if (search_matches.length == 0) return; searchbtn.style["opacity"] = "0.8"; searchbtn.firstChild.nodeValue = "Reset Search" +} - fg_search_update(); +function fg_highlight_sample(samples, sample) { + sample.searchMatch = true; + samples.push(sample); + let e = fg_element_for_sample(sample); + if (e != null) { + let r = e.children[1]; + r.style.fill = searchColor; + } } -function fg_search_update() { - let samples = search_matches.slice(); +function fg_search_update(samples) { + search_matches = samples.slice(); if (samples.length == 0) { matchedtxt.style["opacity"] = "0.0"; diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index 77d919e35e3c..2bf3e53360c5 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -274,7 +274,7 @@ function source_for_sample(sample) { function source_line_for_sample(sample) { let key = sampleKeys[sample.k]; - return sourceNames[key[2]]; + return key[2]; } function function_name(e) { diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js index 46e49b6d8cec..82791c079625 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js @@ -43,55 +43,80 @@ function h_search(term) { function h_update_search() { let re = h_search_regex; - if (re == null) { - return; - } - for (let i = 0; i < histogramData.length; i++) { - let bar = histogramData[i]; - if (name_for_sample(bar).match(re)) { - bar.searchMatch = true; - let e = h_element_for_id(i); - if (e != null) { - let r = e.children[1]; - r.style.fill = searchColor; + if (re != null) { + for (let i = 0; i < histogramData.length; i++) { + let bar = histogramData[i]; + if (name_for_sample(bar).match(re)) { + bar.searchMatch = true; + let e = h_element_for_id(i); + h_highlight_bar(i, bar); + } + } + } else if (hilight_bar != null) { + for (let i = 0; i < histogramData.length; i++) { + let bar = histogramData[i]; + if (hilight_bar.k == bar.k) { + bar.searchMatch = true; + let e = h_element_for_id(i); + h_highlight_bar(i, bar); } } } } -var hilight_element = null; +var hilight_bar = null; function h_reset_search() { for (let i = 0; i < histogramData.length; i++) { let bar = histogramData[i]; if (bar.searchMatch = true) { bar.searchMatch = false; - let e = h_element_for_id(i); - if (e != null) { - let color = bar.currentColor; - if (color == undefined) { - color = h_color_for_sample(color_type, bar); - } - let r = e.children[1]; - r.style.fill = color; - } + h_unhighlight_bar(i, bar); } } h_search_regex = null; } +function h_highlight_bar(id, bar) { + let e = h_element_for_id(id) + if (e != null) { + let r = e.children[1]; + r.style.fill = searchColor; + } +} + +function h_unhighlight_bar(id, bar) { + let e = h_element_for_id(id) + if (e != null) { + let color = bar.currentColor; + if (color == undefined) { + color = h_color_for_sample(color_type, bar); + } + let r = e.children[1]; + r.style.fill = color; + } +} + function h_highlight(e) { - if (hilight_element == e) { + let id = e.getAttribute("id").substring(2); + let bar = histogram_entry_for_id(id); + if (hilight_bar != null && hilight_bar.k == bar.k) { hilight_element = null; reset_search(); } else { - let bar = histogram_entry_for_id(e.getAttribute("id").substring(2)); reset_search(); - hilight_element = e; - let name = name_for_sample(bar); - // Ensure we escape anything that might cause a problem with the regexp. - name = "^" + name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + "$"; // $& means the whole matched string - search(name); + hilight_bar = bar; + h_highlight_bar(id, bar); + + let iter = sample_and_children_depth_first(profileData[0]); + let c = iter.next(); + while (!c.done) { + let sample = c.value; + if (sample.k == bar.k) { + fg_highlight_sample(search_matches, sample); + } + c = iter.next(); + } } } From f976953e27a97880e7ea59d694260fbe8ca43a8e Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Thu, 30 Sep 2021 16:45:46 +0100 Subject: [PATCH 336/681] Combine the legend and help into one popup. --- .../tools/profiler/impl/SVGSamplerOutput.java | 2 +- .../profiler/impl/resources/color_change.js | 24 ++++--- .../profiler/impl/resources/graphowner.js | 64 ------------------- 3 files changed, 12 insertions(+), 78 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index a835ae92bb5a..37e23208bd4c 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -956,7 +956,7 @@ public String drawCanvas(double x, double y) { output.append(ttfString(black(), owner.fontName(), owner.fontSize() + 5, width() / 2, owner.fontSize() * 2, "Flamegraph", "middle", "id=\"fg_title\"")); output.append(ttfString(black(), owner.fontName(), owner.fontSize(), width() / 2, owner.fontSize() * 3, - "Press \"?\" for help, or \"l\" for legend.", "middle", "id=\"fg_help\"")); + "Press \"?\" for legend and help.", "middle", "id=\"fg_help\"")); output.append(ttfString(black(), owner.fontName(), owner.fontSize(), XPAD, owner.fontSize() * 2, "Reset zoom", "", "id=\"unzoom\" onclick=\"unzoom()\" style=\"opacity:0.1;cursor:pointer\"")); output.append(ttfString(black(), owner.fontName(), owner.fontSize(), width() - XPAD, owner.fontSize() * 2, diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js index 11adcc846671..6d90821cabfd 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js @@ -130,21 +130,10 @@ function color_create_legend() { t.style.fontSize = fontSize * 1.5; t.style.fontFamily = "Verdana"; t.style.fill = "rgb(0, 0, 0)"; - t.textContent = "Legend"; - - let t2 = document.createElementNS("http://www.w3.org/2000/svg", "text"); - t2.className.baseVal = "title"; - t2.style.textAnchor = "middle"; - t2.setAttribute("x", 125); - t2.setAttribute("y", fg_frameheight * 3); - t2.style.fontSize = fontSize; - t2.style.fontFamily = "Verdana"; - t2.style.fill = "rgb(0, 0, 0)"; - t2.textContent = "Press \"l\" to toggle legend"; + t.textContent = "Legend & Help"; e.appendChild(r); e.appendChild(t); - e.appendChild(t2); e.style.display = "none"; svg.appendChild(e); @@ -177,6 +166,15 @@ function color_create_legend() { entry_count = 12; } + let help_entry_count = 0; + + for (; help_entry_count < help_strings.length; help_entry_count++) { + graph_help_entry(e, entry_count + help_entry_count + 1, help_strings[help_entry_count][0], help_strings[help_entry_count][1]); + } + + if (help_entry_count > 0) { + entry_count = entry_count + help_entry_count + 1; + } r.height.baseVal.value = (fg_frameheight * 2.5) + (entry_count + 1) * fg_frameheight * 1.5; color_insert_legend(svg); return e; @@ -238,4 +236,4 @@ function color_legend() { // C for color cycle. graph_register_handler("c", "Cycle through graph colorings", color_cycle); -graph_register_handler("l", "Toggle legend display", color_legend); +graph_register_handler("?", "Toggle legend & help display", color_legend); diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index 2bf3e53360c5..295d5b9c9431 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -370,52 +370,6 @@ function owner_resize(new_width) { } var help_strings = []; -var help_state = false; - -function graph_create_help() { - let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - let e = document.createElementNS("http://www.w3.org/2000/svg", "g"); - e.id = "help"; - - let r = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - svg.y.baseVal.value = 50; - r.className.baseVal = "popup"; - r.x.baseVal.value = 0; - r.y.baseVal.value = 0; - r.width.baseVal.value = 250; - r.style.fill = "white"; - r.style.stroke = "black"; - r.style["stroke-width"] = 2; - r.rx.baseVal.value = 2; - r.ry.baseVal.vlaue = 2; - - let t = document.createElementNS("http://www.w3.org/2000/svg", "text"); - t.className.baseVal = "title"; - t.style.textAnchor = "middle"; - t.setAttribute("y", fg_frameheight * 2); - t.style.fontSize = fontSize * 1.5; - t.style.fontFamily = "Verdana"; - t.style.fill = "rgb(0, 0, 0)"; - t.textContent = "Keyboard shortcut"; - - e.appendChild(r); - e.appendChild(t); - e.style.display = "none"; - svg.appendChild(e); - - let entry_count = 0; - - for (; entry_count < help_strings.length; entry_count++) { - graph_help_entry(e, entry_count, help_strings[entry_count][0], help_strings[entry_count][1]); - } - - svg.x.baseVal.value = document.firstElementChild.width.baseVal.value - 250 - xpad; - t.setAttribute("x", 250 / 2); - r.height.baseVal.value = (fg_frameheight * 2.5) + (entry_count + 1) * fg_frameheight * 1.5; - document.firstElementChild.appendChild(svg); - return e; - -} function graph_help_entry(e, i, key, description) { let y = (fg_frameheight * 2) + (i + 1) * fg_frameheight * 1.5; @@ -475,22 +429,6 @@ function graph_popup_fix_width(e, right_justify) { } }; -function graph_help() { - let e = document.getElementById("help"); - if (e == null) { - e = graph_create_help(); - } - if (e != null) { - if (e.style["display"] == "none") { - e.style["display"] = "block"; - graph_popup_fix_width(e, true); - } else { - e.style["display"] = "none"; - } - } - help_state = !help_state; -} - function graph_register_handler(key, description, action) { window.addEventListener("keydown", function (e) { if (e.key == key && !e.isComposing && !e.altKey && !e.ctrlKey && !e.metaKey) { @@ -500,5 +438,3 @@ function graph_register_handler(key, description, action) { }); help_strings.push([key, description]); } - -graph_register_handler("?", "Display keyboard shortcuts", graph_help); From 8a4f9852cae0b2cf709b1c207d6021b1348f7a49 Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Thu, 7 Oct 2021 17:36:25 +0100 Subject: [PATCH 337/681] Refactor to put document height management in one place. --- .../profiler/impl/resources/color_change.js | 9 +++++---- .../tools/profiler/impl/resources/flamegraph.js | 3 +-- .../tools/profiler/impl/resources/graphowner.js | 16 ++++++++++++++++ .../tools/profiler/impl/resources/histogram.js | 3 +-- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js index 6d90821cabfd..6c9a5d5a6d9c 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/color_change.js @@ -156,14 +156,14 @@ function color_create_legend() { } } else if (color_type == "bc") { color_legend_entry(e, 0, color_for_compilation(0, 0), "No self samples"); - for (let i = 0; i <= 10; i++) { - let color = color_for_compilation(10 - i, i); - let text = (i * 10) + "% samples were compiled."; + for (let i = 0; i <= 4; i++) { + let color = color_for_compilation(4 - i, i); + let text = (i * 25) + "% samples were compiled."; color_legend_entry(e, i + 1, color, text); } - entry_count = 12; + entry_count = 6; } let help_entry_count = 0; @@ -232,6 +232,7 @@ function color_legend() { } } legend_state = !legend_state; + graph_ensure_space(); } // C for color cycle. diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js index 354a0b39f020..bd85da960de4 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/flamegraph.js @@ -272,8 +272,7 @@ function fg_canvas_resize() { let fg_canvas = document.getElementById("fg_canvas"); fg_canvas.height.baseVal.value = height; fg_canvas.y.baseVal.value = -height; - svg.height.baseVal.value = svg.height.baseVal.value - old_height + height; - svg.viewBox.baseVal.height = svg.height.baseVal.value; + graph_ensure_space(); } function zoom_internal(sample, parents, unrelated) { diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js index 295d5b9c9431..40e12e4241e0 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/graphowner.js @@ -427,6 +427,7 @@ function graph_popup_fix_width(e, right_justify) { if (right_justify) { e.parentElement.x.baseVal.value = fg_width - max_label_end - xpad; } + graph_ensure_space(); }; function graph_register_handler(key, description, action) { @@ -438,3 +439,18 @@ function graph_register_handler(key, description, action) { }); help_strings.push([key, description]); } + +function graph_ensure_space() { + let svg = document.firstElementChild; + let maxY = 0; + for (const e of svg.getElementsByTagName("svg")) { + if (svg.style["display"] != "none") { + let y = e.y.baseVal.value + e.height.baseVal.value; + if (y > maxY) { + maxY = y; + } + } + } + svg.height.baseVal.value = maxY; + svg.viewBox.baseVal.height = maxY; +} diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js index 82791c079625..24948c6c3104 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/resources/histogram.js @@ -260,8 +260,7 @@ function h_canvas_resize() { h_svg.viewBox.baseVal.height = height; let h_canvas = document.getElementById("h_canvas"); h_canvas.height.baseVal.value = height; - svg.height.baseVal.value = svg.height.baseVal.value - old_height + height; - svg.viewBox.baseVal.height = svg.height.baseVal.value; + graph_ensure_space(); } function calculate_histogram_bars(bars, sample) { From 0e6e18c1f6a634fe0adc26c16aa5b4582b654a92 Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Thu, 7 Oct 2021 13:32:41 -0700 Subject: [PATCH 338/681] Remove failing assertion --- .../src/com/oracle/svm/hosted/meta/HostedMethod.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethod.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethod.java index 260c4ff004ca..13d035dabe57 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethod.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethod.java @@ -488,7 +488,11 @@ public int compareTo(HostedMethod other) { if (result == 0) { result = ((HostedType) this.getSignature().getReturnType(null)).compareTo((HostedType) other.getSignature().getReturnType(null)); } - assert result != 0; + /* + * Note that the result can still be 0 at this point: with class substitutions or incomplete + * classpath, two separate methods can have the same signature. Not ordering such methods is + * fine. GR-32976 should remove the sorting altogether. + */ return result; } From 8297f26304340333574ec5e9a307202099ab3c29 Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Thu, 7 Oct 2021 14:14:07 -0700 Subject: [PATCH 339/681] Avoid NullPointerException --- .../src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java index 054967f7a780..154209e821ea 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java @@ -39,6 +39,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -382,7 +383,7 @@ private boolean foldInvocationUsingReflection(GraphBuilderContext b, ResolvedJav /* String representation of the parameters for debug printing. */ Supplier targetParameters = () -> (receiverValue == null ? "" : receiverValue.toString() + "; ") + - Stream.of(argValues).map(arg -> arg instanceof Object[] ? Arrays.toString((Object[]) arg) : arg.toString()).collect(Collectors.joining(", ")); + Stream.of(argValues).map(arg -> arg instanceof Object[] ? Arrays.toString((Object[]) arg) : Objects.toString(arg)).collect(Collectors.joining(", ")); Object returnValue; try { From 1be269c95a353ee3bfa07917b430c58077d762e6 Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Wed, 22 Sep 2021 17:19:10 -0700 Subject: [PATCH 340/681] Add verification for invoke receiver types --- .../com/oracle/svm/core/SubstrateOptions.java | 3 + .../graal/snippets/NonSnippetLowerings.java | 68 ++++++++++++++++++- .../snippets/ImplicitExceptionsFeature.java | 8 +++ 3 files changed, 77 insertions(+), 2 deletions(-) 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 cd99fbebf10f..c4e350b410ac 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 @@ -620,4 +620,7 @@ protected void onValueUpdate(EconomicMap, Object> values, String ol @APIOption(name = "configure-reflection-metadata")// @Option(help = "Limit method reflection metadata to configuration entries instead of including it for all reachable methods")// public static final HostedOptionKey ConfigureReflectionMetadata = new HostedOptionKey<>(true); + + @Option(help = "Verify type states computed by the static analysis at run time. This is useful when diagnosing problems in the static analysis, but reduces peak performance significantly.", type = Debug)// + public static final HostedOptionKey VerifyTypes = new HostedOptionKey<>(false); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java index 6c94898c9c5b..bffca2c3bfc3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java @@ -33,15 +33,19 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.StampPair; +import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.nodes.BeginNode; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DirectCallTargetNode; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.FixedNode; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.IndirectCallTargetNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeNode; @@ -54,11 +58,15 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IsNullNode; +import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; +import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.extended.OpaqueNode; +import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; @@ -73,6 +81,8 @@ import org.graalvm.word.LocationIdentity; import com.oracle.svm.core.FrameAccess; +import com.oracle.svm.core.SubstrateOptions; +import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.code.CodeInfoTable; import com.oracle.svm.core.graal.code.SubstrateBackend; import com.oracle.svm.core.graal.meta.RuntimeConfiguration; @@ -81,6 +91,8 @@ import com.oracle.svm.core.meta.SharedMethod; import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.core.snippets.ImplicitExceptions; +import com.oracle.svm.core.snippets.SnippetRuntime; +import com.oracle.svm.core.snippets.SubstrateForeignCallTarget; import com.oracle.svm.core.util.VMError; import jdk.vm.ci.code.CallingConvention; @@ -93,9 +105,14 @@ public abstract class NonSnippetLowerings { + public static final SnippetRuntime.SubstrateForeignCallDescriptor REPORT_VERIFY_TYPES_ERROR = SnippetRuntime.findForeignCall( + NonSnippetLowerings.class, "reportVerifyTypesError", false, LocationIdentity.any()); + private final RuntimeConfiguration runtimeConfig; private final Predicate mustNotAllocatePredicate; + final boolean verifyTypes = SubstrateOptions.VerifyTypes.getValue(); + @SuppressWarnings("unused") protected NonSnippetLowerings(RuntimeConfiguration runtimeConfig, Predicate mustNotAllocatePredicate, OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, Map, NodeLoweringProvider> lowerings) { @@ -250,12 +267,53 @@ public void lower(FixedNode node, LoweringTool tool) { SharedMethod method = (SharedMethod) callTarget.targetMethod(); JavaType[] signature = method.getSignature().toParameterTypes(callTarget.isStatic() ? null : method.getDeclaringClass()); CallingConvention.Type callType = method.getCallingConventionKind().toType(true); - InvokeKind invokeKind = callTarget.invokeKind(); SharedMethod[] implementations = method.getImplementations(); + + if (verifyTypes && !callTarget.isStatic() && receiver.getStackKind() == JavaKind.Object && !((SharedMethod) graph.method()).isUninterruptible()) { + /* + * Verify that the receiver is an instance of the class that declares the call + * target method. To avoid that the new type check floats above a deoptimization + * entry point, we need to anchor the receiver to the control flow. To avoid + * that Graal optimizes away the InstanceOfNode immediately, we need an + * OpaqueNode that removes all type information from the receiver. Then we wire + * up an IfNode that leads to a ForeignCallNode in case the verification fails. + */ + FixedValueAnchorNode anchoredReceiver = graph.add(new FixedValueAnchorNode(receiver)); + graph.addBeforeFixed(node, anchoredReceiver); + ValueNode opaqueReceiver = graph.unique(new OpaqueNode(anchoredReceiver)); + TypeReference declaringClass = TypeReference.createTrustedWithoutAssumptions(method.getDeclaringClass()); + LogicNode instanceOf = graph.addOrUniqueWithInputs(InstanceOfNode.create(declaringClass, opaqueReceiver)); + BeginNode passingBegin = graph.add(new BeginNode()); + BeginNode failingBegin = graph.add(new BeginNode()); + IfNode ifNode = graph.add(new IfNode(instanceOf, passingBegin, failingBegin, BranchProbabilityNode.EXTREMELY_FAST_PATH_PROFILE)); + + ((FixedWithNextNode) node.predecessor()).setNext(ifNode); + passingBegin.setNext(node); + + String errorMessage; + if (SubstrateUtil.HOSTED) { + errorMessage = "Invoke " + invokeKind + " of " + method.format("%H.%n(%p)%r"); + errorMessage += System.lineSeparator() + " declaringClass = " + declaringClass; + if (implementations.length == 0 || implementations.length > 10) { + errorMessage += System.lineSeparator() + " implementations.length = " + implementations.length; + } else { + for (int i = 0; i < implementations.length; i++) { + errorMessage += System.lineSeparator() + " implementations[" + i + "] = " + implementations[i].format("%H.%n(%p)%r"); + } + } + } else { + errorMessage = "Invoke (method name not added because message must be a compile-time constant)"; + } + ConstantNode errorConstant = ConstantNode.forConstant(tool.getConstantReflection().forString(errorMessage), tool.getMetaAccess(), graph); + ForeignCallNode reportError = graph.add(new ForeignCallNode(REPORT_VERIFY_TYPES_ERROR, opaqueReceiver, errorConstant)); + reportError.setStateAfter(invoke.stateAfter().duplicateModifiedDuringCall(invoke.bci(), node.getStackKind())); + failingBegin.setNext(reportError); + reportError.setNext(graph.add(new LoweredDeadEndNode())); + } + LoadHubNode hub = null; CallTargetNode loweredCallTarget; - if (invokeKind.isDirect() || implementations.length == 1) { SharedMethod targetMethod = method; if (!invokeKind.isDirect()) { @@ -352,4 +410,10 @@ private CallTargetNode createUnreachableCallTarget(LoweringTool tool, FixedNode } } + @SubstrateForeignCallTarget(stubCallingConvention = true) + private static void reportVerifyTypesError(Object object, String message) { + throw VMError.shouldNotReachHere("VerifyTypes: object=" + (object == null ? "null" : object.getClass().getTypeName()) + + System.lineSeparator() + message + + System.lineSeparator() + "VerifyTypes found a type error"); + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ImplicitExceptionsFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ImplicitExceptionsFeature.java index 46ac9324b928..404e9117e3bb 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ImplicitExceptionsFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ImplicitExceptionsFeature.java @@ -25,9 +25,11 @@ package com.oracle.svm.hosted.snippets; import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.annotate.AutomaticFeature; import com.oracle.svm.core.graal.GraalFeature; import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider; +import com.oracle.svm.core.graal.snippets.NonSnippetLowerings; import com.oracle.svm.core.snippets.ExceptionUnwind; import com.oracle.svm.core.snippets.ImplicitExceptions; import com.oracle.svm.core.snippets.SnippetRuntime.SubstrateForeignCallDescriptor; @@ -46,11 +48,17 @@ public void beforeAnalysis(BeforeAnalysisAccess a) { for (SubstrateForeignCallDescriptor descriptor : ExceptionUnwind.FOREIGN_CALLS) { access.getBigBang().addRootMethod((AnalysisMethod) descriptor.findMethod(access.getMetaAccess())); } + if (SubstrateOptions.VerifyTypes.getValue()) { + access.getBigBang().addRootMethod((AnalysisMethod) NonSnippetLowerings.REPORT_VERIFY_TYPES_ERROR.findMethod(access.getMetaAccess())); + } } @Override public void registerForeignCalls(SubstrateForeignCallsProvider foreignCalls) { foreignCalls.register(ImplicitExceptions.FOREIGN_CALLS); foreignCalls.register(ExceptionUnwind.FOREIGN_CALLS); + if (SubstrateOptions.VerifyTypes.getValue()) { + foreignCalls.register(NonSnippetLowerings.REPORT_VERIFY_TYPES_ERROR); + } } } From d03e3b3a5192b8e6ef205d507bf9b46de48c8459 Mon Sep 17 00:00:00 2001 From: Michael Simacek Date: Fri, 8 Oct 2021 07:40:13 +0000 Subject: [PATCH 341/681] [GR-21590] Update imports PullRequest: graalpython/1987 --- vm/mx.vm/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index b62029f2e605..8c4e334b0a6e 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -75,7 +75,7 @@ }, { "name": "graalpython", - "version": "c6fc7c03df46b19bebe808bc67fc42a484473232", + "version": "f100bf8941139ece20ec0fed3160ed9191cdbbf5", "dynamic": True, "urls": [ {"url": "https://github.com/graalvm/graalpython.git", "kind": "git"}, From 3957e9b3534fbf948a947f65c5c3ff1bb09c3a98 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Wed, 6 Oct 2021 18:26:10 +0200 Subject: [PATCH 342/681] Fail gracefully when invoking method pointers to null or uncompiled methods. --- ....java => InvalidMethodPointerHandler.java} | 33 ++++++++++++++----- .../ClassInitializationFeature.java | 5 ++- .../oracle/svm/hosted/image/NativeImage.java | 29 ++++++++++++++-- .../hosted/image/NativeImageHeapWriter.java | 12 ++----- .../oracle/svm/hosted/meta/MethodPointer.java | 22 +++++++++---- .../svm/hosted/meta/UniverseBuilder.java | 6 ++-- 6 files changed, 74 insertions(+), 33 deletions(-) rename substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/{InvalidVTableEntryHandler.java => InvalidMethodPointerHandler.java} (65%) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidVTableEntryHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java similarity index 65% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidVTableEntryHandler.java rename to substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java index 43b7f36d57f5..1d8e548f8c29 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidVTableEntryHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java @@ -43,16 +43,33 @@ import com.oracle.svm.util.ReflectionUtil; /** - * Provides a stub method that can be used to fill otherwise unused vtable slots. Instead of a - * segfault, this method provides a full diagnostic output with a stack trace. + * Provides stub methods that can be used for uninitialized method pointers. Instead of a segfault, + * the stubs provide full diagnostic output with a stack trace. */ -public final class InvalidVTableEntryHandler { - public static final Method HANDLER_METHOD = ReflectionUtil.lookupMethod(InvalidVTableEntryHandler.class, "invalidVTableEntryHandler"); - public static final String MSG = "Fatal error: Virtual method call used an illegal vtable entry that was seen as unused by the static analysis"; +public final class InvalidMethodPointerHandler { + public static final Method INVALID_VTABLE_ENTRY_HANDLER_METHOD = ReflectionUtil.lookupMethod(InvalidMethodPointerHandler.class, "invalidVTableEntryHandler"); + public static final String INVALID_VTABLE_ENTRY_MSG = "Fatal error: Virtual method call used an illegal vtable entry that was seen as unused by the static analysis"; + + public static final Method METHOD_POINTER_INVALID_HANDLER_METHOD = ReflectionUtil.lookupMethod(InvalidMethodPointerHandler.class, "methodPointerInvalidHandler"); + public static final String METHOD_POINTER_INVALID_MSG = "Fatal error: Method pointer invoked on a method that is null, was not registered for compilation, or was not seen as invoked by the static analysis"; @StubCallingConvention @NeverInline("We need a separate frame that stores all registers") private static void invalidVTableEntryHandler() { + Pointer callerSP = KnownIntrinsics.readCallerStackPointer(); + CodePointer callerIP = KnownIntrinsics.readReturnAddress(); + failFatally(callerSP, callerIP, INVALID_VTABLE_ENTRY_MSG); + } + + @StubCallingConvention + @NeverInline("We need a separate frame that stores all registers") + private static void methodPointerInvalidHandler() { + Pointer callerSP = KnownIntrinsics.readCallerStackPointer(); + CodePointer callerIP = KnownIntrinsics.readReturnAddress(); + failFatally(callerSP, callerIP, METHOD_POINTER_INVALID_MSG); + } + + private static void failFatally(Pointer callerSP, CodePointer callerIP, String message) { VMThreads.StatusSupport.setStatusIgnoreSafepoints(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); @@ -63,13 +80,11 @@ private static void invalidVTableEntryHandler() { * from the method that has the illegal vtable call. That can be helpful when debugging the * cause of the fatal error. */ - Pointer callerSP = KnownIntrinsics.readCallerStackPointer(); - CodePointer callerIP = KnownIntrinsics.readReturnAddress(); LogHandler logHandler = ImageSingletons.lookup(LogHandler.class); - Log log = Log.enterFatalContext(logHandler, callerIP, MSG, null); + Log log = Log.enterFatalContext(logHandler, callerIP, message, null); if (log != null) { SubstrateDiagnostics.printFatalError(log, callerSP, callerIP, WordFactory.nullPointer(), true); - log.string(MSG).newline(); + log.string(message).newline(); } logHandler.fatalError(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java index deda2c6fc758..5572fe9892a1 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java @@ -44,6 +44,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.nativeimage.c.function.CFunctionPointer; import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; @@ -354,11 +355,13 @@ private static ClassInitializationInfo buildRuntimeInitializationInfo(FeatureImp * information. */ assert type.isLinked(); + CFunctionPointer classInitializerFunction = null; AnalysisMethod classInitializer = type.getClassInitializer(); if (classInitializer != null) { assert classInitializer.getCode() != null; access.registerAsCompiled(classInitializer); + classInitializerFunction = MethodPointer.factory(classInitializer); } - return new ClassInitializationInfo(MethodPointer.factory(classInitializer)); + return new ClassInitializationInfo(classInitializerFunction); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java index ef1f7597e74b..d43e640168db 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java @@ -59,6 +59,7 @@ import org.graalvm.compiler.debug.Indent; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.c.function.CFunctionPointer; +import org.graalvm.nativeimage.hosted.Feature; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; @@ -77,9 +78,11 @@ import com.oracle.svm.core.BuildArtifacts; import com.oracle.svm.core.BuildArtifacts.ArtifactType; import com.oracle.svm.core.FrameAccess; +import com.oracle.svm.core.InvalidMethodPointerHandler; import com.oracle.svm.core.Isolates; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.SubstrateUtil; +import com.oracle.svm.core.annotate.AutomaticFeature; import com.oracle.svm.core.c.CConst; import com.oracle.svm.core.c.CGlobalDataImpl; import com.oracle.svm.core.c.CHeader; @@ -96,6 +99,7 @@ import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.core.option.HostedOptionValues; import com.oracle.svm.core.util.UserError; +import com.oracle.svm.hosted.FeatureImpl; import com.oracle.svm.hosted.NativeImageOptions; import com.oracle.svm.hosted.c.CGlobalDataFeature; import com.oracle.svm.hosted.c.NativeLibraries; @@ -564,14 +568,24 @@ private static boolean checkEmbeddedOffset(ProgbitsSectionImpl sectionImpl, fina return true; } - private static void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, final int offset, final RelocatableBuffer.Info info) { + private void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, final int offset, final RelocatableBuffer.Info info) { assert info.getTargetObject() instanceof CFunctionPointer : "Wrong type for FunctionPointer relocation: " + info.getTargetObject().toString(); final int functionPointerRelocationSize = 8; assert info.getRelocationSize() == functionPointerRelocationSize : "Function relocation: " + info.getRelocationSize() + " should be " + functionPointerRelocationSize + " bytes."; // References to functions are via relocations to the symbol for the function. - ResolvedJavaMethod method = ((MethodPointer) info.getTargetObject()).getMethod(); + MethodPointer methodPointer = (MethodPointer) info.getTargetObject(); + HostedMethod target = null; + boolean valid = methodPointer.isValid(); + if (valid) { + ResolvedJavaMethod method = methodPointer.getMethod(); + target = (method instanceof HostedMethod) ? (HostedMethod) method : heap.getUniverse().lookup(method); + valid = target.isCompiled(); + } + if (!valid) { + target = metaAccess.lookupJavaMethod(InvalidMethodPointerHandler.METHOD_POINTER_INVALID_HANDLER_METHOD); + } // A reference to a method. Mark the relocation site using the symbol name. - sectionImpl.markRelocationSite(offset, RelocationKind.getDirect(functionPointerRelocationSize), localSymbolNameForMethod(method), false, 0L); + sectionImpl.markRelocationSite(offset, RelocationKind.getDirect(functionPointerRelocationSize), localSymbolNameForMethod(target), false, 0L); } private static boolean isAddendAligned(Architecture arch, long addend, RelocationKind kind) { @@ -956,3 +970,12 @@ protected NativeTextSectionImpl(RelocatableBuffer relocatableBuffer, ObjectFile protected final NativeImageCodeCache codeCache; } } + +@AutomaticFeature +final class MethodPointerInvalidHandlerFeature implements Feature { + @Override + public void beforeAnalysis(BeforeAnalysisAccess a) { + FeatureImpl.BeforeAnalysisAccessImpl access = (FeatureImpl.BeforeAnalysisAccessImpl) a; + access.registerAsCompiled(InvalidMethodPointerHandler.METHOD_POINTER_INVALID_HANDLER_METHOD); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java index 71c4684c9081..a06325b43b60 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java @@ -55,13 +55,11 @@ import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo; import com.oracle.svm.hosted.meta.HostedClass; import com.oracle.svm.hosted.meta.HostedField; -import com.oracle.svm.hosted.meta.HostedMethod; import com.oracle.svm.hosted.meta.MaterializedConstantFields; import com.oracle.svm.hosted.meta.MethodPointer; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; import sun.misc.Unsafe; /** @@ -242,14 +240,8 @@ private void addNonDataRelocation(RelocatableBuffer buffer, int index, Relocated mustBeReferenceAligned(index); assert pointer instanceof CFunctionPointer : "unknown relocated pointer " + pointer; assert pointer instanceof MethodPointer : "cannot create relocation for unknown FunctionPointer " + pointer; - - ResolvedJavaMethod method = ((MethodPointer) pointer).getMethod(); - HostedMethod hMethod = method instanceof HostedMethod ? (HostedMethod) method : heap.getUniverse().lookup(method); - if (hMethod.isCompiled()) { - // Only compiled methods inserted in vtables require relocation. - int pointerSize = ConfigurationValues.getTarget().wordSize; - addDirectRelocationWithoutAddend(buffer, index, pointerSize, pointer); - } + int pointerSize = ConfigurationValues.getTarget().wordSize; + addDirectRelocationWithoutAddend(buffer, index, pointerSize, pointer); } private static void writePrimitive(RelocatableBuffer buffer, int index, JavaConstant con) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MethodPointer.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MethodPointer.java index d6c92fbcf01e..9aa3dd79710c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MethodPointer.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MethodPointer.java @@ -29,32 +29,40 @@ import org.graalvm.nativeimage.c.function.CFunctionPointer; import org.graalvm.word.ComparableWord; +import com.oracle.svm.core.InvalidMethodPointerHandler; + import jdk.vm.ci.meta.ResolvedJavaMethod; /** * A pointer to the compiled code of a method. */ public class MethodPointer implements CFunctionPointer { + private static final MethodPointer INVALID = new MethodPointer(null); private final ResolvedJavaMethod method; public static CFunctionPointer factory(ResolvedJavaMethod method) { - if (method == null) { - return null; - } else { - return new MethodPointer(method); - } + return (method != null) ? new MethodPointer(method) : INVALID; } protected MethodPointer(ResolvedJavaMethod method) { - assert method != null; this.method = method; } + public boolean isValid() { + return (method != null); + } + public ResolvedJavaMethod getMethod() { + assert isValid(); return method; } + /** + * Always {@code false} because even a pointer to {@code null} or to a method that is not + * compiled will eventually be replaced by + * {@link InvalidMethodPointerHandler#METHOD_POINTER_INVALID_HANDLER_METHOD}. + */ @Override public boolean isNull() { return false; @@ -62,7 +70,7 @@ public boolean isNull() { @Override public boolean isNonNull() { - return true; + return !isNull(); } @Override 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 b4e1414aa82c..84b69d9d54c7 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 @@ -63,7 +63,7 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.results.AbstractAnalysisResultsBuilder; import com.oracle.svm.core.FunctionPointerHolder; -import com.oracle.svm.core.InvalidVTableEntryHandler; +import com.oracle.svm.core.InvalidMethodPointerHandler; import com.oracle.svm.core.StaticFieldsSupport; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.SubstrateUtil; @@ -674,7 +674,7 @@ private void buildVTables() { * To avoid segfaults when jumping to address 0, all unused vtable entries are filled with a * stub that reports a fatal error. */ - HostedMethod invalidVTableEntryHandler = hMetaAccess.lookupJavaMethod(InvalidVTableEntryHandler.HANDLER_METHOD); + HostedMethod invalidVTableEntryHandler = hMetaAccess.lookupJavaMethod(InvalidMethodPointerHandler.INVALID_VTABLE_ENTRY_HANDLER_METHOD); for (HostedType type : hUniverse.getTypes()) { if (type.isArray()) { @@ -999,6 +999,6 @@ final class InvalidVTableEntryFeature implements Feature { @Override public void beforeAnalysis(BeforeAnalysisAccess a) { BeforeAnalysisAccessImpl access = (BeforeAnalysisAccessImpl) a; - access.registerAsCompiled(InvalidVTableEntryHandler.HANDLER_METHOD); + access.registerAsCompiled(InvalidMethodPointerHandler.INVALID_VTABLE_ENTRY_HANDLER_METHOD); } } From 31469571fa38a34ca7e5da48bf67263ed6acdd35 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Thu, 7 Oct 2021 15:46:27 +0200 Subject: [PATCH 343/681] Disallow MethodPointer for null targets entirely. --- .../graal/llvm/LLVMNativeImageCodeCache.java | 2 +- .../svm/core/InvalidMethodPointerHandler.java | 8 +++--- .../graal/hosted/DeoptimizationFeature.java | 2 +- .../ClassInitializationFeature.java | 4 +-- .../code/CEntryPointCallStubSupport.java | 2 +- .../code/CEntryPointLiteralFeature.java | 2 +- .../hosted/image/LIRNativeImageCodeCache.java | 2 +- .../oracle/svm/hosted/image/NativeImage.java | 15 ++++------- .../oracle/svm/hosted/meta/MethodPointer.java | 27 +++++-------------- .../svm/hosted/meta/UniverseBuilder.java | 2 +- .../svm/jni/access/JNIAccessibleMethod.java | 12 ++++----- .../functions/JNIFunctionTablesFeature.java | 6 ++--- .../svm/reflect/hosted/ReflectionFeature.java | 2 +- 13 files changed, 33 insertions(+), 53 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java index c931cf6b2cc2..9ee35d616beb 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java @@ -207,7 +207,7 @@ private void linkCompiledBatches(BatchExecutor executor, DebugContext debug, int stackMapDumper.close(); HostedMethod firstMethod = (HostedMethod) getFirstCompilation().getMethods()[0]; - buildRuntimeMetadata(MethodPointer.factory(firstMethod), WordFactory.signed(textSectionInfo.getCodeSize())); + buildRuntimeMetadata(new MethodPointer(firstMethod), WordFactory.signed(textSectionInfo.getCodeSize())); } private void llvmOptimize(DebugContext debug, String outputPath, String inputPath) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java index 1d8e548f8c29..4b759ea3e307 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java @@ -50,8 +50,8 @@ public final class InvalidMethodPointerHandler { public static final Method INVALID_VTABLE_ENTRY_HANDLER_METHOD = ReflectionUtil.lookupMethod(InvalidMethodPointerHandler.class, "invalidVTableEntryHandler"); public static final String INVALID_VTABLE_ENTRY_MSG = "Fatal error: Virtual method call used an illegal vtable entry that was seen as unused by the static analysis"; - public static final Method METHOD_POINTER_INVALID_HANDLER_METHOD = ReflectionUtil.lookupMethod(InvalidMethodPointerHandler.class, "methodPointerInvalidHandler"); - public static final String METHOD_POINTER_INVALID_MSG = "Fatal error: Method pointer invoked on a method that is null, was not registered for compilation, or was not seen as invoked by the static analysis"; + public static final Method METHOD_POINTER_NOT_COMPILED_HANDLER_METHOD = ReflectionUtil.lookupMethod(InvalidMethodPointerHandler.class, "methodPointerNotCompiledHandler"); + public static final String METHOD_POINTER_NOT_COMPILED_MSG = "Fatal error: Method pointer invoked on a method that was not compiled because it was not seen as invoked by the static analysis nor was it directly registered for compilation"; @StubCallingConvention @NeverInline("We need a separate frame that stores all registers") @@ -63,10 +63,10 @@ private static void invalidVTableEntryHandler() { @StubCallingConvention @NeverInline("We need a separate frame that stores all registers") - private static void methodPointerInvalidHandler() { + private static void methodPointerNotCompiledHandler() { Pointer callerSP = KnownIntrinsics.readCallerStackPointer(); CodePointer callerIP = KnownIntrinsics.readReturnAddress(); - failFatally(callerSP, callerIP, METHOD_POINTER_INVALID_MSG); + failFatally(callerSP, callerIP, METHOD_POINTER_NOT_COMPILED_MSG); } private static void failFatally(Pointer callerSP, CodePointer callerIP, String message) { diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/DeoptimizationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/DeoptimizationFeature.java index 3fee955d70b4..0180a73028dd 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/DeoptimizationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/DeoptimizationFeature.java @@ -126,6 +126,6 @@ public void beforeCompilation(BeforeCompilationAccess a) { CompilationAccessImpl config = (CompilationAccessImpl) a; config.registerAsImmutable(ImageSingletons.lookup(DeoptimizationSupport.class)); HostedMetaAccess metaAccess = config.getMetaAccess(); - DeoptimizationSupport.setDeoptStubPointer(MethodPointer.factory(metaAccess.lookupJavaMethod(deoptStubMethod))); + DeoptimizationSupport.setDeoptStubPointer(new MethodPointer(metaAccess.lookupJavaMethod(deoptStubMethod))); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java index 5572fe9892a1..9060a15a291a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java @@ -341,7 +341,7 @@ private static ClassInitializationInfo buildRuntimeInitializationInfo(FeatureImp /* Synthesize a VerifyError to be thrown at run time. */ AnalysisMethod throwVerifyError = access.getMetaAccess().lookupJavaMethod(ExceptionSynthesizer.throwExceptionMethod(VerifyError.class)); access.registerAsCompiled(throwVerifyError); - return new ClassInitializationInfo(MethodPointer.factory(throwVerifyError)); + return new ClassInitializationInfo(new MethodPointer(throwVerifyError)); } catch (Throwable t) { /* * All other linking errors will be reported as NoClassDefFoundError when initialization @@ -360,7 +360,7 @@ private static ClassInitializationInfo buildRuntimeInitializationInfo(FeatureImp if (classInitializer != null) { assert classInitializer.getCode() != null; access.registerAsCompiled(classInitializer); - classInitializerFunction = MethodPointer.factory(classInitializer); + classInitializerFunction = new MethodPointer(classInitializer); } return new ClassInitializationInfo(classInitializerFunction); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointCallStubSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointCallStubSupport.java index c6eb898ece3b..90a80cb80adf 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointCallStubSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointCallStubSupport.java @@ -110,7 +110,7 @@ public AnalysisMethod registerJavaStubForMethod(AnalysisMethod method) { if (value == null) { assert !bb.getUniverse().sealed(); AnalysisMethod nativeStub = registerStubForMethod(method, () -> CEntryPointData.create(method)); - CFunctionPointer nativeStubAddress = MethodPointer.factory(nativeStub); + CFunctionPointer nativeStubAddress = new MethodPointer(nativeStub); String stubName = SubstrateUtil.uniqueShortName(method); ResolvedJavaType holderClass = bb.getMetaAccess().lookupJavaType(IsolateLeaveStub.class).getWrapped(); CEntryPointJavaCallStubMethod stub = new CEntryPointJavaCallStubMethod(method.getWrapped(), stubName, holderClass, nativeStubAddress); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointLiteralFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointLiteralFeature.java index c5fd686aad87..1e69f5e974f8 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointLiteralFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointLiteralFeature.java @@ -81,7 +81,7 @@ public Object apply(Object source) { * Only during compilation and native image writing, we do the actual * replacement. */ - return MethodPointer.factory(hStub); + return new MethodPointer(hStub); } } return source; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java index a1ae28bde450..19e985859367 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java @@ -103,7 +103,7 @@ public void layoutMethods(DebugContext debug, String imageName, BigBang bb, Fork codeCacheSize = NumUtil.roundUp(codeCacheSize + compilation.getTargetCodeSize(), SubstrateOptions.codeAlignment()); } - buildRuntimeMetadata(MethodPointer.factory(firstMethod), WordFactory.unsigned(codeCacheSize)); + buildRuntimeMetadata(new MethodPointer(firstMethod), WordFactory.unsigned(codeCacheSize)); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java index d43e640168db..b41457106299 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java @@ -574,15 +574,10 @@ private void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, f assert info.getRelocationSize() == functionPointerRelocationSize : "Function relocation: " + info.getRelocationSize() + " should be " + functionPointerRelocationSize + " bytes."; // References to functions are via relocations to the symbol for the function. MethodPointer methodPointer = (MethodPointer) info.getTargetObject(); - HostedMethod target = null; - boolean valid = methodPointer.isValid(); - if (valid) { - ResolvedJavaMethod method = methodPointer.getMethod(); - target = (method instanceof HostedMethod) ? (HostedMethod) method : heap.getUniverse().lookup(method); - valid = target.isCompiled(); - } - if (!valid) { - target = metaAccess.lookupJavaMethod(InvalidMethodPointerHandler.METHOD_POINTER_INVALID_HANDLER_METHOD); + ResolvedJavaMethod method = methodPointer.getMethod(); + HostedMethod target = (method instanceof HostedMethod) ? (HostedMethod) method : heap.getUniverse().lookup(method); + if (!target.isCompiled()) { + target = metaAccess.lookupJavaMethod(InvalidMethodPointerHandler.METHOD_POINTER_NOT_COMPILED_HANDLER_METHOD); } // A reference to a method. Mark the relocation site using the symbol name. sectionImpl.markRelocationSite(offset, RelocationKind.getDirect(functionPointerRelocationSize), localSymbolNameForMethod(target), false, 0L); @@ -976,6 +971,6 @@ final class MethodPointerInvalidHandlerFeature implements Feature { @Override public void beforeAnalysis(BeforeAnalysisAccess a) { FeatureImpl.BeforeAnalysisAccessImpl access = (FeatureImpl.BeforeAnalysisAccessImpl) a; - access.registerAsCompiled(InvalidMethodPointerHandler.METHOD_POINTER_INVALID_HANDLER_METHOD); + access.registerAsCompiled(InvalidMethodPointerHandler.METHOD_POINTER_NOT_COMPILED_HANDLER_METHOD); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MethodPointer.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MethodPointer.java index 9aa3dd79710c..d2af190eba9b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MethodPointer.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MethodPointer.java @@ -26,43 +26,28 @@ import static com.oracle.svm.core.util.VMError.shouldNotReachHere; +import java.util.Objects; + import org.graalvm.nativeimage.c.function.CFunctionPointer; import org.graalvm.word.ComparableWord; -import com.oracle.svm.core.InvalidMethodPointerHandler; - import jdk.vm.ci.meta.ResolvedJavaMethod; /** * A pointer to the compiled code of a method. */ -public class MethodPointer implements CFunctionPointer { - private static final MethodPointer INVALID = new MethodPointer(null); - +public final class MethodPointer implements CFunctionPointer { private final ResolvedJavaMethod method; - public static CFunctionPointer factory(ResolvedJavaMethod method) { - return (method != null) ? new MethodPointer(method) : INVALID; - } - - protected MethodPointer(ResolvedJavaMethod method) { + public MethodPointer(ResolvedJavaMethod method) { + Objects.requireNonNull(method); this.method = method; } - public boolean isValid() { - return (method != null); - } - public ResolvedJavaMethod getMethod() { - assert isValid(); return method; } - /** - * Always {@code false} because even a pointer to {@code null} or to a method that is not - * compiled will eventually be replaced by - * {@link InvalidMethodPointerHandler#METHOD_POINTER_INVALID_HANDLER_METHOD}. - */ @Override public boolean isNull() { return false; @@ -70,7 +55,7 @@ public boolean isNull() { @Override public boolean isNonNull() { - return !isNull(); + return true; } @Override 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 84b69d9d54c7..c4fd6a6496f4 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 @@ -925,7 +925,7 @@ private void buildHubs() { * We install a CodePointer in the vtable; when generating relocation info, we will * know these point into .text */ - vtable[idx] = MethodPointer.factory(type.vtable[idx]); + vtable[idx] = new MethodPointer(type.vtable[idx]); } // pointer maps in Dynamic Hub diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessibleMethod.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessibleMethod.java index adefdc5ab15d..5c85406a0397 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessibleMethod.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessibleMethod.java @@ -124,13 +124,13 @@ public boolean isStatic() { void finishBeforeCompilation(CompilationAccessImpl access) { HostedUniverse hUniverse = access.getUniverse(); AnalysisUniverse aUniverse = access.getUniverse().getBigBang().getUniverse(); - varargsCallWrapper = MethodPointer.factory(hUniverse.lookup(aUniverse.lookup(varargsCallWrapperMethod))); - arrayCallWrapper = MethodPointer.factory(hUniverse.lookup(aUniverse.lookup(arrayCallWrapperMethod))); - valistCallWrapper = MethodPointer.factory(hUniverse.lookup(aUniverse.lookup(valistCallWrapperMethod))); + varargsCallWrapper = new MethodPointer(hUniverse.lookup(aUniverse.lookup(varargsCallWrapperMethod))); + arrayCallWrapper = new MethodPointer(hUniverse.lookup(aUniverse.lookup(arrayCallWrapperMethod))); + valistCallWrapper = new MethodPointer(hUniverse.lookup(aUniverse.lookup(valistCallWrapperMethod))); if (!Modifier.isStatic(modifiers) && !Modifier.isAbstract(modifiers)) { - varargsNonvirtualCallWrapper = MethodPointer.factory(hUniverse.lookup(aUniverse.lookup(varargsNonvirtualCallWrapperMethod))); - arrayNonvirtualCallWrapper = MethodPointer.factory(hUniverse.lookup(aUniverse.lookup(arrayNonvirtualCallWrapperMethod))); - valistNonvirtualCallWrapper = MethodPointer.factory(hUniverse.lookup(aUniverse.lookup(valistNonvirtualCallWrapperMethod))); + varargsNonvirtualCallWrapper = new MethodPointer(hUniverse.lookup(aUniverse.lookup(varargsNonvirtualCallWrapperMethod))); + arrayNonvirtualCallWrapper = new MethodPointer(hUniverse.lookup(aUniverse.lookup(arrayNonvirtualCallWrapperMethod))); + valistNonvirtualCallWrapper = new MethodPointer(hUniverse.lookup(aUniverse.lookup(valistNonvirtualCallWrapperMethod))); } setHidingSubclasses(access.getMetaAccess(), this::anyMatchIgnoreReturnType); } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctionTablesFeature.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctionTablesFeature.java index c317c23ac4ef..602e68473758 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctionTablesFeature.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctionTablesFeature.java @@ -192,7 +192,7 @@ private static CFunctionPointer prepareCallTrampoline(CompilationAccessImpl acce HostedMethod hostedTrampoline = access.getUniverse().lookup(analysisTrampoline); hostedTrampoline.compilationInfo.setCustomParseFunction(trampolineMethod.createCustomParseFunction()); hostedTrampoline.compilationInfo.setCustomCompileFunction(trampolineMethod.createCustomCompileFunction()); - return MethodPointer.factory(hostedTrampoline); + return new MethodPointer(hostedTrampoline); } private static ResolvedJavaMethod getSingleMethod(MetaAccessProvider metaAccess, Class holder) { @@ -203,7 +203,7 @@ private static ResolvedJavaMethod getSingleMethod(MetaAccessProvider metaAccess, private static CFunctionPointer getStubFunctionPointer(CompilationAccessImpl access, HostedMethod method) { AnalysisMethod stub = CEntryPointCallStubSupport.singleton().getStubForMethod(method.getWrapped()); - return MethodPointer.factory(access.getUniverse().lookup(stub)); + return new MethodPointer(access.getUniverse().lookup(stub)); } private void fillJNIInvocationInterfaceTable(CompilationAccessImpl access, CFunctionPointer[] table, CFunctionPointer defaultValue) { @@ -236,7 +236,7 @@ private void fillJNIFunctionsTable(CompilationAccessImpl access, CFunctionPointe HostedMethod hostedMethod = access.getUniverse().lookup(analysisMethod); int offset = field.getOffsetInfo().getProperty(); - setFunctionPointerTable(table, offset, MethodPointer.factory(hostedMethod)); + setFunctionPointerTable(table, offset, new MethodPointer(hostedMethod)); } for (CallVariant variant : CallVariant.values()) { CFunctionPointer trampoline = prepareCallTrampoline(access, variant, false); diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionFeature.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionFeature.java index 827c4ea7d274..02684b29ba1e 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionFeature.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionFeature.java @@ -154,7 +154,7 @@ private Object createAccessor(Executable member) { private CFunctionPointer register(ResolvedJavaMethod method) { AnalysisMethod aMethod = method instanceof AnalysisMethod ? (AnalysisMethod) method : analysisAccess.getUniverse().lookup(method); analysisAccess.registerAsCompiled(aMethod); - return MethodPointer.factory(aMethod); + return new MethodPointer(aMethod); } protected ResolvedJavaMethod createReflectiveInvokeMethod(String name, ResolvedJavaMethod prototype, Method method) { From d1cd9734ef45f09873c7ef45a537a2160df07b52 Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Wed, 22 Sep 2021 11:59:08 +0200 Subject: [PATCH 344/681] Add entry point to dump methods present in the image --- .../oracle/svm/core/code/CodeInfoDecoder.java | 32 +++++------ .../svm/core/code/MethodMetadataEncoder.java | 54 ++++++++++++------- .../RuntimeReflectionConstructors.java | 8 +-- .../reflect/hosted/ReflectionDataBuilder.java | 18 +++---- .../RuntimeReflectionConstructorsImpl.java | 20 +++---- 5 files changed, 72 insertions(+), 60 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoDecoder.java index 76f6a232252b..d1cfdb170f44 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoDecoder.java @@ -568,9 +568,9 @@ public static Executable[] getMethodMetadata(int typeID) { int modifiers = dataReader.getUVInt(); - int paramCount = dataReader.getUVInt(); - Class[] paramTypes = new Class[paramCount]; - for (int j = 0; j < paramCount; ++j) { + int paramTypeCount = dataReader.getUVInt(); + Class[] paramTypes = new Class[paramTypeCount]; + for (int j = 0; j < paramTypeCount; ++j) { int paramTypeIndex = dataReader.getSVInt(); paramTypes[j] = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceClasses(info), paramTypeIndex); } @@ -606,27 +606,27 @@ public static Executable[] getMethodMetadata(int typeID) { typeAnnotations[j] = (byte) dataReader.getS1(); } - boolean parameterDataPresent = dataReader.getU1() == 1; - String[] parameterNames = null; - int[] parameterModifiers = null; - if (parameterDataPresent) { - int parameterCount = dataReader.getUVInt(); - parameterNames = new String[parameterCount]; - parameterModifiers = new int[parameterCount]; - for (int j = 0; j < paramCount; ++j) { - int parameterNameIndex = dataReader.getSVInt(); - parameterNames[j] = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceMethodNames(info), parameterNameIndex); - parameterModifiers[j] = dataReader.getS4(); + boolean reflectParameterDataPresent = dataReader.getU1() == 1; + String[] reflectParameterNames = null; + int[] reflectParameterModifiers = null; + if (reflectParameterDataPresent) { + int reflectParameterCount = dataReader.getUVInt(); + reflectParameterNames = new String[reflectParameterCount]; + reflectParameterModifiers = new int[reflectParameterCount]; + for (int j = 0; j < reflectParameterCount; ++j) { + int reflectParameterNameIndex = dataReader.getSVInt(); + reflectParameterNames[j] = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceMethodNames(info), reflectParameterNameIndex); + reflectParameterModifiers[j] = dataReader.getS4(); } } if (name.equals("")) { assert returnType == void.class; methods[i] = ImageSingletons.lookup(RuntimeReflectionConstructors.class).newConstructor(declaringClass, paramTypes, exceptionTypes, modifiers, signature, - annotations, parameterAnnotations, typeAnnotations, parameterNames, parameterModifiers); + annotations, parameterAnnotations, typeAnnotations, reflectParameterNames, reflectParameterModifiers); } else { methods[i] = ImageSingletons.lookup(RuntimeReflectionConstructors.class).newMethod(declaringClass, name, paramTypes, returnType, exceptionTypes, modifiers, signature, - annotations, parameterAnnotations, null, typeAnnotations, parameterNames, parameterModifiers); + annotations, parameterAnnotations, null, typeAnnotations, reflectParameterNames, reflectParameterModifiers); } } return methods; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/MethodMetadataEncoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/MethodMetadataEncoder.java index 1c115fed93de..1d31af31d210 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/MethodMetadataEncoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/MethodMetadataEncoder.java @@ -44,6 +44,7 @@ import java.util.Set; import java.util.TreeMap; +import org.graalvm.collections.Pair; import org.graalvm.compiler.core.common.util.TypeConversion; import org.graalvm.compiler.core.common.util.UnsafeArrayTypeWriter; import org.graalvm.nativeimage.ImageSingletons; @@ -57,6 +58,7 @@ import com.oracle.svm.core.util.ByteArrayReader; import com.oracle.svm.util.ReflectionUtil; +import jdk.vm.ci.meta.JavaType; import sun.invoke.util.Wrapper; import sun.reflect.annotation.AnnotationType; import sun.reflect.annotation.TypeAnnotation; @@ -67,7 +69,7 @@ public class MethodMetadataEncoder { public static final int NO_METHOD_METADATA = -1; private CodeInfoEncoder.Encoders encoders; - private TreeMap> methodData; + private TreeMap>> methodData; private byte[] methodDataEncoding; private byte[] methodDataIndexEncoding; @@ -111,7 +113,7 @@ public void prepareMetadataForMethod(SharedMethod method, Executable reflectMeth } /* Register string values in annotations */ - registerStrings(GuardedAnnotationAccess.getDeclaredAnnotations(reflectMethod)); + registerStrings(GuardedAnnotationAccess.getDeclaredAnnotations(method)); for (Annotation[] annotations : reflectMethod.getParameterAnnotations()) { registerStrings(annotations); } @@ -126,7 +128,7 @@ public void prepareMetadataForMethod(SharedMethod method, Executable reflectMeth } SharedType declaringType = (SharedType) method.getDeclaringClass(); - methodData.computeIfAbsent(declaringType, t -> new HashSet<>()).add(reflectMethod); + methodData.computeIfAbsent(declaringType, t -> new HashSet<>()).add(Pair.create(method, reflectMethod)); } private static final Method hasRealParameterData = ReflectionUtil.lookupMethod(Executable.class, "hasRealParameterData"); @@ -135,9 +137,9 @@ private void encodeMethodMetadata() { UnsafeArrayTypeWriter dataEncodingBuffer = UnsafeArrayTypeWriter.create(ByteArrayReader.supportsUnalignedMemoryAccess()); UnsafeArrayTypeWriter indexEncodingBuffer = UnsafeArrayTypeWriter.create(ByteArrayReader.supportsUnalignedMemoryAccess()); long lastTypeID = -1; - for (Map.Entry> entry : methodData.entrySet()) { + for (Map.Entry>> entry : methodData.entrySet()) { SharedType declaringType = entry.getKey(); - Set methods = entry.getValue(); + Set> methods = entry.getValue(); long typeID = declaringType.getHub().getTypeID(); assert typeID > lastTypeID; lastTypeID++; @@ -148,62 +150,70 @@ private void encodeMethodMetadata() { long index = dataEncodingBuffer.getBytesWritten(); indexEncodingBuffer.putS4(index); dataEncodingBuffer.putUV(methods.size()); - for (Executable method : methods) { - Class declaringClass = method.getDeclaringClass(); + for (Pair method : methods) { + SharedMethod hostedMethod = method.getLeft(); + Executable reflectMethod = method.getRight(); + + Class declaringClass = getJavaClass((SharedType) hostedMethod.getDeclaringClass()); final int classIndex = encoders.sourceClasses.getIndex(declaringClass); dataEncodingBuffer.putSV(classIndex); - String name = method instanceof Constructor ? "" : ((Method) method).getName(); + String name = hostedMethod.isConstructor() ? "" : hostedMethod.getName(); final int nameIndex = encoders.sourceMethodNames.getIndex(name); dataEncodingBuffer.putSV(nameIndex); - dataEncodingBuffer.putUV(method.getModifiers()); + dataEncodingBuffer.putUV(reflectMethod.getModifiers()); - Class[] parameterTypes = method.getParameterTypes(); + /* Parameter types do not include the receiver */ + JavaType[] parameterTypes = hostedMethod.getSignature().toParameterTypes(null); dataEncodingBuffer.putUV(parameterTypes.length); - for (Class parameterType : parameterTypes) { - final int paramClassIndex = encoders.sourceClasses.getIndex(parameterType); + for (JavaType parameterType : parameterTypes) { + Class parameterClass = getJavaClass((SharedType) parameterType); + final int paramClassIndex = encoders.sourceClasses.getIndex(parameterClass); dataEncodingBuffer.putSV(paramClassIndex); } - Class returnType = method instanceof Constructor ? void.class : ((Method) method).getReturnType(); + Class returnType = void.class; + if (!hostedMethod.isConstructor()) { + returnType = getJavaClass((SharedType) hostedMethod.getSignature().getReturnType(null)); + } final int returnTypeIndex = encoders.sourceClasses.getIndex(returnType); dataEncodingBuffer.putSV(returnTypeIndex); /* Only include types that are in the image (i.e. that can actually be thrown) */ - Class[] exceptionTypes = filterTypes(method.getExceptionTypes()); + Class[] exceptionTypes = filterTypes(reflectMethod.getExceptionTypes()); dataEncodingBuffer.putUV(exceptionTypes.length); for (Class exceptionClazz : exceptionTypes) { final int exceptionClassIndex = encoders.sourceClasses.getIndex(exceptionClazz); dataEncodingBuffer.putSV(exceptionClassIndex); } - final int signatureIndex = encoders.sourceMethodNames.getIndex(getSignature(method)); + final int signatureIndex = encoders.sourceMethodNames.getIndex(getSignature(reflectMethod)); dataEncodingBuffer.putSV(signatureIndex); try { - byte[] annotations = encodeAnnotations(GuardedAnnotationAccess.getDeclaredAnnotations(method)); + byte[] annotations = encodeAnnotations(GuardedAnnotationAccess.getDeclaredAnnotations(hostedMethod)); dataEncodingBuffer.putUV(annotations.length); for (byte b : annotations) { dataEncodingBuffer.putS1(b); } - byte[] parameterAnnotations = encodeParameterAnnotations(method.getParameterAnnotations()); + byte[] parameterAnnotations = encodeParameterAnnotations(reflectMethod.getParameterAnnotations()); dataEncodingBuffer.putUV(parameterAnnotations.length); for (byte b : parameterAnnotations) { dataEncodingBuffer.putS1(b); } - byte[] typeAnnotations = encodeTypeAnnotations((TypeAnnotation[]) parseAllTypeAnnotations.invoke(null, method)); + byte[] typeAnnotations = encodeTypeAnnotations((TypeAnnotation[]) parseAllTypeAnnotations.invoke(null, reflectMethod)); dataEncodingBuffer.putUV(typeAnnotations.length); for (byte b : typeAnnotations) { dataEncodingBuffer.putS1(b); } - boolean parameterDataPresent = (boolean) hasRealParameterData.invoke(method); + boolean parameterDataPresent = (boolean) hasRealParameterData.invoke(reflectMethod); dataEncodingBuffer.putU1(parameterDataPresent ? 1 : 0); if (parameterDataPresent) { - Parameter[] parameters = method.getParameters(); + Parameter[] parameters = reflectMethod.getParameters(); dataEncodingBuffer.putUV(parameters.length); for (Parameter parameter : parameters) { final int parameterNameIndex = encoders.sourceMethodNames.getIndex(parameter.getName()); @@ -226,6 +236,10 @@ private void encodeMethodMetadata() { indexEncodingBuffer.toArray(methodDataIndexEncoding); } + private static Class getJavaClass(SharedType sharedType) { + return sharedType.getHub().getHostedJavaClass(); + } + private Class[] filterTypes(Class[] types) { List> filteredTypes = new ArrayList<>(); for (Class type : types) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/RuntimeReflectionConstructors.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/RuntimeReflectionConstructors.java index 70144b88b2a6..49da93a3384c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/RuntimeReflectionConstructors.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/RuntimeReflectionConstructors.java @@ -41,8 +41,8 @@ Method newMethod(Class declaringClass, byte[] parameterAnnotations, byte[] annotationDefault, byte[] typeAnnotations, - String[] parameterNames, - int[] parameterModifiers); + String[] reflectParameterNames, + int[] reflectParameterModifiers); Constructor newConstructor(Class declaringClass, Class[] parameterTypes, @@ -52,6 +52,6 @@ Constructor newConstructor(Class declaringClass, byte[] annotations, byte[] parameterAnnotations, byte[] typeAnnotations, - String[] parameterNames, - int[] parameterModifiers); + String[] reflectParameterNames, + int[] reflectParameterModifiers); } diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionDataBuilder.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionDataBuilder.java index 661ea1dd667e..0a5d70ab99a0 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionDataBuilder.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionDataBuilder.java @@ -231,12 +231,10 @@ private void processReachableTypes(DuringAnalysisAccessImpl access) { protected void processMethodMetadata(DuringAnalysisAccessImpl access) { if (SubstrateOptions.ConfigureReflectionMetadata.getValue()) { - /* Trigger creation of the AnalysisMethod objects needed to store metadata */ Set newQueriedMethods = new HashSet<>(); for (Executable method : queriedMethods) { if (!SubstitutionReflectivityFilter.shouldExclude(method, access.getMetaAccess(), access.getUniverse())) { - access.getMetaAccess().lookupJavaMethod(method); - registerMetadataForReflection(access, method); + registerMetadataForReflection(access, access.getMetaAccess().lookupJavaMethod(method), method); newQueriedMethods.add(method); } } @@ -248,7 +246,7 @@ protected void processMethodMetadata(DuringAnalysisAccessImpl access) { * method. */ if (method.isReachable() && method.hasJavaMethod()) { - registerMetadataForReflection(access, method.getJavaMethod()); + registerMetadataForReflection(access, method, method.getJavaMethod()); } } } @@ -256,18 +254,18 @@ protected void processMethodMetadata(DuringAnalysisAccessImpl access) { private static final Method parseAllTypeAnnotations = ReflectionUtil.lookupMethod(TypeAnnotationParser.class, "parseAllTypeAnnotations", AnnotatedElement.class); - private void registerMetadataForReflection(DuringAnalysisAccessImpl access, Executable reflectMethod) { + private void registerMetadataForReflection(DuringAnalysisAccessImpl access, AnalysisMethod analysisMethod, Executable reflectMethod) { /* * Reflection signature parsing will try to instantiate classes via Class.forName(). */ - makeTypeReachable(access, reflectMethod.getDeclaringClass(), false); + makeTypeReachable(access, analysisMethod.getDeclaringClass().getJavaClass(), false); for (TypeVariable type : reflectMethod.getTypeParameters()) { makeTypeReachable(access, type, true); } - for (Type paramType : reflectMethod.getGenericParameterTypes()) { + for (Type paramType : analysisMethod.getGenericParameterTypes()) { makeTypeReachable(access, paramType, true); } - if (reflectMethod instanceof Method) { + if (!analysisMethod.isConstructor()) { makeTypeReachable(access, ((Method) reflectMethod).getGenericReturnType(), true); } for (Type exceptionType : reflectMethod.getGenericExceptionTypes()) { @@ -277,7 +275,7 @@ private void registerMetadataForReflection(DuringAnalysisAccessImpl access, Exec /* * Enable runtime parsing of annotations */ - for (Annotation annotation : GuardedAnnotationAccess.getDeclaredAnnotations(reflectMethod)) { + for (Annotation annotation : GuardedAnnotationAccess.getDeclaredAnnotations(analysisMethod)) { makeTypeReachable(access, annotation.annotationType(), false); } for (Annotation[] parameterAnnotations : reflectMethod.getParameterAnnotations()) { @@ -304,7 +302,7 @@ private void makeTypeReachable(DuringAnalysisAccessImpl access, Type type, boole return; } seenTypes.add(type); - if (type instanceof Class) { + if (type instanceof Class && !SubstitutionReflectivityFilter.shouldExclude((Class) type, access.getMetaAccess(), access.getUniverse())) { Class clazz = (Class) type; if (access.getMetaAccess().lookupJavaType(clazz).registerAsReachable()) { access.requireAnalysisIteration(); diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/RuntimeReflectionConstructorsImpl.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/RuntimeReflectionConstructorsImpl.java index e6a1c33372e1..ec0bcbb0d9ca 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/RuntimeReflectionConstructorsImpl.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/RuntimeReflectionConstructorsImpl.java @@ -35,32 +35,32 @@ public class RuntimeReflectionConstructorsImpl implements RuntimeReflectionConstructors { @Override public Method newMethod(Class declaringClass, String name, Class[] parameterTypes, Class returnType, Class[] checkedExceptions, int modifiers, String signature, - byte[] annotations, byte[] parameterAnnotations, byte[] annotationDefault, byte[] typeAnnotations, String[] parameterNames, int[] parameterModifiers) { + byte[] annotations, byte[] parameterAnnotations, byte[] annotationDefault, byte[] typeAnnotations, String[] reflectParameterNames, int[] reflectParameterModifiers) { Target_java_lang_reflect_Method method = new Target_java_lang_reflect_Method(); method.constructor(declaringClass, name, parameterTypes, returnType, checkedExceptions, modifiers, -1, signature, annotations, parameterAnnotations, annotationDefault); - fillParameters(SubstrateUtil.cast(method, Target_java_lang_reflect_Executable.class), parameterNames, parameterModifiers); + fillReflectParameters(SubstrateUtil.cast(method, Target_java_lang_reflect_Executable.class), reflectParameterNames, reflectParameterModifiers); SubstrateUtil.cast(method, Target_java_lang_reflect_Executable.class).typeAnnotations = typeAnnotations; return SubstrateUtil.cast(method, Method.class); } @Override public Constructor newConstructor(Class declaringClass, Class[] parameterTypes, Class[] checkedExceptions, int modifiers, String signature, - byte[] annotations, byte[] parameterAnnotations, byte[] typeAnnotations, String[] parameterNames, int[] parameterModifiers) { + byte[] annotations, byte[] parameterAnnotations, byte[] typeAnnotations, String[] reflectParameterNames, int[] reflectParameterModifiers) { Target_java_lang_reflect_Constructor cons = new Target_java_lang_reflect_Constructor(); cons.constructor(declaringClass, parameterTypes, checkedExceptions, modifiers, -1, signature, annotations, parameterAnnotations); - fillParameters(SubstrateUtil.cast(cons, Target_java_lang_reflect_Executable.class), parameterNames, parameterModifiers); + fillReflectParameters(SubstrateUtil.cast(cons, Target_java_lang_reflect_Executable.class), reflectParameterNames, reflectParameterModifiers); SubstrateUtil.cast(cons, Target_java_lang_reflect_Executable.class).typeAnnotations = typeAnnotations; return SubstrateUtil.cast(cons, Constructor.class); } - private static void fillParameters(Target_java_lang_reflect_Executable executable, String[] parameterNames, int[] parameterModifiers) { - if (parameterNames != null && parameterModifiers != null) { + private static void fillReflectParameters(Target_java_lang_reflect_Executable executable, String[] reflectParameterNames, int[] reflectParameterModifiers) { + if (reflectParameterNames != null && reflectParameterModifiers != null) { executable.hasRealParameterData = true; - assert parameterNames.length == parameterModifiers.length; - executable.parameters = new Target_java_lang_reflect_Parameter[parameterNames.length]; - for (int i = 0; i < parameterNames.length; ++i) { + assert reflectParameterNames.length == reflectParameterModifiers.length; + executable.parameters = new Target_java_lang_reflect_Parameter[reflectParameterNames.length]; + for (int i = 0; i < reflectParameterNames.length; ++i) { executable.parameters[i] = new Target_java_lang_reflect_Parameter(); - executable.parameters[i].constructor(parameterNames[i], parameterModifiers[i], executable, i); + executable.parameters[i].constructor(reflectParameterNames[i], reflectParameterModifiers[i], executable, i); } } else { executable.hasRealParameterData = false; From eb20426be6b77266babdb8d51c5a31316eba7634 Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Tue, 5 Oct 2021 14:02:09 +0200 Subject: [PATCH 345/681] Fix espresso names gate --- espresso/mx.espresso/mx_espresso.py | 9 ++++++++- .../include/libespresso_dynamic.h | 2 -- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/espresso/mx.espresso/mx_espresso.py b/espresso/mx.espresso/mx_espresso.py index 879b402edc4b..bf408b7a8c66 100644 --- a/espresso/mx.espresso/mx_espresso.py +++ b/espresso/mx.espresso/mx_espresso.py @@ -129,7 +129,14 @@ def _espresso_gate_runner(args, tasks): break with open(generated_header, 'r') as generated_header_file: - generated_header_lines = generated_header_file.readlines() + generated_header_lines = [] + for line in generated_header_file.readlines(): + # Ignore definitions that are not needed for Espresso + if not line.startswith("typedef") or "(*Espresso_" in line or "__graal" in line or "(*graal_" in line: + generated_header_lines.append(line) + else: + newline = generated_header_lines.pop() # Remove newline before ignored declaration + assert newline == "\n" errors = errors or mx.update_file(committed_header, ''.join(committed_header_copyright + generated_header_lines), showDiff=True) diff --git a/espresso/src/com.oracle.truffle.espresso.mokapot/include/libespresso_dynamic.h b/espresso/src/com.oracle.truffle.espresso.mokapot/include/libespresso_dynamic.h index 3ad28a709a59..d86a18b168cf 100644 --- a/espresso/src/com.oracle.truffle.espresso.mokapot/include/libespresso_dynamic.h +++ b/espresso/src/com.oracle.truffle.espresso.mokapot/include/libespresso_dynamic.h @@ -42,8 +42,6 @@ typedef int (*Espresso_CloseContext_fn_t)(graal_isolatethread_t* thread, struct typedef void (*Espresso_Exit_fn_t)(graal_isolatethread_t* thread, struct JavaVM_* javaVM); -typedef void (*vmLocatorSymbol_fn_t)(graal_isolatethread_t* thread); - #if defined(__cplusplus) } #endif From c00c4bc0cb073310ee90bb0a7f116349eaaaf712 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Thu, 7 Oct 2021 12:41:07 +0200 Subject: [PATCH 346/681] Improve error and doc for ProxyObject#getMemberKeys(). --- .../graalvm/polyglot/proxy/ProxyObject.java | 17 +++-- .../api/test/polyglot/ProxySPITest.java | 74 ++++++++++++++++++- .../com/oracle/truffle/host/HostProxy.java | 9 +++ 3 files changed, 91 insertions(+), 9 deletions(-) diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/proxy/ProxyObject.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/proxy/ProxyObject.java index eeaec2a074b7..3116b4893391 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/proxy/ProxyObject.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/proxy/ProxyObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -45,6 +45,7 @@ import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.HostAccess; /** * Interface to be implemented to mimic guest language objects that contain members. @@ -63,16 +64,16 @@ public interface ProxyObject extends Proxy { Object getMember(String key); /** - * Returns array of member keys. The returned array must be interpreted as having array elements - * using the semantics of {@link Context#asValue(Object)} otherwise and - * {@link IllegalStateException} is thrown. If one of the return values of the array is not a - * {@link String} then a {@link ClassCastException} is thrown. Examples for valid return values - * are: + * Returns an array of member keys. The returned array must be interpreted as having array + * elements using the semantics of {@link Context#asValue(Object)} and taking host access into + * consideration. Otherwise, an {@link IllegalStateException} is thrown. If one of the return + * values of the array is not a {@link String} then a {@link ClassCastException} is thrown. + * Examples for valid return values are: *

    *
  • null for no member keys *
  • {@link ProxyArray} that returns {@link String} values for each array element - *
  • {@link List } with exclusively String elements - *
  • {@link String String[]} + *
  • {@link List } with exclusively String elements ({@link HostAccess} must allowListAccess) + *
  • {@link String String[]} ({@link HostAccess} must allowArrayAccess) *
  • A guest language object representing an array of strings. *
* Every member key returned by the {@link #getMemberKeys()} method must return diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ProxySPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ProxySPITest.java index f0d3de2acd48..8880e8ab7841 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ProxySPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ProxySPITest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -43,6 +43,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.time.Duration; import java.time.Instant; @@ -55,6 +56,9 @@ import java.util.Map; import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.HostAccess; +import org.graalvm.polyglot.PolyglotAccess; +import org.graalvm.polyglot.PolyglotException; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.proxy.Proxy; import org.graalvm.polyglot.proxy.ProxyArray; @@ -71,6 +75,7 @@ import org.junit.Before; import org.junit.Test; +import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; @@ -78,6 +83,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.nodes.RootNode; /** * Testing the behavior of proxies towards languages. @@ -282,6 +288,72 @@ public void testProxyObject() throws Throwable { assertEmpty(INTEROP.getMembers(proxyInner)); } + /* + * Test for GR27558. + */ + @Test + public void testProxyObjectAndHostAccess() { + setupEnv(Context.newBuilder(ProxyLanguage.ID).allowPolyglotAccess(PolyglotAccess.ALL).allowHostAccess(HostAccess.NONE).build(), new ProxyLanguage() { + @Override + protected CallTarget parse(ParsingRequest request) throws Exception { + String bindingMemberName = request.getSource().getCharacters().toString(); + InteropLibrary interopLibrary = InteropLibrary.getUncached(); + Object memberKeys = interopLibrary.getMembers(interopLibrary.readMember(languageEnv.getPolyglotBindings(), bindingMemberName)); + return RootNode.createConstantNode(memberKeys).getCallTarget(); + } + }); + + class MemberKeysProxy implements ProxyObject { + private Object memberKeys; + + MemberKeysProxy(Object memberKeys) { + this.memberKeys = memberKeys; + } + + @Override + public Object getMemberKeys() { + return memberKeys; + } + + @Override + public boolean hasMember(String key) { + return true; + } + + @Override + public Object getMember(String key) { + return null; + } + + @Override + public void putMember(String key, Value value) { + } + } + + context.initialize(ProxyLanguage.ID); + + Object[] memberKeys = new Object[]{"one", "two"}; + context.getPolyglotBindings().putMember("proxyArray", new MemberKeysProxy(memberKeys)); + context.getPolyglotBindings().putMember("proxyList", new MemberKeysProxy(Arrays.asList(memberKeys))); + context.getPolyglotBindings().putMember("proxyProxyArray", new MemberKeysProxy(ProxyArray.fromArray(memberKeys))); + try { + context.eval(ProxyLanguage.ID, "proxyArray"); + fail(); + } catch (PolyglotException e) { + assertTrue(e.getMessage().contains("allowArrayAccess in HostAccess is false.")); + } + try { + context.eval(ProxyLanguage.ID, "proxyList"); + fail(); + } catch (PolyglotException e) { + assertTrue(e.getMessage().contains("allowListAccess in HostAccess is false.")); + } + Value proxyArrayMembers = context.eval(ProxyLanguage.ID, "proxyProxyArray"); + assertTrue(proxyArrayMembers.hasArrayElements()); + assertEquals(2, proxyArrayMembers.getArraySize()); + assertEquals("two", proxyArrayMembers.getArrayElement(1).asString()); + } + @Test public void testProxyObjectUnsupported() throws Throwable { ProxyObject proxyOuter = new ProxyObject() { diff --git a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostProxy.java b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostProxy.java index a9b07dc869c4..85539494dacf 100644 --- a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostProxy.java +++ b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostProxy.java @@ -48,6 +48,7 @@ import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.List; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.proxy.Proxy; @@ -288,6 +289,14 @@ Object getMembers(@SuppressWarnings("unused") boolean includeInternal, Object guestValue = context.toGuestValue(library, result); InteropLibrary interop = InteropLibrary.getFactory().getUncached(); if (!interop.hasArrayElements(guestValue)) { + if (guestValue instanceof HostObject) { + HostObject hostObject = (HostObject) guestValue; + if (hostObject.obj.getClass().isArray() && !hostObject.getHostClassCache().isArrayAccess()) { + throw illegalProxy(context, "getMemberKeys() returned a Java array %s, but allowArrayAccess in HostAccess is false.", context.asValue(library, guestValue).toString()); + } else if (hostObject.obj instanceof List && !hostObject.getHostClassCache().isListAccess()) { + throw illegalProxy(context, "getMemberKeys() returned a Java List %s, but allowListAccess in HostAccess is false.", context.asValue(library, guestValue).toString()); + } + } throw illegalProxy(context, "getMemberKeys() returned invalid value %s but must return an array of member key Strings.", context.asValue(library, guestValue).toString()); } From 4827acfe8fc6a20f7a3b0ca15745e45d1ecb3368 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Thu, 7 Oct 2021 09:31:45 +0200 Subject: [PATCH 347/681] Espresso: mark 17 as supported in version metadata --- .../src/com/oracle/truffle/espresso/EspressoLanguage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java index 61166a8a1951..3f1c4ca600bf 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java @@ -72,7 +72,7 @@ public final class EspressoLanguage extends TruffleLanguage { public static final String ID = "java"; public static final String NAME = "Java"; public static final String IMPLEMENTATION_NAME = "Espresso"; - public static final String VERSION = "1.8|11"; + public static final String VERSION = "1.8|11|17"; // Espresso VM info public static final String VM_SPECIFICATION_NAME = "Java Virtual Machine Specification"; From 463b0945570cf22e6dd12bfde62e364623a96ad1 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Thu, 7 Oct 2021 11:11:46 +0200 Subject: [PATCH 348/681] Bump copyright year in polyglot launcher --- .../src/org/graalvm/launcher/MultiLanguageShell.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/MultiLanguageShell.java b/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/MultiLanguageShell.java index 4923727ecbf1..1a857ac824f3 100644 --- a/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/MultiLanguageShell.java +++ b/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/MultiLanguageShell.java @@ -223,7 +223,7 @@ private boolean handleBuiltins() { private void printHeader() { println("GraalVM MultiLanguage Shell " + context.getEngine().getVersion()); - println("Copyright (c) 2013-2020, Oracle and/or its affiliates"); + println("Copyright (c) 2013-2021, Oracle and/or its affiliates"); for (Language language : languages) { println(" " + language.getName() + " version " + language.getVersion()); } From bcbc91a5fde77a2a0e9d07466756fbd1ec187d4e Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Fri, 8 Oct 2021 11:54:31 +0200 Subject: [PATCH 349/681] Remove version in espresso language registration This version should rather be the implementation version for which the default value works fine. --- .../src/com/oracle/truffle/espresso/EspressoLanguage.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java index 3f1c4ca600bf..d3f9d3dd0325 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java @@ -25,13 +25,12 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; -import com.oracle.truffle.api.ContextThreadLocal; -import com.oracle.truffle.espresso.runtime.EspressoThreadLocalState; import org.graalvm.home.Version; import org.graalvm.options.OptionDescriptors; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.ContextThreadLocal; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Registration; import com.oracle.truffle.api.instrumentation.ProvidedTags; @@ -56,6 +55,7 @@ import com.oracle.truffle.espresso.nodes.interop.GetBindingsNode; import com.oracle.truffle.espresso.runtime.EspressoContext; import com.oracle.truffle.espresso.runtime.EspressoExitException; +import com.oracle.truffle.espresso.runtime.EspressoThreadLocalState; import com.oracle.truffle.espresso.runtime.StaticObject; import com.oracle.truffle.espresso.runtime.StaticObject.StaticObjectFactory; import com.oracle.truffle.espresso.substitutions.Substitutions; @@ -63,7 +63,6 @@ @Registration(id = EspressoLanguage.ID, // name = EspressoLanguage.NAME, // implementationName = EspressoLanguage.IMPLEMENTATION_NAME, // - version = EspressoLanguage.VERSION, // contextPolicy = TruffleLanguage.ContextPolicy.EXCLUSIVE, // dependentLanguages = {"nfi", "llvm"}) @ProvidedTags({StandardTags.RootTag.class, StandardTags.RootBodyTag.class, StandardTags.StatementTag.class}) @@ -72,7 +71,6 @@ public final class EspressoLanguage extends TruffleLanguage { public static final String ID = "java"; public static final String NAME = "Java"; public static final String IMPLEMENTATION_NAME = "Espresso"; - public static final String VERSION = "1.8|11|17"; // Espresso VM info public static final String VM_SPECIFICATION_NAME = "Java Virtual Machine Specification"; From 4f7d8dc845d50bc746d3e84b163322fb7fb1dd54 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 7 Oct 2021 11:41:10 +0200 Subject: [PATCH 350/681] Improve heap verifier. --- .../svm/core/genscavenge/HeapVerifier.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java index 279319c09629..78f8cb73c4a5 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java @@ -361,17 +361,28 @@ private static boolean verifyReference(Object parentObject, Pointer reference, P if (!HeapImpl.getHeapImpl().isInHeap(referencedObject)) { Log.log().string("Object reference at ").zhex(reference).string(" points outside the Java heap: ").zhex(referencedObject).string(". "); - if (parentObject != null) { - Log.log().string("The object that contains the invalid reference is of type ").string(parentObject.getClass().getName()).newline(); - } else { - Log.log().string("The invalid reference is on the stack.").newline(); - } + printParentObject(parentObject); + return false; + } + + if (!ObjectHeaderImpl.getObjectHeaderImpl().pointsToObjectHeader(referencedObject)) { + Log.log().string("Object reference at ").zhex(reference).string(" does not point to a Java object or the object header of the Java object is invalid: ").zhex(referencedObject) + .string(". "); + printParentObject(parentObject); return false; } return true; } + private static void printParentObject(Object parentObject) { + if (parentObject != null) { + Log.log().string("The object that contains the invalid reference is of type ").string(parentObject.getClass().getName()).newline(); + } else { + Log.log().string("The invalid reference is on the stack.").newline(); + } + } + private static class ImageHeapRegionVerifier implements MemoryWalker.ImageHeapRegionVisitor { private final ImageHeapObjectVerifier objectVerifier; From 01a0e755c678cfc0d6616e700168e01cd6f8b6b7 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 7 Oct 2021 13:33:33 +0200 Subject: [PATCH 351/681] Improve the zeroing of unaligned chunks. --- .../core/genscavenge/HeapChunkProvider.java | 12 ++++--- .../genscavenge/ThreadLocalAllocation.java | 9 ++--- .../svm/core/code/RuntimeCodeInfoAccess.java | 4 +-- .../os/AbstractCommittedMemoryProvider.java | 33 ++++++++++++++++++ .../svm/core/os/CommittedMemoryProvider.java | 34 +++++++++++++++++-- .../core/os/OSCommittedMemoryProvider.java | 5 +++ 6 files changed, 85 insertions(+), 12 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java index 8b00abcf8196..f1cdc1cc1fa1 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java @@ -109,7 +109,7 @@ AlignedHeader produceAlignedChunk() { if (result.isNull()) { /* Unused list was empty, need to allocate memory. */ noteFirstAllocationTime(); - result = (AlignedHeader) CommittedMemoryProvider.get().allocate(chunkSize, HeapParameters.getAlignedHeapChunkAlignment(), false); + result = (AlignedHeader) CommittedMemoryProvider.get().allocateAlignedChunk(chunkSize, HeapParameters.getAlignedHeapChunkAlignment()); if (result.isNull()) { throw ALIGNED_OUT_OF_MEMORY_ERROR; } @@ -267,7 +267,7 @@ UnalignedHeader produceUnalignedChunk(UnsignedWord objectSize) { log().string("[HeapChunkProvider.produceUnalignedChunk objectSize: ").unsigned(objectSize).string(" chunkSize: ").zhex(chunkSize).newline(); noteFirstAllocationTime(); - UnalignedHeader result = (UnalignedHeader) CommittedMemoryProvider.get().allocate(chunkSize, CommittedMemoryProvider.UNALIGNED, false); + UnalignedHeader result = (UnalignedHeader) CommittedMemoryProvider.get().allocateUnalignedChunk(chunkSize); if (result.isNull()) { throw UNALIGNED_OUT_OF_MEMORY_ERROR; } @@ -283,6 +283,10 @@ UnalignedHeader produceUnalignedChunk(UnsignedWord objectSize) { return result; } + public boolean areUnalignedChunksZeroed() { + return CommittedMemoryProvider.get().areUnalignedChunksZeroed(); + } + /** * Releases a list of UnalignedHeapChunks back to the operating system. They are never recycled * to a free list. @@ -362,12 +366,12 @@ static void freeUnalignedChunkList(UnalignedHeader first) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static void freeAlignedChunk(AlignedHeader chunk) { - CommittedMemoryProvider.get().free(chunk, HeapParameters.getAlignedHeapChunkSize(), HeapParameters.getAlignedHeapChunkAlignment(), false); + CommittedMemoryProvider.get().freeAlignedChunk(chunk, HeapParameters.getAlignedHeapChunkSize(), HeapParameters.getAlignedHeapChunkAlignment()); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static void freeUnalignedChunk(UnalignedHeader chunk) { - CommittedMemoryProvider.get().free(chunk, unalignedChunkSize(chunk), CommittedMemoryProvider.UNALIGNED, false); + CommittedMemoryProvider.get().freeUnalignedChunk(chunk, unalignedChunkSize(chunk)); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java index 323dbc14b516..12c240f616eb 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java @@ -234,8 +234,9 @@ private static Object slowPathNewArrayWithoutAllocating(DynamicHub hub, int leng if (size.aboveOrEqual(HeapParameters.getLargeArrayThreshold())) { /* Large arrays go into their own unaligned chunk. */ + boolean needsZeroing = !HeapImpl.getChunkProvider().areUnalignedChunksZeroed(); UnalignedHeapChunk.UnalignedHeader newTlabChunk = HeapImpl.getChunkProvider().produceUnalignedChunk(size); - return allocateLargeArrayInNewTlab(hub, length, size, fillStartOffset, newTlabChunk); + return allocateLargeArrayInNewTlab(hub, length, size, fillStartOffset, newTlabChunk, needsZeroing); } /* Small arrays go into the regular aligned chunk. */ @@ -274,7 +275,7 @@ private static Object allocateSmallArrayInNewTlab(DynamicHub hub, int length, Un } @Uninterruptible(reason = "Holds uninitialized memory, modifies TLAB") - private static Object allocateLargeArrayInNewTlab(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset, UnalignedHeapChunk.UnalignedHeader newTlabChunk) { + private static Object allocateLargeArrayInNewTlab(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset, UnalignedHeapChunk.UnalignedHeader newTlabChunk, boolean needsZeroing) { ThreadLocalAllocation.Descriptor tlab = getTlab(); HeapChunk.setNext(newTlabChunk, tlab.getUnalignedChunk()); @@ -284,8 +285,8 @@ private static Object allocateLargeArrayInNewTlab(DynamicHub hub, int length, Un Pointer memory = UnalignedHeapChunk.allocateMemory(newTlabChunk, size); assert memory.isNonNull(); - /* Install the DynamicHub and length, and zero the elements. */ - return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, true, true, fillStartOffset, true); + /* Install the DynamicHub and length. Also zero the elements if necessary. */ + return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, true, needsZeroing, fillStartOffset, true); } @Uninterruptible(reason = "Returns uninitialized memory, modifies TLAB", callerMustBe = true) 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 bc6322ac101e..f519a203535f 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 @@ -233,12 +233,12 @@ private static void releaseMemory(CodeInfo info, boolean notifyGC) { } public static CodePointer allocateCodeMemory(UnsignedWord size) { - return (CodePointer) CommittedMemoryProvider.get().allocate(size, WordFactory.unsigned(SubstrateOptions.codeAlignment()), true); + return (CodePointer) CommittedMemoryProvider.get().allocateExecutableMemory(size, WordFactory.unsigned(SubstrateOptions.codeAlignment())); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void releaseCodeMemory(CodePointer codeStart, UnsignedWord codeSize) { - CommittedMemoryProvider.get().free(codeStart, codeSize, WordFactory.unsigned(SubstrateOptions.codeAlignment()), true); + CommittedMemoryProvider.get().freeExecutableMemory(codeStart, codeSize, WordFactory.unsigned(SubstrateOptions.codeAlignment())); } public static void makeCodeMemoryExecutableReadOnly(CodePointer codeStart, UnsignedWord codeSize) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractCommittedMemoryProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractCommittedMemoryProvider.java index 3acca7f3f2dd..87412abf2579 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractCommittedMemoryProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractCommittedMemoryProvider.java @@ -48,6 +48,39 @@ public boolean guaranteesHeapPreferredAddressSpaceAlignment() { return SubstrateOptions.SpawnIsolates.getValue() && ImageHeapProvider.get().guaranteesHeapPreferredAddressSpaceAlignment(); } + @Override + public Pointer allocateAlignedChunk(UnsignedWord nbytes, UnsignedWord alignment) { + return allocate(nbytes, alignment, false); + } + + @Override + public Pointer allocateUnalignedChunk(UnsignedWord nbytes) { + return allocate(nbytes, CommittedMemoryProvider.UNALIGNED, false); + } + + @Override + public Pointer allocateExecutableMemory(UnsignedWord nbytes, UnsignedWord alignment) { + return allocate(nbytes, alignment, true); + } + + @Override + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public void freeAlignedChunk(PointerBase start, UnsignedWord nbytes, UnsignedWord alignment) { + free(start, nbytes, alignment, false); + } + + @Override + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public void freeUnalignedChunk(PointerBase start, UnsignedWord nbytes) { + free(start, nbytes, CommittedMemoryProvider.UNALIGNED, false); + } + + @Override + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public void freeExecutableMemory(PointerBase start, UnsignedWord nbytes, UnsignedWord alignment) { + free(start, nbytes, alignment, true); + } + @Uninterruptible(reason = "Still being initialized.") protected static int protectSingleIsolateImageHeap() { assert !SubstrateOptions.SpawnIsolates.getValue() : "Must be handled by ImageHeapProvider when SpawnIsolates is enabled"; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/CommittedMemoryProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/CommittedMemoryProvider.java index 5c982b45b59b..1782f18eb5c5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/CommittedMemoryProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/CommittedMemoryProvider.java @@ -26,6 +26,7 @@ import java.util.EnumSet; +import com.oracle.svm.core.util.VMError; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.c.type.WordPointer; @@ -99,7 +100,23 @@ default UnsignedWord getGranularity() { * @return The start of the allocated block, or {@link WordFactory#nullPointer()} in case of an * error. */ - Pointer allocate(UnsignedWord nbytes, UnsignedWord alignment, boolean executable); + default Pointer allocate(UnsignedWord nbytes, UnsignedWord alignment, boolean executable) { + // We need this default method temporarily so that we can remove the methods allocate and + // free from all subclasses in GR-34236. + throw VMError.shouldNotReachHere("Subclasses must overwrite this method"); + } + + Pointer allocateAlignedChunk(UnsignedWord nbytes, UnsignedWord alignment); + + Pointer allocateUnalignedChunk(UnsignedWord nbytes); + + Pointer allocateExecutableMemory(UnsignedWord nbytes, UnsignedWord alignment); + + /** + * This method returns {@code true} if the memory returned by {@link #allocateUnalignedChunk} is + * guaranteed to be zeroed. + */ + boolean areUnalignedChunksZeroed(); /** * Release a block of committed memory that was allocated with {@link #allocate}, requiring the @@ -112,7 +129,20 @@ default UnsignedWord getGranularity() { * @return true on success, or false otherwise. */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - boolean free(PointerBase start, UnsignedWord nbytes, UnsignedWord alignment, boolean executable); + default boolean free(PointerBase start, UnsignedWord nbytes, UnsignedWord alignment, boolean executable) { + // We need this default method temporarily so that we can remove the methods allocate and + // free from all subclasses in GR-34236. + throw VMError.shouldNotReachHere("Subclasses must overwrite this method"); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + void freeAlignedChunk(PointerBase start, UnsignedWord nbytes, UnsignedWord alignment); + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + void freeUnalignedChunk(PointerBase start, UnsignedWord nbytes); + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + void freeExecutableMemory(PointerBase start, UnsignedWord nbytes, UnsignedWord alignment); /** * Called by the garbage collector before a collection is started, as an opportunity to perform diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/OSCommittedMemoryProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/OSCommittedMemoryProvider.java index 001d5f5679af..1c2e63e80773 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/OSCommittedMemoryProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/OSCommittedMemoryProvider.java @@ -101,6 +101,11 @@ public Pointer allocate(UnsignedWord size, UnsignedWord alignment, boolean execu return committed; } + @Override + public boolean areUnalignedChunksZeroed() { + return false; + } + @Override @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean free(PointerBase start, UnsignedWord nbytes, UnsignedWord alignment, boolean executable) { From 9abe2aea28c7a949aeb0e92bea6b19b7d01f674a Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Fri, 8 Oct 2021 13:40:25 +0200 Subject: [PATCH 352/681] Do not fill pre-zeroed memory with garbage if assertions are enabled. --- .../HotSpotAllocationSnippets.java | 16 +++++----- .../replacements/AllocationSnippets.java | 29 ++++++++++++++----- .../genscavenge/ThreadLocalAllocation.java | 16 ++++++---- .../graal/GenScavengeAllocationSnippets.java | 4 +-- .../graal/nodes/FormatArrayNode.java | 4 ++- .../graal/nodes/FormatObjectNode.java | 3 +- .../snippets/SubstrateAllocationSnippets.java | 22 +++++++------- 7 files changed, 58 insertions(+), 36 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java index e2b59546459c..c57b9dff5f95 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java @@ -148,7 +148,7 @@ public HotSpotAllocationSnippets(GraalHotSpotVMConfig config, HotSpotRegistersPr protected Object allocateInstance(KlassPointer hub, Word prototypeMarkWord, @ConstantParameter long size, - @ConstantParameter boolean fillContents, + @ConstantParameter FillContent fillContents, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter HotSpotAllocationProfilingData profilingData) { Object result = allocateInstanceImpl(hub.asWord(), prototypeMarkWord, WordFactory.unsigned(size), fillContents, emitMemoryBarrier, true, profilingData); @@ -161,7 +161,7 @@ public Object allocateArray(KlassPointer hub, int length, @ConstantParameter int arrayBaseOffset, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, + @ConstantParameter FillContent fillContents, @ConstantParameter int fillStartOffset, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter boolean maybeUnroll, @@ -175,7 +175,7 @@ public Object allocateArray(KlassPointer hub, @Snippet public Object allocateInstanceDynamic(@NonNullParameter Class type, - @ConstantParameter boolean fillContents, + @ConstantParameter FillContent fillContents, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter HotSpotAllocationProfilingData profilingData) { @@ -225,7 +225,7 @@ public Object allocateArrayDynamic(Class elementType, Word prototypeMarkWord, Class voidClass, int length, - @ConstantParameter boolean fillContents, + @ConstantParameter FillContent fillContents, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, @@ -608,7 +608,7 @@ public void lower(NewInstanceNode node, LoweringTool tool) { args.add("hub", hub); args.add("prototypeMarkWord", type.prototypeMarkWord()); args.addConst("size", size); - args.addConst("fillContents", node.fillContents()); + args.addConst("fillContents", FillContent.fromBoolean(node.fillContents())); args.addConst("emitMemoryBarrier", node.emitMemoryBarrier()); args.addConst("profilingData", getProfilingData(localOptions, "instance", type)); @@ -638,7 +638,7 @@ public void lower(NewArrayNode node, LoweringTool tool) { args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length)); args.addConst("arrayBaseOffset", arrayBaseOffset); args.addConst("log2ElementSize", log2ElementSize); - args.addConst("fillContents", node.fillContents()); + args.addConst("fillContents", FillContent.fromBoolean(node.fillContents())); args.addConst("fillStartOffset", arrayBaseOffset); args.addConst("emitMemoryBarrier", node.emitMemoryBarrier()); args.addConst("maybeUnroll", length.isConstant()); @@ -674,7 +674,7 @@ public void lower(DynamicNewInstanceNode node, LoweringTool tool) { Arguments args = new Arguments(allocateInstanceDynamic, node.graph().getGuardsStage(), tool.getLoweringStage()); args.add("type", node.getInstanceType()); - args.addConst("fillContents", node.fillContents()); + args.addConst("fillContents", FillContent.fromBoolean(node.fillContents())); args.addConst("emitMemoryBarrier", node.emitMemoryBarrier()); args.addConst("profilingData", getProfilingData(localOptions, "", null)); @@ -702,7 +702,7 @@ public void lower(DynamicNewArrayNode node, LoweringTool tool) { args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord()); args.add("voidClass", voidClass); args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length)); - args.addConst("fillContents", node.fillContents()); + args.addConst("fillContents", FillContent.fromBoolean(node.fillContents())); args.addConst("emitMemoryBarrier", node.emitMemoryBarrier()); /* * We use Kind.Illegal as a marker value instead of null because constant snippet diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/AllocationSnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/AllocationSnippets.java index f1fbb9982810..98c8cdc2fb90 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/AllocationSnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/AllocationSnippets.java @@ -50,7 +50,7 @@ public abstract class AllocationSnippets implements Snippets { protected Object allocateInstanceImpl(Word hub, Word prototypeMarkWord, UnsignedWord size, - boolean fillContents, + FillContent fillContents, boolean emitMemoryBarrier, boolean constantSize, AllocationProfilingData profilingData) { @@ -76,7 +76,7 @@ protected Object allocateArrayImpl(Word hub, int length, int arrayBaseOffset, int log2ElementSize, - boolean fillContents, + FillContent fillContents, int fillStartOffset, boolean emitMemoryBarrier, boolean maybeUnroll, @@ -267,15 +267,15 @@ protected Object formatObject(Word hub, Word prototypeMarkWord, UnsignedWord size, Word memory, - boolean fillContents, + FillContent fillContents, boolean emitMemoryBarrier, boolean constantSize, AllocationSnippetCounters snippetCounters) { initializeObjectHeader(memory, hub, prototypeMarkWord, false); int headerSize = instanceHeaderSize(); - if (fillContents) { + if (fillContents == FillContent.WITH_ZEROES) { zeroMemory(memory, headerSize, size, constantSize, false, false, false, snippetCounters); - } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { + } else if (REPLACEMENTS_ASSERTIONS_ENABLED && fillContents == FillContent.WITH_GARBAGE_IF_ASSERTIONS_ENABLED) { fillWithGarbage(memory, headerSize, size, constantSize, false, false, snippetCounters); } if (emitMemoryBarrier) { @@ -292,7 +292,7 @@ protected Object formatArray(Word hub, UnsignedWord allocationSize, int length, Word memory, - boolean fillContents, + FillContent fillContents, int fillStartOffset, boolean emitMemoryBarrier, boolean maybeUnroll, @@ -303,9 +303,9 @@ protected Object formatArray(Word hub, // Store hub last as the concurrent garbage collectors assume length is valid if hub field // is not null. initializeObjectHeader(memory, hub, prototypeMarkWord, true); - if (fillContents) { + if (fillContents == FillContent.WITH_ZEROES) { zeroMemory(memory, fillStartOffset, allocationSize, false, maybeUnroll, supportsBulkZeroing, supportsOptimizedFilling, snippetCounters); - } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { + } else if (REPLACEMENTS_ASSERTIONS_ENABLED && fillContents == FillContent.WITH_GARBAGE_IF_ASSERTIONS_ENABLED) { fillWithGarbage(memory, fillStartOffset, allocationSize, false, maybeUnroll, supportsOptimizedFilling, snippetCounters); } if (emitMemoryBarrier) { @@ -374,6 +374,19 @@ protected Object callNewInstanceStub(Word hub, UnsignedWord size) { protected abstract int objectAlignment(); + public enum FillContent { + DO_NOT_FILL, + WITH_ZEROES, + WITH_GARBAGE_IF_ASSERTIONS_ENABLED; + + public static FillContent fromBoolean(boolean fillContents) { + if (fillContents) { + return WITH_ZEROES; + } + return WITH_GARBAGE_IF_ASSERTIONS_ENABLED; + } + } + public static class AllocationProfilingData { final AllocationSnippetCounters snippetCounters; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java index 12c240f616eb..166cb20c673a 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java @@ -28,6 +28,7 @@ import static com.oracle.svm.core.graal.snippets.SubstrateAllocationSnippets.TLAB_TOP_IDENTITY; import org.graalvm.compiler.api.replacements.Fold; +import org.graalvm.compiler.replacements.AllocationSnippets.FillContent; import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.Platform; @@ -256,7 +257,7 @@ private static Object slowPathNewArrayWithoutAllocating(DynamicHub hub, int leng @Uninterruptible(reason = "Holds uninitialized memory.") private static Object allocateInstanceInNewTlab(DynamicHub hub, UnsignedWord size, AlignedHeader newTlabChunk) { Pointer memory = allocateRawMemoryInNewTlab(size, newTlabChunk); - return FormatObjectNode.formatObject(memory, DynamicHub.toClass(hub), false, true, true); + return FormatObjectNode.formatObject(memory, DynamicHub.toClass(hub), false, FillContent.WITH_ZEROES, true); } @Uninterruptible(reason = "Holds uninitialized memory.") @@ -265,13 +266,13 @@ private static Object allocateSmallArrayInCurrentTlab(DynamicHub hub, int length return null; } Pointer memory = allocateRawMemoryInTlab(size, getTlab()); - return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, false, true, fillStartOffset, true); + return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, false, FillContent.WITH_ZEROES, fillStartOffset, true); } @Uninterruptible(reason = "Holds uninitialized memory.") private static Object allocateSmallArrayInNewTlab(DynamicHub hub, int length, UnsignedWord size, int fillStartOffset, AlignedHeader newTlabChunk) { Pointer memory = allocateRawMemoryInNewTlab(size, newTlabChunk); - return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, false, true, fillStartOffset, true); + return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, false, FillContent.WITH_ZEROES, fillStartOffset, true); } @Uninterruptible(reason = "Holds uninitialized memory, modifies TLAB") @@ -285,8 +286,13 @@ private static Object allocateLargeArrayInNewTlab(DynamicHub hub, int length, Un Pointer memory = UnalignedHeapChunk.allocateMemory(newTlabChunk, size); assert memory.isNonNull(); - /* Install the DynamicHub and length. Also zero the elements if necessary. */ - return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, true, needsZeroing, fillStartOffset, true); + /* + * Install the DynamicHub and length and zero the elements if necessary. If the memory is + * already pre-zeroed, we need to ensure that the snippet code does not fill the memory in + * any way. + */ + FillContent fillKind = needsZeroing ? FillContent.WITH_ZEROES : FillContent.DO_NOT_FILL; + return FormatArrayNode.formatArray(memory, DynamicHub.toClass(hub), length, false, true, fillKind, fillStartOffset, true); } @Uninterruptible(reason = "Returns uninitialized memory, modifies TLAB", callerMustBe = true) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSnippets.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSnippets.java index 02c26ff0112b..53f6d2cdeb4a 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSnippets.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSnippets.java @@ -80,7 +80,7 @@ public static void registerLowering(OptionValues options, Iterable hub, int length, boolean rememberedSet, boolean unaligned, boolean fillContents, int fillStartOffset, boolean emitMemoryBarrier); + public static native Object formatArray(Pointer memory, Class hub, int length, boolean rememberedSet, boolean unaligned, AllocationSnippets.FillContent fillContents, int fillStartOffset, + boolean emitMemoryBarrier); } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/nodes/FormatObjectNode.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/nodes/FormatObjectNode.java index f26e502aa2f2..4af31b952e94 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/nodes/FormatObjectNode.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/nodes/FormatObjectNode.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; +import org.graalvm.compiler.replacements.AllocationSnippets.FillContent; import org.graalvm.word.Pointer; @NodeInfo(cycles = CYCLES_64, size = SIZE_64) @@ -75,5 +76,5 @@ public ValueNode getEmitMemoryBarrier() { } @NodeIntrinsic - public static native Object formatObject(Pointer memory, Class hub, boolean rememberedSet, boolean fillContents, boolean emitMemoryBarrier); + public static native Object formatObject(Pointer memory, Class hub, boolean rememberedSet, FillContent fillContents, boolean emitMemoryBarrier); } 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 10164d1d354b..1a660a7d2e45 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 @@ -50,6 +50,7 @@ import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.UnreachableNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.ForeignCallWithExceptionNode; @@ -81,7 +82,6 @@ import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider; import com.oracle.svm.core.graal.nodes.NewStoredContinuationNode; import com.oracle.svm.core.graal.nodes.SubstrateNewHybridInstanceNode; -import org.graalvm.compiler.nodes.UnreachableNode; import com.oracle.svm.core.heap.Heap; import com.oracle.svm.core.heap.StoredContinuation; import com.oracle.svm.core.hub.DynamicHub; @@ -117,7 +117,7 @@ public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCal @Snippet protected Object allocateInstance(DynamicHub hub, @ConstantParameter long size, - @ConstantParameter boolean fillContents, + @ConstantParameter FillContent fillContents, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter AllocationProfilingData profilingData) { DynamicHub checkedHub = checkHub(hub); @@ -131,7 +131,7 @@ protected Object allocateStoredContinuationInstance(DynamicHub hub, @ConstantParameter AllocationProfilingData profilingData) { DynamicHub checkedHub = checkHub(hub); Object result = allocateInstanceImpl(encodeAsTLABObjectHeader(checkedHub), WordFactory.nullPointer(), WordFactory.unsigned(size), - false, true, false, profilingData); + FillContent.WITH_GARBAGE_IF_ASSERTIONS_ENABLED, true, false, profilingData); return piCastToSnippetReplaceeStamp(result); } @@ -140,7 +140,7 @@ public Object allocateArray(DynamicHub hub, int length, @ConstantParameter int arrayBaseOffset, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, + @ConstantParameter FillContent fillContents, @ConstantParameter int fillStartOffset, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter boolean maybeUnroll, @@ -154,7 +154,7 @@ public Object allocateArray(DynamicHub hub, } @Snippet - public Object allocateInstanceDynamic(@NonNullParameter DynamicHub hub, @ConstantParameter boolean fillContents, @ConstantParameter boolean emitMemoryBarrier, + public Object allocateInstanceDynamic(@NonNullParameter DynamicHub hub, @ConstantParameter FillContent fillContents, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter AllocationProfilingData profilingData) { UnsignedWord size = LayoutEncoding.getInstanceSize(hub.getLayoutEncoding()); Object result = allocateInstanceImpl(encodeAsTLABObjectHeader(hub), WordFactory.nullPointer(), size, fillContents, emitMemoryBarrier, false, profilingData); @@ -162,7 +162,7 @@ public Object allocateInstanceDynamic(@NonNullParameter DynamicHub hub, @Constan } @Snippet - public Object allocateArrayDynamic(DynamicHub elementType, int length, @ConstantParameter boolean fillContents, @ConstantParameter boolean emitMemoryBarrier, + public Object allocateArrayDynamic(DynamicHub elementType, int length, @ConstantParameter FillContent fillContents, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter boolean supportsBulkZeroing, @ConstantParameter boolean supportsOptimizedFilling, @ConstantParameter AllocationProfilingData profilingData) { DynamicHub checkedArrayHub = getCheckedArrayHub(elementType); @@ -520,7 +520,7 @@ public void lower(NewInstanceNode node, LoweringTool tool) { Arguments args = new Arguments(allocateInstance, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hubConstant); args.addConst("size", size); - args.addConst("fillContents", node.fillContents()); + args.addConst("fillContents", FillContent.fromBoolean(node.fillContents())); args.addConst("emitMemoryBarrier", node.emitMemoryBarrier()); args.addConst("profilingData", getProfilingData(node, type)); @@ -552,7 +552,7 @@ public void lower(SubstrateNewHybridInstanceNode node, LoweringTool tool) { args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length)); args.addConst("arrayBaseOffset", arrayBaseOffset); args.addConst("log2ElementSize", log2ElementSize); - args.addConst("fillContents", fillContents); + args.addConst("fillContents", FillContent.fromBoolean(fillContents)); args.addConst("fillStartOffset", afterArrayLengthOffset()); args.addConst("emitMemoryBarrier", node.emitMemoryBarrier()); args.addConst("maybeUnroll", length.isConstant()); @@ -585,7 +585,7 @@ public void lower(NewArrayNode node, LoweringTool tool) { args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length)); args.addConst("arrayBaseOffset", arrayBaseOffset); args.addConst("log2ElementSize", log2ElementSize); - args.addConst("fillContents", node.fillContents()); + args.addConst("fillContents", FillContent.fromBoolean(node.fillContents())); args.addConst("fillStartOffset", afterArrayLengthOffset()); args.addConst("emitMemoryBarrier", node.emitMemoryBarrier()); args.addConst("maybeUnroll", length.isConstant()); @@ -633,7 +633,7 @@ public void lower(DynamicNewInstanceNode node, LoweringTool tool) { Arguments args = new Arguments(allocateInstanceDynamic, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", node.getInstanceType()); - args.addConst("fillContents", node.fillContents()); + args.addConst("fillContents", FillContent.fromBoolean(node.fillContents())); args.addConst("emitMemoryBarrier", node.emitMemoryBarrier()); args.addConst("profilingData", getProfilingData(node, null)); @@ -652,7 +652,7 @@ public void lower(DynamicNewArrayNode node, LoweringTool tool) { Arguments args = new Arguments(allocateArrayDynamic, graph.getGuardsStage(), tool.getLoweringStage()); args.add("elementType", node.getElementType()); args.add("length", node.length()); - args.addConst("fillContents", node.fillContents()); + args.addConst("fillContents", FillContent.fromBoolean(node.fillContents())); args.addConst("emitMemoryBarrier", node.emitMemoryBarrier()); args.addConst("supportsBulkZeroing", tool.getLowerer().supportsBulkZeroing()); args.addConst("supportsOptimizedFilling", tool.getLowerer().supportsOptimizedFilling(graph.getOptions())); From e0c9201ac51b4ad7e2d0fd73258b488538279632 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Fri, 8 Oct 2021 10:47:11 +0200 Subject: [PATCH 353/681] Make the safepoint thread more patient. --- .../oracle/svm/core/posix/headers/Sched.java | 5 + .../svm/core/posix/thread/PosixVMThreads.java | 12 +++ .../WindowsProcessPropertiesSupport.java | 6 +- .../WindowsSystemPropertiesSupport.java | 2 +- .../oracle/svm/core/windows/WindowsUtils.java | 2 +- .../core/windows/WindowsVMLockSupport.java | 24 ++--- .../svm/core/windows/WindowsVMThreads.java | 17 ++- .../svm/core/windows/headers/Process.java | 100 +++++++++--------- .../com/oracle/svm/core/thread/Safepoint.java | 89 ++++++++-------- .../com/oracle/svm/core/thread/VMThreads.java | 10 ++ 10 files changed, 152 insertions(+), 115 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Sched.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Sched.java index 20d98e2166dd..660a90989c79 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Sched.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Sched.java @@ -37,4 +37,9 @@ public class Sched { @CFunction public static native int sched_yield(); + + public static class NoTransitions { + @CFunction(transition = CFunction.Transition.NO_TRANSITION) + public static native int sched_yield(); + } } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixVMThreads.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixVMThreads.java index 2d4b08238ae5..dfb7d2c0cb45 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixVMThreads.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixVMThreads.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.posix.thread; +import com.oracle.svm.core.posix.headers.Sched; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.function.CFunction; @@ -76,6 +77,17 @@ public void nativeSleep(int milliseconds) { Time.NoTransitions.nanosleep(ts, WordFactory.nullPointer()); } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + @Override + public void yield() { + Sched.NoTransitions.sched_yield(); + } + + @Override + public boolean supportsPatientSafepoints() { + return true; + } + @Uninterruptible(reason = "Thread state not set up.") @Override protected boolean initializeOnce() { diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsProcessPropertiesSupport.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsProcessPropertiesSupport.java index afee09ac495e..0f5704d77964 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsProcessPropertiesSupport.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsProcessPropertiesSupport.java @@ -85,7 +85,7 @@ public void exec(Path executable, String[] args) { @Override public long getProcessID() { - return Process.GetCurrentProcessId(); + return Process.NoTransitions.GetCurrentProcessId(); } @Override @@ -135,11 +135,11 @@ public boolean destroy(long processID) { @Override public boolean destroyForcibly(long processID) { - HANDLE handle = Process.OpenProcess(Process.PROCESS_TERMINATE(), 0, (int) processID); + HANDLE handle = Process.NoTransitions.OpenProcess(Process.PROCESS_TERMINATE(), 0, (int) processID); if (handle.isNull()) { return false; } - boolean result = Process.TerminateProcess(handle, 1) != 0; + boolean result = Process.NoTransitions.TerminateProcess(handle, 1) != 0; WinBase.CloseHandle(handle); return result; } diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSystemPropertiesSupport.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSystemPropertiesSupport.java index 8ae7f86a2845..ae542af21b06 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSystemPropertiesSupport.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSystemPropertiesSupport.java @@ -92,7 +92,7 @@ protected String userNameValue() { @Override protected String userHomeValue() { WinBase.LPHANDLE tokenHandle = StackValue.get(WinBase.LPHANDLE.class); - if (Process.OpenProcessToken(Process.GetCurrentProcess(), Process.TOKEN_QUERY(), tokenHandle) == 0) { + if (Process.NoTransitions.OpenProcessToken(Process.NoTransitions.GetCurrentProcess(), Process.TOKEN_QUERY(), tokenHandle) == 0) { return "C:\\"; // matches openjdk } diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsUtils.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsUtils.java index dab7acd92e7f..66ab86a0a68e 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsUtils.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsUtils.java @@ -61,7 +61,7 @@ private static final class Target_java_lang_ProcessImpl { public static int getpid(java.lang.Process process) { Target_java_lang_ProcessImpl processImpl = SubstrateUtil.cast(process, Target_java_lang_ProcessImpl.class); - return com.oracle.svm.core.windows.headers.Process.GetProcessId(WordFactory.pointer(processImpl.handle)); + return com.oracle.svm.core.windows.headers.Process.NoTransitions.GetProcessId(WordFactory.pointer(processImpl.handle)); } @TargetClass(java.io.FileDescriptor.class) diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java index 49a555f2d534..db02b50f3260 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java @@ -147,10 +147,10 @@ public static void initialize() { WindowsVMLockSupport support = WindowsVMLockSupport.singleton(); for (WindowsVMMutex mutex : support.mutexes) { // critical sections on windows always support recursive locking - Process.InitializeCriticalSection(mutex.getStructPointer()); + Process.NoTransitions.InitializeCriticalSection(mutex.getStructPointer()); } for (WindowsVMCondition condition : support.conditions) { - Process.InitializeConditionVariable(condition.getStructPointer()); + Process.NoTransitions.InitializeConditionVariable(condition.getStructPointer()); } } @@ -205,14 +205,14 @@ public VMMutex lock() { @Uninterruptible(reason = "Called from uninterruptible code.", callerMustBe = true) public void lockNoTransition() { assertNotOwner("Recursive locking is not supported"); - Process.EnterCriticalSectionNoTrans(getStructPointer()); + Process.NoTransitions.EnterCriticalSection(getStructPointer()); setOwnerToCurrentThread(); } @Override @Uninterruptible(reason = "Called from uninterruptible code.", callerMustBe = true) public void lockNoTransitionUnspecifiedOwner() { - Process.EnterCriticalSectionNoTrans(getStructPointer()); + Process.NoTransitions.EnterCriticalSection(getStructPointer()); setOwnerToUnspecified(); } @@ -220,20 +220,20 @@ public void lockNoTransitionUnspecifiedOwner() { @Uninterruptible(reason = "Called from uninterruptible code.") public void unlock() { clearCurrentThreadOwner(); - Process.LeaveCriticalSection(getStructPointer()); + Process.NoTransitions.LeaveCriticalSection(getStructPointer()); } @Override @Uninterruptible(reason = "Called from uninterruptible code.") public void unlockNoTransitionUnspecifiedOwner() { clearUnspecifiedOwner(); - Process.LeaveCriticalSection(getStructPointer()); + Process.NoTransitions.LeaveCriticalSection(getStructPointer()); } @Override public void unlockWithoutChecks() { clearCurrentThreadOwner(); - Process.LeaveCriticalSectionNoTrans(getStructPointer()); + Process.NoTransitions.LeaveCriticalSection(getStructPointer()); } } @@ -262,7 +262,7 @@ public void block() { @Uninterruptible(reason = "Called from uninterruptible code.", callerMustBe = true) public void blockNoTransition() { mutex.clearCurrentThreadOwner(); - WindowsVMLockSupport.checkResult(Process.SleepConditionVariableCSNoTrans(getStructPointer(), ((WindowsVMMutex) getMutex()).getStructPointer(), SynchAPI.INFINITE()), + WindowsVMLockSupport.checkResult(Process.NoTransitions.SleepConditionVariableCS(getStructPointer(), ((WindowsVMMutex) getMutex()).getStructPointer(), SynchAPI.INFINITE()), "SleepConditionVariableCS"); mutex.setOwnerToCurrentThread(); } @@ -271,7 +271,7 @@ public void blockNoTransition() { @Uninterruptible(reason = "Called from uninterruptible code.", callerMustBe = true) public void blockNoTransitionUnspecifiedOwner() { mutex.clearUnspecifiedOwner(); - WindowsVMLockSupport.checkResult(Process.SleepConditionVariableCSNoTrans(getStructPointer(), ((WindowsVMMutex) getMutex()).getStructPointer(), SynchAPI.INFINITE()), + WindowsVMLockSupport.checkResult(Process.NoTransitions.SleepConditionVariableCS(getStructPointer(), ((WindowsVMMutex) getMutex()).getStructPointer(), SynchAPI.INFINITE()), "SleepConditionVariableCS"); mutex.setOwnerToUnspecified(); } @@ -308,7 +308,7 @@ public long blockNoTransition(long waitNanos) { int dwMilliseconds = (int) (waitNanos / WindowsUtils.NANOSECS_PER_MILLISEC); mutex.clearCurrentThreadOwner(); - final int timedwaitResult = Process.SleepConditionVariableCSNoTrans(getStructPointer(), ((WindowsVMMutex) getMutex()).getStructPointer(), dwMilliseconds); + final int timedwaitResult = Process.NoTransitions.SleepConditionVariableCS(getStructPointer(), ((WindowsVMMutex) getMutex()).getStructPointer(), dwMilliseconds); mutex.setOwnerToCurrentThread(); /* If the timed wait timed out, then I am done blocking. */ @@ -325,12 +325,12 @@ public long blockNoTransition(long waitNanos) { @Override public void signal() { - Process.WakeConditionVariable(getStructPointer()); + Process.NoTransitions.WakeConditionVariable(getStructPointer()); } @Override @Uninterruptible(reason = "Called from uninterruptible code.") public void broadcast() { - Process.WakeAllConditionVariable(getStructPointer()); + Process.NoTransitions.WakeAllConditionVariable(getStructPointer()); } } diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMThreads.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMThreads.java index bf486e90bc73..d15cc5a6eaaf 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMThreads.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMThreads.java @@ -46,8 +46,8 @@ public final class WindowsVMThreads extends VMThreads { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @Override public OSThreadHandle getCurrentOSThreadHandle() { - WinBase.HANDLE pseudoThreadHandle = Process.GetCurrentThread(); - WinBase.HANDLE pseudoProcessHandle = Process.GetCurrentProcess(); + WinBase.HANDLE pseudoThreadHandle = Process.NoTransitions.GetCurrentThread(); + WinBase.HANDLE pseudoProcessHandle = Process.NoTransitions.GetCurrentProcess(); // convert the thread pseudo handle to a real handle using DuplicateHandle WinBase.LPHANDLE pointerToResult = StackValue.get(WinBase.LPHANDLE.class); @@ -61,7 +61,7 @@ public OSThreadHandle getCurrentOSThreadHandle() { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @Override protected OSThreadId getCurrentOSThreadId() { - return WordFactory.unsigned(Process.GetCurrentThreadId()); + return WordFactory.unsigned(Process.NoTransitions.GetCurrentThreadId()); } @Uninterruptible(reason = "Called from uninterruptible code.") @@ -80,6 +80,17 @@ public void nativeSleep(int milliseconds) { SynchAPI.NoTransitions.Sleep(milliseconds); } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + @Override + public void yield() { + Process.NoTransitions.SwitchToThread(); + } + + @Override + public boolean supportsPatientSafepoints() { + return true; + } + /** * Make sure the runtime is initialized for threading. */ diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/headers/Process.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/headers/Process.java index e46fdb7ecbe1..b21eedc4617a 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/headers/Process.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/headers/Process.java @@ -44,27 +44,9 @@ @CContext(WindowsDirectives.class) public class Process { - @CFunction(transition = Transition.NO_TRANSITION) - public static native HANDLE GetCurrentProcess(); - - @CFunction(transition = Transition.NO_TRANSITION) - public static native HANDLE OpenProcess(int dwDesiredAccess, int bInheritHandle, int dwProcessId); - @CConstant public static native int PROCESS_TERMINATE(); - @CFunction(transition = Transition.NO_TRANSITION) - public static native int TerminateProcess(HANDLE hProcess, int uExitCode); - - @CFunction(transition = Transition.NO_TRANSITION) - public static native int GetCurrentProcessId(); - - @CFunction(transition = Transition.NO_TRANSITION) - public static native int GetProcessId(HANDLE hProcess); - - @CFunction(transition = Transition.NO_TRANSITION) - public static native int OpenProcessToken(HANDLE processHandle, int desiredAccess, LPHANDLE tokenHandle); - @CConstant public static native int TOKEN_QUERY(); @@ -81,18 +63,9 @@ public static native HANDLE _beginthreadex(PointerBase security, int stacksize, @CFunction public static native int ResumeThread(HANDLE hThread); - @CFunction(transition = Transition.NO_TRANSITION) - public static native int GetExitCodeThread(HANDLE hThread, CIntPointer lpExitCode); - @CFunction public static native int SwitchToThread(); - @CFunction(transition = Transition.NO_TRANSITION) - public static native int GetCurrentThreadId(); - - @CFunction(transition = Transition.NO_TRANSITION) - public static native HANDLE GetCurrentThread(); - @CConstant public static native int SYNCHRONIZE(); @@ -104,21 +77,9 @@ public interface PCRITICAL_SECTION extends PointerBase { public interface CRITICAL_SECTION extends PointerBase { } - @CFunction(transition = Transition.NO_TRANSITION) - public static native void InitializeCriticalSection(PCRITICAL_SECTION mutex); - - @CFunction(transition = Transition.TO_NATIVE) + @CFunction public static native void EnterCriticalSection(PCRITICAL_SECTION mutex); - @CFunction(value = "EnterCriticalSection", transition = Transition.NO_TRANSITION) - public static native void EnterCriticalSectionNoTrans(PCRITICAL_SECTION mutex); - - @CFunction(transition = Transition.NO_TRANSITION) - public static native void LeaveCriticalSection(PCRITICAL_SECTION mutex); - - @CFunction(value = "LeaveCriticalSection", transition = Transition.NO_TRANSITION) - public static native void LeaveCriticalSectionNoTrans(PCRITICAL_SECTION mutex); - @CStruct public interface PCONDITION_VARIABLE extends PointerBase { } @@ -127,18 +88,59 @@ public interface PCONDITION_VARIABLE extends PointerBase { public interface CONDITION_VARIABLE extends PointerBase { } - @CFunction(transition = Transition.NO_TRANSITION) - public static native void InitializeConditionVariable(PCONDITION_VARIABLE cond); - @CFunction public static native int SleepConditionVariableCS(PCONDITION_VARIABLE cond, PCRITICAL_SECTION mutex, int dwMilliseconds); - @CFunction(value = "SleepConditionVariableCS", transition = Transition.NO_TRANSITION) - public static native int SleepConditionVariableCSNoTrans(PCONDITION_VARIABLE cond, PCRITICAL_SECTION mutex, int dwMilliseconds); + public static class NoTransitions { + @CFunction(transition = Transition.NO_TRANSITION) + public static native HANDLE GetCurrentProcess(); - @CFunction(transition = Transition.NO_TRANSITION) - public static native void WakeConditionVariable(PCONDITION_VARIABLE cond); + @CFunction(transition = Transition.NO_TRANSITION) + public static native HANDLE OpenProcess(int dwDesiredAccess, int bInheritHandle, int dwProcessId); - @CFunction(transition = Transition.NO_TRANSITION) - public static native void WakeAllConditionVariable(PCONDITION_VARIABLE cond); + @CFunction(transition = Transition.NO_TRANSITION) + public static native int TerminateProcess(HANDLE hProcess, int uExitCode); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native int GetCurrentProcessId(); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native int GetProcessId(HANDLE hProcess); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native int OpenProcessToken(HANDLE processHandle, int desiredAccess, LPHANDLE tokenHandle); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native int GetExitCodeThread(HANDLE hThread, CIntPointer lpExitCode); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native int SwitchToThread(); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native int GetCurrentThreadId(); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native HANDLE GetCurrentThread(); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native void InitializeCriticalSection(PCRITICAL_SECTION mutex); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native void EnterCriticalSection(PCRITICAL_SECTION mutex); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native void LeaveCriticalSection(PCRITICAL_SECTION mutex); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native void InitializeConditionVariable(PCONDITION_VARIABLE cond); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native int SleepConditionVariableCS(PCONDITION_VARIABLE cond, PCRITICAL_SECTION mutex, int dwMilliseconds); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native void WakeConditionVariable(PCONDITION_VARIABLE cond); + + @CFunction(transition = Transition.NO_TRANSITION) + public static native void WakeAllConditionVariable(PCONDITION_VARIABLE cond); + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java index e7dd8fa0483c..88398b08f9f4 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java @@ -701,15 +701,18 @@ private static void restoreSafepointRequestedValue(IsolateThread vmThread) { /** Wait for there to be no threads (except myself) still waiting to reach a safepoint. */ private static void waitForSafepoints(String reason) { - final Log trace = Log.noopLog().string("[Safepoint.Master.waitForSafepoints: reason: ").string(reason).newline(); VMThreads.THREAD_MUTEX.assertIsOwner("Must hold mutex while waiting for safepoints."); final long startNanos = System.nanoTime(); long loopNanos = startNanos; + long warningNanos = -1; + long failureNanos = -1; + for (int loopCount = 1; /* return */; loopCount += 1) { int atSafepoint = 0; int ignoreSafepoints = 0; int notAtSafepoint = 0; + int lostUpdates = 0; for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { if (isMyself(vmThread)) { /* Don't wait for myself. */ @@ -727,6 +730,7 @@ private static void waitForSafepoints(String reason) { /* Re-request the safepoint in case of a lost update. */ if (getSafepointRequested(vmThread) > 0 && !StatusSupport.isStatusIgnoreSafepoints(vmThread)) { requestSafepoint(vmThread); + lostUpdates++; } notAtSafepoint += 1; break; @@ -758,24 +762,48 @@ private static void waitForSafepoints(String reason) { } } if (notAtSafepoint == 0) { - trace.string(" returns"); - if (trace.isEnabled() && Statistics.Options.GatherSafepointStatistics.getValue()) { - trace.string(" with installed: ").signed(Statistics.getInstalled()); - } - trace.string("]").newline(); return; } - trace.string(" loopCount: ").signed(loopCount) - .string(" atSafepoint: ").signed(atSafepoint) - .string(" ignoreSafepoints: ").signed(ignoreSafepoints) - .string(" notAtSafepoint: ").signed(notAtSafepoint) - .newline(); - loopNanos = doNotLoopTooLong(loopNanos, startNanos, reason); - maybeFatallyTooLong(startNanos, reason); + if (warningNanos == -1 || failureNanos == -1) { + warningNanos = Safepoint.getSafepointPromptnessWarningNanos(); + failureNanos = Safepoint.getSafepointPromptnessFailureNanos(); + } - // Wait impatiently for requested threads to come to a safepoint. - PauseNode.pause(); + long nanosSinceStart = TimeUtils.nanoSecondsSince(startNanos); + if (warningNanos > 0 || failureNanos > 0) { + long nanosSinceLastWarning = TimeUtils.nanoSecondsSince(loopNanos); + + boolean printWarning = warningNanos > 0 && TimeUtils.nanoTimeLessThan(warningNanos, nanosSinceLastWarning); + boolean fatalError = failureNanos > 0 && TimeUtils.nanoTimeLessThan(failureNanos, nanosSinceStart); + if (printWarning || fatalError) { + Log.log().string("[Safepoint.Master: not all threads reached a safepoint (").string(reason).string(") within ").signed(warningNanos).string(" ns. Total wait time so far: ") + .signed(nanosSinceStart).string(" ns.").newline(); + Log.log().string(" loopCount: ").signed(loopCount) + .string(" atSafepoint: ").signed(atSafepoint) + .string(" ignoreSafepoints: ").signed(ignoreSafepoints) + .string(" notAtSafepoint: ").signed(notAtSafepoint) + .string(" lostUpdates: ").signed(lostUpdates) + .string("]") + .newline(); + + loopNanos = System.nanoTime(); + if (fatalError) { + VMError.guarantee(false, "Safepoint promptness failure."); + } + } + } + + // Wait for requested threads to come to a safepoint. + if (VMThreads.singleton().supportsPatientSafepoints()) { + if (nanosSinceStart < TimeUtils.nanosPerMilli) { + VMThreads.singleton().yield(); + } else { + VMThreads.singleton().nativeSleep(1); + } + } else { + PauseNode.pause(); + } } } @@ -808,37 +836,6 @@ private static void releaseSafepoints(String reason) { trace.string("]").newline(); } - /** Have I looped for too long? If so, complain, but reset the wait. */ - private static long doNotLoopTooLong(long loopNanos, long startNanos, String reason) { - long result = loopNanos; - final long waitedNanos = TimeUtils.nanoSecondsSince(loopNanos); - final long warningNanos = Safepoint.getSafepointPromptnessWarningNanos(); - if ((0 < warningNanos) && TimeUtils.nanoTimeLessThan(warningNanos, waitedNanos)) { - final Log warning = Log.log().string("[Safepoint.Master.doNotLoopTooLong:"); - warning.string(" warningNanos: ").signed(warningNanos).string(" < ").string(" waitedNanos: ").signed(waitedNanos); - warning.string(" startNanos: ").signed(startNanos); - warning.string(" reason: ").string(reason).string("]").newline(); - result = System.nanoTime(); - } - return result; - } - - private static void maybeFatallyTooLong(long startNanos, String reason) { - final long failureNanos = Safepoint.getSafepointPromptnessFailureNanos(); - if (0 < failureNanos) { - /* If a promptness limit was set. */ - final long nanosSinceStart = TimeUtils.nanoSecondsSince(startNanos); - if (TimeUtils.nanoTimeLessThan(failureNanos, nanosSinceStart)) { - /* If the promptness limit was exceeded. */ - final Log warning = Log.log().string("[Safepoint.Master.maybeFatallyTooLong:"); - warning.string(" failureNanos: ").signed(failureNanos).string(" < nanosSinceStart: ").signed(nanosSinceStart); - warning.string(" startNanos: ").signed(startNanos); - warning.string(" reason: ").string(reason).string("]").newline(); - VMError.guarantee(false, "Safepoint promptness failure."); - } - } - } - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) protected IsolateThread getRequestingThread() { return requestingThread; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java index 1cb5883f88b4..6b89d79b492a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java @@ -524,6 +524,16 @@ public void nativeSleep(@SuppressWarnings("unused") int milliseconds) { throw VMError.shouldNotReachHere(); } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public void yield() { + throw VMError.shouldNotReachHere(); + } + + // Should not be implemented and will be removed with GR-34388. + public boolean supportsPatientSafepoints() { + return false; + } + @Uninterruptible(reason = "Called from uninterruptible verification code.", mayBeInlined = true) public boolean verifyThreadIsAttached(IsolateThread thread) { return nextThread(thread) != thread; From bcbcdfb306b0c31367f256c35b0ac86913ac2c53 Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Thu, 19 Aug 2021 16:50:36 +0200 Subject: [PATCH 354/681] Use Polybench to create AOT Sulong benchmarks --- sulong/mx.sulong/mx_sulong.py | 5 +- sulong/mx.sulong/mx_sulong_benchmarks.py | 140 +++++++++++++++++- .../truffle/llvm/launcher/LLVMLauncher.java | 14 +- .../launcher/LLVMMultiContextLauncher.java | 2 +- .../src/org/graalvm/polybench/Config.java | 17 ++- .../graalvm/polybench/PolyBenchLauncher.java | 139 +++++++++++++++-- 6 files changed, 287 insertions(+), 30 deletions(-) diff --git a/sulong/mx.sulong/mx_sulong.py b/sulong/mx.sulong/mx_sulong.py index e71de3b8fcc7..e81f03ac3578 100644 --- a/sulong/mx.sulong/mx_sulong.py +++ b/sulong/mx.sulong/mx_sulong.py @@ -314,7 +314,10 @@ def _open_for_reading(path): _env_flags = os.environ['CPPFLAGS'].split(' ') -mx_benchmark.add_bm_suite(mx_sulong_benchmarks.SulongBenchmarkSuite()) +# Legacy bm suite +mx_benchmark.add_bm_suite(mx_sulong_benchmarks.SulongBenchmarkSuite(False)) +# Polybench bm suite +mx_benchmark.add_bm_suite(mx_sulong_benchmarks.SulongBenchmarkSuite(True)) _toolchains = {} diff --git a/sulong/mx.sulong/mx_sulong_benchmarks.py b/sulong/mx.sulong/mx_sulong_benchmarks.py index 5a31be18842b..257a289655d2 100644 --- a/sulong/mx.sulong/mx_sulong_benchmarks.py +++ b/sulong/mx.sulong/mx_sulong_benchmarks.py @@ -65,9 +65,10 @@ def _parse_results_gen(): class SulongBenchmarkSuite(VmBenchmarkSuite): - def __init__(self, *args, **kwargs): + def __init__(self, use_polybench, *args, **kwargs): super(SulongBenchmarkSuite, self).__init__(*args, **kwargs) self.bench_to_exec = {} + self.use_polybench = use_polybench def group(self): return 'Graal' @@ -76,7 +77,7 @@ def subgroup(self): return 'sulong' def name(self): - return 'csuite' + return 'csuite-polybench' if self.use_polybench else 'csuite' def run(self, benchnames, bmSuiteArgs): vm = self.get_vm_registry().get_vm_from_suite_args(bmSuiteArgs) @@ -101,7 +102,11 @@ def run(self, benchnames, bmSuiteArgs): # prepare_env adds CC, CXX, CFLAGS, etc... and we copy the environment to avoid modifying the default one. env = vm.prepare_env(env) - out = os.path.join(bench_out_dir, vm.out_file()) + outName = vm.out_file() + if self.use_polybench: + env['POLYBENCH'] = 'y' + outName += '.so' + out = os.path.join(bench_out_dir, outName) cmdline = ['make', '-f', '../Makefile', out] if mx._opts.verbose: # The Makefiles should have logic to disable the @ sign @@ -142,6 +147,12 @@ def flakySkipPatterns(self, benchmarks, bmSuiteArgs): return [] def rules(self, out, benchmarks, bmSuiteArgs): + if self.use_polybench: + return self.polybenchRules(out, benchmarks, bmSuiteArgs) + else: + return self.legacyRules(out, benchmarks, bmSuiteArgs) + + def legacyRules(self, out, benchmarks, bmSuiteArgs): return [ SulongBenchmarkRule( r'^run (?P[\d]+) first [\d]+ warmup iterations (?P[\S]+):(?P([ ,]+(?:\d+(?:\.\d+)?))+)', @@ -211,6 +222,47 @@ def rules(self, out, benchmarks, bmSuiteArgs): }), ] + def polybenchRules(self, output, benchmarks, bmSuiteArgs): + metric_name = self._get_metric_name(bmSuiteArgs) + return [ + mx_benchmark.StdOutRule(r"\[(?P.*)\] after warmup: (?P.*) (?P.*)", { + "benchmark": ("", str), + "metric.better": "lower", + "metric.name": "warmup", + "metric.unit": ("", str), + "metric.value": ("", float), + "metric.type": "numeric", + "metric.score-function": "id", + "metric.iteration": 0, + }), + mx_benchmark.StdOutRule(r"\[(?P.*)\] after run: (?P.*) (?P.*)", { + "benchmark": ("", str), + "metric.better": "lower", + "metric.name": metric_name, + "metric.unit": ("", str), + "metric.value": ("", float), + "metric.type": "numeric", + "metric.score-function": "id", + "metric.iteration": 0, + }) + + ] + + def _get_metric_name(self, bmSuiteArgs): + metric = None + for arg in bmSuiteArgs: + if arg.startswith("--metric="): + metric = arg[len("--metric="):] + break + if metric == "compilation-time": + return "compile-time" + elif metric == "partial-evaluation-time": + return "pe-time" + elif metric == "one-shot": + return "one-shot" + else: + return "time" + def workingDirectory(self, benchmarks, bmSuiteArgs): if len(benchmarks) != 1: mx.abort( @@ -225,14 +277,15 @@ def createCommandLineArgs(self, benchmarks, bmSuiteArgs): vmArgs = self.vmArgs(bmSuiteArgs) runArgs = self.runArgs(bmSuiteArgs) try: - runArgs += ['--time', str(int(time.clock_gettime(time.CLOCK_REALTIME) * 1000000))] + if not self.use_polybench: + runArgs += ['--time', str(int(time.clock_gettime(time.CLOCK_REALTIME) * 1000000))] except: # We can end up here in case the python version we're running on doesn't have clock_gettime or CLOCK_REALTIME. pass return vmArgs + [self.bench_to_exec[benchmarks[0]]] + runArgs def get_vm_registry(self): - return native_vm_registry + return native_polybench_vm_registry if self.use_polybench else native_vm_registry class CExecutionEnvironmentMixin(object): @@ -447,6 +500,80 @@ def launcherClass(self): def launcherName(self): return "llimul" +class PolybenchVm(CExecutionEnvironmentMixin, GuestVm): + def config_name(self): + return "default" + + def toolchain_name(self): + return "native" + + def name(self): + return "polybench" + + def launcherClass(self): + return "org.graalvm.polybench.PolyBenchLauncher" + + def launcherName(self): + return "polybench" + + def run(self, cwd, args): + bench_file = args[-1:] + bench_args = args[:-1] + launcher_args = ['--path'] + bench_file + bench_args + if hasattr(self.host_vm(), 'run_launcher'): + result = self.host_vm().run_launcher(self.launcherName(), launcher_args, cwd) + else: + def _filter_properties(args): + props = [] + remaining_args = [] + vm_prefix = "--vm.D" + for arg in args: + if arg.startswith(vm_prefix): + props.append('-D' + arg[len(vm_prefix):]) + else: + remaining_args.append(arg) + return props, remaining_args + + props, launcher_args = _filter_properties(launcher_args) + sulongCmdLine = self.launcher_vm_args() + \ + props + \ + ['-XX:-UseJVMCIClassLoader', self.launcherClass(), '--path'] + bench_file + bench_args + result = self.host_vm().run(cwd, sulongCmdLine) + + ret_code, out, vm_dims = result + return ret_code, add_run_numbers(out), vm_dims + + def prepare_env(self, env): + # if hasattr(self.host_vm(), 'run_launcher'): + # import mx_sdk_vm_impl + # env['CC'] = os.path.join(mx_sdk_vm_impl.graalvm_home(fatalIfMissing=True), 'jre', 'languages', 'llvm', self.toolchain_name(), 'bin', 'graalvm-{}-clang'.format(self.toolchain_name())) + # else: + # we always use the bootstrap toolchain since the toolchain is not installed by default in a graalvm + # change this if we can properly install components into a graalvm deployment + env['CC'] = mx_subst.path_substitutions.substitute(''.format(self.toolchain_name())) + env['CXX'] = mx_subst.path_substitutions.substitute(''.format(self.toolchain_name())) + return env + + def out_file(self): + return 'bench' + + def opt_phases(self): + return [] + + def launcher_vm_args(self): + return mx_sulong.getClasspathOptions(['POLYBENCH']) + + def launcher_args(self, args): + launcher_args = [ + '--experimental-options', + '--engine.CompilationFailureAction=ExitVM', + '--engine.TreatPerformanceWarningsAsErrors=call,instanceof,store', + ] + return launcher_args + args + + def hosting_registry(self): + return java_vm_registry + _suite = mx.suite("sulong") native_vm_registry = VmRegistry("Native", known_host_registries=[java_vm_registry]) @@ -460,3 +587,6 @@ def launcherName(self): native_vm_registry.add_vm(ClangVm('O3', ['-O3']), _suite) native_vm_registry.add_vm(SulongVm(), _suite, 10) native_vm_registry.add_vm(SulongMultiContextVm(), _suite, 10) + +native_polybench_vm_registry = VmRegistry("NativePolybench", known_host_registries=[java_vm_registry]) +native_polybench_vm_registry.add_vm(PolybenchVm(), _suite, 10) diff --git a/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMLauncher.java b/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMLauncher.java index 1d44197b16c8..f40ed909a665 100644 --- a/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMLauncher.java +++ b/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMLauncher.java @@ -29,6 +29,13 @@ */ package com.oracle.truffle.llvm.launcher; +import org.graalvm.launcher.AbstractLanguageLauncher; +import org.graalvm.options.OptionCategory; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.PolyglotException; +import org.graalvm.polyglot.Source; +import org.graalvm.polyglot.Value; + import java.io.File; import java.io.IOException; import java.nio.file.Paths; @@ -40,13 +47,6 @@ import java.util.Set; import java.util.stream.Collectors; -import org.graalvm.launcher.AbstractLanguageLauncher; -import org.graalvm.options.OptionCategory; -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.PolyglotException; -import org.graalvm.polyglot.Source; -import org.graalvm.polyglot.Value; - public class LLVMLauncher extends AbstractLanguageLauncher { public static void main(String[] args) { diff --git a/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMMultiContextLauncher.java b/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMMultiContextLauncher.java index 94ed96829c13..31ecbfe521dc 100644 --- a/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMMultiContextLauncher.java +++ b/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMMultiContextLauncher.java @@ -119,7 +119,7 @@ protected int execute(Context.Builder contextBuilder) { if (i == 0) { contextBuilder.option("engine.DebugCachePreinitializeContext", "false").option("engine.DebugCacheCompile", "aot").// option("engine.DebugTraceCache", "true").// - option("engine.DebugCacheLoad", "true").// + option("engine.DebugCacheLoad", "false").// option("engine.DebugCacheStore", "true").// option("engine.MultiTier", "false").// option("llvm.AOTCacheStore", "true").// diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java index ac9b6fe11c9a..68bd19c5b424 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java @@ -24,9 +24,12 @@ */ package org.graalvm.polybench; +import org.graalvm.polyglot.Value; + import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -import org.graalvm.polyglot.Value; +import java.util.Map; class Config { String path; @@ -35,6 +38,10 @@ class Config { int iterations; Mode mode; Metric metric; + int runCount = 1; + boolean useDebugCache; + final Map multiContextEngineOptions = new HashMap<>(); + final List> perIterationContextOptions = new ArrayList<>(); List unrecognizedArguments = new ArrayList<>(); private static final int DEFAULT = -1; @@ -49,19 +56,23 @@ class Config { this.iterations = DEFAULT; this.mode = Mode.standard; this.metric = new PeakTimeMetric(); + this.perIterationContextOptions.add(new HashMap<>()); // iteration 0 options + this.perIterationContextOptions.add(new HashMap<>()); // iteration >0 options } public void parseBenchSpecificDefaults(Value benchmark) { if (warmupIterations == DEFAULT) { if (benchmark.hasMember("warmupIterations")) { - warmupIterations = benchmark.getMember("warmupIterations").asInt(); + Value warmupIterationsMember = benchmark.getMember("warmupIterations"); + warmupIterations = warmupIterationsMember.canExecute() ? warmupIterationsMember.execute().asInt() : warmupIterationsMember.asInt(); } else { warmupIterations = DEFAULT_WARMUP; } } if (iterations == DEFAULT) { if (benchmark.hasMember("iterations")) { - iterations = benchmark.getMember("iterations").asInt(); + Value iterationsMember = benchmark.getMember("iterations"); + iterations = iterationsMember.canExecute() ? iterationsMember.execute().asInt() : iterationsMember.asInt(); } else { iterations = DEFAULT_ITERATIONS; } diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java index 31ecf94b7357..0b36f4d3af94 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java @@ -24,8 +24,17 @@ */ package org.graalvm.polybench; +import org.graalvm.launcher.AbstractLanguageLauncher; +import org.graalvm.options.OptionCategory; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.Source; +import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.proxy.ProxyArray; + import java.io.File; import java.io.IOException; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -34,23 +43,25 @@ import java.util.NoSuchElementException; import java.util.Optional; import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.logging.Handler; -import org.graalvm.launcher.AbstractLanguageLauncher; -import org.graalvm.options.OptionCategory; -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Source; -import org.graalvm.polyglot.Value; -import org.graalvm.polyglot.proxy.ProxyArray; - public final class PolyBenchLauncher extends AbstractLanguageLauncher { static class ArgumentConsumer { private final String prefix; private final BiConsumer action; + private final Consumer flagAction; ArgumentConsumer(String prefix, BiConsumer action) { this.prefix = prefix; this.action = action; + this.flagAction = null; + } + + ArgumentConsumer(String prefix, Consumer flagAction) { + this.prefix = prefix; + this.action = null; + this.flagAction = flagAction; } boolean consume(String argument, Iterator args, Config options) { @@ -66,6 +77,10 @@ boolean consume(String argument, Iterator args, Config options) { if (!argument.equals(prefix)) { return false; } + if (flagAction != null) { + flagAction.accept(options); + return true; + } try { value = args.next(); } catch (NoSuchElementException e) { @@ -124,6 +139,12 @@ static class ArgumentParser { this.consumers.add(new ArgumentConsumer("-i", (value, config) -> { config.iterations = Integer.parseInt(value); })); + this.consumers.add(new ArgumentConsumer("--use-debug-cache", (config) -> { + config.useDebugCache = true; + })); + this.consumers.add(new ArgumentConsumer("--multi-context-runs", (value, config) -> { + config.runCount = Integer.parseInt(value); + })); } Config parse(List arguments) { @@ -160,6 +181,43 @@ protected List preprocessArguments(List arguments, Map 1) { + List engineArgs = new ArrayList<>(); + List> perIterationArgs = new ArrayList<>(); + perIterationArgs.add(new ArrayList<>()); // iteration 0 args + perIterationArgs.add(new ArrayList<>()); // iteration 1 args + + Iterator iterator = this.config.unrecognizedArguments.iterator(); + while (iterator.hasNext()) { + String option = iterator.next(); + + if (option.contains("=")) { + String[] nameValue = option.split("=", 2); + if (nameValue[0].endsWith(".0")) { + iterator.remove(); + perIterationArgs.get(0).add(nameValue[0].substring(0, nameValue[0].length() - 2) + "=" + nameValue[1]); + } else if (nameValue[0].endsWith(".1")) { + iterator.remove(); + perIterationArgs.get(1).add(nameValue[0].substring(0, nameValue[0].length() - 2) + "=" + nameValue[1]); + } + } + + // The engine options must be separated and used later when building a context + if (option.startsWith("--engine.")) { + iterator.remove(); + engineArgs.add(option); + } else if ("--experimental-options".equals(option)) { + engineArgs.add(option); + perIterationArgs.get(0).add(option); + perIterationArgs.get(1).add(option); + } + } + + parseUnrecognizedOptions(getLanguageId(config.path), config.multiContextEngineOptions, engineArgs); + parseUnrecognizedOptions(getLanguageId(config.path), config.perIterationContextOptions.get(0), perIterationArgs.get(0)); + parseUnrecognizedOptions(getLanguageId(config.path), config.perIterationContextOptions.get(1), perIterationArgs.get(1)); + } return this.config.unrecognizedArguments; } @@ -178,11 +236,52 @@ protected void validateArguments(Map polyglotOptions) { @Override protected void launch(Context.Builder contextBuilder) { contextBuilder.allowAllAccess(true); - runHarness(contextBuilder); + + contextBuilder.options(config.multiContextEngineOptions); + if (!config.useDebugCache && config.runCount > 1) { + contextBuilder.engine(Engine.newBuilder().allowExperimentalOptions(true).options(config.multiContextEngineOptions).build()); + } + + if (config.runCount == 0) { + // Create the context and close it right afterwards to trigger the compilation of AOT + // roots + try (Context context = contextBuilder.build()) { + context.eval(Source.newBuilder(getLanguageId(config.path), Paths.get(config.path).toFile()).build()); + return; + } catch (IOException e) { + throw abort(String.format("Error loading file '%s' (%s)", config.path, e.getMessage())); + } + } + + for (int i = 0; i < config.runCount; i++) { + if (!config.useDebugCache) { + runHarness(contextBuilder); + } else { + if (i == 0) { + contextBuilder.option("engine.DebugCachePreinitializeContext", "false").// + option("engine.DebugCacheCompile", "aot").// + option("engine.DebugCacheStore", "true").// + option("engine.MultiTier", "false").// + option("engine.CompileAOTOnCreate", "false"); + contextBuilder.options(config.perIterationContextOptions.get(0)); + try (Context context = contextBuilder.build()) { + context.eval(Source.newBuilder(getLanguageId(config.path), Paths.get(config.path).toFile()).build()); + } catch (IOException e) { + throw abort(String.format("Error loading file '%s' (%s)", config.path, e.getMessage())); + } + } else { + contextBuilder.option("engine.DebugCacheStore", "false").// + option("engine.DebugCacheLoad", "true"); + contextBuilder.options(config.perIterationContextOptions.get(1)); + runHarness(contextBuilder); + } + } + } } @Override protected String getLanguageId() { + // TODO: this should reflect the language of the input file return "js"; } @@ -198,7 +297,7 @@ protected void printHelp(OptionCategory maxCategory) { System.out.println("Run a benchmark in an arbitrary language on the PolyBench harness."); } - private static String getExtension(String path) { + static String getExtension(String path) { int lastDot = path.lastIndexOf('.'); if (lastDot < 0) { return null; @@ -206,6 +305,23 @@ private static String getExtension(String path) { return path.substring(lastDot + 1); } + String getLanguageId(String path) { + final File file = new File(path); + if ("jar".equals(getExtension(path))) { + return "java"; + } else { + try { + String language = Source.findLanguage(file); + if (language == null) { + throw abort("Could not determine the language for file " + file); + } + return language; + } catch (IOException e) { + throw abort("Error while examining source file '" + file + "': " + e.getMessage()); + } + } + } + private EvalResult evalSource(Context context, String path) { final File file = new File(path); if ("jar".equals(getExtension(path))) { @@ -224,10 +340,7 @@ private EvalResult evalSource(Context context, String path) { Source source; String language; try { - language = Source.findLanguage(file); - if (language == null) { - throw abort("Could not determine the language for file " + file); - } + language = getLanguageId(path); source = Source.newBuilder(language, file).build(); } catch (IOException e) { throw abort("Error while examining source file '" + file + "': " + e.getMessage()); From 9b94083b1d8d073f64d425eb1d330439bdbe272b Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Thu, 26 Aug 2021 14:46:50 +0200 Subject: [PATCH 355/681] AOT related fixes --- .../nodes/others/LLVMAccessSymbolNode.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/others/LLVMAccessSymbolNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/others/LLVMAccessSymbolNode.java index 0fd97ab199ea..36ea67e2e584 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/others/LLVMAccessSymbolNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/others/LLVMAccessSymbolNode.java @@ -29,8 +29,6 @@ */ package com.oracle.truffle.llvm.runtime.nodes.others; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateAOT; @@ -42,7 +40,6 @@ import com.oracle.truffle.llvm.runtime.except.LLVMIllegalSymbolIndexException; import com.oracle.truffle.llvm.runtime.except.LLVMLinkerException; import com.oracle.truffle.llvm.runtime.memory.LLVMStack; -import com.oracle.truffle.llvm.runtime.memory.LLVMStack.LLVMStackAccess; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; import com.oracle.truffle.llvm.runtime.nodes.func.LLVMRootNode; import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer; @@ -57,8 +54,6 @@ public abstract class LLVMAccessSymbolNode extends LLVMExpressionNode { protected final LLVMSymbol symbol; - @CompilationFinal private LLVMStackAccess stackAccess; - LLVMAccessSymbolNode(LLVMSymbol symbol) { this.symbol = LLVMAlias.resolveAlias(symbol); } @@ -98,13 +93,14 @@ public LLVMPointer accessSingleContext(@Cached BranchProfile exception) throws L return checkNull(getContext().getSymbol(symbol, exception), exception); } + protected LLVMStack.LLVMStackAccessHolder createStackAccessHolder() { + return new LLVMStack.LLVMStackAccessHolder(((LLVMRootNode) getRootNode()).getStackAccess()); + } + @Specialization public LLVMPointer accessMultiContext(VirtualFrame frame, - @Cached BranchProfile exception) throws LLVMIllegalSymbolIndexException { - if (stackAccess == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - stackAccess = ((LLVMRootNode) getRootNode()).getStackAccess(); - } - return checkNull(stackAccess.executeGetStack(frame).getContext().getSymbol(symbol, exception), exception); + @Cached("createStackAccessHolder()") LLVMStack.LLVMStackAccessHolder stackAccessHolder, + @Cached BranchProfile exception) throws LLVMIllegalSymbolIndexException { + return checkNull(stackAccessHolder.stackAccess.executeGetStack(frame).getContext().getSymbol(symbol, exception), exception); } } From 412915a90fd8119d720a1e61c08e0053eeec73ea Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Mon, 30 Aug 2021 11:58:56 +0200 Subject: [PATCH 356/681] Polybench launcher JavaDoc plus minor fixes --- sulong/mx.sulong/mx_sulong_benchmarks.py | 36 ++++-- .../src/org/graalvm/polybench/Config.java | 4 +- .../graalvm/polybench/PolyBenchLauncher.java | 120 ++++++++++++------ 3 files changed, 104 insertions(+), 56 deletions(-) diff --git a/sulong/mx.sulong/mx_sulong_benchmarks.py b/sulong/mx.sulong/mx_sulong_benchmarks.py index 257a289655d2..60595e96b4de 100644 --- a/sulong/mx.sulong/mx_sulong_benchmarks.py +++ b/sulong/mx.sulong/mx_sulong_benchmarks.py @@ -113,6 +113,7 @@ def run(self, benchnames, bmSuiteArgs): # so that all executed commands are visible. cmdline += ["MX_VERBOSE=y"] mx.run(cmdline, env=env) + mx.log("Making " + out) self.bench_to_exec[bench] = out finally: # reset current Directory @@ -151,7 +152,7 @@ def rules(self, out, benchmarks, bmSuiteArgs): return self.polybenchRules(out, benchmarks, bmSuiteArgs) else: return self.legacyRules(out, benchmarks, bmSuiteArgs) - + def legacyRules(self, out, benchmarks, bmSuiteArgs): return [ SulongBenchmarkRule( @@ -223,18 +224,12 @@ def legacyRules(self, out, benchmarks, bmSuiteArgs): ] def polybenchRules(self, output, benchmarks, bmSuiteArgs): + warmupIterCountRule = mx_benchmark.StdOutRule(r"warmup-iterations: (?P.*)", { + "result": ("", int), + }), + warmupIterCount = warmupIterCountRule[0].parse(output)[0]['result'] metric_name = self._get_metric_name(bmSuiteArgs) - return [ - mx_benchmark.StdOutRule(r"\[(?P.*)\] after warmup: (?P.*) (?P.*)", { - "benchmark": ("", str), - "metric.better": "lower", - "metric.name": "warmup", - "metric.unit": ("", str), - "metric.value": ("", float), - "metric.type": "numeric", - "metric.score-function": "id", - "metric.iteration": 0, - }), + rules = [ mx_benchmark.StdOutRule(r"\[(?P.*)\] after run: (?P.*) (?P.*)", { "benchmark": ("", str), "metric.better": "lower", @@ -245,8 +240,21 @@ def polybenchRules(self, output, benchmarks, bmSuiteArgs): "metric.score-function": "id", "metric.iteration": 0, }) - ] + if warmupIterCount > 0: + rules += [ + mx_benchmark.StdOutRule(r"\[(?P.*)\] after warmup: (?P.*) (?P.*)", { + "benchmark": ("", str), + "metric.better": "lower", + "metric.name": "warmup", + "metric.unit": ("", str), + "metric.value": ("", float), + "metric.type": "numeric", + "metric.score-function": "id", + "metric.iteration": 0, + }) + ] + return rules def _get_metric_name(self, bmSuiteArgs): metric = None @@ -508,7 +516,7 @@ def toolchain_name(self): return "native" def name(self): - return "polybench" + return "sulong-polybench" def launcherClass(self): return "org.graalvm.polybench.PolyBenchLauncher" diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java index 68bd19c5b424..9aa890a515ac 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java @@ -63,7 +63,7 @@ class Config { public void parseBenchSpecificDefaults(Value benchmark) { if (warmupIterations == DEFAULT) { if (benchmark.hasMember("warmupIterations")) { - Value warmupIterationsMember = benchmark.getMember("warmupIterations"); + Value warmupIterationsMember = benchmark.getMember("warmupIterations"); warmupIterations = warmupIterationsMember.canExecute() ? warmupIterationsMember.execute().asInt() : warmupIterationsMember.asInt(); } else { warmupIterations = DEFAULT_WARMUP; @@ -71,7 +71,7 @@ public void parseBenchSpecificDefaults(Value benchmark) { } if (iterations == DEFAULT) { if (benchmark.hasMember("iterations")) { - Value iterationsMember = benchmark.getMember("iterations"); + Value iterationsMember = benchmark.getMember("iterations"); iterations = iterationsMember.canExecute() ? iterationsMember.execute().asInt() : iterationsMember.asInt(); } else { iterations = DEFAULT_ITERATIONS; diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java index 0b36f4d3af94..1a5a43f3ad6b 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java @@ -46,6 +46,29 @@ import java.util.function.Consumer; import java.util.logging.Handler; +/** + * This launcher allows for multi-context benchmarking, which is enabled by the + * --multi-context-runs option. The value of this option determines the number of + * benchmark runs and can be 0 or greater. When zero runs is specified, a new context + * is created and closed right after the source file is parsed without running the benchmark, + * though. (N.B. This is especially useful for storing auxiliary engine cache containing ASTs + * created during the parsing of the source file.) On the other hand, if the number of runs is + * greater than 1, then a new engine is created and used for each context created for each run. If + * the number of runs is 1 (the default) then no engine is explicitly created. + *

+ * It is possible to specify different arguments for each iteration (N.B. currently for the first + * two iterations only). The pattern of an iteration specific argument is: + * + *

+ * <arg_name>.<iteration>=<value>
+ * 
+ *

+ * In order to facilitate debugging of benchmarks using auxiliary engine cache, the + * --use-debug-cache option can be used. Using this option should be accompanied by + * --multi-context-runs=2. In the first iteration the source is parsed and the + * in-memory auxiliary engine cache is stored without running the benchmark, while the second + * iteration will load the in-memory cache and run the benchmark. + */ public final class PolyBenchLauncher extends AbstractLanguageLauncher { static class ArgumentConsumer { private final String prefix; @@ -183,42 +206,57 @@ protected List preprocessArguments(List arguments, Map 1) { - List engineArgs = new ArrayList<>(); - List> perIterationArgs = new ArrayList<>(); - perIterationArgs.add(new ArrayList<>()); // iteration 0 args - perIterationArgs.add(new ArrayList<>()); // iteration 1 args - - Iterator iterator = this.config.unrecognizedArguments.iterator(); - while (iterator.hasNext()) { - String option = iterator.next(); - - if (option.contains("=")) { - String[] nameValue = option.split("=", 2); - if (nameValue[0].endsWith(".0")) { + processMultiContextArguments(); + } + return this.config.unrecognizedArguments; + } + + private void processMultiContextArguments() { + List engineArgs = new ArrayList<>(); + // The storage for the iteration-specific arguments + List> perIterationArgs = new ArrayList<>(); + // Iteration-specific arguments can be specified for the two first iterations only atm. + perIterationArgs.add(new ArrayList<>()); // iteration 0 args + perIterationArgs.add(new ArrayList<>()); // iteration 1 args + + Iterator iterator = this.config.unrecognizedArguments.iterator(); + while (iterator.hasNext()) { + String option = iterator.next(); + + // Extract iteration-specific arguments. The pattern of an iteration specific arguments + // is: .= + if (option.contains("=")) { + String[] nameValue = option.split("=", 2); + String indexedArgName = nameValue[0]; + if (indexedArgName.length() >= 3) { + String argName = indexedArgName.substring(0, indexedArgName.length() - 2); + String argValue = nameValue[1]; + if (indexedArgName.endsWith(".0")) { iterator.remove(); - perIterationArgs.get(0).add(nameValue[0].substring(0, nameValue[0].length() - 2) + "=" + nameValue[1]); - } else if (nameValue[0].endsWith(".1")) { + perIterationArgs.get(0).add(argName + "=" + argValue); + continue; + } else if (indexedArgName.endsWith(".1")) { iterator.remove(); - perIterationArgs.get(1).add(nameValue[0].substring(0, nameValue[0].length() - 2) + "=" + nameValue[1]); + perIterationArgs.get(1).add(argName + "=" + argValue); + continue; } } - - // The engine options must be separated and used later when building a context - if (option.startsWith("--engine.")) { - iterator.remove(); - engineArgs.add(option); - } else if ("--experimental-options".equals(option)) { - engineArgs.add(option); - perIterationArgs.get(0).add(option); - perIterationArgs.get(1).add(option); - } } - parseUnrecognizedOptions(getLanguageId(config.path), config.multiContextEngineOptions, engineArgs); - parseUnrecognizedOptions(getLanguageId(config.path), config.perIterationContextOptions.get(0), perIterationArgs.get(0)); - parseUnrecognizedOptions(getLanguageId(config.path), config.perIterationContextOptions.get(1), perIterationArgs.get(1)); + // The engine options must be separated and used later when building a context + if (option.startsWith("--engine.")) { + iterator.remove(); + engineArgs.add(option); + } else if ("--experimental-options".equals(option)) { + engineArgs.add(option); + perIterationArgs.get(0).add(option); + perIterationArgs.get(1).add(option); + } } - return this.config.unrecognizedArguments; + + parseUnrecognizedOptions(getLanguageId(config.path), config.multiContextEngineOptions, engineArgs); + parseUnrecognizedOptions(getLanguageId(config.path), config.perIterationContextOptions.get(0), perIterationArgs.get(0)); + parseUnrecognizedOptions(getLanguageId(config.path), config.perIterationContextOptions.get(1), perIterationArgs.get(1)); } @Override @@ -254,16 +292,17 @@ protected void launch(Context.Builder contextBuilder) { } for (int i = 0; i < config.runCount; i++) { - if (!config.useDebugCache) { - runHarness(contextBuilder); - } else { + Map perIterationOptions = config.perIterationContextOptions.get(i); + if (perIterationOptions != null) { + contextBuilder.options(perIterationOptions); + } + if (config.useDebugCache) { + // The debug engine cache facilitation if (i == 0) { - contextBuilder.option("engine.DebugCachePreinitializeContext", "false").// - option("engine.DebugCacheCompile", "aot").// - option("engine.DebugCacheStore", "true").// - option("engine.MultiTier", "false").// - option("engine.CompileAOTOnCreate", "false"); - contextBuilder.options(config.perIterationContextOptions.get(0)); + contextBuilder.option("engine.DebugCacheCompile", "aot").// + option("engine.DebugCacheStore", "true").// + option("engine.MultiTier", "false").// + option("engine.CompileAOTOnCreate", "false"); try (Context context = contextBuilder.build()) { context.eval(Source.newBuilder(getLanguageId(config.path), Paths.get(config.path).toFile()).build()); } catch (IOException e) { @@ -271,10 +310,11 @@ protected void launch(Context.Builder contextBuilder) { } } else { contextBuilder.option("engine.DebugCacheStore", "false").// - option("engine.DebugCacheLoad", "true"); - contextBuilder.options(config.perIterationContextOptions.get(1)); + option("engine.DebugCacheLoad", "true"); runHarness(contextBuilder); } + } else { + runHarness(contextBuilder); } } } From f5dad36c87184f43589a787a26c3978dd7cd9142 Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Tue, 7 Sep 2021 16:15:54 +0200 Subject: [PATCH 357/681] Minor changes in sulong/polybench configuration --- sulong/mx.sulong/mx_sulong_benchmarks.py | 107 ++++++++++++------ .../nodes/others/LLVMAccessSymbolNode.java | 4 +- .../graalvm/polybench/PolyBenchLauncher.java | 2 + 3 files changed, 75 insertions(+), 38 deletions(-) diff --git a/sulong/mx.sulong/mx_sulong_benchmarks.py b/sulong/mx.sulong/mx_sulong_benchmarks.py index 60595e96b4de..b5c7b27f2a0d 100644 --- a/sulong/mx.sulong/mx_sulong_benchmarks.py +++ b/sulong/mx.sulong/mx_sulong_benchmarks.py @@ -63,6 +63,19 @@ def _parse_results_gen(): yield r return (x for x in _parse_results_gen()) +class PolybenchExcludeWarmupRule(mx_benchmark.StdOutRule): + """Rule that behaves as the StdOutRule, but skips input until a certain pattern.""" + + def __init__(self, *args, **kwargs): + self.startPattern = re.compile(kwargs.pop('startPattern')) + super(PolybenchExcludeWarmupRule, self).__init__(*args, **kwargs) + + def parse(self, text): + m = self.startPattern.search(text) + if m: + return super(PolybenchExcludeWarmupRule, self).parse(text[m.end()+1:]) + else: + return [] class SulongBenchmarkSuite(VmBenchmarkSuite): def __init__(self, use_polybench, *args, **kwargs): @@ -113,7 +126,6 @@ def run(self, benchnames, bmSuiteArgs): # so that all executed commands are visible. cmdline += ["MX_VERBOSE=y"] mx.run(cmdline, env=env) - mx.log("Making " + out) self.bench_to_exec[bench] = out finally: # reset current Directory @@ -143,8 +155,12 @@ def flakySkipPatterns(self, benchmarks, bmSuiteArgs): # preparatory benchmark is run using the llimul launcher and passing --multi-context-runs=0. # We can capture this argument here and instruct the benchmark infrastructure to ignore # the output of this benchmark. - if any(a == "--multi-context-runs=0" for a in bmSuiteArgs): - return [re.compile(r'.*', re.MULTILINE)] + if self.use_polybench: + if any(a == "store-aux-engine-cache" for a in bmSuiteArgs): + return [re.compile(r'.*', re.MULTILINE)] + else: + if any(a == "--multi-context-runs=0" for a in bmSuiteArgs): + return [re.compile(r'.*', re.MULTILINE)] return [] def rules(self, out, benchmarks, bmSuiteArgs): @@ -224,36 +240,30 @@ def legacyRules(self, out, benchmarks, bmSuiteArgs): ] def polybenchRules(self, output, benchmarks, bmSuiteArgs): - warmupIterCountRule = mx_benchmark.StdOutRule(r"warmup-iterations: (?P.*)", { - "result": ("", int), - }), - warmupIterCount = warmupIterCountRule[0].parse(output)[0]['result'] - metric_name = self._get_metric_name(bmSuiteArgs) rules = [ - mx_benchmark.StdOutRule(r"\[(?P.*)\] after run: (?P.*) (?P.*)", { - "benchmark": ("", str), - "metric.better": "lower", - "metric.name": metric_name, - "metric.unit": ("", str), - "metric.value": ("", float), - "metric.type": "numeric", - "metric.score-function": "id", - "metric.iteration": 0, - }) + mx_benchmark.StdOutRule(r"\[(?P.*)\] iteration ([0-9]*): (?P.*) (?P.*)", { + "bench-suite": "csuite", + "benchmark": benchmarks[0], + "metric.better": "lower", + "metric.name": "warmup", + "metric.unit": ("", str), + "metric.value": ("", float), + "metric.type": "numeric", + "metric.score-function": "id", + "metric.iteration": ("$iteration", int), + }), + PolybenchExcludeWarmupRule(r"\[(?P.*)\] iteration (?P[0-9]*): (?P.*) (?P.*)", { + "bench-suite": "csuite", + "benchmark": benchmarks[0], + "metric.better": "lower", + "metric.name": "time", + "metric.unit": ("", str), + "metric.value": ("", float), + "metric.type": "numeric", + "metric.score-function": "id", + "metric.iteration": ("", int), + }, startPattern=r"::: Running :::") ] - if warmupIterCount > 0: - rules += [ - mx_benchmark.StdOutRule(r"\[(?P.*)\] after warmup: (?P.*) (?P.*)", { - "benchmark": ("", str), - "metric.better": "lower", - "metric.name": "warmup", - "metric.unit": ("", str), - "metric.value": ("", float), - "metric.type": "numeric", - "metric.score-function": "id", - "metric.iteration": 0, - }) - ] return rules def _get_metric_name(self, bmSuiteArgs): @@ -277,7 +287,12 @@ def workingDirectory(self, benchmarks, bmSuiteArgs): "Please run a specific benchmark (mx benchmark csuite:) or all the benchmarks (mx benchmark csuite:*)") vm = self.get_vm_registry().get_vm_from_suite_args(bmSuiteArgs) assert isinstance(vm, CExecutionEnvironmentMixin) - return join(_benchmarksDirectory(), benchmarks[0], vm.bin_dir()) + + if self.use_polybench and (any(a == "store-aux-engine-cache" for a in bmSuiteArgs) or any(a == "load-aux-engine-cache" for a in bmSuiteArgs)): + # When storing or loading an aux engine cache, the working directory must be the same (the cache for the source is selected by its URL) + return join(_benchmarksDirectory(), benchmarks[0], 'aux-engine-cache') + else: + return join(_benchmarksDirectory(), benchmarks[0], vm.bin_dir()) def createCommandLineArgs(self, benchmarks, bmSuiteArgs): if len(benchmarks) != 1: @@ -509,8 +524,17 @@ def launcherName(self): return "llimul" class PolybenchVm(CExecutionEnvironmentMixin, GuestVm): + + def __init__(self, config_name, options, host_vm=None): + super(PolybenchVm, self).__init__(host_vm) + self._config_name = config_name + self._options = options + + def with_host_vm(self, host_vm): + return PolybenchVm(self._config_name, self._options, host_vm) + def config_name(self): - return "default" + return self._config_name def toolchain_name(self): return "native" @@ -527,7 +551,7 @@ def launcherName(self): def run(self, cwd, args): bench_file = args[-1:] bench_args = args[:-1] - launcher_args = ['--path'] + bench_file + bench_args + launcher_args = ['--path'] + bench_file + self._options + bench_args if hasattr(self.host_vm(), 'run_launcher'): result = self.host_vm().run_launcher(self.launcherName(), launcher_args, cwd) else: @@ -545,7 +569,7 @@ def _filter_properties(args): props, launcher_args = _filter_properties(launcher_args) sulongCmdLine = self.launcher_vm_args() + \ props + \ - ['-XX:-UseJVMCIClassLoader', self.launcherClass(), '--path'] + bench_file + bench_args + ['-XX:-UseJVMCIClassLoader', self.launcherClass(), '--path'] + bench_file + launcher_args result = self.host_vm().run(cwd, sulongCmdLine) ret_code, out, vm_dims = result @@ -597,4 +621,15 @@ def hosting_registry(self): native_vm_registry.add_vm(SulongMultiContextVm(), _suite, 10) native_polybench_vm_registry = VmRegistry("NativePolybench", known_host_registries=[java_vm_registry]) -native_polybench_vm_registry.add_vm(PolybenchVm(), _suite, 10) +native_polybench_vm_registry.add_vm(PolybenchVm('debug-aux-engine-cache', + ['--experimental-options', '--use-debug-cache', '--llvm.AOTCacheStore.0=true', '--llvm.AOTCacheLoad.0=false', + '--llvm.AOTCacheStore.1=false', '--llvm.AOTCacheLoad.1=true', '--engine.DebugCachePreinitializeContext=false', + '--engine.DebugTraceCache=true', '--multi-context-runs=2', '-w', '0', '-i', '10']), _suite, 10) +native_polybench_vm_registry.add_vm(PolybenchVm('store-aux-engine-cache', + ['--experimental-options', '--multi-context-runs=0', '--engine.CacheStore=' + os.path.join(os.getcwd(), 'test.image'), + '--llvm.AOTCacheStore=true', '--engine.CacheCompile=aot', '--engine.CachePreinitializeContext=false', + '--engine.TraceCache=true']), _suite, 10) +native_polybench_vm_registry.add_vm(PolybenchVm('load-aux-engine-cache', + ['--experimental-options', '--multi-context-runs=1', '--engine.CacheLoad=' + os.path.join(os.getcwd(), 'test.image'), + '--llvm.AOTCacheLoad=true', '--engine.CachePreinitializeContext=false', '--engine.TraceCache=true', + '-w', '0', '-i', '10']), _suite, 10) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/others/LLVMAccessSymbolNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/others/LLVMAccessSymbolNode.java index 36ea67e2e584..ec3c504e7b24 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/others/LLVMAccessSymbolNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/others/LLVMAccessSymbolNode.java @@ -99,8 +99,8 @@ protected LLVMStack.LLVMStackAccessHolder createStackAccessHolder() { @Specialization public LLVMPointer accessMultiContext(VirtualFrame frame, - @Cached("createStackAccessHolder()") LLVMStack.LLVMStackAccessHolder stackAccessHolder, - @Cached BranchProfile exception) throws LLVMIllegalSymbolIndexException { + @Cached("createStackAccessHolder()") LLVMStack.LLVMStackAccessHolder stackAccessHolder, + @Cached BranchProfile exception) throws LLVMIllegalSymbolIndexException { return checkNull(stackAccessHolder.stackAccess.executeGetStack(frame).getContext().getSymbol(symbol, exception), exception); } } diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java index 1a5a43f3ad6b..9140bc8a50f9 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java @@ -68,8 +68,10 @@ * --multi-context-runs=2. In the first iteration the source is parsed and the * in-memory auxiliary engine cache is stored without running the benchmark, while the second * iteration will load the in-memory cache and run the benchmark. + * */ public final class PolyBenchLauncher extends AbstractLanguageLauncher { + static class ArgumentConsumer { private final String prefix; private final BiConsumer action; From 5fe0c0e6ca7799fdd004c7c10ec401db77a81ca5 Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Mon, 20 Sep 2021 17:21:32 +0200 Subject: [PATCH 358/681] PolyBenchLauncher: Improved options handling and JavaDoc extended. --- sulong/mx.sulong/mx_sulong_benchmarks.py | 8 +- .../truffle/llvm/launcher/LLVMLauncher.java | 14 +- .../src/org/graalvm/polybench/Config.java | 15 +- .../graalvm/polybench/PolyBenchLauncher.java | 351 +++++++++++------- 4 files changed, 244 insertions(+), 144 deletions(-) diff --git a/sulong/mx.sulong/mx_sulong_benchmarks.py b/sulong/mx.sulong/mx_sulong_benchmarks.py index b5c7b27f2a0d..2e6bb6f9883b 100644 --- a/sulong/mx.sulong/mx_sulong_benchmarks.py +++ b/sulong/mx.sulong/mx_sulong_benchmarks.py @@ -622,11 +622,13 @@ def hosting_registry(self): native_polybench_vm_registry = VmRegistry("NativePolybench", known_host_registries=[java_vm_registry]) native_polybench_vm_registry.add_vm(PolybenchVm('debug-aux-engine-cache', - ['--experimental-options', '--use-debug-cache', '--llvm.AOTCacheStore.0=true', '--llvm.AOTCacheLoad.0=false', - '--llvm.AOTCacheStore.1=false', '--llvm.AOTCacheLoad.1=true', '--engine.DebugCachePreinitializeContext=false', + ['--experimental-options', '--eval-source-only.0', + '--llvm.AOTCacheStore.0=true', '--llvm.AOTCacheLoad.0=false', '--engine.DebugCacheCompile.0=aot', '--engine.DebugCacheStore.0=true', + '--llvm.AOTCacheStore.1=false', '--llvm.AOTCacheLoad.1=true', '--engine.DebugCacheStore.1=false', '--engine.DebugCacheLoad.1=true', + '--engine.MultiTier=false', '--engine.CompileAOTOnCreate=false', '--engine.DebugCachePreinitializeContext=false', '--engine.DebugTraceCache=true', '--multi-context-runs=2', '-w', '0', '-i', '10']), _suite, 10) native_polybench_vm_registry.add_vm(PolybenchVm('store-aux-engine-cache', - ['--experimental-options', '--multi-context-runs=0', '--engine.CacheStore=' + os.path.join(os.getcwd(), 'test.image'), + ['--experimental-options', '--multi-context-runs=1', '--eval-source-only', '--engine.CacheStore=' + os.path.join(os.getcwd(), 'test.image'), '--llvm.AOTCacheStore=true', '--engine.CacheCompile=aot', '--engine.CachePreinitializeContext=false', '--engine.TraceCache=true']), _suite, 10) native_polybench_vm_registry.add_vm(PolybenchVm('load-aux-engine-cache', diff --git a/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMLauncher.java b/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMLauncher.java index f40ed909a665..1d44197b16c8 100644 --- a/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMLauncher.java +++ b/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMLauncher.java @@ -29,13 +29,6 @@ */ package com.oracle.truffle.llvm.launcher; -import org.graalvm.launcher.AbstractLanguageLauncher; -import org.graalvm.options.OptionCategory; -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.PolyglotException; -import org.graalvm.polyglot.Source; -import org.graalvm.polyglot.Value; - import java.io.File; import java.io.IOException; import java.nio.file.Paths; @@ -47,6 +40,13 @@ import java.util.Set; import java.util.stream.Collectors; +import org.graalvm.launcher.AbstractLanguageLauncher; +import org.graalvm.options.OptionCategory; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.PolyglotException; +import org.graalvm.polyglot.Source; +import org.graalvm.polyglot.Value; + public class LLVMLauncher extends AbstractLanguageLauncher { public static void main(String[] args) { diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java index 9aa890a515ac..df35db7923f8 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java @@ -38,14 +38,17 @@ class Config { int iterations; Mode mode; Metric metric; - int runCount = 1; - boolean useDebugCache; - final Map multiContextEngineOptions = new HashMap<>(); - final List> perIterationContextOptions = new ArrayList<>(); + final Map engineOptions = new HashMap<>(); + boolean evalSourceOnly; + + int numberOfRuns = 1; + boolean sharedEngine; + final Map> runOptionsMap = new HashMap<>(); + final Map evalSourceOnlyFlagsMap = new HashMap<>(); + List unrecognizedArguments = new ArrayList<>(); private static final int DEFAULT = -1; - private static final int DEFAULT_WARMUP = 20; private static final int DEFAULT_ITERATIONS = 30; @@ -56,8 +59,6 @@ class Config { this.iterations = DEFAULT; this.mode = Mode.standard; this.metric = new PeakTimeMetric(); - this.perIterationContextOptions.add(new HashMap<>()); // iteration 0 options - this.perIterationContextOptions.add(new HashMap<>()); // iteration >0 options } public void parseBenchSpecificDefaults(Value benchmark) { diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java index 9140bc8a50f9..96691999db79 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java @@ -34,8 +34,8 @@ import java.io.File; import java.io.IOException; -import java.nio.file.Paths; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; @@ -43,50 +43,111 @@ import java.util.NoSuchElementException; import java.util.Optional; import java.util.function.BiConsumer; -import java.util.function.Consumer; import java.util.logging.Handler; /** - * This launcher allows for multi-context benchmarking, which is enabled by the - * --multi-context-runs option. The value of this option determines the number of - * benchmark runs and can be 0 or greater. When zero runs is specified, a new context - * is created and closed right after the source file is parsed without running the benchmark, - * though. (N.B. This is especially useful for storing auxiliary engine cache containing ASTs - * created during the parsing of the source file.) On the other hand, if the number of runs is - * greater than 1, then a new engine is created and used for each context created for each run. If - * the number of runs is 1 (the default) then no engine is explicitly created. + * This launcher is designed for benchmarking Truffle languages. It repeatedly executes the source + * file specified by its path, whereas the number of warmup and hot iterations can be specified + * either explicitly or determined via interop from the evaluated source value by reading or + * executing members iterations and warmupIterations. + *

+ * The launcher generates a structured output containing information on individual iterations as + * well as the benchmark summary. + *

+ * The following options are accepted: + *

    + *
  • --path <script>
  • + *
  • --class-name <class>
  • The class name of an Espresso benchmark inside the jar + * specified by path. + *
  • --mode [interpreter | standard]
  • Indicates whether the benchmark will be run in the + * interpreter only or the Graal compiler will be used. + *
  • --metric [peak-time | compilation-time | partial-evaluation-time | one-shot | none]
  • + *
  • -w <N>
  • The number of warmup iterations + *
  • -i <N>
  • The number of hot iterations + *
  • --eval-source-only
  • Indicates that the source file will be evaluated only, and the + * benchmark execution will be skipped. It can be useful for parsing time benchmarking or for using + * the debug auxiliary engine cache. N.B. This option can also be specified for each run in a + * multi-context benchmarking. See below. + *
+ *

Multi-context benchmarking

+ *

+ * This launcher allows for multi-context benchmarking consisting of several consecutive benchmark + * runs. Each run is executed using a new context instance, while all contexts can + * share a single engine. A multi-context benchmarking can be configured using the following + * options: + *

    + *
  • --multi-context-runs
  • The number of runs + *
  • --shared-engine
  • Indicates whether the contexts will share a single engine + *
*

- * It is possible to specify different arguments for each iteration (N.B. currently for the first - * two iterations only). The pattern of an iteration specific argument is: + * It is possible to specify different arguments for each iteration. The pattern of an iteration + * specific argument is: * *

  * <arg_name>.<iteration>=<value>
+ * OR
+ * <arg_name>.<iteration>
  * 
*

- * In order to facilitate debugging of benchmarks using auxiliary engine cache, the - * --use-debug-cache option can be used. Using this option should be accompanied by - * --multi-context-runs=2. In the first iteration the source is parsed and the - * in-memory auxiliary engine cache is stored without running the benchmark, while the second - * iteration will load the in-memory cache and run the benchmark. - * + *

Examples

+ *

A single run with 5 warmup and 10 hot iterations

+ * + *
+ *     polybench --path bench.so -w 5 -i 10
+ * 
+ * + *

Two runs with 5 warmup and 10 hot iterations each (no shared engine)

+ * + *
+ *     polybench --path bench.so --multi-context-runs=2 -w 5 -i 10
+ * 
+ * + *

Two runs with 5 warmup and 10 hot iterations each with a shared engine

+ * + *
+ *     polybench --path bench.so --multi-context-runs=2 --shared-engine -w 5 -i 10
+ * 
+ * + *

Storing the auxiliary engine cache and skipping the benchmark

+ * + *
+ *     polybench --path bench.so --eval-source-only --experimental-options --engine.CacheStore=test.image --engine.CacheCompile=aot
+ * 
+ * + *

Loading the auxiliary engine cache and running the benchmark

+ * + *
+ *     polybench --path bench.so --experimental-options --engine.CacheLoad=test.image -w 0 -i 10
+ * 
+ * + *

Using the debug engine cache. The first run only evaluates the source and stores the debug + * engine cache, while the second run executes the benchmark with the cache.

+ * + *
+ *     polybench --path bench.so --multi-context-runs=2 --eval-source-only.0 -w 0 -i 10 --experimental-options --engine.DebugCacheCompile.0=aot --engine.DebugCacheStore.0=true --engine.DebugCacheStore.1=false --engine.DebugCacheLoad.1=true
+ * 
+ * + *

Reporting the source evaluation time only for 10 runs

+ * + *
+ *     polybench --path bench.so --multi-context-runs=10 --eval-source-only
+ * 
*/ public final class PolyBenchLauncher extends AbstractLanguageLauncher { static class ArgumentConsumer { private final String prefix; private final BiConsumer action; - private final Consumer flagAction; + private final boolean isFlag; - ArgumentConsumer(String prefix, BiConsumer action) { + /** + * @param isFlag if true, the action is invoked only if the option is present. + * The value is then null. + */ + ArgumentConsumer(String prefix, BiConsumer action, boolean isFlag) { this.prefix = prefix; this.action = action; - this.flagAction = null; - } - - ArgumentConsumer(String prefix, Consumer flagAction) { - this.prefix = prefix; - this.action = null; - this.flagAction = flagAction; + this.isFlag = isFlag; } boolean consume(String argument, Iterator args, Config options) { @@ -97,19 +158,31 @@ boolean consume(String argument, Iterator args, Config options) { final String value; if (prefix.length() > 2 && argument.contains("=")) { // Only multi-character flags support the equals syntax. - value = argument.split("=", 2)[1]; + String[] argNameValue = argument.split("=", 2); + if (!argNameValue[0].equals(prefix)) { + return false; + } + if (isFlag) { + if (!Boolean.parseBoolean(argNameValue[1])) { + return true; + } else { + value = null; + } + } else { + value = argNameValue[1]; + } } else { if (!argument.equals(prefix)) { return false; } - if (flagAction != null) { - flagAction.accept(options); - return true; - } - try { - value = args.next(); - } catch (NoSuchElementException e) { - throw new IllegalArgumentException("Premature end of arguments for prefix " + prefix + "."); + if (isFlag) { + value = null; + } else { + try { + value = args.next(); + } catch (NoSuchElementException e) { + throw new IllegalArgumentException("Premature end of arguments for prefix " + prefix + "."); + } } } action.accept(value, options); @@ -128,13 +201,13 @@ static class ArgumentParser { this.consumers = new ArrayList<>(); this.consumers.add(new ArgumentConsumer("--path", (value, config) -> { config.path = value; - })); + }, false)); this.consumers.add(new ArgumentConsumer("--class-name", (value, config) -> { config.className = value; - })); + }, false)); this.consumers.add(new ArgumentConsumer("--mode", (value, config) -> { config.mode = Config.Mode.parse(value); - })); + }, false)); this.consumers.add(new ArgumentConsumer("--metric", (value, config) -> { switch (value) { case "peak-time": @@ -157,19 +230,22 @@ static class ArgumentParser { default: throw new IllegalArgumentException("Unknown metric: " + value); } - })); + }, false)); this.consumers.add(new ArgumentConsumer("-w", (value, config) -> { config.warmupIterations = Integer.parseInt(value); - })); + }, false)); this.consumers.add(new ArgumentConsumer("-i", (value, config) -> { config.iterations = Integer.parseInt(value); - })); - this.consumers.add(new ArgumentConsumer("--use-debug-cache", (config) -> { - config.useDebugCache = true; - })); + }, false)); + this.consumers.add(new ArgumentConsumer("--shared-engine", (value, config) -> { + config.sharedEngine = true; + }, true)); + this.consumers.add(new ArgumentConsumer("--eval-source-only", (value, config) -> { + config.evalSourceOnly = true; + }, true)); this.consumers.add(new ArgumentConsumer("--multi-context-runs", (value, config) -> { - config.runCount = Integer.parseInt(value); - })); + config.numberOfRuns = Integer.parseInt(value); + }, false)); } Config parse(List arguments) { @@ -188,6 +264,38 @@ Config parse(List arguments) { } } + static class RunOption { + final int runIndex; + final String name; + final String value; + + RunOption(int runIndex, String name, String value) { + this.runIndex = runIndex; + this.name = name; + this.value = value; + } + + static RunOption parse(String option) { + String[] nameValue = option.split("=", 2); + if (nameValue.length < 1) { + return null; + } + String indexedName = nameValue[0]; + int lastDot = indexedName.lastIndexOf('.'); + if (lastDot < 0 || lastDot == indexedName.length() - 1) { + return null; + } + String name = indexedName.substring(0, lastDot); + String runIndexStr = indexedName.substring(lastDot + 1); + try { + int runIndex = Integer.parseInt(runIndexStr); + return new RunOption(runIndex, name, nameValue.length > 1 ? nameValue[1] : null); + } catch (NumberFormatException e) { + return null; + } + } + } + private static final ArgumentParser PARSER = new ArgumentParser(); private Config config; private Optional contextEvalTime = Optional.empty(); @@ -207,19 +315,16 @@ protected List preprocessArguments(List arguments, Map 1) { - processMultiContextArguments(); - } + processMultiContextArguments(); + return this.config.unrecognizedArguments; } private void processMultiContextArguments() { List engineArgs = new ArrayList<>(); // The storage for the iteration-specific arguments - List> perIterationArgs = new ArrayList<>(); - // Iteration-specific arguments can be specified for the two first iterations only atm. - perIterationArgs.add(new ArrayList<>()); // iteration 0 args - perIterationArgs.add(new ArrayList<>()); // iteration 1 args + Map> runOptionsMap = new HashMap<>(); + boolean useExperimental = false; Iterator iterator = this.config.unrecognizedArguments.iterator(); while (iterator.hasNext()) { @@ -227,21 +332,16 @@ private void processMultiContextArguments() { // Extract iteration-specific arguments. The pattern of an iteration specific arguments // is: .= - if (option.contains("=")) { - String[] nameValue = option.split("=", 2); - String indexedArgName = nameValue[0]; - if (indexedArgName.length() >= 3) { - String argName = indexedArgName.substring(0, indexedArgName.length() - 2); - String argValue = nameValue[1]; - if (indexedArgName.endsWith(".0")) { - iterator.remove(); - perIterationArgs.get(0).add(argName + "=" + argValue); - continue; - } else if (indexedArgName.endsWith(".1")) { - iterator.remove(); - perIterationArgs.get(1).add(argName + "=" + argValue); - continue; - } + RunOption runOption = RunOption.parse(option); + if (runOption != null) { + if ("--eval-source-only".equals(runOption.name)) { + iterator.remove(); + config.evalSourceOnlyFlagsMap.put(runOption.runIndex, runOption.value == null || Boolean.parseBoolean(runOption.value)); + } else { + iterator.remove(); + List runOptions = runOptionsMap.computeIfAbsent(runOption.runIndex, (i) -> new ArrayList<>()); + runOptions.add(runOption.name + "=" + runOption.value); + continue; } } @@ -250,15 +350,22 @@ private void processMultiContextArguments() { iterator.remove(); engineArgs.add(option); } else if ("--experimental-options".equals(option)) { + useExperimental = true; engineArgs.add(option); - perIterationArgs.get(0).add(option); - perIterationArgs.get(1).add(option); } } - parseUnrecognizedOptions(getLanguageId(config.path), config.multiContextEngineOptions, engineArgs); - parseUnrecognizedOptions(getLanguageId(config.path), config.perIterationContextOptions.get(0), perIterationArgs.get(0)); - parseUnrecognizedOptions(getLanguageId(config.path), config.perIterationContextOptions.get(1), perIterationArgs.get(1)); + // Parse engine options and store them to config.engineOptions + parseUnrecognizedOptions(getLanguageId(config.path), config.engineOptions, engineArgs); + + // Parse run specific options and store them to config.runOptionsMap + for (Map.Entry> runOptionsEntry : runOptionsMap.entrySet()) { + Map runOptions = config.runOptionsMap.computeIfAbsent(runOptionsEntry.getKey(), (i) -> new HashMap<>()); + if (useExperimental) { + runOptionsEntry.getValue().add("--experimental-options"); + } + parseUnrecognizedOptions(getLanguageId(config.path), runOptions, runOptionsEntry.getValue()); + } } @Override @@ -275,49 +382,32 @@ protected void validateArguments(Map polyglotOptions) { @Override protected void launch(Context.Builder contextBuilder) { - contextBuilder.allowAllAccess(true); - - contextBuilder.options(config.multiContextEngineOptions); - if (!config.useDebugCache && config.runCount > 1) { - contextBuilder.engine(Engine.newBuilder().allowExperimentalOptions(true).options(config.multiContextEngineOptions).build()); + String compilationOptionValue; + switch (config.mode) { + case interpreter: + compilationOptionValue = "false"; + break; + case standard: + compilationOptionValue = "true"; + break; + default: + throw new AssertionError("Unknown execution-mode: " + config.mode); } + config.engineOptions.put("engine.Compilation", compilationOptionValue); - if (config.runCount == 0) { - // Create the context and close it right afterwards to trigger the compilation of AOT - // roots - try (Context context = contextBuilder.build()) { - context.eval(Source.newBuilder(getLanguageId(config.path), Paths.get(config.path).toFile()).build()); - return; - } catch (IOException e) { - throw abort(String.format("Error loading file '%s' (%s)", config.path, e.getMessage())); - } + if (config.sharedEngine) { + contextBuilder.engine(Engine.newBuilder().allowExperimentalOptions(true).options(config.engineOptions).build()); + } else { + contextBuilder.options(config.engineOptions); } + contextBuilder.allowAllAccess(true); - for (int i = 0; i < config.runCount; i++) { - Map perIterationOptions = config.perIterationContextOptions.get(i); + for (int i = 0; i < config.numberOfRuns; i++) { + Map perIterationOptions = config.runOptionsMap.get(i); if (perIterationOptions != null) { contextBuilder.options(perIterationOptions); } - if (config.useDebugCache) { - // The debug engine cache facilitation - if (i == 0) { - contextBuilder.option("engine.DebugCacheCompile", "aot").// - option("engine.DebugCacheStore", "true").// - option("engine.MultiTier", "false").// - option("engine.CompileAOTOnCreate", "false"); - try (Context context = contextBuilder.build()) { - context.eval(Source.newBuilder(getLanguageId(config.path), Paths.get(config.path).toFile()).build()); - } catch (IOException e) { - throw abort(String.format("Error loading file '%s' (%s)", config.path, e.getMessage())); - } - } else { - contextBuilder.option("engine.DebugCacheStore", "false").// - option("engine.DebugCacheLoad", "true"); - runHarness(contextBuilder); - } - } else { - runHarness(contextBuilder); - } + runHarness(contextBuilder, config.evalSourceOnlyFlagsMap.getOrDefault(i, config.evalSourceOnly)); } } @@ -348,6 +438,10 @@ static String getExtension(String path) { } String getLanguageId(String path) { + if (path == null) { + return null; + } + final File file = new File(path); if ("jar".equals(getExtension(path))) { return "java"; @@ -410,21 +504,11 @@ static class EvalResult { } } - private void runHarness(Context.Builder contextBuilder) { + private void runHarness(Context.Builder contextBuilder, boolean evalSourceOnly) { log("::: Starting " + config.path + " :::"); log(config.toString()); log(""); - switch (config.mode) { - case interpreter: - contextBuilder.option("engine.Compilation", "false"); - break; - case standard: - contextBuilder.option("engine.Compilation", "true"); - break; - default: - throw new AssertionError("Unknown execution-mode: " + config.mode); - } contextBuilder.options(config.metric.getEngineOptions(config)); Handler handler = config.metric.getLogHandler(); if (handler != null) { @@ -444,11 +528,15 @@ private void runHarness(Context.Builder contextBuilder) { try (Context context = contextBuilder.build()) { log("::: Initializing :::"); + PeakTimeMetric evalSourceMetric = new PeakTimeMetric(); + evalSourceMetric.beforeIteration(false, 0, config); EvalResult evalResult = evalSource(context, config.path); + evalSourceMetric.afterIteration(false, 0, config); - log("language: " + evalResult.languageId); - log("type: " + (evalResult.isBinarySource ? "binary" : "source code")); - log("length: " + evalResult.sourceLength + (evalResult.isBinarySource ? " bytes" : " characters")); + log("language: " + evalResult.languageId); + log("type: " + (evalResult.isBinarySource ? "binary" : "source code")); + log("length: " + evalResult.sourceLength + (evalResult.isBinarySource ? " bytes" : " characters")); + log("evaluation: " + round(evalSourceMetric.reportAfterAll().get()) + " " + evalSourceMetric.unit()); log(""); log("::: Bench specific options :::"); @@ -459,9 +547,18 @@ private void runHarness(Context.Builder contextBuilder) { log("Initialization completed."); log(""); - log("::: Running warmup :::"); - repeatIterations(context, evalResult.languageId, evalResult.sourceName, evalResult.value, true, config.warmupIterations); - log(""); + if (evalSourceOnly) { + log("::: Iterations skipped :::"); + } else { + log("::: Running warmup :::"); + repeatIterations(context, evalResult.languageId, evalResult.sourceName, evalResult.value, true, config.warmupIterations); + log(""); + + log("::: Running :::"); + config.metric.reset(); + repeatIterations(context, evalResult.languageId, evalResult.sourceName, evalResult.value, false, config.iterations); + log(""); + } log("::: Running :::"); config.metric.reset(); From 6501cfabe7fb35d0454aac87937f24ba14f6e6a5 Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Wed, 29 Sep 2021 13:20:08 +0200 Subject: [PATCH 359/681] PR comments addressed --- sulong/mx.sulong/mx_sulong_benchmarks.py | 4 +- .../src/org/graalvm/polybench/Config.java | 47 +++++- .../graalvm/polybench/PolyBenchLauncher.java | 155 +++++++----------- 3 files changed, 100 insertions(+), 106 deletions(-) diff --git a/sulong/mx.sulong/mx_sulong_benchmarks.py b/sulong/mx.sulong/mx_sulong_benchmarks.py index 2e6bb6f9883b..ba0f705ae1d3 100644 --- a/sulong/mx.sulong/mx_sulong_benchmarks.py +++ b/sulong/mx.sulong/mx_sulong_benchmarks.py @@ -622,13 +622,13 @@ def hosting_registry(self): native_polybench_vm_registry = VmRegistry("NativePolybench", known_host_registries=[java_vm_registry]) native_polybench_vm_registry.add_vm(PolybenchVm('debug-aux-engine-cache', - ['--experimental-options', '--eval-source-only.0', + ['--experimental-options', '--eval-source-only.0=true', '--llvm.AOTCacheStore.0=true', '--llvm.AOTCacheLoad.0=false', '--engine.DebugCacheCompile.0=aot', '--engine.DebugCacheStore.0=true', '--llvm.AOTCacheStore.1=false', '--llvm.AOTCacheLoad.1=true', '--engine.DebugCacheStore.1=false', '--engine.DebugCacheLoad.1=true', '--engine.MultiTier=false', '--engine.CompileAOTOnCreate=false', '--engine.DebugCachePreinitializeContext=false', '--engine.DebugTraceCache=true', '--multi-context-runs=2', '-w', '0', '-i', '10']), _suite, 10) native_polybench_vm_registry.add_vm(PolybenchVm('store-aux-engine-cache', - ['--experimental-options', '--multi-context-runs=1', '--eval-source-only', '--engine.CacheStore=' + os.path.join(os.getcwd(), 'test.image'), + ['--experimental-options', '--multi-context-runs=1', '--eval-source-only=true', '--engine.CacheStore=' + os.path.join(os.getcwd(), 'test.image'), '--llvm.AOTCacheStore=true', '--engine.CacheCompile=aot', '--engine.CachePreinitializeContext=false', '--engine.TraceCache=true']), _suite, 10) native_polybench_vm_registry.add_vm(PolybenchVm('load-aux-engine-cache', diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java index df35db7923f8..ce5dfd75355c 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java @@ -27,31 +27,48 @@ import org.graalvm.polyglot.Value; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; class Config { + + public static final String EVAL_SOURCE_ONLY_OPTION = "--eval-source-only"; + String path; String className; int warmupIterations; int iterations; Mode mode; Metric metric; - final Map engineOptions = new HashMap<>(); - boolean evalSourceOnly; - - int numberOfRuns = 1; - boolean sharedEngine; - final Map> runOptionsMap = new HashMap<>(); - final Map evalSourceOnlyFlagsMap = new HashMap<>(); + boolean evalSourceOnlyDefault; - List unrecognizedArguments = new ArrayList<>(); + final List unrecognizedArguments = new ArrayList<>(); private static final int DEFAULT = -1; private static final int DEFAULT_WARMUP = 20; private static final int DEFAULT_ITERATIONS = 30; + /** + * Multi-context runs related configuration. + */ + int numberOfRuns = 1; + boolean sharedEngine; + final Map engineOptions = new HashMap<>(); + final Map> polyglotRunOptionsMap = new HashMap<>(); + final Map> polybenchRunOptionsMap = new HashMap<>(); + + /** + * Polybench options that can be specified per run. + */ + private static final Set POLYBENCH_RUN_OPTIONS = new HashSet<>(); + static { + POLYBENCH_RUN_OPTIONS.add(EVAL_SOURCE_ONLY_OPTION); + } + Config() { this.path = null; this.className = null; @@ -85,7 +102,10 @@ public String toString() { return "execution-mode: " + mode + "\n" + "metric: " + metric.name() + " (" + metric.unit() + ")" + "\n" + "warmup-iterations: " + (warmupIterations == DEFAULT ? "default" : warmupIterations) + "\n" + - "iterations: " + (iterations == DEFAULT ? "default" : iterations); + "iterations: " + (iterations == DEFAULT ? "default" + : iterations + "\n" + + "runs: " + numberOfRuns + "\n" + + "shared engine: " + sharedEngine); } enum Mode { @@ -103,4 +123,13 @@ static Mode parse(String name) throws IllegalArgumentException { } + static boolean isPolybenchRunOption(String optionName) { + return POLYBENCH_RUN_OPTIONS.contains(optionName); + } + + boolean isEvalSourceOnly(int run) { + String evalSourceOptionValue = polybenchRunOptionsMap.getOrDefault(run, Collections.emptyMap()).get(EVAL_SOURCE_ONLY_OPTION); + return evalSourceOptionValue == null ? evalSourceOnlyDefault : Boolean.parseBoolean(evalSourceOptionValue); + } + } diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java index 96691999db79..ee74ff3b8cdb 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java @@ -58,9 +58,9 @@ *
    *
  • --path <script>
  • *
  • --class-name <class>
  • The class name of an Espresso benchmark inside the jar - * specified by path. - *
  • --mode [interpreter | standard]
  • Indicates whether the benchmark will be run in the - * interpreter only or the Graal compiler will be used. + * specified by path (only relevant when executing Java workloads). + *
  • --mode <mode>
  • Specified the mode which the benchmark will be running in. Consult + * the available modes via the help command. *
  • --metric [peak-time | compilation-time | partial-evaluation-time | one-shot | none]
  • *
  • -w <N>
  • The number of warmup iterations *
  • -i <N>
  • The number of hot iterations @@ -76,17 +76,17 @@ * share a single engine. A multi-context benchmarking can be configured using the following * options: *
      - *
    • --multi-context-runs
    • The number of runs - *
    • --shared-engine
    • Indicates whether the contexts will share a single engine + *
    • --multi-context-runs=<N>
    • The number of runs + *
    • --shared-engine=[true | false]
    • Indicates whether the contexts will share a single + * engine. If false, the context of each run will have a separate engine, otherwise all + * contexts will share a single engine. *
    - *

    - * It is possible to specify different arguments for each iteration. The pattern of an iteration - * specific argument is: + *

    + * It is possible to specify different arguments for each run. The pattern of a run specific + * argument is: * *

    - * <arg_name>.<iteration>=<value>
    - * OR
    - * <arg_name>.<iteration>
    + * <arg_name>.<run>=<value>
      * 
    *

    *

    Examples

    @@ -105,13 +105,13 @@ *

    Two runs with 5 warmup and 10 hot iterations each with a shared engine

    * *
    - *     polybench --path bench.so --multi-context-runs=2 --shared-engine -w 5 -i 10
    + *     polybench --path bench.so --multi-context-runs=2 --shared-engine=true -w 5 -i 10
      * 
    * *

    Storing the auxiliary engine cache and skipping the benchmark

    * *
    - *     polybench --path bench.so --eval-source-only --experimental-options --engine.CacheStore=test.image --engine.CacheCompile=aot
    + *     polybench --path bench.so --eval-source-only=true --experimental-options --engine.CacheStore=test.image --engine.CacheCompile=aot
      * 
    * *

    Loading the auxiliary engine cache and running the benchmark

    @@ -124,13 +124,13 @@ * engine cache, while the second run executes the benchmark with the cache. * *
    - *     polybench --path bench.so --multi-context-runs=2 --eval-source-only.0 -w 0 -i 10 --experimental-options --engine.DebugCacheCompile.0=aot --engine.DebugCacheStore.0=true --engine.DebugCacheStore.1=false --engine.DebugCacheLoad.1=true
    + *     polybench --path bench.so --multi-context-runs=2 --eval-source-only.0=true -w 0 -i 10 --experimental-options --engine.DebugCacheCompile.0=aot --engine.DebugCacheStore.0=true --engine.DebugCacheStore.1=false --engine.DebugCacheLoad.1=true
      * 
    * *

    Reporting the source evaluation time only for 10 runs

    * *
    - *     polybench --path bench.so --multi-context-runs=10 --eval-source-only
    + *     polybench --path bench.so --multi-context-runs=10 --eval-source-only=true
      * 
    */ public final class PolyBenchLauncher extends AbstractLanguageLauncher { @@ -138,16 +138,10 @@ public final class PolyBenchLauncher extends AbstractLanguageLauncher { static class ArgumentConsumer { private final String prefix; private final BiConsumer action; - private final boolean isFlag; - /** - * @param isFlag if true, the action is invoked only if the option is present. - * The value is then null. - */ - ArgumentConsumer(String prefix, BiConsumer action, boolean isFlag) { + ArgumentConsumer(String prefix, BiConsumer action) { this.prefix = prefix; this.action = action; - this.isFlag = isFlag; } boolean consume(String argument, Iterator args, Config options) { @@ -162,27 +156,15 @@ boolean consume(String argument, Iterator args, Config options) { if (!argNameValue[0].equals(prefix)) { return false; } - if (isFlag) { - if (!Boolean.parseBoolean(argNameValue[1])) { - return true; - } else { - value = null; - } - } else { - value = argNameValue[1]; - } + value = argNameValue[1]; } else { if (!argument.equals(prefix)) { return false; } - if (isFlag) { - value = null; - } else { - try { - value = args.next(); - } catch (NoSuchElementException e) { - throw new IllegalArgumentException("Premature end of arguments for prefix " + prefix + "."); - } + try { + value = args.next(); + } catch (NoSuchElementException e) { + throw new IllegalArgumentException("Premature end of arguments for prefix " + prefix + "."); } } action.accept(value, options); @@ -199,15 +181,9 @@ static class ArgumentParser { ArgumentParser() { this.consumers = new ArrayList<>(); - this.consumers.add(new ArgumentConsumer("--path", (value, config) -> { - config.path = value; - }, false)); - this.consumers.add(new ArgumentConsumer("--class-name", (value, config) -> { - config.className = value; - }, false)); - this.consumers.add(new ArgumentConsumer("--mode", (value, config) -> { - config.mode = Config.Mode.parse(value); - }, false)); + this.consumers.add(new ArgumentConsumer("--path", (value, config) -> config.path = value)); + this.consumers.add(new ArgumentConsumer("--class-name", (value, config) -> config.className = value)); + this.consumers.add(new ArgumentConsumer("--mode", (value, config) -> config.mode = Config.Mode.parse(value))); this.consumers.add(new ArgumentConsumer("--metric", (value, config) -> { switch (value) { case "peak-time": @@ -230,22 +206,12 @@ static class ArgumentParser { default: throw new IllegalArgumentException("Unknown metric: " + value); } - }, false)); - this.consumers.add(new ArgumentConsumer("-w", (value, config) -> { - config.warmupIterations = Integer.parseInt(value); - }, false)); - this.consumers.add(new ArgumentConsumer("-i", (value, config) -> { - config.iterations = Integer.parseInt(value); - }, false)); - this.consumers.add(new ArgumentConsumer("--shared-engine", (value, config) -> { - config.sharedEngine = true; - }, true)); - this.consumers.add(new ArgumentConsumer("--eval-source-only", (value, config) -> { - config.evalSourceOnly = true; - }, true)); - this.consumers.add(new ArgumentConsumer("--multi-context-runs", (value, config) -> { - config.numberOfRuns = Integer.parseInt(value); - }, false)); + })); + this.consumers.add(new ArgumentConsumer("-w", (value, config) -> config.warmupIterations = Integer.parseInt(value))); + this.consumers.add(new ArgumentConsumer("-i", (value, config) -> config.iterations = Integer.parseInt(value))); + this.consumers.add(new ArgumentConsumer("--shared-engine", (value, config) -> config.sharedEngine = Boolean.parseBoolean(value))); + this.consumers.add(new ArgumentConsumer("--eval-source-only", (value, config) -> config.evalSourceOnlyDefault = Boolean.parseBoolean(value))); + this.consumers.add(new ArgumentConsumer("--multi-context-runs", (value, config) -> config.numberOfRuns = Integer.parseInt(value))); } Config parse(List arguments) { @@ -321,8 +287,8 @@ protected List preprocessArguments(List arguments, Map engineArgs = new ArrayList<>(); - // The storage for the iteration-specific arguments + List engineOptions = new ArrayList<>(); + // The storage for the run-specific options Map> runOptionsMap = new HashMap<>(); boolean useExperimental = false; @@ -330,37 +296,38 @@ private void processMultiContextArguments() { while (iterator.hasNext()) { String option = iterator.next(); - // Extract iteration-specific arguments. The pattern of an iteration specific arguments - // is: .= + // Extract run-specific arguments. The pattern of a run-specific option + // is: .= RunOption runOption = RunOption.parse(option); if (runOption != null) { - if ("--eval-source-only".equals(runOption.name)) { - iterator.remove(); - config.evalSourceOnlyFlagsMap.put(runOption.runIndex, runOption.value == null || Boolean.parseBoolean(runOption.value)); + iterator.remove(); + if (Config.isPolybenchRunOption(runOption.name)) { + // a run-level PolyBench option + Map pbRunOptions = config.polybenchRunOptionsMap.computeIfAbsent(runOption.runIndex, (i) -> new HashMap<>()); + pbRunOptions.put(runOption.name, runOption.value); } else { + // a run-level polyglot option + List runOptionsToParse = runOptionsMap.computeIfAbsent(runOption.runIndex, (i) -> new ArrayList<>()); + runOptionsToParse.add(runOption.name + "=" + runOption.value); + } + } else { + // The engine options must be separated and used later when building a context + if (option.startsWith("--engine.")) { iterator.remove(); - List runOptions = runOptionsMap.computeIfAbsent(runOption.runIndex, (i) -> new ArrayList<>()); - runOptions.add(runOption.name + "=" + runOption.value); - continue; + engineOptions.add(option); + } else if ("--experimental-options".equals(option)) { + useExperimental = true; + engineOptions.add(option); } } - - // The engine options must be separated and used later when building a context - if (option.startsWith("--engine.")) { - iterator.remove(); - engineArgs.add(option); - } else if ("--experimental-options".equals(option)) { - useExperimental = true; - engineArgs.add(option); - } } // Parse engine options and store them to config.engineOptions - parseUnrecognizedOptions(getLanguageId(config.path), config.engineOptions, engineArgs); + parseUnrecognizedOptions(getLanguageId(config.path), config.engineOptions, engineOptions); // Parse run specific options and store them to config.runOptionsMap for (Map.Entry> runOptionsEntry : runOptionsMap.entrySet()) { - Map runOptions = config.runOptionsMap.computeIfAbsent(runOptionsEntry.getKey(), (i) -> new HashMap<>()); + Map runOptions = config.polyglotRunOptionsMap.computeIfAbsent(runOptionsEntry.getKey(), (i) -> new HashMap<>()); if (useExperimental) { runOptionsEntry.getValue().add("--experimental-options"); } @@ -396,18 +363,18 @@ protected void launch(Context.Builder contextBuilder) { config.engineOptions.put("engine.Compilation", compilationOptionValue); if (config.sharedEngine) { - contextBuilder.engine(Engine.newBuilder().allowExperimentalOptions(true).options(config.engineOptions).build()); + contextBuilder.engine(Engine.newBuilder().options(config.engineOptions).build()); } else { contextBuilder.options(config.engineOptions); } contextBuilder.allowAllAccess(true); for (int i = 0; i < config.numberOfRuns; i++) { - Map perIterationOptions = config.runOptionsMap.get(i); - if (perIterationOptions != null) { - contextBuilder.options(perIterationOptions); + Map perRunOptions = config.polyglotRunOptionsMap.get(i); + if (perRunOptions != null) { + contextBuilder.options(perRunOptions); } - runHarness(contextBuilder, config.evalSourceOnlyFlagsMap.getOrDefault(i, config.evalSourceOnly)); + runHarness(contextBuilder, config.isEvalSourceOnly(i), i); } } @@ -463,7 +430,7 @@ private EvalResult evalSource(Context context, String path) { if ("jar".equals(getExtension(path))) { // Espresso cannot eval .jar files, instead we load the JAR's main class. String className = config.className; - Value mainKlass = null; + Value mainKlass; if (className != null) { mainKlass = context.getBindings("java").getMember(className); } else { @@ -504,7 +471,7 @@ static class EvalResult { } } - private void runHarness(Context.Builder contextBuilder, boolean evalSourceOnly) { + private void runHarness(Context.Builder contextBuilder, boolean evalSourceOnly, int run) { log("::: Starting " + config.path + " :::"); log(config.toString()); log(""); @@ -533,6 +500,7 @@ private void runHarness(Context.Builder contextBuilder, boolean evalSourceOnly) EvalResult evalResult = evalSource(context, config.path); evalSourceMetric.afterIteration(false, 0, config); + log("run: " + run); log("language: " + evalResult.languageId); log("type: " + (evalResult.isBinarySource ? "binary" : "source code")); log("length: " + evalResult.sourceLength + (evalResult.isBinarySource ? " bytes" : " characters")); @@ -560,9 +528,6 @@ private void runHarness(Context.Builder contextBuilder, boolean evalSourceOnly) log(""); } - log("::: Running :::"); - config.metric.reset(); - repeatIterations(context, evalResult.languageId, evalResult.sourceName, evalResult.value, false, config.iterations); // this log message is parsed in mx_vm_benchmark.py, if changed adapt parse rule. contextEvalTime.ifPresent(delta -> log("### Truffle Context eval time (ms): " + round(delta))); log(""); From 872ac6bca71ec2bd7060382c4f1d23c0132c8ee2 Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Fri, 8 Oct 2021 13:47:54 +0200 Subject: [PATCH 360/681] A new Sulong Polybench VM for 3 shared/exclusive runs registered --- sulong/mx.sulong/mx_sulong_benchmarks.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sulong/mx.sulong/mx_sulong_benchmarks.py b/sulong/mx.sulong/mx_sulong_benchmarks.py index ba0f705ae1d3..f063ee5777a6 100644 --- a/sulong/mx.sulong/mx_sulong_benchmarks.py +++ b/sulong/mx.sulong/mx_sulong_benchmarks.py @@ -635,3 +635,7 @@ def hosting_registry(self): ['--experimental-options', '--multi-context-runs=1', '--engine.CacheLoad=' + os.path.join(os.getcwd(), 'test.image'), '--llvm.AOTCacheLoad=true', '--engine.CachePreinitializeContext=false', '--engine.TraceCache=true', '-w', '0', '-i', '10']), _suite, 10) +native_polybench_vm_registry.add_vm(PolybenchVm('3-runs-exclusive-engine', + ['--multi-context-runs=3', '--shared-engine=false', '-w', '10', '-i', '10']), _suite, 10) +native_polybench_vm_registry.add_vm(PolybenchVm('3-runs-shared-engine', + ['--multi-context-runs=3', '--shared-engine=true', '-w', '10', '-i', '10']), _suite, 10) From 01560f5d573ed15d4212c85bd9362f034277078d Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Fri, 1 Oct 2021 10:41:25 +0200 Subject: [PATCH 361/681] PolyBench peak metric can also be initialized via a member execution --- .../src/org/graalvm/polybench/PeakTimeMetric.java | 8 +++++--- .../src/org/graalvm/polybench/PolyBenchLauncher.java | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PeakTimeMetric.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PeakTimeMetric.java index 880a5d3526b1..44843a375b94 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PeakTimeMetric.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PeakTimeMetric.java @@ -59,11 +59,13 @@ private enum Unit { @Override public void parseBenchSpecificOptions(Value runner) { if (runner.hasMember("batchSize")) { - batchSize = runner.getMember("batchSize").asInt(); + Value batchSizeMember = runner.getMember("batchSize"); + this.batchSize = batchSizeMember.canExecute() ? batchSizeMember.execute().asInt() : batchSizeMember.asInt(); } if (runner.hasMember("unit")) { - String u = runner.getMember("unit").asString(); - unit = Unit.valueOf(u); + Value unitMember = runner.getMember("unit"); + String u = unitMember.canExecute() ? unitMember.execute().asString() : unitMember.asString(); + this.unit = Unit.valueOf(u); } } diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java index ee74ff3b8cdb..49164d4dbc20 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java @@ -329,6 +329,8 @@ private void processMultiContextArguments() { for (Map.Entry> runOptionsEntry : runOptionsMap.entrySet()) { Map runOptions = config.polyglotRunOptionsMap.computeIfAbsent(runOptionsEntry.getKey(), (i) -> new HashMap<>()); if (useExperimental) { + // the enabled experimental-options flag must be propagated to runOptions to enable parsing of + // run-level experimental options runOptionsEntry.getValue().add("--experimental-options"); } parseUnrecognizedOptions(getLanguageId(config.path), runOptions, runOptionsEntry.getValue()); @@ -363,7 +365,8 @@ protected void launch(Context.Builder contextBuilder) { config.engineOptions.put("engine.Compilation", compilationOptionValue); if (config.sharedEngine) { - contextBuilder.engine(Engine.newBuilder().options(config.engineOptions).build()); + // allowExperimentalOptions must be enabled as engine.Compilation is experimental + contextBuilder.engine(Engine.newBuilder().allowExperimentalOptions(true).options(config.engineOptions).build()); } else { contextBuilder.options(config.engineOptions); } From b11197628d80cf2a6b8c89f7c86efc5780de9350 Mon Sep 17 00:00:00 2001 From: "thomas.garcia" Date: Fri, 8 Oct 2021 15:29:18 +0200 Subject: [PATCH 362/681] Format pass + more documentation --- .../espresso/threads/GuestRunnable.java | 17 +++++++++-- .../espresso/threads/ThreadsAccess.java | 28 +++++++++++-------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/GuestRunnable.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/GuestRunnable.java index 57acf7030f55..cb47044fa949 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/GuestRunnable.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/GuestRunnable.java @@ -29,13 +29,26 @@ import com.oracle.truffle.espresso.runtime.EspressoExitException; import com.oracle.truffle.espresso.runtime.StaticObject; -public final class GuestRunnable implements Runnable { +/** + * The payload of the host thread executing a guest {@linkplain #thread thread}. + * + * When started, the host thread: + *
      + *
    • Attached itself to the context.
    • + *
    • Fetches the guest {@link Thread#run()} methods and executes it.
    • + *
    • If an exception escapes the guest thread, call + * {@code Thread#dispatchUncaughtException(Throwable)}.
    • + *
    • Upon completion, {@link ThreadsAccess#terminate(StaticObject, DirectCallNode) terminates} the + * guest thread.
    • + *
    + */ +final class GuestRunnable implements Runnable { private final EspressoContext context; private final StaticObject thread; private final DirectCallNode exit; private final DirectCallNode dispatchUncaught; - public GuestRunnable(EspressoContext context, StaticObject thread, DirectCallNode exit, DirectCallNode dispatchUncaught) { + GuestRunnable(EspressoContext context, StaticObject thread, DirectCallNode exit, DirectCallNode dispatchUncaught) { this.context = context; this.thread = thread; this.exit = exit; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java index ad36f951cd5c..9dd1a643052e 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java @@ -178,7 +178,7 @@ public void interrupt(StaticObject guest) { } /** - * Implementation of {@code Thread.clearInterruptEvent} (JDK 13+) + * Implementation of {@code Thread.clearInterruptEvent} (JDK 13+). */ public void clearInterruptEvent() { assert !context.getJavaVersion().java13OrEarlier(); @@ -186,7 +186,7 @@ public void clearInterruptEvent() { } /** - * Sets the interrupted field of the given thread to {@code false} + * Sets the interrupted field of the given thread to {@code false}. */ public void clearInterruptStatus(StaticObject guest) { meta.HIDDEN_INTERRUPTED.setBoolean(guest, false, true); @@ -271,14 +271,16 @@ public Thread createJavaThread(StaticObject guest, DirectCallNode exit, DirectCa } /** - * Termination of a threads works as follows: + * Terminates a given thread. + *

    + * The following procedure is applied for termination: *

      *
    • Prevent other threads from {@linkplain #stop(StaticObject, StaticObject)} stopping} the - * given thread
    • - *
    • Invoke guest {@code Thread.exit()}
    • + * given thread. + *
    • Invoke guest {@code Thread.exit()}.
    • *
    • Sets the status of this thread to {@link State#TERMINATED} and notifies other threads - * waiting on this thread's monitor
    • - *
    • Unregisters the thread
    • + * waiting on this thread's monitor. + *
    • Unregisters the thread from the context.
    • *
    */ public void terminate(StaticObject thread) { @@ -431,23 +433,25 @@ void handleStop(Meta meta) { return; case STOP: synchronized (this) { - // synchronize to mqke sure we are still stopped. + // synchronize to make sure we are still stopped. KillStatus s = status; if (s == STOP) { updateKillState(NORMAL); // check if death cause throwable is set, if not throw ThreadDeath StaticObject deathThrowable = throwable; throw deathThrowable != null ? meta.throwException(deathThrowable) : meta.throwException(meta.java_lang_ThreadDeath); - } else if (s != KILL) { - return; + } else if (s == KILL) { + throw new EspressoExitException(meta.getContext().getExitStatus()); } + // Stop status has been + assert s == NORMAL || s == EXITING; + return; } - // fallthrough case KILL: // This thread refuses to stop. Send a host exception. - assert meta.getContext().isClosing(); throw new EspressoExitException(meta.getContext().getExitStatus()); } + throw EspressoError.shouldNotReachHere(); } } From 12d85593d63cb33917d265e3bac519855e3f1fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Thu, 7 Oct 2021 11:41:17 +0200 Subject: [PATCH 363/681] Remove obsolete maven tag from SVM gates --- substratevm/ci_includes/gate.hocon | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/substratevm/ci_includes/gate.hocon b/substratevm/ci_includes/gate.hocon index 9d6b1b86e61b..e5cd60e10be3 100644 --- a/substratevm/ci_includes/gate.hocon +++ b/substratevm/ci_includes/gate.hocon @@ -35,12 +35,11 @@ builds += [ } } environment : { - MAVEN_REPO_LOCAL : "$BUILD_DIR/.m2" PATH : "$MUSL_LIBS/bin:$PATH" } run: [ ["$MUSL_LIBS/fix_paths.sh"] - ${svm-cmd-gate} ["build,helloworld,test,maven,nativeimagehelp,muslcbuild"] + ${svm-cmd-gate} ["build,helloworld,test,nativeimagehelp,muslcbuild"] ] } ${labsjdk-ce-11} ${svm-common-linux-gate} ${linux-deploy} { @@ -53,21 +52,16 @@ builds += [ name: "gate-svm-style-fullbuild" timelimit: "45:00" environment : { - MAVEN_REPO_LOCAL : "$BUILD_DIR/.m2" MX_BUILD_EXPLODED : "true" # test native-image MX_BUILD_EXPLODED compatibility } run: [ - ${svm-cmd-gate} ["style,fullbuild,helloworld,test,svmjunit,maven"] + ${svm-cmd-gate} ["style,fullbuild,helloworld,test,svmjunit"] ] } ${labsjdk-ce-17} ${svm-common-gate} ${svm-common-windows-jdk17} { name: "gate-svm-windows-basics" - environment: { - PATH : "$MVN_HOME;$PATH" # workaround until GR-10735 is resolved - MAVEN_REPO_LOCAL : "$BUILD_DIR\.m2" - } run: [ - ${svm-cmd-gate} ["build,helloworld,test,svmjunit,maven"] + ${svm-cmd-gate} ["build,helloworld,test,svmjunit"] ] } ] From 693d3ed5c3eb6b39b64f2e765a278acf5b9d99c7 Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Fri, 8 Oct 2021 16:10:02 +0100 Subject: [PATCH 364/681] Make methods static that can be static. --- .../oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index 37e23208bd4c..f63ecbbb2c96 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -500,7 +500,7 @@ private void calculateRecursiveData(JSONObject sample) { } } - private void addRecursiveChild(JSONObject sample, JSONObject child) { + private static void addRecursiveChild(JSONObject sample, JSONObject child) { final JSONArray children; if (!sample.has("rs")) { children = new JSONArray(); @@ -514,7 +514,7 @@ private void addRecursiveChild(JSONObject sample, JSONObject child) { child.put("rh", child.getInt("h")); } - private void mergeCounts(JSONObject a, JSONObject b, boolean child) { + private static void mergeCounts(JSONObject a, JSONObject b, boolean child) { int aRI = a.has("ri") ? a.getInt("ri") : a.getInt("i"); int aRC = a.has("rc") ? a.getInt("rc") : a.getInt("c"); int aRH = a.has("rh") ? a.getInt("rh") : a.getInt("h"); From eb90d434234304f6520be0e7d5ac3c36111d73f4 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 30 Sep 2021 14:24:41 +0200 Subject: [PATCH 365/681] fix NPE in FrameStateAssigmentPhaseBenchmark (GR-34009) --- .../microbenchmarks/graal/util/FrameStateAssignmentState.java | 2 +- .../compiler/microbenchmarks/graal/util/GraphState.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/FrameStateAssignmentState.java b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/FrameStateAssignmentState.java index 5848addc694e..b491ed03b64b 100644 --- a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/FrameStateAssignmentState.java +++ b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/FrameStateAssignmentState.java @@ -34,7 +34,7 @@ public class FrameStateAssignmentState extends GraphState { @Override protected StructuredGraph preprocessOriginal(StructuredGraph structuredGraph) { - new GuardLoweringPhase().apply(structuredGraph, null); + new GuardLoweringPhase().apply(structuredGraph, graal.providers); return structuredGraph; } diff --git a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraphState.java b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraphState.java index 158a9ca7ec7b..e6f6cacedd37 100644 --- a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraphState.java +++ b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraphState.java @@ -44,9 +44,11 @@ @State(Scope.Thread) public abstract class GraphState { + final GraalState graal; + @SuppressWarnings("try") public GraphState() { - GraalState graal = new GraalState(); + graal = new GraalState(); DebugContext debug = graal.debug; ResolvedJavaMethod method = graal.metaAccess.lookupJavaMethod(getMethodFromMethodSpec(getClass())); StructuredGraph structuredGraph = null; From f2869f3476c3f9cb9c939df5eb5ba16d78d2f5ee Mon Sep 17 00:00:00 2001 From: Danilo Ansaloni Date: Mon, 4 Oct 2021 14:56:52 +0200 Subject: [PATCH 366/681] Custom GraalVM distributions defined with an explicit component list should respect component dependencies. For example, a custom GraalVM that includes 'GraalVM compiler' should also include 'Truffle', since the former lists the latter among its dependencies. --- sdk/mx.sdk/mx_sdk_vm_impl.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index d17455695618..6757dee23ae8 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -880,13 +880,14 @@ def build(self): class GraalVmLayoutDistribution(BaseGraalVmLayoutDistribution, LayoutSuper): # pylint: disable=R0901 def __init__(self, base_name, theLicense=None, stage1=False, components=None, **kw_args): self.base_name = base_name - name, base_dir, self.vm_config_name = _get_graalvm_configuration(base_name, components=components, stage1=stage1) + components_with_dependencies = [] if components is None else GraalVmLayoutDistribution._add_dependencies(components) + name, base_dir, self.vm_config_name = _get_graalvm_configuration(base_name, components=components_with_dependencies, stage1=stage1) super(GraalVmLayoutDistribution, self).__init__( suite=_suite, name=name, deps=[], - components=components, + components=components_with_dependencies, is_graalvm=True, exclLibs=[], platformDependent=True, @@ -898,6 +899,17 @@ def __init__(self, base_name, theLicense=None, stage1=False, components=None, ** stage1=stage1, **kw_args) + @staticmethod + def _add_dependencies(components): + components_with_repetitions = components[:] + components_with_dependencies = [] + while components_with_repetitions: + component = components_with_repetitions.pop(0) + if component not in components_with_dependencies: + components_with_dependencies.append(component) + components_with_repetitions.extend(component.direct_dependencies()) + return components_with_dependencies + def extra_suite_revisions_data(self): base_jdk_info = _base_jdk_info() if self == get_final_graalvm_distribution() and base_jdk_info: From 3a0a1aec66fcaf427a71371b5c136b7e3c2c6156 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 28 Sep 2021 11:39:17 +0200 Subject: [PATCH 367/681] removed makegraaljdk command --- compiler/mx.compiler/mx_compiler.py | 390 +++++++--------------------- sdk/mx.sdk/mx_sdk_vm_impl.py | 10 +- 2 files changed, 103 insertions(+), 297 deletions(-) diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index e3475a4188d4..e3afae88a698 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -28,7 +28,7 @@ from __future__ import print_function import os -from os.path import join, exists, getmtime, basename, dirname, isdir, islink +from os.path import join, exists, getmtime, basename, dirname, isdir from argparse import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER import re import stat @@ -36,10 +36,7 @@ import tarfile import subprocess import tempfile -import shutil import sys -import hashlib -import io import mx_truffle import mx_sdk_vm @@ -55,7 +52,6 @@ from mx_javamodules import as_java_module from mx_updategraalinopenjdk import updategraalinopenjdk from mx_renamegraalpackages import renamegraalpackages -from mx_sdk_vm import jlink_new_jdk import mx_sdk_vm_impl import mx_benchmark @@ -426,16 +422,6 @@ def compiler_gate_runner(suites, unit_test_runs, bootstrap_tests, tasks, extraVM ] UnitTestRun('XcompUnitTests', [], tags=GraalTags.test).run(['compiler'], tasks, ['-Xcomp', '-XX:-UseJVMCICompiler'] + _remove_empty_entries(extraVMarguments) + xcompTests) - # Ensure makegraaljdk works - with Task('MakeGraalJDK', tasks, tags=GraalTags.test) as t: - if t: - ws = mx.ensure_dir_exists('MakeGraalJDK-ws') - graaljdk = join(ws, 'graaljdk-' + str(jdk.javaCompliance)) - try: - makegraaljdk_cli(['-a', join(ws, 'graaljdk-' + str(jdk.javaCompliance) + '.tar'), '-b', graaljdk]) - finally: - mx.rmtree(ws) - # Run ctw against rt.jar on hosted with Task('CTW:hosted', tasks, tags=GraalTags.ctw) as t: if t: @@ -641,10 +627,16 @@ def _unittest_config_participant(config): # ALL-UNNAMED. mainClassArgs.extend(['-JUnitOpenPackages', 'jdk.internal.vm.ci/*=jdk.internal.vm.compiler,ALL-UNNAMED']) + limited_modules = None + for arg in vmArgs: + if arg.startswith('--limit-modules'): + assert arg.startswith('--limit-modules='), ('--limit-modules must be separated from its value by "="') + limited_modules = arg[len('--limit-modules='):].split(',') + # Export packages in all Graal modules and their dependencies for dist in _graal_config().dists: jmd = as_java_module(dist, jdk) - if _graaljdk_override is None or jmd in _graaljdk_override.get_modules(): + if limited_modules is None or jmd.name in limited_modules: mainClassArgs.extend(['-JUnitOpenPackages', jmd.name + '/*']) vmArgs.append('--add-modules=' + jmd.name) @@ -669,6 +661,7 @@ def _unittest_config_participant(config): # TODO: GR-31197, this should be removed. vmArgs.append('-Dpolyglot.engine.DynamicCompilationThresholds=false') vmArgs.append('-Dpolyglot.engine.AllowExperimentalOptions=true') + return (vmArgs, mainClass, mainClassArgs) mx_unittest.add_config_participant(_unittest_config_participant) @@ -735,6 +728,29 @@ def _parseVmArgs(args, addDefaultArgs=True): if not any(a.startswith('-Dgraal.ObjdumpExecutables=') for a in args): argsPrefix.append('-Dgraal.ObjdumpExecutables=objdump,gobjdump') + # The GraalVM locator must be disabled so that Truffle languages + # are loaded from the class path. This is the configuration expected + # by the unit tests and benchmarks run via the compiler suite. + if not any(a.startswith('-Dgraalvm.locatorDisabled=') for a in args): + argsPrefix.append('-Dgraalvm.locatorDisabled=true') + + # On JDK8 running a GraalJDK requires putting Truffle and all components + # that have boot jars on the boot class path. + if isJDK8: + new_args = [] + bcpa = [] + # Filter out all instances of -Xbootclasspath/a: from args, keeping + # the last, if any. + for a in args: + if a.startswith('-Xbootclasspath/a:'): + bcpa = a[len('-Xbootclasspath/a:'):].split(os.pathsep) + else: + new_args.append(a) + gc = _graal_config() + bcpa = [bj for bj in gc.boot_jars if basename(bj) != 'graal-sdk.jar'] + gc.truffle_jars + bcpa + argsPrefix.append('-Xbootclasspath/a:' + os.pathsep.join(bcpa)) + args = new_args + return argsPrefix + args def _check_bootstrap_config(args): @@ -808,23 +824,46 @@ def __exit__(self, exc_type, exc_value, traceback): finally: os.remove(tmp_file) -_graaljdk_override = None +def _graaljdk_dist(edition=None): + """ + Gets the GraalJDK distribution specified by `edition`. + A GraalJDK is a fixed GraalVM configuration specified by the `cmp_ce_components` field. -def _graaljdk_home(base_name): - graaljdks = [d for d in mx.sorted_dists() if isinstance(d, mx_sdk_vm_impl.GraalVmLayoutDistribution) and d.base_name == base_name] + :param str edition: 'ce', 'ee' or None. If None, then an EE GraalJDK is returned if available otherwise a CE GraalJDK. + """ + candidates = [d for d in mx.sorted_dists() if isinstance(d, mx_sdk_vm_impl.GraalVmLayoutDistribution)] + if edition is None: + graaljdks = [d for d in candidates if d.base_name == 'GraalJDK_EE'] + if graaljdks: + base_name = 'GraalJDK_EE' + else: + graaljdks = [d for d in candidates if d.base_name == 'GraalJDK_CE'] + if graaljdks: + base_name = 'GraalJDK_CE' + else: + mx.abort("Cannot find any GraalJDK images") + else: + assert edition in ('ce', 'ee'), edition + base_name = 'GraalJDK_{}'.format(edition.upper()) + graaljdks = [d for d in candidates if d.base_name == base_name] if not graaljdks: - raise mx.abort("Cannot find GraalJDK images with base name '{}'".format(base_name)) + raise mx.abort("Cannot find GraalJDK image with base name '{}'".format(base_name)) if len(graaljdks) > 1: raise mx.abort("Found multiple GraalJDKs with the same base name '{}'".format(base_name)) - return join(graaljdks[0].output, graaljdks[0].jdk_base) + return graaljdks[0] -def get_graaljdk(): - if _graaljdk_override is None: - graaljdk_dir, _ = _update_graaljdk(jdk) - graaljdk = mx.JDKConfig(graaljdk_dir) - else: - graaljdk = _graaljdk_override - return graaljdk +def _graaljdk_home(edition=None): + """ + Gets the JAVA_HOME directory for the GraalJDK distribution (see _graaljdk_dist above). + """ + graaljdk_dist = _graaljdk_dist(edition) + return join(graaljdk_dist.output, graaljdk_dist.jdk_base) + +def get_graaljdk(edition=None): + graaljdk_dir = _graaljdk_home(edition) + if not exists(graaljdk_dir): + mx.abort('{} does not exist - forgot to run `mx build`?'.format(graaljdk_dir)) + return mx.JDKConfig(graaljdk_dir) def collate_metrics(args): """ @@ -897,9 +936,6 @@ def run_java(args, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=No graaljdk = get_graaljdk() vm_args = _parseVmArgs(args, addDefaultArgs=addDefaultArgs) args = ['-XX:+UnlockExperimentalVMOptions', '-XX:+EnableJVMCI'] + vm_args - add_exports = join(graaljdk.home, '.add_exports') - if exists(add_exports): - args = ['@' + add_exports] + args _check_bootstrap_config(args) cmd = get_vm_prefix() + [graaljdk.java] + ['-server'] + args map_file = join(graaljdk.home, 'proguard.map') @@ -1076,28 +1112,21 @@ def sl(args): def java_base_unittest(args): """tests whether the Graal compiler runs on a JDK with a minimal set of modules""" - global _graaljdk_override - try: - # Remove GRAAL_MANAGEMENT from the module path as it - # depends on the java.management module which is not in - # the limited module set - base_modules = ['java.base', 'java.logging', 'jdk.internal.vm.ci', 'jdk.unsupported', 'jdk.compiler'] - compiler_modules = [as_java_module(d, jdk).name for d in _graal_config().dists if d.name != 'GRAAL_MANAGEMENT'] - root_module_names = base_modules + compiler_modules - graaljdk_dir, _ = _update_graaljdk(jdk, root_module_names=root_module_names) - _graaljdk_override = mx.JDKConfig(graaljdk_dir) - - if mx_gate.Task.verbose: - extra_args = ['--verbose', '--enable-timing'] - else: - extra_args = [] - # the base JDK doesn't include jdwp - if _graaljdk_override.debug_args: - mx.warn('Ignoring Java debugger arguments because base JDK doesn\'t include jdwp') - with mx.DisableJavaDebugging(): - mx_unittest.unittest(['--suite', 'compiler', '--fail-fast'] + extra_args + args) - finally: - _graaljdk_override = None + # Remove GRAAL_MANAGEMENT from the module path as it + # depends on the java.management module which is not in + # the limited module set + base_modules = ['java.base', 'java.logging', 'jdk.internal.vm.ci', 'jdk.unsupported', 'jdk.compiler'] + compiler_modules = [as_java_module(d, jdk).name for d in _graal_config().dists if d.name != 'GRAAL_MANAGEMENT'] + root_module_names = base_modules + compiler_modules + extra_args = ['--limit-modules=' + ','.join(root_module_names)] + + if mx_gate.Task.verbose: + extra_args.extend(['--verbose', '--enable-timing']) + # the base JDK doesn't include jdwp + if get_graaljdk().debug_args: + mx.warn('Ignoring Java debugger arguments because base JDK doesn\'t include jdwp') + with mx.DisableJavaDebugging(): + mx_unittest.unittest(['--suite', 'compiler', '--fail-fast'] + extra_args + args) def javadoc(args): # metadata package was deprecated, exclude it @@ -1149,243 +1178,7 @@ def _zipadd(arc, filename, arcname): def makegraaljdk_cli(args): """make a JDK with Graal as the default top level JIT""" - parser = ArgumentParser(prog='mx makegraaljdk') - parser.add_argument('-f', '--force', action='store_true', help='overwrite existing GraalJDK') - parser.add_argument('-a', '--archive', action='store', help='name of archive to create', metavar='') - parser.add_argument('-b', '--bootstrap', action='store_true', help='execute a bootstrap of the created GraalJDK') - parser.add_argument('-l', '--license', action='store', help='path to the license file', metavar='') - parser.add_argument('-o', '--overlay', action='store_true', help='Only write the Graal files into the destination') - parser.add_argument('dest', help='destination directory for GraalJDK', metavar='') - args = parser.parse_args(args) - - if args.overlay and not isJDK8: - mx.abort('The --overlay option is only supported on JDK 8') - - dst_jdk_dir = os.path.abspath(args.dest) - if exists(dst_jdk_dir): - if args.force: - shutil.rmtree(dst_jdk_dir) - - _, updated = _update_graaljdk(jdk, dst_jdk_dir, export_truffle=False, with_compiler_name_file=True) - dst_jdk = mx.JDKConfig(dst_jdk_dir) - if not updated: - mx.log(dst_jdk_dir + ' is already up to date') - - if args.license: - shutil.copy(args.license, join(dst_jdk_dir, 'LICENSE')) - if args.bootstrap: - map_file = join(dst_jdk_dir, 'proguard.map') - with StdoutUnstripping(args=[], out=None, err=None, mapFiles=[map_file]) as u: - # Just use a set of flags that will work on all JVMCI enabled VMs without trying - # to remove flags that are unnecessary for a specific VM. - mx.run([dst_jdk.java, '-XX:+UnlockExperimentalVMOptions', '-XX:+UseJVMCICompiler', '-XX:+BootstrapJVMCI', '-version'], out=u.out, err=u.err) - if args.archive: - mx.log('Archiving {}'.format(args.archive)) - create_archive(dst_jdk_dir, args.archive, basename(args.dest) + '/') - -def _update_graaljdk(src_jdk, dst_jdk_dir=None, root_module_names=None, export_truffle=True, with_compiler_name_file=False): - """ - Creates or updates a GraalJDK in `dst_jdk_dir` from `src_jdk`. - - :param str dst_jdk_dir: path where GraalJDK is (to be) located. If None, then a path name is - derived based on _graalvm_components and `root_module_names`. - :param list root_module_names: names of modules in the root set for the new JDK image. If None, - the root set is derived from _graalvm_components. - :param bool export_truffle: specifies if Truffle API packages should be visible to the app class loader. - On JDK 8, this causes Truffle to be on the boot class path. On JDK 9+, this results - in a ``.add_exports`` file in `dst_dst_dir` which can be used as an @argfile VM argument. - :param bool with_compiler_name_file: if True, a ``compiler-name`` file is written in the ``jvmci`` directory under - `dst_jdk_dir`. Depending on `src_jdk`, the existence of this file can set the - value of UseJVMCICompiler be true. For example, see - https://github.com/graalvm/graal-jvmci-8/blob/master/src/share/vm/jvmci/jvmci_globals.hpp#L52 - :return: a tuple containing the path where the GraalJDK is located and a boolean denoting whether - the GraalJDK was update/created (True) or was already up to date (False) - - """ - update_reason = None - if dst_jdk_dir is None: - graaljdks_dir = mx.ensure_dir_exists(join(_suite.get_output_root(platformDependent=True), 'graaljdks')) - graalvm_compiler_short_names = [c.short_name for c in mx_sdk_vm.graalvm_components() if isinstance(c, mx_sdk_vm.GraalVmJvmciComponent) and c.graal_compiler] - jdk_suffix = '-'.join(graalvm_compiler_short_names) - if root_module_names: - jdk_suffix += '-' + hashlib.sha1(_encode(','.join(root_module_names))).hexdigest() - if mx.get_opts().strip_jars: - jdk_suffix += '-stripped' - dst_jdk_dir = join(graaljdks_dir, 'jdk{}-{}'.format(src_jdk.javaCompliance, jdk_suffix)) - if dst_jdk_dir == src_jdk.home: - # Avoid overwriting source JDK - dst_jdk_dir += '_new' - else: - if dst_jdk_dir == src_jdk.home: - mx.abort("Cannot overwrite source JDK: {}".format(src_jdk)) - - # When co-developing JVMCI/JDK changes with Graal, the source JDK - # may have changed and we want to pick up these changes. - source_jdk_timestamps_file = dst_jdk_dir + '.source_jdk_timestamps' - timestamps = [] - nl = '\n' - for root, _, filenames in os.walk(jdk.home): - for name in filenames: - ts = mx.TimeStampFile(join(root, name)) - timestamps.append(str(ts)) - timestamps = sorted(timestamps) - jdk_timestamps = jdk.home + nl + nl.join(timestamps) - jdk_timestamps_outdated = False - if exists(source_jdk_timestamps_file): - with open(source_jdk_timestamps_file) as fp: - old_jdk_timestamps = fp.read() - if old_jdk_timestamps != jdk_timestamps: - jdk_timestamps_outdated = True - old_jdk_home = old_jdk_timestamps.split(nl, 1)[0] - if old_jdk_home == jdk.home: - import difflib - old_timestamps = old_jdk_timestamps.split(nl) - diff = difflib.unified_diff(timestamps, old_timestamps, 'new_timestamps.txt', 'old_timestamps.txt') - update_reason = 'source JDK was updated as shown by following time stamps diff:{}{}'.format(nl, nl.join(diff)) - else: - update_reason = 'source JDK was changed from {} to {}'.format(old_jdk_home, jdk.home) - else: - jdk_timestamps_outdated = True - - if jdk_timestamps_outdated: - with mx.SafeFileCreation(source_jdk_timestamps_file) as sfc: - with open(sfc.tmpPath, 'w') as fp: - fp.write(jdk_timestamps) - - jvmci_release_file = mx.TimeStampFile(join(dst_jdk_dir, 'release.jvmci')) - if update_reason is None: - if not exists(dst_jdk_dir): - update_reason = dst_jdk_dir + ' does not exist' - else: - newer = [e for e in _graal_config().jars if jvmci_release_file.isOlderThan(e)] - if newer: - update_reason = '{} is older than {}'.format(jvmci_release_file, mx.TimeStampFile(newer[0])) - - if update_reason is None: - return dst_jdk_dir, False - - with SafeDirectoryUpdater(dst_jdk_dir) as sdu: - tmp_dst_jdk_dir = sdu.directory - mx.log('Updating/creating {} from {} using intermediate directory {} since {}'.format(dst_jdk_dir, src_jdk.home, tmp_dst_jdk_dir, update_reason)) - def _copy_file(src, dst): - mx.log('Copying {} to {}'.format(src, dst)) - if mx.can_symlink(): - if exists(dst) and islink(dst): - os.remove(dst) - os.symlink(src, dst) - else: - shutil.copyfile(src, dst) - - vm_name = 'Server VM Graal' - for d in _graal_config().jvmci_dists: - version = d.suite.version() - s = ':' + d.suite.name - if version: - s += '_' + d.suite.version() - if s not in vm_name: - vm_name = vm_name + s - - if isJDK8: - jre_dir = join(tmp_dst_jdk_dir, 'jre') - shutil.copytree(src_jdk.home, tmp_dst_jdk_dir) - - boot_dir = mx.ensure_dir_exists(join(jre_dir, 'lib', 'boot')) - jvmci_dir = mx.ensure_dir_exists(join(jre_dir, 'lib', 'jvmci')) - - for src_jar in _graal_config().jvmci_jars: - _copy_file(src_jar, join(jvmci_dir, basename(src_jar))) - - boot_jars = _graal_config().boot_jars - if not export_truffle: - truffle_dir = mx.ensure_dir_exists(join(jre_dir, 'lib', 'truffle')) - for src_jar in _graal_config().truffle_jars: - _copy_file(src_jar, join(truffle_dir, basename(src_jar))) - for jvmci_parent_jar in _graal_config().jvmci_parent_jars: - with open(join(jvmci_dir, 'parentClassLoader.classpath'), 'w') as fp: - fp.write(join('..', 'truffle', basename(jvmci_parent_jar))) - else: - boot_jars += _graal_config().jvmci_parent_jars - - for src_jar in boot_jars: - dst_jar = join(boot_dir, basename(src_jar)) - _copy_file(src_jar, dst_jar) - - else: - module_dists = _graal_config().dists - _check_using_latest_jars(module_dists) - vendor_info = {'vendor-version' : vm_name} - # Setting dedup_legal_notices=False avoids due to license files conflicting - # when switching JAVA_HOME from an OpenJDK to an OracleJDK or vice versa between executions. - if mx_sdk_vm_impl._jlink_libraries(): - jlink_new_jdk(jdk, tmp_dst_jdk_dir, module_dists, ignore_dists=[], root_module_names=root_module_names, vendor_info=vendor_info, dedup_legal_notices=False) - if export_truffle: - jmd = as_java_module(_graal_config().dists_dict['truffle:TRUFFLE_API'], jdk) - add_exports = [] - for package in jmd.packages: - if package == 'com.oracle.truffle.api.impl': - # The impl package should remain private - continue - if jmd.get_package_visibility(package, "") == 'concealed': - add_exports.append('--add-exports={}/{}=ALL-UNNAMED'.format(jmd.name, package)) - if add_exports: - with open(join(tmp_dst_jdk_dir, '.add_exports'), 'w') as fp: - fp.write(os.linesep.join(add_exports)) - else: - mx.warn("--no-jlinking flag used. The resulting VM will be HotSpot, not GraalVM") - shutil.copytree(jdk.home, tmp_dst_jdk_dir, symlinks=True) - jre_dir = tmp_dst_jdk_dir - jvmci_dir = mx.ensure_dir_exists(join(jre_dir, 'lib', 'jvmci')) - - if with_compiler_name_file: - with open(join(jvmci_dir, 'compiler-name'), 'w') as fp: - print('graal', file=fp) - - if jdk.javaCompliance < '9' and mx.get_os() not in ['darwin', 'windows']: - # On JDK 8, the server directory containing the JVM library is - # in an architecture specific directory (except for Darwin and Windows). - libjvm_dir = join(jre_dir, 'lib', mx.get_arch(), 'server') - elif mx.get_os() == 'windows': - libjvm_dir = join(jre_dir, 'bin', 'server') - else: - libjvm_dir = join(jre_dir, 'lib', 'server') - mx.ensure_dir_exists(libjvm_dir) - jvmlib = join(libjvm_dir, mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) - - with open(join(tmp_dst_jdk_dir, 'release.jvmci'), 'w') as fp: - for d in _graal_config().jvmci_dists: - s = d.suite - if s.vc: - print('{}={}'.format(d.name, s.vc.parent(s.dir)), file=fp) - for d in _graal_config().boot_dists + _graal_config().truffle_dists: - s = d.suite - if s.vc: - print('{}={}'.format(d.name, s.vc.parent(s.dir)), file=fp) - - assert exists(jvmlib), jvmlib + ' does not exist' - out = mx.LinesOutputCapture() - mx.run([jdk.java, '-version'], err=out) - line = None - pattern = re.compile(r'(.* )(?:Server|Graal) VM .*\((?:.+ )?build.*') - for line in out.lines: - m = pattern.match(line) - if m: - with io.open(join(libjvm_dir, 'vm.properties'), 'w', newline='') as fp: - # Modify VM name in `java -version` to be Graal along - # with a suffix denoting the commit of each Graal jar. - # For example: - # Java HotSpot(TM) 64-Bit Graal:compiler_88847fb25d1a62977a178331a5e78fa5f8fcbb1a (build 25.71-b01-internal-jvmci-0.34, mixed mode) - print(u'name=' + m.group(1) + vm_name, file=fp) - line = True - break - if line is not True: - mx.abort('Could not find "{}" in output of `java -version`:\n{}'.format(pattern.pattern, os.linesep.join(out.lines))) - - unstrip_map = mx.make_unstrip_map(_graal_config().dists) - if unstrip_map: - with open(join(tmp_dst_jdk_dir, 'proguard.map'), 'w') as fp: - fp.write(unstrip_map) - - return dst_jdk_dir, True + mx.abort('The makegraaljdk command is no longer supported. Use the graaljdk-home command instead.') __graal_config = None @@ -1476,11 +1269,19 @@ def mx_register_dynamic_suite_constituents(register_project, register_distributi graal_jdk_dist.maven = {'groupId': 'org.graalvm', 'tag': 'graaljdk'} register_distribution(graal_jdk_dist) + +def _parse_graaljdk_edition(description, args): + parser = ArgumentParser(description=description) + parser.add_argument('--edition', choices=['ce', 'ee'], default=None, help='GraalJDK CE or EE') + return parser.parse_args(args).edition + def print_graaljdk_home(args): - parser = ArgumentParser(description='Print the GraalJDK home directory') - parser.add_argument('--edition', choices=['ce', 'ee'], default='ce', help='GraalJDK CE or EE') - args = parser.parse_args(args) - print(_graaljdk_home('GraalJDK_{}'.format(args.edition.upper()))) + """print the GraalJDK JAVA_HOME directory""" + print(_graaljdk_home(_parse_graaljdk_edition('Print the GraalJDK JAVA_HOME directory', args))) + +def print_graaljdk_config(args): + """print the GraalJDK config""" + mx_sdk_vm_impl.graalvm_show([], _graaljdk_dist(_parse_graaljdk_edition('Print the GraalJDK config', args))) mx.update_commands(_suite, { 'sl' : [sl, '[SL args|@VM options]'], @@ -1494,6 +1295,7 @@ def print_graaljdk_home(args): 'javadoc': [javadoc, ''], 'makegraaljdk': [makegraaljdk_cli, '[options]'], 'graaljdk-home': [print_graaljdk_home, '[options]'], + 'graaljdk-show': [print_graaljdk_config, '[options]'], }) def mx_post_parse_cmd_line(opts): diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index 6757dee23ae8..df2ddbe31130 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -2907,13 +2907,17 @@ def graalvm_enter(args): mx.run(args.cmd, env=env) -def graalvm_show(args): - """print the GraalVM config""" +def graalvm_show(args, graalvm_dist=None): + """print the GraalVM config + + :param graalvm_dist: the GraalVM distribution whose config is printed. If None, then the + GraalVM configured by the current environment variables is printed. + """ parser = ArgumentParser(prog='mx graalvm-show', description='Print the GraalVM config') parser.add_argument('--stage1', action='store_true', help='show the components for stage1') args = parser.parse_args(args) - graalvm_dist = get_stage1_graalvm_distribution() if args.stage1 else get_final_graalvm_distribution() + graalvm_dist = graalvm_dist or (get_stage1_graalvm_distribution() if args.stage1 else get_final_graalvm_distribution()) print("GraalVM distribution: {}".format(graalvm_dist)) print("Version: {}".format(_suite.release_version())) print("Config name: {}".format(graalvm_dist.vm_config_name)) From cfe4bb9ae9ef536d843c569748cc71cca6fc652f Mon Sep 17 00:00:00 2001 From: Danilo Ansaloni Date: Mon, 4 Oct 2021 23:10:58 +0200 Subject: [PATCH 368/681] Check for invalid GraalVM distributions with forced component lists. GraalVmLauncher and GraalVmLibrary depend on the global stage1 or final GraalVM images. --- sdk/mx.sdk/mx_sdk_vm_impl.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index df2ddbe31130..5d2402ce8230 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -881,6 +881,11 @@ class GraalVmLayoutDistribution(BaseGraalVmLayoutDistribution, LayoutSuper): # def __init__(self, base_name, theLicense=None, stage1=False, components=None, **kw_args): self.base_name = base_name components_with_dependencies = [] if components is None else GraalVmLayoutDistribution._add_dependencies(components) + if components is not None: + for c in components: + if c.launcher_configs or c.library_configs: + mx.abort('Cannot define a GraalVM layout distribution with a forced list of components that includes launcher or library configs. ' + 'The corresponding projects refer to the global stage1 and final GraalVM distributions.') name, base_dir, self.vm_config_name = _get_graalvm_configuration(base_name, components=components_with_dependencies, stage1=stage1) super(GraalVmLayoutDistribution, self).__init__( @@ -2909,9 +2914,9 @@ def graalvm_enter(args): def graalvm_show(args, graalvm_dist=None): """print the GraalVM config - + :param graalvm_dist: the GraalVM distribution whose config is printed. If None, then the - GraalVM configured by the current environment variables is printed. + config of the global stage1 or final GraalVM distribution is printed. """ parser = ArgumentParser(prog='mx graalvm-show', description='Print the GraalVM config') parser.add_argument('--stage1', action='store_true', help='show the components for stage1') From 44cdcba35d7d19c07324482a4bb176a01466cc08 Mon Sep 17 00:00:00 2001 From: Danilo Ansaloni Date: Mon, 4 Oct 2021 23:13:31 +0200 Subject: [PATCH 369/681] When forcing a GraalVM dist, graalvm_show() prints information about components from that dist. --- sdk/mx.sdk/mx_sdk_vm_impl.py | 89 +++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index 5d2402ce8230..9d0255e9be22 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -2912,65 +2912,68 @@ def graalvm_enter(args): mx.run(args.cmd, env=env) -def graalvm_show(args, graalvm_dist=None): +def graalvm_show(args, forced_graalvm_dist=None): """print the GraalVM config - :param graalvm_dist: the GraalVM distribution whose config is printed. If None, then the + :param forced_graalvm_dist: the GraalVM distribution whose config is printed. If None, then the config of the global stage1 or final GraalVM distribution is printed. """ parser = ArgumentParser(prog='mx graalvm-show', description='Print the GraalVM config') parser.add_argument('--stage1', action='store_true', help='show the components for stage1') args = parser.parse_args(args) - graalvm_dist = graalvm_dist or (get_stage1_graalvm_distribution() if args.stage1 else get_final_graalvm_distribution()) + graalvm_dist = forced_graalvm_dist or (get_stage1_graalvm_distribution() if args.stage1 else get_final_graalvm_distribution()) print("GraalVM distribution: {}".format(graalvm_dist)) print("Version: {}".format(_suite.release_version())) print("Config name: {}".format(graalvm_dist.vm_config_name)) print("Components:") - for component in registered_graalvm_components(stage1=args.stage1): + for component in graalvm_dist.components: print(" - {} ('{}', /{})".format(component.name, component.short_name, component.dir_name)) - launchers = [p for p in _suite.projects if isinstance(p, GraalVmLauncher) and p.get_containing_graalvm() == graalvm_dist] - if launchers: - print("Launchers:") - for launcher in launchers: - suffix = '' - profile_cnt = len(_image_profile(GraalVmNativeProperties.canonical_image_name(launcher.native_image_config))) - if profile_cnt > 0: - suffix += " ({} pgo profile file{})".format(profile_cnt, 's' if profile_cnt > 1 else '') - print(" - {} ({}){}".format(launcher.native_image_name, "native" if launcher.is_native() else "bash", suffix)) - else: - print("No launcher") - - libraries = [p for p in _suite.projects if isinstance(p, GraalVmLibrary)] - if libraries and not args.stage1: - print("Libraries:") - for library in libraries: - suffix = '' - if library.is_skipped(): - suffix += " (skipped)" - profile_cnt = len(_image_profile(GraalVmNativeProperties.canonical_image_name(library.native_image_config))) - if profile_cnt > 0: - suffix += " ({} pgo profile file{})".format(profile_cnt, 's' if profile_cnt > 1 else '') - print(" - {}{}".format(library.native_image_name, suffix)) - else: - print("No library") + if forced_graalvm_dist is None: + # Custom GraalVM distributions with a forced component list do not yet support launchers and libraries. + # No installable or standalone is derived from them. + launchers = [p for p in _suite.projects if isinstance(p, GraalVmLauncher) and p.get_containing_graalvm() == graalvm_dist] + if launchers: + print("Launchers:") + for launcher in launchers: + suffix = '' + profile_cnt = len(_image_profile(GraalVmNativeProperties.canonical_image_name(launcher.native_image_config))) + if profile_cnt > 0: + suffix += " ({} pgo profile file{})".format(profile_cnt, 's' if profile_cnt > 1 else '') + print(" - {} ({}){}".format(launcher.native_image_name, "native" if launcher.is_native() else "bash", suffix)) + else: + print("No launcher") + + libraries = [p for p in _suite.projects if isinstance(p, GraalVmLibrary)] + if libraries and not args.stage1: + print("Libraries:") + for library in libraries: + suffix = '' + if library.is_skipped(): + suffix += " (skipped)" + profile_cnt = len(_image_profile(GraalVmNativeProperties.canonical_image_name(library.native_image_config))) + if profile_cnt > 0: + suffix += " ({} pgo profile file{})".format(profile_cnt, 's' if profile_cnt > 1 else '') + print(" - {}{}".format(library.native_image_name, suffix)) + else: + print("No library") - installables = _get_dists(GraalVmInstallableComponent) - if installables and not args.stage1: - print("Installables:") - for i in installables: - print(" - {}".format(i)) - else: - print("No installable") + installables = _get_dists(GraalVmInstallableComponent) + if installables and not args.stage1: + print("Installables:") + for i in installables: + print(" - {}".format(i)) + else: + print("No installable") - standalones = _get_dists(GraalVmStandaloneComponent) - if standalones and not args.stage1: - print("Standalones:") - for s in standalones: - print(" - {}".format(s)) - else: - print("No standalone") + standalones = _get_dists(GraalVmStandaloneComponent) + if standalones and not args.stage1: + print("Standalones:") + for s in standalones: + print(" - {}".format(s)) + else: + print("No standalone") def _get_dists(dist_class): From fbe4ac585385f3de99f9fcd06c79a1a3b265b4bb Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Fri, 8 Oct 2021 18:17:24 +0200 Subject: [PATCH 370/681] fixed pylint warnings --- java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py index 15772f9af0ed..4a68c7e4b5bb 100644 --- a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py +++ b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py @@ -815,9 +815,6 @@ def name(self): else: return "dacapo-{}".format(self.workloadSize()) - def version(self): - return super(DaCapoBenchmarkSuite, self).version() - def defaultSuiteVersion(self): return "9.12-MR1-bach" @@ -1313,7 +1310,7 @@ def runArgs(self, bmSuiteArgs): # Skips initial check benchmark which tests for javac.jar on classpath. runArgs += ["-pja", "-Dspecjvm.run.initial.check=false"] return runArgs - + def vmArgs(self, bmSuiteArgs): vmArgs = super(SpecJvm2008BenchmarkSuite, self).vmArgs(bmSuiteArgs) if java_home_jdk().javaCompliance >= '16' and \ @@ -1866,9 +1863,6 @@ def renaissanceIterations(self): del benchmarks["neo4j-analytics"] return benchmarks - def version(self): - return super(RenaissanceBenchmarkSuite, self).version() - def defaultSuiteVersion(self): # return self.availableSuiteVersions()[-1] return "0.11.0" # stick to 0.11.0 for both JIT and AOT until Native Image is compatible with 0.13.0 (GR-34147) From 95f1f7303b9dbccb425cf72111ff8e32cbadbe86 Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Sat, 9 Oct 2021 05:50:23 +0000 Subject: [PATCH 371/681] [GR-23997] Periodic update of the graal import (2021-10-08). PullRequest: js/2188 --- vm/mx.vm/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 8c4e334b0a6e..f3f69d035de7 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -39,7 +39,7 @@ "name": "graal-nodejs", "subdir": True, "dynamic": True, - "version": "082c333db671f03aba82d15e6d572e196b3878ea", + "version": "5261f7865f77e399ad1b49bfa5de9b784e740e8a", "urls" : [ {"url" : "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, @@ -49,7 +49,7 @@ "name": "graal-js", "subdir": True, "dynamic": True, - "version": "082c333db671f03aba82d15e6d572e196b3878ea", + "version": "5261f7865f77e399ad1b49bfa5de9b784e740e8a", "urls": [ {"url": "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, From 01f82d345f1bf42b77b212533cea40502276ff04 Mon Sep 17 00:00:00 2001 From: "cengfeng.lzy" Date: Fri, 10 Sep 2021 10:32:28 +0800 Subject: [PATCH 372/681] Refactor iterative analysis code to common method Extract the iteratively analyzing code from NativeImageGenerator to PointsToAnalysis so it can be used by both native image generation and standalone pointsto analysis. --- .../com/oracle/graal/pointsto/BigBang.java | 4 ++ .../graal/pointsto/PointsToAnalysis.java | 58 +++++++++++++++++++ .../svm/hosted/NativeImageGenerator.java | 54 ++++------------- 3 files changed, 72 insertions(+), 44 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 4d34825d0c7e..b17b5d7707ea 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 @@ -26,6 +26,7 @@ import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.util.Timer; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -36,6 +37,7 @@ 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 @@ -92,4 +94,6 @@ public interface BigBang extends ReachabilityAnalysis, HeapScanning { Runnable getHeartbeatCallback(); boolean extendedAsserts(); + + void runAnalysis(DebugContext debug, Function duringAnalysisAction) throws InterruptedException; } 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 d73228a53fc1..78c3cc170897 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 @@ -43,7 +43,9 @@ import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLongArray; +import java.util.function.Function; +import com.oracle.graal.pointsto.util.AnalysisError; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; @@ -703,6 +705,62 @@ public HostVM getHostVM() { return hostVM; } + /** + * Iterate until analysis reaches a fixpoint. + * + * + * @param debugContext debug context + * @param duringAnalysisAction The action handler taken during analysis, return true if no more iteration is required. + * It could be the {@link org.graalvm.nativeimage.hosted.Feature#duringAnalysis} + * for Native Image generation, but also can be other similar actions for standalone pointsto + * analysis that does not dependent on {@link com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl} + * and {@link com.oracle.svm.hosted.NativeImageGenerator.AnalysisFeatureHandler}. + * + * @return The error message during the analysis. If the analysis ends successfully, an empty String is returned, otherwise + * the actual error message is returned. + * @throws InterruptedException + */ + @SuppressWarnings("try") + @Override + public void runAnalysis(DebugContext debugContext, Function duringAnalysisAction) throws InterruptedException { + 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). + */ + 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 (StopTimer t2 = getProcessFeaturesTimer().start()) { + int numTypes = universe.getTypes().size(); + int numMethods = universe.getMethods().size(); + int numFields = universe.getFields().size(); + if (duringAnalysisAction.apply(universe)) { + if (numTypes != universe.getTypes().size() || numMethods != universe.getMethods().size() || numFields != universe.getFields().size()) { + AnalysisError.shouldNotReachHere("When a feature makes more types, methods, or fields reachable, it must require another analysis iteration via DuringAnalysisAccess.requireAnalysisIteration()"); + } + return; + } + } + } + } + } + @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); 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 b01843f59fa6..130b39dc9b34 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 @@ -59,6 +59,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +import com.oracle.graal.pointsto.util.AnalysisError; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Pair; import org.graalvm.compiler.api.replacements.Fold; @@ -693,51 +694,16 @@ private boolean runPointsToAnalysis(String imageName, OptionValues options, Debu } try (StopTimer t = bb.getAnalysisTimer().start()) { - - /* - * Iterate until analysis reaches a fixpoint. - */ DuringAnalysisAccessImpl config = new DuringAnalysisAccessImpl(featureHandler, loader, bb, nativeLibraries, debug); - int numIterations = 0; - while (true) { - try (Indent indent2 = debug.logAndIndent("new analysis iteration")) { - /* - * Do the analysis (which itself is done in a similar iterative process) - */ - boolean analysisChanged = bb.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 UserError.abort("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 (StopTimer t2 = bb.getProcessFeaturesTimer().start()) { - int numTypes = aUniverse.getTypes().size(); - int numMethods = aUniverse.getMethods().size(); - int numFields = aUniverse.getFields().size(); - - bb.getHostVM().notifyClassReachabilityListener(aUniverse, config); - featureHandler.forEachFeature(feature -> feature.duringAnalysis(config)); - - if (!config.getAndResetRequireAnalysisIteration()) { - if (numTypes != aUniverse.getTypes().size() || numMethods != aUniverse.getMethods().size() || numFields != aUniverse.getFields().size()) { - throw UserError.abort( - "When a feature makes more types, methods, or fields reachable, it must require another analysis iteration via DuringAnalysisAccess.requireAnalysisIteration()"); - } - break; - } - } - } + try { + bb.runAnalysis(debug, + (aUniverse) -> { + bb.getHostVM().notifyClassReachabilityListener(aUniverse, config); + featureHandler.forEachFeature(feature -> feature.duringAnalysis(config)); + return !config.getAndResetRequireAnalysisIteration(); + }); + } catch (AnalysisError e) { + throw UserError.abort(e, "Analysis step failed. Reason: %s.", e.getMessage()); } assert verifyAssignableTypes(imageName); From fc4b193a6347f86483d40ed7c99da293823564d6 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Thu, 7 Oct 2021 18:21:47 +0200 Subject: [PATCH 373/681] Do not collect data if sampler is not collecting. --- .../src/com/oracle/truffle/tools/profiler/CPUSampler.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java index a69bbe8742bf..3b415774ee79 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java @@ -797,6 +797,9 @@ public void run() { continue; } synchronized (CPUSampler.this) { + if (!collecting) { + return; + } final MutableSamplerData mutableSamplerData = activeContexts.get(result.context); for (StackSample sample : result.samples) { mutableSamplerData.biasStatistic.accept(sample.biasNs); From be7b76df267e5d61cfc17e56bf037e003cac42ec Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Fri, 1 Oct 2021 09:56:44 +0200 Subject: [PATCH 374/681] Try to separate single- and multi-engine code paths. --- .../src/org/graalvm/polybench/Config.java | 76 ++++++++++++++----- .../graalvm/polybench/PolyBenchLauncher.java | 56 +++++++------- 2 files changed, 84 insertions(+), 48 deletions(-) diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java index ce5dfd75355c..5e83971f2a50 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/Config.java @@ -24,8 +24,6 @@ */ package org.graalvm.polybench; -import org.graalvm.polyglot.Value; - import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -34,6 +32,8 @@ import java.util.Map; import java.util.Set; +import org.graalvm.polyglot.Value; + class Config { public static final String EVAL_SOURCE_ONLY_OPTION = "--eval-source-only"; @@ -55,11 +55,16 @@ class Config { /** * Multi-context runs related configuration. */ - int numberOfRuns = 1; - boolean sharedEngine; - final Map engineOptions = new HashMap<>(); - final Map> polyglotRunOptionsMap = new HashMap<>(); - final Map> polybenchRunOptionsMap = new HashMap<>(); + MultiEngineConfig multiEngine; + + Config() { + this.path = null; + this.className = null; + this.warmupIterations = DEFAULT; + this.iterations = DEFAULT; + this.mode = Mode.standard; + this.metric = new PeakTimeMetric(); + } /** * Polybench options that can be specified per run. @@ -69,13 +74,11 @@ class Config { POLYBENCH_RUN_OPTIONS.add(EVAL_SOURCE_ONLY_OPTION); } - Config() { - this.path = null; - this.className = null; - this.warmupIterations = DEFAULT; - this.iterations = DEFAULT; - this.mode = Mode.standard; - this.metric = new PeakTimeMetric(); + public MultiEngineConfig initMultiEngine() { + if (multiEngine == null) { + multiEngine = new MultiEngineConfig(); + } + return multiEngine; } public void parseBenchSpecificDefaults(Value benchmark) { @@ -99,13 +102,34 @@ public void parseBenchSpecificDefaults(Value benchmark) { @Override public String toString() { - return "execution-mode: " + mode + "\n" + + String config = "execution-mode: " + mode + "\n" + "metric: " + metric.name() + " (" + metric.unit() + ")" + "\n" + "warmup-iterations: " + (warmupIterations == DEFAULT ? "default" : warmupIterations) + "\n" + - "iterations: " + (iterations == DEFAULT ? "default" - : iterations + "\n" + - "runs: " + numberOfRuns + "\n" + - "shared engine: " + sharedEngine); + "iterations: " + (iterations == DEFAULT ? "default" : iterations + "\n"); + if (multiEngine != null) { + config += "runs: " + multiEngine.numberOfRuns + "\n" + + "shared engine: " + multiEngine.sharedEngine; + } + return config; + } + + boolean isSingleEngine() { + return multiEngine == null; + } + + String compilation() { + String compilationOptionValue; + switch (mode) { + case interpreter: + compilationOptionValue = "false"; + break; + case standard: + compilationOptionValue = "true"; + break; + default: + throw new AssertionError("Unknown execution-mode: " + mode); + } + return compilationOptionValue; } enum Mode { @@ -128,8 +152,20 @@ static boolean isPolybenchRunOption(String optionName) { } boolean isEvalSourceOnly(int run) { - String evalSourceOptionValue = polybenchRunOptionsMap.getOrDefault(run, Collections.emptyMap()).get(EVAL_SOURCE_ONLY_OPTION); + if (multiEngine == null) { + return evalSourceOnlyDefault; + } + String evalSourceOptionValue = multiEngine.polybenchRunOptionsMap.getOrDefault(run, Collections.emptyMap()).get(EVAL_SOURCE_ONLY_OPTION); return evalSourceOptionValue == null ? evalSourceOnlyDefault : Boolean.parseBoolean(evalSourceOptionValue); } + static final class MultiEngineConfig { + final Map engineOptions = new HashMap<>(); + final Map> polyglotRunOptionsMap = new HashMap<>(); + final Map> polybenchRunOptionsMap = new HashMap<>(); + int numberOfRuns = 1; + boolean sharedEngine; + + } + } diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java index 49164d4dbc20..f5d2c737b690 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java @@ -209,9 +209,9 @@ static class ArgumentParser { })); this.consumers.add(new ArgumentConsumer("-w", (value, config) -> config.warmupIterations = Integer.parseInt(value))); this.consumers.add(new ArgumentConsumer("-i", (value, config) -> config.iterations = Integer.parseInt(value))); - this.consumers.add(new ArgumentConsumer("--shared-engine", (value, config) -> config.sharedEngine = Boolean.parseBoolean(value))); + this.consumers.add(new ArgumentConsumer("--shared-engine", (value, config) -> config.initMultiEngine().sharedEngine = Boolean.parseBoolean(value))); this.consumers.add(new ArgumentConsumer("--eval-source-only", (value, config) -> config.evalSourceOnlyDefault = Boolean.parseBoolean(value))); - this.consumers.add(new ArgumentConsumer("--multi-context-runs", (value, config) -> config.numberOfRuns = Integer.parseInt(value))); + this.consumers.add(new ArgumentConsumer("--multi-context-runs", (value, config) -> config.initMultiEngine().numberOfRuns = Integer.parseInt(value))); } Config parse(List arguments) { @@ -303,7 +303,7 @@ private void processMultiContextArguments() { iterator.remove(); if (Config.isPolybenchRunOption(runOption.name)) { // a run-level PolyBench option - Map pbRunOptions = config.polybenchRunOptionsMap.computeIfAbsent(runOption.runIndex, (i) -> new HashMap<>()); + Map pbRunOptions = config.initMultiEngine().polybenchRunOptionsMap.computeIfAbsent(runOption.runIndex, (i) -> new HashMap<>()); pbRunOptions.put(runOption.name, runOption.value); } else { // a run-level polyglot option @@ -323,17 +323,20 @@ private void processMultiContextArguments() { } // Parse engine options and store them to config.engineOptions - parseUnrecognizedOptions(getLanguageId(config.path), config.engineOptions, engineOptions); - + HashMap polyglotOptions = new HashMap<>(); + parseUnrecognizedOptions(getLanguageId(config.path), polyglotOptions, engineOptions); + if (!polyglotOptions.isEmpty()) { + config.initMultiEngine().engineOptions.putAll(polyglotOptions); + } // Parse run specific options and store them to config.runOptionsMap for (Map.Entry> runOptionsEntry : runOptionsMap.entrySet()) { - Map runOptions = config.polyglotRunOptionsMap.computeIfAbsent(runOptionsEntry.getKey(), (i) -> new HashMap<>()); - if (useExperimental) { - // the enabled experimental-options flag must be propagated to runOptions to enable parsing of - // run-level experimental options - runOptionsEntry.getValue().add("--experimental-options"); + if (!runOptionsEntry.getValue().isEmpty()) { + Map runOptions = config.initMultiEngine().polyglotRunOptionsMap.computeIfAbsent(runOptionsEntry.getKey(), (i) -> new HashMap<>()); + if (useExperimental) { + runOptionsEntry.getValue().add("--experimental-options"); + } + parseUnrecognizedOptions(getLanguageId(config.path), runOptions, runOptionsEntry.getValue()); } - parseUnrecognizedOptions(getLanguageId(config.path), runOptions, runOptionsEntry.getValue()); } } @@ -351,29 +354,26 @@ protected void validateArguments(Map polyglotOptions) { @Override protected void launch(Context.Builder contextBuilder) { - String compilationOptionValue; - switch (config.mode) { - case interpreter: - compilationOptionValue = "false"; - break; - case standard: - compilationOptionValue = "true"; - break; - default: - throw new AssertionError("Unknown execution-mode: " + config.mode); + if (config.isSingleEngine()) { + contextBuilder.option("engine.Compilation", config.compilation()); + runHarness(contextBuilder, config.evalSourceOnlyDefault, 0); + } else { + multiEngineLaunch(contextBuilder); } - config.engineOptions.put("engine.Compilation", compilationOptionValue); + } + + private void multiEngineLaunch(Context.Builder contextBuilder) { + config.multiEngine.engineOptions.put("engine.Compilation", config.compilation()); - if (config.sharedEngine) { - // allowExperimentalOptions must be enabled as engine.Compilation is experimental - contextBuilder.engine(Engine.newBuilder().allowExperimentalOptions(true).options(config.engineOptions).build()); + if (config.multiEngine.sharedEngine) { + contextBuilder.engine(Engine.newBuilder().allowExperimentalOptions(true).options(config.multiEngine.engineOptions).build()); } else { - contextBuilder.options(config.engineOptions); + contextBuilder.options(config.multiEngine.engineOptions); } contextBuilder.allowAllAccess(true); - for (int i = 0; i < config.numberOfRuns; i++) { - Map perRunOptions = config.polyglotRunOptionsMap.get(i); + for (int i = 0; i < config.multiEngine.numberOfRuns; i++) { + Map perRunOptions = config.multiEngine.polyglotRunOptionsMap.get(i); if (perRunOptions != null) { contextBuilder.options(perRunOptions); } From ed4dc1961401c71b8b7b3e8c6b6aae6071b7e733 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 11 Oct 2021 11:42:05 +0200 Subject: [PATCH 375/681] Allow Node.getCost() to be overridden. Fixes #1385 --- .../truffle/api/dsl/test/NodeCostTest.java | 26 ++++++++++++++++++- .../generator/FlatNodeGenFactory.java | 9 +++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java index 5cec950f2986..5d75415498d2 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -48,6 +48,7 @@ import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostViaMethodOverrideNodeFactory; import com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostWithNodeInfoNodeFactory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; @@ -88,6 +89,29 @@ Object cost(Object left) { } + @Test + public void testNodeCostViaMethodOverride() { + TestRootNode node = TestHelper.createRoot(CostViaMethodOverrideNodeFactory.getInstance()); + assertEquals(NodeCost.NONE, node.getNode().getCost()); + assertEquals(21, executeWith(node, 21)); + assertEquals(NodeCost.NONE, node.getNode().getCost()); + } + + @NodeChild + abstract static class CostViaMethodOverrideNode extends ValueNode { + + @Specialization + int costInt(int left) { + return left; + } + + @Override + public final NodeCost getCost() { + return NodeCost.NONE; + } + + } + @Test public void testNodeCostWithNodeInfo() { TestRootNode node = TestHelper.createRoot(CostWithNodeInfoNodeFactory.getInstance()); diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java index 1dcd40c130b7..9496f8ac5b6f 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java @@ -640,7 +640,7 @@ public CodeTypeElement create(CodeTypeElement clazz) { } catch (UnsupportedOperationException e) { } String cost = nodeInfo != null ? ElementUtils.getAnnotationValue(VariableElement.class, nodeInfo, "cost").getSimpleName().toString() : null; - if (cost == null || cost.equals("MONOMORPHIC") /* the default */) { + if ((cost == null || cost.equals("MONOMORPHIC") /* the default */) && isUndeclaredOrOverrideable(clazz, "getCost")) { if (primaryNode) { clazz.add(createGetCostMethod(false)); } @@ -712,7 +712,7 @@ public CodeTypeElement create(CodeTypeElement clazz) { wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type))); } - if (cost == null || cost.equals("MONOMORPHIC") /* the default */) { + if ((cost == null || cost.equals("MONOMORPHIC") /* the default */) && isUndeclaredOrOverrideable(uncached, "getCost")) { uncached.add(createGetCostMethod(true)); } CodeExecutableElement isAdoptable = CodeExecutableElement.cloneNoAnnotations(ElementUtils.findExecutableElement(types.Node, "isAdoptable")); @@ -2915,6 +2915,11 @@ private Element createGetCostMethod(boolean uncached) { } + private static boolean isUndeclaredOrOverrideable(TypeElement sourceType, String methodName) { + List elements = ElementUtils.getDeclaredMethodsInSuperTypes(sourceType, methodName); + return elements.isEmpty() || !elements.iterator().next().getModifiers().contains(Modifier.FINAL); + } + private ExecutableElement createAccessChildMethod(NodeChildData child, boolean uncached) { if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { ExecutableElement getter = (ExecutableElement) child.getAccessElement(); From da748b7feb299b780489bb1516863fc1ee5b301c Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Mon, 11 Oct 2021 10:07:37 +0000 Subject: [PATCH 376/681] [GR-34408] Export object of inspector module should be usable with WeakMap. PullRequest: js/2189 --- vm/mx.vm/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index f3f69d035de7..76101ae7684a 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -39,7 +39,7 @@ "name": "graal-nodejs", "subdir": True, "dynamic": True, - "version": "5261f7865f77e399ad1b49bfa5de9b784e740e8a", + "version": "43f5bc397a09a45f6f6c34ed5b283e58eca1e7ae", "urls" : [ {"url" : "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, @@ -49,7 +49,7 @@ "name": "graal-js", "subdir": True, "dynamic": True, - "version": "5261f7865f77e399ad1b49bfa5de9b784e740e8a", + "version": "43f5bc397a09a45f6f6c34ed5b283e58eca1e7ae", "urls": [ {"url": "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, From 326e19a0c35c766b4c25701d14da779df5ba1917 Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Fri, 8 Oct 2021 13:47:54 +0200 Subject: [PATCH 377/681] A new Sulong Polybench VM for 3 shared/exclusive runs registered --- sulong/mx.sulong/mx_sulong_benchmarks.py | 4 +++ vm/ci_includes/vm-bench-sulong.hocon | 33 +++++++++++++++++++----- vm/mx.vm/mx_vm.py | 1 + vm/mx.vm/polybench-sulong-ce | 3 +++ 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 vm/mx.vm/polybench-sulong-ce diff --git a/sulong/mx.sulong/mx_sulong_benchmarks.py b/sulong/mx.sulong/mx_sulong_benchmarks.py index ba0f705ae1d3..f063ee5777a6 100644 --- a/sulong/mx.sulong/mx_sulong_benchmarks.py +++ b/sulong/mx.sulong/mx_sulong_benchmarks.py @@ -635,3 +635,7 @@ def hosting_registry(self): ['--experimental-options', '--multi-context-runs=1', '--engine.CacheLoad=' + os.path.join(os.getcwd(), 'test.image'), '--llvm.AOTCacheLoad=true', '--engine.CachePreinitializeContext=false', '--engine.TraceCache=true', '-w', '0', '-i', '10']), _suite, 10) +native_polybench_vm_registry.add_vm(PolybenchVm('3-runs-exclusive-engine', + ['--multi-context-runs=3', '--shared-engine=false', '-w', '10', '-i', '10']), _suite, 10) +native_polybench_vm_registry.add_vm(PolybenchVm('3-runs-shared-engine', + ['--multi-context-runs=3', '--shared-engine=true', '-w', '10', '-i', '10']), _suite, 10) diff --git a/vm/ci_includes/vm-bench-sulong.hocon b/vm/ci_includes/vm-bench-sulong.hocon index 2ca28b508aff..4a9c1be0e4ff 100644 --- a/vm/ci_includes/vm-bench-sulong.hocon +++ b/vm/ci_includes/vm-bench-sulong.hocon @@ -89,19 +89,38 @@ csuite-stockfish { } } -bench-llvm-sulong-graalvm-ce-llimul: ${bench_vm_ce_linux_base} ${bench-llvm-sulong-common} ${sulong-weekly-notifications} { + +bench-llvm-sulong-3-runs-shared-engine-ce: ${bench_vm_ce_linux_base} ${bench-llvm-sulong-common} ${sulong-weekly-notifications} { + targets: [gate], + timelimit: "45:00" environment: { - VM_DIST: ce-llimul + VM_DIST: polybench-sulong-ce } setup: ${bench_vm_ce_linux_base.setup} [ [git, clone, --depth, "1", ${repoBase}"${BENCH_REPO_NAME}.git", "../../${BENCH_REPO_NAME}"] ] run: [ - [mx, --dynamicimport, sulong-benchmarks, --env, ce-llimul, benchmark, --results-file, ${bench_vm_ce_linux_base.resultFile}, "csuite:*", --, --native-vm, sulong-multi, --native-vm-config, default, --jvm, graalvm-ce, --jvm-config, "${JVM_CONFIG}", "--multi-context-runs=3"] + [mx, --dynamicimport, sulong-benchmarks, --env, "${VM_DIST}", benchmark, --results-file, ${bench_vm_ce_linux_base.resultFile}, "csuite-polybench:deltablue", --, --nativepolybench-vm, sulong-polybench, --nativepolybench-vm-config, 3-runs-shared-engine, --jvm, graalvm-ce, --jvm-config, "${JVM_CONFIG}"] + ] + teardown: [ + [cat, ${bench_vm_ce_linux_base.resultFile}] + [bench-uploader.py, ${bench_vm_ce_linux_base.resultFile}] ] - timelimit: "10:00:01" } +#bench-llvm-sulong-graalvm-ce-llimul: ${bench_vm_ce_linux_base} ${bench-llvm-sulong-common} ${sulong-weekly-notifications} { +# environment: { +# VM_DIST: ce-llimul +# } +# setup: ${bench_vm_ce_linux_base.setup} [ +# [git, clone, --depth, "1", ${repoBase}"${BENCH_REPO_NAME}.git", "../../${BENCH_REPO_NAME}"] +# ] +# run: [ +# [mx, --dynamicimport, sulong-benchmarks, --env, ce-llimul, benchmark, --results-file, ${bench_vm_ce_linux_base.resultFile}, "csuite:*", --, --native-vm, sulong-multi, --native-vm-config, default, --jvm, graalvm-ce, --jvm-config, "${JVM_CONFIG}", "--multi-context-runs=3"] +# ] +# timelimit: "10:00:01" +#} + bench-llvm-native: ${bench-llvm-common} ${bench-llvm-linux} ${sulong-weekly-notifications} { targets: [weekly, bench] run: [ @@ -116,8 +135,10 @@ builds += [ ${bench-llvm-sulong-graalvm-ce} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-native-csuite", environment: { JVM_CONFIG: native } } ${bench-llvm-sulong-graalvm-ce} ${csuite-stockfish} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-jvm-3-compiler-threads-csuite-stockfish", environment: { JVM_CONFIG: jvm-3-compiler-threads } } ${bench-llvm-sulong-graalvm-ce} ${csuite-stockfish} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-native-3-compiler-threads-csuite-stockfish", environment: { JVM_CONFIG: native-3-compiler-threads } } - ${bench-llvm-sulong-graalvm-ce-llimul} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-llimul-jvm-csuite", environment: { JVM_CONFIG: jvm } } - ${bench-llvm-sulong-graalvm-ce-llimul} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-llimul-native-csuite", environment: { JVM_CONFIG: native } } + #${bench-llvm-sulong-graalvm-ce-llimul} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-llimul-jvm-csuite", environment: { JVM_CONFIG: jvm } } + #${bench-llvm-sulong-graalvm-ce-llimul} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-llimul-native-csuite", environment: { JVM_CONFIG: native } } + ${bench-llvm-sulong-3-runs-shared-engine-ce} {targets: [daily, bench], name: "daily-bench-sulong-3-runs-shared-engine-ce-jvm", environment: { JVM_CONFIG: jvm } } + ${bench-llvm-sulong-3-runs-shared-engine-ce} {targets: [daily, bench], name: "daily-bench-sulong-3-runs-shared-engine-ce-native", environment: { JVM_CONFIG: native } } ${bench-llvm-sulong-core} {name: daily-bench-sulong-graal-core-csuite} # sulong reference benchmark ${bench-llvm-native} {name: "weekly-bench-clangO3-csuite"} diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index 23527feb4938..39dd08a1f027 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -151,6 +151,7 @@ mx_sdk_vm.register_vm_config('ce', ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'java', 'libpoly', 'sespresso', 'spolyglot', 'ejvm', 'bjs', 'blli', 'bnative-image', 'btruffleruby', 'pynl', 'bgraalpython', 'pyn', 'bwasm', 'cmp', 'gwa', 'js', 'lg', 'llp', 'nfi', 'ni', 'nil', 'pbm', 'pmh', 'rby', 'rbyl', 'rgx', 'sdk', 'llrc', 'llrn', 'llrl', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmnfi', 'tfl', 'tflm'], _suite, env_file='polybench-ce') mx_sdk_vm.register_vm_config('ce', ['pbm', 'pmh', 'ni', 'js', 'lg', 'nfi', 'tfl', 'svm', 'nil', 'rgx', 'sdk', 'cmp', 'tflm', 'svmnfi', 'bnative-image', 'bjs', 'snative-image-agent', 'snative-image-diagnostics-agent'], _suite, env_file='polybench-nfi-ce') mx_sdk_vm.register_vm_config('ce', ce_components + ['llmulrl'], _suite, env_file='ce-llimul') +mx_sdk_vm.register_vm_config('ce', ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'blli', 'bnative-image', 'cmp', 'lg', 'llrc', 'llrl', 'llrn', 'nfi', 'ni', 'nil', 'pbm', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmnfi', 'tfl', 'tflm'], _suite, env_file='polybench-sulong-ce') if mx.get_os() == 'windows': mx_sdk_vm.register_vm_config('svm', ['bnative-image', 'bnative-image-configure', 'bpolyglot', 'cmp', 'gvm', 'nfi', 'ni', 'nil', 'nju', 'njucp', 'nic', 'poly', 'polynative', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmnfi', 'tfl', 'tflm'], _suite, env_file=False) diff --git a/vm/mx.vm/polybench-sulong-ce b/vm/mx.vm/polybench-sulong-ce new file mode 100644 index 000000000000..862114493584 --- /dev/null +++ b/vm/mx.vm/polybench-sulong-ce @@ -0,0 +1,3 @@ +DYNAMIC_IMPORTS=/substratevm,/sulong +COMPONENTS=Polybench Launcher,Native Image,LLVM Runtime Launcher,LLVM Runtime Native,LibGraal +NATIVE_IMAGES=polybench,lib:jvmcicompiler From 901fafe9a4a9883244e983d4b6b1376a4e7c5f66 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Mon, 11 Oct 2021 13:25:48 +0300 Subject: [PATCH 378/681] Remove Alpine Linux --- docs/enterprise-overview/architecture-overview.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index 8924085116d4..b6986a8829df 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -70,7 +70,6 @@ The following are the certified platforms for GraalVM Enterprise 21: |------------------------------------ |-------------- |-------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Oracle Linux | 7, 8 | x86 64-bit, ARM 64-bit | [Installation Guide for Linux](/getting-started/installation-linux/) | | Red Hat Enterprise Linux(RHEL) | 7, 8 | x86 64-bit | [Installation Guide for Linux](/getting-started/installation-linux/) | -| Alpine Linux | 7, 8 | x86 64-bit | [Static Native Images](../reference-manual/native-image/StaticImages.md) | | macOS | 10.14 (Mojave), 10.15 (Catalina) | x86 64-bit | [Installation Guide for macOS](/getting-started/installation-macos/) | | Microsoft Windows | Server 2016, 2019 | x86 64-bit | [Installation Guide for Windows](/getting-started/installation-windows/) | From bfdf9dd9ff20f84df5511d2f9be5c47f0f91a271 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 7 Oct 2021 09:36:19 +0200 Subject: [PATCH 379/681] Fix G1 write barrier location identities. --- .../HotSpotG1WriteBarrierSnippets.java | 10 ++--- .../gc/G1WriteBarrierSnippets.java | 42 +++++++++---------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java index aa6b42b0e1d5..367cdc3e324a 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java @@ -202,15 +202,15 @@ public Templates(OptionValues options, Iterable factories, this.lowerer = new HotspotG1WriteBarrierLowerer(config, factory); HotSpotG1WriteBarrierSnippets receiver = new HotSpotG1WriteBarrierSnippets(providers.getRegisters()); - g1PreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PreWriteBarrier", null, receiver, GC_INDEX_LOCATION, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, SATB_QUEUE_INDEX_LOCATION, + g1PreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PreWriteBarrier", null, receiver, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION); - g1ReferentReadBarrier = snippet(G1WriteBarrierSnippets.class, "g1ReferentReadBarrier", null, receiver, GC_INDEX_LOCATION, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, + g1ReferentReadBarrier = snippet(G1WriteBarrierSnippets.class, "g1ReferentReadBarrier", null, receiver, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION); - g1PostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PostWriteBarrier", null, receiver, GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION, CARD_QUEUE_INDEX_LOCATION, + g1PostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PostWriteBarrier", null, receiver, GC_CARD_LOCATION, GC_LOG_LOCATION, CARD_QUEUE_INDEX_LOCATION, CARD_QUEUE_BUFFER_LOCATION); - g1ArrayRangePreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier", null, receiver, GC_INDEX_LOCATION, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, + g1ArrayRangePreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier", null, receiver, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION); - g1ArrayRangePostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", null, receiver, GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION, + g1ArrayRangePostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", null, receiver, GC_CARD_LOCATION, GC_LOG_LOCATION, CARD_QUEUE_INDEX_LOCATION, CARD_QUEUE_BUFFER_LOCATION); } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java index c520568d6238..e7c4033394e3 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java @@ -76,18 +76,19 @@ */ public abstract class G1WriteBarrierSnippets extends WriteBarrierSnippets implements Snippets { + // This location identity is used by the pre- and the post-write barrier to write the different + // kinds of barrier data. It is sufficient to have one location identity as that data is only + // read by the GC. public static final LocationIdentity GC_LOG_LOCATION = NamedLocationIdentity.mutable("GC-Log"); - public static final LocationIdentity GC_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Index"); public static final LocationIdentity SATB_QUEUE_MARKING_LOCATION = NamedLocationIdentity.mutable("GC-Queue-Marking"); public static final LocationIdentity SATB_QUEUE_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Queue-Index"); public static final LocationIdentity SATB_QUEUE_BUFFER_LOCATION = NamedLocationIdentity.mutable("GC-Queue-Buffer"); public static final LocationIdentity CARD_QUEUE_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Card-Queue-Index"); public static final LocationIdentity CARD_QUEUE_BUFFER_LOCATION = NamedLocationIdentity.mutable("GC-Card-Queue-Buffer"); - protected static final LocationIdentity[] KILLED_PRE_WRITE_BARRIER_STUB_LOCATIONS = new LocationIdentity[]{SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION, GC_LOG_LOCATION, - GC_INDEX_LOCATION}; + protected static final LocationIdentity[] KILLED_PRE_WRITE_BARRIER_STUB_LOCATIONS = new LocationIdentity[]{SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION, GC_LOG_LOCATION}; protected static final LocationIdentity[] KILLED_POST_WRITE_BARRIER_STUB_LOCATIONS = new LocationIdentity[]{CARD_QUEUE_INDEX_LOCATION, CARD_QUEUE_BUFFER_LOCATION, GC_LOG_LOCATION, - GC_INDEX_LOCATION, GC_CARD_LOCATION}; + GC_CARD_LOCATION}; public static class Counters { Counters(SnippetCounter.Group.Factory factory) { @@ -167,17 +168,14 @@ private void satbBarrier(Address address, Object object, Object expectedObject, counters.g1ExecutedPreWriteBarrierCounter.inc(); // If the thread-local SATB buffer is full issue a native call which will // initialize a new one and add the entry. - Word indexAddress = thread.add(satbQueueIndexOffset()); - Word indexValue = indexAddress.readWord(0, SATB_QUEUE_INDEX_LOCATION); + Word indexValue = thread.readWord(satbQueueIndexOffset(), SATB_QUEUE_INDEX_LOCATION); if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) { Word bufferAddress = thread.readWord(satbQueueBufferOffset(), SATB_QUEUE_BUFFER_LOCATION); Word nextIndex = indexValue.subtract(wordSize()); - Word logAddress = bufferAddress.add(nextIndex); - // Log the object to be marked as well as update the SATB's buffer next - // index. - Word previousOop = Word.objectToTrackedPointer(previousObject); - logAddress.writeWord(0, previousOop, GC_LOG_LOCATION); - indexAddress.writeWord(0, nextIndex, GC_INDEX_LOCATION); + + // Log the object to be marked as well as update the SATB's buffer next index. + bufferAddress.writeWord(nextIndex, Word.objectToTrackedPointer(previousObject), GC_LOG_LOCATION); + thread.writeWord(satbQueueIndexOffset(), nextIndex, SATB_QUEUE_INDEX_LOCATION); } else { g1PreBarrierStub(previousObject); } @@ -245,12 +243,11 @@ public void g1PostWriteBarrier(Address address, Object object, Object value, @Co if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) { Word bufferAddress = thread.readWord(cardQueueBufferOffset(), CARD_QUEUE_BUFFER_LOCATION); Word nextIndex = indexValue.subtract(wordSize()); - Word logAddress = bufferAddress.add(nextIndex); - Word indexAddress = thread.add(cardQueueIndexOffset()); - // Log the object to be scanned as well as update - // the card queue's next index. - logAddress.writeWord(0, cardAddress, GC_LOG_LOCATION); - indexAddress.writeWord(0, nextIndex, GC_INDEX_LOCATION); + + // Log the object to be scanned as well as update the card queue's next + // index. + bufferAddress.writeWord(nextIndex, cardAddress, GC_LOG_LOCATION); + thread.writeWord(cardQueueIndexOffset(), nextIndex, CARD_QUEUE_INDEX_LOCATION); } else { g1PostBarrierStub(cardAddress); } @@ -283,10 +280,9 @@ public void g1ArrayRangePreWriteBarrier(Address address, long length, @ConstantP if (probability(FREQUENT_PROBABILITY, indexValue != 0)) { indexValue = indexValue - wordSize(); Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue)); - // Log the object to be marked as well as update the SATB's buffer next index. - Word previousOop = Word.objectToTrackedPointer(previousObject); - logAddress.writeWord(0, previousOop, GC_LOG_LOCATION); - indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION); + // Log the object to be marked and update the SATB's buffer next index. + logAddress.writeWord(0, Word.objectToTrackedPointer(previousObject), GC_LOG_LOCATION); + indexAddress.writeWord(0, WordFactory.unsigned(indexValue), SATB_QUEUE_INDEX_LOCATION); } else { g1PreBarrierStub(previousObject); } @@ -325,7 +321,7 @@ public void g1ArrayRangePostWriteBarrier(Address address, long length, @Constant // Log the object to be scanned as well as update // the card queue's next index. logAddress.writeWord(0, cur, GC_LOG_LOCATION); - indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION); + indexAddress.writeWord(0, WordFactory.unsigned(indexValue), CARD_QUEUE_INDEX_LOCATION); } else { g1PostBarrierStub(cur); } From 4f9b4976c20a4c9f817454ce6747b3e10ddaa389 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Fri, 8 Oct 2021 09:02:56 +0200 Subject: [PATCH 380/681] Renamed and split G1 write barrier location identities. --- .../hotspot/GraalHotSpotVMConfig.java | 6 ++-- .../HotSpotG1WriteBarrierSnippets.java | 12 +++---- .../replacements/HotSpotReplacementsUtil.java | 2 +- .../gc/G1WriteBarrierSnippets.java | 33 +++++++++---------- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java index 9cb08c907359..056579f96201 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java @@ -630,7 +630,7 @@ private static String markWordField(String simpleName) { // G1 Collector Related Values. public final byte dirtyCardValue; public final byte g1YoungCardValue; - public final int g1SATBQueueMarkingOffset; + public final int g1SATBQueueMarkingActiveOffset; public final int g1SATBQueueIndexOffset; public final int g1SATBQueueBufferOffset; public final int g1CardQueueIndexOffset; @@ -649,13 +649,13 @@ private static String markWordField(String simpleName) { g1YoungCardValue = getFieldValue("CompilerToVM::Data::g1_young_card", Byte.class, "int"); g1CardQueueIndexOffset = javaThreadDirtyCardQueueOffset + dirtyCardQueueIndexOffset; g1CardQueueBufferOffset = javaThreadDirtyCardQueueOffset + dirtyCardQueueBufferOffset; - g1SATBQueueMarkingOffset = javaThreadSatbMarkQueueOffset + satbMarkQueueActiveOffset; + g1SATBQueueMarkingActiveOffset = javaThreadSatbMarkQueueOffset + satbMarkQueueActiveOffset; g1SATBQueueIndexOffset = javaThreadSatbMarkQueueOffset + satbMarkQueueIndexOffset; g1SATBQueueBufferOffset = javaThreadSatbMarkQueueOffset + satbMarkQueueBufferOffset; } else { dirtyCardValue = getConstant("CardTable::dirty_card", Byte.class); g1YoungCardValue = getConstant("G1CardTable::g1_young_gen", Byte.class); - g1SATBQueueMarkingOffset = getConstant("G1ThreadLocalData::satb_mark_queue_active_offset", Integer.class); + g1SATBQueueMarkingActiveOffset = getConstant("G1ThreadLocalData::satb_mark_queue_active_offset", Integer.class); g1SATBQueueIndexOffset = getConstant("G1ThreadLocalData::satb_mark_queue_index_offset", Integer.class); g1SATBQueueBufferOffset = getConstant("G1ThreadLocalData::satb_mark_queue_buffer_offset", Integer.class); g1CardQueueIndexOffset = getConstant("G1ThreadLocalData::dirty_card_queue_index_offset", Integer.class); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java index 367cdc3e324a..a9801142b312 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java @@ -92,7 +92,7 @@ protected int objectArrayIndexScale() { } @Override - protected int satbQueueMarkingOffset() { + protected int satbQueueMarkingActiveOffset() { return HotSpotReplacementsUtil.g1SATBQueueMarkingOffset(INJECTED_VMCONFIG); } @@ -202,15 +202,15 @@ public Templates(OptionValues options, Iterable factories, this.lowerer = new HotspotG1WriteBarrierLowerer(config, factory); HotSpotG1WriteBarrierSnippets receiver = new HotSpotG1WriteBarrierSnippets(providers.getRegisters()); - g1PreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PreWriteBarrier", null, receiver, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, SATB_QUEUE_INDEX_LOCATION, + g1PreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PreWriteBarrier", null, receiver, SATB_QUEUE_LOG_LOCATION, SATB_QUEUE_MARKING_ACTIVE_LOCATION, SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION); - g1ReferentReadBarrier = snippet(G1WriteBarrierSnippets.class, "g1ReferentReadBarrier", null, receiver, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, + g1ReferentReadBarrier = snippet(G1WriteBarrierSnippets.class, "g1ReferentReadBarrier", null, receiver, SATB_QUEUE_LOG_LOCATION, SATB_QUEUE_MARKING_ACTIVE_LOCATION, SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION); - g1PostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PostWriteBarrier", null, receiver, GC_CARD_LOCATION, GC_LOG_LOCATION, CARD_QUEUE_INDEX_LOCATION, + g1PostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PostWriteBarrier", null, receiver, GC_CARD_LOCATION, CARD_QUEUE_LOG_LOCATION, CARD_QUEUE_INDEX_LOCATION, CARD_QUEUE_BUFFER_LOCATION); - g1ArrayRangePreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier", null, receiver, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, + g1ArrayRangePreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier", null, receiver, SATB_QUEUE_LOG_LOCATION, SATB_QUEUE_MARKING_ACTIVE_LOCATION, SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION); - g1ArrayRangePostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", null, receiver, GC_CARD_LOCATION, GC_LOG_LOCATION, + g1ArrayRangePostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", null, receiver, GC_CARD_LOCATION, CARD_QUEUE_LOG_LOCATION, CARD_QUEUE_INDEX_LOCATION, CARD_QUEUE_BUFFER_LOCATION); } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 42c88a39b221..ec169219f8bf 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -661,7 +661,7 @@ public static int logOfHeapRegionGrainBytes(@InjectedParameter GraalHotSpotVMCon @Fold public static int g1SATBQueueMarkingOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.g1SATBQueueMarkingOffset; + return config.g1SATBQueueMarkingActiveOffset; } @Fold diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java index e7c4033394e3..989768d9e9fb 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java @@ -76,18 +76,17 @@ */ public abstract class G1WriteBarrierSnippets extends WriteBarrierSnippets implements Snippets { - // This location identity is used by the pre- and the post-write barrier to write the different - // kinds of barrier data. It is sufficient to have one location identity as that data is only - // read by the GC. - public static final LocationIdentity GC_LOG_LOCATION = NamedLocationIdentity.mutable("GC-Log"); - public static final LocationIdentity SATB_QUEUE_MARKING_LOCATION = NamedLocationIdentity.mutable("GC-Queue-Marking"); - public static final LocationIdentity SATB_QUEUE_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Queue-Index"); - public static final LocationIdentity SATB_QUEUE_BUFFER_LOCATION = NamedLocationIdentity.mutable("GC-Queue-Buffer"); - public static final LocationIdentity CARD_QUEUE_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Card-Queue-Index"); + public static final LocationIdentity SATB_QUEUE_MARKING_ACTIVE_LOCATION = NamedLocationIdentity.mutable("GC-SATB-Marking-Active"); + public static final LocationIdentity SATB_QUEUE_BUFFER_LOCATION = NamedLocationIdentity.mutable("GC-SATB-Queue-Buffer"); + public static final LocationIdentity SATB_QUEUE_LOG_LOCATION = NamedLocationIdentity.mutable("GC-SATB-Queue-Log"); + public static final LocationIdentity SATB_QUEUE_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-SATB-Queue-Index"); + public static final LocationIdentity CARD_QUEUE_BUFFER_LOCATION = NamedLocationIdentity.mutable("GC-Card-Queue-Buffer"); + public static final LocationIdentity CARD_QUEUE_LOG_LOCATION = NamedLocationIdentity.mutable("GC-Card-Queue-Log"); + public static final LocationIdentity CARD_QUEUE_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Card-Queue-Index"); - protected static final LocationIdentity[] KILLED_PRE_WRITE_BARRIER_STUB_LOCATIONS = new LocationIdentity[]{SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION, GC_LOG_LOCATION}; - protected static final LocationIdentity[] KILLED_POST_WRITE_BARRIER_STUB_LOCATIONS = new LocationIdentity[]{CARD_QUEUE_INDEX_LOCATION, CARD_QUEUE_BUFFER_LOCATION, GC_LOG_LOCATION, + protected static final LocationIdentity[] KILLED_PRE_WRITE_BARRIER_STUB_LOCATIONS = new LocationIdentity[]{SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION, SATB_QUEUE_LOG_LOCATION}; + protected static final LocationIdentity[] KILLED_POST_WRITE_BARRIER_STUB_LOCATIONS = new LocationIdentity[]{CARD_QUEUE_INDEX_LOCATION, CARD_QUEUE_BUFFER_LOCATION, CARD_QUEUE_LOG_LOCATION, GC_CARD_LOCATION}; public static class Counters { @@ -132,7 +131,7 @@ private void satbBarrier(Address address, Object object, Object expectedObject, Word thread = getThread(); verifyOop(object); Word field = Word.fromAddress(address); - byte markingValue = thread.readByte(satbQueueMarkingOffset(), SATB_QUEUE_MARKING_LOCATION); + byte markingValue = thread.readByte(satbQueueMarkingActiveOffset(), SATB_QUEUE_MARKING_ACTIVE_LOCATION); boolean trace = isTracingActive(traceStartCycle); int gcCycle = 0; @@ -174,7 +173,7 @@ private void satbBarrier(Address address, Object object, Object expectedObject, Word nextIndex = indexValue.subtract(wordSize()); // Log the object to be marked as well as update the SATB's buffer next index. - bufferAddress.writeWord(nextIndex, Word.objectToTrackedPointer(previousObject), GC_LOG_LOCATION); + bufferAddress.writeWord(nextIndex, Word.objectToTrackedPointer(previousObject), SATB_QUEUE_LOG_LOCATION); thread.writeWord(satbQueueIndexOffset(), nextIndex, SATB_QUEUE_INDEX_LOCATION); } else { g1PreBarrierStub(previousObject); @@ -246,7 +245,7 @@ public void g1PostWriteBarrier(Address address, Object object, Object value, @Co // Log the object to be scanned as well as update the card queue's next // index. - bufferAddress.writeWord(nextIndex, cardAddress, GC_LOG_LOCATION); + bufferAddress.writeWord(nextIndex, cardAddress, CARD_QUEUE_LOG_LOCATION); thread.writeWord(cardQueueIndexOffset(), nextIndex, CARD_QUEUE_INDEX_LOCATION); } else { g1PostBarrierStub(cardAddress); @@ -260,7 +259,7 @@ public void g1PostWriteBarrier(Address address, Object object, Object value, @Co @Snippet public void g1ArrayRangePreWriteBarrier(Address address, long length, @ConstantParameter int elementStride) { Word thread = getThread(); - byte markingValue = thread.readByte(satbQueueMarkingOffset(), SATB_QUEUE_MARKING_LOCATION); + byte markingValue = thread.readByte(satbQueueMarkingActiveOffset(), SATB_QUEUE_MARKING_ACTIVE_LOCATION); // If the concurrent marker is not enabled or the vector length is zero, return. if (probability(FREQUENT_PROBABILITY, markingValue == (byte) 0 || length == 0)) { return; @@ -281,7 +280,7 @@ public void g1ArrayRangePreWriteBarrier(Address address, long length, @ConstantP indexValue = indexValue - wordSize(); Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue)); // Log the object to be marked and update the SATB's buffer next index. - logAddress.writeWord(0, Word.objectToTrackedPointer(previousObject), GC_LOG_LOCATION); + logAddress.writeWord(0, Word.objectToTrackedPointer(previousObject), SATB_QUEUE_LOG_LOCATION); indexAddress.writeWord(0, WordFactory.unsigned(indexValue), SATB_QUEUE_INDEX_LOCATION); } else { g1PreBarrierStub(previousObject); @@ -320,7 +319,7 @@ public void g1ArrayRangePostWriteBarrier(Address address, long length, @Constant Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue)); // Log the object to be scanned as well as update // the card queue's next index. - logAddress.writeWord(0, cur, GC_LOG_LOCATION); + logAddress.writeWord(0, cur, CARD_QUEUE_LOG_LOCATION); indexAddress.writeWord(0, WordFactory.unsigned(indexValue), CARD_QUEUE_INDEX_LOCATION); } else { g1PostBarrierStub(cur); @@ -337,7 +336,7 @@ public void g1ArrayRangePostWriteBarrier(Address address, long length, @Constant protected abstract int objectArrayIndexScale(); - protected abstract int satbQueueMarkingOffset(); + protected abstract int satbQueueMarkingActiveOffset(); protected abstract int satbQueueBufferOffset(); From 0287f8cefd85ec29e9cd47bef761f3806e5bc92f Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 11 Oct 2021 12:56:46 +0200 Subject: [PATCH 381/681] Minor renamings. --- .../hotspot/replacements/HotSpotG1WriteBarrierSnippets.java | 2 +- .../compiler/hotspot/replacements/HotSpotReplacementsUtil.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java index a9801142b312..18fe93b4f2d6 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java @@ -93,7 +93,7 @@ protected int objectArrayIndexScale() { @Override protected int satbQueueMarkingActiveOffset() { - return HotSpotReplacementsUtil.g1SATBQueueMarkingOffset(INJECTED_VMCONFIG); + return HotSpotReplacementsUtil.g1SATBQueueMarkingActiveOffset(INJECTED_VMCONFIG); } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index ec169219f8bf..ef7d46718cc8 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -660,7 +660,7 @@ public static int logOfHeapRegionGrainBytes(@InjectedParameter GraalHotSpotVMCon } @Fold - public static int g1SATBQueueMarkingOffset(@InjectedParameter GraalHotSpotVMConfig config) { + public static int g1SATBQueueMarkingActiveOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.g1SATBQueueMarkingActiveOffset; } From cf5d9cae439f7f3f94188f79dbff2a8844dbf9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Mon, 11 Oct 2021 13:45:46 +0200 Subject: [PATCH 382/681] Ensure paths for resource lookup contains no duplicates --- .../src/com/oracle/svm/hosted/ResourcesFeature.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java index fbdaa447b084..4ad543dc9683 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java @@ -50,7 +50,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import com.oracle.svm.core.util.VMError; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; @@ -74,6 +73,7 @@ import com.oracle.svm.core.option.LocatableMultiOptionValue; import com.oracle.svm.core.util.ClasspathUtils; import com.oracle.svm.core.util.UserError; +import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; import com.oracle.svm.hosted.config.ConfigurationParserUtils; @@ -220,7 +220,7 @@ public void duringAnalysis(DuringAnalysisAccess access) { */ ImageClassLoader loader = accessImpl.imageClassLoader; - Stream.concat(loader.modulepath().stream(), loader.classpath().stream()).forEach(classpathFile -> { + Stream.concat(loader.modulepath().stream(), loader.classpath().stream()).distinct().forEach(classpathFile -> { try { if (Files.isDirectory(classpathFile)) { scanDirectory(debugContext, classpathFile, includePatterns, excludePatterns); From ec1955e292fad32b047a194106403c1d60a9f875 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Sat, 11 Sep 2021 13:07:43 +0300 Subject: [PATCH 383/681] Try using relative links instead of permalinks --- docs/enterprise-overview/architecture-overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index 512e250d54ff..4b4f5be3e878 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -29,9 +29,9 @@ The conceptual overview and advantages of GraalVM Enterprise are described on th The preceding diagram illustrates a complete high-level architecture of GraalVM Enterprise. -GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](/reference-manual/compiler/), which is written in Java, to the HotSpot Java Virtual Machine. +GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](../reference-manual/compiler.md), which is written in Java, to the HotSpot Java Virtual Machine. -In addition to running Java and JVM-based languages, GraalVM's [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. +In addition to running Java and JVM-based languages, GraalVM's [Truffle language implementation framework](../../truffle/docs/README.md) makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. With GraalVM Truffle, Java and other supported languages can directly interoperate with each other and pass data back and forth in the same memory space. ## Runtime Modes From 8239a729099507fb1008b33d3f9ff5d6d99ae30d Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Sat, 11 Sep 2021 14:00:07 +0300 Subject: [PATCH 384/681] Revert changes --- docs/enterprise-overview/architecture-overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index 4b4f5be3e878..512e250d54ff 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -29,9 +29,9 @@ The conceptual overview and advantages of GraalVM Enterprise are described on th The preceding diagram illustrates a complete high-level architecture of GraalVM Enterprise. -GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](../reference-manual/compiler.md), which is written in Java, to the HotSpot Java Virtual Machine. +GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](/reference-manual/compiler/), which is written in Java, to the HotSpot Java Virtual Machine. -In addition to running Java and JVM-based languages, GraalVM's [Truffle language implementation framework](../../truffle/docs/README.md) makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. +In addition to running Java and JVM-based languages, GraalVM's [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. With GraalVM Truffle, Java and other supported languages can directly interoperate with each other and pass data back and forth in the same memory space. ## Runtime Modes From a19f921576d053825a04548f7a2fa0da042626df Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 21 Sep 2021 21:43:48 +0300 Subject: [PATCH 385/681] Update docs/enterprise-overview --- .../architecture-overview.md | 52 +++++++++---------- .../enterprise-overview/solutions-overview.md | 2 +- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index 512e250d54ff..07b912d070f8 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -10,7 +10,7 @@ It is designed to accelerate the execution of applications written in Java and o GraalVM Enterprise's polyglot capabilities make it possible to mix multiple programming languages in a single application while eliminating any foreign language call costs. This page provides developers, solution architects, and infrastructure architects with an architectural overview of GraalVM Enterprise, as well as information about runtime modes, supported platforms, available distributions, core and additional functionalities, and support levels for various features. -The conceptual overview and advantages of GraalVM Enterprise are described on the [Solutions Overview](https://docs.oracle.com/en/graalvm/enterprise/21/docs/overview/) page. +The conceptual overview and advantages of GraalVM Enterprise are described on the [Solutions Overview](overview.md) page. * [GraalVM Enterprise Architecture](#graalvm-enterprise-architecture) * [Runtime Modes](#runtime-modes) @@ -29,38 +29,38 @@ The conceptual overview and advantages of GraalVM Enterprise are described on th The preceding diagram illustrates a complete high-level architecture of GraalVM Enterprise. -GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](/reference-manual/compiler/), which is written in Java, to the HotSpot Java Virtual Machine. +GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](../reference-manual/compiler.md), which is written in Java, to the HotSpot Java Virtual Machine. -In addition to running Java and JVM-based languages, GraalVM's [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. -With GraalVM Truffle, Java and other supported languages can directly interoperate with each other and pass data back and forth in the same memory space. +In addition to running Java and JVM-based languages, [GraalVM's language implementation framework (Truffle)](../graalvm-as-a-platform/graalvm-as-a-platform.md), makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. +With Truffle, Java and other supported languages can directly interoperate with each other and pass data back and forth in the same memory space. ## Runtime Modes GraalVM Enterprise is unique as a runtime environment offering several modes of operation: JVM runtime mode, Native Image, Java on Truffle (the same Java applications can be run on either). #### JVM Runtime Mode -When running programs on the HotSpot JVM, GraalVM defaults to the [GraalVM compiler](/reference-manual/compiler/) as the top-tier JIT compiler. +When running programs on the HotSpot JVM, GraalVM defaults to the [GraalVM compiler](../reference-manual/compiler.md) as the top-tier JIT compiler. At runtime, an application is loaded and executed normally on the JVM. The JVM passes bytecodes for Java or any other JVM-native language to the compiler, which compiles that to the machine code and returns it to the JVM. -Interpreters for supported languages, written on top of the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/), are themselves Java programs that run on the JVM. +Interpreters for supported languages, written on top of the [Truffle framework](../graalvm-as-a-platform/graalvm-as-a-platform.md), are themselves Java programs that run on the JVM. #### Native Image -[Native Image](/reference-manual/native-image/) is an innovative technology that compiles Java code into a standalone binary executable or a native shared library. +[Native Image](../reference-manual/native-image/README.md) is an innovative technology that compiles Java code into a standalone binary executable or a native shared library. The Java bytecode that is processed during the native image build includes all application classes, dependencies, third party dependent libraries, and any JDK classes that are required. A generated self-contained native executable is specific to each individual operating systems and machine architecture that does not require a JVM. #### Java on Truffle -[Java on Truffle](/reference-manual/java-on-truffle/) is an implementation of the Java Virtual Machine Specification, built with the [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/). +[Java on Truffle](../reference-manual/java-on-truffle/README.md) is an implementation of the Java Virtual Machine Specification, built with the [Truffle framework](../graalvm-as-a-platform/graalvm-as-a-platform.md). It is a complete Java VM that includes all core components, implements the same API as the Java Runtime Environment library, and reuses all JARs and native libraries from GraalVM. Java on Trufle is an experimental technology in GraalVM, available as of version 21.0.0. ## Available Distributions -GraalVM Enterprise distributions are based on Oracle JDK 8, 11, and 16. +GraalVM Enterprise distributions are based on Oracle JDK 8, 11, and 17. GraalVM Enterprise releases include all Oracle Java critical patch updates (CPUs), which are released on a regular schedule to remedy defects and known vulnerabilities. GraalVM Enterprise is available for Linux, macOS, and Windows platforms on x86 64-bit systems, and for Linux on ARM 64-bit system. -The GraalVM Enterprise distribution based on Oracle JDK 16 is experimental with [several known limitations](https://docs.oracle.com/en/graalvm/enterprise/21/docs/overview/known-issues/). +The GraalVM Enterprise distribution based on Oracle JDK 17 is experimental with [several known limitations](https://docs.oracle.com/en/graalvm/enterprise/21/docs/overview/known-issues/). Depending on the platform, the distributions are shipped as *.tar.gz* or *.zip* archives. ## Certified Platforms @@ -69,10 +69,10 @@ The following are the certified platforms for GraalVM Enterprise 21: | Operating System | Version | Architecture | Installation Guide | |------------------------------------ |-------------- |-------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Oracle Linux | 7, 8 | x86 64-bit, ARM 64-bit | [Installation Guide for Linux](/getting-started/installation-linux/) | -| Red Hat Enterprise Linux(RHEL) | 7, 8 | x86 64-bit | [Installation Guide for Linux](/getting-started/installation-linux/) | -| macOS | 10.14 (Mojave), 10.15 (Catalina) | x86 64-bit | [Installation Guide for macOS](/getting-started/installation-macos/) | -| Microsoft Windows | Server 2016, 2019 | x86 64-bit | [Installation Guide for Windows](/getting-started/installation-windows/) | +| Oracle Linux | 7, 8 | x86 64-bit, ARM 64-bit | [Installation Guide for Linux](../getting-started/graalvm-enterprise/installation-linux-aarch64.md) | +| Red Hat Enterprise Linux(RHEL) | 7, 8 | x86 64-bit | [Installation Guide for Linux](../getting-started/graalvm-enterprise/installation-linux.md) | +| macOS | 10.14 (Mojave), 10.15 (Catalina) | x86 64-bit | [Installation Guide for macOS](../getting-started/graalvm-enterprise/installation-macos.md) | +| Microsoft Windows | Server 2016, 2019 | x86 64-bit | [Installation Guide for Windows](../getting-started/graalvm-enterprise/installation-windows.md) | ## Distribution Components List @@ -91,24 +91,24 @@ GraalVM Enterprise consists of core and additional functionalities. **Utilities** * JavaScript REPL with the JavaScript interpreter * `lli` tool to directly execute programs from LLVM bitcode -* [GraalVM Updater](/reference-manual/graalvm-updater/) to install additional functionalities +* [GraalVM Updater](../reference-manual/graalvm-updater.md) to install additional functionalities ### Additional Functionalities GraalVM Enterprise core installation can be extended with more languages runtimes and utilities. Tools/Utilities: -* [Native Image](/reference-manual/native-image/) -- a technology to compile an application ahead-of-time into a native platform executable. -* [LLVM toolchain](/reference-manual/llvm/) -- a set of tools and APIs for compiling native programs to bitcode that can be executed on GraalVM. -* [Java on Truffle](/reference-manual/java-on-truffle/) -- a JVM implementation built upon the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/) to run Java via a Java bytecode interpreter. +* [Native Image](../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native platform executable. +* [LLVM toolchain](../reference-manual/llvm/README.md) -- a set of tools and APIs for compiling native programs to bitcode that can be executed on GraalVM. +* [Java on Truffle](../reference-manual/java-on-truffle/README.md) -- a JVM implementation built upon the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/) to run Java via a Java bytecode interpreter. Runtimes: -* [Node.js](/reference-manual/js/) -- the Node.js 14.16.1 runtime for JavaScript -* [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.3 compatible -* [R](/reference-manual/r/) -- GNU R 4.0.3 compatible -* [GraalWasm](/reference-manual/wasm/) -- WebAssembly (Wasm) +* [Node.js](../reference-manual/js/README.md) -- the Node.js 14.17.6 runtime for JavaScript +* [Python](../reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](../reference-manual/ruby/README.md) -- Ruby 2.7.3 compatible +* [R](../reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [GraalWasm](../reference-manual/wasm/README.md) -- WebAssembly (Wasm) ## Licensing and Support @@ -143,9 +143,9 @@ The following table lists supported and experimental features in GraalVM Enterpr ## What to Read Next -Users who are new to GraalVM Enterprise or have little experience using it, continue to [Getting Started with GraalVM Enterprise](/getting-started//#install-graalvm-enterprise). +Users who are new to GraalVM Enterprise or have little experience using it, continue to [Getting Started with GraalVM Enterprise](../getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md). Download and install GraalVM Enterprise on your local machine, try running the examples provided in the guide, or test GraalVM Enterprise with your workload. -We suggest you then look at more complex [Examples Applications](/docs/examples/). +We suggest you then look at more complex [Examples Applications](../examples/examples.md). -Developers, who have GraalVM Enterprise already installed or have experience using it in the past, can skip the getting started guide and proceed to the [Reference Manuals](/reference-manual/) for +Developers, who have GraalVM Enterprise already installed or have experience using it in the past, can skip the getting started guide and proceed to the [Reference Manuals](../reference-manual/reference-manuals.md) for in-depth coverage of GraalVM Enterprise technologies. diff --git a/docs/enterprise-overview/solutions-overview.md b/docs/enterprise-overview/solutions-overview.md index 1f7a5dc3b625..25bcd89418b9 100644 --- a/docs/enterprise-overview/solutions-overview.md +++ b/docs/enterprise-overview/solutions-overview.md @@ -96,7 +96,7 @@ vulnerabilities. ## Get Started with GraalVM Enterprise -[Get started with GraalVM Enterprise](/getting-started/) and: +[Get started with GraalVM Enterprise](../getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md) and: * reduce IT and storage costs * provide customers with quicker response time * employ fewer resources, freeing up CPU From 80083a19bb0650cfa1cefd310cbd0d528c6d10d8 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 21 Sep 2021 21:53:52 +0300 Subject: [PATCH 386/681] Proofread and update links in docs/examples --- docs/examples/mle-oracle.md | 6 ++++-- docs/examples/polyglot-javascript-java-r.md | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/examples/mle-oracle.md b/docs/examples/mle-oracle.md index 3806fd535cfe..be336d69dca2 100644 --- a/docs/examples/mle-oracle.md +++ b/docs/examples/mle-oracle.md @@ -46,9 +46,9 @@ END; / ``` -Please also note the EXCEPTION clause which makes sure that the context gets dropped either way. This is important to avoid resource leakage. +Note: There is the `EXCEPTION` clause which makes sure that the context gets dropped either way. This is important to avoid resource leakage. -2. Now here's an example that shows how values can be passed between PL/SQL and MLE. As expected, the output is `49`: +2. Now here is an example that shows how values can be passed between PL/SQL and MLE. As expected, the output is `49`: ```sql SET SERVEROUTPUT ON; DECLARE @@ -139,6 +139,7 @@ END; ``` ## Type Conversions + Let us now have a closer look at conversions from Oracle types (as retrieved by SQL queries) to JavaScript types. By default, Oracle data types get automatically converted to regular, native JavaScript types, which can lead to a loss of precision. @@ -249,6 +250,7 @@ END; ``` ## Further Reading + Here is a set of resources that we recommend for further reading about MLE: - [Multilingual Engine: Executing JavaScript in Oracle Database](https://medium.com/graalvm/mle-executing-javascript-in-oracle-database-c545feb1a010) provides further insight into the MLE architecture based on GraalVM. - [MLE and the Future of Server-Side Programming in Oracle APEX](https://blogs.oracle.com/apex/mle-and-the-future-of-server-side-programming-in-oracle-apex) shows step-by-step how to set up a free Oracle Cloud account, provision a database instance and run some JavaScript code in Oracle APEX (powered by MLE). diff --git a/docs/examples/polyglot-javascript-java-r.md b/docs/examples/polyglot-javascript-java-r.md index 9dd251a389d9..31e52eaf4eaf 100644 --- a/docs/examples/polyglot-javascript-java-r.md +++ b/docs/examples/polyglot-javascript-java-r.md @@ -17,7 +17,7 @@ git clone https://github.com/graalvm/graalvm-demos cd graalvm-demos/polyglot-javascript-java-r ``` -2. [Install GraalVM](/docs/getting-started/#install-graalvm) on your platform. +2. [Install GraalVM](../getting-started/graalvm-community/get-started-graalvm-community.md/#install-graalvm) on your platform. 3. To run the demo, you need to enable Node.js support in GraalVM: ```shell From b647d4679e2e6db218e30669a316be0b6be9fa87 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 21 Sep 2021 22:49:48 +0300 Subject: [PATCH 387/681] Proofread and update links in docs/getting-started --- .../architecture-overview.md | 2 +- .../graalvm-ce-container-images.md | 3 +- .../get-started-graalvm-community.md | 64 +++++++++---------- .../graalvm-community/linux-aarch64.md | 6 +- .../graalvm-community/linux.md | 22 +++---- .../graalvm-community/macos.md | 22 +++---- .../graalvm-community/windows.md | 19 +++--- .../get-started-graalvm-enterprise.md | 64 +++++++++---------- .../installation-linux-aarch64.md | 6 +- .../graalvm-enterprise/installation-linux.md | 24 ++++--- .../graalvm-enterprise/installation-macos.md | 24 ++++--- .../installation-windows.md | 23 ++++--- .../oci/compute-instances.md | 2 +- 13 files changed, 136 insertions(+), 145 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index 07b912d070f8..dc47810edac4 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -69,7 +69,7 @@ The following are the certified platforms for GraalVM Enterprise 21: | Operating System | Version | Architecture | Installation Guide | |------------------------------------ |-------------- |-------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Oracle Linux | 7, 8 | x86 64-bit, ARM 64-bit | [Installation Guide for Linux](../getting-started/graalvm-enterprise/installation-linux-aarch64.md) | +| Oracle Linux | 7, 8 | x86 64-bit, ARM 64-bit | [Installation Guide for Linux](../getting-started/graalvm-enterprise/oci/compute-instances.md) | | Red Hat Enterprise Linux(RHEL) | 7, 8 | x86 64-bit | [Installation Guide for Linux](../getting-started/graalvm-enterprise/installation-linux.md) | | macOS | 10.14 (Mojave), 10.15 (Catalina) | x86 64-bit | [Installation Guide for macOS](../getting-started/graalvm-enterprise/installation-macos.md) | | Microsoft Windows | Server 2016, 2019 | x86 64-bit | [Installation Guide for Windows](../getting-started/graalvm-enterprise/installation-windows.md) | diff --git a/docs/getting-started/graalvm-community/container-images/graalvm-ce-container-images.md b/docs/getting-started/graalvm-community/container-images/graalvm-ce-container-images.md index a16a8e3b7014..ed2edb613a87 100644 --- a/docs/getting-started/graalvm-community/container-images/graalvm-ce-container-images.md +++ b/docs/getting-started/graalvm-community/container-images/graalvm-ce-container-images.md @@ -50,9 +50,8 @@ bash-4.4# ``` Please note that the image contains only the components immediately available in the GraalVM Community core download. -However, the [GraalVM Updater](/reference-manual/graalvm-updater/) utility is on the `PATH` and you can install the support for additional languages and runtimes like Node.js, Ruby, R, Python or WebAssembly at will. +However, the [GraalVM Updater, `gu`](../../../reference-manual/graalvm-updater.md), utility is included in the container image and may be used to install additional languages and runtimes like Node.js, Ruby, R, Python or WebAssembly. -However, the [GraalVM Updater, `gu`](/reference-manual/graalvm-updater/), utility is included in the container image and may be used to install additional languages and runtimes like Node.js, Ruby, R, Python or WebAssembly. For example, the following command installs the Ruby support (the output below is truncated for brevity): ```shell diff --git a/docs/getting-started/graalvm-community/get-started-graalvm-community.md b/docs/getting-started/graalvm-community/get-started-graalvm-community.md index f6142b394a12..71f41f11f9dd 100644 --- a/docs/getting-started/graalvm-community/get-started-graalvm-community.md +++ b/docs/getting-started/graalvm-community/get-started-graalvm-community.md @@ -14,18 +14,18 @@ GraalVM's polyglot capabilities make it possible to mix multiple programming lan Here you will find information about installing GraalVM Community Edition, running basic applications with it, and adding support for accompanying features. Further, you will learn about the polyglot capabilities of GraalVM and see how to build platform-specific native executables of JVM-based applications. -If you are new to GraalVM, we recommend starting with [Introduction to GraalVM](/docs/introduction/), where you will find information about GraalVM's architecture, distributions available, supported platforms, core and additional features, and much more. +If you are new to GraaVM, we recommend starting with [Introduction to GraalVM](../../introduction.md), where you will find information about GraalVM's architecture, distributions available, supported platforms, core and additional features, and much more. -If you have GraalVM already installed and have experience using it, you can skip this getting started guide and proceed to the in-depth [Reference Manuals](/reference-manual/). +If you have GraalVM already installed and have experience using it, you can skip this getting started guide and proceed to the in-depth [Reference Manuals](../../reference-manual/reference-manuals.md). ## Install GraalVM Getting GraalVM installed and ready-to-go should take a few minutes. Choose the operating system and proceed to the installation steps: -* [Linux](/docs/getting-started/linux/) -* [Linux AArch64](/docs/getting-started/linux-aarch64/) -* [macOS](/docs/getting-started/macos/) -* [Windows](/docs/getting-started/windows/) +* [Linux](linux.md) +* [Linux AArch64](linux-aarch64.md) +* [macOS](macos.md) +* [Windows](windows.md) ## Start Running Applications @@ -73,10 +73,10 @@ java HelloWorld Hello World! ``` -You can find a collection of larger Java examples on the [Examples Applications](/examples/) page. +You can find a collection of larger Java examples on the [Examples Applications](../../examples/examples.md) page. For more information on the GraalVM -compiler, go to [Compiler](/reference-manual/compiler/). -For more extensive documentation on running Java, proceed to [JVM Languages](/reference-manual/java/). +compiler, go to [Compiler](../../reference-manual/compiler.md). +For more extensive documentation on running Java, proceed to [JVM Languages](../../reference-manual/java/README.md). ## Run JavaScript and Node.js @@ -92,7 +92,7 @@ Node.js support is not installed by default, but can be easily added with GraalV ```shell gu install nodejs node -v -v14.16.1 +v14.17.6 ``` More than 100,000 npm packages are regularly tested and are compatible with GraalVM, including modules like express, react, async, request, browserify, grunt, mocha, and underscore. @@ -124,7 +124,7 @@ node app.js ``` For more detailed documentation and information on compatibility with Node.js, -proceed to [JavaScript and Node.js](/reference-manual/js/). +proceed to [JavaScript and Node.js](../../reference-manual/js/README.md). ## Run LLVM Languages @@ -154,12 +154,12 @@ $LLVM_TOOLCHAIN/clang hello.c -o hello lli hello ``` -For in-depth documentation and more examples of running LLVM bitcode on GraalVM, go to [LLVM Languages](/reference-manual/llvm/). +For in-depth documentation and more examples of running LLVM bitcode on GraalVM, go to [LLVM Languages](../../reference-manual/llvm/README.md). ## Run Python With GraalVM you can run Python applications in the Python 3 runtime environment. -The support is not available by default, but you can quickly add it to GraalVM using the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +The support is not available by default, but you can quickly add it to GraalVM using the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install python ``` @@ -173,12 +173,12 @@ graalpython >>> exit() ``` -More examples and additional information on Python support in GraalVM can be found in the [Python reference manual](/reference-manual/python/). +More examples and additional information on Python support in GraalVM can be found in the [Python reference manual](../../reference-manual/python/README.md). ## Run Ruby GraalVM provides a high-performance Ruby runtime environment including the `gem` command that allows you to interact with RubyGems, Ruby Bundler, and much more. -The Ruby runtime is not available by default in GraalVM, but can be easily added using the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +The Ruby runtime is not available by default in GraalVM, but can be easily added using the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install ruby ``` @@ -189,7 +189,7 @@ ruby [options] program.rb ``` GraalVM Ruby runtime environment uses the -[same options as the standard implementation of Ruby](/reference-manual/ruby/Options/), +[same options as the standard implementation of Ruby](../../reference-manual/ruby/Options.md), with some additions. For example: ```shell gem install chunky_png @@ -197,12 +197,12 @@ ruby -r chunky_png -e "puts ChunkyPNG::Color.to_hex(ChunkyPNG::Color('mintcream #f5fffa80 ``` -More examples and in-depth documentation can be found in the [Ruby reference manual](/reference-manual/ruby/). +More examples and in-depth documentation can be found in the [Ruby reference manual](../../reference-manual/ruby/README.md). ## Run R GraalVM provides a GNU-compatible environment to run R programs directly or in the REPL mode. -Although the R language support is not available by default, you can add it to GraalVM using the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +Although the R language support is not available by default, you can add it to GraalVM using the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install R ``` @@ -217,12 +217,12 @@ R version 4.0.3 (FastR) [1] 2 ``` -More examples and in-depth documentation can be found in the [R reference manual](/reference-manual/r/). +More examples and in-depth documentation can be found in the [R reference manual](../../reference-manual/r/README.md). ## Run WebAssembly With GraalVM you can run programs compiled to WebAssembly. -The support is not available by default, but you can add it to GraalVM using the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +The support is not available by default, but you can add it to GraalVM using the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install wasm ``` @@ -256,7 +256,7 @@ Then you can run the compiled WebAssembly binary on GraalVM as follows: wasm --Builtins=wasi_snapshot_preview1 floyd.wasm ``` -More details can be found in the [WebAssembly reference manual](/reference-manual/wasm/). +More details can be found in the [WebAssembly reference manual](../../reference-manual/wasm/README.md). ## Combine Languages @@ -265,12 +265,12 @@ To enable interoperability, GraalVM provides the `--polyglot` flag. For example, running `js --jvm --polyglot example.js` executes `example.js` in a polyglot context. If the program calls any code in other supported languages, GraalVM executes that code in the same runtime as the `example.js` application. -For more information on running polyglot applications, see [Polyglot Programming](/reference-manual/polyglot-programming/). +For more information on running polyglot applications, see [Polyglot Programming](../../reference-manual/polyglot-programming.md). ## Native Images With GraalVM you can compile Java bytecode into a platform-specific, self-contained, native executable - a native image - to achieve faster startup and smaller footprint for your application. -The [Native Image](/reference-manual/native-image/) functionality is not available by default, but can be easily installed with the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +The [Native Image](../../reference-manual/native-image/README.md) functionality is not available by default, but can be easily installed with the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install native-image ``` @@ -285,7 +285,7 @@ public class HelloWorld { } ``` -> Note: For compilation `native-image` depends on the local toolchain. Make sure your system meets the [prerequisites](/reference-manual/native-image/#prerequisites). +> Note: For compilation `native-image` depends on the local toolchain. Make sure your system meets the [prerequisites](../../reference-manual/native-image/README.md/#prerequisites). Compile _HelloWorld.java_ to bytecode and then build a native image: ```shell @@ -300,7 +300,7 @@ Invoking it executes the natively compiled code of the `HelloWorld` class as fol Hello, World! ``` -More detailed documentation on this innovative technology is available in the [Native Image reference manual](/reference-manual/native-image/). +More detailed documentation on this innovative technology is available in the [Native Image reference manual](../../reference-manual/native-image/README.md). ## Polyglot Capabilities of Native Images @@ -336,7 +336,7 @@ javac PrettyPrintJSON.java native-image --language:js --initialize-at-build-time PrettyPrintJSON ``` The native image generatation will take several minutes as it does not just build the `PrettyPrintJSON` class, but also builds JavaScript. -Additionally, the image building requires large amounts of physical memory, especially if you build an image with the [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) included, which is the case here. +Additionally, the image building requires large amounts of physical memory, especially if you build an image with the [Truffle language implementation framework](../../graalvm-as-a-platform/graalvm-as-a-platform.md) included, which is the case here. The resulting executable can now perform JSON pretty-printing: ```shell @@ -384,14 +384,14 @@ sys 0m0.016s ## What to Read Next ### New Users -Since this guide is intended mainly for users new to GraalVM, or users who are familiar with GraalVM but may have little experience using it, please consider investigating more complex [Example Applications](/examples/). -We also recommend checking our [GraalVM Team Blog](/blog/). +Since this guide is intended mainly for users new to GraalVM, or users who are familiar with GraalVM but may have little experience using it, please consider investigating more complex [Example Applications](../../examples/examples.md). +We also recommend checking our [GraalVM Team Blog](https://medium.com/graalvm). ### Advanced Users -If you are mostly interested in GraalVM support for a specific language, or want more in-depth details about GraalVM's diverse technologies, proceed to [Reference Manuals](/reference-manual/). +If you are mostly interested in GraalVM support for a specific language, or want more in-depth details about GraalVM's diverse technologies, proceed to [Reference Manuals](../../reference-manual/reference-manuals.md). -If you are looking for the tooling support GraalVM offers, proceed to [Debugging and Monitoring Tools](/tools/). +If you are looking for the tooling support GraalVM offers, proceed to [Debugging and Monitoring Tools](../../tools/tools.md). -If you are considering GraalVM as a platform for your future language or tool implementation, go to [GraalVM as a Platform](/graalvm-as-a-platform/language-implementation-framework/). +If you are considering GraalVM as a platform for your future language or tool implementation, go to [GraalVM as a Platform](../../graalvm-as-a-platform/graalvm-as-a-platform.md). -You can find information on GraalVM's security model in the [Security Guide](/security-guide/), and rich API documentation in [GraalVM SDK Javadoc](https://www.graalvm.org/sdk/javadoc/) and [Truffle Javadoc](https://www.graalvm.org/truffle/javadoc/). +You can find information on GraalVM's security model in the [Security Guide](../../security/security-guide.md), and rich API documentation in [GraalVM SDK Javadoc](https://www.graalvm.org/sdk/javadoc/) and [Truffle Javadoc](https://www.graalvm.org/truffle/javadoc/). diff --git a/docs/getting-started/graalvm-community/linux-aarch64.md b/docs/getting-started/graalvm-community/linux-aarch64.md index e4fb8d221c09..eb9aea7b63eb 100644 --- a/docs/getting-started/graalvm-community/linux-aarch64.md +++ b/docs/getting-started/graalvm-community/linux-aarch64.md @@ -15,7 +15,7 @@ Note: The base GraalVM Community distribution including all components is **expe You can install the GraalVM distribution for Linux ARM64 systems from an archive file (_.tar.gz_). This allows you to install GraalVM for the current user into any location, without affecting other JDK installations. -1. Navigate to the [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Depending on the workload, select Java 11 or 16 based distribution for the Linux AArch64 architecture, and download. +1. Navigate to the [GraalVM Releases repository on GitHub](https://github.com/graalvm/graalvm-ce-builds/releases). Depending on the workload, select Java 11 or 17 based distribution for the Linux AArch64 architecture, and download. 2. Change the directory to the location where you want to install GraalVM, then move the _.tar.gz_ archive to it. 3. Unzip the archive: ```shell @@ -38,6 +38,6 @@ For Oracle GraalVM Enterprise Edition users, find the installation instructions ## Supported Functionalities -The 64-bit GraalVM Community distribution for Linux platforms includes OpenJDK with the GraalVM compiler enabled, the [GraalVM Updater, `gu`](/reference-manual/graalvm-updater/), tool, the JavaScript runtime, and some developer tools (e.g., Chrome inspector based debugger, Visual VM). -Support for [Native Image](/reference-manual/native-image/), Node.js, LLVM and WebAssembly runtimes can be installed with `gu`. +The 64-bit GraalVM Community distribution for Linux platforms includes OpenJDK with the GraalVM compiler enabled, the [GraalVM Updater, `gu`](../../reference-manual/graalvm-updater.md), tool, the JavaScript runtime, and some developer tools (e.g., Chrome inspector based debugger, Visual VM). +Support for [Native Image](../../reference-manual/native-image/README.md), Node.js, LLVM and WebAssembly runtimes can be installed with `gu`. Runtimes for Python, FastR, and Ruby languages are not available in this distribution yet. diff --git a/docs/getting-started/graalvm-community/linux.md b/docs/getting-started/graalvm-community/linux.md index 8b152d3abfda..65bdf352011d 100644 --- a/docs/getting-started/graalvm-community/linux.md +++ b/docs/getting-started/graalvm-community/linux.md @@ -36,20 +36,18 @@ The base distribution of GraalVM Community Edition for Linux (AMD64) platforms i The base installation can be extended with: Tools/Utilities: -* [Native Image](/reference-manual/native-image/) -- a technology to compile an application ahead-of-time into a native executable -* [LLVM toolchain](/reference-manual/llvm/Compiling/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](/reference-manual/java-on-truffle/) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM +* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable +* [LLVM toolchain](../../reference-manual/llvm/Compiling.md/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible -* [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.2 compatible -* [R](/reference-manual/r/) -- GNU R 4.0.3 compatible -* [Wasm](/reference-manual/wasm/) -- WebAssembly (Wasm) +* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible +* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible +* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Community base distribution and must be installed separately. -To assist a user with installation, GraalVM includes -**GraalVM Updater**, a command line utility to install and manage additional -functionalities. Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} -to add any necessary language runtime or utility from above to GraalVM. +To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. +Proceed to the [installation steps](../../reference-manual/graalvm-updater.md/#component-installation) to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/getting-started/graalvm-community/macos.md b/docs/getting-started/graalvm-community/macos.md index 4828d64b6229..6ef34b5b7f57 100644 --- a/docs/getting-started/graalvm-community/macos.md +++ b/docs/getting-started/graalvm-community/macos.md @@ -66,20 +66,18 @@ The base distribution of GraalVM Community Edition for macOS includes OpenJDK wi The base installation can be extended with: Tools/Utilities: -* [Native Image](/reference-manual/native-image/) -- a technology to compile an application ahead-of-time into a native executable -* [LLVM toolchain](/reference-manual/llvm/Compiling/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](/reference-manual/java-on-truffle/) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM +* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable +* [LLVM toolchain](../../reference-manual/llvm/Compiling.md/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible -* [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.2 compatible -* [R](/reference-manual/r/) -- GNU R 4.0.3 compatible -* [Wasm](/reference-manual/wasm/) -- WebAssembly (Wasm) +* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible +* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible +* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Community base distribution and must be installed separately. -To assist a user with installation, GraalVM includes -**GraalVM Updater**, a command line utility to install and manage additional -functionalities. Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} -to add any necessary language runtime or utility from above to GraalVM. +To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. +Proceed to the [installation steps](../../reference-manual/graalvm-updater.md/#component-installation) to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/getting-started/graalvm-community/windows.md b/docs/getting-started/graalvm-community/windows.md index 75bd7134e958..b48ac12cfac7 100644 --- a/docs/getting-started/graalvm-community/windows.md +++ b/docs/getting-started/graalvm-community/windows.md @@ -39,16 +39,17 @@ To run GraalVM Community Edition based on OpenJDK 8u292 on a Windows platform, t ## Supported Functionalities -The GraalVM Community distribution for Windows platforms includes OpenJDK with the GraalVM compiler enabled, the [GraalVM Updater](/reference-manual/graalvm-updater/) tool to install additional functionalities, the JavaScript runtime, and the developer tools (e.g., Chrome inspector based debugger, Profiler, etc.). -Currently, the GraalVM environment on Windows can be extended with [Native Image](/reference-manual/native-image/), [Java on Trufle](/reference-manual/java-on-truffle/), WebAssembly, and Node.js support. +The GraalVM Community distribution for Windows platforms includes OpenJDK with the GraalVM compiler enabled, the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool to install additional functionalities, the JavaScript runtime, and the developer tools (e.g., Chrome inspector based debugger, Profiler, etc.). +Currently, the GraalVM environment on Windows can be extended with [Native Image](../../reference-manual/native-image/README.md), [Java on Trufle](../../reference-manual/java-on-truffle/README.md), WebAssembly, and Node.js support. ## Prerequisites for Using Native Image on Windows -To make use of Native Image on Windows, observe the following recommendations. -The required Microsoft Visual C++ (MSVC) version depends on the JDK version that GraalVM is based on. -For GraalVM based on JDK 8, you will need MSVC 2010 SP1 version. The recommended installation method is using Microsoft Windows SDK 7.1: -1. Download the SDK file `GRMSDKX_EN_DVD.iso` for from [Microsoft](https://www.microsoft.com/en-gb/download). -2. Mount the image by opening `F:\Setup\SDKSetup.exe` directly. +On Windows, Native Image requires Visual Studio Code and Microsoft Visual C++(MSVC). +You can use Visual Studio 2017 version 15.9 or later. +There are two installation options: +- Install the Visual Studio Code Build Tools with the Windows 10 SDK +- Install Visual Studio Code with the Windows 10 SDK -For GraalVM distribution based on JDK 11, you will need MSVC 2017 15.5.5 or later version. +The last prerequisite is the proper [Developer Command Prompt](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt_shortcuts) for your version of [Visual Studio](https://visualstudio.microsoft.com/vs/). +On Windows the `native-image` tool only works when it is executed from the **x64 Native Tools Command Prompt**. -The last prerequisite, common for both distributions, is the proper [Developer Command Prompt](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt_shortcuts) for your version of [Visual Studio](https://visualstudio.microsoft.com/vs/). On Windows the `native-image` tool only works when it is executed from the **x64 Native Tools Command Prompt**. +Step by step instructions on installing Visual Studio Build Tools and Windows 10 SDK, and starting using Native Image can be found [here](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311). diff --git a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md index 24c251a1b064..d6e8179693a8 100644 --- a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md +++ b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md @@ -8,10 +8,10 @@ permalink: /getting-started/ Here you will find information about downloading and installing GraalVM Enterprise, running basic applications with it, and adding support for its accompanying features. Further, you will learn about the polyglot capabilities of GraalVM Enterprise and see how to build platform-specific native executables of JVM-based applications. -If you are new to GraalVM Enterprise or have little experience using it, we recommend starting with the [GraalVM Enterprise Overview](https://docs.oracle.com/en/graalvm/enterprise/21/docs/overview/architecture/) page. +If you are new to GraalVM Enterprise or have little experience using it, we recommend starting with the [GraalVM Enterprise Overview](../../enterprise-overview/architecture-overview.md) page. There you will find information about GraalVM Enterprise's architecture, the distributions available, supported platforms, licensing and support, core and additional features, and much more. -If you have GraalVM Enterprise already installed and have experience using it, you can skip this getting started guide and proceed to the in-depth [Reference Manuals](/reference-manual/). +If you have GraalVM Enterprise already installed and have experience using it, you can skip this getting started guide and proceed to the in-depth [Reference Manuals](../../reference-manual/reference-manuals.md). ## Download GraalVM Enterprise @@ -25,11 +25,11 @@ You can get Oracle GraalVM Enterprise Edition by: Getting GraalVM Enterprise installed and ready-to-go should take a few minutes. Choose your operating system and proceed to the installation steps for your specific platform: -* [Linux](/getting-started/installation-linux/) -* [Linux ARM64](/getting-started/installation-linux-aarch64/) -* [Oracle Linux](/getting-started/oci/compute-instances/) -* [macOS](/getting-started/installation-macos/) -* [Windows](/getting-started/installation-windows/) +* [Linux](installation-linux.md) +* [Linux ARM64](installation-linux-aarch64.md) +* [Oracle Linux](oci/compute-instances.md) +* [macOS](installation-macos.md) +* [Windows](installation-windows.md) ## Start Running Applications @@ -78,9 +78,9 @@ java HelloWorld Hello World! ``` -You can find a collection of larger Java examples on the [Examples Applications](/examples/) page. -For more information on the GraalVM compiler, go to [Compiler](/reference-manual/compiler/). -For more extensive documentation on running Java, proceed to [JVM Languages](/reference-manual/java/). +You can find a collection of larger Java examples on the [Examples Applications](../../examples/examples.md) page. +For more information on the GraalVM compiler, go to [Compiler](../../reference-manual/compiler.md). +For more extensive documentation on running Java, proceed to [JVM Languages](../../reference-manual/java/README.md). ### JavaScript and Node.js GraalVM Enterprise can execute plain JavaScript code, both in REPL mode and by executing script files directly: @@ -95,7 +95,7 @@ Node.js support is not installed by default, but can be easily added with GraalV ```shell gu install nodejs node -v -v15.12.0 +v14.17.6 ``` More than 100,000 npm packages are regularly tested and are compatible with GraalVM Enterprise, including modules like express, react, async, request, browserify, grunt, mocha, and underscore. @@ -127,7 +127,7 @@ Run _app.js_ on GraalVM Enterprise using the `node` command: node app.js ``` -For more detailed documentation and information on compatibility with Node.js, proceed to [JavaScript and Node.js](/reference-manual/js/). +For more detailed documentation and information on compatibility with Node.js, proceed to [JavaScript and Node.js](../../reference-manual/js/README.md). ### LLVM Languages @@ -161,12 +161,12 @@ $LLVM_TOOLCHAIN/clang hello.c -o hello lli hello ``` -For in-depth documentation and more examples of running LLVM bitcode on GraalVM Enterprise, go to [LLVM Languages](/reference-manual/llvm/). +For in-depth documentation and more examples of running LLVM bitcode on GraalVM Enterprise, go to [LLVM Languages](../../reference-manual/llvm/README.md). ### Python With GraalVM Enterprise you can run Python applications in the Python 3 runtime environment. -The support is not available by default, but you can quickly add it to GraalVM using the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +The support is not available by default, but you can quickly add it to GraalVM using the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install python ``` @@ -180,12 +180,12 @@ graalpython >>> exit() ``` -More examples and additional information on Python support in GraalVM can be found in the [Python reference manual](/reference-manual/python/). +More examples and additional information on Python support in GraalVM can be found in the [Python reference manual](../../reference-manual/python/README.md). ### Ruby GraalVM Enterprise provides a high-performance Ruby runtime environment including the `gem` command that allows you to interact with RubyGems, Ruby Bundler, and much more. -The Ruby runtime is not available by default in GraalVM, but can be easily added using the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +The Ruby runtime is not available by default in GraalVM, but can be easily added using the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install ruby ``` @@ -196,7 +196,7 @@ ruby [options] program.rb ``` GraalVM Ruby runtime environment uses the -[same options as the standard implementation of Ruby](/reference-manual/ruby/Options/), +[same options as the standard implementation of Ruby](../../reference-manual/ruby/Options.md), with some additions. For example: ```shell gem install chunky_png @@ -204,12 +204,12 @@ ruby -r chunky_png -e "puts ChunkyPNG::Color.to_hex(ChunkyPNG::Color('mintcream #f5fffa80 ``` -More examples and in-depth documentation can be found in the [Ruby reference manual](/reference-manual/ruby/). +More examples and in-depth documentation can be found in the [Ruby reference manual](../../reference-manual/ruby/README.md). ### R GraalVM Enterprise provides a GNU-compatible environment to run R programs directly or in the REPL mode. -Although the R language support is not available by default, you can add it to GraalVM Enterprise using the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +Although the R language support is not available by default, you can add it to GraalVM Enterprise using the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install R ``` @@ -224,12 +224,12 @@ R version 4.0.3 (FastR) [1] 2 ``` -More examples and in-depth documentation can be found in the [R reference manual](/reference-manual/r/). +More examples and in-depth documentation can be found in the [R reference manual](../../reference-manual/r/README.md). ### WebAssembly With GraalVM Enterprise you can run programs compiled to WebAssembly. -The support is not available by default, but you can add it to GraalVM using the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +The support is not available by default, but you can add it to GraalVM using the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install wasm ``` @@ -264,12 +264,12 @@ Then you can run the compiled WebAssembly binary on GraalVM as follows: wasm --Builtins=wasi_snapshot_preview1 floyd.wasm ``` -More details can be found in the [WebAssembly reference manual](/reference-manual/wasm/). +More details can be found in the [WebAssembly reference manual](../../reference-manual/wasm/README.md). ## Native Images With GraalVM Enterprise you can compile Java bytecode into a platform-specific, self-contained, native executable - a native image - to achieve faster startup and a smaller footprint for your application. -The [Native Image](/reference-manual/native-image/) functionality is not available by default, but can be easily installed with the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +The [Native Image](../../reference-manual/native-image/README.md) functionality is not available by default, but can be easily installed with the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool: ```shell gu install native-image ``` @@ -284,7 +284,7 @@ public class HelloWorld { } ``` -> Note: For compilation `native-image` depends on the local toolchain. Make sure your system meets the [prerequisites](/reference-manual/native-image/#prerequisites). +> Note: For compilation `native-image` depends on the local toolchain. Make sure your system meets the [prerequisites](../../reference-manual/native-image/README.md/#prerequisites). Compile _HelloWorld.java_ to bytecode and then build a native image: ```shell @@ -299,7 +299,7 @@ Invoking it executes the natively compiled code of the `HelloWorld` class as fol Hello, World! ``` -More detailed documentation on this innovative technology is available in the [Native Image reference manual](/reference-manual/native-image/). +More detailed documentation on this innovative technology is available in the [Native Image reference manual](../../reference-manual/native-image/README.md). ## Polyglot Capabilities of Native Images @@ -335,7 +335,7 @@ native-image --language:js --initialize-at-build-time PrettyPrintJSON The native image generatation will take several minutes as it does not just build the `PrettyPrintJSON` class, but also builds JavaScript. Additionally, the image building requires large amounts of physical memory, especially if you build an image with -the [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) included, which is the case here. +the [Truffle language implementation framework](../../graalvm-as-a-platform/graalvm-as-a-platform.md) included, which is the case here. The resulting executable can now perform JSON pretty-printing: @@ -388,24 +388,24 @@ To enable interoperability, GraalVM Enterprise provides the `--polyglot` flag. For example, running `js --jvm --polyglot example.js` executes `example.js` in a polyglot context. If the program calls any code in other supported languages, GraalVM Enterprise executes that code in the same runtime as the `example.js` application. -For more information on running polyglot applications, see [Polyglot Programming](/reference-manual/polyglot-programming/). +For more information on running polyglot applications, see [Polyglot Programming](../../reference-manual/polyglot-programming.md). ## What to Read Next ### New Users Since this guide is intended mainly for users new to GraalVM Enterprise, or users -who are familiar with GraalVM Enterprise but may have little experience using it, consider investigating more complex [Example Applications](/examples/). +who are familiar with GraalVM Enterprise but may have little experience using it, consider investigating more complex [Example Applications](../../examples/examples.md). ### Oracle Cloud Users Oracle Cloud users considering GraalVM Enterprise for their cloud workloads are -invited to read [GraalVM Enterprise on OCI](/getting-started/oci/compute-instances/). +invited to read [GraalVM Enterprise on OCI](oci/compute-instances.md). This page focuses on using GraalVM Enterprise with the Oracle Cloud Infrastructure Virtual Machine compute instance. ### Advanced Users -If you are mostly interested in GraalVM Enterprise support for a specific language, or want more in-depth details about GraalVM Enterprise's diverse features, proceed to [Reference Manuals](/reference-manual/). +If you are mostly interested in GraalVM Enterprise support for a specific language, or want more in-depth details about GraalVM Enterprise's diverse features, proceed to [Reference Manuals](../../reference-manual/reference-manuals.md). -If you are looking for the tooling support GraalVM Enterprise offers, proceed to [Debugging and Monitoring Tools](/tools/). +If you are looking for the tooling support GraalVM Enterprise offers, proceed to [Debugging and Monitoring Tools](../../tools/tools.md). -If you are considering GraalVM Enterprise as a platform for your future language or tool implementation, go to [GraalVM Enterprise as a Platform](/graalvm-as-a-platform/). +If you are considering GraalVM Enterprise as a platform for your future language or tool implementation, go to [GraalVM Enterprise as a Platform](../../graalvm-as-a-platform/graalvm-as-a-platform.md). You can find information on GraalVM Enterprise's security model in the [Security Guide](/security-guide/), and rich API documentation in [GraalVM SDK Javadoc](https://docs.oracle.com/en/graalvm/enterprise/21/sdk/index.html). diff --git a/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md b/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md index 320ef5e8a66d..4f486a86bc16 100644 --- a/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md +++ b/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md @@ -14,7 +14,7 @@ You can install the GraalVM distribution for Linux ARM64 systems from an archive This allows you to install GraalVM for the current user into any location, without affecting other JDK installations. 1. Navigate to [Oracle GraalVM Downloads](https://www.oracle.com/downloads/graalvm-downloads.html?selected_tab=21). -2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **11** or **16** for the Java version, **Linux** for the operating system, and **aarch64** for the architecture. +2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **11** or **17** for the Java version, **Linux** for the operating system, and **aarch64** for the architecture. 3. Click on the **GraalVM Enterprise Core** download link. Before you download a file, you must accept the [Oracle License Agreement](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) in the popup window. 4. When the download button becomes active, press it to start downloading **graalvm-ee-java11-linux-aarch64-.tar.gz**. 5. Change the directory to the location where you want to install GraalVM Enterprise, then move the _.tar.gz_ archive to it. @@ -37,6 +37,6 @@ Optionally, you can specify GraalVM Enterprise as the default JRE or JDK install ## Supported Functionalities -The 64-bit GraalVM Enterprise distribution for Linux platforms includes Oracle JDK with the GraalVM compiler enabled, the [GraalVM Updater, `gu`](/reference-manual/graalvm-updater/) tool, the JavaScript runtime, and some developer tools (e.g., Chrome inspector based debugger, Visual VM). -Support for [Native Image](/reference-manual/native-image/), Node.js, LLVM and WebAssembly runtimes can be installed with `gu`. +The 64-bit GraalVM Enterprise distribution for Linux platforms includes Oracle JDK with the GraalVM compiler enabled, the [GraalVM Updater, `gu`](../../reference-manual/graalvm-updater.md) tool, the JavaScript runtime, and some developer tools (e.g., Chrome inspector based debugger, Visual VM). +Support for [Native Image](../../reference-manual/native-image/README.md), Node.js, LLVM and WebAssembly runtimes can be installed with `gu`. Runtimes for Python, FastR, and Ruby languages are not available in this distribution yet. diff --git a/docs/getting-started/graalvm-enterprise/installation-linux.md b/docs/getting-started/graalvm-enterprise/installation-linux.md index 84c9c4e1a3a2..56fda647c330 100644 --- a/docs/getting-started/graalvm-enterprise/installation-linux.md +++ b/docs/getting-started/graalvm-enterprise/installation-linux.md @@ -8,7 +8,7 @@ permalink: /getting-started/installation-linux/ Follow these steps to install Oracle GraalVM Enterprise Edition on the Linux operating system: 1. Navigate to [Oracle GraalVM Downloads](https://www.oracle.com/downloads/graalvm-downloads.html?selected_tab=21). -2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **16** for the Java version, **Linux** for the operating system, and **amd64** for the architecture. +2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **17** for the Java version, **Linux** for the operating system, and **amd64** for the architecture. 3. Click on the **GraalVM Enterprise Core** download link. Before you download a file, you must accept the [Oracle License Agreement](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) in the popup window. 4. When the download button becomes active, press it to start downloading **graalvm-ee-java-linux-amd64-.tar.gz**. 5. Change the directory to the location where you want to install GraalVM Enterprise, then move the _.tar.gz_ archive to it. @@ -35,20 +35,18 @@ The base distribution of GraalVM Enterprise for Linux (AMD64) platforms includes The base installation can be extended with: Tools/Utilities: -* [Native Image](/reference-manual/enterprise-native-image/) -- a technology to compile an application ahead-of-time into a native executable -* [LLVM toolchain](/reference-manual/llvm/) -- a set of tools and APIs for compiling native programs to bitcode that can be executed on GraalVM Enterprise -* [Java on Truffle](/reference-manual/java-on-truffle/) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Enterprise +* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable +* [LLVM toolchain](../../reference-manual/llvm/Compiling.md/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible -* [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.3 compatible -* [R](/reference-manual/r/) -- GNU R 4.0.3 compatible -* [Wasm](/reference-manual/wasm/) -- WebAssembly (Wasm) +* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible +* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible +* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Enterprise base distribution and must be installed separately. -To assist a user with installation, GraalVM Enterprise includes -**GraalVM Updater**, a command line utility to install and manage additional -functionalities. Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} -to add any necessary language runtime or utility from above to the GraalVM Enterprise core. +To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. +Proceed to the [installation steps](../../reference-manual/graalvm-updater.md/#component-installation) to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/getting-started/graalvm-enterprise/installation-macos.md b/docs/getting-started/graalvm-enterprise/installation-macos.md index 086dc63feb9d..2484107b3f84 100644 --- a/docs/getting-started/graalvm-enterprise/installation-macos.md +++ b/docs/getting-started/graalvm-enterprise/installation-macos.md @@ -17,7 +17,7 @@ the JDK installation path is: Follow these steps to install Oracle GraalVM Enterprise Edition on the macOS operating system: 1. Navigate to[ Oracle GraalVM Downloads](https://www.oracle.com/downloads/graalvm-downloads.html). -2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **16** for the Java version, and **macOS** for the operating system. +2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **17** for the Java version, and **macOS** for the operating system. 3. Click on the **GraalVM Enterprise Core** download link. Before you download a file, you must accept the [Oracle License Agreement](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) in the popup window. 4. When the download button becomes active, press it to start downloading **graalvm-ee-java-darvin-amd64-.tar.gz**. 5. Unzip the archive: @@ -66,20 +66,18 @@ The base distribution of GraalVM Enterprise for macOS platforms includes Oracle The base installation can be extended with: Tools/Utilities: -* [Native Image](/reference-manual/native-image/) -- a technology to compile an application ahead-of-time into a native executable -* [LLVM toolchain](/reference-manual/llvm/) -- a set of tools and APIs for compiling native programs to bitcode that can be executed on GraalVM Enterprise -* [Java on Truffle](/reference-manual/java-on-truffle/) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Enterprise +* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable +* [LLVM toolchain](../../reference-manual/llvm/Compiling.md/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible -* [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.3 compatible -* [R](/reference-manual/r/) -- GNU R 4.0.3 compatible -* [Wasm](/reference-manual/wasm/) -- WebAssembly (Wasm) +* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible +* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible +* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Enterprise base distribution and must be installed separately. -To assist users with installation, GraalVM Enterprise includes -**GraalVM Updater**, a command line utility to install and manage additional -functionalities. Proceed to the [installation steps](/reference-manual/graalvm-updater/#component-installation){:target="_blank"} -to add any necessary language runtime or utility from above to the GraalVM Enterprise core. +To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. +Proceed to the [installation steps](../../reference-manual/graalvm-updater.md/#component-installation) to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/getting-started/graalvm-enterprise/installation-windows.md b/docs/getting-started/graalvm-enterprise/installation-windows.md index 0807a4a50643..78d933cbe076 100644 --- a/docs/getting-started/graalvm-enterprise/installation-windows.md +++ b/docs/getting-started/graalvm-enterprise/installation-windows.md @@ -9,7 +9,7 @@ You can install Oracle GraalVM Enterprise Edition on the Windows operating syste Follow these steps: 1. Navigate to [Oracle GraalVM Downloads](https://www.oracle.com/downloads/graalvm-downloads.html). -2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **16** for the Java version, and **Windows** for the operating system. +2. Select the preferable GraalVM Enterprise version in the Release Version dropdown, **8**, **11**, or **17** for the Java version, and **Windows** for the operating system. 3. Click on the **GraalVM Enterprise Core** download link. Before you download a file, you must accept the [Oracle License Agreement](https://www.oracle.com/downloads/licenses/graalvm-otn-license.html) in the popup window. 4. When the download button becomes active, press it to start downloading graalvm-ee-java-windows-amd64-.zip. 5. Change the directory to the location where you want to install GraalVM Enterprise, then move the _.zip_ archive to it. @@ -36,18 +36,17 @@ Optionally, you can specify GraalVM Enterprise as the JRE or JDK installation in ## Supported Functionalities -The GraalVM Enterprise distribution for Windows platforms includes Oracle JDK with the GraalVM compiler enabled, the [GraalVM Updater](/reference-manual/graalvm-updater/) tool, the JavaScript runtime, and the developer tools (e.g., Chrome inspector based debugger, Profiler, etc.). -Currently, the GraalVM Enterprise environment on Windows can be extended with [Native Image](/reference-manual/native-image/), [Java on Trufle](/reference-manual/java-on-truffle/), WebAssembly, and Node.js support. +The GraalVM Enterprise distribution for Windows platforms includes Oracle JDK with the GraalVM compiler enabled, the [GraalVM Updater](../../reference-manual/graalvm-updater.md) tool, the JavaScript runtime, and the developer tools (e.g., Chrome inspector based debugger, Profiler, etc.). +Currently, the GraalVM Enterprise environment on Windows can be extended with [Native Image](../../reference-manual/native-image/README.md), [Java on Trufle](../../reference-manual/java-on-truffle/README.md), WebAssembly, and Node.js support. ## Prerequisites for Using Native Image on Windows -To make use of Native Image on Windows, observe the following recommendations. The -required Microsoft Visual C++ (MSVC) version depends on the JDK version that -GraalVM is based on. For GraalVM Enterprise distribution based on JDK 8, you will need MSVC -2010 SP1 version. The recommended installation method is using Microsoft Windows -SDK 7.1: -1. Download the SDK file `GRMSDKX_EN_DVD.iso` for from [Microsoft](https://www.microsoft.com/en-gb/download). -2. Mount the image by opening `F:\Setup\SDKSetup.exe` directly. +On Windows, Native Image requires Visual Studio Code and Microsoft Visual C++(MSVC). +You can use Visual Studio 2017 version 15.9 or later. +There are two installation options: +- Install the Visual Studio Code Build Tools with the Windows 10 SDK +- Install Visual Studio Code with the Windows 10 SDK -For GraalVM Enterprise distribution based on JDK 11, you will need MSVC 2017 15.5.5 or later version. +The last prerequisite is the proper [Developer Command Prompt](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt_shortcuts) for your version of [Visual Studio](https://visualstudio.microsoft.com/vs/). +On Windows the `native-image` tool only works when it is executed from the **x64 Native Tools Command Prompt**. -The last prerequisite, common for both distributions, is the proper [Developer Command Prompt](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#developer_command_prompt_shortcuts) for your version of [Visual Studio](https://visualstudio.microsoft.com/vs/). On Windows the `native-image` tool only works when it is executed from the **x64 Native Tools Command Prompt**. +Step by step instructions on installing Visual Studio Build Tools and Windows 10 SDK, and starting using Native Image can be found [here](https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311). diff --git a/docs/getting-started/graalvm-enterprise/oci/compute-instances.md b/docs/getting-started/graalvm-enterprise/oci/compute-instances.md index 341a50daaa77..221d231b9537 100644 --- a/docs/getting-started/graalvm-enterprise/oci/compute-instances.md +++ b/docs/getting-started/graalvm-enterprise/oci/compute-instances.md @@ -79,7 +79,7 @@ Now you have a ready-to-go VM instance with GraalVM Enterprise installed and rea ``` 2. Look up the necessary RPM package name and add it to GraalVM Enterprise with the `yum install command` command. -For example, to install [Native Image](/reference-manual/native-image/), which is a technology to ahead-of-time compile Java code to a standalone native executable, run this command: +For example, to install [Native Image](../../../reference-manual/native-image/README.md), which is a technology to ahead-of-time compile Java code to a standalone native executable, run this command: ```shell sudo yum install graalvm21-ee-11-native-image From f55661d696c912d1fec4fdd0fe8929bf29865493 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 21 Sep 2021 22:50:34 +0300 Subject: [PATCH 388/681] Follow up --- .../graalvm-community/get-started-graalvm-community.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/getting-started/graalvm-community/get-started-graalvm-community.md b/docs/getting-started/graalvm-community/get-started-graalvm-community.md index 71f41f11f9dd..805fb85c7929 100644 --- a/docs/getting-started/graalvm-community/get-started-graalvm-community.md +++ b/docs/getting-started/graalvm-community/get-started-graalvm-community.md @@ -123,8 +123,7 @@ Run _app.js_ on GraalVM Enterprise using the `node` command: node app.js ``` -For more detailed documentation and information on compatibility with Node.js, -proceed to [JavaScript and Node.js](../../reference-manual/js/README.md). +For more detailed documentation and information on compatibility with Node.js, proceed to [JavaScript and Node.js](../../reference-manual/js/README.md). ## Run LLVM Languages From 26487183fc2471520b0483812cc97de802aaf6c6 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 21 Sep 2021 23:18:05 +0300 Subject: [PATCH 389/681] Proofread and update links in docs/graalvm-as-a-platform --- .../architecture-overview.md | 6 +- .../get-started-graalvm-community.md | 4 +- .../get-started-graalvm-enterprise.md | 4 +- .../graalvm-as-a-platform.md | 8 +- .../implement-instrument.md | 103 +++++++++--------- .../implement-language.md | 90 +++++---------- 6 files changed, 93 insertions(+), 122 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index dc47810edac4..6c5e3999851e 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -31,7 +31,7 @@ The preceding diagram illustrates a complete high-level architecture of GraalVM GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](../reference-manual/compiler.md), which is written in Java, to the HotSpot Java Virtual Machine. -In addition to running Java and JVM-based languages, [GraalVM's language implementation framework (Truffle)](../graalvm-as-a-platform/graalvm-as-a-platform.md), makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. +In addition to running Java and JVM-based languages, [GraalVM's language implementation framework (Truffle)](../graalvm-as-a-platform/truffle/README.md), makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. With Truffle, Java and other supported languages can directly interoperate with each other and pass data back and forth in the same memory space. ## Runtime Modes @@ -42,7 +42,7 @@ GraalVM Enterprise is unique as a runtime environment offering several modes of When running programs on the HotSpot JVM, GraalVM defaults to the [GraalVM compiler](../reference-manual/compiler.md) as the top-tier JIT compiler. At runtime, an application is loaded and executed normally on the JVM. The JVM passes bytecodes for Java or any other JVM-native language to the compiler, which compiles that to the machine code and returns it to the JVM. -Interpreters for supported languages, written on top of the [Truffle framework](../graalvm-as-a-platform/graalvm-as-a-platform.md), are themselves Java programs that run on the JVM. +Interpreters for supported languages, written on top of the [Truffle framework](../graalvm-as-a-platform/truffle/README.md), are themselves Java programs that run on the JVM. #### Native Image [Native Image](../reference-manual/native-image/README.md) is an innovative technology that compiles Java code into a standalone binary executable or a native shared library. @@ -50,7 +50,7 @@ The Java bytecode that is processed during the native image build includes all a A generated self-contained native executable is specific to each individual operating systems and machine architecture that does not require a JVM. #### Java on Truffle -[Java on Truffle](../reference-manual/java-on-truffle/README.md) is an implementation of the Java Virtual Machine Specification, built with the [Truffle framework](../graalvm-as-a-platform/graalvm-as-a-platform.md). +[Java on Truffle](../reference-manual/java-on-truffle/README.md) is an implementation of the Java Virtual Machine Specification, built with the [Truffle framework](../graalvm-as-a-platform/truffle/README.md). It is a complete Java VM that includes all core components, implements the same API as the Java Runtime Environment library, and reuses all JARs and native libraries from GraalVM. Java on Trufle is an experimental technology in GraalVM, available as of version 21.0.0. diff --git a/docs/getting-started/graalvm-community/get-started-graalvm-community.md b/docs/getting-started/graalvm-community/get-started-graalvm-community.md index 805fb85c7929..ad0c41664ff9 100644 --- a/docs/getting-started/graalvm-community/get-started-graalvm-community.md +++ b/docs/getting-started/graalvm-community/get-started-graalvm-community.md @@ -335,7 +335,7 @@ javac PrettyPrintJSON.java native-image --language:js --initialize-at-build-time PrettyPrintJSON ``` The native image generatation will take several minutes as it does not just build the `PrettyPrintJSON` class, but also builds JavaScript. -Additionally, the image building requires large amounts of physical memory, especially if you build an image with the [Truffle language implementation framework](../../graalvm-as-a-platform/graalvm-as-a-platform.md) included, which is the case here. +Additionally, the image building requires large amounts of physical memory, especially if you build an image with the [Truffle language implementation framework](../../graalvm-as-a-platform/truffle/README.md) included, which is the case here. The resulting executable can now perform JSON pretty-printing: ```shell @@ -391,6 +391,6 @@ If you are mostly interested in GraalVM support for a specific language, or want If you are looking for the tooling support GraalVM offers, proceed to [Debugging and Monitoring Tools](../../tools/tools.md). -If you are considering GraalVM as a platform for your future language or tool implementation, go to [GraalVM as a Platform](../../graalvm-as-a-platform/graalvm-as-a-platform.md). +If you are considering GraalVM as a platform for your future language or tool implementation, go to [GraalVM as a Platform](../../graalvm-as-a-platform/truffle/README.md). You can find information on GraalVM's security model in the [Security Guide](../../security/security-guide.md), and rich API documentation in [GraalVM SDK Javadoc](https://www.graalvm.org/sdk/javadoc/) and [Truffle Javadoc](https://www.graalvm.org/truffle/javadoc/). diff --git a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md index d6e8179693a8..4a1c4c755809 100644 --- a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md +++ b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md @@ -335,7 +335,7 @@ native-image --language:js --initialize-at-build-time PrettyPrintJSON The native image generatation will take several minutes as it does not just build the `PrettyPrintJSON` class, but also builds JavaScript. Additionally, the image building requires large amounts of physical memory, especially if you build an image with -the [Truffle language implementation framework](../../graalvm-as-a-platform/graalvm-as-a-platform.md) included, which is the case here. +the [Truffle language implementation framework](../../graalvm-as-a-platform/truffle/README.md) included, which is the case here. The resulting executable can now perform JSON pretty-printing: @@ -406,6 +406,6 @@ If you are mostly interested in GraalVM Enterprise support for a specific langua If you are looking for the tooling support GraalVM Enterprise offers, proceed to [Debugging and Monitoring Tools](../../tools/tools.md). -If you are considering GraalVM Enterprise as a platform for your future language or tool implementation, go to [GraalVM Enterprise as a Platform](../../graalvm-as-a-platform/graalvm-as-a-platform.md). +If you are considering GraalVM Enterprise as a platform for your future language or tool implementation, go to [GraalVM Enterprise as a Platform](../../graalvm-as-a-platform/truffle/README.md). You can find information on GraalVM Enterprise's security model in the [Security Guide](/security-guide/), and rich API documentation in [GraalVM SDK Javadoc](https://docs.oracle.com/en/graalvm/enterprise/21/sdk/index.html). diff --git a/docs/graalvm-as-a-platform/graalvm-as-a-platform.md b/docs/graalvm-as-a-platform/graalvm-as-a-platform.md index 10e957fb8e01..f5cd20a924a5 100644 --- a/docs/graalvm-as-a-platform/graalvm-as-a-platform.md +++ b/docs/graalvm-as-a-platform/graalvm-as-a-platform.md @@ -8,21 +8,21 @@ toc_group: graalvm-as-a-platform # GraalVM as a Platform -GraalVM is an open ecosystem and allows users to implement a custom language or tool on top of it with the [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) which offers APIs for writing interpreters for programming languages in the form of Java programs. +GraalVM is an open ecosystem and allows users to implement a custom language or tool on top of it with the [Truffle language implementation framework](truffle/README.md) which offers APIs for writing interpreters for programming languages in the form of Java programs. GraalVM loads and runs the Truffle framework, which itself is a Java program -- a collection of JAR files -- together with interpreters. These get optimized at runtime into efficient machine code for executing loaded programs. -Learn more about this framework from its [reference documentation](/graalvm-as-a-platform/language-implementation-framework/). +Learn more about this framework from its [reference documentation](truffle/README.md). ## Implement Your Language With the [Language API](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/package-summary.html) offered by the Truffle framework, you can implement a language interpreter on top of GraalVM. -To get started, proceed to [Implement Your Language](/graalvm-as-a-platform/implement-language/). +To get started, proceed to [Implement Your Language](implement-language.md). ## Implement Your Tool With the [Instrument API](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/package-summary.html) offered by the Truffle framework, you can create language-agnostic tools like debuggers, profilers, or other instruments on top of GraalVM. -To get started, proceed to [Implement Your Tool](/graalvm-as-a-platform/implement-instrument/). +To get started, proceed to [Implement Your Tool](implement-instrument.md). diff --git a/docs/graalvm-as-a-platform/implement-instrument.md b/docs/graalvm-as-a-platform/implement-instrument.md index 1a2eb62b6290..697d245a9f83 100644 --- a/docs/graalvm-as-a-platform/implement-instrument.md +++ b/docs/graalvm-as-a-platform/implement-instrument.md @@ -14,22 +14,18 @@ Instruments can track very fine-grained, VM-level runtime events to profile, ins ## Simple Tool -To provide an easier starting point for tool developers we have created a -[Simple Tool](https://github.com/graalvm/simpletool) example project. This is a -javadoc-rich Maven project which implements a simple code coverage tool. +To provide an easier starting point for tool developers we have created a [Simple Tool](https://github.com/graalvm/simpletool) example project. +This is a javadoc-rich Maven project which implements a simple code coverage tool. -We recommend cloning the repository and exploring the source code as a starting -point for tool development. The following sections will provide a guided tour of -the steps needed to build and run a GraalVM tool, using Simple Tool source code -as the running example. These sections do not cover all of the features of the -[Instrument API](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/package-summary.html) so we encourage you to check the javadoc for more details. +We recommend cloning the repository and exploring the source code as a starting point for tool development. +The following sections will provide a guided tour of the steps needed to build and run a GraalVM tool, using Simple Tool source code as the running example. +These sections do not cover all of the features of the [Instrument API](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/package-summary.html) so we encourage you to check the javadoc for more details. ### Requirements -As mentioned before, Simple Tool is a code coverage tool. Ultimately, it -should provide the developer with information on what percentage of source code -lines was executed, as well as exactly which lines were executed. With that in -mind, we can define some high-level requirements from our tool: +As mentioned before, Simple Tool is a code coverage tool. +Ultimately, it should provide the developer with information on what percentage of source code lines was executed, as well as exactly which lines were executed. +With that in mind, we can define some high-level requirements from our tool: 1. The tool keeps track of loaded source code. 2. The tool keeps track of executed source code. @@ -40,14 +36,10 @@ mind, we can define some high-level requirements from our tool: The main starting point for tools is subclassing the [TruffleInstrument](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/TruffleInstrument.html) class. Unsurprisingly, the simple tool code base does exactly this, creating the [SimpleCoverageInstrument](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L84) class. -The -[Registration](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/TruffleInstrument.Registration.html) -annotation on the class ensures that the newly created instrument is registered -with the Instrument API, i.e., that it will be automatically -discovered by the framework. It also provides some metadata about the -instrument: ID, name, version, which services the instrument provides, and -whether the instrument is internal or not. In order for this annotation to be -effective the DSL processor needs to process this class. This is, in the case of Simple Tool, done automatically by having the DSL processor as a dependency in the [Maven configuration](https://github.com/graalvm/simpletool/blob/master/pom.xml#L83). +The [Registration](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/TruffleInstrument.Registration.html) annotation on the class ensures that the newly created instrument is registered with the Instrument API, i.e., that it will be automatically discovered by the framework. +It also provides some metadata about the instrument: ID, name, version, which services the instrument provides, and whether the instrument is internal or not. +In order for this annotation to be effective the DSL processor needs to process this class. +This is, in the case of Simple Tool, done automatically by having the DSL processor as a dependency in the [Maven configuration](https://github.com/graalvm/simpletool/blob/master/pom.xml#L83). Now we will look back at the implementation of the `SimpleCoverageInstrument` class, namely which methods from `TruffleInstrument` it overrides. These are [onCreate](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L130), [onDispose](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L182), and [getOptionDescriptors](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L245). @@ -68,6 +60,7 @@ Similarly, in the `onDispose` method we check the options for the state of the ` What does it mean "to enable a tool?" In general, it means that we tell the framework about the events we are interested in and how we want to react to them. Looking at our `enable` method, it does the following: + - First, it defines [SourceSectionFilter](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/SourceSectionFilter.html). This filter is a declarative definition of the parts of the source code we are interested in. In our example, we care about all nodes that are considered expressions, and we do not care about internal language parts. @@ -89,22 +82,14 @@ The instrument keeps a mapping from each `Source` to a [Coverage](https://github ### Execution Event Node Guest languages are implemented as Abstract Syntax Tree (AST) interpreters. -The language implementers annotate certain nodes with tags, which allows us to -select which nodes we are interested in, by using the aforementioned -`SourceSectionFilter`, in a language-agnostic manner. - -The main power of the Instrument API lies in its ability to insert specialised -nodes in the AST which "wrap" the nodes of interest. These nodes are built using -the same infrastructure that the language developers use, and are, from the -perspective of the runtime, indistinguishable from the language nodes. This -means that all of the techniques used to optimize guest languages into such high -performing language implementations are available to the tool developers as -well. +The language implementers annotate certain nodes with tags, which allows us to select which nodes we are interested in, by using the aforementioned `SourceSectionFilter`, in a language-agnostic manner. + +The main power of the Instrument API lies in its ability to insert specialised nodes in the AST which "wrap" the nodes of interest. +These nodes are built using the same infrastructure that the language developers use, and are, from the perspective of the runtime, indistinguishable from the language nodes. +This means that all of the techniques used to optimize guest languages into such high performing language implementations are available to the tool developers as well. More information about these techniques is available in the [language implementation documentation](https://github.com/oracle/graal/tree/master/truffle/docs). -Suffice it to say that for Simple Tool to meet its second requirement, we need to -instrument all expressions with our own node that will notify us when that -expression is executed. +Suffice it to say that for Simple Tool to meet its second requirement, we need to instrument all expressions with our own node that will notify us when that expression is executed. For this task we use the [CoverageNode](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/CoverageNode.java). It is a subclass of [ExecutionEventNode](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/ExecutionEventNode.html) which, as the name implies, is used to instrument events during execution. @@ -113,16 +98,13 @@ This method is invoked when the "wrapped" node returns a value, i.e., is success The implementation is rather simple. We just notify the instrument that the node with this particular `SourceSection` has been executed, and the instrument updates the `Coverage` object in its coverage map. The instrument is notified only once per node, as the logic is guarded by the [flag](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/CoverageNode.java#L60). -The fact that this flag is annotated with [CompilationFinal](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/CompilerDirectives.CompilationFinal.html) and that the call to the instrument is preceded by a call to [transferToInterpreterAndInvalidate()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/CompilerDirectives.html#transferToInterpreterAndInvalidate--) is a standard technique in Truffle which ensures that once this instrumentation is no longer needed (i.e., a node has been executed), the instrumentation is removed from further compilations, along with any performance overhead. +The fact that this flag is annotated with [CompilationFinal](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/CompilerDirectives.CompilationFinal.html) and that the call to the instrument is preceded by a call to [transferToInterpreterAndInvalidate()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/CompilerDirectives.html#transferToInterpreterAndInvalidate--) is a standard technique in Truffle, which ensures that once this instrumentation is no longer needed (i.e., a node has been executed), the instrumentation is removed from further compilations, along with any performance overhead. -In order for the framework to know how to instantiate the `CoverageNode` when it -is needed, we need to provide a factory for it. +In order for the framework to know how to instantiate the `CoverageNode` when it is needed, we need to provide a factory for it. The factory is the [CoverageEventFactory](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/CoverageEventFactory.java), a subclass of [ExecutionEventNodeFactory](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/ExecutionEventNodeFactory.html). This class just ensures that each `CoverageNode` knows the `SourceSection` it is instrumenting by looking it up in the provided [EventContext](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/EventContext.html). -Finally, when we are [enabling the instrument](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L173), -we tell the instrumenter to use our factory to "wrap" the nodes selected by our -filter. +Finally, when we are [enabling the instrument](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L173), we tell the instrumenter to use our factory to "wrap" the nodes selected by our filter. ### Interaction Between Users and Instruments @@ -146,7 +128,7 @@ As mentioned before, Simple Tool is a Maven project. Setting `JAVA_HOME` to a GraalVM installation and running `mvn package` produces a `target/simpletool-.jar`. This is the Simple Tool distribution form. -The [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/) offers a clear separation between the language/tooling code and the application code. +The [Truffle framework](truffle/README.md) offers a clear separation between the language/tooling code and the application code. For this reason, putting the JAR on the class path will not result in the framework realizing a new tool is needed. To achieve this we use `--vm.Dtruffle.class.path.append=/path/to/simpletool-.jar` as is illustrated in a [launcher script for our simple tool](https://github.com/graalvm/simpletool/blob/master/simpletool). This script also shows we can [set the CLI options](https://github.com/graalvm/simpletool/blob/master/simpletool#L19) we specified for Simple Tool. @@ -325,7 +307,10 @@ Execution event nodes can implement certain callback methods to intercept runtim 2. `onReturnValue`: executed after a source code element returns a value. 3. `onReturnExceptional`: executed in case the filtered source code element throws an exception. -Execution event nodes are created on a _per code location_ basis. Therefore, they can be used to store data specific to a given source code location in the instrumented application. As an example, an instrumentation node can simply keep track of all code locations that have already been visited using a node-local flag. Such a node-local `boolean` flag can be used to track the execution of AST nodes in the following way: +Execution event nodes are created on a _per code location_ basis. +Therefore, they can be used to store data specific to a given source code location in the instrumented application. +As an example, an instrumentation node can simply keep track of all code locations that have already been visited using a node-local flag. +Such a node-local `boolean` flag can be used to track the execution of AST nodes in the following way: ```java // To keep track of all source code locations executed @@ -349,10 +334,13 @@ public ExecutionEventNode create(final EventContext ec) { } ``` -As the above code shows, an `ExecutionEventNode` is a valid AST node. This implies that the instrumentation code will be optimized by the GraalVM runtime together with the instrumented application, resulting in minimal instrumentation overhead. Furthermore, this allows instrument developers to use the [Truffle framework compiler directives](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/CompilerDirectives.html) directly from instrumentation nodes. In the example, compiler directives are used to inform the GraalVM compiler that `visited` can be considered compilation-final. +As the above code shows, an `ExecutionEventNode` is a valid AST node. +This implies that the instrumentation code will be optimized by the GraalVM runtime together with the instrumented application, resulting in minimal instrumentation overhead. Furthermore, this allows instrument developers to use the [Truffle framework compiler directives](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/CompilerDirectives.html) directly from instrumentation nodes. +In the example, compiler directives are used to inform the GraalVM compiler that `visited` can be considered compilation-final. -Each instrumentation node is bound to a specific code location. Such locations can be accessed by the agent using the provided [`EventContext`](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/EventContext.html) object. -The context object gives instrumentation nodes access to a variety of information about the current AST nodes being executed. Examples of query APIs available to instrumentation agents through `EventContext` include: +Each instrumentation node is bound to a specific code location. +Such locations can be accessed by the agent using the provided [`EventContext`](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/EventContext.html) object. The context object gives instrumentation nodes access to a variety of information about the current AST nodes being executed. +Examples of query APIs available to instrumentation agents through `EventContext` include: 1. `hasTag`: to query an instrumented node for a certain node `Tag` (e.g., to check if a statement node is also a conditional node). 2. `getInstrumentedSourceSection`: to access the [`SourceSection`](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/source/SourceSection.html) associated with the current node. @@ -376,7 +364,10 @@ SourceSectionFilter inputGeneratingLocations = SourceSectionFilter.newBuilder() instrumenter.attachExecutionEventFactory(sourceSectionFilter, inputGeneratingLocations, factory); ``` -The first source section filter (`sourceSectionFilter`, in the example) is a normal filter equivalent to other filters described before, and is used to identify the source code locations to be monitored. The second section filter, `inputGeneratingLocations`, is used by the agent to specify the _intermediate values_ that should be monitored for a certain source section. Intermediate values correspond to _all_ observable values that are involved in the execution of a monitored code element, and are reported to the instrumentation agent by means of the `onInputValue` callback. As an example, let us assume an agent needs to profile all _operand_ values provided to sum operations (i.e., `+`) in JavaScript: +The first source section filter (`sourceSectionFilter`, in the example) is a normal filter equivalent to other filters described before, and is used to identify the source code locations to be monitored. +The second section filter, `inputGeneratingLocations`, is used by the agent to specify the _intermediate values_ that should be monitored for a certain source section. +Intermediate values correspond to _all_ observable values that are involved in the execution of a monitored code element, and are reported to the instrumentation agent by means of the `onInputValue` callback. +As an example, let us assume an agent needs to profile all _operand_ values provided to sum operations (i.e., `+`) in JavaScript: ```javascript var a = 3; @@ -421,13 +412,19 @@ onEnter - VariableWrite onReturnValue - VariableWrite ``` -The `onInputValue` method can be used in combination with source section filters to intercept very fine-grained execution events such as intermediate values used by language expressions. The intermediate values that are accessible to the Instrumentation framework greatly depend on the instrumentation support provided by each language. Moreover, languages may provide additional metadata associated with language-specific `Tag` classes. +The `onInputValue` method can be used in combination with source section filters to intercept very fine-grained execution events such as intermediate values used by language expressions. +The intermediate values that are accessible to the Instrumentation framework greatly depend on the instrumentation support provided by each language. +Moreover, languages may provide additional metadata associated with language-specific `Tag` classes. ### Altering the Execution Flow of an Application -The instrumentation capabilities that we have presented so far enable users to _observe_ certain aspects of a running application. In addition to passive monitoring of an application's behavior, the Instrument API features support for actively _altering_ the behavior of an application at runtime. Such capabilities can be used to write complex instrumentation agents that affect the behavior of a running application to achieve specific runtime semantics. For example, one could alter the semantics of a running application to ensure that certain methods or functions are never executed (e.g., by throwing an exception when they are called). +The instrumentation capabilities that we have presented so far enable users to _observe_ certain aspects of a running application. +In addition to passive monitoring of an application's behavior, the Instrument API features support for actively _altering_ the behavior of an application at runtime. +Such capabilities can be used to write complex instrumentation agents that affect the behavior of a running application to achieve specific runtime semantics. +For example, one could alter the semantics of a running application to ensure that certain methods or functions are never executed (e.g., by throwing an exception when they are called). -Instrumentation agents with such capabilities can be implemented by leveraging the `onUnwind` callback in execution event listeners and factories. As an example, let's consider the following JavaScript code: +Instrumentation agents with such capabilities can be implemented by leveraging the `onUnwind` callback in execution event listeners and factories. +As an example, let's consider the following JavaScript code: ```javascript function inc(x) { @@ -484,6 +481,10 @@ public static class UniversalAnswerInstrument extends TruffleInstrument { } ``` -When enabled, the instrument will execute its `onReturnValue` callback each time a function call returns. The callback reads the associated source section (using `getInstrumentedSourceSection`) and looks for a specific source code pattern (the function call `inc(c)`, in this case). As soon as such code pattern is found, the instrument throws a special runtime exception, called `UnwindException`, that instructs the Instrumentation framework about a change in the current application's execution flow. The exception is intercepted by the `onUnwind` callback of the instrumentation agent, which can be used to return _any_ arbitrary value to the original instrumented application. +When enabled, the instrument will execute its `onReturnValue` callback each time a function call returns. +The callback reads the associated source section (using `getInstrumentedSourceSection`) and looks for a specific source code pattern (the function call `inc(c)`, in this case). +As soon as such code pattern is found, the instrument throws a special runtime exception, called `UnwindException`, that instructs the Instrumentation framework about a change in the current application's execution flow. +The exception is intercepted by the `onUnwind` callback of the instrumentation agent, which can be used to return _any_ arbitrary value to the original instrumented application. -In the example, all calls to `inc(c)` will return `42` regardless of any application-specific data. A more realistic instrument might access and monitor several aspects of an application, and might not rely on source code locations, but rather on object instances or other application-specific data. +In the example, all calls to `inc(c)` will return `42` regardless of any application-specific data. +A more realistic instrument might access and monitor several aspects of an application, and might not rely on source code locations, but rather on object instances or other application-specific data. diff --git a/docs/graalvm-as-a-platform/implement-language.md b/docs/graalvm-as-a-platform/implement-language.md index 28c182776fc9..de08b6962c7a 100644 --- a/docs/graalvm-as-a-platform/implement-language.md +++ b/docs/graalvm-as-a-platform/implement-language.md @@ -11,7 +11,7 @@ toc_group: graalvm-as-a-platform We have found that the easiest way to get started with implementing your own language is by extending an existing language such as SimpleLanguage. [SimpleLanguage](https://github.com/graalvm/simplelanguage) is a demonstration language built using the [Language API](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/package-summary.html). The SimpleLanguage project provides a showcase on how to use the Language APIs for writing your own language. -It aims to use most of the available [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) (henceforth "Truffle") features, and documents their use extensively with inline source documentation. +It aims to use most of the available [Truffle language implementation framework](truffle/README.md) (henceforth "Truffle") features, and documents their use extensively with inline source documentation. To start, ensure [Maven3](https://maven.apache.org/download.cgi) and GraalVM are available in your system. @@ -29,12 +29,7 @@ For macOS, use: export JAVA_HOME=/path/to/graalvm/Contents/Home export PATH=/path/to/graalvm/Contents/Home/bin:$PATH ``` -4. Execute `mvn package` from the SimpleLanguage folder to build the language. -The command also builds a `slnative` executable in the `simplelanguage/native` -directory and a `sl-component.jar` language component which later can be installed -into GraalVM using the [GraalVM Updater](../reference-manual/graalvm-updater.md) tool. -Please verify ithat the `native-image` plugin is available in your GraalVM distribution -to avoid build failure: +4. Execute `mvn package` from the SimpleLanguage folder to build the language. The command also builds a `slnative` executable in the `simplelanguage/native` directory and a `sl-component.jar` language component which later can be installed into GraalVM using the [GraalVM Updater](../reference-manual/graalvm-updater.md) tool. Please verify ithat the `native-image` plugin is available in your GraalVM distribution to avoid build failure: ```shell gu list gu install native-image @@ -53,7 +48,8 @@ The SimpleLanguage demonstration language is licensed under the [Universal Permi ## IDE Setup -The [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/) provides language-agnostic infrastructure to realize standard IDE features by providing additional APIs. If you would like to experiment with your language and get the benefits of an IDE, consider importing SimpleLanguage as an example. +The [Truffle framework](truffle/README.md) provides language-agnostic infrastructure to realize standard IDE features by providing additional APIs. +If you would like to experiment with your language and get the benefits of an IDE, consider importing SimpleLanguage as an example. ### Eclipse @@ -117,13 +113,10 @@ gu -L install /path/to/sl-component.jar ## SimpleLanguage Native Image -A language built with Truffle can be AOT compiled using [Native Image](../reference-manual/native-image/README.md). Running -`mvn package` in the SimpleLanguage folder also builds a `slnative` executable -in the `native` directory. This executable is the full SimpleLanguage -implementation as a single native application, and has no need for GraalVM in -order to execute SimpleLanguage code. Besides this, a big advantage of using the -native executable when compared to running on GraalVM is the greatly faster -startup time as shown bellow: +A language built with Truffle can be AOT compiled using [Native Image](../reference-manual/native-image/README.md). +Running `mvn package` in the SimpleLanguage folder also builds a `slnative` executable in the `native` directory. +This executable is the full SimpleLanguage implementation as a single native application, and has no need for GraalVM in order to execute SimpleLanguage code. +Besides this, a big advantage of using the native executable when compared to running on GraalVM is the greatly faster startup time as shown bellow: ```shell time ./sl language/tests/HelloWorld.sl == running on org.graalvm.polyglot.Engine@2db0f6b2 @@ -143,23 +136,17 @@ user 0m0.000s sys 0m0.000s ``` -This snipped shows a timed execution of a "Hello World" program using the `sl` -launcher script, which runs SimpleLanguage on GraalVM, using Native -Image. We can see that when running on GraalVM the execution takes 405ms. Since -our SimpleLanguage program does just one print statement, we can conclude that -almost all of this time is spent starting up GraalVM and initializing the -language itself. When using the native executable we see that the execution takes -only 4ms, showing two orders of magnitude faster startup than running on -GraalVM. +This snipped shows a timed execution of a "Hello World" program using the `sl` launcher script, which runs SimpleLanguage on GraalVM, using Native Image. +We can see that when running on GraalVM the execution takes 405ms. +Since our SimpleLanguage program does just one print statement, we can conclude that almost all of this time is spent starting up GraalVM and initializing the language itself. +When using the native executable we see that the execution takes only 4ms, showing two orders of magnitude faster startup than running on GraalVM. For more information on the `native-image` tool consider reading the [reference manual](../reference-manual/native-image/README.md). ### Disable SimpleLanguage Native Image Build -Building the native executable through Maven is attached to the Maven `package` -phase. Since the native executable build can take a bit of time, we provide the -option to skip this build by setting the `SL_BUILD_NATIVE` environment variable -to `false` like so: +Building the native executable through Maven is attached to the Maven `package` phase. +Since the native executable build can take a bit of time, we provide the option to skip this build by setting the `SL_BUILD_NATIVE` environment variable to `false` like so: ```shell export SL_BUILD_NATIVE=false @@ -180,8 +167,7 @@ Skipping the native image build because SL_BUILD_NATIVE is set to false. ## Run SimpleLanguage with the Newest Compiler 21.2.0 -In the outstanding case that you need to execute SimpleLanguage with the newest -version of the GraalVM compiler, please follow these instructions: +In the outstanding case that you need to execute SimpleLanguage with the newest version of the GraalVM compiler, please follow these instructions: 1. Download the latest [JVMCI JDK 8](https://github.com/graalvm/graal-jvmci-8/releases/) and point JAVA_HOME at it: ```shell @@ -215,16 +201,12 @@ mx -v --jdk=jvmci vm -cp /path/to/simplelanguage/launcher/target/launcher-21.2.0 ## Run SimpleLanguage Using Command Line -Executing SimpleLanguage code is normally done with the `sl` script which sets -up the necessary command line depending on whether `JAVA_HOME` points to -GraalVM or another JVM installation. The following subsections describe the -command line for both cases. +Executing SimpleLanguage code is normally done with the `sl` script which sets up the necessary command line depending on whether `JAVA_HOME` points to GraalVM or another JVM installation. +The following subsections describe the command line for both cases. ### Run SimpleLanguage with GraalVM as JAVA_HOME -Assuming `JAVA_HOME` points to the GraalVM installation and that the current -working directory is the `simplelanguage` directory, to run SimpleLanguage one -should execute the following command: +Assuming `JAVA_HOME` points to the GraalVM installation and that the current working directory is the `simplelanguage` directory, to run SimpleLanguage one should execute the following command: ```shell $JAVA_HOME/bin/java \ @@ -233,25 +215,18 @@ $JAVA_HOME/bin/java \ com.oracle.truffle.sl.launcher.SLMain language/tests/Add.sl ``` -In short, we place the launcher JAR on the class path and execute its main -class, but we inform GraalVM of the presence of SimpleLanguage by using the -`-Dtruffle.class.path.append` option and providing it the path to the fat -language JAR. Having the language on a separate class path ensures a strong -separation between the language implementation and its embedding context (in -this case, the launcher). +In short, we place the launcher JAR on the class path and execute its main class, but we inform GraalVM of the presence of SimpleLanguage by using the `-Dtruffle.class.path.append` option and providing it the path to the fat language JAR. +Having the language on a separate class path ensures a strong separation between the language implementation and its embedding context (in this case, the launcher). #### Disable Class Path Separation *NOTE! This should only be used during development.* -For development purposes it is useful to disable the class path separation and enable having the -language implementation on the application class path (for example, for testing +For development purposes it is useful to disable the class path separation and enable having the language implementation on the application class path (for example, for testing the internals of the language). -For the GraalVM distribution based on JDK 8, you can add the `-XX:-UseJVMCIClassLoader` -option. This disables the class path isolation, enabling the language -implementation to be placed on the application class path. The command line can -be as follows: +For the GraalVM distribution based on JDK 8, you can add the `-XX:-UseJVMCIClassLoader` option. +This disables the class path isolation, enabling the language implementation to be placed on the application class path. The command line can be as follows: ```shell $JAVA_HOME/bin/java \ @@ -260,11 +235,11 @@ $JAVA_HOME/bin/java \ com.oracle.truffle.sl.launcher.SLMain language/tests/Add.sl ``` -For the JDK 11-based distribution of GraalVM, the `-XX:-UseJVMCIClassLoader` option -is not valid. The Java Module System isolation is used. You can achieve the same behavior -using `--add-exports` or `--upgrade-module-path`. The latter is preferable. +For the JDK 11-based distribution of GraalVM, the `-XX:-UseJVMCIClassLoader` option is not valid. +The Java Module System isolation is used. You can achieve the same behavior using `--add-exports` or `--upgrade-module-path`. The latter is preferable. -The Language API JAR on Maven Central exports all API packages in its module-info. Apply the `--upgrade-module-path` option together with `-Dgraalvm.locatorDisabled=true` and this JAR to export Language API packages: +The Language API JAR on Maven Central exports all API packages in its module-info. +Apply the `--upgrade-module-path` option together with `-Dgraalvm.locatorDisabled=true` and this JAR to export Language API packages: ```shell -Dgraalvm.locatorDisabled=true --module-path=:${truffle.dir} --upgrade-module-path=${truffle.dir}/truffle-api.jar ``` @@ -273,15 +248,10 @@ A sample POM using `--upgrade-module-path` to export Language API packages can b ### Other JVM Implementations -Unlike GraalVM, which includes all the dependencies needed to run a language -implemented with [Truffle](/graalvm-as-a-platform/language-implementation-framework/), other JVM implementations need additional -JARs to be present on the class path. These are the Language API and GraalVM SDK -JARs available from Maven Central. +Unlike GraalVM, which includes all the dependencies needed to run a language implemented with [Truffle](truffle/README.md), other JVM implementations need additional JARs to be present on the class path. +These are the Language API and GraalVM SDK JARs available from Maven Central. -Assuming `JAVA_HOME` points to a stock JDK installation, and that the current -working directory is the `simplelanguage` directory and the Language API and -GraalVM SDK JARs are present in that directory, one can execute SimpleLanguage -with the following command: +Assuming `JAVA_HOME` points to a stock JDK installation, and that the current working directory is the `simplelanguage` directory and the Language API and GraalVM SDK JARs are present in that directory, one can execute SimpleLanguage with the following command: ```shell $JAVA_HOME/bin/java \ From e8c31d61ffa086d028ca10aa05c5da6fa310c394 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 21 Sep 2021 23:20:36 +0300 Subject: [PATCH 390/681] Proofread and update links in docs/guides --- docs/guides/guides.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/guides/guides.md b/docs/guides/guides.md index cddfe00d279a..ee499535af58 100644 --- a/docs/guides/guides.md +++ b/docs/guides/guides.md @@ -21,10 +21,10 @@ At runtime, an application is loaded and executed normally by the JVM. In order to follow the steps in this guide, you must have GraalVM installed. In case you do not have it installed, getting GraalVM downloaded and ready-to-go should only take a few minutes. Choose your operating system and proceed to the installation steps: -- [Linux](/docs/getting-started/linux/) -- [Linux AArch64](/docs/getting-started/linux-aarch64/) -- [macOS](/docs/getting-started/macos/) -- [Windows](/docs/getting-started/windows/) +- [Linux](../getting-started/graalvm-community/linux.md) +- [Linux AArch64](../getting-started/graalvm-community/linux-aarch64.md) +- [macOS](../getting-started/graalvm-community/macos.md) +- [Windows](../getting-started/graalvm-community/windows.md) For the purpose of this guide, GraalVM Enterprise based on Java 11 distribution for macOS platform is used. To ensure you have successfully installed GraalVM, verify it is available in the `PATH` environment variable and the `JAVA_HOME` points to it. From 9ea0d14a34b95af01907aba8f8e386c194d4e3bb Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 21 Sep 2021 23:29:17 +0300 Subject: [PATCH 391/681] Proofread and update links in docs/introduction.md --- docs/introduction.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/introduction.md b/docs/introduction.md index 65ddeb55c202..bfa72daa728c 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -26,7 +26,7 @@ This page provides an architectural overview of GraalVM and its runtime modes, s GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](https://github.com/oracle/graal/tree/master/compiler), which is written in Java, to the HotSpot Java Virtual Machine. -In addition to running Java and JVM-based languages, GraalVM's [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. +In addition to running Java and JVM-based languages, [GraalVM's language implementation framework (Truffle)](graalvm-as-a-platform/truffle/README.md) makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. With GraalVM Truffle, Java and other supported languages can directly interoperate with each other and pass data back and forth in the same memory space. ## Runtime Modes @@ -34,18 +34,18 @@ With GraalVM Truffle, Java and other supported languages can directly interopera GraalVM is unique as a runtime environment offering several modes of operation: JVM runtime mode, Native Image, Java on Truffle (the same Java applications can be run on either). #### JVM Runtime Mode -When running programs on the HotSpot JVM, GraalVM defaults to the [GraalVM compiler](/reference-manual/compiler/) as the top-tier JIT compiler. +When running programs on the HotSpot JVM, GraalVM defaults to the [GraalVM compiler](reference-manual/compiler.md) as the top-tier JIT compiler. At runtime, an application is loaded and executed normally on the JVM. The JVM passes bytecodes for Java or any other JVM-native language to the compiler, which compiles that to the machine code and returns it to the JVM. -Interpreters for supported languages, written on top of the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/), are themselves Java programs that run on the JVM. +Interpreters for supported languages, written on top of the [Truffle framework](graalvm-as-a-platform/truffle/README.md), are themselves Java programs that run on the JVM. #### Native Image -[Native Image](/reference-manual/native-image/) is an innovative technology that compiles Java code into a standalone binary executable or a native shared library. +[Native Image](reference-manual/native-image/README.md) is an innovative technology that compiles Java code into a standalone binary executable or a native shared library. The Java bytecode that is processed during the native image build includes all application classes, dependencies, third party dependent libraries, and any JDK classes that are required. A generated self-contained native executable is specific to each individual operating systems and machine architecture that does not require a JVM. #### Java on Truffle -[Java on Truffle](/reference-manual/java-on-truffle/) is an implementation of the Java Virtual Machine Specification, built with the [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/). +[Java on Truffle](reference-manual/java-on-truffle/README.md) is an implementation of the Java Virtual Machine Specification, built with the [Truffle language implementation framework](graalvm-as-a-platform/truffle/README.md). It is a complete Java VM that includes all core components, implements the same API as the Java Runtime Environment library, and reuses all JARs and native libraries from GraalVM. Java on Trufle is an experimental technology in GraalVM, available as of version 21.0.0. @@ -55,9 +55,9 @@ GraalVM is available as **GraalVM Enterprise** and **GraalVM Community** edition GraalVM Enterprise is based on Oracle JDK while GraalVM Community is based on OpenJDK. GraalVM is available for Linux, macOS, and Windows platforms on x86 64-bit systems, and for Linux on ARM 64-bit system. -The GraalVM distribution based on Oracle JDK 16 is experimental with [several known limitations](/release-notes/known-issues/). +The GraalVM distribution based on Oracle JDK 17 is experimental with [several known limitations](https://www.graalvm.org/release-notes/known-issues/). Depending on the platform, the distributions are shipped as *.tar.gz* or *.zip* archives. -See the [Getting Started guide](/docs/getting-started/) for installation instructions. +See the [Getting Started guide](getting-started/graalvm-community/get-started-graalvm-community.md) for installation instructions. ## Distribution Components List @@ -77,24 +77,24 @@ The core components enable using GraalVM as a runtime platform for programs writ **Utilities** * JavaScript REPL with the JavaScript interpreter * `lli` tool to directly execute programs from LLVM bitcode -* [GraalVM Updater](/reference-manual/graalvm-updater/) to install additional functionalities +* [GraalVM Updater](reference-manual/graalvm-updater.md) to install additional functionalities ### Additional Components GraalVM core installation can be extended with more languages runtimes and utilities. Tools/Utilities: -* [Native Image](/reference-manual/native-image/) -- a technology to compile an application ahead-of-time into a native executable. -* [LLVM toolchain](/reference-manual/llvm/) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime. -* [Java on Truffle](/reference-manual/java-on-truffle/) -- a JVM implementation built upon the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/) to run Java via a Java bytecode interpreter. +* [Native Image](reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable. +* [LLVM toolchain](reference-manual/llvm/README.md) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime. +* [Java on Truffle](reference-manual/java-on-truffle/README.md) -- a JVM implementation built upon the [Truffle framework](graalvm-as-a-platform/truffle/README.md) to run Java via a Java bytecode interpreter. Runtimes: -* [Node.js](/reference-manual/js/) -- the Node.js 14.16.1 runtime for JavaScript -* [Python](/reference-manual/python/) -- Python 3.8.5 compatible -* [Ruby](/reference-manual/ruby/) -- Ruby 2.7.3 compatible -* [R](/reference-manual/r/) -- GNU R 4.0.3 compatible -* [GraalWasm](/reference-manual/wasm/) -- WebAssembly (Wasm) +* [Node.js](reference-manual/js/README.md) -- the Node.js 14.17.6 runtime for JavaScript +* [Python](reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](reference-manual/ruby/README.md) -- Ruby 2.7.3 compatible +* [R](reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [GraalWasm](reference-manual/wasm/README.md) -- WebAssembly (Wasm) ## Licensing and Support @@ -126,11 +126,11 @@ The following table lists production-ready and experimental features in GraalVM ## What to Read Next -Whether you are new to GraalVM or have little experience using it, continue to [Get Started with GraalVM](/docs/getting-started/). +Whether you are new to GraalVM or have little experience using it, continue to [Get Started with GraalVM](getting-started/graalvm-community/get-started-graalvm-community.md). Install GraalVM on your local machine, try running the examples provided in the guide, or test GraalVM with your workload. -After that we suggest you to look at more complex [Examples Applications](/examples/). +After that we suggest you to look at more complex [Examples Applications](examples/examples.md). -Developers who have GraalVM already installed or have experience using, can skip the getting started guide and proceed to the [Reference Manuals](/reference-manual/) for in-depth coverage of GraalVM technologies. +Developers who have GraalVM already installed or have experience using, can skip the getting started guide and proceed to the [Reference Manuals](reference-manual/reference-manuals.md) for in-depth coverage of GraalVM technologies. To start coding with the GraalVM Polyglot APIs, check out the [GraalVM SDK Java API Reference](http://www.graalvm.org/sdk/javadoc). From 1439006547d9669a414160675992f1b826d6f5ab Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 23 Sep 2021 21:53:06 +0300 Subject: [PATCH 392/681] Proofread and update permalinks to rel paths in graal/docs/tools --- docs/tools/chrome-debugger.md | 4 +- docs/tools/code-coverage.md | 59 ++++++++------------ docs/tools/dap.md | 4 +- docs/tools/graalvm-insight.md | 58 +++++++++----------- docs/tools/ideal-graph-visualizer.md | 80 +++++++++++++--------------- docs/tools/lsp.md | 12 ++--- docs/tools/profiling.md | 58 ++++++++------------ docs/tools/visualvm.md | 72 +++++++++++-------------- docs/tools/vscode/graalvm/README.md | 4 +- docs/tools/vscode/vscode.md | 6 +-- 10 files changed, 152 insertions(+), 205 deletions(-) diff --git a/docs/tools/chrome-debugger.md b/docs/tools/chrome-debugger.md index 5d87871181d2..506e0ac7592d 100644 --- a/docs/tools/chrome-debugger.md +++ b/docs/tools/chrome-debugger.md @@ -8,9 +8,11 @@ redirect_from: /docs/tools/chrome-debugger/ # Chrome Debugger -GraalVM supports debugging of guest language applications and provides a built-in implementation of the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). This allows you to attach compatible debuggers such as [Chrome Developer Tools](https://developers.google.com/web/tools/chrome-devtools/) to GraalVM. +GraalVM supports debugging of guest language applications and provides a built-in implementation of the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). +This allows you to attach compatible debuggers such as [Chrome Developer Tools](https://developers.google.com/web/tools/chrome-devtools/) to GraalVM. To debug guest language applications, pass the `--inspect` option to the command line launcher, as in the following example with a Node.js _HelloWorld_ program: + ```javascript var http = require('http'); diff --git a/docs/tools/code-coverage.md b/docs/tools/code-coverage.md index 5367925cbe33..81d6ae8910ed 100644 --- a/docs/tools/code-coverage.md +++ b/docs/tools/code-coverage.md @@ -7,22 +7,15 @@ permalink: /tools/code-coverage/ # Code Coverage Command Line Tool -As of version 19.3.0, GraalVM provides a **code coverage command line tool** -that lets users record and analyze the source code coverage of a particular execution -of code. +GraalVM provides a **code coverage command line tool** that lets users record and analyze the source code coverage of a particular execution of code. -Code coverage, as a percentage of source code lines, functions, or statements -covered, is an important metric for understanding a particular source code +Code coverage, as a percentage of source code lines, functions, or statements covered, is an important metric for understanding a particular source code execution, and is commonly associated with test quality (test coverage). -Providing a visual coverage overview for individual lines of code shows the -developer which code paths are covered and which are not, giving insight into -the character of the execution which can, for example, inform further testing -efforts. +Providing a visual coverage overview for individual lines of code shows the developer which code paths are covered and which are not, giving insight into the character of the execution which can, for example, inform further testing efforts. -The example application below will be used to demonstrate GraalVM's code -coverage capabilities. This application defines a -`getPrime` function that calculates the n-th prime using a basic prime number -calculator based on the [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) algorithm. It also has a somewhat naive cache of the first 20 prime numbers. +The example application below will be used to demonstrate GraalVM's code coverage capabilities. +This application defines a `getPrime` function that calculates the n-th prime using a basic prime number calculator based on the [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) algorithm. +It also has a somewhat naive cache of the first 20 prime numbers. 1. Copy the following code into a new file named `primes.js`: @@ -96,11 +89,10 @@ Shows what percent of each element was covered during execution /path/to/primes.js | 20.69% | 26.67% | 22.22% -------------------------------------------------------- ``` -The tracer prints a coverage histogram for each source file. You can see that -statement coverage is roughly 20%, line coverage is roughly 26%, and root coverage (the -term "root" covers functions, methods, etc.) is 22.22%. This tells your that our -simple tests are not particularly good at exercising the source code. Next you -will figure out which parts of the code are not covered. +The tracer prints a coverage histogram for each source file. +You can see that statement coverage is roughly 20%, line coverage is roughly 26%, and root coverage (the term "root" covers functions, methods, etc.) is 22.22%. +This tells your that our simple tests are not particularly good at exercising the source code. +Next you will figure out which parts of the code are not covered. 4. Run `js primes.js --coverage --coverage.Output=detailed`. Prepare for a somewhat verbose output. Specifying the output as `detailed` will print all the source code lines with a @@ -175,16 +167,15 @@ p if (n > cache.length) { return calculatePrime(n); } -------------------------------------------------------- ``` -As the legend at the beginning of the output explains, lines that are covered by -the execution are preceded with a `+`. Lines not covered by the execution are -preceded with a `-`. Lines that are covered partially are preceded with `p` (e.g., when an `if` -statement is covered but only one branch is taken, consider the other bench +As the legend at the beginning of the output explains, lines that are covered by the execution are preceded with a `+`. +Lines not covered by the execution are preceded with a `-`. +Lines that are covered partially are preceded with `p` (e.g., when an `if` statement is covered but only one branch is taken, consider the other bench to be incidentally covered). -Looking at the output you can see that the `calculatePrime` function and all its -calls are never executed. Looking again at the assertions and the `getPrime` -function, it becomes clear that our tests always hit the cache. Thus most of the -code is never executed. You can improve on that. +Looking at the output you can see that the `calculatePrime` function and all its calls are never executed. +Looking again at the assertions and the `getPrime` function, it becomes clear that our tests always hit the cache. +Thus most of the code is never executed. +You can improve on that. 5. Add `console.assert(getPrime(30) == 113);` to the end of the `primes.js` file and run `js primes.js --coverage`. Since the new assertion added calls @@ -205,11 +196,9 @@ Code coverage histogram. ## Integrating with Other Tools -The code coverage tool provides ways to integrate with other tools. Running -with `--coverage.Output=lcov` produces output in the commonly used -[lcov](https://linux.die.net/man/1/lcov) format which is used by multiple tools -(e.g., `genhtml`) to display coverage data. Take a look at the next example that -shows how to visualise coverage of a Node.js app with Visual Studio Code. +The code coverage tool provides ways to integrate with other tools. +Running with `--coverage.Output=lcov` produces output in the commonly used [lcov](https://linux.die.net/man/1/lcov) format which is used by multiple tools (e.g., `genhtml`) to display coverage data. +Take a look at the next example that shows how to visualise coverage of a Node.js app with Visual Studio Code. 1. Copy the following code into a new file named `nodeapp.js`: @@ -244,9 +233,7 @@ node --coverage --coverage.Output=lcov \ nodeapp.js ``` -Note that the Code Coverage Highlighter plugin looks for the `lcov.info` file in -the `coverage` directory by default, so direct the output of the code -coverage tool there. +Note that the Code Coverage Highlighter plugin looks for the `lcov.info` file in the `coverage` directory by default, so direct the output of the code coverage tool there. 5. Visit [localhost:3000/](http://localhost:3000/) in your browser, then visit [localhost:3000/shutdown](http://localhost:3000/shutdown) to close the app. @@ -255,6 +242,4 @@ and `coverage` directory and you should be greeted with an image similar to the ![](img/vscode-coverage.png) -If you wish to integrate the data gathered by the GraalVM code coverage tool -with your own visualisation, the `--coverage.Output=json` option results in -the output being a JSON file with the raw data gathered by the tracker. +If you wish to integrate the data gathered by the GraalVM code coverage tool with your own visualisation, the `--coverage.Output=json` option results in the output being a JSON file with the raw data gathered by the tracker. diff --git a/docs/tools/dap.md b/docs/tools/dap.md index c890f7b60aea..42256a1ec8fe 100644 --- a/docs/tools/dap.md +++ b/docs/tools/dap.md @@ -77,10 +77,10 @@ code . 8. Start debugging (F5). The other approach is to use VS Code with the GraalVM extension installed. -Follow the steps described in -[Node.js and JavaScript Debugging](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm#javascript-and-node.js-debugging), and launch the application being debugged directly from VS Code. +Follow the steps described in [Node.js and JavaScript Debugging](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm#javascript-and-node.js-debugging), and launch the application being debugged directly from VS Code. When debugging a guest language application from VS Code, a user can choose a protocol to use by setting the protocol attribute in the corresponding debug configuration to either `chromeDevTools` or `debugAdapter`. To connect to the open DAP port in this scenario, the content of the _launch.json_ should be: + ```json { "version": "0.2.0", diff --git a/docs/tools/graalvm-insight.md b/docs/tools/graalvm-insight.md index 752869b2375c..8bdf45600b1b 100644 --- a/docs/tools/graalvm-insight.md +++ b/docs/tools/graalvm-insight.md @@ -7,22 +7,20 @@ permalink: /tools/graalvm-insight/ # GraalVM Insight -GraalVM Insight is a multipurpose, flexible tool for writing reliable -microservices solutions that traces program runtime behavior and gathers insights. +* [Start Using GraalVM Insight](#start-using-graalvm-insight) +* [Polyglot Tracing](#polyglot-tracing) +* [Inspecting Values](#inspecting-values) -The dynamic nature of the tool helps users to selectively apply tracing pointcuts on -already running applications with no loss of performance. Insight -also provides detailed access to runtime behavior of a program, allowing users to -inspect values and types at invocation or allocation sites. GraalVM Insight further permits users to -modify computed values, interrupt execution, and quickly experiment with -behavioral changes without modifying the application code. +GraalVM Insight is a multipurpose, flexible tool for writing reliable microservices solutions that traces program runtime behavior and gathers insights. + +The dynamic nature of the tool helps users to selectively apply tracing pointcuts on already running applications with no loss of performance. +GraalVM Insight also provides detailed access to runtime behavior of a program, allowing users to inspect values and types at invocation or allocation sites. +The tool further permits users to modify computed values, interrupt execution, and quickly experiment with behavioral changes without modifying the application code. This page provides information on GraalVM Insight as of the 20.1 version. To learn about Insight on versions 20.0 and 19.3, proceed [here](https://github.com/oracle/graal/blob/release/graal-vm/20.0/tools/docs/T-Trace.md). -Note: The GraalVM Insight tool is offered as a technology preview and requires the user to -pass the `--experimental-options` option in order to enable the `--insight` -instrument. +Note: The GraalVM Insight tool is offered as a technology preview and requires the user to pass the `--experimental-options` option in order to enable the `--insight` instrument. ## Start Using GraalVM Insight @@ -48,14 +46,11 @@ Loading 505 characters from [eval]-wrapper Loading 29 characters from [eval] The result: 42 ``` -The _source-tracing.js_ script used the provided `insight` object to -attach a source listener to the runtime. Whenever the script was loaded, the -listener got notified of it and could take an action -- printing the length and -name of the processed script. +The _source-tracing.js_ script used the provided `insight` object to attach a source listener to the runtime. +Whenever the script was loaded, the listener got notified of it and could take an action -- printing the length and name of the processed script. The Insight information can be collected to a print statement or a histogram. -The following _function-histogram-tracing.js_ script counts all method invocations -and dumps the most frequent ones when the execution of a program is over: +The following _function-histogram-tracing.js_ script counts all method invocations and dumps the most frequent ones when the execution of a program is over: ```javascript var map = new Map(); @@ -90,10 +85,9 @@ insight.on('enter', function(ev) { insight.on('close', dumpHistogram); ``` -The `map` is a global variable shared inside of the Insight script that allows the -code to share data between the `insight.on('enter')` function and the `dumpHistogram` -function. The latter is executed when the node process execution is over -(registered via `insight.on('close', dumpHistogram`). Invoke it as: +The `map` is a global variable shared inside of the Insight script that allows the code to share data between the `insight.on('enter')` function and the `dumpHistogram` function. +The latter is executed when the node process execution is over (registered via `insight.on('close', dumpHistogram`). Invoke it as: + ```shell $JAVA_HOME/bin/node --experimental-options --insight=function-histogram-tracing.js --js.print -e "print('The result: ' + 6 * 7)" The result: 42 @@ -120,9 +114,7 @@ The result: 42 ## Polyglot Tracing -The previous examples were written in JavaScript, but due to GraalVM's polyglot -nature, you can take the same instrument and use it in a program written in, -e.g., the Ruby language. +The previous examples were written in JavaScript, but due to GraalVM's polyglot nature, you can take the same instrument and use it in a program written in, e.g., the Ruby language. 1. Create the _source-trace.js_ file: ```javascript @@ -178,10 +170,9 @@ With Ruby: 42 ## Inspecting Values -GraalVM Insight not only allows one to trace where the program execution is happening, -it also offers access to values of local variables and function arguments during -program execution. You can, for example, write an instrument that shows the value of -argument `n` in the function `fib`: +GraalVM Insight not only allows one to trace where the program execution is happening, it also offers access to values of local variables and function arguments during program execution. +You can, for example, write an instrument that shows the value of argument `n` in the function `fib`: + ```javascript insight.on('enter', function(ctx, frame) { print('fib for ' + frame.n); @@ -191,9 +182,9 @@ insight.on('enter', function(ctx, frame) { }); ``` -This instrument uses the second function argument, `frame`, to get access to values of -local variables inside every instrumented function. The above script -also uses `rootNameFilter` to apply its hook only to the function named `fib`: +This instrument uses the second function argument, `frame`, to get access to values of local variables inside every instrumented function. +The above script also uses `rootNameFilter` to apply its hook only to the function named `fib`: + ```javascript function fib(n) { if (n < 1) return 0; @@ -203,9 +194,8 @@ function fib(n) { print("Two is the result " + fib(3)); ``` -When the instrument is stored in a `fib-trace.js` file and the actual code is in -`fib.js`, invoking the following command yields detailed information about the -program execution and parameters passed between function invocations: +When the instrument is stored in a `fib-trace.js` file and the actual code is in `fib.js`, invoking the following command yields detailed information about the program execution and parameters passed between function invocations: + ```shell $JAVA_HOME/bin/node --experimental-options --insight=fib-trace.js --js.print fib.js fib for 3 diff --git a/docs/tools/ideal-graph-visualizer.md b/docs/tools/ideal-graph-visualizer.md index 8c2ab3321b41..0ea34d012602 100644 --- a/docs/tools/ideal-graph-visualizer.md +++ b/docs/tools/ideal-graph-visualizer.md @@ -7,13 +7,17 @@ permalink: /tools/igv/ # Ideal Graph Visualizer -Ideal Graph Visualizer (IGV) is a developer tool allowing users to analyze compilation -graphs and investigate performance issues. The tool is essential for any -language implementers building on top of **Oracle GraalVM Enterprise Edition**. It is -available as a separate download on [Oracle Technology Network](https://www.oracle.com/technetwork/oracle-labs/program-languages/downloads/index.html) and requires accepting the Oracle Technology Network Developer License. +* [Browsing Graphs](#browsing-graphs) +* [Viewing Source Code](#viewing-source-code) +* [Dumping Graphs](#dumping-graphs) + +Ideal Graph Visualizer (IGV) is a developer tool allowing users to analyze compilation graphs and investigate performance issues. +The tool is essential for any language implementers building on top of **Oracle GraalVM Enterprise Edition**. +It is available as a separate download on [Oracle Technology Network](https://www.oracle.com/downloads/graalvm-downloads.html) and requires accepting the Oracle Technology Network Developer License. IGV is developed to view and inspect intermediate representation graphs -- a language-independent intermediate representation (IR) between the source -language and the machine code, generated by the compiler. See [Dumping Graphs](/tools/igv/#dumping-graphs) below. +language and the machine code, generated by the compiler. +See [Dumping Graphs](#dumping-graphs) below. 1. Unzip the downloaded package and enter `bin` directory: ```shell @@ -46,7 +50,8 @@ and connect the `Test.rb` script to the running IGV: gu list ruby --jvm --polyglot --vm.Dgraal.Dump=:1 --vm.Dgraal.PrintGraph=Network Test.rb ``` -This causes GraalVM Enterprise to dump compiler graphs in the IGV format over the network to an IGV process listening on `127.0.0.1:4445`. Once the connection is made, you are able to see the graphs in the Outline window. +This causes GraalVM Enterprise to dump compiler graphs in the IGV format over the network to an IGV process listening on `127.0.0.1:4445`. +Once the connection is made, you are able to see the graphs in the Outline window. Find, e.g., the `java.lang.String.char(int)` folder and open its After Parsing graph by double-clicking. If the node has `sourceNodePosition` property, then the Processing window will attempt to display its location and the entire stacktrace. @@ -58,57 +63,48 @@ Select a node in the graph and press the Go to Source button in the Stack View w ![](img/IGV_add_source.png) -Graphs navigation is also available from the Context menu, enabled by focusing -and right-clicking a specific graph node. The Extract Nodes option will re-render -a graph and display only the selected nodes and their neighbors. +Graphs navigation is also available from the Context menu, enabled by focusing and right-clicking a specific graph node. +The Extract Nodes option will re-render a graph and display only the selected nodes and their neighbors. ![](img/IGV_context_menu.png) -If the graph is larger than the screen, manipulate with the Satellite view button -in the main toolbar to move the viewport rectangle. +If the graph is larger than the screen, manipulate with the Satellite view button in the main toolbar to move the viewport rectangle. ![](img/IGV_satellite_view.png) -For user preference, the graph color scheme is adjustable by editing -the Coloring filter, enabled by default in the left sidebar. +For user preference, the graph color scheme is adjustable by editing the Coloring filter, enabled by default in the left sidebar. ## Viewing Source Code -Source code views can be opened in manual and assisted modes. Once you select a node -in the graph view, the Processing view will open. If the IGV knows where the source code -for the current frame is, the green Go to Source arrow is enabled. If the IGV does not -know where the source is, the line is greyed out and a Looking Glass button appears. +Source code views can be opened in manual and assisted modes. +Once you select a node in the graph view, the Processing view will open. +If the IGV knows where the source code for the current frame is, the green Go to Source arrow is enabled. +If the IGV does not know where the source is, the line is greyed out and a Looking Glass button appears. ![](img/IGV_add_source.png) Press it and select Locate in Java project to locate the correct project in the dialog. The IGV hides projects which do not contain the required source file. The Source Collections serves to display the stand alone roots added by "Add root of sources" general action. -If the source is located using the preferred method (i.e., from a Java project), -its project can be later managed on the Project tab. That one is initially hidden, -but you can display the list of opened projects using Window -> Projects. +If the source is located using the preferred method (i.e., from a Java project), its project can be later managed on the Project tab. +That one is initially hidden, but you can display the list of opened projects using Window -> Projects. ## Dumping Graphs -The IGV tool is developed to allow GraalVM Enterprise language implementers -to optimize their languages assembled with the [Language Implentation Framework](/graalvm-as-a-platform/language-implementation-framework/). As a development -tool it should not be installed to production environments. - -To dump the GraalVM compiler graphs from an embedded Java application to the IGV, -you need to add options to GraalVM-based processes. Depending on the language/VM -used, you may need to prefix the options by `--vm`. See the particular -language's documentation for the details. The main option to add is -`-Dgraal.Dump=:1`. This will dump graphs in an IGV readable format to the local -file system. To send the dumps directly to the IGV over the network, add -`-Dgraal.PrintGraph=Network` when starting a GraalVM instance. Optionally a -port can be specified. Then dumps are sent to the IGV from the running GraalVM on -localhost. If the IGV does not listen on localhost, Options -> Ideal Graph Settings| -Accept Data From Network can be checked. If there is not an IGV instance -listening on `127.0.0.1` or it cannot be connected to, the dumps will be -redirected to the local file system. The file system location is `graal_dumps/` -under the current working directory of the process and can be changed with the -`-Dgraal.DumpPath` option. - -In case an older GraalVM Enterprise is used, you may need to explicitly request that dumps -include the `nodeSourcePosition` property. This is done by adding the -`-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints` options. +The IGV tool is developed to allow GraalVM Enterprise language implementers to optimize their languages assembled with the [Language Implentation Framework](../graalvm-as-a-platform/truffle/README.md). +As a development tool it should not be installed to production environments. + +To dump the GraalVM compiler graphs from an embedded Java application to the IGV, you need to add options to GraalVM-based processes. +Depending on the language/VM used, you may need to prefix the options by `--vm`. +See the particular language's documentation for the details. +The main option to add is `-Dgraal.Dump=:1`. +This will dump graphs in an IGV readable format to the local file system. +To send the dumps directly to the IGV over the network, add `-Dgraal.PrintGraph=Network` when starting a GraalVM instance. +Optionally a port can be specified. +Then dumps are sent to the IGV from the running GraalVM on localhost. +If the IGV does not listen on localhost, Options -> Ideal Graph Settings|Accept Data From Network can be checked. +If there is not an IGV instance listening on `127.0.0.1` or it cannot be connected to, the dumps will be redirected to the local file system. +The file system location is `graal_dumps/` under the current working directory of the process and can be changed with the `-Dgraal.DumpPath` option. + +In case an older GraalVM Enterprise is used, you may need to explicitly request that dumps include the `nodeSourcePosition` property. +This is done by adding the `-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints` options. diff --git a/docs/tools/lsp.md b/docs/tools/lsp.md index f831f89238ad..5ebcc01a9ebd 100644 --- a/docs/tools/lsp.md +++ b/docs/tools/lsp.md @@ -7,13 +7,12 @@ permalink: /tools/lsp/ # Language Server Protocol -GraalVM supports [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) (LSP) for guest languages. It provides features like code-completion, find usages and alike for the client tools -- IDEs like Visual Studio Code. +GraalVM supports [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) (LSP) for guest languages. +It provides features like code-completion, find usages and alike for the client tools -- IDEs like Visual Studio Code. -To start the GraalVM Language Server, pass the `--lsp` option to the command -line launcher as in the following example with a Node.js application. +To start the GraalVM Language Server, pass the `--lsp` option to the command line launcher as in the following example with a Node.js application. -Note: The GraalVM Language Server is offered as a technology preview and requires the -user to pass the `--experimental-options` option for its activation. +Note: The GraalVM Language Server is offered as a technology preview and requires the user to pass the `--experimental-options` option for its activation. ```shell node --experimental-options --lsp app.js @@ -23,7 +22,8 @@ Example app listening on port 3000! ![](img/vscode_cc_1.png) _GraalVM Enterprise-provided code completion for R script, part of the Node.js Polyglot application_ -The GraalVM Language Server itself does not provide the static data usually gathered by parsing the application sources (as these data are sometimes fuzzy in the cases of dynamic languages). Instead, the Language Server was designed to provide the accurate dynamic data gathered from the application runtime. +The GraalVM Language Server itself does not provide the static data usually gathered by parsing the application sources (as these data are sometimes fuzzy in the cases of dynamic languages). +Instead, the Language Server was designed to provide the accurate dynamic data gathered from the application runtime. However, the Language Server could delegate to the existing language servers written specially for the particular languages (using the `--lsp.Delegates` launcher option) and merge the static data returned from these servers with its own dynamic data to a single result. diff --git a/docs/tools/profiling.md b/docs/tools/profiling.md index f5cc19a9e5f3..074829129442 100644 --- a/docs/tools/profiling.md +++ b/docs/tools/profiling.md @@ -7,17 +7,13 @@ permalink: /tools/profiling/ # Profiling Command Line Tools -GraalVM **profiling command line tools** help you optimize your code -through analysis of CPU and memory usage. +GraalVM **profiling command line tools** help you optimize your code through analysis of CPU and memory usage. -Most applications spend 80% of their runtime in 20% of the code. For this -reason, to optimize the code, it is essential to know where the application -spends its time. In this section, we use an example application to demonstrate -the three main profiling capabilities that GraalVM offers: CPU Tracer, CPU -Sampler, and Memory Tracer. +Most applications spend 80% of their runtime in 20% of the code. +For this reason, to optimize the code, it is essential to know where the application spends its time. +In this section, we use an example application to demonstrate the three main profiling capabilities that GraalVM offers: CPU Tracer, CPU Sampler, and Memory Tracer. -This example application uses a basic prime -number calculator based on the [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) +This example application uses a basic prime number calculator based on the [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) algorithm. 1. Copy the following code into a new file named `primes.js`: @@ -90,7 +86,7 @@ algorithm. Total Time: Time spent somewhere on the stack. ---------------------------------------------------------------------------------------------------- Thread[main,5,main] - Name | Total Time || Self Time || Location + Name | Total Time || Self Time || Location ---------------------------------------------------------------------------------------------------- accept | 7330ms 88.8% || 7330ms 88.8% || primes.js~13-22:191-419 :program | 8250ms 100.0% || 420ms 5.1% || primes.js~1-46:0-982 @@ -101,19 +97,18 @@ algorithm. ---------------------------------------------------------------------------------------------------- ``` By default the sampler prints an execution time histogram for each JavaScript function. - You can produce a flame graph in SVG format by doing + You can produce a flame graph in SVG format by doing ```shell js primes.js --cpusampler --cpusampler.Output=flamegraph --cpusampler.OutputFile=primes.svg ``` which should produce something like this - + ![](img/profiler_flamegraph.png) - + You can zoom into the graph by clicking on elements. - By default, CPU sampling takes a sample every 10 milliseconds. From the - result, we can see that roughly 89% of the time is spent - in the `DivisibleByFilter.accept` function. + By default, CPU sampling takes a sample every 10 milliseconds. + From the result, we can see that roughly 89% of the time is spent in the `DivisibleByFilter.accept` function. ```javascript accept(n) { @@ -129,8 +124,7 @@ algorithm. ``` Now use the CPU Tracer to collect execution counts of each statement: -4. Run `js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=*accept` -to collect execution counts for all statements in methods ending with `accept`: +4. Run `js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=*accept` to collect execution counts for all statements in methods ending with `accept`: ```shell js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=*accept Computed 5000 prime numbers. The last 5 are 48563,48571,48589,48593,48611. @@ -154,14 +148,10 @@ to collect execution counts for all statements in methods ending with `accept`: ----------------------------------------------------------------------------------------- ``` - The output shows execution counters for each statement, instead of timing - information. Tracing histograms often provides insights into the behavior - of the algorithm that needs optimization. + The output shows execution counters for each statement, instead of timing information. + Tracing histograms often provides insights into the behavior of the algorithm that needs optimization. -5. Run `js primes.js --experimental-options --memtracer` to display source code locations and -counts of reported allocations. Note that the Memory Tracer tool for capturing allocations is currently an -experimental feature in GraalVM. As such, `--memtracer` must -be preceded by the `--experimental-options` command line option. +5. Run `js primes.js --experimental-options --memtracer` to display source code locations and counts of reported allocations. Note that the Memory Tracer tool for capturing allocations is currently an experimental feature in GraalVM. As such, `--memtracer` must be preceded by the `--experimental-options` command line option. ```shell js primes.js --experimental-options --memtracer Computed 5000 prime numbers. The last 5 are 48563,48571,48589,48593,48611. @@ -179,21 +169,15 @@ be preceded by the `--experimental-options` command line option. ``` - This output shows the number of allocations which were recorded per function. - For each prime number that was computed, the program allocates one object in - `next` and one in `constructor` of `DivisibleByFilter`. Allocations are recorded - independently of whether they could get eliminated by the compiler. + This output shows the number of allocations which were recorded per function. For each prime number that was computed, the program allocates one object in `next` and one in `constructor` of `DivisibleByFilter`. + Allocations are recorded independently of whether they could get eliminated by the compiler. - The GraalVM compiler is particularly powerful in optimizing allocations and can push - allocations into infrequent branches to increase execution performance. The - GraalVM team plans to add information about memory optimizations to the - memory tracer in the future. + The GraalVM compiler is particularly powerful in optimizing allocations and can push allocations into infrequent branches to increase execution performance. + The GraalVM team plans to add information about memory optimizations to the memory tracer in the future. ## Tools Options -Use the `--help:tools` option in all guest language launchers to display -reference information for CPU Sampler, CPU Tracer, and Memory Tracer. - -The current set of available options is as follows: +Use the `--help:tools` option in all guest language launchers to display reference information for CPU Sampler, CPU Tracer, and Memory Tracer. +The current set of available options is as follows. ### CPU Sampler Options diff --git a/docs/tools/visualvm.md b/docs/tools/visualvm.md index fd9a18b21e7c..cb34b024619e 100644 --- a/docs/tools/visualvm.md +++ b/docs/tools/visualvm.md @@ -21,66 +21,59 @@ currently available: To start VisualVM, execute `jvisualvm`. Immediately after startup, the tool shows all locally running Java processes in the Applications area, including the VisualVM process, itself. ### Capture a Heap Dump -To capture a heap dump of, for example, a Ruby application for later analysis, -start your application and let it run for a few seconds to warm up. Then -right-click its process in VisualVM and invoke the Heap Dump action. A -new heap viewer for the Ruby process opens. - -__Note:__ [Native Image](../reference-manual/native-image/README.md) does not implement the JVMTI agent, so triggering heap dump creation from the Applications area is impossible. Apply the `-H:+AllowVMInspection` flag with the `native-image` tool for native image processes. This way your application will handle signals and capture a heap dump when it receives the SIGUSR1 signal. The guest language REPL process must be started also with the `--jvm` flag to monitor it using VisualVM. This functionality is available with [GraalVM Enterprise Edition](https://www.oracle.com/downloads/graalvm-downloads.html). It is not available in GraalVM Community Edition. See the [Generating Native Heap Dumps](../reference-manual/native-image/NativeImageHeapdumpEnterprise.md) page for details on capturing heap dumps from a native image process. +To capture a heap dump of, for example, a Ruby application for later analysis, start your application and let it run for a few seconds to warm up. +Then right-click its process in VisualVM and invoke the Heap Dump action. +A new heap viewer for the Ruby process opens. + +__Note:__ [Native Image](../reference-manual/native-image/README.md) does not implement the JVMTI agent, so triggering heap dump creation from the Applications area is impossible. +Apply the `-H:+AllowVMInspection` flag with the `native-image` tool for native image processes. +This way your application will handle signals and capture a heap dump when it receives the SIGUSR1 signal. +The guest language REPL process must be started also with the `--jvm` flag to monitor it using VisualVM. +This functionality is available with [GraalVM Enterprise Edition](https://www.oracle.com/downloads/graalvm-downloads.html). +It is not available in GraalVM Community Edition. +See the [Generating Native Heap Dumps](../reference-manual/native-image/NativeImageHeapdumpEnterprise.md) page for details on capturing heap dumps from a native image process. ### Analyzing Objects -Initially the Summary view for the Java heap is displayed. To analyze the Ruby -heap, click the leftmost (Summary) dropdown in the Heap Viewer toolbar, choose -the Ruby Heap scope and select the Objects view. Now the heap viewer displays -all Ruby heap objects, aggregated by their type. +Initially the Summary view for the Java heap is displayed. +To analyze the Ruby heap, click the leftmost (Summary) dropdown in the Heap Viewer toolbar, choose the Ruby Heap scope and select the Objects view. +Now the heap viewer displays all Ruby heap objects, aggregated by their type. Expand the Proc node in the Results view to see a list of objects of this type. -Each object displays its logical value as provided by the underlying -implementation. Expand the objects to access their variables and references, -where available. +Each object displays its logical value as provided by the underlying implementation. +Expand the objects to access their variables and references, where available. ![](img/HeapViewer_objects.png) -Now enable the Preview, Variables, and References details by clicking the buttons -in the toolbar, and select the individual _ProcType_ objects. Where available, the -Preview view shows the corresponding source fragment, the Variables view shows -variables of the object, and the References view shows objects referring to the -selected object. +Now enable the Preview, Variables, and References details by clicking the buttons in the toolbar, and select the individual _ProcType_ objects. +Where available, the Preview view shows the corresponding source fragment, the Variables view shows variables of the object, and the References view shows objects referring to the selected object. -Last, use the Presets dropdown in the Heap Viewer toolbar to switch the view -from All Objects to Dominators or GC Roots. To display the heap dominators, -retained sizes must be computed first, which can take a few minutes for the -_server.rb_ example. Select the Objects aggregation in the toolbar to view the -individual dominators or GC roots. +Last, use the Presets dropdown in the Heap Viewer toolbar to switch the view from All Objects to Dominators or GC Roots. +To display the heap dominators, retained sizes must be computed first, which can take a few minutes for the _server.rb_ example. +Select the Objects aggregation in the toolbar to view the individual dominators or GC roots. ![](img/HeapViewer_objects_dominators.png) ### Analyzing Threads -Click the leftmost dropdown in the Heap Viewer toolbar and select the Threads -view for the Ruby heap. The heap viewer now displays the Ruby thread stack -trace, including local objects. The stack trace can alternatively be displayed -textually by clicking the HTML toolbar button. +Click the leftmost dropdown in the Heap Viewer toolbar and select the Threads view for the Ruby heap. +The heap viewer now displays the Ruby thread stack trace, including local objects. The stack trace can alternatively be displayed textually by clicking the HTML toolbar button. ![](img/HeapViewer_thread.png) ### Reading JFR Snapshots -The VisualVM tool bundled with GraalVM 19.2.x and later has the ability to read JFR snapshots -- snapshots taken with JDK Flight Recorder (previously Java Flight Recorder). JFR is a tool for collecting -diagnostic and profiling data about a running Java application. It is integrated -into the Java Virtual Machine (JVM) and causes almost no performance overhead, -so it can be used even in heavily loaded production environments. +The VisualVM tool bundled with GraalVM 19.2.x and later has the ability to read JFR snapshots -- snapshots taken with JDK Flight Recorder (previously Java Flight Recorder). +JFR is a tool for collecting diagnostic and profiling data about a running Java application. +It is integrated into the Java Virtual Machine (JVM) and causes almost no performance overhead, so it can be used even in heavily loaded production environments. To install the JFR support, released as a plugin: 1. Run `/bin/jvisualvm` to start VisualVM; 2. Navigate to Tools > Plugins > Available Plugins to list all available plugins, then install the _VisualVM-JFR_ and _VisualVM-JFR-Generic_ modules. -The JFR snapshots can be opened using either the File > Load action, or by -double-clicking the JFR Snapshots node and adding the snapshot into the JFR -repository, permanently. Please follow the documentation for your Java version to -create JFR snapshots. +The JFR snapshots can be opened using either the File > Load action, or by double-clicking the JFR Snapshots node and adding the snapshot into the JFR +repository, permanently. +Please follow the documentation for your Java version to create JFR snapshots. -The JFR viewer reads all JFR snapshots created from Java 7 onward, and presents the data in typical -VisualVM views familiar to the tool users. +The JFR viewer reads all JFR snapshots created from Java 7 onward, and presents the data in typical VisualVM views familiar to the tool users. ![](img/visualvm_jfr.png) @@ -109,7 +102,4 @@ usage, etc. * Recording tab - lists the recording settings and basic snapshot telemetry like number of events, total recording time, etc. -Note: the support of JDK Flight Recorder is currently experimental. Some advanced features like -analyzing JVM internals, showing event stack traces, or support for creating JFR -snapshots from live processes are not available in this preview version and will -be addressed incrementally in the following releases. +Note: The support of JDK Flight Recorder is currently experimental. Some advanced features like analyzing JVM internals, showing event stack traces, or support for creating JFR snapshots from live processes are not available in this preview version and will be addressed incrementally in the following releases. diff --git a/docs/tools/vscode/graalvm/README.md b/docs/tools/vscode/graalvm/README.md index 2f0ba532c380..10b1036a5887 100644 --- a/docs/tools/vscode/graalvm/README.md +++ b/docs/tools/vscode/graalvm/README.md @@ -216,7 +216,7 @@ This brings the visual Java tooling to VS Code. ![VisualVM and VS Code Integration](images/vscode_visualvm.png) -To get started, you need to get the latest stable GraalVM release using the **Download & Install GraalVM** action from the **Gr** activity view, as described in the [Installation and Setup](README.md#installation-and-setup) section. +To get started, you need to get the latest stable GraalVM release using the **Download & Install GraalVM** action from the **Gr** activity view, as described in the [Installation and Setup](#installation-and-setup) section. Make sure the GraalVM is set as **active**. Once a GraalVM installation is set as active, the Command Palette contains the following commands related to VisualVM: @@ -552,7 +552,7 @@ Once the `solargraph` gem is installed, the Ruby Language Server is automaticall ### Additional Editor Features -Since the easy writing of [polyglot](https://www.graalvm.org/docs/reference-manual/polyglot) applications is one of the defining features of GraalVM, the code completion invoked inside JavaScript sources provides items for `Polyglot.eval(...)`, `Polyglot.evalFile(...)`, and `Java.type(...)` calls. +Since the easy writing of [polyglot applications](https://www.graalvm.org/reference-manual/polyglot-programming/) is one of the defining features of GraalVM, the code completion invoked inside JavaScript sources provides items for `Polyglot.eval(...)`, `Polyglot.evalFile(...)`, and `Java.type(...)` calls. ![Image Code Completion](images/code-completion-js.png) diff --git a/docs/tools/vscode/vscode.md b/docs/tools/vscode/vscode.md index a5dddceafd15..948adab0a8d2 100644 --- a/docs/tools/vscode/vscode.md +++ b/docs/tools/vscode/vscode.md @@ -12,13 +12,13 @@ VS Code is an integrated development environment that provides the embedded Gi The following extensions are available for download from Visual Studio Code Marketplace: -- [**GraalVM Tools for Java**](/tools/vscode/graalvm-extension/) provides a full-fledged support for the Java language and, additionally, enables a polyglot environment in VS Code, making it a comfortable and convenient integrated development environment to work with. +- [**GraalVM Tools for Java**](graalvm/README.md) provides a full-fledged support for the Java language and, additionally, enables a polyglot environment in VS Code, making it a comfortable and convenient integrated development environment to work with. Users can edit, run and debug either single-language applications written in any of the GraalVM-supported languages (Java, JS, Ruby, R, and Python), or polyglot applications without the need to install any other additional extensions. The extension also offers the installation wizard that allows to download and install GraalVM and its optional features directly from the user interface. Get the extension from [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm). -- [**GraalVM Tools for Micronaut**](/tools/vscode/micronaut-extension/) provides full support for developing applications based on the [Micronaut framework](https://micronaut.io/). The extension also enables the [Micronaut Launch](https://micronaut.io/launch/) application that allows you to create Micronaut projects through an interface inside VS Code, in addition to using the console CLI. This extension is integrated with GraalVM to provide all Native Image capabilities. You can generate native images directly from VS Code, and deploy them to a Docker Registry. Get the extension from [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.micronaut). +- [**GraalVM Tools for Micronaut**](micronaut/README.md) provides full support for developing applications based on the [Micronaut framework](https://micronaut.io/). The extension also enables the [Micronaut Launch](https://micronaut.io/launch/) application that allows you to create Micronaut projects through an interface inside VS Code, in addition to using the console CLI. This extension is integrated with GraalVM to provide all Native Image capabilities. You can generate native images directly from VS Code, and deploy them to a Docker Registry. Get the extension from [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.micronaut). -- [**GraalVM Extension Pack for Java**](/tools/vscode/graalvm-extension-pack/) is a collection of extensions that helps users write, debug and test Java, JavaScript, Python, Ruby, R and polyglot applications running on GraalVM, either standalone or using the Micronaut framework. +- [**GraalVM Extension Pack for Java**](graalvm-pack/README.md) is a collection of extensions that helps users write, debug and test Java, JavaScript, Python, Ruby, R and polyglot applications running on GraalVM, either standalone or using the Micronaut framework. GraalVM Extension Pack for Java bundles [GraalVM Tools for Java](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm), [GraalVM Tools for Micronaut](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.micronaut), and [Apache NetBeans Language Server](https://marketplace.visualstudio.com/items?itemName=asf.apache-netbeans-java) extensions. Get the extension pack from [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm-pack). As of GraalVM 21.2.0, the GraalVM Tools for Java extension introduced a new feature - the integration with VisualVM (https://visualvm.github.io), which is the all-in-one Java (and polyglot) monitoring and troubleshooting tool. From 0a9f90728064d869b3c6730dd7b33ff05ec139ea Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 23 Sep 2021 22:08:35 +0300 Subject: [PATCH 393/681] Docs/reference-manuals updated ref links from permalinks to rel paths; Start sentences from a new line --- docs/reference-manual/compiler.md | 10 +- docs/reference-manual/graalvm-updater.md | 102 +++++++----------- docs/reference-manual/polyglot-programming.md | 19 ++-- docs/reference-manual/reference-manuals.md | 26 ++--- 4 files changed, 67 insertions(+), 90 deletions(-) diff --git a/docs/reference-manual/compiler.md b/docs/reference-manual/compiler.md index 66da06569e70..7a267b595390 100644 --- a/docs/reference-manual/compiler.md +++ b/docs/reference-manual/compiler.md @@ -27,7 +27,7 @@ The GraalVM compiler assures performance advantages for highly-abstracted progra Code using more abstraction and modern Java features like Streams or Lambdas will see greater speedups. Low-level code or code that converges to things like I/O, memory allocation, or garbage collection will see less improvement. Consequently, an application running on GraalVM needs to spend less time doing memory management and garbage collection. -For more information on performance tuning, refer to [Compiler Configuration on JVM](/reference-manual/java/options/). +For more information on performance tuning, refer to [Compiler Configuration on JVM](java/Options.md). ## Graph Compilation @@ -37,7 +37,7 @@ A *graph* was selected for this role. The graph can represent similar statements of different languages in the same way, like "if" statements or loops, which makes it possible to mix languages in the same program. The GraalVM compiler can then perform language-independent optimization and generate machine code on this graph. -GraalVM also includes the [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) -- a library, written in Java -- to build interpreters for programming languages, which then run on GraalVM. +GraalVM also includes the [Truffle language implementation framework](../graalvm-as-a-platform/truffle/README.md) -- a library, written in Java -- to build interpreters for programming languages, which then run on GraalVM. These languages can consequently benefit from the optimization possibilities of the GraalVM compiler. The pipeline for such compilation is: @@ -50,9 +50,9 @@ hot (i.e., called many times), it is scheduled for compilation by the compiler. ## Ahead-of-time Compilation -Besides the Truffle framework, GraalVM incorporates its optimizing compiler into an advanced ahead-of-time (AOT) compilation technology -- [Native Image](/reference-manual/native-image/) -- which translates Java and JVM-based code into a native platform executable. +Besides the Truffle framework, GraalVM incorporates its optimizing compiler into an advanced ahead-of-time (AOT) compilation technology -- [Native Image](native-image/README.md) -- which translates Java and JVM-based code into a native platform executable. These native executables start nearly instantaneously, are smaller, and consume less resources of the same Java application, making them ideal for cloud deployments and microservices. -For more information about AOT compilation, go to [Native Image](/reference-manual/native-image/). +For more information about AOT compilation, go to [Native Image](native-image/README.md). ## Compiler Operating Modes @@ -80,7 +80,7 @@ This will produce diagnostic data for every method compiled by the compiler. To refine the set of methods for which diagnostic data is produced, use the `-Dgraal.MethodFilter=.` option. For example, `-Dgraal.MethodFilter=java.lang.String.*,HashMap.get` will produce diagnostic data only for methods in the `java.lang.String` class as well as methods named `get` in a class whose non-qualified name is `HashMap`. -Instead of being written to a file, diagnostic data can also be sent over the network to the [Ideal Graph Visualizer](/tools/igv/). +Instead of being written to a file, diagnostic data can also be sent over the network to the [Ideal Graph Visualizer](../tools/ideal-graph-visualizer.md). This requires the `-Dgraal.PrintGraph=Network` option, upon which the compiler will try to send diagnostic data to _127.0.0.1:4445_. This network endpoint can be configured with the `-Dgraal.PrintGraphHost` and `-Dgraal.PrintGraphPort` options. diff --git a/docs/reference-manual/graalvm-updater.md b/docs/reference-manual/graalvm-updater.md index abf06080ab1a..fd9bd47d4ee3 100644 --- a/docs/reference-manual/graalvm-updater.md +++ b/docs/reference-manual/graalvm-updater.md @@ -31,16 +31,16 @@ The following GraalVM language runtimes and utilities are available for installa Tools/Utilities: -* [Native Image](/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable -* [LLVM toolchain](/llvm/README.md) -- a set of tools and APIs for compiling native programs to bitcode that can be executed on GraalVM -* [Java on Truffle](/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM +* [Native Image](native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable +* [LLVM toolchain](llvm/README.md) -- a set of tools and APIs for compiling native programs to bitcode that can be executed on GraalVM +* [Java on Truffle](java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](/reference-manual/js/) -- Node.js 14.16.1 compatible -* [Python](/python/README.md) -- Python 3.8.5-compatible -* [Ruby](/ruby/README.md) -- Ruby 2.7.3-compatible -* [R](/r/README.md) -- GNU R 4.0.3-compatible -* [Wasm](/wasm/README.md) -- WebAssembly (Wasm) +* [Node.js](js/README.md) -- Node.js 14.16.1 compatible +* [Python](python/README.md) -- Python 3.8.5-compatible +* [Ruby](ruby/README.md) -- Ruby 2.7.3-compatible +* [R](r/README.md) -- GNU R 4.0.3-compatible +* [Wasm](wasm/README.md) -- WebAssembly (Wasm) GraalVM Updater verifies whether or not the version of a component is appropriate for the current GraalVM installation. Components are released for each GraalVM distribution with respective updates, and those downloaded for previous release(s) cannot be used with newer ones. @@ -63,21 +63,16 @@ gu available ```shell gu install ruby ``` -GraalVM Updater first downloads the list of components, then uses the -information in the list to download the actual component package, then installs -it. To see more verbose output during the installation, like the download -progress bar, print versions, and dependency information, use the `-v` -(`--verbose`) switch. - -If a component being installed depends on another component, GraalVM Updater will -search the catalog to find an appropriate dependency and install it as well. If -the required components cannot be found, installation will fail. - -When using custom catalog URLs, it is possible, for a convenience, to set -the environment variable `GRAALVM_CATALOG` pointing to the custom catalog's URL. -GraalVM Updater will use the URL defined by `GRAALVM_CATALOG` in preference to -the builtin ones. You may setup the environment variable in startup or profile -scripts. + +GraalVM Updater first downloads the list of components, then uses the information in the list to download the actual component package, then installs it. +To see more verbose output during the installation, like the download progress bar, print versions, and dependency information, use the `-v` (`--verbose`) switch. + +If a component being installed depends on another component, GraalVM Updater will search the catalog to find an appropriate dependency and install it as well. +If the required components cannot be found, installation will fail. + +When using custom catalog URLs, it is possible, for a convenience, to set the environment variable `GRAALVM_CATALOG` pointing to the custom catalog's URL. +GraalVM Updater will use the URL defined by `GRAALVM_CATALOG` in preference to the builtin ones. +You may setup the environment variable in startup or profile scripts. Note: If you need, for some reason to set the `GRAALVM_HOME` environment variable, it may affect `gu` operation. If it is set, it should point to the intended GraalVM installation, same as `JAVA_HOME` and `PATH`. @@ -243,9 +238,8 @@ GraalVM Updater common options: * `-v, --verbose`: enable verbose output. Print versions and dependency information * `--version`: print version -Oracle GraalVM Enterprise Edition users might need to pass an -additional verification step to login to the Oracle components repository. GraalVM -Updater tool provides options for that: +Oracle GraalVM Enterprise Edition users might need to pass an additional verification step to login to the Oracle components repository. +GraalVM Updater tool provides options for that: * `--public-key / -k `: set the path to a custom GPG public key path * `--username/-U`: enter a username @@ -260,34 +254,25 @@ Runtime options: ## Configure Proxies -If GraalVM Updater needs to reach the component catalog, or download a component -package, it may need to pass through the HTTP/HTTPS proxy, if the network uses one. On -_macOS_, the proxy settings are automatically obtained from the OS. On _Linux_, -ensure that the `http_proxy` and `https_proxy` environment variables are set -appropriately before launching the `gu` tool. Refer to the distribution -and/or desktop environment documentation for the details. +If GraalVM Updater needs to reach the component catalog, or download a component package, it may need to pass through the HTTP/HTTPS proxy, if the network uses one. +On _macOS_, the proxy settings are automatically obtained from the OS. +On _Linux_, ensure that the `http_proxy` and `https_proxy` environment variables are set appropriately before launching the `gu` tool. +Refer to the distribution and/or desktop environment documentation for the details. -GraalVM Updater intentionally does not support an option to disable certificate -or hostname verification, for security reasons. A user may try to add a proxy's -certificate to the GraalVM default security trust store. A user can also -download a component manually to a folder, and then use `gu -L install /path/to/file` or `gu -C /path/to/download/dir install component` to install from a local filesystem. +GraalVM Updater intentionally does not support an option to disable certificate or hostname verification, for security reasons. +A user may try to add a proxy's certificate to the GraalVM default security trust store. +A user can also download a component manually to a folder, and then use `gu -L install /path/to/file` or `gu -C /path/to/download/dir install component` to install from a local filesystem. ### Working without Internet Access -If your machine cannot access and download the catalog and components from -the Internet, either because it is behind a proxy, or for security reasons, -GraalVM Updater can install components from a local directory, or a directory on -a network share accessible on the target machine. +If your machine cannot access and download the catalog and components from the Internet, either because it is behind a proxy, or for security reasons, +GraalVM Updater can install components from a local directory, or a directory on a network share accessible on the target machine. -You need to prepare a directory, download all components that you want to install -and their dependencies (in case they require other GraalVM components to work) into -that directory. +You need to prepare a directory, download all components that you want to install and their dependencies (in case they require other GraalVM components to work) into that directory. -Then you can use `gu -L install /path/to/file` (where the `-L` option instructs to use local files, -equivalent to `--local-file` or `--file`). Adding the `-D` option will instruct GraalVM Updater -to look for potential dependencies in the directory next to the -installable file. Additionally, `gu -C /path/to/download/dir install component` can be used, with the specified -directory contents acting as a catalog of components. +Then you can use `gu -L install /path/to/file` (where the `-L` option instructs to use local files, equivalent to `--local-file` or `--file`). +Adding the `-D` option will instruct GraalVM Updater to look for potential dependencies in the directory next to the installable file. +Additionally, `gu -C /path/to/download/dir install component` can be used, with the specified directory contents acting as a catalog of components. Note that with `gu -L` you need to specify the component's file name, while when using `gu -C `, the component name must be used: ```shell @@ -300,13 +285,10 @@ gu -C /tmp/instalables install ruby ## Replace Components and Files -A component may be only installed once. GraalVM Updater refuses to install a -component if a component with the same ID is already installed. However, the -installed component can be replaced. GraalVM Updater first uninstalls the -component and then installs a new package. +A component may be only installed once. GraalVM Updater refuses to install a component if a component with the same ID is already installed. +However, the installed component can be replaced. GraalVM Updater first uninstalls the component and then installs a new package. -To replace a component, use the `-r` -option, and the `-L` (`--local-file` or `--file`) option to treat parameters as local filename of a packaged component: +To replace a component, use the `-r` option, and the `-L` (`--local-file` or `--file`) option to treat parameters as local filename of a packaged component: ```shell gu install -L -r component.jar gu install -r ruby @@ -314,18 +296,16 @@ gu install -r ruby The process is the same as if `gu remove` is run first and `gu install` next. -GraalVM Updater also refuses to overwrite existing files if the -to-be-installed and existing versions differ. There are cases when refreshing -file contents may be needed, such as if they were modified or damaged. In this case, use the `-o` option: +GraalVM Updater also refuses to overwrite existing files if the to-be-installed and existing versions differ. +There are cases when refreshing file contents may be needed, such as if they were modified or damaged. +In this case, use the `-o` option: ```shell gu install -L -o component.jar gu install -o ruby ``` -GraalVM Updater will then instruct the user to replace the contained files of a -component. By default, it will not alter anything. Alternatively, use the `-f` -(`--force`) option, which disables most of the checks, and allows the user to -install non-matching versions. +GraalVM Updater will then instruct the user to replace the contained files of a component. +By default, it will not alter anything. Alternatively, use the `-f` (`--force`) option, which disables most of the checks, and allows the user to install non-matching versions. ### Troubleshooting diff --git a/docs/reference-manual/polyglot-programming.md b/docs/reference-manual/polyglot-programming.md index fb8074f062cc..752c3584e3fd 100644 --- a/docs/reference-manual/polyglot-programming.md +++ b/docs/reference-manual/polyglot-programming.md @@ -14,20 +14,17 @@ permalink: /reference-manual/polyglot-programming/ * [Passing Options Programmatically](#passing-options-programmatically) * [Passing Options Using JVM Arguments](#passing-options-using-jvm-arguments) -GraalVM allows users to write polyglot applications that seamlessly -pass values from one language to another by means of the [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) (henceforth "Truffle"). +GraalVM allows users to write polyglot applications that seamlessly pass values from one language to another by means of the [Truffle language implementation framework](../graalvm-as-a-platform/truffle/README.md) (henceforth "Truffle"). Truffle is a Java library for building programming languages implementations as interpreters for self-modifying Abstract Syntax Trees. When writing a language interpreter with Truffle, it will automatically use the GraalVM compiler as a just-in-time compiler for the language. By having access to this framework, a Ruby application, for example, can run on the same JVM as a Java application. Also, a host JVM-based language and a guest language can directly interoperate with each other and pass data back and forth in the same memory space. -In order to provide foreign polyglot values in the languages implemented with Truffle, the so-called _polyglot interoperability protocol_ has been developed. This -interoperability protocol consists of a set of standardized messages that every -language implements and uses for foreign polyglot values. The protocol allows -GraalVM to support interoperability between any combination of languages without -requiring them to know of each other. For more details, proceed to the -[High-Performance Cross-Language Interoperability in a Multi-Language Runtime](http://dx.doi.org/10.1145/2816707.2816714) paper. +In order to provide foreign polyglot values in the languages implemented with Truffle, the so-called _polyglot interoperability protocol_ has been developed. +This interoperability protocol consists of a set of standardized messages that every language implements and uses for foreign polyglot values. +The protocol allows GraalVM to support interoperability between any combination of languages without requiring them to know of each other. +For more details, proceed to the [High-Performance Cross-Language Interoperability in a Multi-Language Runtime](http://dx.doi.org/10.1145/2816707.2816714) paper. Throughout this section you learn how to combine multiple languages using GraalVM Polyglot APIs. @@ -41,12 +38,12 @@ Ensure you set up GraalVM before you begin. The below examples work: * on a JVM, by passing `--polyglot --jvm`. * on native launchers with `--polyglot` (e.g., `js --polyglot`). - It might be required to [rebuild images](/reference-manual/graalvm-updater/#rebuild-images) to access languages installed with `gu`. + It might be required to [rebuild images](graalvm-updater.md/#rebuild-images) to access languages installed with `gu`. * with native executables (e.g., `native-image --language:js`). For native launchers and native executables using Java as a Target Language and accessing classes other than Java arrays, it is required to recompile the image and provide -a [reflection configuration file](/reference-manual/native-image/Reflection/). +a [reflection configuration file](native-image/Reflection.md). Note: To start an application with LLVM as a Target Language, make sure to precompile the _polyglot.c_ file provided below. @@ -201,7 +198,7 @@ polyglot --jvm polyglot.js polyglot.R polyglot.rb ``` We have also included a basic experimental shell for multiple languages called the _Polyglot Shell_. -It is useful to quickly test the interactivity of languages implemented with the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/). +It is useful to quickly test the interactivity of languages implemented with the [Truffle framework](../graalvm-as-a-platform/truffle/README.md). This is how you can start it: ```shell diff --git a/docs/reference-manual/reference-manuals.md b/docs/reference-manual/reference-manuals.md index 969593093a0d..3c1e33cd879d 100644 --- a/docs/reference-manual/reference-manuals.md +++ b/docs/reference-manual/reference-manuals.md @@ -14,25 +14,25 @@ environment for their workloads. ## Technologies -[Native Image](/reference-manual/native-image/) - learn in detail about Native Image: GraalVM's innovative technology that can ahead-of-time compile Java code to a self-contained native executable. +[Native Image](native-image/README.md) - learn in detail about Native Image: GraalVM's innovative technology that can ahead-of-time compile Java code to a self-contained native executable. -[Compiler](/reference-manual/compiler/) - learn about the uniqueness of the GraalVM compiler and its advantages. +[Compiler](compiler.md) - learn about the uniqueness of the GraalVM compiler and its advantages. -[Updater](/reference-manual/graalvm-updater/) - learn how to add more capabilities and upgrade the core GraalVM installation. +[Updater](graalvm-updater.md) - learn how to add more capabilities and upgrade the core GraalVM installation. -[Polyglot Programming](/reference-manual/polyglot-programming/) - learn how to write polyglot applications and allow languages to directly interoperate with each other in the same memory space. +[Polyglot Programming](polyglot-programming.md) - learn how to write polyglot applications and allow languages to directly interoperate with each other in the same memory space. -[Embedding Languages](/reference-manual/embed-languages/) - learn how to embed polyglot applications in Java host applications or native images. +[Embedding Languages](embedding/embed-languages.md) - learn how to embed polyglot applications in Java host applications or native images. ## Specific Languages If you are mostly interested in the GraalVM support for a specific language, here you can find the most extensive documentation: -* [Java](/reference-manual/java/) -* [Java on Truffle](/reference-manual/java-on-truffle/) -* [JavaScript and Node.js](/reference-manual/js/) -* [LLVM Languages](/reference-manual/llvm/) -* [Python](/reference-manual/python/) -* [R](/reference-manual/r/) -* [Ruby](/reference-manual/ruby/) -* [WebAssembly](/reference-manual/wasm/) +* [Java](java/README.md) +* [Java on Truffle](java-on-truffle/README.md) +* [JavaScript and Node.js](js/README.md) +* [LLVM Languages](llvm/README.md) +* [Python](python/README.md) +* [R](r/README.md) +* [Ruby](ruby/README.md) +* [WebAssembly](wasm/README.md) From 7d272da3ce44ecbeec24cd51aea3807d9cb41e82 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 23 Sep 2021 22:39:20 +0300 Subject: [PATCH 394/681] docs/embedding, docs/java, docs/java-on-truffle, docs/llvm, docs/wasm update ref links to rel paths; start sentences from a new line --- .../embedding/embed-languages.md | 6 +- .../embedding/sandbox-options.md | 2 +- .../reference-manual/java-on-truffle/Demos.md | 8 +- docs/reference-manual/java-on-truffle/FAQ.md | 2 +- .../java-on-truffle/HotSwapPluginAPI.md | 6 +- .../java-on-truffle/ImplementationDetails.md | 8 +- .../java-on-truffle/Interoperability.md | 2 +- .../java-on-truffle/README.md | 20 +-- docs/reference-manual/java/Operations.md | 126 +++++++----------- docs/reference-manual/java/README.md | 2 +- docs/reference-manual/llvm/Compatibility.md | 18 +-- docs/reference-manual/llvm/Compiling.md | 42 +++--- docs/reference-manual/llvm/Debugging.md | 15 +-- .../reference-manual/llvm/Interoperability.md | 21 +-- docs/reference-manual/llvm/NativeExecution.md | 18 +-- docs/reference-manual/llvm/README.md | 13 +- docs/reference-manual/wasm/README.md | 6 +- 17 files changed, 125 insertions(+), 190 deletions(-) diff --git a/docs/reference-manual/embedding/embed-languages.md b/docs/reference-manual/embedding/embed-languages.md index 24bc455db339..6f5c07cd083a 100644 --- a/docs/reference-manual/embedding/embed-languages.md +++ b/docs/reference-manual/embedding/embed-languages.md @@ -31,7 +31,7 @@ beneath each code example to choose between JavaScript, R, Ruby, and Python. Ensure you set up GraalVM before you begin. ## Compile and Run a Polyglot Application -GraalVM can run polyglot applications written in any language implemented with the [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/). +GraalVM can run polyglot applications written in any language implemented with the [Truffle language implementation framework](../../graalvm-as-a-platform/truffle/README.md). These languages are henceforth referenced as **guest languages**. Complete the steps in this section to create a sample polyglot @@ -543,12 +543,12 @@ public class Main { public static void main(String[] args) { try (Context outer = Context.newBuilder() .allowAllAccess(true) - .build()) { + .build()) { outer.eval("js", "inner = Java.type('org.graalvm.polyglot.Context').create()"); outer.eval("js", "value = inner.eval('js', '({data:42})')"); int result = outer.eval("js", "value.data").asInt(); outer.eval("js", "inner.close()"); - + System.out.println("Valid " + (result == 42)); } } diff --git a/docs/reference-manual/embedding/sandbox-options.md b/docs/reference-manual/embedding/sandbox-options.md index 116e08e0aef6..2c20f3904650 100644 --- a/docs/reference-manual/embedding/sandbox-options.md +++ b/docs/reference-manual/embedding/sandbox-options.md @@ -6,7 +6,7 @@ The following document describes how to configure sandbox resource limits using In general all resource limit options are prefixed with `sandbox` option group and they can be listed using the help of any language launcher provided in GraalVM e.g. `js --help:tools`. Polyglot options can be provided through the language launcher, using the polyglot embedding API of the Graal SDK, or on the JVM using a system property. -For better understanding of the examples it is recommended to read the [polyglot embedding guide](/reference-manual/embed-languages/) of the reference manual first. +For better understanding of the examples it is recommended to read the [polyglot embedding guide](embed-languages.md) of the reference manual first. Currently all sandbox options are experimental therefore in these examples it is assumed that experimental options are enabled (e.g. with `--experimental-options`). The options are a best effort approach to limiting resource usage of guest applications. diff --git a/docs/reference-manual/java-on-truffle/Demos.md b/docs/reference-manual/java-on-truffle/Demos.md index 16f73280241d..6e1af7f10350 100644 --- a/docs/reference-manual/java-on-truffle/Demos.md +++ b/docs/reference-manual/java-on-truffle/Demos.md @@ -131,7 +131,7 @@ GraalVM Native Image technology allows compiling applications ahead-of-time (AOT The main trade off for using Native Image is that the analysis and compilation of your program happens under the closed world assumption, meaning the static analysis needs to process all bytecode which will ever be executed in the application. This makes using some language features like dynamic class loading or reflection tricky. -Java on Truffle is a JVM implementation of a JVM bytecode interpreter, built on the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/). +Java on Truffle is a JVM implementation of a JVM bytecode interpreter, built on the [Truffle framework](../../graalvm-as-a-platform/truffle/README.md). It is essentially a Java application, as are the Truffle framework itself and the GraalVM JIT compiler. All three of them can be compiled ahead-of-time with `native-image`. Using Java on Truffle for some parts of your application makes it possible to isolate the required dynamic behaviour and still use the native image on the rest of your code. @@ -144,9 +144,9 @@ It is a REPL capable of evaluating Java code and consists of two parts: This design naturally fits the point we are trying to illustrate. We can build a native executable of the JShell's UI part, and make it include Java on Truffle to run the code dynamically specified at run time. Prerequisites: -* [GraalVM 21.0](/downloads/) -* [Native Image](/reference-manual/native-image/#install-native-image) -* [Java on Truffle](/reference-manual/java-on-truffle/#install-java-on-truffle) +* [GraalVM 21.0](https://www.graalvm.org/downloads/) +* [Native Image](../native-image/README.md/#install-native-image) +* [Java on Truffle](README.md/#install-java-on-truffle) 1. Clone the [project](https://github.com/graalvm/graalvm-demos) with the demo applications and navigate to the `espresso-jshell` directory: diff --git a/docs/reference-manual/java-on-truffle/FAQ.md b/docs/reference-manual/java-on-truffle/FAQ.md index b54113ff9670..8020dd6535f8 100644 --- a/docs/reference-manual/java-on-truffle/FAQ.md +++ b/docs/reference-manual/java-on-truffle/FAQ.md @@ -14,7 +14,7 @@ That means it can only run a Java program once it has been compiled to Java byte In the GraalVM family, this is similar to WebAssembly or the LLVM interpreter: while both can run C programs, they have to be complied by a C compiler first. ### Does Java running on Truffle run on HotSpot too? -Like other languages implemented with the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/), it can run both as a native image or on top of HotSpot. +Like other languages implemented with the [Truffle framework](../../graalvm-as-a-platform/truffle/README.md), it can run both as a native image or on top of HotSpot. Running on top of HotSpot is currently only possible on Linux. We plan to extend this capability to macOS and Windows platforms also. diff --git a/docs/reference-manual/java-on-truffle/HotSwapPluginAPI.md b/docs/reference-manual/java-on-truffle/HotSwapPluginAPI.md index 55891a5abf89..3f755bab2d7b 100644 --- a/docs/reference-manual/java-on-truffle/HotSwapPluginAPI.md +++ b/docs/reference-manual/java-on-truffle/HotSwapPluginAPI.md @@ -7,7 +7,7 @@ permalink: /reference-manual/java-on-truffle/hotswap-plugin/ # Truffle on Java HotSwap Plugin API -With Java on Truffle you can benefit from enhanced HotSwap [capabilites](/reference-manual/java-on-truffle/demos/#enhanced-hotswap-capabilities-with-java-on-truffle) that allow the code to evolve naturally during development without the need for restarting a running application. +With Java on Truffle you can benefit from enhanced HotSwap [capabilites](Demos.md/#enhanced-hotswap-capabilities-with-java-on-truffle) that allow the code to evolve naturally during development without the need for restarting a running application. ​ While code reloading (HotSwap) is a powerful tool, it is not sufficient to reflect all kinds of changes, e.g., changes to annotations, framework-specific changes such as implemented services or beans. For these things the code often needs to be executed to reload configurations or contexts before the changes are fully reflected in the running instance. @@ -18,7 +18,7 @@ The main design principle is that you can register various HotSwap listeners tha Examples include the ability to re-run a static initializer, a generic post HotSwap callback and hooks when implementations for a certain service provider changes. ​ **Note**: The HotSwap Plugin API is under development and more fine-grained registration of HotSwap listeners are likely to be added upon requests from the community. -You are welcomed to send enhancement requests to help shape the API through our community support [channels](/community/). +You are welcomed to send enhancement requests to help shape the API through our community support [channels](https://www.graalvm.org/community/). Review the HotSwap Plugin API by going through a running example that will enable more powerful reloading support on [Micronaut](https://micronaut.io/). ​ @@ -138,7 +138,7 @@ Here is a sample application created from the tutorial ["Creating your first Mic Example's sources can be downloaded as a ready-made Gradle project from [here](https://guides.micronaut.io/latest/micronaut-creating-first-graal-app-gradle-java.zip). Download, unzip and open the project in your IDE. -Before you proceed, make sure that you have Java on Truffle [installed](/reference-manual/java-on-truffle/#install-java-on-truffle) and set the GraalVM as the project SDK. +Before you proceed, make sure that you have Java on Truffle [installed](README.md/#install-java-on-truffle) and set the GraalVM as the project SDK. ​ 1. In your IDE navigate to the root `build.gradle` within the sample project. Add: diff --git a/docs/reference-manual/java-on-truffle/ImplementationDetails.md b/docs/reference-manual/java-on-truffle/ImplementationDetails.md index 02b49e1b5ae7..a5a83ccb56fe 100644 --- a/docs/reference-manual/java-on-truffle/ImplementationDetails.md +++ b/docs/reference-manual/java-on-truffle/ImplementationDetails.md @@ -21,7 +21,7 @@ Java on Truffle is a minified Java VM that implements all core components of a V * Java Debug Wire Protocol (JDWP) Java on Truffle reuses all JARs and native libraries from GraalVM. -All native libraries and methods are loaded/accessed/called via [Truffle Native Function Interface (JNI)](https://www.graalvm.org/graalvm-as-a-platform/language-implementation-framework/NFI/). +All native libraries and methods are loaded/accessed/called via [Truffle Native Function Interface (JNI)](../../graalvm-as-a-platform/truffle/NFI.md). JNI handles are implemented in Java on Truffle, e.g., all Truffle NFI methods only receive and return primitives. Some methods are substituted for performance, e.g., `Math.sqrt`, `System.arraycopy`, avoiding the expensive transition to native. @@ -33,8 +33,8 @@ This mode is not used when running in a native image since there will be no conf * Java on Truffle does not implement the [JVM Tool Interface (JVMTI)](https://docs.oracle.com/en/java/javase/11/docs/specs/jvmti.html). As a result, it does not support the `-agentlib`, or `-agentpath` VM options. * Java on Truffle does not implement the `java.lang.instrument` interface. As a result it does not support the `-javaagent` VM option. -* Java on Truffle currently uses the standard native libraries from the Java core library. This requires allowing a polyglot `Context` native access. Because of the way these libraries are loaded (via [Truffle NFI](https://www.graalvm.org/graalvm-as-a-platform/language-implementation-framework/NFI/)), running on top of HotSpot only works on Linux (with `glibc`). Running as part of a native image works on Linux, Windows, and macOS but it currently limited to one context. +* Java on Truffle currently uses the standard native libraries from the Java core library. This requires allowing a polyglot `Context` native access. Because of the way these libraries are loaded (via [Truffle NFI](../../graalvm-as-a-platform/truffle/NFI.md)), running on top of HotSpot only works on Linux (with `glibc`). Running as part of a native image works on Linux, Windows, and macOS but it currently limited to one context. * Support for [Java Management Extensions (JMX)](https://docs.oracle.com/javase/tutorial/jmx/index.html) is partial and some methods might return partial data. -* The [Debugger Protocol Implementation (JDWP)](https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/jdwp-spec.html) lacks some capabilities compared to HotSpot. It will correctly report the supported [capabilities](https://docs.oracle.com/javase/8/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Capabilities). In particular actions that require to enumerate all Java objects are not supported. However it does support a few hot reloading cases that HotSpot does not. See [Enhanced HotSwap Capabilities with Java on Truffle](/reference-manual/java-on-truffle/demos/#enhanced-hotswap-capabilities-with-java-on-truffle). +* The [Debugger Protocol Implementation (JDWP)](https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/jdwp-spec.html) lacks some capabilities compared to HotSpot. It will correctly report the supported [capabilities](https://docs.oracle.com/javase/8/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Capabilities). In particular actions that require to enumerate all Java objects are not supported. However it does support a few hot reloading cases that HotSpot does not. See [Enhanced HotSwap Capabilities with Java on Truffle](Demos.md/#enhanced-hotswap-capabilities-with-java-on-truffle). * When the `java.MultiThreaded` option is set to "false", [reference processing](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/package-summary.html) will not happen. Depending on the application, this could create resource leaks. Note that this option is set to "false" automatically if Java on Truffle runs in a context where a single-threaded language is enabled (e.g., JavaScript). -* Java on Truffle does not support the [Polyglot API](https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/package-summary.html) yet. However, it provides a guest Java Polyglot API, described in `polyglot.jar`. For more information, see [Interoperability with Truffle Languages](/reference-manual/java-on-truffle/interoperability/). +* Java on Truffle does not support the [Polyglot API](https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/package-summary.html) yet. However, it provides a guest Java Polyglot API, described in `polyglot.jar`. For more information, see [Interoperability with Truffle Languages](Interoperability.md). diff --git a/docs/reference-manual/java-on-truffle/Interoperability.md b/docs/reference-manual/java-on-truffle/Interoperability.md index 4c4e24b27587..2cd16b77f0cc 100644 --- a/docs/reference-manual/java-on-truffle/Interoperability.md +++ b/docs/reference-manual/java-on-truffle/Interoperability.md @@ -7,7 +7,7 @@ permalink: /reference-manual/java-on-truffle/interoperability/ # Interoperability with Truffle Languages -Java on Truffle allows you to interface other "Truffle" languages (languages which interpreters are implemented with the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/)) to create polyglot programs -- programs written in more than one language. +Java on Truffle allows you to interface other "Truffle" languages (languages which interpreters are implemented with the [Truffle framework](../../graalvm-as-a-platform/truffle/README.md)) to create polyglot programs -- programs written in more than one language. This guide describes how to load code written in foreign languages, how to export and import objects between languages, how to use Java on Truffle objects from a foreign language, how to use foreign objects from Java on Truffle, and how to embed in host Java. diff --git a/docs/reference-manual/java-on-truffle/README.md b/docs/reference-manual/java-on-truffle/README.md index 6dfe6681fbc4..5adec74167a6 100644 --- a/docs/reference-manual/java-on-truffle/README.md +++ b/docs/reference-manual/java-on-truffle/README.md @@ -7,14 +7,14 @@ permalink: /reference-manual/java-on-truffle/ # Java on Truffle -Using GraalVM, you can run Java applications normally [on the JVM](/reference-manual/java/), in [Native Image](/reference-manual/native-image/), and now on Truffle. +Using GraalVM, you can run Java applications normally [on the JVM](../java/README.md), in [Native Image](../native-image/README.md), and now on Truffle. Java on Truffle is an implementation of the Java Virtual Machine Specification, [Java SE 8](https://docs.oracle.com/javase/specs/jvms/se8/html/index.html) and [Java SE 11](https://docs.oracle.com/javase/specs/jvms/se11/html/index.html), built upon GraalVM as a Truffle interpreter. It is a minified Java VM that includes all core components of a VM, implements the same API as the Java Runtime Environment library (libjvm.so), and reuses all JARs and native libraries from GraalVM. -See the [Implementation Details](/reference-manual/java-on-truffle/implementation/) for more information. +See the [Implementation Details](ImplementationDetails.md) for more information. The project name behind this implementation is "Espresso". Its open source version is available on [GitHub](https://github.com/oracle/graal/tree/master/espresso). -The Java on Truffle execution mode runs Java via a Java bytecode interpreter, implemented with the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/) – an open-source library for writing interpreters for programming languages. +The Java on Truffle execution mode runs Java via a Java bytecode interpreter, implemented with the [Truffle framework](../../graalvm-as-a-platform/truffle/README.md) – an open-source library for writing interpreters for programming languages. Now Java can be executed by the same principle as other languages in the GraalVM ecosystem (JavaScript, Ruby, Python, R), directly interoperate with those languages, and pass data back and forth in the same memory space. Besides complete language interoperability, with Java on Truffle you can: @@ -28,8 +28,8 @@ It is available as of version 21.0.0. ## Install Java on Truffle -To run Java on Truffle, you need to have [GraalVM installed](/docs/getting-started/#install-graalvm). -The Java on Truffle runtime is not available by default, but can be easily added to GraalVM using the [GraalVM Updater tool](/reference-manual/graalvm-updater/). +To run Java on Truffle, you need to have [GraalVM installed](../../getting-started/graalvm-community/get-started-graalvm-community.md). +The Java on Truffle runtime is not available by default, but can be easily added to GraalVM using the [GraalVM Updater tool](../graalvm-updater.md). For GraalVM Community Edition users, run the following command to install Java on Truffle from the GitHub catalog: ```shell @@ -81,7 +81,7 @@ You can still influence the performance by passing the following options to `jav * `--engine.MultiTier=true` to enable multi-tier compilation; * `--engine.Inlining=false` in combination with `--java.InlineFieldAccessors=true` to make the compilation faster, in exchange for slower performance. -The `--vm.XX:` syntax ensures the option is passed to the underlying [native image VM](https://www.graalvm.org/reference-manual/native-image/HostedvsRuntimeOptions). +The `--vm.XX:` syntax ensures the option is passed to the underlying [native image VM](../native-image/HostedvsRuntimeOptions.md). When using the `-XX:` syntax, the VM first checks if there is such an option in the Java on Truffle runtime. If there is none, it will try to apply this option to the underlying native image VM. This might be important for options such as `MaxDirectMemorySize` which can be set independently at both levels: `-XX:MaxDirectMemorySize=256M` controls how much native memory can be reserved by the Java program running on Truffle (the guest VM), while `--vm.XX:MaxDirectMemorySize=256M` controls how much native memory can be reserved by native image (the host VM). @@ -167,11 +167,11 @@ It should show GraalVM as project's JRE and VM options should include `-truffle ## What to Read Next Java on Truffle enables a seamless Java interoperability with other languages in the GraalVM ecosystem. -Check the [Interoperability with Truffle Languages guide](/reference-manual/java-on-truffle/interoperability/) to learn how to load code written in foreign languages, export and import objects between languages, how to use Java-on-Truffle objects from a foreign language and vice versa to create powerful polyglot programs. +Check the [Interoperability with Truffle Languages guide](Interoperability.md) to learn how to load code written in foreign languages, export and import objects between languages, how to use Java-on-Truffle objects from a foreign language and vice versa to create powerful polyglot programs. -To learn about the implementation approach, project's current status, and known limitations proceed to [Implementation Details](/reference-manual/java-on-truffle/implementation/). +To learn about the implementation approach, project's current status, and known limitations proceed to [Implementation Details](ImplementationDetails.md). You can already run some large applications like the Eclipse IDE, Scala or other languages REPLs, etc. in the Java on Truffle execution mode. -We recommend having a look at the collection of [Demo Applications](/reference-manual/java-on-truffle/demos/). +We recommend having a look at the collection of [Demo Applications](Demos.md). -If you have a question, check the available [FAQs](/reference-manual/java-on-truffle/faq/), or reach us directly over the **#espresso** channel in [GraalVM Slack](https://www.graalvm.org/slack-invitation/). +If you have a question, check the available [FAQs](FAQ.md), or reach us directly over the **#espresso** channel in [GraalVM Slack](https://www.graalvm.org/slack-invitation/). diff --git a/docs/reference-manual/java/Operations.md b/docs/reference-manual/java/Operations.md index d295a86b7e84..88064a7c2416 100644 --- a/docs/reference-manual/java/Operations.md +++ b/docs/reference-manual/java/Operations.md @@ -9,75 +9,55 @@ permalink: /reference-manual/java/operations/ ## Running the GraalVM Compiler in Native Image vs on the JVM -When running the GraalVM compiler on the JVM, it goes through the same warm-up phase that the -rest of the Java application does. That is, it is first interpreted before -its hot methods are compiled. This can translate into slightly longer times -until the application reaches peak performance when compared to the native compilers -in the JVM such as C1 and C2. - -To address the issue of taking longer to reach to peak performance, **libgraal** -was introduced -- a shared library, produced using [Native Image](../native-image/README.md) to ahead-of-time compile the compiler itself. That means the GraalVM Enterprise -compiler is deployed as a native shared library. - -In this mode, the -compiler uses memory separate from the HotSpot heap, and it runs compiled from -the start. Therefore it has execution properties similar to other native HotSpot -compilers such as C1 and C2. Currently, this is the **default mode** of -operation. It can be disabled with `-XX:-UseJVMCINativeLibrary`. +When running the GraalVM compiler on the JVM, it goes through the same warm-up phase that the rest of the Java application does. +That is, it is first interpreted before its hot methods are compiled. +This can translate into slightly longer times until the application reaches peak performance when compared to the native compilers in the JVM such as C1 and C2. + +To address the issue of taking longer to reach to peak performance, **libgraal** was introduced -- a shared library, produced using [Native Image](../native-image/README.md) to ahead-of-time compile the compiler itself. +That means the GraalVM Enterprise compiler is deployed as a native shared library. + +In this mode, the compiler uses memory separate from the HotSpot heap, and it runs compiled from the start. +Therefore it has execution properties similar to other native HotSpot compilers such as C1 and C2. +Currently, this is the **default mode** of operation. +It can be disabled with `-XX:-UseJVMCINativeLibrary`. ## Measuring Performance The first thing to be sure of when measuring performance is to ensure the JVM is using the GraalVM Enterprise compiler. -In the GraalVM binary, the JVM is configured to use the GraalVM compiler -as the top tier compiler by default. You can confirm this by adding `-Dgraal.ShowConfiguration=info` -to the command line. It will produce a line of output similar to the one below -when the compiler is initialized: +In the GraalVM binary, the JVM is configured to use the GraalVM compiler as the top tier compiler by default. +You can confirm this by adding `-Dgraal.ShowConfiguration=info` to the command line. +It will produce a line of output similar to the one below when the compiler is initialized: ```shell Using Graal compiler configuration 'community' provided by org.graalvm.compiler.hotspot.CommunityCompilerConfigurationFactory loaded from jar:file:/Users/dsimon/graal/graal/compiler/mxbuild/dists/graal.jar!/org/graalvm/compiler/hotspot/CommunityCompilerConfigurationFactory.class ``` -Note: The GraalVM compiler is only initialized on the first top-tier JIT compilation request -so if your application is short-lived, you may not see this output. +Note: The GraalVM compiler is only initialized on the first top-tier JIT compilation request so if your application is short-lived, you may not see this output. -Optimizing JVM-based applications is a science in itself. The compilation may not -even be a factor in the case of poor performance as the problem may -lie in any other part of the VM (I/O, garbage collection, threading, etc), or in -a poorly written application or 3rd party library code. For this reason, it's -worth utilizing the [JDK Mission Control](https://www.oracle.com/java/technologies/jdk-mission-control.html) tool chain to -diagnose the application behavior. +Optimizing JVM-based applications is a science in itself. The compilation may not even be a factor in the case of poor performance as the problem may +lie in any other part of the VM (I/O, garbage collection, threading, etc), or in a poorly written application or 3rd party library code. +For this reason, it's worth utilizing the [JDK Mission Control](https://www.oracle.com/java/technologies/jdk-mission-control.html) tool chain to diagnose the application behavior. -You can also compare performance against the native top-tier compiler in the JVM by -adding `-XX:-UseJVMCICompiler` to the command line. +You can also compare performance against the native top-tier compiler in the JVM by adding `-XX:-UseJVMCICompiler` to the command line. -If you observe a significant performance regression when using the GraalVM compiler, please -open an issue on GitHub. Attaching a Java Flight Recorder log and instructions -to reproduce the issue makes investigation easier and thus the -chances of a fix higher. Even better is if you can submit a [JMH](http://openjdk.java.net/projects/code-tools/jmh/) -benchmark that represents the hottest parts of your application (as identified -by a profiler). This allows us to very quickly pinpoint missing optimization -opportunities or to offer suggestions on how to restructure the code to -avoid or reduce performance bottlenecks. +If you observe a significant performance regression when using the GraalVM compiler, please open an issue on GitHub. +Attaching a Java Flight Recorder log and instructions to reproduce the issue makes investigation easier and thus the chances of a fix higher. +Even better is if you can submit a [JMH](http://openjdk.java.net/projects/code-tools/jmh/) benchmark that represents the hottest parts of your application (as identified by a profiler). +This allows us to very quickly pinpoint missing optimization opportunities or to offer suggestions on how to restructure the code to avoid or reduce performance bottlenecks. ## Troubleshooting the GraalVM Compiler -Like all software, the GraalVM compiler is not guaranteed to be bug free so it is useful to -know how to diagnose and submit useful bug reports if you encounter issues. +Like all software, the GraalVM compiler is not guaranteed to be bug free so it is useful to know how to diagnose and submit useful bug reports if you encounter issues. -If you spot a security vulnerability, please do **not** report it via GitHub Issues or the public mailing lists, -but via the process outlined at [Reporting Vulnerabilities guide](https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html). +If you spot a security vulnerability, please do **not** report it via GitHub Issues or the public mailing lists, but via the process outlined at [Reporting Vulnerabilities guide](https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html). ### Compilation Exceptions -One advantage of the compiler being written in Java is that runtime exceptions during -compilation are not fatal VM errors. Instead, each compilation has an exception -handler that takes action based on the `graal.CompilationFailureAction` -property. +One advantage of the compiler being written in Java is that runtime exceptions during compilation are not fatal VM errors. +Instead, each compilation has an exception handler that takes action based on the `graal.CompilationFailureAction` property. -The default value is `Silent`. Specifying `Diagnose` causes failing compilations to be retried -with extra diagnostics enabled. In this case, just before the VM exits, all diagnostic output -captured during retried compilations is written to a `.zip` file and its location -is printed on the console: +The default value is `Silent`. Specifying `Diagnose` causes failing compilations to be retried with extra diagnostics enabled. +In this case, just before the VM exits, all diagnostic output captured during retried compilations is written to a `.zip` file and its location is printed on the console: ```shell Graal diagnostic output saved in /Users/demo/graal-dumps/1499768882600/graal_diagnostics_64565.zip ``` @@ -92,11 +72,8 @@ are also supported: ### Code Generation Errors The other type of error you might encounter with compilers is the production of incorrect machine code. -This error can cause a VM crash, which should produce a file that starts with -`hs_err_pid` in the current working directory of the VM process. In most cases, -there is a section in the file that shows the stack at the time of the crash, -including the type of code for each frame in the stack, as in the following -example: +This error can cause a VM crash, which should produce a file that starts with `hs_err_pid` in the current working directory of the VM process. +In most cases, there is a section in the file that shows the stack at the time of the crash, including the type of code for each frame in the stack, as in the following example: ```shell Stack: [0x00007000020b1000,0x00007000021b1000], sp=0x00007000021af7a0, free space=1017k @@ -106,16 +83,14 @@ j org.graalvm.compiler.core.gen.NodeLIRBuilder.doBlock(Lorg/graalvm/compiler/no j org.graalvm.compiler.core.LIRGenerationPhase.emitBlock(Lorg/graalvm/compiler/nodes/spi/NodeLIRBuilderTool;Lorg/graalvm/compiler/lir/gen/LIRGenerationResult;Lorg/graalvm/compiler/nodes/cfg/Block;Lorg/graalvm/compiler/nodes/StructuredGraph;Lorg/graalvm/compiler/core/common/cfg/BlockMap;)V+65 ``` -This example shows that the top frame was compiled (J) by the JVMCI compiler, -which is the GraalVM compiler. The crash occurred at offset 0x141 in the machine -code produced for: +This example shows that the top frame was compiled (J) by the JVMCI compiler, which is the GraalVM compiler. +The crash occurred at offset 0x141 in the machine code produced for: ```shell org.graalvm.compiler.core.gen.NodeLIRBuilder.matchComplexExpressions(Ljava/util/List;)V ``` -The next two frames in the stack were executed in the interpreter (j). The -location of the crash is also often indicated near the top of the file with -something like this: +The next two frames in the stack were executed in the interpreter (j). +The location of the crash is also often indicated near the top of the file with something like this: ```shell # Problematic frame: # J 761 JVMCI org.graalvm.compiler.core.gen.NodeLIRBuilder.matchComplexExpressions(Ljava/util/List;)V (299 bytes) @ 0x0000000108a2fc01 [0x0000000108a2fac0+0x141] (null) @@ -123,8 +98,7 @@ something like this: In this example, there is likely an error in the code produced by the GraalVM compiler for `NodeLIRBuilder.matchComplexExpressions`. -When filing an issue on [GitHub](https://github.com/oracle/graal/issues) -for such a crash, you should first attempt to reproduce the crash with extra +When filing an issue on [GitHub](https://github.com/oracle/graal/issues) for such a crash, you should first attempt to reproduce the crash with extra diagnostics enabled for the compilation of the problematic method. In this example, you would add the following to your command line: ```shell @@ -132,21 +106,15 @@ In this example, you would add the following to your command line: ``` These options are described in more detail [here](https://github.com/oracle/graal/blob/master/compiler/docs/Debugging.md). -In brief, these options tell the compiler to capture snapshots of the compiler state at -verbosity level 2 while compiling any method named `matchComplexExpressions` in -a class with a simple name of `NodeLIRBuilder`. The complete format of the -`MethodFilter` option is described in the output of `java -XX:+JVMCIPrintProperties`. +In brief, these options tell the compiler to capture snapshots of the compiler state at verbosity level 2 while compiling any method named `matchComplexExpressions` in a class with a simple name of `NodeLIRBuilder`. +The complete format of the `MethodFilter` option is described in the output of `java -XX:+JVMCIPrintProperties`. -Quite often, the crash location does not exist directly in the problematic method -mentioned in the crash log but comes from an inlined method. +Quite often, the crash location does not exist directly in the problematic method mentioned in the crash log but comes from an inlined method. -In such a case, simply filtering for the problematic method might not capture an -erroneous compilation causing a crash. +In such a case, simply filtering for the problematic method might not capture an erroneous compilation causing a crash. -To improve the likelihood of capturing an erroneous compilation, you need to -broaden the `MethodFilter` value. To guide this, add `-Dgraal.PrintCompilation=true` -when trying to reproduce the crash so you can see what was compiled just before -the crash. +To improve the likelihood of capturing an erroneous compilation, you need to broaden the `MethodFilter` value. +To guide this, add `-Dgraal.PrintCompilation=true` when trying to reproduce the crash so you can see what was compiled just before the crash. The following shows sample output from the console: ```shell @@ -166,19 +134,15 @@ HotSpotCompilation-1221 Lorg/graalvm/compiler/hotspot/amd64/AMD64HotSpotL # Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again ``` Here we see that the crash happened in a different method than the first crash. -As such, we expand the filter argument to be `-Dgraal.MethodFilter= -NodeLIRBuilder.matchComplexExpressions,AMD64HotSpotLIRGenerator.getResult` -and run again. +As such, we expand the filter argument to be `-Dgraal.MethodFilter=NodeLIRBuilder.matchComplexExpressions,AMD64HotSpotLIRGenerator.getResult` and run again. -When the VM crashes in this way, it does not execute the shutdown code that -archives the GraalVM compiler diagnostic output or delete the directory it was written to. +When the VM crashes in this way, it does not execute the shutdown code that archives the GraalVM compiler diagnostic output or delete the directory it was written to. This must be done manually after the crash. By default, the directory is `$PWD/graal-dumps/`; for example, `./graal-dumps/1499938817387`. However, you can set the directory with `-Dgraal.DumpPath=`. -A message, such as the following, is printed to the console when this -directory is first used by the compiler: +A message, such as the following, is printed to the console when this directory is first used by the compiler: ```shell Dumping debug output in /Users/demo/graal-dumps/1499768882600 ``` diff --git a/docs/reference-manual/java/README.md b/docs/reference-manual/java/README.md index a710012e773a..39b017e18d15 100644 --- a/docs/reference-manual/java/README.md +++ b/docs/reference-manual/java/README.md @@ -14,7 +14,7 @@ The JVM passes bytecode to the GraalVM compiler, which compiles that to the mach GraalVM's dynamic compiler can improve the efficiency and the speed of applications written in Java, Scala, Kotlin, or other JVM languages through unique approaches to code analysis and optimization. For example, it assures performance advantages for highly abstracted programs due to its ability to remove costly object allocations. -To learn more, go to the [Compiler](/reference-manual/compiler/) page. +To learn more, go to the [Compiler](../compiler.md) page. The open source compiler's code is available on [GitHub](https://github.com/oracle/graal/tree/master/compiler). ## Compiler Operating Modes diff --git a/docs/reference-manual/llvm/Compatibility.md b/docs/reference-manual/llvm/Compatibility.md index 7f285f5a1331..c2925c1ea2a3 100644 --- a/docs/reference-manual/llvm/Compatibility.md +++ b/docs/reference-manual/llvm/Compatibility.md @@ -11,21 +11,15 @@ It is recommended to use the LLVM toolchain shipped with GraalVM. ## Optimizations Flags -In contrast to the static compilation model of LLVM languages, in GraalVM the -machine code is not directly produced from the LLVM bitcode. There is an -additional dynamic compilation step by the GraalVM compiler. +In contrast to the static compilation model of LLVM languages, in GraalVM the machine code is not directly produced from the LLVM bitcode. +There is an additional dynamic compilation step by the GraalVM compiler. -First, the LLVM frontend (e.g., `clang`) performs optimizations on -the bitcode level, and then the GraalVM compiler does its own optimizations on top of that -during dynamic compilation. Some optimizations are better when done -ahead-of-time on bitcode, while other optimizations are better left for the -dynamic compilation of the GraalVM compiler, when profiling information is available. +First, the LLVM frontend (e.g., `clang`) performs optimizations on the bitcode level, and then the GraalVM compiler does its own optimizations on top of that during dynamic compilation. +Some optimizations are better when done ahead-of-time on bitcode, while other optimizations are better left for the dynamic compilation of the GraalVM compiler, when profiling information is available. -The LLVM toolchain that is shipped with GraalVM automatically selects the -recommended flags by default. +The LLVM toolchain that is shipped with GraalVM automatically selects the recommended flags by default. -Generally, all optimization levels should work, but for a better result, it is -recommended to compile the bitcode with the optimization level `-O1`. +Generally, all optimization levels should work, but for a better result, it is recommended to compile the bitcode with the optimization level `-O1`. For cross-language interoperability, the `-mem2reg` optimization is required. There are two ways to get that: either compile with at least `-O1`, or use the `opt` tool to apply the `-mem2reg` optimization manually. diff --git a/docs/reference-manual/llvm/Compiling.md b/docs/reference-manual/llvm/Compiling.md index 4c7d74b507b1..1500c2a0600e 100644 --- a/docs/reference-manual/llvm/Compiling.md +++ b/docs/reference-manual/llvm/Compiling.md @@ -11,8 +11,7 @@ As the first step, you have to compile a program to LLVM bitcode using some LLVM ## File Format -While the GraalVM LLVM runtime can execute [plain bitcode files](https://llvm.org/docs/BitCodeFormat.html), -the preferred format is a _native executable_ with _embedded bitcode_. +While the GraalVM LLVM runtime can execute [plain bitcode files](https://llvm.org/docs/BitCodeFormat.html), the preferred format is a _native executable_ with _embedded bitcode_. The executable file formats differ on Linux and macOS. Linux by default uses ELF files. The bitcode is stored in a section called `.llvmbc`. @@ -31,13 +30,13 @@ To simplify compiling C/C++ to executables with embedded bitcode, GraalVM comes The toolchain contains compilers such as `clang` for C or `clang++` for C++, but also other tools that are needed for building native projects such as a linker (`ld`), or an archiver (`ar`) for creating static libraries. -The LLVM toolchain can be added to GraalVM on demand with the [GraalVM Updater](https://www.graalvm.org/reference-manual/graalvm-updater) tool: +The LLVM toolchain can be added to GraalVM on demand with the [GraalVM Updater](../graalvm-updater.md) tool: ```shell $GRAALVM_HOME/bin/gu install llvm-toolchain ``` The above command will install the LLVM toolchain from the GitHub catalog for GraalVM Community users. -For GraalVM Enterprise users, the [manual installation](https://www.graalvm.org/reference-manual/graalvm-updater/#manual-installation) is required. +For GraalVM Enterprise users, the [manual installation](../graalvm-updater.md/#manual-installation) is required. To get the location of the toolchain, use the `--print-toolchain-path` argument of `lli`: ```shell @@ -71,8 +70,8 @@ $GRAALVM_HOME/bin/lli hello ## External Library Dependencies -If the bitcode file depends on external libraries, GraalVM will automatically -pick up the dependencies from the binary headers. For example: +If the bitcode file depends on external libraries, GraalVM will automatically pick up the dependencies from the binary headers. +For example: ```c #include #include @@ -95,9 +94,9 @@ lli hello-curses ## Running C++ -For running C++ code, the GraalVM LLVM runtime requires the -[`libc++`](https://libcxx.llvm.org) standard library from the LLVM project. The -LLVM toolchain shipped with GraalVM automatically links against `libc++`. For example, save this code as a _hello-c++.cpp_ file: +For running C++ code, the GraalVM LLVM runtime requires the [`libc++`](https://libcxx.llvm.org) standard library from the LLVM project. +The LLVM toolchain shipped with GraalVM automatically links against `libc++`. +For example, save this code as a _hello-c++.cpp_ file: ```c++ #include @@ -115,9 +114,8 @@ Hello, C++ World! ## Running Rust -The LLVM toolchain, bundled with GraalVM, does not come with the Rust -compiler. To install Rust, run the following in your command prompt, then follow the -onscreen instructions: +The LLVM toolchain, bundled with GraalVM, does not come with the Rust compiler. +To install Rust, run the following in your command prompt, then follow the onscreen instructions: ```shell curl https://sh.rustup.rs -sSf | sh ``` @@ -134,32 +132,26 @@ This can be then compiled to bitcode with the `--emit=llvm-bc` flag: rustc --emit=llvm-bc hello-rust.rs ``` -To run the Rust program, we have to tell GraalVM where to find the Rust -standard libraries: +To run the Rust program, we have to tell GraalVM where to find the Rust standard libraries: ```shell lli --lib $(rustc --print sysroot)/lib/libstd-* hello-rust.bc Hello Rust! ``` -Since the Rust compiler is not using the LLVM toolchain shipped with GraalVM, depending on the -local Rust installation, an error similar to one of the following might happen: +Since the Rust compiler is not using the LLVM toolchain shipped with GraalVM, depending on the local Rust installation, an error similar to one of the following might happen: ``` Mismatching target triple (expected x86_64-unknown-linux-gnu, got x86_64-pc-linux-gnu) Mismatching target triple (expected x86_64-apple-macosx10.11.0, got x86_64-apple-darwin) ``` -This indicates that the Rust compiler used a different target triple than the LLVM toolchain -shipped with GraalVM. In this particular case, the differences are just different naming -conventions across Linux distributions or MacOS versions, there is no real difference. +This indicates that the Rust compiler used a different target triple than the LLVM toolchain shipped with GraalVM. +In this particular case, the differences are just different naming conventions across Linux distributions or MacOS versions, there is no real difference. In that case, the error can be safely ignored: ```shell lli --experimental-options --llvm.verifyBitcode=false --lib $(rustc --print sysroot)/lib/libstd-* hello-rust.bc ``` -This option should only be used after manually verifying that the target triples are -really compatible, i.e., the architecture, operating system, and C library all match. -For example, `x86_64-unknown-linux-musl` and `x86_64-unknown-linux-gnu` are really different, -the bitcode is compiled for a different C library. The `--llvm.verifyBitcode=false` option -disables all checks, GraalVM will then try to run the bitcode regardless, which might randomly -fail in unexpected ways. +This option should only be used after manually verifying that the target triples are really compatible, i.e., the architecture, operating system, and C library all match. +For example, `x86_64-unknown-linux-musl` and `x86_64-unknown-linux-gnu` are really different, the bitcode is compiled for a different C library. +The `--llvm.verifyBitcode=false` option disables all checks, GraalVM will then try to run the bitcode regardless, which might randomly fail in unexpected ways. diff --git a/docs/reference-manual/llvm/Debugging.md b/docs/reference-manual/llvm/Debugging.md index 6cd9556f5273..e1ee07053df8 100644 --- a/docs/reference-manual/llvm/Debugging.md +++ b/docs/reference-manual/llvm/Debugging.md @@ -12,9 +12,9 @@ This includes support for single-stepping, breakpoints, and inspection of local To use this feature, make sure to compile your program with debug information enabled by specifying the `-g` argument when compiling with `clang` (the LLVM toolchain shipped with GraalVM will automatically enable debug information). This gives you the ability to step through the program's source code and set breakpoints in it. -With GraalVM 20.0 and older, the option `--llvm.enableLVI=true` is needed for being able to inspect variables during debugging. + To start debugging, run `lli` with the `--inspect` option: ```shell @@ -35,14 +35,13 @@ To instead parse functions eagerly, and be able to set breakpoints also in funct Program-defined breakpoints using the `__builtin_debugtrap` function enables you to mark locations in the program at which you explicitly want GraalVM to halt the program and switch to the debugger. The debugger automatically halts at each call to this function as if a breakpoint were set on the call. You can use this feature to quickly reach the code you are actually trying to debug without having to first find and set a breakpoint on it after launching your application. -You can also instruct Chrome Inspector not to suspend your program at the first source-level statement being executed. When doing so, GraalVM will instead execute your program until it reaches a call to `__builtin_debugtrap()` before invoking the debugger. +You can also instruct Chrome Inspector not to suspend your program at the first source-level statement being executed. +When doing so, GraalVM will instead execute your program until it reaches a call to `__builtin_debugtrap()` before invoking the debugger. To enable this behavior you need to pass the arguments `lli --inspect.Suspend=false --inspect.WaitAttached=true`. ## Locating Source Files -Debug information in LLVM bitcode files contains absolute search paths to identify the -location of source code. If the source files did not move, it should be found automatically. +Debug information in LLVM bitcode files contains absolute search paths to identify the location of source code. +If the source files did not move, it should be found automatically. -If the source files moved, or were compiled on a different machine, a search path can be -specified using the `--inspect.SourcePath=` option (multiple paths can be separated -by `:`). +If the source files moved, or were compiled on a different machine, a search path can be specified using the `--inspect.SourcePath=` option (multiple paths can be separated by `:`). diff --git a/docs/reference-manual/llvm/Interoperability.md b/docs/reference-manual/llvm/Interoperability.md index 7910a0e0b877..9900f825bba0 100644 --- a/docs/reference-manual/llvm/Interoperability.md +++ b/docs/reference-manual/llvm/Interoperability.md @@ -9,13 +9,10 @@ permalink: /reference-manual/llvm/Interoperability/ GraalVM supports several other programming languages including JavaScript, Python, Ruby, and R. While GraalVM's implementation of `lli` is designed to run LLVM bitcode, it also provides the API for programming language interoperability that lets you execute code from any other GraalVM-supported language. -Dynamic languages like JavaScript usually access object members by name. Since -normally names are not preserved in LLVM bitcode, it must be compiled with debug -information enabled (the LLVM toolchain shipped with GraalVM will automatically enable -debugging information). +Dynamic languages like JavaScript usually access object members by name. +Since normally names are not preserved in LLVM bitcode, it must be compiled with debug information enabled (the LLVM toolchain shipped with GraalVM will automatically enable debugging information). -The following example demonstrates how you can use the API for interoperability -with other programming languages. +The following example demonstrates how you can use the API for interoperability with other programming languages. Define a C struct for points and implement allocation functions in a file named _cpart.c_: @@ -52,9 +49,7 @@ void printPoint(struct Point *p) { } ``` -Make sure `LLVM_TOOLCHAIN` resolves to the GraalVM LLVM toolchain (`lli --print-toolchain-path`), -and then compile _cpart.c_ (the graalvm-llvm library defines the polyglot -API functions used in the example): +Make sure `LLVM_TOOLCHAIN` resolves to the GraalVM LLVM toolchain (`lli --print-toolchain-path`), and then compile _cpart.c_ (the graalvm-llvm library defines the Polyglot API functions used in the example): ```shell $LLVM_TOOLCHAIN/clang -shared cpart.c -lgraalvm-llvm -o cpart.so ``` @@ -104,9 +99,8 @@ Point<17.000000,42.000000> ## Polyglot C API -There are also lower level API functions for directly accessing polyglot values -from C. See the [Polyglot Programming](https://graalvm.org/reference-manual/polyglot-programming/) reference -and the comments in `polyglot.h` for more details. +There are also lower level API functions for directly accessing polyglot values from C. +See the [Polyglot Programming](../polyglot-programming.md) reference and the comments in `polyglot.h` for more details. For example, this program allocates and accesses a Java array from C: ```c @@ -163,5 +157,4 @@ java Polyglot 24 ``` -See the [Embedding Languages](https://graalvm.org/reference-manual/embed-languages/) reference for -more information. +See the [Embedding Languages](../embedding/embed-languages.md) reference for more information. diff --git a/docs/reference-manual/llvm/NativeExecution.md b/docs/reference-manual/llvm/NativeExecution.md index 6171d928ffc6..6892db89e2f7 100644 --- a/docs/reference-manual/llvm/NativeExecution.md +++ b/docs/reference-manual/llvm/NativeExecution.md @@ -12,24 +12,16 @@ The difference lies in safety guarantees and cross-language interoperability. Note: Managed execution mode for LLVM bitcode is possible with GraalVM Enterprise only. -In the default configuration, cross-language interoperability requires bitcode -to be compiled with the debug information enabled (`-g`), and the `-mem2reg` -optimization performed on LLVM bitcode (compiled with at least `-O1`, or -explicitly using the `opt` tool). These requirements can be overcome in a -managed environment of GraalVM Enterprise that allows native code to participate in the -polyglot programs, passing and receiving the data from any other supported -language. In terms of security, the execution of native code in a managed -environment passes with additional safety features: catching illegal pointer -accesses, accessing arrays outside of the bounds, etc. +In the default configuration, cross-language interoperability requires bitcode to be compiled with the debug information enabled (`-g`), and the `-mem2reg` optimization performed on LLVM bitcode (compiled with at least `-O1`, or explicitly using the `opt` tool). +These requirements can be overcome in a managed environment of GraalVM Enterprise that allows native code to participate in the polyglot programs, passing and receiving the data from any other supported language. +In terms of security, the execution of native code in a managed environment passes with additional safety features: catching illegal pointer accesses, accessing arrays outside of the bounds, etc. There are certain limitations and differences to the native execution depending on the GraalVM edition. Consider them respectively. ### Limitations and Differences to Native Execution on Top of GraalVM Community -The LLVM interpreter in GraalVM Community Edition environment allows executing LLVM bitcode within a -multilingual context. Even though it aspires to be a generic LLVM runtime, there -are certain fundamental and/or implementational limitations that users need to -be aware of. +The LLVM interpreter in GraalVM Community Edition environment allows executing LLVM bitcode within a multilingual context. +Even though it aspires to be a generic LLVM runtime, there are certain fundamental and/or implementational limitations that users need to be aware of. The following restrictions and differences to native execution (i.e., bitcode compiled down to native code) exist when LLVM bitcode is executed with the LLVM interpreter on top of GraalVM Community: diff --git a/docs/reference-manual/llvm/README.md b/docs/reference-manual/llvm/README.md index dfcd66c93ff0..829b9d8c943c 100644 --- a/docs/reference-manual/llvm/README.md +++ b/docs/reference-manual/llvm/README.md @@ -14,15 +14,16 @@ This allows seamless interoperability with the dynamic languages supported by Gr ## Running LLVM Bitcode on GraalVM -To run LLVM-based languages on GraalVM, the binaries need to be compiled with embedded -bitcode. The [Compiling](Compiling.md) guide provides information on -how to compile a program to LLVM bitcode and what file format is expected. +To run LLVM-based languages on GraalVM, the binaries need to be compiled with embedded bitcode. +The [Compiling](Compiling.md) guide provides information on how to compile a program to LLVM bitcode and what file format is expected. The syntax to execute programs in LLVM bitcode format on GraalVM is: ```shell lli [LLI options] [GraalVM options] [polyglot options] [program args] ``` -Here, `` is [a compiled program with embedded LLVM bitcode](Compiling.md). See [LLI Command Options](Options.md) or use `lli --help` for options explanations. -Note: LLVM bitcode is platform-dependent. The program must be compiled to -bitcode for an appropriate platform. +Here, `` is [a compiled program with embedded LLVM bitcode](Compiling.md). +See [LLI Command Options](Options.md) or use `lli --help` for options explanations. + +Note: LLVM bitcode is platform-dependent. +The program must be compiled to bitcode for an appropriate platform. diff --git a/docs/reference-manual/wasm/README.md b/docs/reference-manual/wasm/README.md index 4c47f89a120d..2b6f7b191cca 100644 --- a/docs/reference-manual/wasm/README.md +++ b/docs/reference-manual/wasm/README.md @@ -13,12 +13,12 @@ The support for WebAssembly is in the early stages of its development. ## Installing Wasm -The support is not available by default, but you can add it to GraalVM using the [GraalVM Updater](/reference-manual/graalvm-updater/) tool: +The support is not available by default, but you can add it to GraalVM using the [GraalVM Updater](../graalvm-updater.md) tool: ```shell gu install wasm ``` The above command will install a community version of a component from the GitHub catalog. -For GraalVM Enterprise users, the [manual component installation](/reference-manual/graalvm-updater/#component-installation) is required. +For GraalVM Enterprise users, the [manual component installation](../graalvm-updater.md/#component-installation) is required. Then `wasm` launcher, which can run compiled WebAssembly binary code, becomes available. @@ -75,4 +75,4 @@ Value mainFunction = context.getBindings("wasm").getMember("main").getMember("_s mainFunction.execute(); ``` -For more polyglot examples, visit the [Polyglot Programming](/reference-manual/polyglot-programming/) page. +For more polyglot examples, visit the [Polyglot Programming](../polyglot-programming.md) page. From fceb33743665882f6d3929c3e4b80bed05506972 Mon Sep 17 00:00:00 2001 From: Andrew Dinn Date: Mon, 11 Oct 2021 13:55:25 +0100 Subject: [PATCH 395/681] Use correct form code (DW_FORM_sec_offset) for stmt_list attribute. --- .../oracle/objectfile/elf/dwarf/DwarfAbbrevSectionImpl.java | 6 +++--- .../src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java | 3 ++- .../oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java | 2 +- .../com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java | 4 ++++ 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfAbbrevSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfAbbrevSectionImpl.java index 26916fc8cec1..e8ab5db09050 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfAbbrevSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfAbbrevSectionImpl.java @@ -277,8 +277,8 @@ public void createContent() { * *
  • DW_AT_use_UTF8 : ... DW_FORM_flag * - *
  • DW_AT_stmt_list : .. DW_FORM_data4 n.b only for abbrev-code == - * class_unit1 + *
  • DW_AT_stmt_list : .. DW_FORM_sec_offset n.b only for abbrev-code + * == class_unit1 * *
* @@ -886,7 +886,7 @@ private int writeClassUnitAbbrev(@SuppressWarnings("unused") DebugContext contex } if (abbrevCode == DwarfDebugInfo.DW_ABBREV_CODE_class_unit1) { pos = writeAttrType(DwarfDebugInfo.DW_AT_stmt_list, buffer, pos); - pos = writeAttrForm(DwarfDebugInfo.DW_FORM_data4, buffer, pos); + pos = writeAttrForm(DwarfDebugInfo.DW_FORM_sec_offset, buffer, pos); } /* * Now terminate. diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java index 8fcad6f32b1d..9adc3617678a 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java @@ -169,11 +169,12 @@ public class DwarfDebugInfo extends DebugInfoBase { @SuppressWarnings("unused") public static final int DW_FORM_data8 = 0x7; @SuppressWarnings("unused") private static final int DW_FORM_string = 0x8; @SuppressWarnings("unused") public static final int DW_FORM_block1 = 0x0a; + public static final int DW_FORM_ref_addr = 0x10; @SuppressWarnings("unused") public static final int DW_FORM_ref1 = 0x11; @SuppressWarnings("unused") public static final int DW_FORM_ref2 = 0x12; @SuppressWarnings("unused") public static final int DW_FORM_ref4 = 0x13; @SuppressWarnings("unused") public static final int DW_FORM_ref8 = 0x14; - public static final int DW_FORM_ref_addr = 0x10; + public static final int DW_FORM_sec_offset = 0x17; public static final int DW_FORM_data1 = 0x0b; public static final int DW_FORM_flag = 0xc; public static final int DW_FORM_strp = 0xe; diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java index b20f1c80f71b..9a93f68fd374 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfInfoSectionImpl.java @@ -457,7 +457,7 @@ private int writePrimaryClassUnit(DebugContext context, ClassEntry classEntry, b /* Only write stmt_list if the entry actually has line number info. */ if (abbrevCode == DwarfDebugInfo.DW_ABBREV_CODE_class_unit1) { log(context, " [0x%08x] stmt_list 0x%08x", pos, lineIndex); - pos = writeAttrData4(lineIndex, buffer, pos); + pos = writeAttrSecOffset(lineIndex, buffer, pos); } /* Now write the child DIEs starting with the layout and pointer type. */ diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java index ce45876549e2..bfe21bdb33c0 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java @@ -340,6 +340,10 @@ protected int writeAttrData4(int value, byte[] buffer, int pos) { } } + protected int writeAttrSecOffset(int value, byte[] buffer, int pos) { + return writeAttrData4(value, buffer, pos); + } + protected int writeAttrData2(short value, byte[] buffer, int pos) { if (buffer == null) { return pos + putShort(value, scratch, 0); From b1f7d424832a3ea6d1ba6a6db417d0f26c866fa5 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 23 Sep 2021 23:42:59 +0300 Subject: [PATCH 396/681] docs/reference-manual/native-image update ref links to rel paths; start sentences from a new line --- docs/reference-manual/native-image/Agent.md | 94 +++++++----- .../native-image/BuildConfiguration.md | 103 ++++++------- docs/reference-manual/native-image/C-API.md | 6 +- .../native-image/ClassInitialization.md | 7 +- .../native-image/DynamicProxy.md | 5 +- .../native-image/HostedvsRuntimeOptions.md | 13 +- .../ImplementingNativeMethodsInJavaWithSVM.md | 138 +++++++----------- docs/reference-manual/native-image/JNI.md | 5 +- .../native-image/LLVMBackend.md | 9 +- .../native-image/Limitations.md | 28 ++-- .../NativeImageHeapdumpEnterprise.md | 48 +++--- docs/reference-manual/native-image/Options.md | 22 +-- docs/reference-manual/native-image/README.md | 63 ++++---- .../native-image/Reflection.md | 7 +- docs/reference-manual/native-image/Reports.md | 9 +- .../native-image/Resources.md | 25 ++-- 16 files changed, 256 insertions(+), 326 deletions(-) diff --git a/docs/reference-manual/native-image/Agent.md b/docs/reference-manual/native-image/Agent.md index 1505c516379d..bfbf7d51c920 100644 --- a/docs/reference-manual/native-image/Agent.md +++ b/docs/reference-manual/native-image/Agent.md @@ -72,11 +72,9 @@ public class ReflectionExample { } ``` -This is a simple Java program where non-constant strings for accessing program -elements by name must come as external inputs. The main method invokes a method -of a particular class (`Class.forName`) whose names are passed as command line -arguments. Providing any other class or method name on the command line leads to -an exception. +This is a simple Java program where non-constant strings for accessing program elements by name must come as external inputs. +The main method invokes a method of a particular class (`Class.forName`) whose names are passed as command line arguments. +Providing any other class or method name on the command line leads to an exception. Having compiled the example, invoke each method: ```shell @@ -94,10 +92,7 @@ $JAVA_HOME/bin/native-image ReflectionExample ... ./reflectionexample ``` -The `reflectionexample` binary is just a launcher for the JVM. To -build a native image with reflective lookup operations, apply the tracing -agent to write a configuration file to be later fed into the native image -build together. +The `reflectionexample` binary is just a launcher for the JVM. To build a native image with reflective lookup operations, apply the tracing agent to write a configuration file to be later fed into the native image build together. 1. Create a directory `META-INF/native-image` in the working directory: ```shell @@ -108,17 +103,16 @@ mkdir -p META-INF/native-image ```shell $JAVA_HOME/bin/java -agentlib:native-image-agent=config-output-dir=META-INF/native-image ReflectionExample StringReverser reverse "hello" ``` -This command creates a _reflection-config.json_ file which makes the `StringReverser` class and the `reverse()` method accessible via reflection. The _jni-config.json_, _proxy-config.json_ , and _resource-config.json_ configuration files are written in that directory too. +This command creates a _reflection-config.json_ file which makes the `StringReverser` class and the `reverse()` method accessible via reflection. +The _jni-config.json_, _proxy-config.json_ , and _resource-config.json_ configuration files are written in that directory too. 3. Build a native image: ```shell $JAVA_HOME/bin/native-image --no-fallback ReflectionExample ``` -The native image builder automatically picks up configuration files in the -_META-INF/native-image_ directory or subdirectories. However, it is recommended -to have _META-INF/native-image_ location on the class path, either via a JAR -file or via the `-cp` flag. It will help to avoid confusion for IDE users where a -directory structure is defined by the tool. +The native image builder automatically picks up configuration files in the _META-INF/native-image_ directory or subdirectories. +However, it is recommended to have _META-INF/native-image_ location on the class path, either via a JAR file or via the `-cp` flag. +It will help to avoid confusion for IDE users where a directory structure is defined by the tool. 4. Test the methods, but remember that you have not run the tracing agent twice to create a configuration that supports both: ```shell @@ -131,20 +125,15 @@ Exception in thread "main" java.lang.ClassNotFoundException: StringCapitalizer at ReflectionExample.main(ReflectionExample.java:21) ``` -Neither the tracing agent nor native images generator can automatically check -if the provided configuration files are complete. The agent only observes and -records which values are accessed through reflection so that the same accesses -are possible in a native image. You can either manually edit the -_reflection-config.json_ file, or re-run the tracing agent to transform the -existing configuration file, or extend it by using `config-merge-dir` option: +Neither the tracing agent nor native images generator can automatically check if the provided configuration files are complete. +The agent only observes and records which values are accessed through reflection so that the same accesses are possible in a native image. +You can either manually edit the _reflection-config.json_ file, or re-run the tracing agent to transform the existing configuration file, or extend it by using `config-merge-dir` option: ```shell $JAVA_HOME/bin/java -agentlib:native-image-agent=config-merge-dir=META-INF/native-image ReflectionExample StringCapitalizer capitalize "hello" ``` -Note, the different `config-merge-dir` option instructs the agent to extend the -existing configuration files instead of overwriting them. After re-building the -native image, the `StringCapitalizer` class and the `capitalize` method will be -accessible too. +Note, the different `config-merge-dir` option instructs the agent to extend the existing configuration files instead of overwriting them. +After re-building the native image, the `StringCapitalizer` class and the `capitalize` method will be accessible too. ![](/img/reflect_config_file_merged.png) @@ -152,9 +141,13 @@ accessible too. ### Caller-based Filters -By default, the agent filters dynamic accesses which Native Image supports without configuration. The filter mechanism works by identifying the Java method performing the access, also referred to as _caller_ method, and matching its declaring class against a sequence of filter rules. The built-in filter rules exclude dynamic accesses which originate in the JVM, or in parts of a Java class library directly supported by Native Image (such as `java.nio`) from the generated configuration files. Which item (class, method, field, resource, etc.) is being accessed is not relevant for filtering. +By default, the agent filters dynamic accesses which Native Image supports without configuration. +The filter mechanism works by identifying the Java method performing the access, also referred to as _caller_ method, and matching its declaring class against a sequence of filter rules. +The built-in filter rules exclude dynamic accesses which originate in the JVM, or in parts of a Java class library directly supported by Native Image (such as `java.nio`) from the generated configuration files. +Which item (class, method, field, resource, etc.) is being accessed is not relevant for filtering. -In addition to the built-in filter, custom filter files with additional rules can be specified using the `caller-filter-file` option. For example: `-agentlib:caller-filter-file=/path/to/filter-file,config-output-dir=...` +In addition to the built-in filter, custom filter files with additional rules can be specified using the `caller-filter-file` option. +For example: `-agentlib:caller-filter-file=/path/to/filter-file,config-output-dir=...` Filter files have the following structure: ```json @@ -166,25 +159,46 @@ Filter files have the following structure: } ``` -The `rules` section contains a sequence of rules. Each rule specifies either `includeClasses`, which means that lookups originating in matching classes will be included in the resulting configuration, or `excludeClasses`, which excludes lookups originating in matching classes from the configuration. Each rule defines a pattern for the set of matching classes, which can end in `.*` or `.**`: a `.*` ending matches all classes in a package and that package only, while a `.**` ending matches all classes in the package as well as in all subpackages at any depth. Without `.*` or `.**`, the rule applies only to a single class with the qualified name that matches the pattern. All rules are processed in the sequence in which they are specified, so later rules can partially or entirely override earlier ones. When multiple filter files are provided (by specifying multiple `caller-filter-file` options), their rules are chained together in the order in which the files are specified. The rules of the built-in caller filter are always processed first, so they can be overridden in custom filter files. +The `rules` section contains a sequence of rules. +Each rule specifies either `includeClasses`, which means that lookups originating in matching classes will be included in the resulting configuration, or `excludeClasses`, which excludes lookups originating in matching classes from the configuration. +Each rule defines a pattern for the set of matching classes, which can end in `.*` or `.**`: a `.*` ending matches all classes in a package and that package only, while a `.**` ending matches all classes in the package as well as in all subpackages at any depth. Without `.*` or `.**`, the rule applies only to a single class with the qualified name that matches the pattern. +All rules are processed in the sequence in which they are specified, so later rules can partially or entirely override earlier ones. +When multiple filter files are provided (by specifying multiple `caller-filter-file` options), their rules are chained together in the order in which the files are specified. +The rules of the built-in caller filter are always processed first, so they can be overridden in custom filter files. -In the example above, the first rule excludes lookups originating in all classes from package `com.oracle.svm` and from all of its subpackages (and their subpackages, etc.) from the generated configuration. In the next rule however, lookups from those classes that are directly in package `com.oracle.svm.tutorial` are included again. Finally, lookups from the `HostedHelper` class is excluded again. Each of these rules partially overrides the previous ones. For example, if the rules were in the reverse order, the exclusion of `com.oracle.svm.**` would be the last rule and would override all other rules. +In the example above, the first rule excludes lookups originating in all classes from package `com.oracle.svm` and from all of its subpackages (and their subpackages, etc.) from the generated configuration. +In the next rule however, lookups from those classes that are directly in package `com.oracle.svm.tutorial` are included again. +Finally, lookups from the `HostedHelper` class is excluded again. Each of these rules partially overrides the previous ones. +For example, if the rules were in the reverse order, the exclusion of `com.oracle.svm.**` would be the last rule and would override all other rules. -For testing purposes, the built-in filter for Java class library lookups can be disabled by adding the `no-builtin-caller-filter` option, but the resulting configuration files are generally unsuitable for a native image build. Similarly, the built-in filter for Java VM-internal accesses based on heuristics can be disabled with `no-builtin-heuristic-filter` and will also generally lead to less usable configuration files. For example: `-agentlib:native-image-agent=no-builtin-caller-filter,no-builtin-heuristic-filter,config-output-dir=...` +For testing purposes, the built-in filter for Java class library lookups can be disabled by adding the `no-builtin-caller-filter` option, but the resulting configuration files are generally unsuitable for a native image build. +Similarly, the built-in filter for Java VM-internal accesses based on heuristics can be disabled with `no-builtin-heuristic-filter` and will also generally lead to less usable configuration files. +For example: `-agentlib:native-image-agent=no-builtin-caller-filter,no-builtin-heuristic-filter,config-output-dir=...` ### Access Filters -Unlike the caller-based filters described above, which filter dynamic accesses based on where they originate from, _access filters_ apply to the _target_ of the access. Therefore, access filters enable directly excluding packages and classes (and their members) from the generated configuration. +Unlike the caller-based filters described above, which filter dynamic accesses based on where they originate from, _access filters_ apply to the _target_ of the access. +Therefore, access filters enable directly excluding packages and classes (and their members) from the generated configuration. -By default, all accessed classes (which also pass the caller-based filters and the built-in filters) are included in the generated configuration. Using the `access-filter-file` option, a custom filter file that follows the file structure described above can be added. The option can be specified more than once to add multiple filter files and can be combined with the other filter options. For example: `-agentlib:access-filter-file=/path/to/access-filter-file,caller-filter-file=/path/to/caller-filter-file,config-output-dir=...` +By default, all accessed classes (which also pass the caller-based filters and the built-in filters) are included in the generated configuration. +Using the `access-filter-file` option, a custom filter file that follows the file structure described above can be added. +The option can be specified more than once to add multiple filter files and can be combined with the other filter options. +For example: `-agentlib:access-filter-file=/path/to/access-filter-file,caller-filter-file=/path/to/caller-filter-file,config-output-dir=...` ### Specifying Configuration Files as Native Image Arguments -A directory containing configuration files that is not part of the class path can be specified to `native-image` via `-H:ConfigurationFileDirectories=/path/to/config-dir/`. This directory must directly contain all four files: `jni-config.json`, `reflect-config.json`, `proxy-config.json` and `resource-config.json`. A directory with the same four configuration files that is on the class path, but not in `META-INF/native-image/`, can be provided via `-H:ConfigurationResourceRoots=path/to/resources/`. Both `-H:ConfigurationFileDirectories` and `-H:ConfigurationResourceRoots` can also take a comma-separated list of directories. +A directory containing configuration files that is not part of the class path can be specified to `native-image` via `-H:ConfigurationFileDirectories=/path/to/config-dir/`. +This directory must directly contain all four files: `jni-config.json`, `reflect-config.json`, `proxy-config.json` and `resource-config.json`. +A directory with the same four configuration files that is on the class path, but not in `META-INF/native-image/`, can be provided via `-H:ConfigurationResourceRoots=path/to/resources/`. +Both `-H:ConfigurationFileDirectories` and `-H:ConfigurationResourceRoots` can also take a comma-separated list of directories. ### Injecting the Agent via the Process Environment -Altering the `java` command line to inject the agent can prove to be difficult if the Java process is launched by an application or script file, or if Java is even embedded in an existing process. In that case, it is also possible to inject the agent via the `JAVA_TOOL_OPTIONS` environment variable. This environment variable can be picked up by multiple Java processes which run at the same time, in which case each agent must write to a separate output directory with `config-output-dir`. (The next section describes how to merge sets of configuration files.) In order to use separate paths with a single global `JAVA_TOOL_OPTIONS` variable, the agent's output path options support placeholders: +Altering the `java` command line to inject the agent can prove to be difficult if the Java process is launched by an application or script file, or if Java is even embedded in an existing process. +In that case, it is also possible to inject the agent via the `JAVA_TOOL_OPTIONS` environment variable. +This environment variable can be picked up by multiple Java processes which run at the same time, in which case each agent must write to a separate output directory with `config-output-dir`. +(The next section describes how to merge sets of configuration files.) +In order to use separate paths with a single global `JAVA_TOOL_OPTIONS` variable, the agent's output path options support placeholders: ```shell export JAVA_TOOL_OPTIONS="-agentlib:native-image-agent=config-output-dir=/path/to/config-output-dir-{pid}-{datetime}/" ``` @@ -193,26 +207,30 @@ The `{pid}` placeholder is replaced with the process identifier, while `{datetim ### Trace Files -In the examples above, `native-image-agent` has been used to both keep track of the dynamic accesses in a Java VM and then to generate a set of configuration files from them. However, for a better understanding of the execution, the agent can also write a _trace file_ in JSON format that contains each individual access: +In the examples above, `native-image-agent` has been used to both keep track of the dynamic accesses in a Java VM and then to generate a set of configuration files from them. +However, for a better understanding of the execution, the agent can also write a _trace file_ in JSON format that contains each individual access: ```shell $JAVA_HOME/bin/java -agentlib:native-image-agent=trace-output=/path/to/trace-file.json ... ``` -The `native-image-configure` tool can transform trace files to configuration files that can be used in native image builds. The following command reads and processes `trace-file.json` and generates a set of configuration files in directory `/path/to/config-dir/`: +The `native-image-configure` tool can transform trace files to configuration files that can be used in native image builds. +The following command reads and processes `trace-file.json` and generates a set of configuration files in directory `/path/to/config-dir/`: ```shell native-image-configure generate --trace-input=/path/to/trace-file.json --output-dir=/path/to/config-dir/ ``` ### Interoperability -Although the agent is distributed with GraalVM, it uses the JVM Tool Interface (JVMTI) and can potentially be used with other JVMs that support JVMTI. In this case, it is necessary to provide the absolute path of the agent: +Although the agent is distributed with GraalVM, it uses the JVM Tool Interface (JVMTI) and can potentially be used with other JVMs that support JVMTI. +In this case, it is necessary to provide the absolute path of the agent: ```shell /path/to/some/java -agentpath:/path/to/graalvm/jre/lib/amd64/libnative-image-agent.so= ... ``` ### Native Image Configure Tool -When using the agent in multiple processes at the same time as described in the previous section, `config-output-dir` is a safe option, but results in multiple sets of configuration files. The `native-image-configure-launcher` tool can be used to merge these configuration files. This tool must first be built with: +When using the agent in multiple processes at the same time as described in the previous section, `config-output-dir` is a safe option, but results in multiple sets of configuration files. The `native-image-configure-launcher` tool can be used to merge these configuration files. +This tool must first be built with: ```shell native-image --macro:native-image-configure-launcher ``` diff --git a/docs/reference-manual/native-image/BuildConfiguration.md b/docs/reference-manual/native-image/BuildConfiguration.md index d7718abb2707..60303172d45b 100644 --- a/docs/reference-manual/native-image/BuildConfiguration.md +++ b/docs/reference-manual/native-image/BuildConfiguration.md @@ -18,22 +18,17 @@ Native Image supports a wide range of options to configure a native image build ## Embedding a Configuration File -A recommended way to provide configuration is to embed a -**native-image.properties** file into a project JAR file. The Native Image builder -will automatically pick up all configuration options provided anywhere below the -resource location `META-INF/native-image/` and use it to construct -`native-image` command line arguments. - -To avoid a situation when constituent parts of a project are built -with overlapping configurations, it is recommended to use "subdirectories" within -`META-INF/native-image`. That way a JAR file built from multiple maven projects -cannot suffer from overlapping `native-image` configurations. For example: +A recommended way to provide configuration is to embed a **native-image.properties** file into a project JAR file. +The Native Image builder will automatically pick up all configuration options provided anywhere below the resource location `META-INF/native-image/` and use it to construct `native-image` command line arguments. + +To avoid a situation when constituent parts of a project are built with overlapping configurations, it is recommended to use "subdirectories" within `META-INF/native-image`. +That way a JAR file built from multiple maven projects cannot suffer from overlapping `native-image` configurations. +For example: * _foo.jar_ has its configurations in `META-INF/native-image/foo_groupID/foo_artifactID` * _bar.jar_ has its configurations in `META-INF/native-image/bar_groupID/bar_artifactID` -The JAR file that contains `foo` and `bar` will then contain both configurations -without conflicting with one another. Therefore the recommended layout for -storing native image configuration data in JAR files is the following: +The JAR file that contains `foo` and `bar` will then contain both configurations without conflicting with one another. +Therefore the recommended layout for storing native image configuration data in JAR files is the following: ``` META-INF/ └── native-image @@ -42,12 +37,9 @@ META-INF/ └── native-image.properties ``` -Note that the use of `${.}` in a _native-image.properties_ file expands to the -resource location that contains that exact configuration file. This can be -useful if the _native-image.properties_ file wants to refer to resources within -its "subfolder", for example, `-H:SubstitutionResources=${.}/substitutions.json`. -Always make sure to use the option variants that take resources, i.e., use -`-H:ResourceConfigurationResources` instead of `-H:ResourceConfigurationFiles`. +Note that the use of `${.}` in a _native-image.properties_ file expands to the resource location that contains that exact configuration file. +This can be useful if the _native-image.properties_ file wants to refer to resources within its "subfolder", for example, `-H:SubstitutionResources=${.}/substitutions.json`. +Always make sure to use the option variants that take resources, i.e., use `-H:ResourceConfigurationResources` instead of `-H:ResourceConfigurationFiles`. Other options that are known to work in this context are: * `-H:DynamicProxyConfigurationResources` * `-H:JNIConfigurationResources` @@ -56,16 +48,14 @@ Other options that are known to work in this context are: * `-H:SubstitutionResources` * `-H:SerializationConfigurationResources` -By having such a composable _native-image.properties_ file, building an image -does not require any additional arguments specified on command line. It is -sufficient to just run the following command: +By having such a composable _native-image.properties_ file, building an image does not require any additional arguments specified on command line. +It is sufficient to just run the following command: ```shell $JAVA_HOME/bin/native-image -jar target/.jar ``` -To debug which configuration data gets applied for the image building, use `native-image --verbose`. This will show from where `native-image` picks up the -configurations to construct the final composite configuration command line -options for the native image builder. +To debug which configuration data gets applied for the image building, use `native-image --verbose`. +This will show from where `native-image` picks up the configurations to construct the final composite configuration command line options for the native image builder. ```shell native-image --verbose -jar build/basic-app-0.1-all.jar Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/common/native-image.properties @@ -89,44 +79,38 @@ supported. **Args** -Use this property if your project requires custom `native-image` command line options to build correctly. For example, the `native-image-configure-examples/configure-at-runtime-example` has `Args = --initialize-at-build-time=com.fasterxml.jackson.annotation.JsonProperty$Access` in its `native-image.properties` file to ensure the class `com.fasterxml.jackson.annotation.JsonProperty$Access` gets initialized at image build time. +Use this property if your project requires custom `native-image` command line options to build correctly. +For example, the `native-image-configure-examples/configure-at-runtime-example` has `Args = --initialize-at-build-time=com.fasterxml.jackson.annotation.JsonProperty$Access` in its `native-image.properties` file to ensure the class `com.fasterxml.jackson.annotation.JsonProperty$Access` gets initialized at image build time. **JavaArgs** -Sometimes it can be necessary to provide custom options to the JVM that runs the -native image builder. The `JavaArgs` property can be used in this case. +Sometimes it can be necessary to provide custom options to the JVM that runs the native image builder. +The `JavaArgs` property can be used in this case. **ImageName** -This property can be used to specify a user-defined name for the image. If -`ImageName` is not used, a name gets automatically chosen: +This property can be used to specify a user-defined name for the image. +If `ImageName` is not used, a name gets automatically chosen: * `native-image -jar ` has a default image name `` * `native-image -cp ... fully.qualified.MainClass` has a default image name `fully.qualified.mainclass` -Note that using `ImageName` does not prevent the user to override the name later via command line. For example, if `foo.bar` contains `ImageName=foo_app`: +Note that using `ImageName` does not prevent the user to override the name later via command line. +For example, if `foo.bar` contains `ImageName=foo_app`: * `native-image -jar foo.bar` generates the image `foo_app` but * `native-image -jar foo.bar application` generates the image `application` ### Order of Arguments Evaluation -The arguments passed to `native-image` are evaluated left-to-right. This also -extends to arguments that get passed indirectly via `META-INF/native-image` -based native image configuration. Suppose you have a JAR file that contains -_native-image.properties_ with `Args = -H:Optimize=0`. Then by using the -`-H:Optimize=2` option after `-cp ` you can override the setting that -comes from the JAR file. +The arguments passed to `native-image` are evaluated left-to-right. +This also extends to arguments that get passed indirectly via `META-INF/native-image` based native image configuration. +Suppose you have a JAR file that contains _native-image.properties_ with `Args = -H:Optimize=0`. +Then by using the `-H:Optimize=2` option after `-cp ` you can override the setting that comes from the JAR file. ### Specifying Default Options for Native Image -If there is a need to pass some options for every image build unconditionally, for -example, to always generate an image in verbose mode (`--verbose`), you can -make use of the `NATIVE_IMAGE_CONFIG_FILE` environment variable. -If it is set to a Java properties file, the Native Image builder will use the -default setting defined in there on each invocation. Write a -configuration file and export -`NATIVE_IMAGE_CONFIG_FILE=$HOME/.native-image/default.properties` in -`~/.bash_profile`. Every time `native-image` gets used, it will implicitly use -the arguments specified as `NativeImageArgs`, plus the arguments specified on the -command line. Here is an example of a configuration file, saved as -`~/.native-image/default.properties`: +If there is a need to pass some options for every image build unconditionally, for example, to always generate an image in verbose mode (`--verbose`), you can make use of the `NATIVE_IMAGE_CONFIG_FILE` environment variable. +If it is set to a Java properties file, the Native Image builder will use the default setting defined in there on each invocation. +Write a configuration file and export `NATIVE_IMAGE_CONFIG_FILE=$HOME/.native-image/default.properties` in `~/.bash_profile`. +Every time `native-image` gets used, it will implicitly use the arguments specified as `NativeImageArgs`, plus the arguments specified on the command line. +Here is an example of a configuration file, saved as `~/.native-image/default.properties`: ``` NativeImageArgs = --configurations-path /home/user/custom-image-configs \ @@ -146,9 +130,9 @@ export NATIVE_IMAGE_USER_HOME= $HOME/.local/share/native-image The native image build runs on the Java HotSpot VM and uses the memory management of the underlying platform. The usual Java HotSpot command-line options for garbage collection apply to the native image builder. -During the native image build, the representation of a whole program is created to -figure out which classes and methods will be used at run time. It is a -computationally intensive process. The default values for memory usage at image build time are: +During the native image build, the representation of a whole program is created to figure out which classes and methods will be used at run time. +It is a computationally intensive process. +The default values for memory usage at image build time are: ``` -Xss10M \ -Xms1G \ @@ -164,21 +148,16 @@ Check other related options to the native image builder from the `native-image - ## Runtime vs Build-Time Initialization -Building your application into a native image allows you to decide which parts -of your application should be run at image build time and which parts have to -run at image run time. +Building your application into a native image allows you to decide which parts of your application should be run at image build time and which parts have to run at image run time. -All class-initialization code (static initializers and static -field initialization) of the application you build an image for is executed -at image run time by default. Sometimes it is beneficial to allow class -initialization code to get executed at image build time for faster startup (e.g., -if some static fields get initialized to run-time independent data). This can be -controlled with the following `native-image` options: +All class-initialization code (static initializers and static field initialization) of the application you build an image for is executed at image run time by default. +Sometimes it is beneficial to allow class initialization code to get executed at image build time for faster startup (e.g., if some static fields get initialized to run-time independent data). +This can be controlled with the following `native-image` options: * `--initialize-at-build-time=` * `--initialize-at-run-time=` -In addition to that, arbitrary computations are allowed at build time that can be put into `ImageSingletons` that are -accessible at image run time. For more information please have a look at [Native Image configuration examples](https://github.com/graalvm/graalvm-demos/tree/master/native-image-configure-examples). +In addition to that, arbitrary computations are allowed at build time that can be put into `ImageSingletons` that are accessible at image run time. +For more information please have a look at [Native Image configuration examples](https://github.com/graalvm/graalvm-demos/tree/master/native-image-configure-examples). For more information, continue reading to the [Class Initialization in Native Image](ClassInitialization.md) guide. diff --git a/docs/reference-manual/native-image/C-API.md b/docs/reference-manual/native-image/C-API.md index d662844d550e..a482cb8c7788 100644 --- a/docs/reference-manual/native-image/C-API.md +++ b/docs/reference-manual/native-image/C-API.md @@ -6,7 +6,7 @@ permalink: /reference-manual/native-image/C-API/ --- # Native Image C API -Native Image provides an API for the C language for initializing isolates and attaching threads for use with the entry point feature that is demonstrated [here](README.md#images-and-entry-points). +Native Image provides an API for the C language for initializing isolates and attaching threads for use with the entry point feature that is demonstrated [here](README.md/#images-and-entry-points). The C API is available when Native Image is built as a shared library and its declarations are included in the header file that is generated during the build. ```c @@ -79,6 +79,4 @@ int graal_detach_thread(graal_isolatethread_t* thread); */ int graal_tear_down_isolate(graal_isolatethread_t* thread); ``` -In addition to the C level API, there is also a way to initialize an isolate -from Java and thus use Java and Native Image to -[implement native methods in Java](ImplementingNativeMethodsInJavaWithSVM.md). +In addition to the C level API, there is also a way to initialize an isolate from Java and thus use Java and Native Image to [implement native methods in Java](ImplementingNativeMethodsInJavaWithSVM.md). diff --git a/docs/reference-manual/native-image/ClassInitialization.md b/docs/reference-manual/native-image/ClassInitialization.md index 5b457b014fca..225191923327 100644 --- a/docs/reference-manual/native-image/ClassInitialization.md +++ b/docs/reference-manual/native-image/ClassInitialization.md @@ -19,7 +19,9 @@ Access to the static fields that were initialized at build time is transparent t Specifying class initialization policies can be complicated due to the following constraints that come from class initialization semantics: * When a class is initialized, all super classes and super interfaces with default methods must also be initialized. -Interfaces without default methods, however, are not initialized. To describe this, a short-term "relevant supertype" is used furhter, and a relevant subtype for subtypes of classes and interfaces with default methods. +Interfaces without default methods, however, are not initialized. +To describe this, a short-term "relevant supertype" is used furhter, and a relevant subtype for subtypes of classes and interfaces with default methods. + * Relevant supertypes of types initialized at build time must also be initialized at build time. * Relevant subtypes of types initialized at run time must also be initialized at run time. * No instances classes that are initialized at run time must be present in the image. @@ -31,7 +33,8 @@ To enjoy the complete out-of-the-box experience of Native Image and still get th * [Explicitly Specifying Class Initialization](#explicitly-specifying-class-initialization) To track which classes were initialized and why, one can use the flag `-H:+PrintClassInitialization`. -This flag greatly helps to configure the image build to work as intended. The goal is to have as many classes as possible initialized at build time, yet keep the correct semantics of the program. +This flag greatly helps to configure the image build to work as intended. +The goal is to have as many classes as possible initialized at build time, yet keep the correct semantics of the program. ## Build-Time Initialization of Native Image Runtime diff --git a/docs/reference-manual/native-image/DynamicProxy.md b/docs/reference-manual/native-image/DynamicProxy.md index d70cbaf4b534..e64d68d5c6d0 100644 --- a/docs/reference-manual/native-image/DynamicProxy.md +++ b/docs/reference-manual/native-image/DynamicProxy.md @@ -12,11 +12,12 @@ Dynamic proxy classes are generated from a list of interfaces. Native Image does not provide machinery for generating and interpreting bytecodes at run time. Therefore all dynamic proxy classes need to be generated at native image build time. -See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md#assisted-configuration-of-native-image-builds). +See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md/#assisted-configuration-of-native-image-builds). ## Automatic Detection -Native Image employs a simple static analysis that detects calls to `java.lang.reflect.Proxy.newProxyInstance(ClassLoader, Class[], InvocationHandler)` and `java.lang.reflect.Proxy.getProxyClass(ClassLoader, Class[])`, then tries to determine the list of interfaces that define dynamic proxies automatically. Given the list of interfaces, Native Image generates proxy classes at image build time and adds them to the native image heap. +Native Image employs a simple static analysis that detects calls to `java.lang.reflect.Proxy.newProxyInstance(ClassLoader, Class[], InvocationHandler)` and `java.lang.reflect.Proxy.getProxyClass(ClassLoader, Class[])`, then tries to determine the list of interfaces that define dynamic proxies automatically. +Given the list of interfaces, Native Image generates proxy classes at image build time and adds them to the native image heap. In addition to generating the dynamic proxy class, the constructor of the generated class that takes a `java.lang.reflect.InvocationHandler` argument, i.e., the one reflectively invoked by `java.lang.reflect.Proxy.newProxyInstance(ClassLoader, Class[], InvocationHandler)`, is registered for reflection so that dynamic proxy instances can be allocated at run time. The analysis is limited to situations where the list of interfaces comes from a constant array or an array that is allocated in the same method. diff --git a/docs/reference-manual/native-image/HostedvsRuntimeOptions.md b/docs/reference-manual/native-image/HostedvsRuntimeOptions.md index 1c15425aa568..27a9fc34f329 100644 --- a/docs/reference-manual/native-image/HostedvsRuntimeOptions.md +++ b/docs/reference-manual/native-image/HostedvsRuntimeOptions.md @@ -6,8 +6,7 @@ permalink: /reference-manual/native-image/HostedvsRuntimeOptions/ --- # Native Image Hosted and Runtime Options -Along with all the options listed in the [Options](Options.md) -guide, Native Image also distinguishes hosted and runtime options. +Along with all the options listed in the [Options](Options.md) guide, Native Image also distinguishes hosted and runtime options. * Hosted options: configure a native image build, i.e., influence what is put into the image and how the image is built. These are set using the prefix `-H:` on the command line. @@ -19,15 +18,11 @@ For developer documentation on how to define and use options, read the documenta ## List of Useful Options ### Graph Dumping -Native Image re-used the GraalVM options for graph dumping, logging, counters, -and everything else in the GraalVM debug environment. These GraalVM options can -be used both as hosted options (if you want to dump graphs of the native image -builder), and as runtime options (if you want to dump graphs during dynamic +Native Image re-used the GraalVM options for graph dumping, logging, counters, and everything else in the GraalVM debug environment. +These GraalVM options can be used both as hosted options (if you want to dump graphs of the native image builder), and as runtime options (if you want to dump graphs during dynamic compilation at runtime). -The GraalVM compiler options that work as expected include `Dump`, `DumpOnError`, `Log`, -`MethodFilter`, and the options to specify file names and ports for the dump -handlers. +The GraalVM compiler options that work as expected include `Dump`, `DumpOnError`, `Log`, `MethodFilter`, and the options to specify file names and ports for the dump handlers. For example: * To dump the compiler graphs of the native image builder: `-H:Dump= -H:MethodFilter=ClassName.MethodName`. diff --git a/docs/reference-manual/native-image/ImplementingNativeMethodsInJavaWithSVM.md b/docs/reference-manual/native-image/ImplementingNativeMethodsInJavaWithSVM.md index d5bf3ac44288..422818d8c979 100644 --- a/docs/reference-manual/native-image/ImplementingNativeMethodsInJavaWithSVM.md +++ b/docs/reference-manual/native-image/ImplementingNativeMethodsInJavaWithSVM.md @@ -6,20 +6,15 @@ permalink: /reference-manual/native-image/ImplementingNativeMethodsInJavaWithSVM --- # Implementing Native Methods in Java with Native Image -Native Image can be used to implement low-level system operations in Java and -make them available via JNI to Java code executing on a standard JVM. As -a result one can use the same language to write the application logic -as well as the system calls. +Native Image can be used to implement low-level system operations in Java and make them available via JNI to Java code executing on a standard JVM. +As a result one can use the same language to write the application logic as well as the system calls. -Note that this document describes the opposite of what is commonly done via JNI: -usually low-level system operations are implemented in C and invoked from Java -using JNI. If you are interested in how Native Image supports the common use case, -continue reading to the [Native Image JNI support](JNI.md) guide instead. +Note that this document describes the opposite of what is commonly done via JNI: usually low-level system operations are implemented in C and invoked from Java using JNI. +If you are interested in how Native Image supports the common use case, continue reading to the [Native Image JNI support](JNI.md) guide instead. ## Create a Shared Library -First of all one has to use the `native-image` builder to generate a shared library -with some JNI-compatible [entry points](README.md#build-a-shared-library). +First of all one has to use the `native-image` builder to generate a shared library with some JNI-compatible [entry points](README.md/#build-a-shared-library). Start with the Java code: ```java package org.pkg.implnative; @@ -34,20 +29,15 @@ public final class NativeImpl { } } ``` -After being processed by the `native-image` builder, the code -[exposes a C function](C-API.md) `Java_org_pkg_apinative_Native_add` -(the name follows conventions of JNI that will be handy later) and -a Native Image signature typical for JNI methods. The first parameter -is a reference to the `JNIEnv*` value. The second parameter is a reference -to the `jclass` value for the class declaring the method. The third parameter is a -portable (e.g., `long`) identifier of the [Native Image isolatethread](C-API.md). -The rest of the parameters are the actual parameters of the Java `Native.add` -method described in the next section. Compile the code with the `--shared` option: +After being processed by the `native-image` builder, the code [exposes a C function](C-API.md) `Java_org_pkg_apinative_Native_add` (the name follows conventions of JNI that will be handy later) and a Native Image signature typical for JNI methods. +The first parameter is a reference to the `JNIEnv*` value. +The second parameter is a reference to the `jclass` value for the class declaring the method. +The third parameter is a portable (e.g., `long`) identifier of the [Native Image isolatethread](C-API.md). +The rest of the parameters are the actual parameters of the Java `Native.add` method described in the next section. Compile the code with the `--shared` option: ```shell $GRAALVM/bin/native-image --shared -H:Name=libnativeimpl -cp nativeimpl ``` -The `libnativeimpl.so` is generated. We are ready to use it from standard -Java code. +The `libnativeimpl.so` is generated. We are ready to use it from standard Java code. ## Bind a Java Native Method @@ -59,16 +49,14 @@ public final class Native { private static native int add(long isolateThreadId, int a, int b); } ``` -The package name of the class, as well as the name of the method, has to correspond -(after the [JNI mangling](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html)) -to the name of the `@CEntryPoint` introduced previously. The first argument is -a portable (e.g., `long`) identifier of the Native Image isolate thread. The rest of the arguments -match the parameters of the entry point. +The package name of the class, as well as the name of the method, has to correspond (after the [JNI mangling](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html)) to the name of the `@CEntryPoint` introduced previously. +The first argument is a portable (e.g., `long`) identifier of the Native Image isolate thread. +The rest of the arguments match the parameters of the entry point. ## Loading the Native Library -The next step is to bind the JDK with the generated `.so` library. For example, -make sure the implementation of the native `Native.add` method is loaded. +The next step is to bind the JDK with the generated `.so` library. +For example, make sure the implementation of the native `Native.add` method is loaded. Simple `load` or `loadLibrary` calls will do: ```java public static void main(String[] args) { @@ -76,27 +64,23 @@ public static void main(String[] args) { // ... } ``` -This is assuming your `LD_LIBRARY_PATH` environment variable is specified, -or the `java.library.path` Java property is properly set. +This is assuming your `LD_LIBRARY_PATH` environment variable is specified, or the `java.library.path` Java property is properly set. ## Initializing a Native Image Isolate -Before making calls to the `Native.add` method, we need to create a Native Image -isolate. Native Image provides a special built-in to allow that: -`CEntryPoint.Builtin.CREATE_ISOLATE`. Define another method along your other -existing `@CEntryPoint` methods. Let it return `IsolateThread` and take no parameters: +Before making calls to the `Native.add` method, we need to create a Native Image isolate. +Native Image provides a special built-in to allow that: `CEntryPoint.Builtin.CREATE_ISOLATE`. +Define another method along your other existing `@CEntryPoint` methods. +Let it return `IsolateThread` and take no parameters: ```java public final class NativeImpl { @CEntryPoint(name = "Java_org_pkg_apinative_Native_createIsolate", builtin=CEntryPoint.Builtin.CREATE_ISOLATE) public static native IsolateThread createIsolate(); } ``` -Native Image then generates default native implementation of the -method into the final `.so` library. -The method initializes the Native Image runtime and -returns a portable identification, e.g., `long`, to hold -an instance of a [Native Image isolatethread](C-API.md). The isolate thread can then be used for -multiple invocations of the native part of your code: +Native Image then generates default native implementation of the method into the final `.so` library. +The method initializes the Native Image runtime and returns a portable identification, e.g., `long`, to hold an instance of a [Native Image isolatethread](C-API.md). +The isolate thread can then be used for multiple invocations of the native part of your code: ```java package org.pkg.apinative; @@ -115,19 +99,16 @@ public final class Native { private static native long createIsolate(); } ``` -The standard JVM is started. It initializes a Native Image isolate, -attaches the current thread to the isolate, and the universal answer `42` is -then computed three times inside of the isolate. +The standard JVM is started. It initializes a Native Image isolate, attaches the current thread to the isolate, and the universal answer `42` is then computed three times inside of the isolate. ## Calling JVM from Native Java -There is a detailed [tutorial on the C interface](https://github.com/oracle/graal/blob/master/substratevm/src/com.oracle.svm.tutorial/src/com/oracle/svm/tutorial/CInterfaceTutorial.java) of Native Image. The following example shows how to make a callback to JVM. +There is a detailed [tutorial on the C interface](https://github.com/oracle/graal/blob/master/substratevm/src/com.oracle.svm.tutorial/src/com/oracle/svm/tutorial/CInterfaceTutorial.java) of Native Image. +The following example shows how to make a callback to JVM. -In the classical setup, when C needs to call into JVM, it uses a [jni.h](JNI.md) -header file. The file defines essential JVM structures (like `JNIEnv`) as well as -functions one can invoke to inspect classes, access fields, and call methods -in the JVM. In order to call these functions from the `NativeImpl` class in the above -example, you need to define appropriate Java API wrappers of the `jni.h` concepts: +In the classical setup, when C needs to call into JVM, it uses a [jni.h](JNI.md) header file. +The file defines essential JVM structures (like `JNIEnv`) as well as functions one can invoke to inspect classes, access fields, and call methods in the JVM. +In order to call these functions from the `NativeImpl` class in the above example, you need to define appropriate Java API wrappers of the `jni.h` concepts: ```java @CContext(JNIHeaderDirectives.class) @@ -172,20 +153,14 @@ interface JMethodID extends PointerBase { } ``` -Leaving aside the meaning of `JNIHeaderDirectives` for now, the rest -of the interfaces are type-safe representations of the C pointers found in the -`jni.h` file. `JClass`, `JMethodID`, and `JObject` are all pointers. Thanks to -the above definitions, you now have Java interfaces to represent -instances of these objects in your native Java code in a type-safe way. - -The core part of any [JNI](JNI.md) API is the set of functions one can call -when talking to the JVM. There are dozens of them, but in the `JNINativeInterface` -definition, you just define wrappers for those few that are needed in the example. -Again, give them proper types, so in your native Java code you can use -`GetMethodId.find(...)`, `CallStaticVoidMethod.call(...)`, etc. In addition, -there is another important part missing in the puzzle - the `jvalue` union type -wrapping all the possible Java primitive and object types. Here are definitions -of its getters and setters: +Leaving aside the meaning of `JNIHeaderDirectives` for now, the rest of the interfaces are type-safe representations of the C pointers found in the `jni.h` file. `JClass`, `JMethodID`, and `JObject` are all pointers. +Thanks to the above definitions, you now have Java interfaces to represent instances of these objects in your native Java code in a type-safe way. + +The core part of any [JNI](JNI.md) API is the set of functions one can call when talking to the JVM. +There are dozens of them, but in the `JNINativeInterface` definition, you just define wrappers for those few that are needed in the example. +Again, give them proper types, so in your native Java code you can use `GetMethodId.find(...)`, `CallStaticVoidMethod.call(...)`, etc. +In addition, there is another important part missing in the puzzle - the `jvalue` union type wrapping all the possible Java primitive and object types. +Here are definitions of its getters and setters: ```java @CContext(JNIHeaderDirectives.class) @@ -215,13 +190,9 @@ interface JValue extends PointerBase { JValue addressOf(int index); } ``` -The `addressOf` method is a special Native Image construct used to perform -C pointer arithmetics. Given a pointer, one can treat it as the initial element of -an array, then, for example, use `addressOf(1)` to access the subsequent element. -With this you have all the API needed to make a callback - redefine -the previously introduced `NativeImpl.add` method to accept properly typed -pointers, and then use these pointers to invoke a JVM method before computing -the sum of `a + b`: +The `addressOf` method is a special Native Image construct used to perform C pointer arithmetics. +Given a pointer, one can treat it as the initial element of an array, then, for example, use `addressOf(1)` to access the subsequent element. +With this you have all the API needed to make a callback - redefine the previously introduced `NativeImpl.add` method to accept properly typed pointers, and then use these pointers to invoke a JVM method before computing the sum of `a + b`: ```java @CEntryPoint(name = "Java_org_pkg_apinative_Native_add") @@ -250,13 +221,9 @@ static int add(JNIEnvironment env, JClass clazz, @CEntryPoint.IsolateThreadConte } ``` -The above example seeks a static method `hello` and invokes it with eight -`JValue` parameters in an array reserved by `StackValue.get` -on the stack. Individual parameters are accessed by use of -the `addressOf` operator and filled with appropriate primitive values -before the call happens. The method `hello` is defined in the class `Native` -and prints values of all parameters to verify they are properly -propagated from the `NativeImpl.add` caller: +The above example seeks a static method `hello` and invokes it with eight `JValue` parameters in an array reserved by `StackValue.get` on the stack. +Individual parameters are accessed by use of the `addressOf` operator and filled with appropriate primitive values before the call happens. +The method `hello` is defined in the class `Native` and prints values of all parameters to verify they are properly propagated from the `NativeImpl.add` caller: ``` public class Native { @@ -268,11 +235,9 @@ public class Native { ``` There is just one final piece to explain: the `JNIHeaderDirectives`. -The Native Image C interface needs to understand the layout of the C structures. It -needs to know at which offset of `JNINativeInterface` structure it can find -the pointer to the `GetMethodId` function. To do so, it needs `jni.h` and additional -files during compilation. One can specify them by `@CContext` annotation and -implementation of its `Directives`: +The Native Image C interface needs to understand the layout of the C structures. +It needs to know at which offset of `JNINativeInterface` structure it can find the pointer to the `GetMethodId` function. +To do so, it needs `jni.h` and additional files during compilation. One can specify them by `@CContext` annotation and implementation of its `Directives`: ```java final class JNIHeaderDirectives implements CContext.Directives { @@ -300,10 +265,7 @@ final class JNIHeaderDirectives implements CContext.Directives { } ``` -The good thing is that `jni.h` is inside of every JDK, so one can use the -`java.home` property to locate the necessary header files. The actual logic -can, of course, be made more robust and OS-independent. +The good thing is that `jni.h` is inside of every JDK, so one can use the `java.home` property to locate the necessary header files. +The actual logic can, of course, be made more robust and OS-independent. -Implementing any JVM native method in Java and/or making callbacks to the JVM -with Native Image should now be as easy as expanding upon the given example -and invoking `native-image`. +Implementing any JVM native method in Java and/or making callbacks to the JVM with Native Image should now be as easy as expanding upon the given example and invoking `native-image`. diff --git a/docs/reference-manual/native-image/JNI.md b/docs/reference-manual/native-image/JNI.md index b658101f7818..d932552b3903 100644 --- a/docs/reference-manual/native-image/JNI.md +++ b/docs/reference-manual/native-image/JNI.md @@ -9,7 +9,7 @@ permalink: /reference-manual/native-image/JNI/ JNI is a native API that enables Java code to interact with native code and vice versa. This page gives an overview of the JNI implementation in Native Image. -See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md#assisted-configuration-of-native-image-builds). +See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md/#assisted-configuration-of-native-image-builds). ## Integration JNI support is enabled by default and built into Native Image builds. Individual classes, methods, and fields that should be accessible via JNI must be specified during native image generation in a configuration file (read below). @@ -53,7 +53,8 @@ class JNIRegistrationFeature implements Feature { } } ``` -To activate the custom feature `--features=` needs to be passed to native-image. [Native Image Build Configuration](BuildConfiguration.md) explains how this can be automated with a `native-image.properties` file in `META-INF/native-image`. +To activate the custom feature `--features=` needs to be passed to native-image. +[Native Image Build Configuration](BuildConfiguration.md) explains how this can be automated with a `native-image.properties` file in `META-INF/native-image`. ## Object Handles JNI does not permit direct access to Java objects. diff --git a/docs/reference-manual/native-image/LLVMBackend.md b/docs/reference-manual/native-image/LLVMBackend.md index e25dd6aacaa0..15e22d898bf8 100644 --- a/docs/reference-manual/native-image/LLVMBackend.md +++ b/docs/reference-manual/native-image/LLVMBackend.md @@ -6,7 +6,8 @@ permalink: /reference-manual/native-image/LLVMBackend/ --- # LLVM Backend for Native Image -Native Image includes an alternative backend which uses the [LLVM intermediate representation](https://llvm.org/docs/LangRef.html) and the [LLVM compiler](http://llvm.org/docs/CommandGuide/llc.html) to produce native executables. To use it, add the `-H:CompilerBackend=llvm` option to the Native Image invocation. +Native Image includes an alternative backend which uses the [LLVM intermediate representation](https://llvm.org/docs/LangRef.html) and the [LLVM compiler](http://llvm.org/docs/CommandGuide/llc.html) to produce native executables. +To use it, add the `-H:CompilerBackend=llvm` option to the Native Image invocation. The LLVM backend requires GraalVM's LLVM toolchain to be installed (with `gu install llvm-toolchain`). @@ -29,13 +30,15 @@ The LLVM backend requires GraalVM's LLVM toolchain to be installed (with `gu ins ## How to Add a Target Architecture to GraalVM Using LLVM Backend -An interesting use case for the LLVM backend is to target a new architecture without having to implement a complete new backend for Native Image. The following are the necessary steps to achieve this at the moment. +An interesting use case for the LLVM backend is to target a new architecture without having to implement a complete new backend for Native Image. +The following are the necessary steps to achieve this at the moment. ### Target-Specific LLVM Settings There are a few instances where the GraalVM code has to go deeper than the target-independent nature of LLVM. These are most notably inline assembly snippets to implement direct register accesses and direct register jumps (for trampolines), as well as precisions about the structure of the stack frames of the code emitted by LLVM. -All in all, this represents less than a dozen simple values to be set for each new target. It is our goal that in the future this will be the only addition needed to support a new target. +All in all, this represents less than a dozen simple values to be set for each new target. +It is our goal that in the future this will be the only addition needed to support a new target. _([Complete set of values for AArch64](https://github.com/oracle/graal/commit/80cceec6f6299181d94e844eb22dffbef3ecc9e4))_ diff --git a/docs/reference-manual/native-image/Limitations.md b/docs/reference-manual/native-image/Limitations.md index 23974f379729..38bca092e4c3 100644 --- a/docs/reference-manual/native-image/Limitations.md +++ b/docs/reference-manual/native-image/Limitations.md @@ -19,7 +19,9 @@ If an application is not optimizable, then a so-called fallback image is generat ## Class Metadata Features (Require Configuration) -The following features generally require the configuration at image build time in order to use the closed-world optimization. This configuration ensures that the minimum amount of space necessary is used in the native image binary. +The following features generally require the configuration at image build time in order to use the closed-world optimization. +This configuration ensures that the minimum amount of space necessary is used in the native image binary. + If one of the following features is used without providing a configuration at image build time, a fallback image is generated. ### Dynamic Class Loading @@ -47,7 +49,8 @@ For more details, read the [Dynamic Proxies support](DynamicProxy.md) guide. ### JNI (Java Native Interface) Native code may access Java objects, classes, methods and fields by name, in a similar way to using the reflection API in Java code. -For the same reasons, any Java artifacts accessed by name via JNI must be specified during a native image generation in a [configuration file](BuildConfiguration.md). For more details, read the [JNI Implementation](JNI.md) guide. +For the same reasons, any Java artifacts accessed by name via JNI must be specified during a native image generation in a [configuration file](BuildConfiguration.md). +For more details, read the [JNI Implementation](JNI.md) guide. As an alternative, and in addition to JNI, Native Image provides its own native interface that is much simpler than JNI and with lower overhead. It allows calls between Java and C, and access of C data structures from Java code. @@ -56,8 +59,8 @@ For more details, read the [JavaDoc of the package `org.graalvm.nativeimage.c` a ### Serialization Java serialization requires class metadata information in order to function and must be specified during a native image generation in a [configuration file](BuildConfiguration.md). -However, Java serialization has been a persistent source of security vulnerabilities. The Java architects have announced that the existing serialization mechanism will be replaced -with a new mechanism avoiding these problems in the near future. +However, Java serialization has been a persistent source of security vulnerabilities. +The Java architects have announced that the existing serialization mechanism will be replaced with a new mechanism avoiding these problems in the near future. ## Features Incompatible with Closed-World Optimization @@ -80,16 +83,12 @@ Native Image implements some Java features in a different way than the Java HotS ### Signal Handlers -Registering a signal handler requires to start a new thread that handles the -signal and invokes the shutdown hooks. By default, no signal handlers are -registered when building a native image, unless they are registered explicitly by the user. -For example, it is not recommended to register the default signal -handlers when building a shared library, but it is desirable to include -signal handlers when building native images for containerized environments, like -Docker containers. +Registering a signal handler requires to start a new thread that handles the signal and invokes the shutdown hooks. +By default, no signal handlers are registered when building a native image, unless they are registered explicitly by the user. +For example, it is not recommended to register the default signal handlers when building a shared library, but it is desirable to include signal handlers when building native images for containerized environments, like Docker containers. -To register the default signal handlers, pass the `--install-exit-handlers` option to the -`native-image` builder. This option gives you the same signal handlers as a JVM does. +To register the default signal handlers, pass the `--install-exit-handlers` option to the `native-image` builder. +This option gives you the same signal handlers as a JVM does. ### Class Initializers By default, classes are initialized at image run time. @@ -99,8 +98,7 @@ Class initialization behaviour can be adjusted using the options `--initialize- See `native-image --help` for details. Classes of the JDK class libraries are handled for you and do not need special consideration from the user. -Native Image users should be aware that class initialization at image build time -may break specific assumptions in existing code. +Native Image users should be aware that class initialization at image build time may break specific assumptions in existing code. For example, files loaded in a class initializer may not be in the same place at image build time as at image run time. Also, certain objects such as a file descriptors or running threads must not be stored into a native image binary. If such objects are reachable at image build time, image generation fails with an error. diff --git a/docs/reference-manual/native-image/NativeImageHeapdumpEnterprise.md b/docs/reference-manual/native-image/NativeImageHeapdumpEnterprise.md index 3cf3f0c9c362..9c89b0cb884f 100644 --- a/docs/reference-manual/native-image/NativeImageHeapdumpEnterprise.md +++ b/docs/reference-manual/native-image/NativeImageHeapdumpEnterprise.md @@ -8,24 +8,20 @@ permalink: /reference-manual/native-image/NativeImageHeapdump/ With GraalVM Enterprise Edition you can generate heap dumps of the Native Image processes to monitor the execution. -Native Image does not implement JVMTI agent and it is not possible to trigger -heap dump creation using tools like _VisualVM_ or _jmap_. You can build a native image for your application in a way so that it can handle certain signals and then get a heap -dump when the application receives the `USR1` signal (other supported signals are `QUIT/BREAK` for stackdumps and `USR2` to dump runtime compilation info). You only need to build your image with GraalVM Enterprise Native Image and use the `-H:+AllowVMInspection` option. +Native Image does not implement JVMTI agent and it is not possible to trigger heap dump creation using tools like _VisualVM_ or _jmap_. +You can build a native image for your application in a way so that it can handle certain signals and then get a heap dump when the application receives the `USR1` signal (other supported signals are `QUIT/BREAK` for stackdumps and `USR2` to dump runtime compilation info). +You only need to build your image with GraalVM Enterprise Native Image and use the `-H:+AllowVMInspection` option. -Another possibility is to -write a special method which will generate a heap dump at certain points in the -lifetime of your application. For example, when certain conditions are met while -executing a native image, your application code can trigger heap dump creation. -A dedicated [`org.graalvm.nativeimage.VMRuntime#dumpHeap`](https://github.com/oracle/graal/blob/master/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VMInspection.java) API exists for this -purpose. Both possibilities are covered in this guide. +Another possibility is to write a special method which will generate a heap dump at certain points in the lifetime of your application. For example, when certain conditions are met while executing a native image, your application code can trigger heap dump creation. +A dedicated [`org.graalvm.nativeimage.VMRuntime#dumpHeap`](https://github.com/oracle/graal/blob/master/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VMInspection.java) API exists for this purpose. +Both possibilities are covered in this guide. Note: This feature is available with **GraalVM Enterprise** only. ## Handle SIGUSR1 Signal -The following Java example is a simple multi-threaded application which runs for -60 seconds. There is enough time to get its PID and send the SIGUSR1 signal -which will generate a heap dump into the application's working directory. Save -the following code as _SVMHeapDump.java_ file on your disk: +The following Java example is a simple multi-threaded application which runs for 60 seconds. +There is enough time to get its PID and send the SIGUSR1 signal which will generate a heap dump into the application's working directory. +Save the following code as _SVMHeapDump.java_ file on your disk: ```java import java.text.DateFormat; import java.util.Date; @@ -81,9 +77,8 @@ $JAVA_HOME/bin/javac SVMHeapDump.java ``` If you run it on `java`, you will see that it runs for 60 seconds then finishes. -Build a native executable and provide the `-H:+AllowVMInspection` option for the -builder. This way the native executable will accept SIGUSR1 signal to produce a -heap dump. +Build a native executable and provide the `-H:+AllowVMInspection` option for the builder. +This way the native executable will accept SIGUSR1 signal to produce a heap dump. ```shell $JAVA_HOME/bin/native-image SVMHeapDump -H:+AllowVMInspection @@ -105,9 +100,8 @@ $JAVA_HOME/bin/native-image SVMHeapDump -H:+AllowVMInspection [svmheapdump:41691] [total]: 47,805.47 ms, 2.62 GB ``` -The `native-image` builder analyzes existing `SVMHeapDump.class` and creates from -it an executable file. When the command completes, `svmheapdump` is created in -the current directory. +The `native-image` builder analyzes existing `SVMHeapDump.class` and creates from it an executable file. +When the command completes, `svmheapdump` is created in the current directory. ##### Run the application and check the heap dump Run the application: @@ -121,10 +115,7 @@ Starting thread! May 15, 2020, 4:28:14 PM: Thread started, it will run for 60 seconds ``` -Open the 2nd terminal to get the process ID of the running `svmheapdump` -application using a command like `ps -C svmheapdump -o pid=` for Linux OS and -`pgrep svmheapdump` for macOS. Copy the printed process ID, e.g. 100, and use it -to send the signal to the running application: +Open the 2nd terminal to get the process ID of the running `svmheapdump` application using a command like `ps -C svmheapdump -o pid=` for Linux OS and `pgrep svmheapdump` for macOS. Copy the printed process ID, e.g. 100, and use it to send the signal to the running application: ```shell kill -SIGUSR1 100 ``` @@ -132,8 +123,7 @@ The heap dump will be available at the working directory while the application c ## Generate a Heap Dump from within a Java Application -The following Java example shows how a heap dump can be generated from within -a running Java application using `VMRuntime.dumpHeap()` after some condition is met. +The following Java example shows how a heap dump can be generated from within a running Java application using `VMRuntime.dumpHeap()` after some condition is met. The condition to generate a heap dump is provided as an option on the command line. Save the code snippet below as _SVMHeapDumpAPI.java_. @@ -186,8 +176,7 @@ public class SVMHeapDumpAPI { } } ``` -The application creates some data to have something to dump, checks the command line -to see if heap dump has to be created, and then in method `createHeapDump()` creates +The application creates some data to have something to dump, checks the command line to see if heap dump has to be created, and then in method `createHeapDump()` creates the actual heap dump, performing checks for file's existence. #### Building a Native Image @@ -219,8 +208,7 @@ $JAVA_HOME/bin/native-image SVMHeapDumpAPI When the command completes, the `svmheapdumpapi` executable is created in the current directory. ##### Run the application and check the heap dump -Now you can run your native image application and generate a heap dump from it -with the output similar to one below: +Now you can run your native image application and generate a heap dump from it with the output similar to one below: ```shell ./svmheapdumpapi --heapdump Sep 15, 2020, 4:06:36 PM: Hello GraalVM native image developer. @@ -228,4 +216,4 @@ Your command line options are: --heapdump Heap dump created /var/folders/hw/s9d78jts67gdc8cfyq5fjcdm0000gp/T/SVMHeapDump-6437252222863577987.hprof, size: 8051959 ``` -The resulting heap dump can be then opened with the [VisualVM](/tools/visualvm/) tool like any other Java heap dump. +The resulting heap dump can be then opened with the [VisualVM](../../tools/visualvm.md) tool like any other Java heap dump. diff --git a/docs/reference-manual/native-image/Options.md b/docs/reference-manual/native-image/Options.md index 63c20d8b84c8..d9be72e84b20 100644 --- a/docs/reference-manual/native-image/Options.md +++ b/docs/reference-manual/native-image/Options.md @@ -6,29 +6,23 @@ permalink: /reference-manual/native-image/Options/ --- # Native Image Options -The `native-image` builder needs to provide the classpath for all classes -using the familiar option from the `java` launcher: `-cp` is followed by a list -of directories or JAR files, separated by `:`. The name of the class containing -the `main` method is the last argument, or you can use `-jar` and provide a JAR -file that specifies the main method in its manifest. +The `native-image` builder needs to provide the classpath for all classes using the familiar option from the `java` launcher: `-cp` is followed by a list of directories or JAR files, separated by `:`. +The name of the class containing the `main` method is the last argument, or you can use `-jar` and provide a JAR file that specifies the main method in its manifest. The syntax of the `native-image` command is: -- `native-image [options] class [imagename] [options]` to build an executable file for a class in the -current working directory. Invoking it executes the native-compiled code of that +- `native-image [options] class [imagename] [options]` to build an executable file for a class in the current working directory. Invoking it executes the native-compiled code of that class. - `native-image [options] -jar jarfile [imagename] [options]` to build an image for a JAR file. -The options passed to `native-image` are evaluated left-to-right. For more information, see [Native Image Build Configuration](BuildConfiguration.md#order-of-arguments-evaluation). +The options passed to `native-image` are evaluated left-to-right. For more information, see [Native Image Build Configuration](BuildConfiguration.md/#order-of-arguments-evaluation). -The options fall into four categories: -image generation options, macro options, non-standard options, and server options. +The options fall into four categories: image generation options, macro options, non-standard options, and server options. Non-standard and server options are subject to change through a deprecation cycle. -Command-line help is available. Run `native-image --help` to get -the commands overview, and `native-image --help-extra` to print help on non-standard, -macro, and server options. +Command-line help is available. +Run `native-image --help` to get the commands overview, and `native-image --help-extra` to print help on non-standard, macro, and server options. ### Options to Native Image Builder @@ -94,7 +88,7 @@ instantiation is traced for. * `--tool:lsp`: add the Language Server Protocol support to later attach compatible debuggers to GraalVM in IDEs like VS Code * `--tool:profiler`: add profiling support to a GraalVM supported language -The `--language:python`, `--language:ruby` and `--language:R` polyglot macro options become available once the corresponding languages are added to the base GraalVM installation (see the [GraalVM Updater](https://www.graalvm.org/reference-manual/graalvm-updater/) guide). +The `--language:python`, `--language:ruby` and `--language:R` polyglot macro options become available once the corresponding languages are added to the base GraalVM installation (see the [GraalVM Updater](../graalvm-updater.md) guide). ### Non-standard Options * `--expert-options`: list image build options for experts diff --git a/docs/reference-manual/native-image/README.md b/docs/reference-manual/native-image/README.md index f54ac4b42196..c6ad06cc7082 100644 --- a/docs/reference-manual/native-image/README.md +++ b/docs/reference-manual/native-image/README.md @@ -18,11 +18,9 @@ Then it ahead-of-time compiles that reachable code and data to a native executab This entire process is called **building an image** (or the **image build time**) to clearly distinguish it from the compilation of Java source code to bytecode. Native Image supports JVM-based languages, e.g., Java, Scala, Clojure, Kotlin. -The resulting image can, optionally, execute dynamic languages like -JavaScript, Ruby, R or Python. Polyglot embeddings can also be compiled -ahead-of-time. To inform `native-image` of a guest language used by an -application, specify `--language:` for each guest language (e.g., -`--language:js`). +The resulting image can, optionally, execute dynamic languages like JavaScript, Ruby, R or Python. +Polyglot embeddings can also be compiled ahead-of-time. +To inform `native-image` of a guest language used by an application, specify `--language:` for each guest language (e.g., `--language:js`). * [Install Native Image](#install-native-image) * [Prerequisites](#prerequisites) @@ -42,7 +40,7 @@ For more information, check the [Oracle Technology Network License Agreement for ## Install Native Image -Native Image can be added to GraalVM with the [GraalVM Updater](https://www.graalvm.org/reference-manual/graalvm-updater/) tool. +Native Image can be added to GraalVM with the [GraalVM Updater](../graalvm-updater.md) tool. Run this command to install Native Image: ```shell @@ -52,13 +50,11 @@ After this additional step, the `native-image` executable will become available the `GRAALVM_HOME/bin` directory. The above command will install Native Image from the GitHub catalog for GraalVM Community users. -For GraalVM Enterprise users, the [manual installation](https://www.graalvm.org/reference-manual/graalvm-updater/#manual-installation) is required. +For GraalVM Enterprise users, the [manual installation](../graalvm-updater.md/#manual-installation) is required. ## Prerequisites -For compilation `native-image` depends on the local toolchain. Install - `glibc-devel`, `zlib-devel` (header files for the C library and `zlib`) -and `gcc`, using a package manager available on your OS. Some Linux distributions may additionally require `libstdc++-static`. +For compilation `native-image` depends on the local toolchain. Install `glibc-devel`, `zlib-devel` (header files for the C library and `zlib`) and `gcc`, using a package manager available on your OS. Some Linux distributions may additionally require `libstdc++-static`. On Oracle Linux use `yum` package manager: ```shell @@ -105,12 +101,9 @@ To build a native image of a JAR file, use: native-image [options] -jar jarfile [imagename] [options] ``` -The `native-image` command needs to provide the class path for all classes using -the familiar option from the java launcher: `-cp` followed by a list of +The `native-image` command needs to provide the class path for all classes using the familiar option from the java launcher: `-cp` followed by a list of directories or JAR files, separated by `:` on Linux and macOS platforms, or `;` on Windows. -The name of the class containing the -main method is the last argument, or you can use `-jar` and provide a JAR -file that specifies the main method in its manifest. +The name of the class containing the main method is the last argument, or you can use `-jar` and provide a JAR file that specifies the main method in its manifest. As an example, take this small Java program that reverses a String using recursion: ```java @@ -134,20 +127,18 @@ Compile it and build a native image from the Java class: javac Example.java native-image Example ``` -The native image builder ahead-of-time compiles the `Example` class into a -standalone executable, `example`, in the current working directory. Run the executable: +The native image builder ahead-of-time compiles the `Example` class into a standalone executable, `example`, in the current working directory. +Run the executable: ```shell ./example ``` -Another option to the native image builder that might be helpful is -`--install-exit-handlers`. It is not recommended to register the default signal -handlers when building a shared library. However, it is desirable to include -signal handlers when building a native image for containerized environments, like -Docker containers. The `--install-exit-handlers` option gives you the same -signal handlers that a JVM does. +Another option to the native image builder that might be helpful is `--install-exit-handlers`. +It is not recommended to register the default signal handlers when building a shared library. +However, it is desirable to include signal handlers when building a native image for containerized environments, like Docker containers. +The `--install-exit-handlers` option gives you the same signal handlers that a JVM does. -For more complex examples, visit the [native image generation](https://www.graalvm.org/examples/native-image-examples/) or [compiling a Java and Kotlin app ahead-of-time](https://www.graalvm.org/examples/java-kotlin-aot/) pages. +For more complex examples, visit the [native image generation](../../examples/native-image-examples.md) or [compiling a Java and Kotlin app ahead-of-time](../../examples/java-kotlin-aot.md) pages. ## Build a Shared Library @@ -165,7 +156,9 @@ Note: if you build a shared library where you do not specify a main class, you m As mentioned in the previous section, you need to have at least one entry point method for a native image to be useful. For shared libraries, Native Image provides the `@CEntryPoint` annotation to specify entry point methods that should be exported and callable from C. -Entry point methods must be static and may only have non-object parameters and return types – this includes Java primitives, but also Word types (including pointers). One of the parameters of an entry point method has to be of type `IsolateThread` or `Isolate`. This parameter provides the current thread's execution context for the call. +Entry point methods must be static and may only have non-object parameters and return types – this includes Java primitives, but also Word types (including pointers). +One of the parameters of an entry point method has to be of type `IsolateThread` or `Isolate`. +This parameter provides the current thread's execution context for the call. For example: @@ -176,7 +169,8 @@ For example: ``` When building a shared library, an additional C header file is generated. -This header file contains declarations for the [C API](C-API.md), which allows creating isolates and attaching threads from C code, as well as declarations for each entry point in the source code. The generated C declaration for the above example is: +This header file contains declarations for the [C API](C-API.md), which allows creating isolates and attaching threads from C code, as well as declarations for each entry point in the source code. +The generated C declaration for the above example is: ```c int add(graal_isolatethread_t* thread, int a, int b); ``` @@ -192,9 +186,9 @@ native-image -cp hello EmptyHello ... ``` -If you do not know what GraalVM distribution is set to the `PATH` environment -variable, how to determine if a native image was compiled with Community or -Enterprise Edition? Run this command: +If you do not know what GraalVM distribution is set to the `PATH` environment variable, how to determine if a native image was compiled with Community or +Enterprise Edition? +Run this command: ```shell strings emptyhello | grep com.oracle.svm.core.VM ``` @@ -229,10 +223,7 @@ com.oracle.svm.core.VM=GraalVM Java 11 EE ## Ahead-of-time Compilation Limitations -There is a small portion of Java features are not susceptible to ahead-of-time -compilation, and will therefore miss out on the performance advantages. To be -able to build a highly optimized native executable, GraalVM runs an aggressive static -analysis that requires a closed-world assumption, which means that all classes -and all bytecodes that are reachable at run time must be known at build time. -Therefore, it is not possible to load new data that have not been available -during ahead-of-time compilation. Continue reading to [GraalVM Native Image Compatibility and Optimization](Limitations.md). +There is a small portion of Java features are not susceptible to ahead-of-time compilation, and will therefore miss out on the performance advantages. +To be able to build a highly optimized native executable, GraalVM runs an aggressive static analysis that requires a closed-world assumption, which means that all classes and all bytecodes that are reachable at run time must be known at build time. +Therefore, it is not possible to load new data that have not been available during ahead-of-time compilation. +Continue reading to [GraalVM Native Image Compatibility and Optimization](Limitations.md). diff --git a/docs/reference-manual/native-image/Reflection.md b/docs/reference-manual/native-image/Reflection.md index 483653e2b70e..23016e1553e7 100644 --- a/docs/reference-manual/native-image/Reflection.md +++ b/docs/reference-manual/native-image/Reflection.md @@ -15,7 +15,7 @@ Examining and accessing program elements through `java.lang.reflect.*` or loadin Native Image tries to resolve the target elements through a static analysis that detects calls to the Reflection API. Where the analysis fails, the program elements reflectively accessed at run time must be specified using a manual configuration. -See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md#assisted-configuration-of-native-image-builds). +See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md/#assisted-configuration-of-native-image-builds). ## Automatic Detection @@ -144,7 +144,7 @@ Conditional configuration is the *preferred* way to specify reflection configura If a `condition` is omitted, the element is always included. When the same `condition` is used for two distinct elements in two configuration entries, both elements will be included when the condition is satisfied. When a configuration entry should be enabled if one of several types are reachable, it is necessary to add two configuration entries: one entry for each condition. -When used with [assisted configuration](BuildConfiguration.md#assisted-configuration-of-native-image-builds), conditional entries of existing configuration will not be fused with agent-collected entries as agent-collected entries. +When used with [assisted configuration](BuildConfiguration.md/#assisted-configuration-of-native-image-builds), conditional entries of existing configuration will not be fused with agent-collected entries as agent-collected entries. ### Configuration with Features @@ -165,7 +165,8 @@ class RuntimeReflectionRegistrationFeature implements Feature { } } ``` -To activate the custom feature `--features=` needs to be passed to native-image. [Native Image Build Configuration](BuildConfiguration.md) explains how this can be automated with a `native-image.properties` file in `META-INF/native-image`. +To activate the custom feature `--features=` needs to be passed to native-image. +[Native Image Build Configuration](BuildConfiguration.md) explains how this can be automated with a `native-image.properties` file in `META-INF/native-image`. ### Use of Reflection during Native Image Generation Reflection can be used without restrictions during a native image generation, for example, in static initializers. diff --git a/docs/reference-manual/native-image/Reports.md b/docs/reference-manual/native-image/Reports.md index d0aee5feae2b..1b518cdabfdc 100644 --- a/docs/reference-manual/native-image/Reports.md +++ b/docs/reference-manual/native-image/Reports.md @@ -6,12 +6,9 @@ permalink: /reference-manual/native-image/Reports/ --- # Points-to Analysis Reports -The points-to analysis produces two kinds of reports: analysis call tree and -image object tree. This information is produced by an intermediate step in the -image building process and represents the static analysis view of the call graph -and heap object graph. These graphs are further transformed in the image -building process before they are AOT compiled into the image and written into -the image heap, respectively. +The points-to analysis produces two kinds of reports: analysis call tree and image object tree. +This information is produced by an intermediate step in the image building process and represents the static analysis view of the call graph and heap object graph. +These graphs are further transformed in the image building process before they are AOT compiled into the image and written into the image heap, respectively. #### Call tree The call tree is a a breadth-first tree reduction of the call graph as seen by the points-to analysis. diff --git a/docs/reference-manual/native-image/Resources.md b/docs/reference-manual/native-image/Resources.md index 3c12fe49671f..03fbf4ec0073 100644 --- a/docs/reference-manual/native-image/Resources.md +++ b/docs/reference-manual/native-image/Resources.md @@ -26,7 +26,9 @@ To make calls such as `Class.getResource()` or `Class.getResourceAsStream()` (or } ``` -The configuration file's path must be provided to `native-image` with `-H:ResourceConfigurationFiles=/path/to/resource-config.json`. Alternatively, individual resource paths can also be specified directly to `native-image`: +The configuration file's path must be provided to `native-image` with `-H:ResourceConfigurationFiles=/path/to/resource-config.json`. +Alternatively, individual resource paths can also be specified directly to `native-image`: + ```shell native-image -H:IncludeResources= -H:ExcludeResources= ... ``` @@ -56,13 +58,12 @@ Then: (or alternatively with a single `.*/(Resource0|Resource1).txt$`). * Also, if we want to include everything except the `Resource2.txt` file, we can simply exclude it with `-H:IncludeResources='.*/Resource.*txt$'` followed by `-H:ExcludeResources='.*/Resource2.txt$'`. -See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md#assisted-configuration-of-native-image-builds). +See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md/#assisted-configuration-of-native-image-builds). ## Locales -It is also possible to specify which locales should be included in the image and what should be the default one. For -example, to switch the default locale to German and also include French and English, one can use the following hosted -options. +It is also possible to specify which locales should be included in the image and what should be the default one. +For example, to switch the default locale to German and also include French and English, one can use the following hosted options. ```shell native-image -H:DefaultLocale=de -H:IncludeLocales=fr,en ``` @@ -74,7 +75,8 @@ binary. Java localization support (`java.util.ResourceBundle`) enables Java code to load L10N resources and show the right user messages suitable for actual runtime settings like time locale and format, etc. -Native Image needs ahead-of-time knowledge of the resource bundles your application needs so that it can load and store the appropriate bundles for usage in the generated binary. The bundles can be specified in the resource configuration file (see above), in the `bundles` section: +Native Image needs ahead-of-time knowledge of the resource bundles your application needs so that it can load and store the appropriate bundles for usage in the generated binary. +The bundles can be specified in the resource configuration file (see above), in the `bundles` section: ```json { @@ -91,13 +93,12 @@ Alternatively, bundles can be specified directly as options to `native-image` as ```shell native-image -H:IncludeResourceBundles=your.pgk.Bundle,another.pkg.Resource,etc.Bundle ... ``` -By default, the requested bundles are included for all requested locales. In order to optimize this, it is possible to -use ``IncludeResourceBundles`` with locale specific substring, for -example ``-H:+IncludeResourceBundles=com.company.bundles.MyBundle_fr-FR`` will include the bundle only in French. +By default, the requested bundles are included for all requested locales. +In order to optimize this, it is possible to use ``IncludeResourceBundles`` with locale specific substring, for example ``-H:+IncludeResourceBundles=com.company.bundles.MyBundle_fr-FR`` will include the bundle only in French. ### JVM Mode of Localization -Resource Bundle lookup is a complex and dynamic mechanism which utilizes a lot of the infrastructure of JVM. As a result of that, it causes image size increase -for smaller applications such as Hello World. Therefore, an optimized mode is set by default in which this lookup is simplified utilizing the fact the all -bundles are known ahead of time. +Resource Bundle lookup is a complex and dynamic mechanism which utilizes a lot of the infrastructure of JVM. +As a result of that, it causes image size increase for smaller applications such as Hello World. +Therefore, an optimized mode is set by default in which this lookup is simplified utilizing the fact the all bundles are known ahead of time. In case you would like to use the original JVM lookup, use the `-H:-LocalizationOptimizedMode` option. From 59710028f1813818402af8a75a960f0682a52100 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 23 Sep 2021 23:56:50 +0300 Subject: [PATCH 397/681] Update links to internal docs from using permalinks to relative paths in graal/truffle/docs --- truffle/docs/AuxiliaryEngineCachingEnterprise.md | 2 +- truffle/docs/DynamicObjectModel.md | 2 +- truffle/docs/InteropMigration.md | 2 +- truffle/docs/LanguageTutorial.md | 2 +- truffle/docs/OnStackReplacement.md | 11 +++++------ truffle/docs/Optimizing.md | 2 +- truffle/docs/Profiling.md | 2 +- truffle/docs/README.md | 2 +- truffle/docs/StaticObjectModel.md | 2 +- 9 files changed, 13 insertions(+), 14 deletions(-) diff --git a/truffle/docs/AuxiliaryEngineCachingEnterprise.md b/truffle/docs/AuxiliaryEngineCachingEnterprise.md index fc1e709deae4..43c93e1e4eeb 100644 --- a/truffle/docs/AuxiliaryEngineCachingEnterprise.md +++ b/truffle/docs/AuxiliaryEngineCachingEnterprise.md @@ -19,7 +19,7 @@ This includes: 2. Execution and profiling of the guest application in the interpreter. 3. Compilation of the AST to machine code. -Within a single OS process, the work performed during warmup can be shared by specifying an [explicit engine](https://www.graalvm.org/reference-manual/embed-languages/#code-caching-across-multiple-contexts). +Within a single OS process, the work performed during warmup can be shared by specifying an [explicit engine](../../reference-manual/embedding/embed-languages.md/#code-caching-across-multiple-contexts). This requires language implementations to disable context-related optimizations to avoid deoptimizations between contexts that share code. Auxiliary engine caching builds upon the mechanism for disabling context-related optimizations and adds the capability to persist an engine with ASTs and optimized machine code to disk. This way, the work performed during warmup can be significantly reduced in the first application context of a new process. diff --git a/truffle/docs/DynamicObjectModel.md b/truffle/docs/DynamicObjectModel.md index f922cbaa220b..ad63e1ae0606 100644 --- a/truffle/docs/DynamicObjectModel.md +++ b/truffle/docs/DynamicObjectModel.md @@ -184,4 +184,4 @@ public abstract class MakePairNode extends BinaryExpressionNode { A high-level description of the object model has been published in [**An Object Storage Model for the Truffle Language Implementation Framework**](http://dl.acm.org/citation.cfm?id=2647517). -See [Truffle documentation](https://github.com/oracle/graal/tree/master/truffle/docs) and [publications](https://github.com/oracle/graal/blob/master/docs/Publications.md) for more tutorials, presentations, and publications about Truffle and GraalVM. +See [Truffle publications](https://github.com/oracle/graal/blob/master/docs/Publications.md) for more presentations and publications about Truffle and GraalVM. diff --git a/truffle/docs/InteropMigration.md b/truffle/docs/InteropMigration.md index 7baf9f706f45..f311f74db028 100644 --- a/truffle/docs/InteropMigration.md +++ b/truffle/docs/InteropMigration.md @@ -7,7 +7,7 @@ permalink: /graalvm-as-a-platform/language-implementation-framework/InteropMigra # Truffle Interop 2.0 This document is targeted at guest language and tool implementers. -It is recommended to read the [Truffle Library Tutorial](https://github.com/oracle/graal/blob/master/truffle/docs/TruffleLibraries.md) first, before proceeding. +It is recommended to read the [Truffle Library Tutorial](./TruffleLibraries.md) first, before proceeding. ## Motivation diff --git a/truffle/docs/LanguageTutorial.md b/truffle/docs/LanguageTutorial.md index f64a1570b074..2e14b4324c5b 100644 --- a/truffle/docs/LanguageTutorial.md +++ b/truffle/docs/LanguageTutorial.md @@ -19,5 +19,5 @@ Conference on Programming Language Design and Implementation [PLDI 2016](http:// Next Steps: * Start to subclass [TruffleLanguage](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.html) for your own language implementation. * Fork [SimpleLanguage](https://github.com/graalvm/simplelanguage), a toy language that demonstrates how to use many Truffle features. -* Embed Truffle languages in Java host applications using the [Polyglot API](https://graalvm.org/reference-manual/embed-languages/). +* Embed Truffle languages in Java host applications using the [Polyglot API](../../reference-manual/embedding/embed-languages.md). * Read [GraalVM/Truffle publications](https://github.com/oracle/graal/blob/master/docs/Publications.md). diff --git a/truffle/docs/OnStackReplacement.md b/truffle/docs/OnStackReplacement.md index 722bf2df0161..7645ae9f6ef2 100644 --- a/truffle/docs/OnStackReplacement.md +++ b/truffle/docs/OnStackReplacement.md @@ -1,7 +1,7 @@ --- layout: docs toc_group: truffle -link_title: On-Stack Replacement +link_title: On-Stack Replacement permalink: /graalvm-as-a-platform/language-implementation-framework/OnStackReplacement/ --- # On-Stack Replacement (OSR) @@ -15,7 +15,7 @@ On-stack replacement (OSR) is a technique used in Truffle to "break out" of the Truffle supports OSR for both AST interpreters (i.e., ASTs with `LoopNode`s) and bytecode interpreters (i.e., nodes with dispatch loops). In either case, Truffle uses heuristics to detect when a long-running loop is being interpreted and can perform OSR to speed up execution. -## OSR for AST interpreters +## OSR for AST interpreters Languages using standard Truffle APIs get OSR for free on Graal. The runtime tracks the number of times a `LoopNode` (created using `TruffleRuntime.createLoopNode(RepeatingNode)`) executes in the interpreter. @@ -33,9 +33,9 @@ A bytecode dispatch node typically looks something like the following: ```java class BytecodeDispatchNode extends Node { @CompilationFinal byte[] bytecode; - + ... - + @ExplodeLoop(kind = ExplodeLoop.LoopExplosionKind.MERGE_EXPLODE) Object execute(VirtualFrame frame) { int bci = 0; @@ -81,7 +81,7 @@ The example above can be refactored to support OSR as follows: class BytecodeDispatchNode extends Node implements BytecodeOSRNode { @CompilationFinal byte[] bytecode; @CompilationFinal private Object osrMetadata; - + ... Object execute(VirtualFrame frame) { @@ -176,4 +176,3 @@ For example, in the compilation log, a bytecode OSR entry may look something lik ``` See [Debugging](https://github.com/oracle/graal/blob/master/compiler/docs/Debugging.md) for more details on debugging Graal compilations. - diff --git a/truffle/docs/Optimizing.md b/truffle/docs/Optimizing.md index 1824da72f7aa..bb642996e41f 100644 --- a/truffle/docs/Optimizing.md +++ b/truffle/docs/Optimizing.md @@ -577,7 +577,7 @@ The `--engine.TraceCompilation` option also shows CallTarget invalidations with ## Ideal Graph Visualizer -The [Ideal Graph Visualizer (IGV)](https://docs.oracle.com/en/graalvm/enterprise/21/docs/tools/igv/) is a tool to understand Truffle ASTs and the GraalVM compiler graphs. +The [Ideal Graph Visualizer (IGV)](../../tools/ideal-graph-visualizer.md) is a tool to understand Truffle ASTs and the GraalVM compiler graphs. A typical usage is to run with `--vm.Dgraal.Dump=Truffle:1 --vm.Dgraal.PrintGraph=Network`, which will show you Truffle ASTs, guest-language call graphs, and the Graal graphs as they leave the Truffle phase. If the `-Dgraal.PrintGraph=Network` flag is omitted then the dump files are placed in the `graal_dumps` directory, which you should then open in IGV. diff --git a/truffle/docs/Profiling.md b/truffle/docs/Profiling.md index 1435783b2144..e09e1701786a 100644 --- a/truffle/docs/Profiling.md +++ b/truffle/docs/Profiling.md @@ -9,7 +9,7 @@ permalink: /graalvm-as-a-platform/language-implementation-framework/Profiling/ There is no shortage of tools for profiling interpreters written using Truffle. When running in JVM mode you can use standard JVM tooling such as VisualVM, Java Flight Recorder, and Oracle Developer Studio. When running in Native Image you can use `callgrind` from the Valgrind tool suite, and other system tools such as `strace`. As a language running on GraalVM, other GraalVM tools can be used. -For a broad enough definition of profiling, you can also use the [Ideal Graph Visualizer (IGV)](https://docs.oracle.com/en/graalvm/enterprise/21/docs/tools/igv/) and C1 Visualizer to inspect the compiler output. +For a broad enough definition of profiling, you can also use the [Ideal Graph Visualizer (IGV)](../../tools/ideal-graph-visualizer.md) and C1 Visualizer to inspect the compiler output. This guide is less about how to use each tool and more about suggestions for extracting the most useful information from the tools, assuming a basic knowledge of their usage. diff --git a/truffle/docs/README.md b/truffle/docs/README.md index cb063485ac24..8e6ffe01268d 100644 --- a/truffle/docs/README.md +++ b/truffle/docs/README.md @@ -50,7 +50,7 @@ Consider reading [these publications](https://github.com/oracle/graal/blob/maste Implementing a language using Truffle offers a way to interoperate with other "Truffle" languages. To learn more about verifying that your language is a valid polyglot citizen, read more about using the [Polyglot TCK](./TCK.md). Somewhat related topics worth exploring are [Truffle Libraries](./TruffleLibraries.md), as well as how to use them to implement a language [interoperability](./InteropMigration.md). -Languages implemented with Truffle can also be embedded in Java host applications using the [Polyglot API](https://graalvm.org/reference-manual/embed-languages/). +Languages implemented with Truffle can also be embedded in Java host applications using the [Polyglot API](../../reference-manual/embedding/embed-languages.md). To better understand how to improve the performance of your language please consult the documentation on [profiling](./Profiling.md) and [optimizing](./Optimizing.md) your language. Also, to better understand how to use Truffle's automated monomorphization feature (i.e., splitting), look at the [related documentation](./splitting/Monomorphization.md). diff --git a/truffle/docs/StaticObjectModel.md b/truffle/docs/StaticObjectModel.md index b19c4041b12e..d09d5454713f 100644 --- a/truffle/docs/StaticObjectModel.md +++ b/truffle/docs/StaticObjectModel.md @@ -222,7 +222,7 @@ public void wrongShape(TruffleLanguage language) { ``` While these checks are often useful, they might be redundant if the language implementation already performs them, for example using a verifier. -While the first type of checks (on property type) is very efficient and cannot be disabled, the second type of checks (on the shape) is computationally expensive and can be disabled via a command line argument: +While the first type of checks (on property type) is very efficient and cannot be disabled, the second type of checks (on the shape) is computationally expensive and can be disabled via a command line argument: ``` --experimental-options --engine.RelaxStaticObjectSafetyChecks=true ``` From ccccfdabfefdcae3c4509aa79ef440f3b40983a3 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Wed, 29 Sep 2021 13:16:34 +0300 Subject: [PATCH 398/681] Correct the path to Truffle readme, following the last meeting solution --- docs/enterprise-overview/architecture-overview.md | 6 +++--- .../graalvm-community/get-started-graalvm-community.md | 4 ++-- .../graalvm-enterprise/get-started-graalvm-enterprise.md | 4 ++-- docs/introduction.md | 8 ++++---- docs/reference-manual/compiler.md | 2 +- docs/reference-manual/embedding/embed-languages.md | 2 +- docs/reference-manual/java-on-truffle/Demos.md | 2 +- docs/reference-manual/java-on-truffle/FAQ.md | 2 +- docs/reference-manual/java-on-truffle/Interoperability.md | 2 +- docs/reference-manual/java-on-truffle/README.md | 2 +- docs/reference-manual/polyglot-programming.md | 4 ++-- docs/tools/ideal-graph-visualizer.md | 2 +- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index 6c5e3999851e..ef3aaf880a84 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -31,7 +31,7 @@ The preceding diagram illustrates a complete high-level architecture of GraalVM GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](../reference-manual/compiler.md), which is written in Java, to the HotSpot Java Virtual Machine. -In addition to running Java and JVM-based languages, [GraalVM's language implementation framework (Truffle)](../graalvm-as-a-platform/truffle/README.md), makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. +In addition to running Java and JVM-based languages, [GraalVM's language implementation framework (Truffle)](../../truffle/docs/README.md), makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. With Truffle, Java and other supported languages can directly interoperate with each other and pass data back and forth in the same memory space. ## Runtime Modes @@ -42,7 +42,7 @@ GraalVM Enterprise is unique as a runtime environment offering several modes of When running programs on the HotSpot JVM, GraalVM defaults to the [GraalVM compiler](../reference-manual/compiler.md) as the top-tier JIT compiler. At runtime, an application is loaded and executed normally on the JVM. The JVM passes bytecodes for Java or any other JVM-native language to the compiler, which compiles that to the machine code and returns it to the JVM. -Interpreters for supported languages, written on top of the [Truffle framework](../graalvm-as-a-platform/truffle/README.md), are themselves Java programs that run on the JVM. +Interpreters for supported languages, written on top of the [Truffle framework](../../truffle/docs/README.md), are themselves Java programs that run on the JVM. #### Native Image [Native Image](../reference-manual/native-image/README.md) is an innovative technology that compiles Java code into a standalone binary executable or a native shared library. @@ -50,7 +50,7 @@ The Java bytecode that is processed during the native image build includes all a A generated self-contained native executable is specific to each individual operating systems and machine architecture that does not require a JVM. #### Java on Truffle -[Java on Truffle](../reference-manual/java-on-truffle/README.md) is an implementation of the Java Virtual Machine Specification, built with the [Truffle framework](../graalvm-as-a-platform/truffle/README.md). +[Java on Truffle](../reference-manual/java-on-truffle/README.md) is an implementation of the Java Virtual Machine Specification, built with the [Truffle framework](../../truffle/docs/README.md). It is a complete Java VM that includes all core components, implements the same API as the Java Runtime Environment library, and reuses all JARs and native libraries from GraalVM. Java on Trufle is an experimental technology in GraalVM, available as of version 21.0.0. diff --git a/docs/getting-started/graalvm-community/get-started-graalvm-community.md b/docs/getting-started/graalvm-community/get-started-graalvm-community.md index ad0c41664ff9..63248c6f148e 100644 --- a/docs/getting-started/graalvm-community/get-started-graalvm-community.md +++ b/docs/getting-started/graalvm-community/get-started-graalvm-community.md @@ -335,7 +335,7 @@ javac PrettyPrintJSON.java native-image --language:js --initialize-at-build-time PrettyPrintJSON ``` The native image generatation will take several minutes as it does not just build the `PrettyPrintJSON` class, but also builds JavaScript. -Additionally, the image building requires large amounts of physical memory, especially if you build an image with the [Truffle language implementation framework](../../graalvm-as-a-platform/truffle/README.md) included, which is the case here. +Additionally, the image building requires large amounts of physical memory, especially if you build an image with the [Truffle language implementation framework](../../../truffle/docs/README.md) included, which is the case here. The resulting executable can now perform JSON pretty-printing: ```shell @@ -391,6 +391,6 @@ If you are mostly interested in GraalVM support for a specific language, or want If you are looking for the tooling support GraalVM offers, proceed to [Debugging and Monitoring Tools](../../tools/tools.md). -If you are considering GraalVM as a platform for your future language or tool implementation, go to [GraalVM as a Platform](../../graalvm-as-a-platform/truffle/README.md). +If you are considering GraalVM as a platform for your future language or tool implementation, go to [GraalVM as a Platform](../../../truffle/docs/README.md). You can find information on GraalVM's security model in the [Security Guide](../../security/security-guide.md), and rich API documentation in [GraalVM SDK Javadoc](https://www.graalvm.org/sdk/javadoc/) and [Truffle Javadoc](https://www.graalvm.org/truffle/javadoc/). diff --git a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md index 4a1c4c755809..8bf0843113bb 100644 --- a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md +++ b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md @@ -335,7 +335,7 @@ native-image --language:js --initialize-at-build-time PrettyPrintJSON The native image generatation will take several minutes as it does not just build the `PrettyPrintJSON` class, but also builds JavaScript. Additionally, the image building requires large amounts of physical memory, especially if you build an image with -the [Truffle language implementation framework](../../graalvm-as-a-platform/truffle/README.md) included, which is the case here. +the [Truffle language implementation framework](../../../truffle/docs/README.md) included, which is the case here. The resulting executable can now perform JSON pretty-printing: @@ -406,6 +406,6 @@ If you are mostly interested in GraalVM Enterprise support for a specific langua If you are looking for the tooling support GraalVM Enterprise offers, proceed to [Debugging and Monitoring Tools](../../tools/tools.md). -If you are considering GraalVM Enterprise as a platform for your future language or tool implementation, go to [GraalVM Enterprise as a Platform](../../graalvm-as-a-platform/truffle/README.md). +If you are considering GraalVM Enterprise as a platform for your future language or tool implementation, go to [GraalVM Enterprise as a Platform](../../../truffle/docs/README.md). You can find information on GraalVM Enterprise's security model in the [Security Guide](/security-guide/), and rich API documentation in [GraalVM SDK Javadoc](https://docs.oracle.com/en/graalvm/enterprise/21/sdk/index.html). diff --git a/docs/introduction.md b/docs/introduction.md index bfa72daa728c..b8af73d11e14 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -26,7 +26,7 @@ This page provides an architectural overview of GraalVM and its runtime modes, s GraalVM adds an [advanced just-in-time (JIT) optimizing compiler](https://github.com/oracle/graal/tree/master/compiler), which is written in Java, to the HotSpot Java Virtual Machine. -In addition to running Java and JVM-based languages, [GraalVM's language implementation framework (Truffle)](graalvm-as-a-platform/truffle/README.md) makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. +In addition to running Java and JVM-based languages, [GraalVM's language implementation framework (Truffle)](../truffle/docs/README.md) makes it possible to run JavaScript, Ruby, Python, and a number of other popular languages on the JVM. With GraalVM Truffle, Java and other supported languages can directly interoperate with each other and pass data back and forth in the same memory space. ## Runtime Modes @@ -37,7 +37,7 @@ GraalVM is unique as a runtime environment offering several modes of operation: When running programs on the HotSpot JVM, GraalVM defaults to the [GraalVM compiler](reference-manual/compiler.md) as the top-tier JIT compiler. At runtime, an application is loaded and executed normally on the JVM. The JVM passes bytecodes for Java or any other JVM-native language to the compiler, which compiles that to the machine code and returns it to the JVM. -Interpreters for supported languages, written on top of the [Truffle framework](graalvm-as-a-platform/truffle/README.md), are themselves Java programs that run on the JVM. +Interpreters for supported languages, written on top of the [Truffle framework](../truffle/docs/README.md), are themselves Java programs that run on the JVM. #### Native Image [Native Image](reference-manual/native-image/README.md) is an innovative technology that compiles Java code into a standalone binary executable or a native shared library. @@ -45,7 +45,7 @@ The Java bytecode that is processed during the native image build includes all a A generated self-contained native executable is specific to each individual operating systems and machine architecture that does not require a JVM. #### Java on Truffle -[Java on Truffle](reference-manual/java-on-truffle/README.md) is an implementation of the Java Virtual Machine Specification, built with the [Truffle language implementation framework](graalvm-as-a-platform/truffle/README.md). +[Java on Truffle](reference-manual/java-on-truffle/README.md) is an implementation of the Java Virtual Machine Specification, built with the [Truffle language implementation framework](../truffle/docs/README.md). It is a complete Java VM that includes all core components, implements the same API as the Java Runtime Environment library, and reuses all JARs and native libraries from GraalVM. Java on Trufle is an experimental technology in GraalVM, available as of version 21.0.0. @@ -86,7 +86,7 @@ Tools/Utilities: * [Native Image](reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable. * [LLVM toolchain](reference-manual/llvm/README.md) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime. -* [Java on Truffle](reference-manual/java-on-truffle/README.md) -- a JVM implementation built upon the [Truffle framework](graalvm-as-a-platform/truffle/README.md) to run Java via a Java bytecode interpreter. +* [Java on Truffle](reference-manual/java-on-truffle/README.md) -- a JVM implementation built upon the [Truffle framework](../truffle/docs/README.md) to run Java via a Java bytecode interpreter. Runtimes: diff --git a/docs/reference-manual/compiler.md b/docs/reference-manual/compiler.md index 7a267b595390..1e8f12e5033b 100644 --- a/docs/reference-manual/compiler.md +++ b/docs/reference-manual/compiler.md @@ -37,7 +37,7 @@ A *graph* was selected for this role. The graph can represent similar statements of different languages in the same way, like "if" statements or loops, which makes it possible to mix languages in the same program. The GraalVM compiler can then perform language-independent optimization and generate machine code on this graph. -GraalVM also includes the [Truffle language implementation framework](../graalvm-as-a-platform/truffle/README.md) -- a library, written in Java -- to build interpreters for programming languages, which then run on GraalVM. +GraalVM also includes the [Truffle language implementation framework](../../truffle/docs/README.md) -- a library, written in Java -- to build interpreters for programming languages, which then run on GraalVM. These languages can consequently benefit from the optimization possibilities of the GraalVM compiler. The pipeline for such compilation is: diff --git a/docs/reference-manual/embedding/embed-languages.md b/docs/reference-manual/embedding/embed-languages.md index 6f5c07cd083a..1a0a1b29077c 100644 --- a/docs/reference-manual/embedding/embed-languages.md +++ b/docs/reference-manual/embedding/embed-languages.md @@ -31,7 +31,7 @@ beneath each code example to choose between JavaScript, R, Ruby, and Python. Ensure you set up GraalVM before you begin. ## Compile and Run a Polyglot Application -GraalVM can run polyglot applications written in any language implemented with the [Truffle language implementation framework](../../graalvm-as-a-platform/truffle/README.md). +GraalVM can run polyglot applications written in any language implemented with the [Truffle language implementation framework](../../../truffle/docs/README.md). These languages are henceforth referenced as **guest languages**. Complete the steps in this section to create a sample polyglot diff --git a/docs/reference-manual/java-on-truffle/Demos.md b/docs/reference-manual/java-on-truffle/Demos.md index 6e1af7f10350..2bb2bc569721 100644 --- a/docs/reference-manual/java-on-truffle/Demos.md +++ b/docs/reference-manual/java-on-truffle/Demos.md @@ -131,7 +131,7 @@ GraalVM Native Image technology allows compiling applications ahead-of-time (AOT The main trade off for using Native Image is that the analysis and compilation of your program happens under the closed world assumption, meaning the static analysis needs to process all bytecode which will ever be executed in the application. This makes using some language features like dynamic class loading or reflection tricky. -Java on Truffle is a JVM implementation of a JVM bytecode interpreter, built on the [Truffle framework](../../graalvm-as-a-platform/truffle/README.md). +Java on Truffle is a JVM implementation of a JVM bytecode interpreter, built on the [Truffle framework](../../../truffle/docs/README.md). It is essentially a Java application, as are the Truffle framework itself and the GraalVM JIT compiler. All three of them can be compiled ahead-of-time with `native-image`. Using Java on Truffle for some parts of your application makes it possible to isolate the required dynamic behaviour and still use the native image on the rest of your code. diff --git a/docs/reference-manual/java-on-truffle/FAQ.md b/docs/reference-manual/java-on-truffle/FAQ.md index 8020dd6535f8..b130e63066e2 100644 --- a/docs/reference-manual/java-on-truffle/FAQ.md +++ b/docs/reference-manual/java-on-truffle/FAQ.md @@ -14,7 +14,7 @@ That means it can only run a Java program once it has been compiled to Java byte In the GraalVM family, this is similar to WebAssembly or the LLVM interpreter: while both can run C programs, they have to be complied by a C compiler first. ### Does Java running on Truffle run on HotSpot too? -Like other languages implemented with the [Truffle framework](../../graalvm-as-a-platform/truffle/README.md), it can run both as a native image or on top of HotSpot. +Like other languages implemented with the [Truffle framework](../../../truffle/docs/README.md), it can run both as a native image or on top of HotSpot. Running on top of HotSpot is currently only possible on Linux. We plan to extend this capability to macOS and Windows platforms also. diff --git a/docs/reference-manual/java-on-truffle/Interoperability.md b/docs/reference-manual/java-on-truffle/Interoperability.md index 2cd16b77f0cc..7551851d064e 100644 --- a/docs/reference-manual/java-on-truffle/Interoperability.md +++ b/docs/reference-manual/java-on-truffle/Interoperability.md @@ -7,7 +7,7 @@ permalink: /reference-manual/java-on-truffle/interoperability/ # Interoperability with Truffle Languages -Java on Truffle allows you to interface other "Truffle" languages (languages which interpreters are implemented with the [Truffle framework](../../graalvm-as-a-platform/truffle/README.md)) to create polyglot programs -- programs written in more than one language. +Java on Truffle allows you to interface other "Truffle" languages (languages which interpreters are implemented with the [Truffle framework](../../../truffle/docs/README.md)) to create polyglot programs -- programs written in more than one language. This guide describes how to load code written in foreign languages, how to export and import objects between languages, how to use Java on Truffle objects from a foreign language, how to use foreign objects from Java on Truffle, and how to embed in host Java. diff --git a/docs/reference-manual/java-on-truffle/README.md b/docs/reference-manual/java-on-truffle/README.md index 5adec74167a6..6576102facb1 100644 --- a/docs/reference-manual/java-on-truffle/README.md +++ b/docs/reference-manual/java-on-truffle/README.md @@ -14,7 +14,7 @@ See the [Implementation Details](ImplementationDetails.md) for more information. The project name behind this implementation is "Espresso". Its open source version is available on [GitHub](https://github.com/oracle/graal/tree/master/espresso). -The Java on Truffle execution mode runs Java via a Java bytecode interpreter, implemented with the [Truffle framework](../../graalvm-as-a-platform/truffle/README.md) – an open-source library for writing interpreters for programming languages. +The Java on Truffle execution mode runs Java via a Java bytecode interpreter, implemented with the [Truffle framework](../../../truffle/docs/README.md) – an open-source library for writing interpreters for programming languages. Now Java can be executed by the same principle as other languages in the GraalVM ecosystem (JavaScript, Ruby, Python, R), directly interoperate with those languages, and pass data back and forth in the same memory space. Besides complete language interoperability, with Java on Truffle you can: diff --git a/docs/reference-manual/polyglot-programming.md b/docs/reference-manual/polyglot-programming.md index 752c3584e3fd..68acdc34d70e 100644 --- a/docs/reference-manual/polyglot-programming.md +++ b/docs/reference-manual/polyglot-programming.md @@ -14,7 +14,7 @@ permalink: /reference-manual/polyglot-programming/ * [Passing Options Programmatically](#passing-options-programmatically) * [Passing Options Using JVM Arguments](#passing-options-using-jvm-arguments) -GraalVM allows users to write polyglot applications that seamlessly pass values from one language to another by means of the [Truffle language implementation framework](../graalvm-as-a-platform/truffle/README.md) (henceforth "Truffle"). +GraalVM allows users to write polyglot applications that seamlessly pass values from one language to another by means of the [Truffle language implementation framework](../../../truffle/docs/README.md) (henceforth "Truffle"). Truffle is a Java library for building programming languages implementations as interpreters for self-modifying Abstract Syntax Trees. When writing a language interpreter with Truffle, it will automatically use the GraalVM compiler as a just-in-time compiler for the language. @@ -198,7 +198,7 @@ polyglot --jvm polyglot.js polyglot.R polyglot.rb ``` We have also included a basic experimental shell for multiple languages called the _Polyglot Shell_. -It is useful to quickly test the interactivity of languages implemented with the [Truffle framework](../graalvm-as-a-platform/truffle/README.md). +It is useful to quickly test the interactivity of languages implemented with the [Truffle framework](../../truffle/docs/README.md). This is how you can start it: ```shell diff --git a/docs/tools/ideal-graph-visualizer.md b/docs/tools/ideal-graph-visualizer.md index 0ea34d012602..ac85fd3b9bf1 100644 --- a/docs/tools/ideal-graph-visualizer.md +++ b/docs/tools/ideal-graph-visualizer.md @@ -91,7 +91,7 @@ That one is initially hidden, but you can display the list of opened projects us ## Dumping Graphs -The IGV tool is developed to allow GraalVM Enterprise language implementers to optimize their languages assembled with the [Language Implentation Framework](../graalvm-as-a-platform/truffle/README.md). +The IGV tool is developed to allow GraalVM Enterprise language implementers to optimize their languages assembled with the [Language Implentation Framework](../../truffle/docs/README.md). As a development tool it should not be installed to production environments. To dump the GraalVM compiler graphs from an embedded Java application to the IGV, you need to add options to GraalVM-based processes. From a032c565ff88c5b01bbaec598f0b25432e2a4f8f Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Wed, 6 Oct 2021 19:31:49 +0300 Subject: [PATCH 399/681] Follow Benoit Daloze comments --- .../architecture-overview.md | 2 +- docs/examples/java-kotlin-aot.md | 2 +- docs/examples/native-image-examples.md | 2 +- docs/examples/polyglot-javascript-java-r.md | 2 +- .../get-started-graalvm-community.md | 2 +- .../graalvm-community/linux.md | 18 ++++++++--------- .../graalvm-community/macos.md | 18 ++++++++--------- .../get-started-graalvm-enterprise.md | 2 +- .../graalvm-enterprise/installation-linux.md | 18 ++++++++--------- .../graalvm-enterprise/installation-macos.md | 18 ++++++++--------- .../reference-manual/java-on-truffle/Demos.md | 4 ++-- .../java-on-truffle/HotSwapPluginAPI.md | 4 ++-- .../java-on-truffle/ImplementationDetails.md | 2 +- docs/reference-manual/java/README.md | 2 +- docs/reference-manual/llvm/Compiling.md | 2 +- docs/reference-manual/native-image/C-API.md | 2 +- .../native-image/DynamicProxy.md | 2 +- .../ImplementingNativeMethodsInJavaWithSVM.md | 2 +- docs/reference-manual/native-image/JNI.md | 2 +- docs/reference-manual/native-image/Options.md | 2 +- docs/reference-manual/native-image/README.md | 2 +- .../native-image/Reflection.md | 4 ++-- .../native-image/Resources.md | 2 +- docs/reference-manual/polyglot-programming.md | 2 +- docs/reference-manual/wasm/README.md | 2 +- docs/tools/vscode/graalvm/README.md | 20 +++++++++---------- docs/tools/vscode/micronaut/README.md | 2 +- 27 files changed, 71 insertions(+), 71 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index ef3aaf880a84..41b6882f5d53 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -10,7 +10,7 @@ It is designed to accelerate the execution of applications written in Java and o GraalVM Enterprise's polyglot capabilities make it possible to mix multiple programming languages in a single application while eliminating any foreign language call costs. This page provides developers, solution architects, and infrastructure architects with an architectural overview of GraalVM Enterprise, as well as information about runtime modes, supported platforms, available distributions, core and additional functionalities, and support levels for various features. -The conceptual overview and advantages of GraalVM Enterprise are described on the [Solutions Overview](overview.md) page. +The conceptual overview and advantages of GraalVM Enterprise are described on the [Solutions Overview](solutions-overview.md) page. * [GraalVM Enterprise Architecture](#graalvm-enterprise-architecture) * [Runtime Modes](#runtime-modes) diff --git a/docs/examples/java-kotlin-aot.md b/docs/examples/java-kotlin-aot.md index 725c4b71cf6f..dcca8454177f 100644 --- a/docs/examples/java-kotlin-aot.md +++ b/docs/examples/java-kotlin-aot.md @@ -38,7 +38,7 @@ export GRAALVM_HOME=/Users/${current_user}/path/to/graalvm/Contents/Home ``` Note that your paths are likely to be different depending on the download location. -3. [Install Native Image](../reference-manual/native-image/README.md/#install-native-image) to make use of the `native-image` utility. +3. [Install Native Image](../reference-manual/native-image/README.md#install-native-image) to make use of the `native-image` utility. 4. Then execute: ```shell diff --git a/docs/examples/native-image-examples.md b/docs/examples/native-image-examples.md index b1412280e053..cc24d0c1bbb2 100644 --- a/docs/examples/native-image-examples.md +++ b/docs/examples/native-image-examples.md @@ -38,7 +38,7 @@ export GRAALVM_HOME=/Users/${current_user}/path/to/graalvm/Contents/Home ``` Note that your paths are likely to be different depending on the download location. -3. [Install Native Image](../reference-manual/native-image/README.md/#install-native-image) to make use of the `native-image` utility. +3. [Install Native Image](../reference-manual/native-image/README.md#install-native-image) to make use of the `native-image` utility. 4. Then execute: ```shell diff --git a/docs/examples/polyglot-javascript-java-r.md b/docs/examples/polyglot-javascript-java-r.md index 31e52eaf4eaf..32c82e4ae8d4 100644 --- a/docs/examples/polyglot-javascript-java-r.md +++ b/docs/examples/polyglot-javascript-java-r.md @@ -17,7 +17,7 @@ git clone https://github.com/graalvm/graalvm-demos cd graalvm-demos/polyglot-javascript-java-r ``` -2. [Install GraalVM](../getting-started/graalvm-community/get-started-graalvm-community.md/#install-graalvm) on your platform. +2. [Install GraalVM](../getting-started/graalvm-community/get-started-graalvm-community.md#install-graalvm) on your platform. 3. To run the demo, you need to enable Node.js support in GraalVM: ```shell diff --git a/docs/getting-started/graalvm-community/get-started-graalvm-community.md b/docs/getting-started/graalvm-community/get-started-graalvm-community.md index 63248c6f148e..ea7c393b83d6 100644 --- a/docs/getting-started/graalvm-community/get-started-graalvm-community.md +++ b/docs/getting-started/graalvm-community/get-started-graalvm-community.md @@ -284,7 +284,7 @@ public class HelloWorld { } ``` -> Note: For compilation `native-image` depends on the local toolchain. Make sure your system meets the [prerequisites](../../reference-manual/native-image/README.md/#prerequisites). +> Note: For compilation `native-image` depends on the local toolchain. Make sure your system meets the [prerequisites](../../reference-manual/native-image/README.md#prerequisites). Compile _HelloWorld.java_ to bytecode and then build a native image: ```shell diff --git a/docs/getting-started/graalvm-community/linux.md b/docs/getting-started/graalvm-community/linux.md index 65bdf352011d..dcaf41dda0a0 100644 --- a/docs/getting-started/graalvm-community/linux.md +++ b/docs/getting-started/graalvm-community/linux.md @@ -36,18 +36,18 @@ The base distribution of GraalVM Community Edition for Linux (AMD64) platforms i The base installation can be extended with: Tools/Utilities: -* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable -* [LLVM toolchain](../../reference-manual/llvm/Compiling.md/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM +* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable +* [LLVM toolchain](../../reference-manual/llvm/Compiling.md#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible -* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible -* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible -* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible -* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) +* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible +* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible +* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Community base distribution and must be installed separately. To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. -Proceed to the [installation steps](../../reference-manual/graalvm-updater.md/#component-installation) to add any necessary language runtime or utility from above to GraalVM. +Proceed to the [installation steps](../../reference-manual/graalvm-updater.md#component-installation) to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/getting-started/graalvm-community/macos.md b/docs/getting-started/graalvm-community/macos.md index 6ef34b5b7f57..1f25684ffc00 100644 --- a/docs/getting-started/graalvm-community/macos.md +++ b/docs/getting-started/graalvm-community/macos.md @@ -66,18 +66,18 @@ The base distribution of GraalVM Community Edition for macOS includes OpenJDK wi The base installation can be extended with: Tools/Utilities: -* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable -* [LLVM toolchain](../../reference-manual/llvm/Compiling.md/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM +* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable +* [LLVM toolchain](../../reference-manual/llvm/Compiling.md#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible -* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible -* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible -* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible -* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) +* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible +* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible +* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Community base distribution and must be installed separately. To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. -Proceed to the [installation steps](../../reference-manual/graalvm-updater.md/#component-installation) to add any necessary language runtime or utility from above to GraalVM. +Proceed to the [installation steps](../../reference-manual/graalvm-updater.md#component-installation) to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md index 8bf0843113bb..f7ea8016c2fd 100644 --- a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md +++ b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md @@ -284,7 +284,7 @@ public class HelloWorld { } ``` -> Note: For compilation `native-image` depends on the local toolchain. Make sure your system meets the [prerequisites](../../reference-manual/native-image/README.md/#prerequisites). +> Note: For compilation `native-image` depends on the local toolchain. Make sure your system meets the [prerequisites](../../reference-manual/native-image/README.md#prerequisites). Compile _HelloWorld.java_ to bytecode and then build a native image: ```shell diff --git a/docs/getting-started/graalvm-enterprise/installation-linux.md b/docs/getting-started/graalvm-enterprise/installation-linux.md index 56fda647c330..c1419588f83a 100644 --- a/docs/getting-started/graalvm-enterprise/installation-linux.md +++ b/docs/getting-started/graalvm-enterprise/installation-linux.md @@ -35,18 +35,18 @@ The base distribution of GraalVM Enterprise for Linux (AMD64) platforms includes The base installation can be extended with: Tools/Utilities: -* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable -* [LLVM toolchain](../../reference-manual/llvm/Compiling.md/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM +* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable +* [LLVM toolchain](../../reference-manual/llvm/Compiling.md#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible -* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible -* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible -* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible -* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) +* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible +* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible +* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Enterprise base distribution and must be installed separately. To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. -Proceed to the [installation steps](../../reference-manual/graalvm-updater.md/#component-installation) to add any necessary language runtime or utility from above to GraalVM. +Proceed to the [installation steps](../../reference-manual/graalvm-updater.md#component-installation) to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/getting-started/graalvm-enterprise/installation-macos.md b/docs/getting-started/graalvm-enterprise/installation-macos.md index 2484107b3f84..34d15f565608 100644 --- a/docs/getting-started/graalvm-enterprise/installation-macos.md +++ b/docs/getting-started/graalvm-enterprise/installation-macos.md @@ -66,18 +66,18 @@ The base distribution of GraalVM Enterprise for macOS platforms includes Oracle The base installation can be extended with: Tools/Utilities: -* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable -* [LLVM toolchain](../../reference-manual/llvm/Compiling.md/#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM +* [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable +* [LLVM toolchain](../../reference-manual/llvm/Compiling.md#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: -* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible -* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible -* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible -* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible -* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) +* [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible +* [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible +* [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible +* [R](/../../reference-manual/r/README.md) -- GNU R 4.0.3 compatible +* [Wasm](../../reference-manual/wasm/README.md) -- WebAssembly (Wasm) ​ These runtimes are not part of the GraalVM Enterprise base distribution and must be installed separately. To assist a user with installation, GraalVM includes **GraalVM Updater**, a command line utility to install and manage additional functionalities. -Proceed to the [installation steps](../../reference-manual/graalvm-updater.md/#component-installation) to add any necessary language runtime or utility from above to GraalVM. +Proceed to the [installation steps](../../reference-manual/graalvm-updater.md#component-installation) to add any necessary language runtime or utility from above to GraalVM. diff --git a/docs/reference-manual/java-on-truffle/Demos.md b/docs/reference-manual/java-on-truffle/Demos.md index 2bb2bc569721..4a58b715cf93 100644 --- a/docs/reference-manual/java-on-truffle/Demos.md +++ b/docs/reference-manual/java-on-truffle/Demos.md @@ -145,8 +145,8 @@ This design naturally fits the point we are trying to illustrate. We can build a Prerequisites: * [GraalVM 21.0](https://www.graalvm.org/downloads/) -* [Native Image](../native-image/README.md/#install-native-image) -* [Java on Truffle](README.md/#install-java-on-truffle) +* [Native Image](../native-image/README.md#install-native-image) +* [Java on Truffle](README.md#install-java-on-truffle) 1. Clone the [project](https://github.com/graalvm/graalvm-demos) with the demo applications and navigate to the `espresso-jshell` directory: diff --git a/docs/reference-manual/java-on-truffle/HotSwapPluginAPI.md b/docs/reference-manual/java-on-truffle/HotSwapPluginAPI.md index 3f755bab2d7b..145c056976a3 100644 --- a/docs/reference-manual/java-on-truffle/HotSwapPluginAPI.md +++ b/docs/reference-manual/java-on-truffle/HotSwapPluginAPI.md @@ -7,7 +7,7 @@ permalink: /reference-manual/java-on-truffle/hotswap-plugin/ # Truffle on Java HotSwap Plugin API -With Java on Truffle you can benefit from enhanced HotSwap [capabilites](Demos.md/#enhanced-hotswap-capabilities-with-java-on-truffle) that allow the code to evolve naturally during development without the need for restarting a running application. +With Java on Truffle you can benefit from enhanced HotSwap [capabilites](Demos.md#enhanced-hotswap-capabilities-with-java-on-truffle) that allow the code to evolve naturally during development without the need for restarting a running application. ​ While code reloading (HotSwap) is a powerful tool, it is not sufficient to reflect all kinds of changes, e.g., changes to annotations, framework-specific changes such as implemented services or beans. For these things the code often needs to be executed to reload configurations or contexts before the changes are fully reflected in the running instance. @@ -138,7 +138,7 @@ Here is a sample application created from the tutorial ["Creating your first Mic Example's sources can be downloaded as a ready-made Gradle project from [here](https://guides.micronaut.io/latest/micronaut-creating-first-graal-app-gradle-java.zip). Download, unzip and open the project in your IDE. -Before you proceed, make sure that you have Java on Truffle [installed](README.md/#install-java-on-truffle) and set the GraalVM as the project SDK. +Before you proceed, make sure that you have Java on Truffle [installed](README.md#install-java-on-truffle) and set the GraalVM as the project SDK. ​ 1. In your IDE navigate to the root `build.gradle` within the sample project. Add: diff --git a/docs/reference-manual/java-on-truffle/ImplementationDetails.md b/docs/reference-manual/java-on-truffle/ImplementationDetails.md index a5a83ccb56fe..ba327146a7bf 100644 --- a/docs/reference-manual/java-on-truffle/ImplementationDetails.md +++ b/docs/reference-manual/java-on-truffle/ImplementationDetails.md @@ -35,6 +35,6 @@ This mode is not used when running in a native image since there will be no conf * Java on Truffle does not implement the `java.lang.instrument` interface. As a result it does not support the `-javaagent` VM option. * Java on Truffle currently uses the standard native libraries from the Java core library. This requires allowing a polyglot `Context` native access. Because of the way these libraries are loaded (via [Truffle NFI](../../graalvm-as-a-platform/truffle/NFI.md)), running on top of HotSpot only works on Linux (with `glibc`). Running as part of a native image works on Linux, Windows, and macOS but it currently limited to one context. * Support for [Java Management Extensions (JMX)](https://docs.oracle.com/javase/tutorial/jmx/index.html) is partial and some methods might return partial data. -* The [Debugger Protocol Implementation (JDWP)](https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/jdwp-spec.html) lacks some capabilities compared to HotSpot. It will correctly report the supported [capabilities](https://docs.oracle.com/javase/8/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Capabilities). In particular actions that require to enumerate all Java objects are not supported. However it does support a few hot reloading cases that HotSpot does not. See [Enhanced HotSwap Capabilities with Java on Truffle](Demos.md/#enhanced-hotswap-capabilities-with-java-on-truffle). +* The [Debugger Protocol Implementation (JDWP)](https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/jdwp-spec.html) lacks some capabilities compared to HotSpot. It will correctly report the supported [capabilities](https://docs.oracle.com/javase/8/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Capabilities). In particular actions that require to enumerate all Java objects are not supported. However it does support a few hot reloading cases that HotSpot does not. See [Enhanced HotSwap Capabilities with Java on Truffle](Demos.md#enhanced-hotswap-capabilities-with-java-on-truffle). * When the `java.MultiThreaded` option is set to "false", [reference processing](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/package-summary.html) will not happen. Depending on the application, this could create resource leaks. Note that this option is set to "false" automatically if Java on Truffle runs in a context where a single-threaded language is enabled (e.g., JavaScript). * Java on Truffle does not support the [Polyglot API](https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/package-summary.html) yet. However, it provides a guest Java Polyglot API, described in `polyglot.jar`. For more information, see [Interoperability with Truffle Languages](Interoperability.md). diff --git a/docs/reference-manual/java/README.md b/docs/reference-manual/java/README.md index 39b017e18d15..ce9337c9355f 100644 --- a/docs/reference-manual/java/README.md +++ b/docs/reference-manual/java/README.md @@ -28,7 +28,7 @@ This is the default and recommended mode of operation. - **jargraal**: the GraalVM compiler goes through the same warm-up phase that the rest of the Java application does. That is, it is first interpreted before its hot methods are compiled. This mode is selected with the `-XX:-UseJVMCINativeLibrary` command-line option. This will delay the time to reach peak performance as the compiler itself needs to be compiled before it produces code quickly. -This mode allows you to [debug the GraalVM compiler with a Java debugger](Operations.md/#troubleshooting-the-graalvm-compiler). +This mode allows you to [debug the GraalVM compiler with a Java debugger](Operations.md#troubleshooting-the-graalvm-compiler). ## Interoperability diff --git a/docs/reference-manual/llvm/Compiling.md b/docs/reference-manual/llvm/Compiling.md index 1500c2a0600e..aed0ad20800c 100644 --- a/docs/reference-manual/llvm/Compiling.md +++ b/docs/reference-manual/llvm/Compiling.md @@ -36,7 +36,7 @@ $GRAALVM_HOME/bin/gu install llvm-toolchain ``` The above command will install the LLVM toolchain from the GitHub catalog for GraalVM Community users. -For GraalVM Enterprise users, the [manual installation](../graalvm-updater.md/#manual-installation) is required. +For GraalVM Enterprise users, the [manual installation](../graalvm-updater.md#manual-installation) is required. To get the location of the toolchain, use the `--print-toolchain-path` argument of `lli`: ```shell diff --git a/docs/reference-manual/native-image/C-API.md b/docs/reference-manual/native-image/C-API.md index a482cb8c7788..a0611d270dfb 100644 --- a/docs/reference-manual/native-image/C-API.md +++ b/docs/reference-manual/native-image/C-API.md @@ -6,7 +6,7 @@ permalink: /reference-manual/native-image/C-API/ --- # Native Image C API -Native Image provides an API for the C language for initializing isolates and attaching threads for use with the entry point feature that is demonstrated [here](README.md/#images-and-entry-points). +Native Image provides an API for the C language for initializing isolates and attaching threads for use with the entry point feature that is demonstrated [here](README.md#images-and-entry-points). The C API is available when Native Image is built as a shared library and its declarations are included in the header file that is generated during the build. ```c diff --git a/docs/reference-manual/native-image/DynamicProxy.md b/docs/reference-manual/native-image/DynamicProxy.md index e64d68d5c6d0..0ff440024398 100644 --- a/docs/reference-manual/native-image/DynamicProxy.md +++ b/docs/reference-manual/native-image/DynamicProxy.md @@ -12,7 +12,7 @@ Dynamic proxy classes are generated from a list of interfaces. Native Image does not provide machinery for generating and interpreting bytecodes at run time. Therefore all dynamic proxy classes need to be generated at native image build time. -See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md/#assisted-configuration-of-native-image-builds). +See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md#assisted-configuration-of-native-image-builds). ## Automatic Detection diff --git a/docs/reference-manual/native-image/ImplementingNativeMethodsInJavaWithSVM.md b/docs/reference-manual/native-image/ImplementingNativeMethodsInJavaWithSVM.md index 422818d8c979..89f20feb3201 100644 --- a/docs/reference-manual/native-image/ImplementingNativeMethodsInJavaWithSVM.md +++ b/docs/reference-manual/native-image/ImplementingNativeMethodsInJavaWithSVM.md @@ -14,7 +14,7 @@ If you are interested in how Native Image supports the common use case, continue ## Create a Shared Library -First of all one has to use the `native-image` builder to generate a shared library with some JNI-compatible [entry points](README.md/#build-a-shared-library). +First of all one has to use the `native-image` builder to generate a shared library with some JNI-compatible [entry points](README.md#build-a-shared-library). Start with the Java code: ```java package org.pkg.implnative; diff --git a/docs/reference-manual/native-image/JNI.md b/docs/reference-manual/native-image/JNI.md index d932552b3903..18099d071af9 100644 --- a/docs/reference-manual/native-image/JNI.md +++ b/docs/reference-manual/native-image/JNI.md @@ -9,7 +9,7 @@ permalink: /reference-manual/native-image/JNI/ JNI is a native API that enables Java code to interact with native code and vice versa. This page gives an overview of the JNI implementation in Native Image. -See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md/#assisted-configuration-of-native-image-builds). +See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md#assisted-configuration-of-native-image-builds). ## Integration JNI support is enabled by default and built into Native Image builds. Individual classes, methods, and fields that should be accessible via JNI must be specified during native image generation in a configuration file (read below). diff --git a/docs/reference-manual/native-image/Options.md b/docs/reference-manual/native-image/Options.md index d9be72e84b20..a6b43c6fcc7d 100644 --- a/docs/reference-manual/native-image/Options.md +++ b/docs/reference-manual/native-image/Options.md @@ -16,7 +16,7 @@ class. - `native-image [options] -jar jarfile [imagename] [options]` to build an image for a JAR file. -The options passed to `native-image` are evaluated left-to-right. For more information, see [Native Image Build Configuration](BuildConfiguration.md/#order-of-arguments-evaluation). +The options passed to `native-image` are evaluated left-to-right. For more information, see [Native Image Build Configuration](BuildConfiguration.md#order-of-arguments-evaluation). The options fall into four categories: image generation options, macro options, non-standard options, and server options. Non-standard and server options are subject to change through a deprecation cycle. diff --git a/docs/reference-manual/native-image/README.md b/docs/reference-manual/native-image/README.md index c6ad06cc7082..dbe44de953dd 100644 --- a/docs/reference-manual/native-image/README.md +++ b/docs/reference-manual/native-image/README.md @@ -50,7 +50,7 @@ After this additional step, the `native-image` executable will become available the `GRAALVM_HOME/bin` directory. The above command will install Native Image from the GitHub catalog for GraalVM Community users. -For GraalVM Enterprise users, the [manual installation](../graalvm-updater.md/#manual-installation) is required. +For GraalVM Enterprise users, the [manual installation](../graalvm-updater.md#manual-installation) is required. ## Prerequisites diff --git a/docs/reference-manual/native-image/Reflection.md b/docs/reference-manual/native-image/Reflection.md index 23016e1553e7..86176c7e3a16 100644 --- a/docs/reference-manual/native-image/Reflection.md +++ b/docs/reference-manual/native-image/Reflection.md @@ -15,7 +15,7 @@ Examining and accessing program elements through `java.lang.reflect.*` or loadin Native Image tries to resolve the target elements through a static analysis that detects calls to the Reflection API. Where the analysis fails, the program elements reflectively accessed at run time must be specified using a manual configuration. -See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md/#assisted-configuration-of-native-image-builds). +See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md#assisted-configuration-of-native-image-builds). ## Automatic Detection @@ -144,7 +144,7 @@ Conditional configuration is the *preferred* way to specify reflection configura If a `condition` is omitted, the element is always included. When the same `condition` is used for two distinct elements in two configuration entries, both elements will be included when the condition is satisfied. When a configuration entry should be enabled if one of several types are reachable, it is necessary to add two configuration entries: one entry for each condition. -When used with [assisted configuration](BuildConfiguration.md/#assisted-configuration-of-native-image-builds), conditional entries of existing configuration will not be fused with agent-collected entries as agent-collected entries. +When used with [assisted configuration](BuildConfiguration.md#assisted-configuration-of-native-image-builds), conditional entries of existing configuration will not be fused with agent-collected entries as agent-collected entries. ### Configuration with Features diff --git a/docs/reference-manual/native-image/Resources.md b/docs/reference-manual/native-image/Resources.md index 03fbf4ec0073..e1aa1e5d8b72 100644 --- a/docs/reference-manual/native-image/Resources.md +++ b/docs/reference-manual/native-image/Resources.md @@ -58,7 +58,7 @@ Then: (or alternatively with a single `.*/(Resource0|Resource1).txt$`). * Also, if we want to include everything except the `Resource2.txt` file, we can simply exclude it with `-H:IncludeResources='.*/Resource.*txt$'` followed by `-H:ExcludeResources='.*/Resource2.txt$'`. -See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md/#assisted-configuration-of-native-image-builds). +See also the [guide on assisted configuration of Java resources and other dynamic features](BuildConfiguration.md#assisted-configuration-of-native-image-builds). ## Locales diff --git a/docs/reference-manual/polyglot-programming.md b/docs/reference-manual/polyglot-programming.md index 68acdc34d70e..8c4fc237511f 100644 --- a/docs/reference-manual/polyglot-programming.md +++ b/docs/reference-manual/polyglot-programming.md @@ -38,7 +38,7 @@ Ensure you set up GraalVM before you begin. The below examples work: * on a JVM, by passing `--polyglot --jvm`. * on native launchers with `--polyglot` (e.g., `js --polyglot`). - It might be required to [rebuild images](graalvm-updater.md/#rebuild-images) to access languages installed with `gu`. + It might be required to [rebuild images](graalvm-updater.md#rebuild-images) to access languages installed with `gu`. * with native executables (e.g., `native-image --language:js`). For native launchers and native executables using Java as a Target Language diff --git a/docs/reference-manual/wasm/README.md b/docs/reference-manual/wasm/README.md index 2b6f7b191cca..66b106f68f37 100644 --- a/docs/reference-manual/wasm/README.md +++ b/docs/reference-manual/wasm/README.md @@ -18,7 +18,7 @@ The support is not available by default, but you can add it to GraalVM using the gu install wasm ``` The above command will install a community version of a component from the GitHub catalog. -For GraalVM Enterprise users, the [manual component installation](../graalvm-updater.md/#component-installation) is required. +For GraalVM Enterprise users, the [manual component installation](../graalvm-updater.md#component-installation) is required. Then `wasm` launcher, which can run compiled WebAssembly binary code, becomes available. diff --git a/docs/tools/vscode/graalvm/README.md b/docs/tools/vscode/graalvm/README.md index 10b1036a5887..7e547ea330c0 100644 --- a/docs/tools/vscode/graalvm/README.md +++ b/docs/tools/vscode/graalvm/README.md @@ -192,7 +192,7 @@ Open the _launch.json_ file and click the Add Configuration... button in the bot 5. Generate load to the running process to invoke more code and generate the best configuration. Once all possible execution paths have been executed, terminate the process. At this point the Native Image agent dumps the collected configuration to the selected output directory. -Once the configuration for Native Image has been generated, follow the documentation on how to [generate a native image for a project](https://www.graalvm.org/reference-manual/native-image/#build-a-native-image) from the command line, or how to [build native images right from VS Code](../micronaut/README.md#generate-native-images-of-micronaut-projects). +Once the configuration for Native Image has been generated, follow the documentation on how to [generate a native image for a project](https://www.graalvm.org/reference-manual/native-image#build-a-native-image) from the command line, or how to [build native images right from VS Code](../micronaut/README.md#generate-native-images-of-micronaut-projects). ## Native Image Debugger @@ -461,7 +461,7 @@ For example, to connect to the Chrome Dev Tools protocol port, the content of th Alternatively, to pass the `--polyglot` option to any of the existing application launchers, add the `runtimeArgs` attribute containing the `--polyglot` value to their respective debug configurations. -> Note: In some cases (polyglot application calls Java or R, or native launcher accesses languages installed with `gu` without [rebuilding images](https://www.graalvm.org/reference-manual/graalvm-updater/#component-uninstallation)), also passing the `--jvm` option is necessary. +> Note: In some cases (polyglot application calls Java or R, or native launcher accesses languages installed with `gu` without [rebuilding images](https://www.graalvm.org/reference-manual/graalvm-updater#component-uninstallation)), also passing the `--jvm` option is necessary. ![Image Debug Configuration for Python](images/polyglot-debug-config.png) @@ -502,14 +502,14 @@ GraalVM supports smart editing features of development tools used to create gues This allows you to attach compatible development tools such as VS Code to GraalVM and to get features like auto complete, go to declaration, or documentation on hover. Currently, [GraalVM's Language Server Protocol](https://www.graalvm.org/tools/lsp/) implementation supports the following services: -* [Text Document Synchronization](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_synchronization) -* [Hover Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover) -* [Completion Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion) -* [Signature Help Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp) -* [Document Highlight Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight) -* [Code Action Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction) -* [Code Lens Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeLens) -* [Execute Command Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand) +* [Text Document Synchronization](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_synchronization) +* [Hover Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_hover) +* [Completion Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_completion) +* [Signature Help Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_signatureHelp) +* [Document Highlight Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_documentHighlight) +* [Code Action Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_codeAction) +* [Code Lens Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_codeLens) +* [Execute Command Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#workspace_executeCommand) > Note: The Language Server Protocol is offered as a technology preview and requires to pass the `--experimental-options` option for its activation. diff --git a/docs/tools/vscode/micronaut/README.md b/docs/tools/vscode/micronaut/README.md index 8e8935c68048..8f7a736296ce 100644 --- a/docs/tools/vscode/micronaut/README.md +++ b/docs/tools/vscode/micronaut/README.md @@ -11,7 +11,7 @@ permalink: /tools/vscode/micronaut-extension/ The extension is Technology Preview. The extension also enables the [Micronaut Launch](https://micronaut.io/launch/) application that allows you to create Micronaut projects through an interface inside VS Code, in addition to using the console CLI. -There are, of course, other ways to create a new Micronaut application. If you provide a path to the [Micronaut CLI installation](https://micronaut-projects.github.io/micronaut-starter/latest/guide/#installation), you can create a project using the `mn` executable. If you prefer not to install the Micronaut CLI, and you are running on Linux or macOS, you can `curl` the project. Lastly, you can navigate to Micronaut Launch in a browser, create a new project, download it and open in VS Code. +There are, of course, other ways to create a new Micronaut application. If you provide a path to the [Micronaut CLI installation](https://micronaut-projects.github.io/micronaut-starter/latest/guide#installation), you can create a project using the `mn` executable. If you prefer not to install the Micronaut CLI, and you are running on Linux or macOS, you can `curl` the project. Lastly, you can navigate to Micronaut Launch in a browser, create a new project, download it and open in VS Code. In combination with the [GraalVM Tools for Java extension](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm), you can run Micronaut projects on GraalVM, and debug them directly from the VS Code development environment with different debugging protocols enabled with the extension. This extension for Micronaut was also developed to help developers build native images directly from VS Code. From 5328deb3b404335edd6b24d167d8233f1568b5ca Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Wed, 6 Oct 2021 19:48:19 +0300 Subject: [PATCH 400/681] Follow Benoit Daloze comments --- truffle/docs/AOTOverview.md | 2 +- truffle/docs/AuxiliaryEngineCachingEnterprise.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/truffle/docs/AOTOverview.md b/truffle/docs/AOTOverview.md index d03e1f3ba362..6cc08039af29 100644 --- a/truffle/docs/AOTOverview.md +++ b/truffle/docs/AOTOverview.md @@ -28,7 +28,7 @@ For more information see [TruffleLanguage.patchContext](https://www.graalvm.org/ ### Code sharing within the same Isolate/Process A polyglot engine can be used in order to determine the scope of code sharing between contexts. -An example of how that can be done can be found in the [reference manual](https://www.graalvm.org/reference-manual/embed-languages/#code-caching-across-multiple-contexts). +An example of how that can be done can be found in the [reference manual](../../docs/reference-manual/embedding/embed-languages.md#code-caching-across-multiple-contexts). When a language is initialized for a polyglot context, a new language instance is requested from an engine. If the language supports [ContextPolicy.SHARED](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.ContextPolicy.html#SHARED), then the language instance will be reused for an engine instance. The source parsing cache is associated with a language instance, so parsing happens once per language instance. diff --git a/truffle/docs/AuxiliaryEngineCachingEnterprise.md b/truffle/docs/AuxiliaryEngineCachingEnterprise.md index 43c93e1e4eeb..3f829d487181 100644 --- a/truffle/docs/AuxiliaryEngineCachingEnterprise.md +++ b/truffle/docs/AuxiliaryEngineCachingEnterprise.md @@ -19,7 +19,7 @@ This includes: 2. Execution and profiling of the guest application in the interpreter. 3. Compilation of the AST to machine code. -Within a single OS process, the work performed during warmup can be shared by specifying an [explicit engine](../../reference-manual/embedding/embed-languages.md/#code-caching-across-multiple-contexts). +Within a single OS process, the work performed during warmup can be shared by specifying an [explicit engine](../../docs/reference-manual/embedding/embed-languages.md#code-caching-across-multiple-contexts). This requires language implementations to disable context-related optimizations to avoid deoptimizations between contexts that share code. Auxiliary engine caching builds upon the mechanism for disabling context-related optimizations and adds the capability to persist an engine with ASTs and optimized machine code to disk. This way, the work performed during warmup can be significantly reduced in the first application context of a new process. From 301a4c304f4415d7c46cd0fe01f2a88d3ca4a0d3 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 7 Oct 2021 13:42:37 +0300 Subject: [PATCH 401/681] Follow Gilles D. comments --- docs/enterprise-overview/architecture-overview.md | 2 +- docs/getting-started/graalvm-community/linux.md | 2 +- docs/getting-started/graalvm-community/macos.md | 2 +- docs/getting-started/graalvm-enterprise/installation-linux.md | 2 +- docs/getting-started/graalvm-enterprise/installation-macos.md | 2 +- docs/reference-manual/graalvm-updater.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index 41b6882f5d53..5ef72aecffed 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -100,10 +100,10 @@ Tools/Utilities: * [Native Image](../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native platform executable. * [LLVM toolchain](../reference-manual/llvm/README.md) -- a set of tools and APIs for compiling native programs to bitcode that can be executed on GraalVM. -* [Java on Truffle](../reference-manual/java-on-truffle/README.md) -- a JVM implementation built upon the [Truffle framework](/graalvm-as-a-platform/language-implementation-framework/) to run Java via a Java bytecode interpreter. Runtimes: +* [Java on Truffle](../reference-manual/java-on-truffle/README.md) -- a JVM implementation built upon the [Truffle framework](../../truffle/docs/README.md) to run Java via a Java bytecode interpreter. * [Node.js](../reference-manual/js/README.md) -- the Node.js 14.17.6 runtime for JavaScript * [Python](../reference-manual/python/README.md) -- Python 3.8.5 compatible * [Ruby](../reference-manual/ruby/README.md) -- Ruby 2.7.3 compatible diff --git a/docs/getting-started/graalvm-community/linux.md b/docs/getting-started/graalvm-community/linux.md index dcaf41dda0a0..fa4cf5873ff6 100644 --- a/docs/getting-started/graalvm-community/linux.md +++ b/docs/getting-started/graalvm-community/linux.md @@ -38,9 +38,9 @@ The base installation can be extended with: Tools/Utilities: * [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable * [LLVM toolchain](../../reference-manual/llvm/Compiling.md#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM * [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible * [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible * [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible diff --git a/docs/getting-started/graalvm-community/macos.md b/docs/getting-started/graalvm-community/macos.md index 1f25684ffc00..3ed2bc31fe32 100644 --- a/docs/getting-started/graalvm-community/macos.md +++ b/docs/getting-started/graalvm-community/macos.md @@ -68,9 +68,9 @@ The base installation can be extended with: Tools/Utilities: * [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable * [LLVM toolchain](../../reference-manual/llvm/Compiling.md#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM * [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible * [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible * [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible diff --git a/docs/getting-started/graalvm-enterprise/installation-linux.md b/docs/getting-started/graalvm-enterprise/installation-linux.md index c1419588f83a..e40d026bc347 100644 --- a/docs/getting-started/graalvm-enterprise/installation-linux.md +++ b/docs/getting-started/graalvm-enterprise/installation-linux.md @@ -37,9 +37,9 @@ The base installation can be extended with: Tools/Utilities: * [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable * [LLVM toolchain](../../reference-manual/llvm/Compiling.md#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM * [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible * [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible * [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible diff --git a/docs/getting-started/graalvm-enterprise/installation-macos.md b/docs/getting-started/graalvm-enterprise/installation-macos.md index 34d15f565608..dbd2f65e64fc 100644 --- a/docs/getting-started/graalvm-enterprise/installation-macos.md +++ b/docs/getting-started/graalvm-enterprise/installation-macos.md @@ -68,9 +68,9 @@ The base installation can be extended with: Tools/Utilities: * [Native Image](../../reference-manual/native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable * [LLVM toolchain](../../reference-manual/llvm/Compiling.md#llvm-toolchain-for-compiling-cc) -- a set of tools and APIs for compiling native programs to bitcode that can be executed with on the GraalVM runtime -* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: +* [Java on Truffle](../../reference-manual/java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM * [Node.js](../../reference-manual/js/README.md) -- Node.js v14.17.6 compatible * [Python](../../reference-manual/python/README.md) -- Python 3.8.5 compatible * [Ruby](../../reference-manual/ruby/README.md) -- Ruby 2.7.2 compatible diff --git a/docs/reference-manual/graalvm-updater.md b/docs/reference-manual/graalvm-updater.md index fd9bd47d4ee3..bc1754a85fe0 100644 --- a/docs/reference-manual/graalvm-updater.md +++ b/docs/reference-manual/graalvm-updater.md @@ -33,9 +33,9 @@ Tools/Utilities: * [Native Image](native-image/README.md) -- a technology to compile an application ahead-of-time into a native executable * [LLVM toolchain](llvm/README.md) -- a set of tools and APIs for compiling native programs to bitcode that can be executed on GraalVM -* [Java on Truffle](java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM Runtimes: +* [Java on Truffle](java-on-truffle/README.md) -- a Java Virtual Machine implementation based on a Truffle interpreter for GraalVM * [Node.js](js/README.md) -- Node.js 14.16.1 compatible * [Python](python/README.md) -- Python 3.8.5-compatible * [Ruby](ruby/README.md) -- Ruby 2.7.3-compatible From f9134bf8bd37bb3dca5f75d6fe2ce35a7c166e8d Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Thu, 7 Oct 2021 13:53:39 +0300 Subject: [PATCH 402/681] Fix broken links reported by absolutize.rb script --- docs/graalvm-as-a-platform/graalvm-as-a-platform.md | 4 ++-- docs/graalvm-as-a-platform/implement-instrument.md | 4 ++-- docs/graalvm-as-a-platform/implement-language.md | 6 +++--- .../java-on-truffle/ImplementationDetails.md | 4 ++-- docs/reference-manual/polyglot-programming.md | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/graalvm-as-a-platform/graalvm-as-a-platform.md b/docs/graalvm-as-a-platform/graalvm-as-a-platform.md index f5cd20a924a5..7c5af0090264 100644 --- a/docs/graalvm-as-a-platform/graalvm-as-a-platform.md +++ b/docs/graalvm-as-a-platform/graalvm-as-a-platform.md @@ -8,12 +8,12 @@ toc_group: graalvm-as-a-platform # GraalVM as a Platform -GraalVM is an open ecosystem and allows users to implement a custom language or tool on top of it with the [Truffle language implementation framework](truffle/README.md) which offers APIs for writing interpreters for programming languages in the form of Java programs. +GraalVM is an open ecosystem and allows users to implement a custom language or tool on top of it with the [Truffle language implementation framework](../../truffle/docs/README.md) which offers APIs for writing interpreters for programming languages in the form of Java programs. GraalVM loads and runs the Truffle framework, which itself is a Java program -- a collection of JAR files -- together with interpreters. These get optimized at runtime into efficient machine code for executing loaded programs. -Learn more about this framework from its [reference documentation](truffle/README.md). +Learn more about this framework from its [reference documentation](../../truffle/docs/README.md). ## Implement Your Language diff --git a/docs/graalvm-as-a-platform/implement-instrument.md b/docs/graalvm-as-a-platform/implement-instrument.md index 697d245a9f83..a4a3f54ea8e6 100644 --- a/docs/graalvm-as-a-platform/implement-instrument.md +++ b/docs/graalvm-as-a-platform/implement-instrument.md @@ -46,7 +46,7 @@ These are [onCreate](https://github.com/graalvm/simpletool/blob/master/src/main/ The `onCreate` and `onDispose` methods are self-explanatory: they are called by the framework when the instrument is created and disposed. We will discuss their implementations later, but first let us discuss the remaining one: `getOptionDescriptors`. -The [Truffle language implementation framework](/graalvm-as-a-platform/language-implementation-framework/) comes with its own system for specifying command-line options. +The [Truffle language implementation framework](../../truffle/docs/README.md) comes with its own system for specifying command-line options. These options allow tool users to control the tool either from the command line or when creating [polyglot contexts](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/Context.html). It is annotation-based, and examples for such options are the [ENABLED](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L91) and [PRINT_COVERAGE](https://github.com/graalvm/simpletool/blob/master/src/main/java/com/oracle/truffle/st/SimpleCoverageInstrument.java#L97) fields of `SimpleCoverageInstrument`. Both of these are static final fields of the type [OptionKey](https://www.graalvm.org/truffle/javadoc/org/graalvm/options/OptionKey.html) annotated with [Option](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Option.html) which, similar to the `Registration` annotation, provides some metadata for the option. @@ -128,7 +128,7 @@ As mentioned before, Simple Tool is a Maven project. Setting `JAVA_HOME` to a GraalVM installation and running `mvn package` produces a `target/simpletool-.jar`. This is the Simple Tool distribution form. -The [Truffle framework](truffle/README.md) offers a clear separation between the language/tooling code and the application code. +The [Truffle framework](../../truffle/docs/README.md) offers a clear separation between the language/tooling code and the application code. For this reason, putting the JAR on the class path will not result in the framework realizing a new tool is needed. To achieve this we use `--vm.Dtruffle.class.path.append=/path/to/simpletool-.jar` as is illustrated in a [launcher script for our simple tool](https://github.com/graalvm/simpletool/blob/master/simpletool). This script also shows we can [set the CLI options](https://github.com/graalvm/simpletool/blob/master/simpletool#L19) we specified for Simple Tool. diff --git a/docs/graalvm-as-a-platform/implement-language.md b/docs/graalvm-as-a-platform/implement-language.md index de08b6962c7a..07b0a70facc2 100644 --- a/docs/graalvm-as-a-platform/implement-language.md +++ b/docs/graalvm-as-a-platform/implement-language.md @@ -11,7 +11,7 @@ toc_group: graalvm-as-a-platform We have found that the easiest way to get started with implementing your own language is by extending an existing language such as SimpleLanguage. [SimpleLanguage](https://github.com/graalvm/simplelanguage) is a demonstration language built using the [Language API](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/package-summary.html). The SimpleLanguage project provides a showcase on how to use the Language APIs for writing your own language. -It aims to use most of the available [Truffle language implementation framework](truffle/README.md) (henceforth "Truffle") features, and documents their use extensively with inline source documentation. +It aims to use most of the available [Truffle language implementation framework](../../truffle/docs/README.md) (henceforth "Truffle") features, and documents their use extensively with inline source documentation. To start, ensure [Maven3](https://maven.apache.org/download.cgi) and GraalVM are available in your system. @@ -48,7 +48,7 @@ The SimpleLanguage demonstration language is licensed under the [Universal Permi ## IDE Setup -The [Truffle framework](truffle/README.md) provides language-agnostic infrastructure to realize standard IDE features by providing additional APIs. +The [Truffle framework](../../truffle/docs/README.md) provides language-agnostic infrastructure to realize standard IDE features by providing additional APIs. If you would like to experiment with your language and get the benefits of an IDE, consider importing SimpleLanguage as an example. ### Eclipse @@ -248,7 +248,7 @@ A sample POM using `--upgrade-module-path` to export Language API packages can b ### Other JVM Implementations -Unlike GraalVM, which includes all the dependencies needed to run a language implemented with [Truffle](truffle/README.md), other JVM implementations need additional JARs to be present on the class path. +Unlike GraalVM, which includes all the dependencies needed to run a language implemented with [Truffle](../../truffle/docs/README.md), other JVM implementations need additional JARs to be present on the class path. These are the Language API and GraalVM SDK JARs available from Maven Central. Assuming `JAVA_HOME` points to a stock JDK installation, and that the current working directory is the `simplelanguage` directory and the Language API and GraalVM SDK JARs are present in that directory, one can execute SimpleLanguage with the following command: diff --git a/docs/reference-manual/java-on-truffle/ImplementationDetails.md b/docs/reference-manual/java-on-truffle/ImplementationDetails.md index ba327146a7bf..866eb7486e3b 100644 --- a/docs/reference-manual/java-on-truffle/ImplementationDetails.md +++ b/docs/reference-manual/java-on-truffle/ImplementationDetails.md @@ -21,7 +21,7 @@ Java on Truffle is a minified Java VM that implements all core components of a V * Java Debug Wire Protocol (JDWP) Java on Truffle reuses all JARs and native libraries from GraalVM. -All native libraries and methods are loaded/accessed/called via [Truffle Native Function Interface (JNI)](../../graalvm-as-a-platform/truffle/NFI.md). +All native libraries and methods are loaded/accessed/called via [Truffle Native Function Interface (JNI)](../../../truffle/docs/NFI.md). JNI handles are implemented in Java on Truffle, e.g., all Truffle NFI methods only receive and return primitives. Some methods are substituted for performance, e.g., `Math.sqrt`, `System.arraycopy`, avoiding the expensive transition to native. @@ -33,7 +33,7 @@ This mode is not used when running in a native image since there will be no conf * Java on Truffle does not implement the [JVM Tool Interface (JVMTI)](https://docs.oracle.com/en/java/javase/11/docs/specs/jvmti.html). As a result, it does not support the `-agentlib`, or `-agentpath` VM options. * Java on Truffle does not implement the `java.lang.instrument` interface. As a result it does not support the `-javaagent` VM option. -* Java on Truffle currently uses the standard native libraries from the Java core library. This requires allowing a polyglot `Context` native access. Because of the way these libraries are loaded (via [Truffle NFI](../../graalvm-as-a-platform/truffle/NFI.md)), running on top of HotSpot only works on Linux (with `glibc`). Running as part of a native image works on Linux, Windows, and macOS but it currently limited to one context. +* Java on Truffle currently uses the standard native libraries from the Java core library. This requires allowing a polyglot `Context` native access. Because of the way these libraries are loaded (via [Truffle NFI](../../../truffle/docs/NFI.md)), running on top of HotSpot only works on Linux (with `glibc`). Running as part of a native image works on Linux, Windows, and macOS but it currently limited to one context. * Support for [Java Management Extensions (JMX)](https://docs.oracle.com/javase/tutorial/jmx/index.html) is partial and some methods might return partial data. * The [Debugger Protocol Implementation (JDWP)](https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/jdwp-spec.html) lacks some capabilities compared to HotSpot. It will correctly report the supported [capabilities](https://docs.oracle.com/javase/8/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Capabilities). In particular actions that require to enumerate all Java objects are not supported. However it does support a few hot reloading cases that HotSpot does not. See [Enhanced HotSwap Capabilities with Java on Truffle](Demos.md#enhanced-hotswap-capabilities-with-java-on-truffle). * When the `java.MultiThreaded` option is set to "false", [reference processing](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/package-summary.html) will not happen. Depending on the application, this could create resource leaks. Note that this option is set to "false" automatically if Java on Truffle runs in a context where a single-threaded language is enabled (e.g., JavaScript). diff --git a/docs/reference-manual/polyglot-programming.md b/docs/reference-manual/polyglot-programming.md index 8c4fc237511f..8377017f6ae2 100644 --- a/docs/reference-manual/polyglot-programming.md +++ b/docs/reference-manual/polyglot-programming.md @@ -14,7 +14,7 @@ permalink: /reference-manual/polyglot-programming/ * [Passing Options Programmatically](#passing-options-programmatically) * [Passing Options Using JVM Arguments](#passing-options-using-jvm-arguments) -GraalVM allows users to write polyglot applications that seamlessly pass values from one language to another by means of the [Truffle language implementation framework](../../../truffle/docs/README.md) (henceforth "Truffle"). +GraalVM allows users to write polyglot applications that seamlessly pass values from one language to another by means of the [Truffle language implementation framework](../../truffle/docs/README.md) (henceforth "Truffle"). Truffle is a Java library for building programming languages implementations as interpreters for self-modifying Abstract Syntax Trees. When writing a language interpreter with Truffle, it will automatically use the GraalVM compiler as a just-in-time compiler for the language. From 9e3e2489cbda59d727e5ec8febfa7c7ccd2b47db Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Fri, 8 Oct 2021 14:44:53 +0300 Subject: [PATCH 403/681] Fix broken links reported by check_links.rb script --- .../graalvm-community/get-started-graalvm-community.md | 2 +- docs/reference-manual/embedding/embed-languages.md | 7 ++----- truffle/docs/LanguageTutorial.md | 2 +- truffle/docs/Optimizing.md | 2 +- truffle/docs/Profiling.md | 2 +- truffle/docs/README.md | 2 +- 6 files changed, 7 insertions(+), 10 deletions(-) diff --git a/docs/getting-started/graalvm-community/get-started-graalvm-community.md b/docs/getting-started/graalvm-community/get-started-graalvm-community.md index ea7c393b83d6..6e92f80a5719 100644 --- a/docs/getting-started/graalvm-community/get-started-graalvm-community.md +++ b/docs/getting-started/graalvm-community/get-started-graalvm-community.md @@ -188,7 +188,7 @@ ruby [options] program.rb ``` GraalVM Ruby runtime environment uses the -[same options as the standard implementation of Ruby](../../reference-manual/ruby/Options.md), +[same options as the standard implementation of Ruby](../../reference-manual/ruby/options.md), with some additions. For example: ```shell gem install chunky_png diff --git a/docs/reference-manual/embedding/embed-languages.md b/docs/reference-manual/embedding/embed-languages.md index 1a0a1b29077c..af23ca87db09 100644 --- a/docs/reference-manual/embedding/embed-languages.md +++ b/docs/reference-manual/embedding/embed-languages.md @@ -17,11 +17,10 @@ permalink: /reference-manual/embed-languages/ * [Build Native Images from Polyglot Applications](#build-native-images-from-polyglot-applications) * [Code Caching Across Multiple Contexts](#code-caching-across-multiple-contexts) * [Embed languages in Guest Languages](#embed-languages-in-guest-languages) -* [Step Through with Execution Listeners](#step-through-with-execution-listeners) * [Build a Shell for Many Languages](#build-a-shell-for-many-languages) +* [Step Through with Execution Listeners](#step-through-with-execution-listeners) * [Configure Sandbox Resource Limits](#configure-sandbox-resource-limits) - The GraalVM Polyglot API lets you embed and run code from guest languages in JVM-based host applications. Throughout this section, you will learn how to create a host application in Java that @@ -493,7 +492,7 @@ Caching may be disabled explicitly by setting [cached(boolean cached)](https:// Consider the following code snippet as an example: -``` +```java public class Main { public static void main(String[] args) { try (Engine engine = Engine.create()) { @@ -600,8 +599,6 @@ for (;;) { } ``` - - ## Step Through with Execution Listeners The GraalVM Polyglot API allows users to instrument the execution of guest languages through [ExecutionListener class](http://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/management/ExecutionListener.html). For example, it lets you attach an execution listener that is invoked for every statement of the guest language program. Execution listeners diff --git a/truffle/docs/LanguageTutorial.md b/truffle/docs/LanguageTutorial.md index 2e14b4324c5b..a90a8c9811a9 100644 --- a/truffle/docs/LanguageTutorial.md +++ b/truffle/docs/LanguageTutorial.md @@ -19,5 +19,5 @@ Conference on Programming Language Design and Implementation [PLDI 2016](http:// Next Steps: * Start to subclass [TruffleLanguage](http://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.html) for your own language implementation. * Fork [SimpleLanguage](https://github.com/graalvm/simplelanguage), a toy language that demonstrates how to use many Truffle features. -* Embed Truffle languages in Java host applications using the [Polyglot API](../../reference-manual/embedding/embed-languages.md). +* Embed Truffle languages in Java host applications using the [Polyglot API](../../docs/reference-manual/embedding/embed-languages.md). * Read [GraalVM/Truffle publications](https://github.com/oracle/graal/blob/master/docs/Publications.md). diff --git a/truffle/docs/Optimizing.md b/truffle/docs/Optimizing.md index bb642996e41f..e8a86116117a 100644 --- a/truffle/docs/Optimizing.md +++ b/truffle/docs/Optimizing.md @@ -577,7 +577,7 @@ The `--engine.TraceCompilation` option also shows CallTarget invalidations with ## Ideal Graph Visualizer -The [Ideal Graph Visualizer (IGV)](../../tools/ideal-graph-visualizer.md) is a tool to understand Truffle ASTs and the GraalVM compiler graphs. +The [Ideal Graph Visualizer (IGV)](../../docs/tools/ideal-graph-visualizer.md) is a tool to understand Truffle ASTs and the GraalVM compiler graphs. A typical usage is to run with `--vm.Dgraal.Dump=Truffle:1 --vm.Dgraal.PrintGraph=Network`, which will show you Truffle ASTs, guest-language call graphs, and the Graal graphs as they leave the Truffle phase. If the `-Dgraal.PrintGraph=Network` flag is omitted then the dump files are placed in the `graal_dumps` directory, which you should then open in IGV. diff --git a/truffle/docs/Profiling.md b/truffle/docs/Profiling.md index e09e1701786a..c324bf8b1cbe 100644 --- a/truffle/docs/Profiling.md +++ b/truffle/docs/Profiling.md @@ -9,7 +9,7 @@ permalink: /graalvm-as-a-platform/language-implementation-framework/Profiling/ There is no shortage of tools for profiling interpreters written using Truffle. When running in JVM mode you can use standard JVM tooling such as VisualVM, Java Flight Recorder, and Oracle Developer Studio. When running in Native Image you can use `callgrind` from the Valgrind tool suite, and other system tools such as `strace`. As a language running on GraalVM, other GraalVM tools can be used. -For a broad enough definition of profiling, you can also use the [Ideal Graph Visualizer (IGV)](../../tools/ideal-graph-visualizer.md) and C1 Visualizer to inspect the compiler output. +For a broad enough definition of profiling, you can also use the [Ideal Graph Visualizer (IGV)](../../docs/tools/ideal-graph-visualizer.md) and C1 Visualizer to inspect the compiler output. This guide is less about how to use each tool and more about suggestions for extracting the most useful information from the tools, assuming a basic knowledge of their usage. diff --git a/truffle/docs/README.md b/truffle/docs/README.md index 8e6ffe01268d..ce9d7a63a3c7 100644 --- a/truffle/docs/README.md +++ b/truffle/docs/README.md @@ -50,7 +50,7 @@ Consider reading [these publications](https://github.com/oracle/graal/blob/maste Implementing a language using Truffle offers a way to interoperate with other "Truffle" languages. To learn more about verifying that your language is a valid polyglot citizen, read more about using the [Polyglot TCK](./TCK.md). Somewhat related topics worth exploring are [Truffle Libraries](./TruffleLibraries.md), as well as how to use them to implement a language [interoperability](./InteropMigration.md). -Languages implemented with Truffle can also be embedded in Java host applications using the [Polyglot API](../../reference-manual/embedding/embed-languages.md). +Languages implemented with Truffle can also be embedded in Java host applications using the [Polyglot API](../../docs/reference-manual/embedding/embed-languages.md). To better understand how to improve the performance of your language please consult the documentation on [profiling](./Profiling.md) and [optimizing](./Optimizing.md) your language. Also, to better understand how to use Truffle's automated monomorphization feature (i.e., splitting), look at the [related documentation](./splitting/Monomorphization.md). From 69f7dd2cbfa0980d84a3022eac92a5f766ff983f Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 11 Oct 2021 11:56:48 +0200 Subject: [PATCH 404/681] Fix formatting of examples in JavaDoc. Closes #1517. --- .../truffle/api/dsl/Specialization.java | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java b/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java index bd832d6a50e3..7fa179c72690 100644 --- a/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java +++ b/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java @@ -262,9 +262,13 @@ * Example usage: * *
-     * static boolean acceptOperand(int operand) { assert operand <= 42; return operand & 1 ==
-     * 1; } @Specialization(guards = {"operand <= 42", "acceptOperand(operand)"}) void
-     * doSpecialization(int operand) {...}
+     * static boolean acceptOperand(int operand) {
+     *     assert operand <= 42;
+     *     return (operand & 1) == 1;
+     * }
+     *
+     * @Specialization(guards = {"operand <= 42", "acceptOperand(operand)"})
+     * void doSpecialization(int operand) {...}
      * 
* *

@@ -305,11 +309,11 @@ * Example usage: * *
-     * abstract static class DynamicObject() { abstract Shape getShape(); ... } static
-     * abstract class Shape() { abstract Assumption getUnmodifiedAssuption(); ... }
-     * @Specialization(guards = "operand.getShape() == cachedShape", assumptions =
-     * "cachedShape.getUnmodifiedAssumption()") void doAssumeUnmodifiedShape(DynamicObject
-     * operand, @Cached("operand.getShape()") Shape cachedShape) {...}
+     * abstract static class DynamicObject() { abstract Shape getShape(); ... }
+     * abstract static class Shape() { abstract Assumption getUnmodifiedAssuption(); ... }
+     *
+     * @Specialization(guards = "operand.getShape() == cachedShape", assumptions = "cachedShape.getUnmodifiedAssumption()")
+     * void doAssumeUnmodifiedShape(DynamicObject operand, @Cached("operand.getShape()") Shape cachedShape) {...}
      * 
* *

@@ -350,10 +354,12 @@ * Example usage: * *
-     * static int getCacheLimit() { return
-     * Integer.parseInt(System.getProperty("language.cacheLimit")); } @Specialization(guards =
-     * "operand == cachedOperand", limit = "getCacheLimit()") void doCached(Object
-     * operand, @Cached("operand") Object cachedOperand) {...}
+     * static int getCacheLimit() {
+     *     return Integer.parseInt(System.getProperty("language.cacheLimit"));
+     * }
+     *
+     * @Specialization(guards = "operand == cachedOperand", limit = "getCacheLimit()")
+     * void doCached(Object operand, @Cached("operand") Object cachedOperand) {...}
      * 
* *

From c997a8a71a0ac520abe93575b157e6f092baf233 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Mon, 11 Oct 2021 15:29:56 +0200 Subject: [PATCH 405/681] Set $JDT to `builtin` on public gates. --- .github/workflows/main.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b5dce652c33e..8ae3f6512a89 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,6 +31,7 @@ env: MX_GIT_CACHE: refcache MX_PYTHON_VERSION: 3 JAVA_HOME: ${{ github.workspace }}/jdk + JDT: builtin MX_PATH: ${{ github.workspace }}/mx jobs: @@ -150,16 +151,6 @@ jobs: git fetch --unshallow fi - if [[ ${GATE} == *fullbuild* ]] - then - # Only test JDT on JDK8 - if [ "${JDK}" == "openjdk8" ] - then - export JDT=${MX_PATH}/ecj.jar - wget --no-verbose https://archive.eclipse.org/eclipse/downloads/drops4/R-4.14-201912100610/ecj-4.14.jar -O ${JDT} - fi - fi - echo ${JAVA_HOME} ${JAVA_HOME}/bin/java -version if [[ ${WITHOUT_VCS} ]] From ec12f06dd452cfa6c112ff94ede4ec524d58d34a Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Mon, 11 Oct 2021 13:51:30 +0200 Subject: [PATCH 406/681] LLVMMultiContextLauncher removed as it is replaced by Polybench --- sulong/mx.sulong/mx_sulong.py | 31 ---- sulong/mx.sulong/mx_sulong_benchmarks.py | 10 -- .../launcher/LLVMMultiContextLauncher.java | 152 ------------------ vm/ci_includes/vm-bench-sulong.hocon | 16 -- vm/mx.vm/mx_vm.py | 3 +- .../graalvm/polybench/PolyBenchLauncher.java | 3 +- 6 files changed, 3 insertions(+), 212 deletions(-) delete mode 100644 sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMMultiContextLauncher.java diff --git a/sulong/mx.sulong/mx_sulong.py b/sulong/mx.sulong/mx_sulong.py index e81f03ac3578..94e2fbacd41f 100644 --- a/sulong/mx.sulong/mx_sulong.py +++ b/sulong/mx.sulong/mx_sulong.py @@ -233,15 +233,6 @@ def runLLVM(args=None, out=None, err=None, timeout=None, nonZeroIsFatal=True, ge dists.append('CHROMEINSPECTOR') return mx.run_java(getCommonOptions(False) + vmArgs + get_classpath_options(dists) + ["com.oracle.truffle.llvm.launcher.LLVMLauncher"] + sulongArgs, timeout=timeout, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err) -@mx.command(_suite.name, "llimul") -def runLLVMMul(args=None, out=None, err=None, timeout=None, nonZeroIsFatal=True, get_classpath_options=getClasspathOptions): - """uses Sulong to execute a LLVM IR file""" - vmArgs, sulongArgs = truffle_extract_VM_args(args) - dists = [] - if "tools" in (s.name for s in mx.suites()): - dists.append('CHROMEINSPECTOR') - return mx.run_java(getCommonOptions(False) + vmArgs + get_classpath_options(dists) + ["com.oracle.truffle.llvm.launcher.LLVMMultiContextLauncher"] + sulongArgs, timeout=timeout, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err) - @mx.command(_suite.name, "lli") def lli(args=None, out=None): """run lli via the current GraalVM""" @@ -507,25 +498,3 @@ def _get_jar_dists(self): ], installable=False, )) - -mx_sdk_vm.register_graalvm_component(mx_sdk_vm.GraalVmLanguage( - suite=_suite, - name='LLVM Multi-Context Runtime Launcher', - short_name='llmulrl', - dir_name='llvm', - license_files=[], - third_party_license_files=[], - dependencies=[], - truffle_jars=[], - support_distributions=[], - launcher_configs=[ - mx_sdk_vm.LanguageLauncherConfig( - destination='bin/', - jar_distributions=['sulong:SULONG_LAUNCHER'], - main_class='com.oracle.truffle.llvm.launcher.LLVMMultiContextLauncher', - build_args=[], - language='llvm', - ), - ], - installable=False, -)) diff --git a/sulong/mx.sulong/mx_sulong_benchmarks.py b/sulong/mx.sulong/mx_sulong_benchmarks.py index f063ee5777a6..3e48d867d96d 100644 --- a/sulong/mx.sulong/mx_sulong_benchmarks.py +++ b/sulong/mx.sulong/mx_sulong_benchmarks.py @@ -513,15 +513,6 @@ def launcher_args(self, args): def hosting_registry(self): return java_vm_registry -class SulongMultiContextVm(SulongVm): - def name(self): - return "sulong-multi" - - def launcherClass(self): - return "com.oracle.truffle.llvm.launcher.LLVMMultiContextLauncher" - - def launcherName(self): - return "llimul" class PolybenchVm(CExecutionEnvironmentMixin, GuestVm): @@ -618,7 +609,6 @@ def hosting_registry(self): native_vm_registry.add_vm(GccVm('O3', ['-O3']), _suite) native_vm_registry.add_vm(ClangVm('O3', ['-O3']), _suite) native_vm_registry.add_vm(SulongVm(), _suite, 10) -native_vm_registry.add_vm(SulongMultiContextVm(), _suite, 10) native_polybench_vm_registry = VmRegistry("NativePolybench", known_host_registries=[java_vm_registry]) native_polybench_vm_registry.add_vm(PolybenchVm('debug-aux-engine-cache', diff --git a/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMMultiContextLauncher.java b/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMMultiContextLauncher.java deleted file mode 100644 index 31ecbfe521dc..000000000000 --- a/sulong/projects/com.oracle.truffle.llvm.launcher/src/com/oracle/truffle/llvm/launcher/LLVMMultiContextLauncher.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used to - * endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.oracle.truffle.llvm.launcher; - -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Engine; -import org.graalvm.polyglot.Source; -import org.graalvm.polyglot.Value; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -public class LLVMMultiContextLauncher extends LLVMLauncher { - - private static final int DEFAULT_NUMBER_OF_RUNS = 1; - - private final Map multiContextEngineOptions = new HashMap<>(); - private int numOfRuns = DEFAULT_NUMBER_OF_RUNS; - private boolean useDebugCache = false; - - public static void main(String[] args) { - new LLVMMultiContextLauncher().launch(args); - } - - @Override - protected List preprocessArguments(List arguments, Map polyglotOptions) { - List unrecognizedOptions = super.preprocessArguments(arguments, polyglotOptions); - - // The engine options must be separated and used later when building the shared engine - List engineArgs = new ArrayList<>(); - Iterator iterator = unrecognizedOptions.iterator(); - while (iterator.hasNext()) { - String option = iterator.next(); - if (option.startsWith("--engine.")) { - iterator.remove(); - engineArgs.add(option); - continue; - } else if (option.startsWith("--use-debug-cache")) { - iterator.remove(); - this.useDebugCache = true; - } else if (option.startsWith("--multi-context-runs")) { - iterator.remove(); - String[] argPair = option.split("="); - if (argPair.length < 2) { - throw abort("Missing integer value for " + argPair[0]); - } - try { - numOfRuns = Integer.parseInt(argPair[1]); - } catch (NumberFormatException e) { - throw abort("Invalid integer value for " + argPair[0]); - } - } else if ("--experimental-options".equals(option)) { - engineArgs.add(option); - } - } - - parseUnrecognizedOptions(getLanguageId(), multiContextEngineOptions, engineArgs); - - return unrecognizedOptions; - } - - @Override - protected int execute(Context.Builder contextBuilder) { - contextBuilder.options(multiContextEngineOptions); - if (!useDebugCache) { - if (numOfRuns <= 1) { - // Do not create the shared engine for the number of runs <= 1 - contextBuilder.options(multiContextEngineOptions); - } else { - contextBuilder.engine(Engine.newBuilder().allowExperimentalOptions(true).options(multiContextEngineOptions).build()); - } - } - if (numOfRuns == 0) { - // Create the context and close it right afterwards to trigger the compilation of AOT - // roots - try (Context context = contextBuilder.build()) { - context.eval(Source.newBuilder(getLanguageId(), file).build()); - return 0; - } catch (IOException e) { - throw abort(String.format("Error loading file '%s' (%s)", file, e.getMessage())); - } - } else { - int ret = 0; - for (int i = 0; i < numOfRuns; i++) { - if (!useDebugCache) { - ret = super.execute(contextBuilder); - } else { - if (i == 0) { - contextBuilder.option("engine.DebugCachePreinitializeContext", "false").option("engine.DebugCacheCompile", "aot").// - option("engine.DebugTraceCache", "true").// - option("engine.DebugCacheLoad", "false").// - option("engine.DebugCacheStore", "true").// - option("engine.MultiTier", "false").// - option("llvm.AOTCacheStore", "true").// - option("engine.CompileAOTOnCreate", "false"); - try (Context context = contextBuilder.build()) { - Value library = context.eval(Source.newBuilder(getLanguageId(), file).build()); - if (!library.canExecute()) { - throw abort("no main function found"); - } - Value main = library.getMember("main"); - if (!main.canExecute()) { - throw abort("no executable main function found"); - } - } catch (IOException e) { - throw abort(String.format("Error loading file '%s' (%s)", file, e.getMessage())); - } - } else { - contextBuilder.option("engine.DebugCacheStore", "false").// - option("engine.DebugCacheLoad", "true").// - option("llvm.AOTCacheStore", "false").// - option("llvm.AOTCacheLoad", "true").// - option("engine.CompileAOTOnCreate", "false"); - ret = super.execute(contextBuilder); - } - } - } - return ret; - } - } -} diff --git a/vm/ci_includes/vm-bench-sulong.hocon b/vm/ci_includes/vm-bench-sulong.hocon index 4a9c1be0e4ff..a706bcf35af0 100644 --- a/vm/ci_includes/vm-bench-sulong.hocon +++ b/vm/ci_includes/vm-bench-sulong.hocon @@ -89,7 +89,6 @@ csuite-stockfish { } } - bench-llvm-sulong-3-runs-shared-engine-ce: ${bench_vm_ce_linux_base} ${bench-llvm-sulong-common} ${sulong-weekly-notifications} { targets: [gate], timelimit: "45:00" @@ -108,19 +107,6 @@ bench-llvm-sulong-3-runs-shared-engine-ce: ${bench_vm_ce_linux_base} ${bench-llv ] } -#bench-llvm-sulong-graalvm-ce-llimul: ${bench_vm_ce_linux_base} ${bench-llvm-sulong-common} ${sulong-weekly-notifications} { -# environment: { -# VM_DIST: ce-llimul -# } -# setup: ${bench_vm_ce_linux_base.setup} [ -# [git, clone, --depth, "1", ${repoBase}"${BENCH_REPO_NAME}.git", "../../${BENCH_REPO_NAME}"] -# ] -# run: [ -# [mx, --dynamicimport, sulong-benchmarks, --env, ce-llimul, benchmark, --results-file, ${bench_vm_ce_linux_base.resultFile}, "csuite:*", --, --native-vm, sulong-multi, --native-vm-config, default, --jvm, graalvm-ce, --jvm-config, "${JVM_CONFIG}", "--multi-context-runs=3"] -# ] -# timelimit: "10:00:01" -#} - bench-llvm-native: ${bench-llvm-common} ${bench-llvm-linux} ${sulong-weekly-notifications} { targets: [weekly, bench] run: [ @@ -135,8 +121,6 @@ builds += [ ${bench-llvm-sulong-graalvm-ce} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-native-csuite", environment: { JVM_CONFIG: native } } ${bench-llvm-sulong-graalvm-ce} ${csuite-stockfish} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-jvm-3-compiler-threads-csuite-stockfish", environment: { JVM_CONFIG: jvm-3-compiler-threads } } ${bench-llvm-sulong-graalvm-ce} ${csuite-stockfish} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-native-3-compiler-threads-csuite-stockfish", environment: { JVM_CONFIG: native-3-compiler-threads } } - #${bench-llvm-sulong-graalvm-ce-llimul} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-llimul-jvm-csuite", environment: { JVM_CONFIG: jvm } } - #${bench-llvm-sulong-graalvm-ce-llimul} {targets: [daily, bench], name: "daily-bench-sulong-graalvm-ce-llimul-native-csuite", environment: { JVM_CONFIG: native } } ${bench-llvm-sulong-3-runs-shared-engine-ce} {targets: [daily, bench], name: "daily-bench-sulong-3-runs-shared-engine-ce-jvm", environment: { JVM_CONFIG: jvm } } ${bench-llvm-sulong-3-runs-shared-engine-ce} {targets: [daily, bench], name: "daily-bench-sulong-3-runs-shared-engine-ce-native", environment: { JVM_CONFIG: native } } ${bench-llvm-sulong-core} {name: daily-bench-sulong-graal-core-csuite} diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index 39dd08a1f027..a1c6b2fcfc56 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -131,7 +131,7 @@ ce_components = ['bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'poly', 'polynative', 'pro', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] ce_complete_components = ['bpolyglot', 'cmp', 'cov', 'dap', 'ejvm', 'gu', 'gvm', 'gwa', 'ins', 'insight', 'insightheap', 'java', 'js', 'lg', 'libpoly', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nil', 'njs', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rby', 'rbyl', 'rgx', 'sdk', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'vvm'] ce_ruby_components = ['cmp', 'cov', 'dap', 'gvm', 'ins', 'insight', 'insightheap', 'lg', 'llp', 'llrc', 'llrn', 'lsp', 'nfi', 'pro', 'rby', 'rbyl', 'rgx', 'sdk', 'svm', 'svmnfi', 'tfl', 'tflm', 'vvm'] -ce_python_components = ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgu', 'bjs', 'blli', 'bllimul', 'bnative-image', 'bnative-image-configure', 'bpolybench', 'bpolyglot', 'cmp', 'cov', 'dap', 'dis', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llmulrl', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nic', 'nil', 'nju', 'njucp', 'pbm', 'pmh', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svml', 'svmnfi', 'tfl', 'tflm', 'vvm'] +ce_python_components = ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgu', 'bjs', 'blli', 'bnative-image', 'bnative-image-configure', 'bpolybench', 'bpolyglot', 'cmp', 'cov', 'dap', 'dis', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lg', 'libpoly', 'llp', 'llrc', 'llrl', 'llrn', 'lsp', 'nfi', 'ni', 'nic', 'nil', 'nju', 'njucp', 'pbm', 'pmh', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rgx', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svml', 'svmnfi', 'tfl', 'tflm', 'vvm'] ce_fastr_components = ce_components + ['R', 'llp', 'bRMain'] ce_no_native_components = ['bgu', 'bjs', 'blli', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgraalvm-native-binutil', 'bnative-image', 'bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'js', 'lsp', 'nfi', 'ni', 'nil', 'polynative', 'pro', 'rgx', 'sdk', 'llrc', 'llrn', 'llrl', 'snative-image-agent', 'snative-image-diagnostics-agent', 'spolyglot', 'svm', 'svmnfi', 'svml', 'tfl', 'tflm', 'libpoly', 'poly', 'vvm'] @@ -150,7 +150,6 @@ mx_sdk_vm.register_vm_config('toolchain-only-bash', ['bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'bgraalvm-native-binutil', 'tfl', 'tflm', 'gu', 'svm', 'svmnfi', 'gvm', 'polynative', 'llp', 'nfi', 'svml', 'bgu', 'sdk', 'llrc', 'llrn', 'cmp'], _suite, env_file=False) mx_sdk_vm.register_vm_config('ce', ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'java', 'libpoly', 'sespresso', 'spolyglot', 'ejvm', 'bjs', 'blli', 'bnative-image', 'btruffleruby', 'pynl', 'bgraalpython', 'pyn', 'bwasm', 'cmp', 'gwa', 'js', 'lg', 'llp', 'nfi', 'ni', 'nil', 'pbm', 'pmh', 'rby', 'rbyl', 'rgx', 'sdk', 'llrc', 'llrn', 'llrl', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmnfi', 'tfl', 'tflm'], _suite, env_file='polybench-ce') mx_sdk_vm.register_vm_config('ce', ['pbm', 'pmh', 'ni', 'js', 'lg', 'nfi', 'tfl', 'svm', 'nil', 'rgx', 'sdk', 'cmp', 'tflm', 'svmnfi', 'bnative-image', 'bjs', 'snative-image-agent', 'snative-image-diagnostics-agent'], _suite, env_file='polybench-nfi-ce') -mx_sdk_vm.register_vm_config('ce', ce_components + ['llmulrl'], _suite, env_file='ce-llimul') mx_sdk_vm.register_vm_config('ce', ['bgraalvm-native-binutil', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bgraalvm-native-ld', 'blli', 'bnative-image', 'cmp', 'lg', 'llrc', 'llrl', 'llrn', 'nfi', 'ni', 'nil', 'pbm', 'sdk', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmnfi', 'tfl', 'tflm'], _suite, env_file='polybench-sulong-ce') if mx.get_os() == 'windows': diff --git a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java index 49164d4dbc20..40a00c2d63af 100644 --- a/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java +++ b/vm/src/org.graalvm.polybench/src/org/graalvm/polybench/PolyBenchLauncher.java @@ -329,7 +329,8 @@ private void processMultiContextArguments() { for (Map.Entry> runOptionsEntry : runOptionsMap.entrySet()) { Map runOptions = config.polyglotRunOptionsMap.computeIfAbsent(runOptionsEntry.getKey(), (i) -> new HashMap<>()); if (useExperimental) { - // the enabled experimental-options flag must be propagated to runOptions to enable parsing of + // the enabled experimental-options flag must be propagated to runOptions to enable + // parsing of // run-level experimental options runOptionsEntry.getValue().add("--experimental-options"); } From 4985f200fe26334d4a94473b300c188587dcfb2c Mon Sep 17 00:00:00 2001 From: David Kozak Date: Thu, 7 Oct 2021 13:48:24 +0200 Subject: [PATCH 407/681] introduce an option to change the default charset --- ...ContentSubstitutedLocalizationSupport.java | 5 +-- .../jdk/localization/LocalizationFeature.java | 36 +++++++++++++------ .../jdk/localization/LocalizationSupport.java | 5 ++- .../OptimizedLocalizationSupport.java | 5 +-- .../Target_java_nio_charset_Charset.java | 8 +---- 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java index 5a23e72535bf..ea7742149315 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.jdk.localization; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.ListResourceBundle; @@ -65,8 +66,8 @@ public class BundleContentSubstitutedLocalizationSupport extends LocalizationSup private final Map, StoredBundle> storedBundles = new ConcurrentHashMap<>(); - public BundleContentSubstitutedLocalizationSupport(Locale defaultLocale, Set locales, List requestedPatterns, ForkJoinPool pool) { - super(defaultLocale, locales); + public BundleContentSubstitutedLocalizationSupport(Locale defaultLocale, Set locales, Charset defaultCharset, List requestedPatterns, ForkJoinPool pool) { + super(defaultLocale, locales, defaultCharset); this.pool = pool; this.compressBundlesPatterns = parseCompressBundlePatterns(requestedPatterns); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationFeature.java index 61473859ebaf..2243cc09d93e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationFeature.java @@ -28,6 +28,8 @@ import java.lang.reflect.Field; import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.text.spi.BreakIteratorProvider; import java.text.spi.CollatorProvider; @@ -134,6 +136,8 @@ public abstract class LocalizationFeature implements Feature { */ protected Locale defaultLocale = Locale.getDefault(); + private Charset defaultCharset; + protected Set allLocales; protected LocalizationSupport support; @@ -150,6 +154,9 @@ public static class Options { @Option(help = "Default locale of the image, by the default it is the same as the default locale of the image builder.", type = OptionType.User)// public static final HostedOptionKey DefaultLocale = new HostedOptionKey<>(Locale.getDefault().toLanguageTag()); + @Option(help = "Default charset of the image, by the default it is the same as the default charset of the image builder.", type = OptionType.User)// + public static final HostedOptionKey DefaultCharset = new HostedOptionKey<>(Charset.defaultCharset().name()); + @Option(help = "Comma separated list of locales to be included into the image. The default locale is included in the list automatically if not present.", type = OptionType.User)// public static final HostedOptionKey IncludeLocales = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings()); @@ -228,6 +235,13 @@ public void afterRegistration(AfterRegistrationAccess access) { allLocales = processLocalesOption(); defaultLocale = parseLocaleFromTag(Options.DefaultLocale.getValue()); UserError.guarantee(defaultLocale != null, "Invalid default locale %s", Options.DefaultLocale.getValue()); + try { + defaultCharset = Charset.forName(Options.DefaultCharset.getValue()); + VMError.guarantee(defaultCharset.name().equals(Options.DefaultCharset.getValue()), + "Failed to locate charset " + Options.DefaultCharset.getValue() + ", instead " + defaultCharset.name() + " was provided"); + } catch (IllegalCharsetNameException | UnsupportedCharsetException ex) { + throw UserError.abort(ex, "Invalid default charset %s", Options.DefaultCharset.getValue()); + } allLocales.add(defaultLocale); support = selectLocalizationSupport(); ImageSingletons.add(LocalizationSupport.class, support); @@ -245,12 +259,12 @@ public void afterRegistration(AfterRegistrationAccess access) { @Platforms(Platform.HOSTED_ONLY.class) private LocalizationSupport selectLocalizationSupport() { if (optimizedMode) { - return new OptimizedLocalizationSupport(defaultLocale, allLocales); + return new OptimizedLocalizationSupport(defaultLocale, allLocales, defaultCharset); } else if (substituteLoadLookup) { List requestedPatterns = Options.LocalizationCompressBundles.getValue().values(); - return new BundleContentSubstitutedLocalizationSupport(defaultLocale, allLocales, requestedPatterns, compressionPool); + return new BundleContentSubstitutedLocalizationSupport(defaultLocale, allLocales, defaultCharset, requestedPatterns, compressionPool); } - return new LocalizationSupport(defaultLocale, allLocales); + return new LocalizationSupport(defaultLocale, allLocales, defaultCharset); } @Override @@ -317,19 +331,19 @@ private static Set processLocalesOption() { * more than this can add additional charsets. */ @Platforms(Platform.HOSTED_ONLY.class) - private static void addCharsets() { + private void addCharsets() { if (Options.AddAllCharsets.getValue()) { for (Charset c : Charset.availableCharsets().values()) { addCharset(c); } } else { - addCharset(Charset.defaultCharset()); - addCharset(Charset.forName("US-ASCII")); - addCharset(Charset.forName("ISO-8859-1")); - addCharset(Charset.forName("UTF-8")); - addCharset(Charset.forName("UTF-16BE")); - addCharset(Charset.forName("UTF-16LE")); - addCharset(Charset.forName("UTF-16")); + addCharset(defaultCharset); + addCharset(StandardCharsets.US_ASCII); + addCharset(StandardCharsets.ISO_8859_1); + addCharset(StandardCharsets.UTF_8); + addCharset(StandardCharsets.UTF_16BE); + addCharset(StandardCharsets.UTF_16LE); + addCharset(StandardCharsets.UTF_16); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java index cd601c0dcc46..f5a95b1cd59d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java @@ -63,9 +63,12 @@ public class LocalizationSupport { public final ResourceBundle.Control control = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT); - public LocalizationSupport(Locale defaultLocale, Set locales) { + public final Charset defaultCharset; + + public LocalizationSupport(Locale defaultLocale, Set locales, Charset defaultCharset) { this.defaultLocale = defaultLocale; this.allLocales = locales.toArray(new Locale[0]); + this.defaultCharset = defaultCharset; this.supportedLanguageTags = locales.stream().map(Locale::toString).collect(Collectors.toSet()); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/OptimizedLocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/OptimizedLocalizationSupport.java index 0ce86b49d2ea..d064ac0cf0c3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/OptimizedLocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/OptimizedLocalizationSupport.java @@ -27,6 +27,7 @@ import com.oracle.svm.core.option.SubstrateOptionsParser; import org.graalvm.collections.Pair; +import java.nio.charset.Charset; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -50,8 +51,8 @@ public class OptimizedLocalizationSupport extends LocalizationSupport { private final String includeResourceBundlesOption = SubstrateOptionsParser.commandArgument(LocalizationFeature.Options.IncludeResourceBundles, ""); - public OptimizedLocalizationSupport(Locale defaultLocale, Set locales) { - super(defaultLocale, locales); + public OptimizedLocalizationSupport(Locale defaultLocale, Set locales, Charset defaultCharset) { + super(defaultLocale, locales, defaultCharset); } /** diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_nio_charset_Charset.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_nio_charset_Charset.java index 1f3b52c8ddbd..47ee22a10192 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_nio_charset_Charset.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_nio_charset_Charset.java @@ -42,15 +42,9 @@ @SuppressWarnings({"unused"}) final class Target_java_nio_charset_Charset { - @Alias private static Charset defaultCharset; - @Substitute private static Charset defaultCharset() { - /* - * The default charset is initialized during native image generation and therefore always - * available without any checks. - */ - return defaultCharset; + return ImageSingletons.lookup(LocalizationSupport.class).defaultCharset; } @Substitute From e04d3e2cd23cf42a20ca02dd8ff8cd37b139b1e0 Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Mon, 11 Oct 2021 16:06:21 +0200 Subject: [PATCH 408/681] Use NeverValidAssumption and AlwaysValidAssumption for never leaf and always leaf classes in CHA --- .../hierarchy/NoOpClassHierarchyOracle.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java index a5d3489af394..8ff1fe2bbb77 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/analysis/hierarchy/NoOpClassHierarchyOracle.java @@ -25,6 +25,8 @@ import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.utilities.AlwaysValidAssumption; +import com.oracle.truffle.api.utilities.NeverValidAssumption; import com.oracle.truffle.espresso.impl.ObjectKlass; /** @@ -34,9 +36,10 @@ public class NoOpClassHierarchyOracle implements ClassHierarchyOracle { protected static class LeafTypeAssumptionImpl implements LeafTypeAssumption { private final Assumption underlying; - static final LeafTypeAssumption NeverValidAssumption = new LeafTypeAssumptionImpl("invalid"); - static { - NeverValidAssumption.getAssumption().invalidate(); + + // Used only to create never valid and always valid instances + private LeafTypeAssumptionImpl(Assumption underlyingAssumption) { + underlying = underlyingAssumption; } private LeafTypeAssumptionImpl(String assumptionName) { @@ -55,8 +58,8 @@ public Assumption getAssumption() { protected static final LeafTypeAssumptionAccessor assumptionAccessor = new LeafTypeAssumptionAccessor(); - protected static final LeafTypeAssumption FinalIsAlwaysLeaf = new LeafTypeAssumptionImpl("final class is always a CHA leaf"); - protected static final LeafTypeAssumption NotLeaf = LeafTypeAssumptionImpl.NeverValidAssumption; + protected static final LeafTypeAssumption FinalIsAlwaysLeaf = new LeafTypeAssumptionImpl(AlwaysValidAssumption.INSTANCE); + protected static final LeafTypeAssumption NotLeaf = new LeafTypeAssumptionImpl(NeverValidAssumption.INSTANCE); @Override public LeafTypeAssumption createAssumptionForNewKlass(ObjectKlass newKlass) { From 32796df1c5d2e060b2048d6dab2f29f4ec130960 Mon Sep 17 00:00:00 2001 From: Ondrej Tethal Date: Mon, 11 Oct 2021 14:42:58 +0000 Subject: [PATCH 409/681] [GR-21590] Update imports PullRequest: graalpython/1994 --- vm/mx.vm/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 76101ae7684a..18842643c9a6 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -75,7 +75,7 @@ }, { "name": "graalpython", - "version": "f100bf8941139ece20ec0fed3160ed9191cdbbf5", + "version": "a48aebd1681cc9b0bb454ab0995c97c5d2cbc5df", "dynamic": True, "urls": [ {"url": "https://github.com/graalvm/graalpython.git", "kind": "git"}, From 6d61e2d778c27193780f30338bb4e48cd1580437 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 11 Oct 2021 18:44:25 +0200 Subject: [PATCH 410/681] Prevent a safepoint when thread tries to print a fatal error. --- .../oracle/svm/core/genscavenge/GCImpl.java | 10 +- .../posix/pthread/PthreadVMLockSupport.java | 2 +- .../core/windows/WindowsVMLockSupport.java | 2 +- .../svm/core/InvalidMethodPointerHandler.java | 2 +- .../oracle/svm/core/SubstrateDiagnostics.java | 5 + .../svm/core/SubstrateSegfaultHandler.java | 2 +- .../graal/snippets/CEntryPointSnippets.java | 2 +- .../svm/core/graal/snippets/DeoptTester.java | 3 +- .../svm/core/jdk/VMErrorSubstitutions.java | 2 +- .../oracle/svm/core/thread/JavaThreads.java | 5 +- .../com/oracle/svm/core/thread/Safepoint.java | 42 ++-- .../com/oracle/svm/core/thread/VMThreads.java | 213 ++++++++++++------ .../svm/jni/functions/JNIFunctions.java | 2 +- 13 files changed, 191 insertions(+), 101 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index 83f506087d87..8dc6e9965bdb 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -783,14 +783,10 @@ private void blackenStackRoots() { */ continue; } - if (VMThreads.StatusSupport.isStatusIgnoreSafepoints(vmThread)) { + if (!VMThreads.SafepointBehavior.safepointChecksEnabled(vmThread)) { /* - * When a thread is ignoring safepoints, it is reporting a fatal VM error. - * The thread is not paused and we cannot safely walk its stack (we don't - * even know where it starts). We simply ignore it and keep collecting until - * it terminates the VM rather than crashing here. The thread might access - * the heap to print diagnostics, but it must do so with due caution and - * should not crash because of our ongoing GC. + * When a thread is ignoring safepoints, then the thread is not paused and + * we cannot safely walk its stack (we don't even know where it starts). */ continue; } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java index 8e10d8674795..f19e589eef9d 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java @@ -166,7 +166,7 @@ protected static void checkResult(int result, String functionName) { * Functions are called very early and late during our execution, so there is not much * we can do when they fail. */ - VMThreads.StatusSupport.setStatusIgnoreSafepoints(); + VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); Log.log().string(functionName).string(" returned ").signed(result).newline(); ImageSingletons.lookup(LogHandler.class).fatalError(); } diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java index 49a555f2d534..44ddefc253e6 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java @@ -161,7 +161,7 @@ static void checkResult(int result, String functionName) { * Functions are called very early and late during our execution, so there is not much * we can do when they fail. */ - VMThreads.StatusSupport.setStatusIgnoreSafepoints(); + VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); int lastError = WinBase.GetLastError(); Log.log().string(functionName).string(" failed with error ").hex(lastError).newline(); ImageSingletons.lookup(LogHandler.class).fatalError(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java index 4b759ea3e307..d6061d66f714 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java @@ -70,7 +70,7 @@ private static void methodPointerNotCompiledHandler() { } private static void failFatally(Pointer callerSP, CodePointer callerIP, String message) { - VMThreads.StatusSupport.setStatusIgnoreSafepoints(); + VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); /* diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java index f2fb6cc092bc..ff6ef10c845e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java @@ -26,6 +26,7 @@ import java.util.Arrays; +import com.oracle.svm.core.thread.VMThreads.SafepointBehavior; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.SuppressFBWarnings; @@ -616,6 +617,10 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev log.string("Threads:").indent(true); for (IsolateThread thread = VMThreads.firstThreadUnsafe(); thread.isNonNull(); thread = VMThreads.nextThread(thread)) { log.zhex(thread).spaces(1).string(VMThreads.StatusSupport.getStatusString(thread)); + int safepointBehavior = SafepointBehavior.getSafepointBehavior(thread); + if (safepointBehavior != SafepointBehavior.ALLOW_SAFEPOINT) { + log.string(" (").string(SafepointBehavior.toString(safepointBehavior)).string(")"); + } if (allowJavaHeapAccess) { Thread threadObj = JavaThreads.fromVMThread(thread); log.string(" \"").string(threadObj.getName()).string("\" - ").object(threadObj); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java index 2f5ff9018b2c..94ac2f378480 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java @@ -153,7 +153,7 @@ protected static boolean tryEnterIsolate(RegisterDumper.Context context) { @Uninterruptible(reason = "Must be uninterruptible until we get immune to safepoints.", calleeMustBe = false) @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in segfault handler.", overridesCallers = true) protected static void dump(PointerBase signalInfo, RegisterDumper.Context context) { - VMThreads.StatusSupport.setStatusIgnoreSafepoints(); + VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); dumpInterruptibly(signalInfo, context); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index bf6fd263cc54..08bfdf6ca930 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -565,7 +565,7 @@ public static int reportExceptionSnippet(Throwable exception) { @Uninterruptible(reason = "Avoid StackOverflowError and safepoints until they are disabled permanently", calleeMustBe = false) @SubstrateForeignCallTarget(stubCallingConvention = false) private static int reportException(Throwable exception) { - VMThreads.StatusSupport.setStatusIgnoreSafepoints(); + VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); logException(exception); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/DeoptTester.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/DeoptTester.java index cf23fa5a53ae..eb20a6b52c3d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/DeoptTester.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/DeoptTester.java @@ -29,7 +29,6 @@ import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.options.Option; -import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.c.function.CodePointer; import org.graalvm.word.LocationIdentity; import org.graalvm.word.Pointer; @@ -112,7 +111,7 @@ public static void deoptTest() { !CEntryPointSnippets.isIsolateInitialized() || ThreadingSupportImpl.isRecurringCallbackPaused() || VMOperation.isInProgress() || - VMThreads.StatusSupport.isStatusIgnoreSafepoints(CurrentIsolate.getCurrentThread()) || + !VMThreads.SafepointBehavior.safepointChecksEnabled() || !JavaThreads.currentJavaThreadInitialized()) { return; // Thread or VM is not in a safe (or sane) state for deoptimization } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java index c8dc6da515a5..a6957ee1ee75 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java @@ -99,7 +99,7 @@ public class VMErrorSubstitutions { @Uninterruptible(reason = "Allow VMError to be used in uninterruptible code.") static RuntimeException shouldNotReachHere(CodePointer callerIP, String msg, Throwable ex) { ThreadStackPrinter.printBacktrace(); - VMThreads.StatusSupport.setStatusIgnoreSafepoints(); + VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); VMErrorSubstitutions.shutdown(callerIP, msg, ex); throw UnreachableNode.unreachable(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java index bb208acc802d..7a5f25aa3ffe 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java @@ -36,6 +36,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import com.oracle.svm.core.thread.VMThreads.SafepointBehavior; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; @@ -421,12 +422,12 @@ public boolean tearDown() { * When this method is being executed, we expect that the current thread owns * {@linkplain VMThreads#THREAD_MUTEX}. This is fine even though this method is not * {@linkplain Uninterruptible} because this method is either executed as part of a VM operation - * or {@linkplain StatusSupport#setStatusIgnoreSafepoints()} was called. + * or {@linkplain SafepointBehavior#setIgnoreThreadInSafepointHandling()} was called. */ @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate while detaching a thread.") public static void detachThread(IsolateThread vmThread) { VMThreads.THREAD_MUTEX.assertIsOwner("Must hold the VMThreads mutex"); - assert StatusSupport.isStatusIgnoreSafepoints(vmThread) || VMOperation.isInProgress(); + assert SafepointBehavior.isIgnoredBySafepointHandling(vmThread) || VMOperation.isInProgress(); Thread thread = currentThread.get(vmThread); ParkEvent.detach(getUnsafeParkEvent(thread)); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java index e7dd8fa0483c..30bb4e0273b8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java @@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicInteger; +import com.oracle.svm.core.thread.VMThreads.SafepointBehavior; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; @@ -386,8 +387,8 @@ private static void enterSlowPathSafepointCheck() throws Throwable { @AlwaysInline("Always inline into foreign call stub") @Uninterruptible(reason = "Must not contain safepoint checks") public static void slowPathSafepointCheck() throws Throwable { - if (StatusSupport.isStatusIgnoreSafepoints(CurrentIsolate.getCurrentThread())) { - /* The thread is detaching so it won't ever need to execute a safepoint again. */ + if (!SafepointBehavior.safepointChecksEnabled()) { + /* Safepoints are explicitly disabled for this thread. */ Safepoint.setSafepointRequested(THREAD_REQUEST_RESET); return; } @@ -518,8 +519,8 @@ public static void transitionVMToNative() { @Uninterruptible(reason = "Must not contain safepoint checks") private static void enterSlowPathTransitionFromNativeToNewStatus(int newStatus) { VMError.guarantee(StatusSupport.isStatusNativeOrSafepoint(), "Must either be at a safepoint or in native mode"); - VMError.guarantee(!StatusSupport.isStatusIgnoreSafepoints(CurrentIsolate.getCurrentThread()), - "When safepoints are disabled, the thread can only be in Native mode, so the fast path transition must succeed and this slow path must not be called"); + VMError.guarantee(SafepointBehavior.safepointChecksEnabled(), + "When safepoint checks are disabled, the thread can only be in Native mode, so the fast path transition must succeed and this slow path must not be called"); Statistics.incSlowPathFrozen(); try { @@ -634,16 +635,12 @@ private static void requestSafepoints(String reason) { final Log trace = Log.noopLog().string("[Safepoint.Master.requestSafepoints: reason: ").string(reason); // Walk the threads list and ask each thread (except myself) to come to a safepoint. - // TODO: Do I always bring *all* threads to a safepoint? Could I stop some of them? for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { if (isMyself(vmThread)) { continue; } - if (StatusSupport.isStatusIgnoreSafepoints(vmThread)) { - /* - * If the thread is exiting/exited or safepoints are disabled for another - * reason, do not ask it to stop at safepoints. - */ + if (!SafepointBehavior.safepointChecksEnabled(vmThread)) { + /* If safepoints are disabled, do not ask it to stop at safepoints. */ continue; } requestSafepoint(vmThread); @@ -713,19 +710,22 @@ private static void waitForSafepoints(String reason) { for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { if (isMyself(vmThread)) { /* Don't wait for myself. */ - } else if (StatusSupport.isStatusIgnoreSafepoints(vmThread)) { - /* - * If the thread has exited or safepoints are disabled for another reason, - * then I do not need to worry about bringing it to a safepoint. - */ - ignoreSafepoints += 1; + continue; + } + + int safepointBehavior = SafepointBehavior.getSafepointBehavior(vmThread); + if (safepointBehavior == SafepointBehavior.PREVENT_VM_FROM_REACHING_SAFEPOINT) { + notAtSafepoint++; + } else if (safepointBehavior == SafepointBehavior.IGNORE_THREAD_IN_SAFEPOINT_HANDLING) { + ignoreSafepoints++; } else { + assert safepointBehavior == SafepointBehavior.ALLOW_SAFEPOINT; int status = StatusSupport.getStatusVolatile(vmThread); switch (status) { case StatusSupport.STATUS_IN_JAVA: case StatusSupport.STATUS_IN_VM: { /* Re-request the safepoint in case of a lost update. */ - if (getSafepointRequested(vmThread) > 0 && !StatusSupport.isStatusIgnoreSafepoints(vmThread)) { + if (getSafepointRequested(vmThread) > 0) { requestSafepoint(vmThread); } notAtSafepoint += 1; @@ -785,7 +785,7 @@ private static void releaseSafepoints(String reason) { VMThreads.THREAD_MUTEX.assertIsOwner("Must hold mutex when releasing safepoints."); // Set all the thread statuses that are at safepoint back to being in native code. for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { - if (!isMyself(vmThread) && !StatusSupport.isStatusIgnoreSafepoints(vmThread)) { + if (!isMyself(vmThread) && SafepointBehavior.safepointChecksEnabled(vmThread)) { if (trace.isEnabled()) { trace.string(" vmThread status: ").string(StatusSupport.getStatusString(vmThread)); } @@ -864,9 +864,13 @@ public static int countingVMOperation() { int notAtSafepoint = 0; for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { - if (StatusSupport.isStatusIgnoreSafepoints(vmThread)) { + int safepointBehavior = SafepointBehavior.getSafepointBehavior(vmThread); + if (safepointBehavior == SafepointBehavior.PREVENT_VM_FROM_REACHING_SAFEPOINT) { + notAtSafepoint++; + } else if (safepointBehavior == SafepointBehavior.IGNORE_THREAD_IN_SAFEPOINT_HANDLING) { ignoreSafepoints += 1; } else { + assert safepointBehavior == SafepointBehavior.ALLOW_SAFEPOINT; // Check if the thread is at a safepoint or in native code. int status = StatusSupport.getStatusVolatile(vmThread); switch (status) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java index 1cb5883f88b4..95f2eda2fd57 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java @@ -87,7 +87,7 @@ public static VMThreads singleton() { *
  • Acquire the mutex outside of a VM operation but only execute uninterruptible code. This * is safe as the uninterruptible code cannot trigger a safepoint.
  • *
  • Acquire the mutex from a thread that previously called - * {@link StatusSupport#setStatusIgnoreSafepoints()}.
  • + * {@link SafepointBehavior#setIgnoreThreadInSafepointHandling()}. * * * Deadlock example 1: @@ -120,7 +120,9 @@ public static VMThreads singleton() { */ protected static final VMCondition THREAD_LIST_CONDITION = new VMCondition(THREAD_MUTEX); - /** The first element in the linked list of {@link IsolateThread}s. */ + /** + * The first element in the linked list of {@link IsolateThread}s. + */ private static IsolateThread head; /** * This field is used to guarantee that all isolate threads that were started by SVM have exited @@ -142,7 +144,9 @@ public static VMThreads singleton() { private static final FastThreadLocalWord OSThreadIdTL = FastThreadLocalFactory.createWord("VMThreads.OSThreadIdTL"); protected static final FastThreadLocalWord OSThreadHandleTL = FastThreadLocalFactory.createWord("VMThreads.OSThreadHandleTL"); public static final FastThreadLocalWord IsolateTL = FastThreadLocalFactory.createWord("VMThreads.IsolateTL"); - /** The highest stack address. */ + /** + * The highest stack address. + */ public static final FastThreadLocalWord StackBase = FastThreadLocalFactory.createWord("VMThreads.StackBase"); /** * The lowest stack address. Note that this value does not necessarily match the value that is @@ -161,13 +165,17 @@ public static boolean isInitialized() { return initializationState.get() >= STATE_INITIALIZED; } - /** Is threading being torn down? */ + /** + * Is threading being torn down? + */ @Uninterruptible(reason = "Called from uninterruptible code during tear down.") public static boolean isTearingDown() { return initializationState.get() >= STATE_TEARING_DOWN; } - /** Note that threading is being torn down. */ + /** + * Note that threading is being torn down. + */ static void setTearingDown() { initializationState.set(STATE_TEARING_DOWN); } @@ -329,7 +337,7 @@ public void detachThread(IsolateThread thread) { cleanupBeforeDetach(thread); - setStatusIgnoreSafepointsAndLock(); + setIgnoreThreadInSafepointHandlingAndLock(); OSThreadHandle threadToCleanup; try { detachThreadInSafeContext(thread); @@ -356,11 +364,11 @@ public void detachThread(IsolateThread thread) { } /* - * Make me immune to safepoints (the safepoint mechanism ignores me). We are calling functions - * that are not marked as @Uninterruptible during the detach process. We hold the THREAD_MUTEX, - * so we know that we are not going to be interrupted by a safepoint. But a safepoint can - * already be requested, or our safepoint counter can reach 0 - so it is still possible that we - * enter the safepoint slow path. + * Make me immune to safepoints and make the safepoint mechanism ignore me. We are calling + * functions that are not marked as @Uninterruptible during the detach process. We hold the + * THREAD_MUTEX, so we know that we are not going to be interrupted by a safepoint. But a + * safepoint can already be requested, or our safepoint counter can reach 0 - so it is still + * possible that we enter the safepoint slow path. * * Between setting the status and acquiring the TREAD_MUTEX, we must not access the heap. * Otherwise, we risk a race with the GC as this thread will continue executing even though the @@ -368,8 +376,8 @@ public void detachThread(IsolateThread thread) { */ @Uninterruptible(reason = "Called from uninterruptible code.") @NeverInline("Prevent that anything floats between setting the status and acquiring the mutex.") - private static void setStatusIgnoreSafepointsAndLock() { - StatusSupport.setStatusIgnoreSafepoints(); + private static void setIgnoreThreadInSafepointHandlingAndLock() { + SafepointBehavior.setIgnoreThreadInSafepointHandling(); THREAD_MUTEX.lockNoTransition(); } @@ -607,51 +615,56 @@ public static boolean printLocationInfo(Log log, UnsignedWord value, boolean all * Access to platform-specific implementations. */ - /** A thread-local enum giving the thread status of a VMThread. And supporting methods. */ + /** + * A thread-local enum giving the thread status of a VMThread. And supporting methods. + */ public static class StatusSupport { - /** The status of a {@link IsolateThread}. */ + /** + * The status of a {@link IsolateThread}. + */ public static final FastThreadLocalInt statusTL = FastThreadLocalFactory.createInt("StatusSupport.statusTL").setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); /** - * Boolean flag whether safepoints are disabled. This is a separate thread local in addition - * to the {@link #statusTL} because we need the disabled flag to be "sticky": once - * safepoints are disabled, they must never be enabled again. Either the thread is getting - * detached, or a fatal error occurred and we are printing diagnostics before killing the - * VM. + * An illegal thread state for places where we need to pass a value. */ - private static final FastThreadLocalInt safepointsDisabledTL = FastThreadLocalFactory.createInt("StatusSupport.safepointsDisabledTL"); - - /** An illegal thread state for places where we need to pass a value. */ public static final int STATUS_ILLEGAL = -1; /** * {@link IsolateThread} memory has been allocated for the thread, but the thread is not on * the VMThreads list yet. */ public static final int STATUS_CREATED = 0; - /** The thread is running in Java code. */ + /** + * The thread is running in Java code. + */ public static final int STATUS_IN_JAVA = STATUS_CREATED + 1; - /** The thread has been requested to stop at a safepoint. */ + /** + * The thread has been requested to stop at a safepoint. + */ public static final int STATUS_IN_SAFEPOINT = STATUS_IN_JAVA + 1; - /** The thread is running in native code. */ + /** + * The thread is running in native code. + */ public static final int STATUS_IN_NATIVE = STATUS_IN_SAFEPOINT + 1; - /** The thread is running in trusted native code that was linked into the image. */ + /** + * The thread is running in trusted native code that was linked into the image. + */ public static final int STATUS_IN_VM = STATUS_IN_NATIVE + 1; private static final int MAX_STATUS = STATUS_IN_VM; @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - private static String statusToString(int status, boolean safepointsDisabled) { + private static String statusToString(int status) { switch (status) { case STATUS_CREATED: - return safepointsDisabled ? "STATUS_CREATED (safepoints disabled)" : "STATUS_CREATED"; + return "STATUS_CREATED"; case STATUS_IN_JAVA: - return safepointsDisabled ? "STATUS_IN_JAVA (safepoints disabled)" : "STATUS_IN_JAVA"; + return "STATUS_IN_JAVA"; case STATUS_IN_SAFEPOINT: - return safepointsDisabled ? "STATUS_IN_SAFEPOINT (safepoints disabled)" : "STATUS_IN_SAFEPOINT"; + return "STATUS_IN_SAFEPOINT"; case STATUS_IN_NATIVE: - return safepointsDisabled ? "STATUS_IN_NATIVE (safepoints disabled)" : "STATUS_IN_NATIVE"; + return "STATUS_IN_NATIVE"; case STATUS_IN_VM: - return safepointsDisabled ? "STATUS_IN_VM (safepoints disabled)" : "STATUS_IN_VM"; + return "STATUS_IN_VM"; default: return "STATUS error"; } @@ -659,10 +672,12 @@ private static String statusToString(int status, boolean safepointsDisabled) { /* Access methods to treat VMThreads.statusTL as a volatile int. */ - /** For debugging. */ + /** + * For debugging. + */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static String getStatusString(IsolateThread vmThread) { - return statusToString(statusTL.getVolatile(vmThread), isStatusIgnoreSafepoints(vmThread)); + return statusToString(statusTL.getVolatile(vmThread)); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @@ -685,12 +700,16 @@ public static void setStatusNative(IsolateThread vmThread) { statusTL.setVolatile(vmThread, STATUS_IN_NATIVE); } - /** There is no unguarded change to safepoint. */ + /** + * There is no unguarded change to safepoint. + */ public static boolean compareAndSetNativeToSafepoint(IsolateThread vmThread) { return statusTL.compareAndSet(vmThread, STATUS_IN_NATIVE, STATUS_IN_SAFEPOINT); } - /** An unguarded transition to Java. */ + /** + * An unguarded transition to Java. + */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void setStatusJavaUnguarded() { statusTL.setVolatile(STATUS_IN_JAVA); @@ -700,7 +719,9 @@ public static void setStatusVM() { statusTL.setVolatile(STATUS_IN_VM); } - /** A guarded transition from native to another status. */ + /** + * A guarded transition from native to another status. + */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean compareAndSetNativeToNewStatus(int newStatus) { return statusTL.compareAndSet(STATUS_IN_NATIVE, newStatus); @@ -741,16 +762,6 @@ public static boolean isStatusJava() { return (statusTL.getVolatile() == STATUS_IN_JAVA); } - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public static boolean isStatusIgnoreSafepoints() { - return safepointsDisabledTL.getVolatile() == 1; - } - - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public static boolean isStatusIgnoreSafepoints(IsolateThread vmThread) { - return safepointsDisabledTL.getVolatile(vmThread) == 1; - } - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void assertStatusJava() { String msg = "Thread status must be 'Java'."; @@ -787,20 +798,10 @@ public static void assertStatusVM() { } } - /** - * Make myself immune to safepoints. Set the thread status to ensure that the safepoint - * mechanism ignores me. It is not necessary to clear a pending safepoint request (i.e., to - * reset the safepoint counter) because the safepoint slow path is going to do that in case. - * - * Be careful with this method. If a thread is marked to ignore safepoints, it means that it - * can continue executing while a safepoint (and therefore a GC) is in progress. So, either - * prevent that a safepoint can be initiated (by holding the {@link #THREAD_MUTEX}) or make - * sure that this thread does not access any movable heap objects (even executing write - * barriers can already cause issues). - */ + // This method will be removed in GR-34435. @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void setStatusIgnoreSafepoints() { - safepointsDisabledTL.setVolatile(1); + SafepointBehavior.setPreventVMFromReachingSafepoint(); } public static boolean isValidStatus(int status) { @@ -828,17 +829,99 @@ public static int getNewThreadStatus(CFunctionOptions.Transition transition) { } } + public static class SafepointBehavior { + /** Determines how this thread interacts with the safepoint handling. */ + private static final FastThreadLocalInt safepointBehaviorTL = FastThreadLocalFactory.createInt("StatusSupport.safepointBehaviorTL"); + + /** The thread will freeze as soon as possible if a safepoint is requested. */ + public static final int ALLOW_SAFEPOINT = 0; + + /** + * The thread won't freeze at a safepoint, and will actively prevent the VM from reaching a + * safepoint (regardless of the thread status). + */ + static final int PREVENT_VM_FROM_REACHING_SAFEPOINT = 1; + + /** + * The thread won't freeze at a safepoint and the safepoint handling will ignore the thread. + * So, the VM will be able to reach a safepoint regardless of the status of this thread. + */ + static final int IGNORE_THREAD_IN_SAFEPOINT_HANDLING = 2; + + public static boolean isIgnoredBySafepointHandling(IsolateThread vmThread) { + return safepointBehaviorTL.getVolatile(vmThread) == IGNORE_THREAD_IN_SAFEPOINT_HANDLING; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static boolean safepointChecksEnabled() { + return safepointBehaviorTL.getVolatile() == ALLOW_SAFEPOINT; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static boolean safepointChecksEnabled(IsolateThread vmThread) { + return safepointBehaviorTL.getVolatile(vmThread) == ALLOW_SAFEPOINT; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static int getSafepointBehavior(IsolateThread vmThread) { + return safepointBehaviorTL.getVolatile(vmThread); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static void setPreventVMFromReachingSafepoint() { + assert safepointChecksEnabled(); + safepointBehaviorTL.setVolatile(PREVENT_VM_FROM_REACHING_SAFEPOINT); + } + + /** + * Changes the safepoint behavior so that this thread won't freeze at a safepoint and the + * safepoint handling will ignore the thread. So, the VM will be able to reach a safepoint + * regardless of the status of this thread. + * + * Be careful with this. If a thread is ignored by the safepoint handling, it means that it + * can continue executing while a safepoint (and therefore a GC) is in progress. So, either + * prevent that a safepoint can be initiated (by holding the {@link #THREAD_MUTEX}) or make + * sure that this thread does not access any movable heap objects (even executing write + * barriers can already cause issues). + */ + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + static void setIgnoreThreadInSafepointHandling() { + assert safepointChecksEnabled(); + safepointBehaviorTL.setVolatile(IGNORE_THREAD_IN_SAFEPOINT_HANDLING); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static String toString(int safepointBehavior) { + switch (safepointBehavior) { + case ALLOW_SAFEPOINT: + return ""; + case PREVENT_VM_FROM_REACHING_SAFEPOINT: + return "PREVENT_VM_FROM_REACHING_SAFEPOINT"; + case IGNORE_THREAD_IN_SAFEPOINT_HANDLING: + return "IGNORE_THREAD_IN_SAFEPOINT_HANDLING"; + default: + return "Invalid safepoint behavior"; + } + } + } + /** * A thread-local enum conveying any actions needed before thread begins executing Java code. */ public static class ActionOnTransitionToJavaSupport { - /** The actions to be performed. */ + /** + * The actions to be performed. + */ private static final FastThreadLocalInt actionTL = FastThreadLocalFactory.createInt("ActionOnTransitionToJavaSupport.actionTL"); - /** The thread does not need to take any action. */ + /** + * The thread does not need to take any action. + */ private static final int NO_ACTION = 0; - /** Code synchronization should be performed due to newly installed code. */ + /** + * Code synchronization should be performed due to newly installed code. + */ private static final int SYNCHRONIZE_CODE = NO_ACTION + 1; @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @@ -886,7 +969,9 @@ public static class ActionOnExitSafepointSupport { */ private static final int SWITCH_STACK = NO_ACTION + 1; - /** Target of stack switching. */ + /** + * Target of stack switching. + */ private static final FastThreadLocalWord returnSP = FastThreadLocalFactory.createWord("ActionOnExitSafepointSupport.returnSP"); private static final FastThreadLocalWord returnIP = FastThreadLocalFactory.createWord("ActionOnExitSafepointSupport.returnIP"); diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java index 32815f040dcd..d6df15bb1676 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java @@ -832,7 +832,7 @@ static void FatalError(JNIEnvironment env, CCharPointer message) { if (log != null) { try { log.string("Fatal error reported via JNI: ").string(message).newline(); - VMThreads.StatusSupport.setStatusIgnoreSafepoints(); + VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); SubstrateDiagnostics.printFatalError(log, KnownIntrinsics.readCallerStackPointer(), callerIP); } catch (Throwable ignored) { /* From fce8ec4f96f5cf6450ebeeea09a44320946ef61c Mon Sep 17 00:00:00 2001 From: Duncan MacGregor Date: Mon, 11 Oct 2021 14:16:21 +0100 Subject: [PATCH 411/681] Fix linter errors. --- .../tools/profiler/impl/SVGSamplerOutput.java | 58 ++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java index f63ecbbb2c96..f7dbe37e5b2b 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/impl/SVGSamplerOutput.java @@ -369,19 +369,25 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SampleKey other = (SampleKey) obj; - if (nameId != other.nameId) + if (nameId != other.nameId) { return false; - if (sourceId != other.sourceId) + } + if (sourceId != other.sourceId) { return false; - if (sourceLine != other.sourceLine) + } + if (sourceLine != other.sourceLine) { return false; + } return true; } } @@ -410,38 +416,38 @@ private int indexForSampleKey(String name, SourceSection section) { private int indexForSampleKey(String name, String sourceFile, int line) { int nameId = nameHash.computeIfAbsent(name, k -> { - sampleNames.put(k); - return nameCounter++; - }); + sampleNames.put(k); + return nameCounter++; + }); int sourceId = sourceHash.computeIfAbsent(sourceFile, k -> { - sourceNames.put(k); - return sourceCounter++; - }); + sourceNames.put(k); + return sourceCounter++; + }); return keyHash.computeIfAbsent(new SampleKey(nameId, sourceId, line), k -> { - sampleKeys.add(k); - JSONArray jsonKey = new JSONArray(); - jsonKey.put(k.nameId); - jsonKey.put(k.sourceId); - jsonKey.put(k.sourceLine); - sampleJsonKeys.put(jsonKey); - return keyCounter++; - }); + sampleKeys.add(k); + JSONArray jsonKey = new JSONArray(); + jsonKey.put(k.nameId); + jsonKey.put(k.sourceId); + jsonKey.put(k.sourceLine); + sampleJsonKeys.put(jsonKey); + return keyCounter++; + }); } private HashMap> recursiveChildMap = new HashMap<>(); private HashMap childrenByKeyForSample(JSONObject sample) { return recursiveChildMap.computeIfAbsent(sample.getInt("id"), k -> { - HashMap childMap = new HashMap<>(); - return childMap; - }); + HashMap childMap = new HashMap<>(); + return childMap; + }); } private static final class RecursivePositionTask { JSONObject sample; long x; - public RecursivePositionTask(JSONObject sample, long x) { + RecursivePositionTask(JSONObject sample, long x) { this.sample = sample; this.x = x; } @@ -513,7 +519,7 @@ private static void addRecursiveChild(JSONObject sample, JSONObject child) { child.put("ri", child.getInt("i")); child.put("rh", child.getInt("h")); } - + private static void mergeCounts(JSONObject a, JSONObject b, boolean child) { int aRI = a.has("ri") ? a.getInt("ri") : a.getInt("i"); int aRC = a.has("rc") ? a.getInt("rc") : a.getInt("c"); @@ -1140,7 +1146,7 @@ private void buildHistogram(JSONObject sample, ArrayDeque samples, M if (sample.has("s")) { JSONArray children = sample.getJSONArray("s"); for (Object childId : children) { - samples.add(owner.sampleDataForId((Integer)childId)); + samples.add(owner.sampleDataForId((Integer) childId)); } } } From 567a6d2648a891b91847dd51c0390b390c63593a Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 11 Oct 2021 19:46:08 +0200 Subject: [PATCH 412/681] Fix invalid handle creation when we know that a compiler is already initialized. --- .../hotspot/libgraal/LibGraalHotSpotTruffleCompiler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalHotSpotTruffleCompiler.java b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalHotSpotTruffleCompiler.java index a9b1155a115e..b17238329ec9 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalHotSpotTruffleCompiler.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalHotSpotTruffleCompiler.java @@ -144,7 +144,7 @@ public void shutdown() { @SuppressWarnings("try") public void installTruffleCallBoundaryMethod(ResolvedJavaMethod method) { try (LibGraalScope scope = new LibGraalScope(LibGraalScope.DetachAction.DETACH_RUNTIME_AND_RELEASE)) { - TruffleToLibGraalCalls.installTruffleCallBoundaryMethod(getIsolateThread(), handle(optionsEncoder(null), null, false), LibGraal.translate(method)); + TruffleToLibGraalCalls.installTruffleCallBoundaryMethod(getIsolateThread(), handle(), LibGraal.translate(method)); } } @@ -152,7 +152,7 @@ public void installTruffleCallBoundaryMethod(ResolvedJavaMethod method) { @SuppressWarnings("try") public void installTruffleReservedOopMethod(ResolvedJavaMethod method) { try (LibGraalScope scope = new LibGraalScope(LibGraalScope.DetachAction.DETACH_RUNTIME_AND_RELEASE)) { - TruffleToLibGraalCalls.installTruffleReservedOopMethod(getIsolateThread(), handle(optionsEncoder(null), null, false), LibGraal.translate(method)); + TruffleToLibGraalCalls.installTruffleReservedOopMethod(getIsolateThread(), handle(), LibGraal.translate(method)); } } From 63574f381fc3da6214173defe09dd008fe8fe0bf Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 11 Oct 2021 19:51:07 +0200 Subject: [PATCH 413/681] Improve documentation in bypassedReservedOop. --- .../AbstractHotSpotTruffleRuntime.java | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot/src/org/graalvm/compiler/truffle/runtime/hotspot/AbstractHotSpotTruffleRuntime.java b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot/src/org/graalvm/compiler/truffle/runtime/hotspot/AbstractHotSpotTruffleRuntime.java index 2cf0b48d2099..b1756139cc6b 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot/src/org/graalvm/compiler/truffle/runtime/hotspot/AbstractHotSpotTruffleRuntime.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot/src/org/graalvm/compiler/truffle/runtime/hotspot/AbstractHotSpotTruffleRuntime.java @@ -465,7 +465,6 @@ public boolean bypassedReservedOop(boolean waitForInit) { throw CompilerDirectives.shouldNotReachHere("bypassedReservedOop without field available. default fast thread locals should be used instead."); } - // finish initialization CompilationTask task = initializationTask; if (task != null) { while (waitForInit) { @@ -478,17 +477,46 @@ public boolean bypassedReservedOop(boolean waitForInit) { continue; } } - // compiler init did install the methods + /* + * We were currently initializing. No need to reinstall the code stubs. Just try using + * them again has a very likely-hood of succeeding or if we do not wait for + * inititialization then the caller can use oop accessor methods + * (setJVMCIReservedReference0, getJVMCIReservedReference0) instead. + */ return true; } + if (!truffleCompilerInitialized) { + /* + * If the initialization did not yet complete here, then this means that initializing + * the compiler failed. We can therefore not continue installing the stubs. So we + * re-throw the compiler initialization error or we return false which will likely + * trigger an assertion error in the caller at a later point. + */ if (truffleCompilerInitializationException != null) { throw new AssertionError("Compiler initialization failed cannot continue.", truffleCompilerInitializationException); } return false; } - // otherwise stubs are installed as part of initialization. + + /* + * If we reached this point we are not initializing anymore and the compiler is successfully + * initialized. If bypassedReservedOop was called this also means that we skipped the + * installed code for the JVMCI reserved oop accessor. This can happen if the debugger steps + * over the code and invalidates any installed Java code stub, the HotSpot code cache + * decides to clean up the the stub for the accessor method or this happened due to an + * initialization race condition. In all three cases the best we can do is to try to install + * the stub code again even if this means repeated compilation and installation of this + * method during debug-stepping. Unfortunately there is no known way to detect invalidation + * of HotSpot installed code reliably. + */ installReservedOopMethods((HotSpotTruffleCompiler) truffleCompiler); + + /* + * We have reinstalled the stubs. Returning true indicates that the caller should retry + * calling the stubs or use other available means like the oop accessor methods + * (setJVMCIReservedReference0, getJVMCIReservedReference0). + */ return true; } From c5099360721ac8d6bf9ef663f9ca4af1fa83b024 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 11 Oct 2021 21:58:11 +0200 Subject: [PATCH 414/681] Avoid transient issues by refactoring NoTagSamplingTest to no longer be timing based. --- .../profiler/test/NoTagSamplingTest.java | 82 ++++++++++++------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java index 755a20734e9f..8939a359323d 100644 --- a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java +++ b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java @@ -24,15 +24,23 @@ */ package com.oracle.truffle.tools.profiler.test; -import java.util.Collection; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Source; -import org.junit.Assert; import org.junit.Test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleSafepoint; @@ -40,24 +48,49 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.test.polyglot.ProxyLanguage; import com.oracle.truffle.tools.profiler.CPUSampler; -import com.oracle.truffle.tools.profiler.CPUSamplerData; -import com.oracle.truffle.tools.profiler.ProfilerNode; +import com.oracle.truffle.tools.profiler.StackTraceEntry; public class NoTagSamplingTest { + private static final String TEST_ROOT_NAME = LILRootNode.class.getName(); + + private static Semaphore await; + @Test - public void testNoTagSampling() { - Context context = Context.create(NoTagLanguage.ID); - CPUSampler sampler = CPUSampler.find(context.getEngine()); - sampler.setCollecting(true); - Source source = Source.newBuilder(NoTagLanguage.ID, "", "").buildLiteral(); - // Eval twice so that we compile on first call when running with compile immediately. - context.eval(source); - context.eval(source); - sampler.setCollecting(false); - final CPUSamplerData data = sampler.getData().values().iterator().next(); - final Collection> profilerNodes = data.getThreadData().values().iterator().next(); - Assert.assertEquals(1, profilerNodes.size()); + public void testNoTagSampling() throws InterruptedException, ExecutionException { + ExecutorService singleThread = Executors.newSingleThreadExecutor(); + await = new Semaphore(0); + try (Context context = Context.create(NoTagLanguage.ID)) { + CPUSampler sampler = CPUSampler.find(context.getEngine()); + Source source = Source.newBuilder(NoTagLanguage.ID, "", "").buildLiteral(); + Future f = singleThread.submit(() -> { + return context.eval(source).asInt(); + }); + + Map> sample = null; + for (int i = 0; i < 10000; i++) {// times out ofter 10s + sample = sampler.takeSample(); + if (!sample.isEmpty()) { + break; + } + try { + Thread.sleep(1); + } catch (InterruptedException e) { + throw new AssertionError(e); + } + } + + // wait for future + await.release(); + assertEquals(42, f.get()); + assertTrue(!sample.isEmpty()); + List entries = sample.values().iterator().next(); + assertEquals(1, entries.size()); + assertEquals(TEST_ROOT_NAME, entries.get(0).getRootName()); + + singleThread.shutdown(); + singleThread.awaitTermination(10, TimeUnit.SECONDS); + } } @@ -67,21 +100,14 @@ protected LILRootNode(TruffleLanguage language) { super(language); } - @TruffleBoundary - private static void sleepSomeTime() { - try { - Thread.sleep(1); - } catch (InterruptedException e) { - Assert.fail(); - } + @Override + public String getName() { + return TEST_ROOT_NAME; } @Override public Object execute(VirtualFrame frame) { - for (int i = 0; i < 100; i++) { - sleepSomeTime(); - TruffleSafepoint.poll(this); - } + TruffleSafepoint.setBlockedThreadInterruptible(this, Semaphore::acquire, await); return 42; } } From 1dc204bea9f692a37565fbf078596982183d7e52 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 11 Oct 2021 22:22:58 +0200 Subject: [PATCH 415/681] Fix checkstyle. --- .../oracle/truffle/tools/profiler/test/NoTagSamplingTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java index 8939a359323d..3290875cb74d 100644 --- a/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java +++ b/tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/NoTagSamplingTest.java @@ -68,7 +68,7 @@ public void testNoTagSampling() throws InterruptedException, ExecutionException }); Map> sample = null; - for (int i = 0; i < 10000; i++) {// times out ofter 10s + for (int i = 0; i < 10000; i++) { // times out after 10s sample = sampler.takeSample(); if (!sample.isEmpty()) { break; From ca6ac05e8598e679b0b5f8a8d128a36e7e591d4d Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Tue, 12 Oct 2021 07:11:56 +0000 Subject: [PATCH 416/681] Use getCallTarget() instead of createCallTarget(). --- .../truffle/tools/chromeinspector/test/ProfilerTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/ProfilerTest.java b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/ProfilerTest.java index b01c882c147c..0764458c8541 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/ProfilerTest.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/ProfilerTest.java @@ -25,7 +25,6 @@ package com.oracle.truffle.tools.chromeinspector.test; import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleSafepoint; import com.oracle.truffle.api.frame.VirtualFrame; @@ -105,7 +104,7 @@ private static class TestNoSourceLanguage extends ProxyLanguage { @Override protected final CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { - return Truffle.getRuntime().createCallTarget(new NoSourceRootNode(languageInstance)); + return new NoSourceRootNode(languageInstance).getCallTarget(); } private final class NoSourceRootNode extends RootNode { From b8a3cb9cae550e148e7b37e82f798a8b910a9861 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Tue, 12 Oct 2021 10:48:19 +0200 Subject: [PATCH 417/681] Minor fix. --- .../src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java | 2 +- .../com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java index f1cdc1cc1fa1..df8cc8897bb4 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java @@ -283,7 +283,7 @@ UnalignedHeader produceUnalignedChunk(UnsignedWord objectSize) { return result; } - public boolean areUnalignedChunksZeroed() { + public static boolean areUnalignedChunksZeroed() { return CommittedMemoryProvider.get().areUnalignedChunksZeroed(); } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java index 166cb20c673a..1f124f2bbcc9 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java @@ -235,7 +235,7 @@ private static Object slowPathNewArrayWithoutAllocating(DynamicHub hub, int leng if (size.aboveOrEqual(HeapParameters.getLargeArrayThreshold())) { /* Large arrays go into their own unaligned chunk. */ - boolean needsZeroing = !HeapImpl.getChunkProvider().areUnalignedChunksZeroed(); + boolean needsZeroing = !HeapChunkProvider.areUnalignedChunksZeroed(); UnalignedHeapChunk.UnalignedHeader newTlabChunk = HeapImpl.getChunkProvider().produceUnalignedChunk(size); return allocateLargeArrayInNewTlab(hub, length, size, fillStartOffset, newTlabChunk, needsZeroing); } From 01135c19e990277519ca06b7e00276e2f2f42d62 Mon Sep 17 00:00:00 2001 From: Matthias Neugschwandtner Date: Thu, 19 Aug 2021 11:04:43 +0200 Subject: [PATCH 418/681] Add LanguageLibraryConfig and native launcher A native launcher application that can launch language libraries. --- espresso/mx.espresso/mx_espresso.py | 1 + sdk/CHANGELOG.md | 1 + sdk/mx.sdk/mx_sdk.py | 1 + sdk/mx.sdk/mx_sdk_vm.py | 18 +- sdk/mx.sdk/mx_sdk_vm_impl.py | 89 ++++++- .../src/launcher.cc | 236 ++++++++++++++++++ .../org.graalvm.launcher/launcher.jniconfig | 8 + .../native-image.properties | 3 +- .../launcher/AbstractLanguageLauncher.java | 84 ++++++- .../org/graalvm/nativeimage/ImageInfo.java | 4 +- .../svm/core/posix/SunMiscSubstitutions.java | 3 + .../svm/core/SubstrateExitHandlerFeature.java | 3 +- .../com/oracle/svm/core/SubstrateOptions.java | 19 +- 13 files changed, 453 insertions(+), 17 deletions(-) create mode 100644 sdk/src/org.graalvm.launcher.native/src/launcher.cc create mode 100644 sdk/src/org.graalvm.launcher/src/META-INF/native-image/org.graalvm.launcher/launcher.jniconfig diff --git a/espresso/mx.espresso/mx_espresso.py b/espresso/mx.espresso/mx_espresso.py index bf408b7a8c66..4634a54c2393 100644 --- a/espresso/mx.espresso/mx_espresso.py +++ b/espresso/mx.espresso/mx_espresso.py @@ -173,6 +173,7 @@ def _espresso_gate_runner(args, tasks): '--language:java', '--tool:all', '-H:+EnableSignalAPI', + '-R:+EnableSignalHandling', '-R:+InstallSegfaultHandler', '--features=com.oracle.truffle.espresso.FinalizationFeature', ], diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index 063ed15bffd5..7e9aed9588b2 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -4,6 +4,7 @@ This changelog summarizes major changes between GraalVM SDK versions. The main f ## Version 22.0.0 * (GR-33657) Native Image API: Added `CEntryPoint#include` attribute which can be used to controll if the entry point should be automatically added to the shared library. +* (GR-33207) Native image language libraries: languages can now be deployed as native image libraries, facilitating native embedding scenarios. In this case, a native launcher loads the library dynamically. ## Version 21.3.0 * Added the ability to share values between contexts. Please see `Context.Builder.allowValueSharing(boolean)` for further details. diff --git a/sdk/mx.sdk/mx_sdk.py b/sdk/mx.sdk/mx_sdk.py index 4095538281ff..71bf8556addd 100644 --- a/sdk/mx.sdk/mx_sdk.py +++ b/sdk/mx.sdk/mx_sdk.py @@ -143,6 +143,7 @@ def mx_post_parse_cmd_line(args): LauncherConfig = mx_sdk_vm.LauncherConfig LanguageLauncherConfig = mx_sdk_vm.LanguageLauncherConfig LibraryConfig = mx_sdk_vm.LibraryConfig +LanguageLibraryConfig = mx_sdk_vm.LanguageLibraryConfig GraalVmComponent = mx_sdk_vm.GraalVmComponent GraalVmTruffleComponent = mx_sdk_vm.GraalVmTruffleComponent GraalVmLanguage = mx_sdk_vm.GraalVmLanguage diff --git a/sdk/mx.sdk/mx_sdk_vm.py b/sdk/mx.sdk/mx_sdk_vm.py index 9067f23c0f43..0b5df4036d1b 100644 --- a/sdk/mx.sdk/mx_sdk_vm.py +++ b/sdk/mx.sdk/mx_sdk_vm.py @@ -191,14 +191,28 @@ def __init__(self, destination, jar_distributions, main_class, build_args, langu class LibraryConfig(AbstractNativeImageConfig): - def __init__(self, destination, jar_distributions, build_args, jvm_library=False, use_modules=None, **kwargs): + def __init__(self, destination, jar_distributions, build_args, jvm_library=False, use_modules=None, home_finder=False, **kwargs): """ :param bool jvm_library """ - super(LibraryConfig, self).__init__(destination, jar_distributions, build_args, use_modules, **kwargs) + super(LibraryConfig, self).__init__(destination, jar_distributions, build_args, use_modules, home_finder=home_finder, **kwargs) self.jvm_library = jvm_library +class LanguageLibraryConfig(LibraryConfig): + def __init__(self, destination, jar_distributions, main_class, build_args, language, is_sdk_launcher=True, launchers=None, **kwargs): + """ + :param str language + :param str main_class + """ + super(LanguageLibraryConfig, self).__init__(destination, jar_distributions, build_args, home_finder=True, **kwargs) + self.is_sdk_launcher = is_sdk_launcher + self.main_class = main_class + self.language = language + self.default_symlinks = None + self.relative_home_paths = {} + self.launchers = [mx_subst.path_substitutions.substitute(l) for l in launchers] if launchers else [] + class GraalVmComponent(object): def __init__(self, suite, diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index fff469e96bea..2385cd4a6af8 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -59,6 +59,7 @@ import mx import mx_gate +import mx_native import mx_subst import mx_sdk import mx_sdk_vm @@ -721,6 +722,11 @@ def _find_escaping_links(root_dir): # add `LibraryConfig.destination` and the generated header files to the layout _add(layout, _svm_library_dest, _source_type + ':' + _library_project_name, _component) _add(layout, _svm_library_home, _source_type + ':' + _library_project_name + '/*.h', _component) + if (not stage1 or _skip_libraries(_library_config)) and isinstance(_library_config, mx_sdk.LanguageLibraryConfig): + # add native launchers for language libraries + for _executable in _library_config.launchers: + _add(layout, join(_component_base, _executable), 'dependency:{}'.format(NativeLibraryLauncherProject.library_launcher_project_name(_library_config)), _component) + _add_link(_jdk_jre_bin, _component_base + _executable) _add_native_image_macro(_library_config, _component) graalvm_dists.update(_component.polyglot_lib_jar_dependencies) @@ -1280,9 +1286,15 @@ def contents(self): else: raise mx.abort("Unsupported image config type: " + str(type(image_config))) - if isinstance(image_config, mx_sdk.LanguageLauncherConfig): + if isinstance(image_config, (mx_sdk.LanguageLauncherConfig, mx_sdk.LanguageLibraryConfig)): build_args += ['--language:' + image_config.language, '--tool:all'] + if isinstance(image_config, mx_sdk.LanguageLibraryConfig): + build_args += [ + '-Dorg.graalvm.launcher.class=' + image_config.main_class, + '-H:+EnableSignalAPI', + ] + source_type = 'skip' if isinstance(image_config, mx_sdk.LibraryConfig) and _skip_libraries(image_config) else 'dependency' graalvm_image_destination = graalvm_dist.find_single_source_location(source_type + ':' + project_name_f(image_config)) @@ -1292,13 +1304,12 @@ def contents(self): '-Dorg.graalvm.launcher.relative.home=' + relpath(graalvm_image_destination, graalvm_home), ] - if isinstance(image_config, mx_sdk.LauncherConfig): + if isinstance(image_config, (mx_sdk.LauncherConfig, mx_sdk.LanguageLibraryConfig)): if image_config.is_sdk_launcher: launcher_classpath = NativePropertiesBuildTask.get_launcher_classpath(graalvm_dist, graalvm_home, image_config, self.subject.component, exclude_implicit=True) - build_args += [ - '-H:-ParseRuntimeOptions', - '-Dorg.graalvm.launcher.classpath=' + os.pathsep.join(launcher_classpath), - ] + build_args += ['-Dorg.graalvm.launcher.classpath=' + os.pathsep.join(launcher_classpath)] + if isinstance(image_config, mx_sdk.LauncherConfig): + build_args += ['-H:-ParseRuntimeOptions'] build_args += [ '--install-exit-handlers', @@ -2559,6 +2570,65 @@ def _get_native_image_configs(component, config_type): def _libpolyglot_macro_dist_name(component): return component.short_name + "_libpolyglot_macro" +class NativeLibraryLauncherProject(mx_native.DefaultNativeProject): + def __init__(self, component, language_library_config): + _dir = join(_suite.dir, "src", "org.graalvm.launcher.native") + self.language_library_config = language_library_config + self.component = component + self.jvm_launcher = _skip_libraries(self.language_library_config) or not _get_svm_support().is_supported() + _dependencies = [] if self.jvm_launcher else [GraalVmNativeImage.project_name(self.language_library_config)] + super(NativeLibraryLauncherProject, self).__init__(_suite, NativeLibraryLauncherProject.library_launcher_project_name(self.language_library_config), 'src', [], _dependencies, None, _dir, 'executable', deliverable=self.language_library_config.language, use_jdk_headers=True) + + @staticmethod + def library_launcher_project_name(language_library_config): + return "org.graalvm.launcher.native." + language_library_config.language + + @property + def cflags(self): + _dist = get_final_graalvm_distribution() + _exe_path = _dist.find_single_source_location('dependency:' + NativeLibraryLauncherProject.library_launcher_project_name(self.language_library_config)) + _dynamic_cflags = [ + '-DCP_SEP=' + os.pathsep, + '-DDIR_SEP=' + ('\\\\' if mx.is_windows() else '/'), + ] + if self.jvm_launcher: + _graalvm_home = _get_graalvm_archive_path("") + _cp = NativePropertiesBuildTask.get_launcher_classpath(_dist, _graalvm_home, self.language_library_config, self.component, exclude_implicit=True) + _cp = [join(_dist.path_substitutions.substitute(''), x) for x in _cp] + # path from langauge launcher to jars + _cp = [relpath(x, start=dirname(_exe_path)) for x in _cp] + if mx.is_windows(): + _libjvm_path = join(_dist.path_substitutions.substitute(''), 'bin', 'server', 'jvm.dll') + _libjvm_path = relpath(_libjvm_path, start=dirname(_exe_path)).replace('\\', '\\\\') + _cp = [x.replace('\\', '\\\\') for x in _cp] + else: + if _src_jdk_version < 9 and mx.is_linux(): + _libjvm_path = join(_dist.path_substitutions.substitute(''), 'lib', mx.get_arch(), 'server', mx.add_lib_suffix("libjvm")) + else: + _libjvm_path = join(_dist.path_substitutions.substitute(''), 'lib', 'server', mx.add_lib_suffix("libjvm")) + _libjvm_path = relpath(_libjvm_path, start=dirname(_exe_path)) + _dynamic_cflags += [ + '-DJVM', + '-DLAUNCHER_CLASS=' + self.language_library_config.main_class, + '-DLAUNCHER_CLASSPATH="{\\"' + '\\", \\"'.join(_cp) + '\\"}"', + '-DLIBLANG_RELPATH=' + _libjvm_path, + ] + else: + _lib_path = _dist.find_single_source_location('dependency:' + GraalVmLibrary.project_name(self.language_library_config)) + # path from language launcher to library + _liblang_relpath = relpath(_lib_path, start=dirname(_exe_path)) + _dynamic_cflags += [ + '-DLIBLANG_RELPATH=' + (_liblang_relpath.replace('\\', '\\\\') if mx.is_windows() else _liblang_relpath) + ] + return super(NativeLibraryLauncherProject, self).cflags + _dynamic_cflags + + @property + def ldlibs(self): + _dynamic_ldlibs = [] + if not mx.is_windows(): + _dynamic_ldlibs += ['-ldl'] + return super(NativeLibraryLauncherProject, self).ldlibs + _dynamic_ldlibs + def has_vm_suite(): global _vm_suite if _vm_suite == 'uninitialized': @@ -2605,12 +2675,15 @@ def mx_register_dynamic_suite_constituents(register_project, register_distributi needs_stage1 = True if with_svm: register_project(GraalVmNativeProperties(component, launcher_config)) - if with_svm: - for library_config in _get_library_configs(component): + for library_config in _get_library_configs(component): + if with_svm: register_project(GraalVmLibrary(component, GraalVmNativeImage.project_name(library_config), [], library_config)) assert with_svm register_project(GraalVmNativeProperties(component, library_config)) needs_stage1 = True # library configs need a stage1 even when they are skipped + if isinstance(library_config, mx_sdk.LanguageLibraryConfig): + launcher_project = NativeLibraryLauncherProject(component, library_config) + register_project(launcher_project) if component.installable and not _disable_installable(component): installables.setdefault(component.installable_id, []).append(component) if libpolyglot_component is not None and GraalVmLibPolyglotNativeProperties.needs_lib_polyglot_native_properties(component): diff --git a/sdk/src/org.graalvm.launcher.native/src/launcher.cc b/sdk/src/org.graalvm.launcher.native/src/launcher.cc new file mode 100644 index 000000000000..f9fd5cc9b4ce --- /dev/null +++ b/sdk/src/org.graalvm.launcher.native/src/launcher.cc @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +#define QUOTE(name) #name +#define STR(macro) QUOTE(macro) + +#ifdef JVM + #ifndef LAUNCHER_CLASS + #error launcher class undefined + #endif + #define LAUNCHER_CLASS_STR STR(LAUNCHER_CLASS) + #ifndef LAUNCHER_CLASSPATH + #error launcher classpath undefined + #endif +#endif + +#ifndef LIBLANG_RELPATH + #error path to native library undefined +#endif + +#ifndef DIR_SEP + #error directory separator undefined +#endif + +#ifndef CP_SEP + #error class path separator undefined +#endif + +#define LIBLANG_RELPATH_STR STR(LIBLANG_RELPATH) +#define DIR_SEP_STR STR(DIR_SEP) +#define CP_SEP_STR STR(CP_SEP) + +#if defined (__linux__) + #include + #include + #include + #include +#elif defined (__APPLE__) + #include + #include + #include + #include + #include +#elif defined (_WIN32) + #include + #include + #include +#else + #error platform not supported or undefined +#endif + +typedef jint(*CreateJVM)(JavaVM **, void **, void *); + +char *exe_directory() { + #if defined (__linux__) + return dirname(realpath("/proc/self/exe", NULL)); + #elif defined (__APPLE__) + char path[PATH_MAX]; + uint32_t path_len = PATH_MAX; + _NSGetExecutablePath(path, &path_len); + return dirname(realpath(path, NULL)); + #elif defined (_WIN32) + char *path = (char *)malloc(_MAX_PATH); + GetModuleFileNameA(NULL, path, _MAX_PATH); + // get the directory part + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + _splitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0); + _makepath_s(path, _MAX_PATH, drive, dir, NULL, NULL); + return path; + #endif +} + +CreateJVM loadliblang(char *exe_dir) { + int size = strlen(exe_dir) + sizeof(DIR_SEP_STR) + sizeof(LIBLANG_RELPATH_STR) + 1; + char *liblang_path = (char*)malloc(size); + strcpy(liblang_path, exe_dir); + strcat(liblang_path, DIR_SEP_STR); + strcat(liblang_path, LIBLANG_RELPATH_STR); +#if defined (__linux__) || defined (__APPLE__) + void* jvm_handle = dlopen(liblang_path, RTLD_NOW); + if (jvm_handle != NULL) { + return (CreateJVM) dlsym(jvm_handle, "JNI_CreateJavaVM"); + } +#else + HMODULE jvm_handle = LoadLibraryA(liblang_path); + if (jvm_handle != NULL) { + return (CreateJVM) GetProcAddress(jvm_handle, "JNI_CreateJavaVM"); + } +#endif + return NULL; +} + +int main(int argc, char **argv) { + char *exe_dir = exe_directory(); + CreateJVM createJVM = loadliblang(exe_dir); + if (!createJVM) { + fprintf(stderr, "Could not load language library.\n"); + return -1; + } + JavaVM *jvm; + JNIEnv *env; + JavaVMInitArgs vm_args; + JavaVMOption options[4]; + #ifdef JVM + const char *cp_entries[] = LAUNCHER_CLASSPATH; + int cp_cnt = sizeof(cp_entries) / sizeof(*cp_entries); + int size = (strlen(exe_dir) + sizeof(DIR_SEP_STR)) * cp_cnt + sizeof(CP_SEP_STR) * (cp_cnt-1) + 1; + for (int i = 0; i < cp_cnt; i++) { + size += strlen(cp_entries[i]); + } + const char cp_property[] = "-Djava.class.path="; + size += sizeof(cp_property); + char *cp = (char *)malloc(size); + strcpy(cp, cp_property); + for (int i = 0; i < cp_cnt; i++) { + strcat(cp, exe_dir); + strcat(cp, DIR_SEP_STR); + strcat(cp, cp_entries[i]); + if (i < cp_cnt-1) { + strcat(cp, CP_SEP_STR); + } + } + options[0].optionString = cp; + options[1].optionString = "-Dorg.graalvm.launcher.class=" LAUNCHER_CLASS_STR; + vm_args.nOptions = 2; + #else + vm_args.nOptions = 0; + #endif + vm_args.version = JNI_VERSION_1_8; + vm_args.options = options; + vm_args.ignoreUnrecognized = false; + + int res = createJVM(&jvm, (void**)&env, &vm_args); + if (res != JNI_OK) { + fprintf(stderr, "Creation of the JVM failed.\n"); + return -1; + } + jclass byteArrayClass = env->FindClass("[B"); + if (byteArrayClass == NULL) { + fprintf(stderr, "Byte array class not found.\n"); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + } + return -1; + } + jclass launcherClass = env->FindClass("org/graalvm/launcher/AbstractLanguageLauncher"); + if (launcherClass == NULL) { + fprintf(stderr, "Launcher class not found.\n"); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + } + return -1; + } + jmethodID mid = env->GetStaticMethodID(launcherClass, "runLauncher", "([[BIJ)V"); + if (mid == NULL) { + fprintf(stderr, "Launcher entry point not found.\n"); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + } + return -1; + } + + // create args string array + long argv_native = (long)argv; + int argc_native = argc; + argv++; + argc--; + + jobjectArray args = env->NewObjectArray(argc, byteArrayClass, NULL); + for (int i = 0; i < argc; i++) { + int arraySize = strlen(argv[i]); + jbyteArray arg = env->NewByteArray(arraySize); + env->SetByteArrayRegion(arg, 0, arraySize, (jbyte *)(argv[i])); + if (env->ExceptionCheck()) { + fprintf(stderr, "Error in SetByteArrayRegion:\n"); + env->ExceptionDescribe(); + return -1; + } + env->SetObjectArrayElement(args, i, arg); + if (env->ExceptionCheck()) { + fprintf(stderr, "Error in SetObjectArrayElement:\n"); + env->ExceptionDescribe(); + return -1; + } + } + + // invoke launcher entry point + env->CallStaticVoidMethod(launcherClass, mid, args, argc_native, argv_native); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + return -1; + } + return 0; +} diff --git a/sdk/src/org.graalvm.launcher/src/META-INF/native-image/org.graalvm.launcher/launcher.jniconfig b/sdk/src/org.graalvm.launcher/src/META-INF/native-image/org.graalvm.launcher/launcher.jniconfig new file mode 100644 index 000000000000..3a35a5d84541 --- /dev/null +++ b/sdk/src/org.graalvm.launcher/src/META-INF/native-image/org.graalvm.launcher/launcher.jniconfig @@ -0,0 +1,8 @@ +[ + { + "name": "org.graalvm.launcher.AbstractLanguageLauncher", + "methods": [ + { "name": "runLauncher" } + ] + } +] diff --git a/sdk/src/org.graalvm.launcher/src/META-INF/native-image/org.graalvm.launcher/native-image.properties b/sdk/src/org.graalvm.launcher/src/META-INF/native-image/org.graalvm.launcher/native-image.properties index c5657e153d52..f2f92c7b5c9e 100644 --- a/sdk/src/org.graalvm.launcher/src/META-INF/native-image/org.graalvm.launcher/native-image.properties +++ b/sdk/src/org.graalvm.launcher/src/META-INF/native-image/org.graalvm.launcher/native-image.properties @@ -1 +1,2 @@ -Args = --features=com.oracle.svm.thirdparty.jline.JLine3Feature +Args = --features=com.oracle.svm.thirdparty.jline.JLine3Feature \ + -H:JNIConfigurationResources=${.}/launcher.jniconfig \ No newline at end of file diff --git a/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/AbstractLanguageLauncher.java b/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/AbstractLanguageLauncher.java index c5c12f2ed490..20c3350846a0 100644 --- a/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/AbstractLanguageLauncher.java +++ b/sdk/src/org.graalvm.launcher/src/org/graalvm/launcher/AbstractLanguageLauncher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -40,6 +40,7 @@ */ package org.graalvm.launcher; +import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -47,6 +48,7 @@ import java.util.List; import java.util.Map; +import org.graalvm.nativeimage.RuntimeOptions; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.Language; @@ -54,6 +56,38 @@ public abstract class AbstractLanguageLauncher extends LanguageLauncherBase { + private static final Constructor LAUNCHER_CTOR; + private int nativeArgc; + private long nativeArgv; + + static { + LAUNCHER_CTOR = getLauncherCtor(); + } + + /** + * Looks up the launcher constructor based on the launcher class passed in via the + * org.graalvm.launcher.class system property. + * + * @return launcher constructor, if found. + */ + @SuppressWarnings("unchecked") + private static Constructor getLauncherCtor() { + String launcherClassName = System.getProperty("org.graalvm.launcher.class"); + Constructor launcherCtor = null; + if (launcherClassName != null) { + try { + Class launcherClass = (Class) Class.forName(launcherClassName); + if (!AbstractLanguageLauncher.class.isAssignableFrom(launcherClass)) { + throw new Exception("Launcher does not implement " + AbstractLanguageLauncher.class.getName()); + } + launcherCtor = launcherClass.getConstructor(); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + return launcherCtor; + } + /** * This starts the launcher. it should be called from the main method: * @@ -81,6 +115,54 @@ protected final void launch(String[] args) { } } + /** + * Entry point for invoking the launcher via JNI. Relies on a launcher constructor to be set via + * the org.graalvm.launcher.class system property. + * + * @param args the command line arguments as an encoding-agnostic byte array + * @param argc the number of native command line arguments + * @param argv pointer to argv + * @throws Exception if no launcher constructor has been set. + */ + public static void runLauncher(byte[][] args, int argc, long argv) throws Exception { + if (isAOT()) { + // enable signal handling for the launcher + RuntimeOptions.set("EnableSignalHandling", true); + } + + if (LAUNCHER_CTOR == null) { + throw new Exception("Launcher constructor has not been set."); + } + + String[] arguments = new String[args.length]; + for (int i = 0; i < args.length; i++) { + arguments[i] = new String(args[i]); + } + + AbstractLanguageLauncher launcher = LAUNCHER_CTOR.newInstance(); + launcher.nativeArgc = argc; + launcher.nativeArgv = argv; + launcher.launch(arguments); + } + + /** + * The native argument count as passed to the main method of the native launcher. + * + * @return native argument count, including the program name + */ + protected int getNativeArgc() { + return nativeArgc; + } + + /** + * The native argument values as passed to the main method of the native launcher. + * + * @return pointer to the native argument values, including the program name + */ + protected long getNativeArgv() { + return nativeArgv; + } + protected static final boolean IS_LIBPOLYGLOT = Boolean.getBoolean("graalvm.libpolyglot"); final void launch(List args, Map defaultOptions, boolean doNativeSetup) { diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java index a9534889435d..94a3090fc1fd 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -143,7 +143,7 @@ public static boolean inImageBuildtimeCode() { } /** - * Returns true if the image is build as an executable. + * Returns true if the image is built as an executable. * * @since 19.0 */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SunMiscSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SunMiscSubstitutions.java index 18130398b026..b4e3799697d9 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SunMiscSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SunMiscSubstitutions.java @@ -136,6 +136,9 @@ private Util_jdk_internal_misc_Signal() { * signals that the VM itself uses. */ static long handle0(int sig, long nativeH) { + if (!SubstrateOptions.EnableSignalHandling.getValue()) { + return sunMiscSignalIgnoreHandler; + } ensureInitialized(); final Signal.SignalDispatcher newDispatcher = nativeHToDispatcher(nativeH); /* If the dispatcher is the CSunMiscSignal handler, then check if the signal is in range. */ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateExitHandlerFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateExitHandlerFeature.java index bce7b3801781..a50ba94c0619 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateExitHandlerFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateExitHandlerFeature.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.core; -import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.hosted.Feature; import com.oracle.svm.core.annotate.Alias; @@ -36,7 +35,7 @@ public class SubstrateExitHandlerFeature implements Feature { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { - if (SubstrateOptions.InstallExitHandlers.getValue() && ImageInfo.isExecutable()) { + if (SubstrateOptions.InstallExitHandlers.getValue()) { RuntimeSupport.getRuntimeSupport().addStartupHook(new SubstrateExitHandlerStartupHook()); } } 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 c4e350b410ac..b03574525b03 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 @@ -46,6 +46,7 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; +import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.ImageSingletons; import com.oracle.svm.core.deopt.DeoptimizationSupport; @@ -425,7 +426,7 @@ public static boolean useLLVMBackend() { public static final HostedOptionKey CheckToolchain = new HostedOptionKey<>(true); @APIOption(name = "install-exit-handlers")// - @Option(help = "Provide java.lang.Terminator exit handlers for executable images", type = User)// + @Option(help = "Provide java.lang.Terminator exit handlers", type = User)// public static final HostedOptionKey InstallExitHandlers = new HostedOptionKey<>(false); @Option(help = "When set to true, the image generator verifies that the image heap does not contain a home directory as a substring", type = User)// @@ -564,6 +565,22 @@ public Boolean getValue(OptionValues values) { } }; + @Option(help = "Enables signal handling", stability = OptionStability.EXPERIMENTAL, type = Expert)// + public static final RuntimeOptionKey EnableSignalHandling = new RuntimeOptionKey(null) { + @Override + public Boolean getValueOrDefault(UnmodifiableEconomicMap, Object> values) { + if (values.containsKey(this)) { + return (Boolean) values.get(this); + } + return ImageInfo.isExecutable(); + } + + @Override + public Boolean getValue(OptionValues values) { + return getValueOrDefault(values.getMap()); + } + }; + @Option(help = "Enable Java Flight Recorder.")// public static final RuntimeOptionKey FlightRecorder = new RuntimeOptionKey<>(false); From ec3c9dc2b94a9a456b74f46611f6e9cba8813614 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Mon, 6 Sep 2021 16:07:27 +0200 Subject: [PATCH 419/681] Initial cleanup of compilation tracing. --- .../truffle/runtime/OptimizedCallTarget.java | 8 +++ .../debug/TraceCompilationListener.java | 65 +++++++++---------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java index e4c5c33eab42..0b1d424a8019 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.function.Supplier; @@ -328,6 +329,8 @@ public Class getType() { private volatile WeakReference singleCallNode = NO_CALL; volatile List blockCompilations; + private final int id; + private static final AtomicInteger idCounter = new AtomicInteger(0); protected OptimizedCallTarget(OptimizedCallTarget sourceCallTarget, RootNode rootNode) { assert sourceCallTarget == null || sourceCallTarget.sourceCallTarget == null : "Cannot create a clone of a cloned CallTarget"; @@ -339,6 +342,7 @@ protected OptimizedCallTarget(OptimizedCallTarget sourceCallTarget, RootNode roo // Do not adopt children of OSRRootNodes; we want to preserve the parent of the child // node(s). this.uninitializedNodeCount = !isOSR() ? GraalRuntimeAccessor.NODES.adoptChildrenAndCount(rootNode) : -1; + id = idCounter.getAndIncrement(); } final Assumption getNodeRewritingAssumption() { @@ -1683,4 +1687,8 @@ private boolean prepareForAOTImpl() { boolean isOSR() { return rootNode instanceof BaseOSRRootNode; } + + public int id() { + return id; + } } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java index af174b538f64..ffbcbd32bd86 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java @@ -69,32 +69,32 @@ private static Map defaultProperties(OptimizedCallTarget target) @Override public void onCompilationQueued(OptimizedCallTarget target, int tier) { if (target.engine.traceCompilationDetails) { - runtime.logEvent(target, 0, "opt queued", queueProperties(target, tier)); + log(target, "opt queued", queueProperties(target, tier, 1)); } } @Override public void onCompilationDequeued(OptimizedCallTarget target, Object source, CharSequence reason, int tier) { if (target.engine.traceCompilationDetails) { - Map properties = queueProperties(target, tier); + Map properties = queueProperties(target, tier, -1); properties.put("Reason", reason); - runtime.logEvent(target, 0, "opt unqueued", properties); + log(target, "opt unqueued", properties); } } - private Map queueProperties(OptimizedCallTarget target, int tier) { + private Map queueProperties(OptimizedCallTarget target, int tier, int queueChange) { Map properties = new LinkedHashMap<>(); - GraalTruffleRuntimeListener.addASTSizeProperty(target, properties); properties.put("Tier", Integer.toString(tier)); // to avoid padding - int callThreshold = tier == 1 ? target.engine.callThresholdInInterpreter : target.engine.callThresholdInFirstTier; int scale = runtime.compilationThresholdScale(); - properties.put("Calls/Thres", String.format("%7d/%5d", target.getCallCount(), FixedPointMath.multiply(scale, callThreshold))); int callAndLoopThreshold = tier == 1 ? target.engine.callAndLoopThresholdInInterpreter : target.engine.callAndLoopThresholdInFirstTier; properties.put("CallsAndLoop/Thres", String.format("%7d/%5d", target.getCallAndLoopCount(), FixedPointMath.multiply(scale, callAndLoopThreshold))); - properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); - properties.put("QueueSize", runtime.getCompilationQueueSize()); + properties.put("Queue", String.format("(Size %d, Change %c%d, Scale %.2f)", + runtime.getCompilationQueueSize(), + queueChange >= 0 ? '+' : '-', + Math.abs(queueChange), + FixedPointMath.toDouble(scale))); properties.put("Time", System.nanoTime() - startTime); - properties.put("Scale", FixedPointMath.toDouble(scale)); + properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); return properties; } @@ -106,7 +106,7 @@ public void onCompilationFailed(OptimizedCallTarget target, String reason, boole } else { Map properties = compilationEndProperties(target, null, null, null, tier); properties.put("Reason", reason); - runtime.logEvent(target, 0, "opt failed", properties); + log(target, "opt failed", properties); } currentCompilation.set(null); } @@ -115,7 +115,7 @@ public void onCompilationFailed(OptimizedCallTarget target, String reason, boole @Override public void onCompilationStarted(OptimizedCallTarget target, int tier) { if (target.engine.traceCompilationDetails) { - runtime.logEvent(target, 0, "opt start", queueProperties(target, tier)); + log(target, "opt start", queueProperties(target, tier, -1)); } if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { @@ -123,13 +123,18 @@ public void onCompilationStarted(OptimizedCallTarget target, int tier) { } } + private void log(OptimizedCallTarget target, String event, Map properties) { + String subject = String.format("id=%-6d %s", target.id(), target.getName()); + runtime.logEvent(target, 0, event, subject, properties, null); + } + @Override public void onCompilationDeoptimized(OptimizedCallTarget target, Frame frame) { if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { Map properties = new LinkedHashMap<>(); GraalTruffleRuntimeListener.addASTSizeProperty(target, properties); properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); - runtime.logEvent(target, 0, "opt deopt", properties); + log(target, "opt deopt", properties); } } @@ -150,43 +155,35 @@ public void onCompilationSuccess(OptimizedCallTarget target, TruffleInlining inl Map properties = compilationEndProperties(target, inliningDecision, graph, result, tier); - runtime.logEvent(target, 0, "opt done", properties); + log(target, "opt done", properties); currentCompilation.set(null); } private Map compilationEndProperties(OptimizedCallTarget target, TruffleInlining inliningDecision, GraphInfo graph, CompilationResultInfo result, int tier) { long timeCompilationFinished = System.nanoTime(); - int nodeCountLowered = graph == null ? 0 : graph.getNodeCount(); Times compilation = currentCompilation.get(); - int calls = 0; - int inlinedCalls; - if (inliningDecision == null) { - CallCountVisitor visitor = new CallCountVisitor(); - target.accept(visitor); - calls = visitor.calls; - inlinedCalls = 0; - } else { - calls = inliningDecision.countCalls(); - inlinedCalls = inliningDecision.countInlinedCalls(); - } - int dispatchedCalls = calls - inlinedCalls; Map properties = new LinkedHashMap<>(); - GraalTruffleRuntimeListener.addASTSizeProperty(target, properties); properties.put("Tier", Integer.toString(tier)); // to avoid padding properties.put("Time", String.format("%4.0f(%4.0f+%-4.0f)ms", // (timeCompilationFinished - compilation.timeCompilationStarted) / 1e6, // (compilation.timePartialEvaluationFinished - compilation.timeCompilationStarted) / 1e6, // (timeCompilationFinished - compilation.timePartialEvaluationFinished) / 1e6)); - properties.put("Inlined", String.format("%3dY %3dN", inlinedCalls, dispatchedCalls)); - properties.put("IR", String.format("%5d/%5d", compilation.nodeCountPartialEval, nodeCountLowered)); - properties.put("CodeSize", result == null ? 0 : result.getTargetCodeSize()); + if (inliningDecision != null) { + int inlinedCalls = inliningDecision.countInlinedCalls(); + int dispatchedCalls = inliningDecision.countCalls() - inlinedCalls; + properties.put("Inlined", String.format("%3dY %3dN", inlinedCalls, dispatchedCalls)); + } + if (graph != null) { + properties.put("IR", String.format("%5d/%5d", compilation.nodeCountPartialEval, graph.getNodeCount())); + } + if (result != null) { + properties.put("CodeSize", result.getTargetCodeSize()); + } if (target.getCodeAddress() != 0) { properties.put("Addr", "0x" + Long.toHexString(target.getCodeAddress())); - } else { - properties.put("Addr", "N/A"); } properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); return properties; @@ -204,7 +201,7 @@ public void onCompilationInvalidated(OptimizedCallTarget target, Object source, if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { Map properties = defaultProperties(target); properties.put("Reason", reason); - runtime.logEvent(target, 0, "opt inv.", properties); + log(target, "opt inv.", properties); } } From da01a39cc76664556beac50b70038f8d2b010ac1 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Mon, 6 Sep 2021 17:57:04 +0200 Subject: [PATCH 420/681] Better tracing for "compilation started". --- .../common/TruffleCompilationTask.java | 16 ++++++++ .../runtime/BackgroundCompileQueue.java | 14 ++----- .../truffle/runtime/CompilationTask.java | 40 +++++++++++++++++-- .../truffle/runtime/GraalTruffleRuntime.java | 1 + .../runtime/GraalTruffleRuntimeListener.java | 8 +++- ...GraalTruffleRuntimeListenerDispatcher.java | 5 +++ .../runtime/TraversingBlockingQueue.java | 36 +++++++++++------ .../debug/TraceCompilationListener.java | 36 ++++++++++------- 8 files changed, 114 insertions(+), 42 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilationTask.java b/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilationTask.java index db8757acfe78..cb318c15b4cb 100644 --- a/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilationTask.java +++ b/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilationTask.java @@ -52,4 +52,20 @@ default int tier() { TruffleInliningData inliningData(); boolean hasNextTier(); + + default long time() { + return 0; + } + + default double weight() { + return Double.NaN; + } + + default double rate() { + return Double.NaN; + } + + default int queueChange() { + return 0; + } } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/BackgroundCompileQueue.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/BackgroundCompileQueue.java index 9b0b779df64f..22f4206a1270 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/BackgroundCompileQueue.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/BackgroundCompileQueue.java @@ -193,17 +193,9 @@ private long nextId() { } public int getQueueSize() { - final ExecutorService threadPool = compilationExecutorService; - if (threadPool instanceof ThreadPoolExecutor) { - BlockingQueue queue = ((ThreadPoolExecutor) threadPool).getQueue(); - int count = 0; - for (Runnable runnable : queue) { - CompilationTask.ExecutorServiceWrapper wrapper = (CompilationTask.ExecutorServiceWrapper) runnable; - if (!wrapper.isCancelled() && !wrapper.compileTask.isCancelled()) { - count++; - } - } - return count; + final ThreadPoolExecutor threadPool = compilationExecutorService; + if (threadPool != null) { + return threadPool.getQueue().size(); } else { return 0; } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java index bff7c078f4af..731e66eea396 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java @@ -70,6 +70,10 @@ public void accept(CompilationTask task) { private double lastWeight; private boolean isOSR; + private double lastRate; + private long time; + private int queueChange; + private CompilationTask(BackgroundCompileQueue.Priority priority, WeakReference targetRef, Consumer action, long id) { this.priority = priority; this.targetRef = targetRef; @@ -264,9 +268,10 @@ boolean updateWeight(long currentTime) { return true; } int count = target.getCallAndLoopCount(); - double weight = rate(count, elapsed) * count; + lastRate = rate(count, elapsed); lastTime = currentTime; lastCount = count; + double weight = lastRate * lastCount; if (engineData.traversingFirstTierPriority) { lastWeight = weight; } else { @@ -290,8 +295,8 @@ boolean updateWeight(long currentTime) { } private double rate(int count, long elapsed) { - double rawRate = ((double) count - lastCount) / elapsed; - return 1.0 + (Double.isNaN(rawRate) ? 0 : rawRate); + lastRate = ((double) count - lastCount) / elapsed; + return 1.0 + (Double.isNaN(lastRate) ? 0 : lastRate); } public int targetHighestCompiledTier() { @@ -302,6 +307,35 @@ public int targetHighestCompiledTier() { return target.highestCompiledTier(); } + @Override + public long time() { + return time; + } + + @Override + public double weight() { + return lastWeight; + } + + @Override + public double rate() { + return lastRate; + } + + @Override + public int queueChange() { + return queueChange; + } + + void setTime(long time) { + this.time = time; + } + + void setQueueChange(int queueChange) { + this.queueChange = queueChange; + } + + /** * Since {@link BackgroundCompileQueue} uses a {@link java.util.concurrent.ThreadPoolExecutor} * to run compilations, and since the executor expects each {@link Callable} (in our case, the diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java index 16ed9eb4e42f..bb8407a1f096 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java @@ -782,6 +782,7 @@ private void compileImpl(TruffleDebugContext initialDebug, OptimizedCallTarget c debug = compiler.openDebugContext(optionsMap, compilation); } listeners.onCompilationStarted(callTarget, task.tier()); + listeners.onCompilationStarted(callTarget, task.tier(), task.time(), task.weight(), task.rate(), task.queueChange()); compilationStarted = true; try { compiler.doCompile(debug, compilation, optionsMap, task, listeners.isEmpty() ? null : listeners); diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java index 9de24d2bd264..bb987d1828c3 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java @@ -119,13 +119,19 @@ default void onCompilationStarted(OptimizedCallTarget target) { onCompilationStarted(target, 0); } + /** + * @deprecated Use {@link #onCompilationStarted(OptimizedCallTarget, int)} + */ + @Deprecated + default void onCompilationStarted(OptimizedCallTarget target, int tier) {} + /** * Notifies this object when compilation of {@code target} is about to start. * * @param target the call target about to be compiled * @param tier Which compilation tier is in question. */ - default void onCompilationStarted(OptimizedCallTarget target, int tier) { + default void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { } /** diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java index 17cc552d9c88..bce665f14612 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java @@ -78,6 +78,11 @@ public void onCompilationStarted(OptimizedCallTarget target, int tier) { invokeListeners((l) -> l.onCompilationStarted(target, tier)); } + @Override + public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { + invokeListeners((l) -> l.onCompilationStarted(target, tier, time, weight, rate, queueChange)); + } + @Override public void onCompilationTruffleTierFinished(OptimizedCallTarget target, TruffleInlining inliningDecision, GraphInfo graph) { invokeListeners((l) -> l.onCompilationTruffleTierFinished(target, inliningDecision, graph)); diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/TraversingBlockingQueue.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/TraversingBlockingQueue.java index 6d29f5870772..58bc083ae0c8 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/TraversingBlockingQueue.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/TraversingBlockingQueue.java @@ -79,23 +79,33 @@ private synchronized Runnable takeMax() { if (entries.isEmpty()) { return null; } - long time = System.nanoTime(); - Iterator it = entries.iterator(); Runnable max = null; - while (it.hasNext()) { - Runnable entry = it.next(); - CompilationTask task = task(entry); - // updateWeight returns false only if the task's target does not exist - if (task.isCancelled() || !task.updateWeight(time)) { - it.remove(); - continue; + long time = System.nanoTime(); + int removed = 0; + try { + Iterator it = entries.iterator(); + while (it.hasNext()) { + Runnable entry = it.next(); + CompilationTask task = task(entry); + // updateWeight returns false only if the task's target does not exist + if (task.isCancelled() || !task.updateWeight(time)) { + it.remove(); + removed--; + continue; + } + if (max == null || task.isHigherPriorityThan(task(max))) { + max = entry; + } } - if (max == null || task.isHigherPriorityThan(task(max))) { - max = entry; + // entries.remove can only return false if a sleeping thread takes the only element + return entries.remove(max) ? max : null; + } finally { + if (max != null) { + CompilationTask task = task(max); + task.setTime(System.nanoTime() - time); + task.setQueueChange(removed - 1); } } - // entries.remove can only return false if a sleeping thread takes the only element - return entries.remove(max) ? max : null; } @Override diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java index ffbcbd32bd86..05985ad4379e 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java @@ -49,7 +49,6 @@ public final class TraceCompilationListener extends AbstractGraalTruffleRuntimeListener { private final ThreadLocal currentCompilation = new ThreadLocal<>(); - private long startTime = System.nanoTime(); private TraceCompilationListener(GraalTruffleRuntime runtime) { super(runtime); @@ -59,13 +58,6 @@ public static void install(GraalTruffleRuntime runtime) { runtime.addListener(new TraceCompilationListener(runtime)); } - private static Map defaultProperties(OptimizedCallTarget target) { - Map properties = new LinkedHashMap<>(); - properties.putAll(target.getDebugProperties()); - properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); - return properties; - } - @Override public void onCompilationQueued(OptimizedCallTarget target, int tier) { if (target.engine.traceCompilationDetails) { @@ -76,7 +68,7 @@ public void onCompilationQueued(OptimizedCallTarget target, int tier) { @Override public void onCompilationDequeued(OptimizedCallTarget target, Object source, CharSequence reason, int tier) { if (target.engine.traceCompilationDetails) { - Map properties = queueProperties(target, tier, -1); + Map properties = queueProperties(target, tier, 0); properties.put("Reason", reason); log(target, "opt unqueued", properties); } @@ -93,7 +85,7 @@ private Map queueProperties(OptimizedCallTarget target, int tier queueChange >= 0 ? '+' : '-', Math.abs(queueChange), FixedPointMath.toDouble(scale))); - properties.put("Time", System.nanoTime() - startTime); + properties.put("Time", System.nanoTime()); properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); return properties; } @@ -113,9 +105,9 @@ public void onCompilationFailed(OptimizedCallTarget target, String reason, boole } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier) { + public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { if (target.engine.traceCompilationDetails) { - log(target, "opt start", queueProperties(target, tier, -1)); + log(target, "opt start", startedProperties(target, tier, time, weight, rate, queueChange)); } if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { @@ -123,6 +115,22 @@ public void onCompilationStarted(OptimizedCallTarget target, int tier) { } } + private Map startedProperties(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { + Map properties = new LinkedHashMap<>(); + properties.put("Tier", Integer.toString(tier)); // to avoid padding + properties.put("Weight", weight); + properties.put("Rate", Double.toString(rate)); + properties.put("Queue", String.format("(Size %d, Change %c%d, Scale %.2f, Time %dus)", + runtime.getCompilationQueueSize(), + queueChange >= 0 ? '+' : '-', + Math.abs(queueChange), + FixedPointMath.toDouble(runtime.compilationThresholdScale()), + time / 1000)); + properties.put("Time", System.nanoTime()); + properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); + return properties; + } + private void log(OptimizedCallTarget target, String event, Map properties) { String subject = String.format("id=%-6d %s", target.id(), target.getName()); runtime.logEvent(target, 0, event, subject, properties, null); @@ -132,7 +140,6 @@ private void log(OptimizedCallTarget target, String event, Map p public void onCompilationDeoptimized(OptimizedCallTarget target, Frame frame) { if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { Map properties = new LinkedHashMap<>(); - GraalTruffleRuntimeListener.addASTSizeProperty(target, properties); properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); log(target, "opt deopt", properties); } @@ -199,7 +206,8 @@ private static String formatSourceSection(SourceSection sourceSection) { @Override public void onCompilationInvalidated(OptimizedCallTarget target, Object source, CharSequence reason) { if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { - Map properties = defaultProperties(target); + Map properties = new LinkedHashMap<>(); + properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); properties.put("Reason", reason); log(target, "opt inv.", properties); } From 3f61edfffe18a3d133a35172e4416234b5649a9d Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Tue, 7 Sep 2021 11:18:50 +0200 Subject: [PATCH 421/681] Dealing with the deprecation. --- .../compiler/truffle/runtime/CompilationTask.java | 1 - .../truffle/runtime/GraalTruffleRuntimeListener.java | 9 +-------- .../runtime/GraalTruffleRuntimeListenerDispatcher.java | 1 + .../compiler/truffle/runtime/debug/JFRListener.java | 2 +- .../truffle/runtime/debug/StatisticsListener.java | 6 +++--- .../truffle/runtime/debug/TraceCompilationListener.java | 1 - .../truffle/test/GraalTruffleRuntimeListenerTest.java | 2 +- .../truffle/test/TruffleBoundaryExceptionsTest.java | 2 +- 8 files changed, 8 insertions(+), 16 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java index 731e66eea396..3ec41ee58993 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java @@ -335,7 +335,6 @@ void setQueueChange(int queueChange) { this.queueChange = queueChange; } - /** * Since {@link BackgroundCompileQueue} uses a {@link java.util.concurrent.ThreadPoolExecutor} * to run compilations, and since the executor expects each {@link Callable} (in our case, the diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java index bb987d1828c3..760e45f9b8c7 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java @@ -115,16 +115,9 @@ default void onCompilationDequeued(OptimizedCallTarget target, Object source, Ch * @deprecated Use {@link #onCompilationStarted(OptimizedCallTarget, int)} */ @Deprecated - default void onCompilationStarted(OptimizedCallTarget target) { - onCompilationStarted(target, 0); + default void onCompilationStarted(OptimizedCallTarget target, int tier) { } - /** - * @deprecated Use {@link #onCompilationStarted(OptimizedCallTarget, int)} - */ - @Deprecated - default void onCompilationStarted(OptimizedCallTarget target, int tier) {} - /** * Notifies this object when compilation of {@code target} is about to start. * diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java index bce665f14612..16eae36525dd 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java @@ -74,6 +74,7 @@ public void onCompilationFailed(OptimizedCallTarget target, String reason, boole } @Override + @SuppressWarnings("deprecation") public void onCompilationStarted(OptimizedCallTarget target, int tier) { invokeListeners((l) -> l.onCompilationStarted(target, tier)); } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/JFRListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/JFRListener.java index 950b6195efd8..2c82817e3b28 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/JFRListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/JFRListener.java @@ -104,7 +104,7 @@ public static boolean isInstrumented(ResolvedJavaMethod method) { } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier) { + public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { CompilationEvent event = null; if (factory != null) { event = factory.createCompilationEvent(); diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/StatisticsListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/StatisticsListener.java index bd20d827d5e9..b88c28833177 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/StatisticsListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/StatisticsListener.java @@ -167,7 +167,7 @@ public synchronized void onCompilationInvalidated(OptimizedCallTarget target, Ob } @Override - public synchronized void onCompilationStarted(OptimizedCallTarget target, int tier) { + public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { compilations++; final Times times = new Times(); compilationTimes.set(times); @@ -620,10 +620,10 @@ public void onCompilationQueued(OptimizedCallTarget target, int tier) { } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier) { + public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { StatisticsListener listener = target.engine.statisticsListener; if (listener != null) { - listener.onCompilationStarted(target, tier); + listener.onCompilationStarted(target, tier, time, weight, rate, queueChange); } } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java index 05985ad4379e..396e6cabc1dc 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java @@ -171,7 +171,6 @@ private Map compilationEndProperties(OptimizedCallTarget target, long timeCompilationFinished = System.nanoTime(); Times compilation = currentCompilation.get(); - Map properties = new LinkedHashMap<>(); properties.put("Tier", Integer.toString(tier)); // to avoid padding properties.put("Time", String.format("%4.0f(%4.0f+%-4.0f)ms", // diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java index fb13b5d17f4a..6afe468b0f5a 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java @@ -373,7 +373,7 @@ public void onCompilationDequeued(OptimizedCallTarget target, Object source, Cha } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier) { + public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { if (isImportant(target)) { waitForInitialTarget(); events.add(EventType.COMPILATION_STARTED); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java index 6307b305fdd3..bac986321e63 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java @@ -88,7 +88,7 @@ public void throwExceptionBoundary() { final int[] compilationCount = {0}; GraalTruffleRuntimeListener listener = new GraalTruffleRuntimeListener() { @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier) { + public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { compilationCount[0]++; } }; From c0d3baad11bee340c6f30ea052d5575aa9c29a04 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Tue, 7 Sep 2021 13:26:00 +0200 Subject: [PATCH 422/681] Fix compilation retry. --- .../truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java index 16eae36525dd..48c040949d77 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java @@ -169,6 +169,6 @@ public void onFailure(CompilableTruffleAST compilable, String reason, boolean ba @Override public void onCompilationRetry(CompilableTruffleAST compilable, int tier) { onCompilationQueued((OptimizedCallTarget) compilable, tier); - onCompilationStarted((OptimizedCallTarget) compilable, tier); + onCompilationStarted((OptimizedCallTarget) compilable, tier, 0, 0, 0, 0); } } From 053c0978b2b73eea62a8d822e0a916ec53794fc6 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Tue, 7 Sep 2021 14:23:32 +0200 Subject: [PATCH 423/681] Update javadoc. --- .../truffle/runtime/GraalTruffleRuntimeListener.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java index 760e45f9b8c7..7d6049454726 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java @@ -112,9 +112,13 @@ default void onCompilationDequeued(OptimizedCallTarget target, Object source, Ch } /** + * @param target the call target about to be compiled + * @param tier Which compilation tier is in question. + * * @deprecated Use {@link #onCompilationStarted(OptimizedCallTarget, int)} */ @Deprecated + @SuppressWarnings("unused") default void onCompilationStarted(OptimizedCallTarget target, int tier) { } @@ -122,8 +126,13 @@ default void onCompilationStarted(OptimizedCallTarget target, int tier) { * Notifies this object when compilation of {@code target} is about to start. * * @param target the call target about to be compiled - * @param tier Which compilation tier is in question. + * @param tier which compilation tier is in question. + * @param weight the parameter by which we choose this compilation among others form the queue. + * @param rate the dynamic component that contributes to weight. + * @param queueChange how has starting this compilation impacted the number of compilations in + * the queue. */ + @SuppressWarnings("unused") default void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { } From 2058ed7978ba0fcb11a49a065c86cc162af05152 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Tue, 7 Sep 2021 16:00:34 +0200 Subject: [PATCH 424/681] Fix test. --- .../com/oracle/truffle/api/dsl/test/examples/AOTTutorial.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/AOTTutorial.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/AOTTutorial.java index 9bf7876dbd75..dcca349a9fac 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/AOTTutorial.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/AOTTutorial.java @@ -372,7 +372,7 @@ public void testAOT() { // immediately compiled at parse time without prior execution. Value v = context.parse("AOTTestLanguage", "sample"); String beforeExecute = log.toString(); - assertTrue(beforeExecute, beforeExecute.contains("[engine] opt done sample")); + assertTrue(beforeExecute, beforeExecute.contains("[engine] opt done") && beforeExecute.contains("sample")); // we can compile the function and it is executed compiled immediately. // note that if we would use any other types than the ones used during AOT From b1ec312e9fb6d452406e4ae02b662a6015693ae0 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Fri, 24 Sep 2021 08:48:25 +0200 Subject: [PATCH 425/681] Better compilation tracing format. --- .../truffle/runtime/CompilationTask.java | 4 +- .../truffle/runtime/OptimizedCallTarget.java | 8 +- .../debug/TraceCompilationListener.java | 166 +++++++++--------- 3 files changed, 90 insertions(+), 88 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java index 3ec41ee58993..9b315d6ce8d5 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/CompilationTask.java @@ -271,7 +271,7 @@ boolean updateWeight(long currentTime) { lastRate = rate(count, elapsed); lastTime = currentTime; lastCount = count; - double weight = lastRate * lastCount; + double weight = (1 + lastRate) * lastCount; if (engineData.traversingFirstTierPriority) { lastWeight = weight; } else { @@ -296,7 +296,7 @@ boolean updateWeight(long currentTime) { private double rate(int count, long elapsed) { lastRate = ((double) count - lastCount) / elapsed; - return 1.0 + (Double.isNaN(lastRate) ? 0 : lastRate); + return (Double.isNaN(lastRate) ? 0 : lastRate); } public int targetHighestCompiledTier() { diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java index 0b1d424a8019..fc1a90521c77 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/OptimizedCallTarget.java @@ -329,7 +329,7 @@ public Class getType() { private volatile WeakReference singleCallNode = NO_CALL; volatile List blockCompilations; - private final int id; + public final int id; private static final AtomicInteger idCounter = new AtomicInteger(0); protected OptimizedCallTarget(OptimizedCallTarget sourceCallTarget, RootNode rootNode) { @@ -997,7 +997,7 @@ public final String getName() { if (result == null) { result = rootNode.toString(); if (sourceCallTarget != null) { - result += " "; + result += " "; } nameCache = result; } @@ -1687,8 +1687,4 @@ private boolean prepareForAOTImpl() { boolean isOSR() { return rootNode instanceof BaseOSRRootNode; } - - public int id() { - return id; - } } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java index 396e6cabc1dc..f1288e4330b6 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java @@ -24,9 +24,6 @@ */ package org.graalvm.compiler.truffle.runtime.debug; -import java.util.LinkedHashMap; -import java.util.Map; - import org.graalvm.compiler.truffle.common.TruffleCompilerListener.CompilationResultInfo; import org.graalvm.compiler.truffle.common.TruffleCompilerListener.GraphInfo; import org.graalvm.compiler.truffle.runtime.AbstractGraalTruffleRuntimeListener; @@ -58,47 +55,74 @@ public static void install(GraalTruffleRuntime runtime) { runtime.addListener(new TraceCompilationListener(runtime)); } + public static final String TIER_FORMAT = " Tier %d "; + private static final String QUEUE_FORMAT = "Queue: Size %4d Change %c%-2d Scale %5.2f Elapsed %4dus "; + private static final String TARGET_FORMAT = "id=%-5d %-50s "; + // @formatter:off + private static final String QUEUED_FORMAT = "opt queued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Src %s | Time %d "; + private static final String UNQUEUED_FORMAT = "opt unqueued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Src %s | Time %d "; + private static final String START_FORMAT = "opt start " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Weight %8d | Rate %.5f | " + QUEUE_FORMAT + "| Src %s | Time %d "; + private static final String DONE_FORMAT = "opt done " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Src %s | Time %d "; + private static final String FAILED_FORMAT = "opt failed " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Src %s | Time %d "; + private static final String INV_FORMAT = "opt inv " + TARGET_FORMAT + "| Reason %s | Src %s | Time %d "; + private static final String DEOPT_FORMAT = "opt deopt " + TARGET_FORMAT + "| Src %s | Time %d "; + // @formatter:on + @Override public void onCompilationQueued(OptimizedCallTarget target, int tier) { if (target.engine.traceCompilationDetails) { - log(target, "opt queued", queueProperties(target, tier, 1)); + int callAndLoopThreshold = tier == 1 ? target.engine.callAndLoopThresholdInInterpreter : target.engine.callAndLoopThresholdInFirstTier; + int scale = runtime.compilationThresholdScale(); + log(target, String.format(QUEUED_FORMAT, + target.id, + target.getName(), + tier, + target.getCallAndLoopCount(), + FixedPointMath.multiply(scale, callAndLoopThreshold), + runtime.getCompilationQueueSize(), + '+', + 1, + FixedPointMath.toDouble(scale), + 0, + formatSourceSection(target.getRootNode().getSourceSection()), + System.nanoTime())); } } @Override public void onCompilationDequeued(OptimizedCallTarget target, Object source, CharSequence reason, int tier) { if (target.engine.traceCompilationDetails) { - Map properties = queueProperties(target, tier, 0); - properties.put("Reason", reason); - log(target, "opt unqueued", properties); + int callAndLoopThreshold = tier == 1 ? target.engine.callAndLoopThresholdInInterpreter : target.engine.callAndLoopThresholdInFirstTier; + int scale = runtime.compilationThresholdScale(); + log(target, String.format(UNQUEUED_FORMAT, + target.id, + target.getName(), + tier, + target.getCallAndLoopCount(), + FixedPointMath.multiply(scale, callAndLoopThreshold), + runtime.getCompilationQueueSize(), + ' ', + 0, + FixedPointMath.toDouble(scale), + 0, + formatSourceSection(target.getRootNode().getSourceSection()), + System.nanoTime())); } } - private Map queueProperties(OptimizedCallTarget target, int tier, int queueChange) { - Map properties = new LinkedHashMap<>(); - properties.put("Tier", Integer.toString(tier)); // to avoid padding - int scale = runtime.compilationThresholdScale(); - int callAndLoopThreshold = tier == 1 ? target.engine.callAndLoopThresholdInInterpreter : target.engine.callAndLoopThresholdInFirstTier; - properties.put("CallsAndLoop/Thres", String.format("%7d/%5d", target.getCallAndLoopCount(), FixedPointMath.multiply(scale, callAndLoopThreshold))); - properties.put("Queue", String.format("(Size %d, Change %c%d, Scale %.2f)", - runtime.getCompilationQueueSize(), - queueChange >= 0 ? '+' : '-', - Math.abs(queueChange), - FixedPointMath.toDouble(scale))); - properties.put("Time", System.nanoTime()); - properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); - return properties; - } - @Override public void onCompilationFailed(OptimizedCallTarget target, String reason, boolean bailout, boolean permanentBailout, int tier) { if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { if (!isPermanentFailure(bailout, permanentBailout)) { onCompilationDequeued(target, null, "Non permanent bailout: " + reason, tier); } else { - Map properties = compilationEndProperties(target, null, null, null, tier); - properties.put("Reason", reason); - log(target, "opt failed", properties); + log(target, String.format(FAILED_FORMAT, + target.id, + target.getName(), + tier, + compilationTime(), + formatSourceSection(target.getRootNode().getSourceSection()), + System.nanoTime())); } currentCompilation.set(null); } @@ -107,7 +131,19 @@ public void onCompilationFailed(OptimizedCallTarget target, String reason, boole @Override public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { if (target.engine.traceCompilationDetails) { - log(target, "opt start", startedProperties(target, tier, time, weight, rate, queueChange)); + log(target, String.format(START_FORMAT, + target.id, + target.getName(), + tier, + (int) weight, + rate, + runtime.getCompilationQueueSize(), + queueChange >= 0 ? '+' : '-', + Math.abs(queueChange), + FixedPointMath.toDouble(runtime.compilationThresholdScale()), + time / 1000, + formatSourceSection(target.getRootNode().getSourceSection()), + System.nanoTime())); } if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { @@ -115,33 +151,18 @@ public void onCompilationStarted(OptimizedCallTarget target, int tier, long time } } - private Map startedProperties(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { - Map properties = new LinkedHashMap<>(); - properties.put("Tier", Integer.toString(tier)); // to avoid padding - properties.put("Weight", weight); - properties.put("Rate", Double.toString(rate)); - properties.put("Queue", String.format("(Size %d, Change %c%d, Scale %.2f, Time %dus)", - runtime.getCompilationQueueSize(), - queueChange >= 0 ? '+' : '-', - Math.abs(queueChange), - FixedPointMath.toDouble(runtime.compilationThresholdScale()), - time / 1000)); - properties.put("Time", System.nanoTime()); - properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); - return properties; - } - - private void log(OptimizedCallTarget target, String event, Map properties) { - String subject = String.format("id=%-6d %s", target.id(), target.getName()); - runtime.logEvent(target, 0, event, subject, properties, null); + private void log(OptimizedCallTarget target, String message) { + runtime.log(target, message); } @Override public void onCompilationDeoptimized(OptimizedCallTarget target, Frame frame) { if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { - Map properties = new LinkedHashMap<>(); - properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); - log(target, "opt deopt", properties); + log(target, String.format(DEOPT_FORMAT, + target.id, + target.getName(), + formatSourceSection(target.getRootNode().getSourceSection()), + System.nanoTime())); } } @@ -159,40 +180,23 @@ public void onCompilationSuccess(OptimizedCallTarget target, TruffleInlining inl if (!target.engine.traceCompilation && !target.engine.traceCompilationDetails) { return; } - - Map properties = compilationEndProperties(target, inliningDecision, graph, result, tier); - - log(target, "opt done", properties); - + log(target, String.format(DONE_FORMAT, + target.id, + target.getName(), + tier, + compilationTime(), + formatSourceSection(target.getRootNode().getSourceSection()), + System.nanoTime())); currentCompilation.set(null); } - private Map compilationEndProperties(OptimizedCallTarget target, TruffleInlining inliningDecision, GraphInfo graph, CompilationResultInfo result, int tier) { + private String compilationTime() { long timeCompilationFinished = System.nanoTime(); Times compilation = currentCompilation.get(); - - Map properties = new LinkedHashMap<>(); - properties.put("Tier", Integer.toString(tier)); // to avoid padding - properties.put("Time", String.format("%4.0f(%4.0f+%-4.0f)ms", // + return String.format("%4.0f(%4.0f+%-4.0f)ms", // (timeCompilationFinished - compilation.timeCompilationStarted) / 1e6, // (compilation.timePartialEvaluationFinished - compilation.timeCompilationStarted) / 1e6, // - (timeCompilationFinished - compilation.timePartialEvaluationFinished) / 1e6)); - if (inliningDecision != null) { - int inlinedCalls = inliningDecision.countInlinedCalls(); - int dispatchedCalls = inliningDecision.countCalls() - inlinedCalls; - properties.put("Inlined", String.format("%3dY %3dN", inlinedCalls, dispatchedCalls)); - } - if (graph != null) { - properties.put("IR", String.format("%5d/%5d", compilation.nodeCountPartialEval, graph.getNodeCount())); - } - if (result != null) { - properties.put("CodeSize", result.getTargetCodeSize()); - } - if (target.getCodeAddress() != 0) { - properties.put("Addr", "0x" + Long.toHexString(target.getCodeAddress())); - } - properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); - return properties; + (timeCompilationFinished - compilation.timePartialEvaluationFinished) / 1e6); } private static String formatSourceSection(SourceSection sourceSection) { @@ -205,10 +209,12 @@ private static String formatSourceSection(SourceSection sourceSection) { @Override public void onCompilationInvalidated(OptimizedCallTarget target, Object source, CharSequence reason) { if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { - Map properties = new LinkedHashMap<>(); - properties.put("Src", formatSourceSection(target.getRootNode().getSourceSection())); - properties.put("Reason", reason); - log(target, "opt inv.", properties); + log(target, String.format(INV_FORMAT, + target.id, + target.getName(), + reason, + formatSourceSection(target.getRootNode().getSourceSection()), + System.nanoTime())); } } From 54416e702de3204618b863d69204950dda353c4f Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Tue, 28 Sep 2021 09:44:19 +0200 Subject: [PATCH 426/681] Print reason where it's needed. --- .../truffle/runtime/debug/TraceCompilationListener.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java index f1288e4330b6..54b39e089edd 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java @@ -60,10 +60,10 @@ public static void install(GraalTruffleRuntime runtime) { private static final String TARGET_FORMAT = "id=%-5d %-50s "; // @formatter:off private static final String QUEUED_FORMAT = "opt queued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Src %s | Time %d "; - private static final String UNQUEUED_FORMAT = "opt unqueued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Src %s | Time %d "; + private static final String UNQUEUED_FORMAT = "opt unqueued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Reason: %s | Src %s | Time %d "; private static final String START_FORMAT = "opt start " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Weight %8d | Rate %.5f | " + QUEUE_FORMAT + "| Src %s | Time %d "; private static final String DONE_FORMAT = "opt done " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Src %s | Time %d "; - private static final String FAILED_FORMAT = "opt failed " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Src %s | Time %d "; + private static final String FAILED_FORMAT = "opt failed " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Reason: %s | Src %s | Time %d "; private static final String INV_FORMAT = "opt inv " + TARGET_FORMAT + "| Reason %s | Src %s | Time %d "; private static final String DEOPT_FORMAT = "opt deopt " + TARGET_FORMAT + "| Src %s | Time %d "; // @formatter:on @@ -105,6 +105,7 @@ public void onCompilationDequeued(OptimizedCallTarget target, Object source, Cha 0, FixedPointMath.toDouble(scale), 0, + reason, formatSourceSection(target.getRootNode().getSourceSection()), System.nanoTime())); } @@ -121,6 +122,7 @@ public void onCompilationFailed(OptimizedCallTarget target, String reason, boole target.getName(), tier, compilationTime(), + reason, formatSourceSection(target.getRootNode().getSourceSection()), System.nanoTime())); } From 11636bce94d608ecdbe36ea085edb199e2963ac5 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Fri, 24 Sep 2021 08:50:50 +0200 Subject: [PATCH 427/681] Remove call to deprecated method. --- .../graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java | 1 - .../compiler/truffle/runtime/GraalTruffleRuntimeListener.java | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java index bb8407a1f096..7b45a85f9c0e 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java @@ -781,7 +781,6 @@ private void compileImpl(TruffleDebugContext initialDebug, OptimizedCallTarget c if (debug == null) { debug = compiler.openDebugContext(optionsMap, compilation); } - listeners.onCompilationStarted(callTarget, task.tier()); listeners.onCompilationStarted(callTarget, task.tier(), task.time(), task.weight(), task.rate(), task.queueChange()); compilationStarted = true; try { diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java index 7d6049454726..7345a3763da0 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java @@ -132,8 +132,9 @@ default void onCompilationStarted(OptimizedCallTarget target, int tier) { * @param queueChange how has starting this compilation impacted the number of compilations in * the queue. */ - @SuppressWarnings("unused") + @SuppressWarnings({"unused", "deprecated"}) default void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { + onCompilationStarted(target, tier); } /** From 119cf3eca7aec33141b16f85289a0546de7c1ee4 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Wed, 29 Sep 2021 13:43:13 +0200 Subject: [PATCH 428/681] Update docs. --- truffle/docs/Optimizing.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/truffle/docs/Optimizing.md b/truffle/docs/Optimizing.md index e8a86116117a..071700057d5d 100644 --- a/truffle/docs/Optimizing.md +++ b/truffle/docs/Optimizing.md @@ -49,16 +49,16 @@ The `--engine.TraceCompilation` command prints a line each time a method is comp The `--engine.TraceCompilationDetails` command prints a line when compilation is queued, started, or completed: ```shell -[engine] opt queued BinaryConstraint.output |AST 19|Tier 2|Calls/Thres 1000/ 3|CallsAndLoop/Thres 1000/ 1000|Src octane-deltablue.js:416|QueueSize 0|Time 1725905750 -[engine] opt start BinaryConstraint.output |AST 19|Tier 2|Calls/Thres 1000/ 3|CallsAndLoop/Thres 1000/ 1000|Src octane-deltablue.js:416|QueueSize 0|Time 1734518023 -[engine] opt queued OrderedCollection.size |AST 10|Tier 2|Calls/Thres 1000/ 3|CallsAndLoop/Thres 1000/ 1000|Src octane-deltablue.js:71|QueueSize 0|Time 1743713143 -[engine] opt start OrderedCollection.size |AST 10|Tier 2|Calls/Thres 1000/ 3|CallsAndLoop/Thres 1000/ 1000|Src octane-deltablue.js:71|QueueSize 0|Time 1744034479 -[engine] opt queued Planner.addConstraintsConsumingTo |AST 51|Tier 2|Calls/Thres 368/ 3|CallsAndLoop/Thres 1001/ 1000|Src octane-deltablue.js:743|QueueSize 1|Time 1791073465 -... more queues ... -[engine] opt queued BinaryConstraint.markInputs |AST 13|Tier 2|Calls/Thres 1000/ 3|CallsAndLoop/Thres 1000/ 1000|Src octane-deltablue.js:402|QueueSize 27|Time 2813136318 -[engine] opt done BinaryConstraint.output |AST 19|Tier 2|Time 1146( 851+295 )ms|Inlined 0Y 0N|IR 106/ 167|CodeSize 634|Addr 0x7f600586f990|Src octane-deltablue.js:416 -[engine] opt start Planner.removePropagateFrom |AST 149|Tier 2|Calls/Thres 8/ 3|CallsAndLoop/Thres 2052/ 1000|Src octane-deltablue.js:717|QueueSize 26|Time 2903518862 -[engine] opt queued UnaryConstraint.output |AST 7|Tier 2|Calls/Thres 1000/ 3|CallsAndLoop/Thres 1000/ 1000|Src octane-deltablue.js:255|QueueSize 27|Time 3175165217 +[engine] opt queued id=237 BinaryConstraint.output | Tier 1 | Count/Thres 25/ 25 | Queue: Size 1 Change +1 Scale 0.06 Elapsed 0us | Src octane-deltablue.js:416 | Time 317044280158387 +[engine] opt start id=237 BinaryConstraint.output | Tier 1 | Weight 25 | Rate 0.00000 | Queue: Size 0 Change +0 Scale 0.06 Elapsed 0us | Src octane-deltablue.js:416 | Time 317044278139824 +[engine] opt queued id=239 OrderedCollection.size | Tier 1 | Count/Thres 25/ 25 | Queue: Size 1 Change +1 Scale 0.06 Elapsed 0us | Src octane-deltablue.js:71 | Time 317044313989575 +[engine] opt queued id=52 Array.prototype.push | Tier 1 | Count/Thres 25/ 50 | Queue: Size 2 Change +1 Scale 0.13 Elapsed 0us | Src :1 | Time 317044336408392 +[engine] opt start id=239 OrderedCollection.size | Tier 1 | Weight 88875 | Rate 0.00000 | Queue: Size 6 Change -1 Scale 0.31 Elapsed 328us | Src octane-deltablue.js:71 | Time 317045054478062 +... more log ... +[engine] opt start id=237 BinaryConstraint.output | Tier 2 | Weight 256510 | Rate 0.00007 | Queue: Size 21 Change -1 Scale 1.00 Elapsed 17us | Src octane-deltablue.js:416 | Time 317056014011223 +[engine] opt done id=293 change | Tier 1 | Elapsed 271( 186+86 )ms | Src octane-deltablue.js:867 | Time 317056063627727 +[engine] opt start id=271 Plan.size | Tier 2 | Weight 233921 | Rate 0.00008 | Queue: Size 20 Change -1 Scale 1.00 Elapsed 26us | Src octane-deltablue.js:770 | Time 317056067292754 +[engine] opt done id=237 BinaryConstraint.output | Tier 2 | Elapsed 140( 124+17 )ms | Src octane-deltablue.js:416 | Time 317056154362876 ``` The `--engine.TraceCompilationAST` command prints the Truffle AST for each compilation: From efe16b5373dfc6a2e303d3fae3f35571514772f0 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Fri, 24 Sep 2021 09:08:59 +0200 Subject: [PATCH 429/681] Pass compilation task to listeners. --- .../hotspot/libgraal/TruffleFromLibGraal.java | 2 +- .../truffle/common/TruffleCompilerListener.java | 7 ++++--- .../libgraal/HSTruffleCompilerListener.java | 6 ++++-- .../truffle/compiler/TruffleCompilerImpl.java | 2 +- .../libgraal/TruffleFromLibGraalEntryPoints.java | 4 ++-- .../truffle/runtime/GraalTruffleRuntime.java | 2 +- .../runtime/GraalTruffleRuntimeListener.java | 5 +++-- .../GraalTruffleRuntimeListenerDispatcher.java | 11 ++++++----- .../truffle/runtime/debug/JFRListener.java | 3 ++- .../truffle/runtime/debug/StatisticsListener.java | 9 +++++---- .../runtime/debug/TraceCompilationListener.java | 15 ++++++++------- .../test/GraalTruffleRuntimeListenerTest.java | 3 ++- .../test/TruffleBoundaryExceptionsTest.java | 3 ++- .../test/libgraal/JNIExceptionWrapperTest.java | 4 ---- .../IsolatedTruffleCompilerEventForwarder.java | 8 ++++---- 15 files changed, 45 insertions(+), 39 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.common.hotspot.libgraal/src/org/graalvm/compiler/truffle/common/hotspot/libgraal/TruffleFromLibGraal.java b/compiler/src/org.graalvm.compiler.truffle.common.hotspot.libgraal/src/org/graalvm/compiler/truffle/common/hotspot/libgraal/TruffleFromLibGraal.java index 27676762aa98..40a663c7bedd 100644 --- a/compiler/src/org.graalvm.compiler.truffle.common.hotspot.libgraal/src/org/graalvm/compiler/truffle/common/hotspot/libgraal/TruffleFromLibGraal.java +++ b/compiler/src/org.graalvm.compiler.truffle.common.hotspot.libgraal/src/org/graalvm/compiler/truffle/common/hotspot/libgraal/TruffleFromLibGraal.java @@ -112,7 +112,7 @@ enum Id implements FromLibGraalId { Log(void.class, Object.class, String.class, Object.class, String.class), OnCodeInstallation(void.class, Object.class, Object.class, long.class), OnCompilationFailed(void.class, Object.class, Supplier.class, boolean.class, boolean.class, boolean.class, boolean.class), - OnCompilationRetry(void.class, Object.class, Object.class, int.class), + OnCompilationRetry(void.class, Object.class, Object.class, Object.class), OnFailure(void.class, Object.class, Object.class, String.class, boolean.class, boolean.class, int.class), OnGraalTierFinished(void.class, Object.class, Object.class, long.class), OnSuccess(void.class, Object.class, Object.class, Object.class, long.class, long.class, int.class), diff --git a/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilerListener.java b/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilerListener.java index 0f69111afa87..0b839e0900b7 100644 --- a/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilerListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilerListener.java @@ -172,8 +172,8 @@ default void onFailure(CompilableTruffleAST compilable, String reason, boolean b * @deprecated use {@link #onCompilationRetry(CompilableTruffleAST, int)} */ @Deprecated - default void onCompilationRetry(CompilableTruffleAST compilable) { - onCompilationRetry(compilable, 0); + @SuppressWarnings("unused") + default void onCompilationRetry(CompilableTruffleAST compilable, int tier) { } /** @@ -183,6 +183,7 @@ default void onCompilationRetry(CompilableTruffleAST compilable) { * @param compilable the Truffle AST which is going to be re-compiled. * @param tier Which compilation tier is in question. */ - default void onCompilationRetry(CompilableTruffleAST compilable, int tier) { + default void onCompilationRetry(CompilableTruffleAST compilable, TruffleCompilationTask task) { + onCompilationRetry(compilable, task.tier()); } } diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HSTruffleCompilerListener.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HSTruffleCompilerListener.java index f30d5d68afb6..b98f72a5a5bf 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HSTruffleCompilerListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HSTruffleCompilerListener.java @@ -39,6 +39,7 @@ import java.io.Closeable; import org.graalvm.compiler.truffle.common.CompilableTruffleAST; +import org.graalvm.compiler.truffle.common.TruffleCompilationTask; import org.graalvm.compiler.truffle.common.TruffleCompilerListener; import org.graalvm.compiler.truffle.common.TruffleInliningData; import org.graalvm.compiler.truffle.common.hotspot.libgraal.TruffleFromLibGraal; @@ -102,10 +103,11 @@ public void onFailure(CompilableTruffleAST compilable, String serializedExceptio @TruffleFromLibGraal(OnCompilationRetry) @Override - public void onCompilationRetry(CompilableTruffleAST compilable, int tier) { + public void onCompilationRetry(CompilableTruffleAST compilable, TruffleCompilationTask task) { JObject hsCompilable = ((HSCompilableTruffleAST) compilable).getHandle(); + JObject hsTask = ((HSTruffleCompilationTask) task).getHandle(); JNIEnv env = JNIMethodScope.env(); - callOnCompilationRetry(env, getHandle(), hsCompilable, tier); + callOnCompilationRetry(env, getHandle(), hsCompilable, hsTask); } private static final class LibGraalObjectHandleScope implements Closeable { diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilerImpl.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilerImpl.java index 0175d6e8ae39..048d4defa0a4 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilerImpl.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilerImpl.java @@ -698,7 +698,7 @@ protected ExceptionAction lookupAction(OptionValues compilerOptions, Throwable c @Override protected DebugContext createRetryDebugContext(DebugContext initialDebug, OptionValues compilerOptions, PrintStream logStream) { - listener.onCompilationRetry(compilable, task.tier()); + listener.onCompilationRetry(compilable, task); return createDebugContext(compilerOptions, compilationId, compilable, logStream); } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/TruffleFromLibGraalEntryPoints.java b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/TruffleFromLibGraalEntryPoints.java index 1793f52afb19..624b75821f95 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/TruffleFromLibGraalEntryPoints.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/TruffleFromLibGraalEntryPoints.java @@ -383,8 +383,8 @@ static void onFailure(Object listener, Object compilable, String reason, boolean } @TruffleFromLibGraal(OnCompilationRetry) - static void onCompilationRetry(Object listener, Object compilable, int tier) { - ((TruffleCompilerListener) listener).onCompilationRetry((CompilableTruffleAST) compilable, tier); + static void onCompilationRetry(Object listener, Object compilable, Object task) { + ((TruffleCompilerListener) listener).onCompilationRetry((CompilableTruffleAST) compilable, (TruffleCompilationTask) task); } @TruffleFromLibGraal(OnGraalTierFinished) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java index 7b45a85f9c0e..521c63c1b563 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java @@ -781,7 +781,7 @@ private void compileImpl(TruffleDebugContext initialDebug, OptimizedCallTarget c if (debug == null) { debug = compiler.openDebugContext(optionsMap, compilation); } - listeners.onCompilationStarted(callTarget, task.tier(), task.time(), task.weight(), task.rate(), task.queueChange()); + listeners.onCompilationStarted(callTarget, task); compilationStarted = true; try { compiler.doCompile(debug, compilation, optionsMap, task, listeners.isEmpty() ? null : listeners); diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java index 7345a3763da0..1aad23ad9cac 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java @@ -26,6 +26,7 @@ import java.util.Map; +import org.graalvm.compiler.truffle.common.TruffleCompilationTask; import org.graalvm.compiler.truffle.common.TruffleCompilerListener.CompilationResultInfo; import org.graalvm.compiler.truffle.common.TruffleCompilerListener.GraphInfo; @@ -133,8 +134,8 @@ default void onCompilationStarted(OptimizedCallTarget target, int tier) { * the queue. */ @SuppressWarnings({"unused", "deprecated"}) - default void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { - onCompilationStarted(target, tier); + default void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) { + onCompilationStarted(target, task.tier()); } /** diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java index 48c040949d77..b3e341250f1b 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java @@ -28,6 +28,7 @@ import java.util.function.Consumer; import org.graalvm.compiler.truffle.common.CompilableTruffleAST; +import org.graalvm.compiler.truffle.common.TruffleCompilationTask; import org.graalvm.compiler.truffle.common.TruffleCompilerListener; import org.graalvm.compiler.truffle.common.TruffleInliningData; @@ -80,8 +81,8 @@ public void onCompilationStarted(OptimizedCallTarget target, int tier) { } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { - invokeListeners((l) -> l.onCompilationStarted(target, tier, time, weight, rate, queueChange)); + public void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) { + invokeListeners((l) -> l.onCompilationStarted(target, task)); } @Override @@ -167,8 +168,8 @@ public void onFailure(CompilableTruffleAST compilable, String reason, boolean ba } @Override - public void onCompilationRetry(CompilableTruffleAST compilable, int tier) { - onCompilationQueued((OptimizedCallTarget) compilable, tier); - onCompilationStarted((OptimizedCallTarget) compilable, tier, 0, 0, 0, 0); + public void onCompilationRetry(CompilableTruffleAST compilable, TruffleCompilationTask task) { + onCompilationQueued((OptimizedCallTarget) compilable, task.tier()); + onCompilationStarted((OptimizedCallTarget) compilable, (CompilationTask) task); } } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/JFRListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/JFRListener.java index 2c82817e3b28..8b59a10e1b81 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/JFRListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/JFRListener.java @@ -27,6 +27,7 @@ import java.util.Iterator; import java.util.concurrent.atomic.AtomicLong; +import org.graalvm.compiler.truffle.common.TruffleCompilationTask; import org.graalvm.compiler.truffle.common.TruffleCompilerListener.CompilationResultInfo; import org.graalvm.compiler.truffle.common.TruffleCompilerListener.GraphInfo; import org.graalvm.compiler.truffle.jfr.CompilationEvent; @@ -104,7 +105,7 @@ public static boolean isInstrumented(ResolvedJavaMethod method) { } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { + public void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) { CompilationEvent event = null; if (factory != null) { event = factory.createCompilationEvent(); diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/StatisticsListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/StatisticsListener.java index b88c28833177..945df1805c77 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/StatisticsListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/StatisticsListener.java @@ -38,8 +38,8 @@ import java.util.function.Function; import java.util.logging.Level; -import com.oracle.truffle.api.nodes.NodeVisitor; import org.graalvm.compiler.truffle.common.CompilableTruffleAST; +import org.graalvm.compiler.truffle.common.TruffleCompilationTask; import org.graalvm.compiler.truffle.common.TruffleCompilerListener.CompilationResultInfo; import org.graalvm.compiler.truffle.common.TruffleCompilerListener.GraphInfo; import org.graalvm.compiler.truffle.runtime.AbstractGraalTruffleRuntimeListener; @@ -55,6 +55,7 @@ import com.oracle.truffle.api.nodes.LoopNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeVisitor; public final class StatisticsListener extends AbstractGraalTruffleRuntimeListener { @@ -167,7 +168,7 @@ public synchronized void onCompilationInvalidated(OptimizedCallTarget target, Ob } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { + public void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) { compilations++; final Times times = new Times(); compilationTimes.set(times); @@ -620,10 +621,10 @@ public void onCompilationQueued(OptimizedCallTarget target, int tier) { } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { + public void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) { StatisticsListener listener = target.engine.statisticsListener; if (listener != null) { - listener.onCompilationStarted(target, tier, time, weight, rate, queueChange); + listener.onCompilationStarted(target, task); } } diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java index 54b39e089edd..a824dba02d7e 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.truffle.runtime.debug; +import org.graalvm.compiler.truffle.common.TruffleCompilationTask; import org.graalvm.compiler.truffle.common.TruffleCompilerListener.CompilationResultInfo; import org.graalvm.compiler.truffle.common.TruffleCompilerListener.GraphInfo; import org.graalvm.compiler.truffle.runtime.AbstractGraalTruffleRuntimeListener; @@ -131,19 +132,19 @@ public void onCompilationFailed(OptimizedCallTarget target, String reason, boole } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { + public void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) { if (target.engine.traceCompilationDetails) { log(target, String.format(START_FORMAT, target.id, target.getName(), - tier, - (int) weight, - rate, + task.tier(), + (int) task.weight(), + task.rate(), runtime.getCompilationQueueSize(), - queueChange >= 0 ? '+' : '-', - Math.abs(queueChange), + task.queueChange() >= 0 ? '+' : '-', + Math.abs(task.queueChange()), FixedPointMath.toDouble(runtime.compilationThresholdScale()), - time / 1000, + task.time() / 1000, formatSourceSection(target.getRootNode().getSourceSection()), System.nanoTime())); } diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java index 6afe468b0f5a..cbbce3f0a329 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/GraalTruffleRuntimeListenerTest.java @@ -34,6 +34,7 @@ import java.util.Collections; import java.util.List; +import org.graalvm.compiler.truffle.common.TruffleCompilationTask; import org.graalvm.compiler.truffle.common.TruffleCompilerListener; import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntimeListener; @@ -373,7 +374,7 @@ public void onCompilationDequeued(OptimizedCallTarget target, Object source, Cha } @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { + public void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) { if (isImportant(target)) { waitForInitialTarget(); events.add(EventType.COMPILATION_STARTED); diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java index bac986321e63..f8737f74a231 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/TruffleBoundaryExceptionsTest.java @@ -28,6 +28,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import org.graalvm.compiler.truffle.common.TruffleCompilationTask; import org.graalvm.compiler.truffle.options.PolyglotCompilerOptions; import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntimeListener; @@ -88,7 +89,7 @@ public void throwExceptionBoundary() { final int[] compilationCount = {0}; GraalTruffleRuntimeListener listener = new GraalTruffleRuntimeListener() { @Override - public void onCompilationStarted(OptimizedCallTarget target, int tier, long time, double weight, double rate, int queueChange) { + public void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) { compilationCount[0]++; } }; diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/libgraal/JNIExceptionWrapperTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/libgraal/JNIExceptionWrapperTest.java index 3b12a9715dd7..40bba5eecd1d 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/libgraal/JNIExceptionWrapperTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/libgraal/JNIExceptionWrapperTest.java @@ -139,10 +139,6 @@ public void onSuccess(CompilableTruffleAST compilable, TruffleInliningData inlin @Override public void onFailure(CompilableTruffleAST compilable, String reason, boolean bailout, boolean permanentBailout, int tier) { } - - @Override - public void onCompilationRetry(CompilableTruffleAST compilable, int tier) { - } } private static class TestTruffleCompilationTask implements TruffleCompilationTask { diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java index ad5e1e046153..464c1f797cef 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java @@ -85,8 +85,8 @@ public void onFailure(CompilableTruffleAST compilable, String reason, boolean ba } @Override - public void onCompilationRetry(CompilableTruffleAST compilable, int tier) { - onCompilationRetry0(IsolatedCompileContext.get().getClient(), contextHandle, tier); + public void onCompilationRetry(CompilableTruffleAST compilable, TruffleCompilationTask task) { + onCompilationRetry0(IsolatedCompileContext.get().getClient(), contextHandle, IsolatedCompileClient.get().hand(task)); } @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) @@ -124,9 +124,9 @@ private static void onFailure0(@SuppressWarnings("unused") ClientIsolateThread c @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) - private static void onCompilationRetry0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle contextHandle, int tier) { + private static void onCompilationRetry0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle contextHandle, @SuppressWarnings("unused") ClientHandle task) { IsolatedEventContext context = IsolatedCompileClient.get().unhand(contextHandle); - context.listener.onCompilationRetry(context.compilable, tier); + context.listener.onCompilationRetry(context.compilable, context.task); } } From 6c9968d9b49ebb2e62cd1ef20cce1debbbf79c28 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Thu, 30 Sep 2021 14:41:33 +0200 Subject: [PATCH 430/681] Fix libgraal bridge. --- .../compiler/hotspot/libgraal/HSTruffleCompilerListener.java | 3 ++- .../compiler/truffle/compiler/TruffleCompilerImpl.java | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HSTruffleCompilerListener.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HSTruffleCompilerListener.java index b98f72a5a5bf..a61240580a9e 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HSTruffleCompilerListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HSTruffleCompilerListener.java @@ -43,6 +43,7 @@ import org.graalvm.compiler.truffle.common.TruffleCompilerListener; import org.graalvm.compiler.truffle.common.TruffleInliningData; import org.graalvm.compiler.truffle.common.hotspot.libgraal.TruffleFromLibGraal; +import org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl; import org.graalvm.nativebridge.jni.HSObject; import org.graalvm.nativebridge.jni.JNI.JNIEnv; import org.graalvm.nativebridge.jni.JNI.JObject; @@ -105,7 +106,7 @@ public void onFailure(CompilableTruffleAST compilable, String serializedExceptio @Override public void onCompilationRetry(CompilableTruffleAST compilable, TruffleCompilationTask task) { JObject hsCompilable = ((HSCompilableTruffleAST) compilable).getHandle(); - JObject hsTask = ((HSTruffleCompilationTask) task).getHandle(); + JObject hsTask = ((HSTruffleCompilationTask) ((TruffleCompilerImpl.CancellableTruffleCompilationTask) task).getDelegate()).getHandle(); JNIEnv env = JNIMethodScope.env(); callOnCompilationRetry(env, getHandle(), hsCompilable, hsTask); } diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilerImpl.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilerImpl.java index 048d4defa0a4..e0a06e084367 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilerImpl.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilerImpl.java @@ -947,6 +947,10 @@ public boolean hasNextTier() { public String toString() { return delegate.toString(); } + + public TruffleCompilationTask getDelegate() { + return delegate; + } } private static final class TTYToPolyglotLoggerBridge implements Consumer { From 93cb5095bbcffb896d552d40fb9dd735517ad358 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Thu, 30 Sep 2021 14:54:29 +0200 Subject: [PATCH 431/681] Cleanup and checkstyle. --- .../truffle/common/TruffleCompilerListener.java | 2 +- .../runtime/debug/TraceCompilationListener.java | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilerListener.java b/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilerListener.java index 0b839e0900b7..65e4d194cd3e 100644 --- a/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilerListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.common/src/org/graalvm/compiler/truffle/common/TruffleCompilerListener.java @@ -181,7 +181,7 @@ default void onCompilationRetry(CompilableTruffleAST compilable, int tier) { * compilation problem. * * @param compilable the Truffle AST which is going to be re-compiled. - * @param tier Which compilation tier is in question. + * @param task Which compilation task is in question. */ default void onCompilationRetry(CompilableTruffleAST compilable, TruffleCompilationTask task) { onCompilationRetry(compilable, task.tier()); diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java index a824dba02d7e..633127f71d48 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java @@ -60,13 +60,13 @@ public static void install(GraalTruffleRuntime runtime) { private static final String QUEUE_FORMAT = "Queue: Size %4d Change %c%-2d Scale %5.2f Elapsed %4dus "; private static final String TARGET_FORMAT = "id=%-5d %-50s "; // @formatter:off - private static final String QUEUED_FORMAT = "opt queued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Src %s | Time %d "; - private static final String UNQUEUED_FORMAT = "opt unqueued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Reason: %s | Src %s | Time %d "; - private static final String START_FORMAT = "opt start " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Weight %8d | Rate %.5f | " + QUEUE_FORMAT + "| Src %s | Time %d "; - private static final String DONE_FORMAT = "opt done " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Src %s | Time %d "; - private static final String FAILED_FORMAT = "opt failed " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Reason: %s | Src %s | Time %d "; - private static final String INV_FORMAT = "opt inv " + TARGET_FORMAT + "| Reason %s | Src %s | Time %d "; - private static final String DEOPT_FORMAT = "opt deopt " + TARGET_FORMAT + "| Src %s | Time %d "; + private static final String QUEUED_FORMAT = "opt queued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Src %s | Time %d"; + private static final String UNQUEUED_FORMAT = "opt unqueued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Reason: %s | Src %s | Time %d"; + private static final String START_FORMAT = "opt start " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Weight %8d | Rate %.5f | " + QUEUE_FORMAT + "| Src %s | Time %d"; + private static final String DONE_FORMAT = "opt done " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Src %s | Time %d"; + private static final String FAILED_FORMAT = "opt failed " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Reason: %s | Src %s | Time %d"; + private static final String INV_FORMAT = "opt inv " + TARGET_FORMAT + "| Reason %s | Src %s | Time %d"; + private static final String DEOPT_FORMAT = "opt deopt " + TARGET_FORMAT + "| Src %s | Time %d"; // @formatter:on @Override From c90fd63fc9ec15b1f231afd8cb9b0b82cbd7dde6 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Tue, 12 Oct 2021 11:14:37 +0200 Subject: [PATCH 432/681] Don't differentiate between explicit and implicit relocation addend. On a given a relocation addend will be either explicit or implicit. --- .../objectfile/BasicProgbitsSectionImpl.java | 14 +-- .../src/com/oracle/objectfile/ObjectFile.java | 17 +--- .../oracle/objectfile/StringSectionImpl.java | 6 +- .../com/oracle/objectfile/elf/ELFMachine.java | 57 +---------- .../oracle/objectfile/elf/ELFObjectFile.java | 44 +++++---- .../objectfile/elf/ELFProgbitsSection.java | 4 +- .../objectfile/elf/ELFRelocationSection.java | 21 +++- .../objectfile/elf/ELFUserDefinedSection.java | 35 ++++--- .../elf/dwarf/DwarfSectionImpl.java | 4 +- .../objectfile/macho/MachOObjectFile.java | 2 +- .../objectfile/macho/MachORegularSection.java | 4 +- .../macho/MachORelocationElement.java | 96 +++++++++---------- .../macho/MachOUserDefinedSection.java | 31 +++--- .../objectfile/pecoff/PECoffMachine.java | 47 +-------- .../objectfile/pecoff/PECoffObjectFile.java | 8 +- .../pecoff/PECoffProgbitsSection.java | 6 +- .../pecoff/PECoffRelocationTable.java | 25 +---- .../pecoff/PECoffUserDefinedSection.java | 50 +++------- .../objectfile/pecoff/cv/CVLineRecord.java | 4 +- .../pecoff/cv/CVSymbolSubrecord.java | 4 +- .../code/aarch64/AArch64HostedPatcher.java | 12 +-- .../oracle/svm/hosted/image/NativeImage.java | 19 ++-- .../svm/hosted/image/RelocatableBuffer.java | 22 ++--- 23 files changed, 198 insertions(+), 334 deletions(-) diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/BasicProgbitsSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/BasicProgbitsSectionImpl.java index f0269d2e1447..b74d2177a943 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/BasicProgbitsSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/BasicProgbitsSectionImpl.java @@ -113,21 +113,21 @@ public List
    getElements() { } @Override - public void markRelocationSite(int offset, RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { - ((RelocatableSectionImpl) getElement()).markRelocationSite(offset, ByteBuffer.wrap(getContent()).order(getOwner().getByteOrder()), k, symbolName, useImplicitAddend, - explicitAddend); + public void markRelocationSite(int offset, RelocationKind k, String symbolName, long addend) { + ((RelocatableSectionImpl) getElement()).markRelocationSite(offset, ByteBuffer.wrap(getContent()).order(getOwner().getByteOrder()), k, symbolName, + addend); } @Override - public final void markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { + public final void markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, String symbolName, long addend) { assert getContent() == null || bb.array() == getContent(); - ((RelocatableSectionImpl) getElement()).markRelocationSite(offset, bb, k, symbolName, useImplicitAddend, explicitAddend); + ((RelocatableSectionImpl) getElement()).markRelocationSite(offset, bb, k, symbolName, addend); } @Override - public Element getOrCreateRelocationElement(boolean useImplicitAddend) { + public Element getOrCreateRelocationElement(long addend) { // FIXME: This looks suspicious: turning an Element back into an Impl? - return ((RelocatableSectionImpl) getElement()).getOrCreateRelocationElement(useImplicitAddend); + return ((RelocatableSectionImpl) getElement()).getOrCreateRelocationElement(addend); } @Override diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java index 3c879bec2cb9..5484b9f97b49 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java @@ -358,11 +358,6 @@ public static int getRelocationSize(RelocationKind kind) { * Interface implemented by objects implementing a specific relocation method and size. */ public interface RelocationMethod { - - boolean canUseImplicitAddend(); - - boolean canUseExplicitAddend(); - /* * If we were implementing a linker, we'd have a method something like * @@ -412,10 +407,9 @@ public interface RelocatableSectionImpl extends ElementImpl { * @param k the kind of fixup to be applied * @param symbolName the name of the symbol whose value is used to compute the fixed-up * bytes - * @param useImplicitAddend whether the current bytes are to be used as an addend - * @param explicitAddend a full-width addend, or null if useImplicitAddend is true + * @param addend a full-width addend, or 0 if unneeded */ - void markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend); + void markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, String symbolName, long addend); /** * Force the creation of a relocation section/element for this section, and return it. This @@ -423,13 +417,12 @@ public interface RelocatableSectionImpl extends ElementImpl { * which leads to unpredictable results (e.g. not appearing in the ELF SHT, if the SHT was * written before the section was created). * - * @param useImplicitAddend whether the relocation section of interest is for implicit - * addends + * @param addend whether a full-width addend, or 0 if unneeded * * @return the element which will hold relocation records (of the argument-specified kind) * for this section */ - Element getOrCreateRelocationElement(boolean useImplicitAddend); + Element getOrCreateRelocationElement(long addend); } /** @@ -446,7 +439,7 @@ public interface ProgbitsSectionImpl extends RelocatableSectionImpl { * passed a buffer. It uses the byte array accessed by {@link #getContent} and * {@link #setContent}. */ - void markRelocationSite(int offset, RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend); + void markRelocationSite(int offset, RelocationKind k, String symbolName, long addend); } public interface NobitsSectionImpl extends ElementImpl { diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/StringSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/StringSectionImpl.java index fc262713ac3a..a96531f0f1a2 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/StringSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/StringSectionImpl.java @@ -119,17 +119,17 @@ public StringSectionImpl() { */ @Override - public Element getOrCreateRelocationElement(boolean useImplicitAddend) { + public Element getOrCreateRelocationElement(long addend) { throw new UnsupportedOperationException("can't mark relocaction sites in string section"); } @Override - public void markRelocationSite(int offset, RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { + public void markRelocationSite(int offset, RelocationKind k, String symbolName, long addend) { throw new UnsupportedOperationException("can't mark relocaction sites in string section"); } @Override - public void markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { + public void markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, String symbolName, long addend) { throw new UnsupportedOperationException("can't mark relocaction sites in string section"); } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFMachine.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFMachine.java index c7b69cf630f8..4e1aa9456449 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFMachine.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFMachine.java @@ -33,12 +33,6 @@ * ELF machine type (incomplete). Each machine type also defines its set of relocation types. */ public enum ELFMachine/* implements Integral */ { - NONE { - @Override - Class> relocationTypes() { - return ELFDummyRelocation.class; - } - }, X86_64 { @Override Class> relocationTypes() { @@ -136,16 +130,13 @@ public static ELFRelocationMethod getRelocation(ELFMachine m, RelocationKind k) } default: - case NONE: - return ELFDummyRelocation.R_NONE; + throw new IllegalStateException("unknown ELF machine type"); } } // TODO: use explicit enum values public static ELFMachine from(int m) { switch (m) { - case 0: - return NONE; case 0x3E: return X86_64; case 0xB7: @@ -156,9 +147,7 @@ public static ELFMachine from(int m) { } public short toShort() { - if (this == NONE) { - return 0; - } else if (this == AArch64) { + if (this == AArch64) { return 0xB7; } else if (this == X86_64) { return 0x3E; @@ -176,25 +165,6 @@ public static ELFMachine getSystemNativeValue() { } } -enum ELFDummyRelocation implements ELFRelocationMethod { - R_NONE; - - @Override - public boolean canUseExplicitAddend() { - return true; - } - - @Override - public boolean canUseImplicitAddend() { - return true; - } - - @Override - public long toLong() { - return ordinal(); - } -} - enum ELFX86_64Relocation implements ELFRelocationMethod { // These are all named R_X86_64_... in elf.h, // but we just use R_... to keep it short. @@ -245,19 +215,6 @@ enum ELFX86_64Relocation implements ELFRelocationMethod { assert R_COUNT.ordinal() == 39; } - /* - * x86-64 relocs always use explicit addends. - */ - @Override - public boolean canUseExplicitAddend() { - return true; - } - - @Override - public boolean canUseImplicitAddend() { - return false; - } - @Override public long toLong() { return ordinal(); @@ -398,16 +355,6 @@ enum ELFAArch64Relocation implements ELFRelocationMethod { this.code = code; } - @Override - public boolean canUseImplicitAddend() { - return false; - } - - @Override - public boolean canUseExplicitAddend() { - return true; - } - @Override public long toLong() { return code; diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFObjectFile.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFObjectFile.java index 9e696a1bbaa7..ab705f9717f6 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFObjectFile.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFObjectFile.java @@ -35,6 +35,9 @@ import java.util.Map; import java.util.Set; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; + import com.oracle.objectfile.BuildDependency; import com.oracle.objectfile.ElementImpl; import com.oracle.objectfile.LayoutDecision; @@ -45,15 +48,13 @@ import com.oracle.objectfile.debuginfo.DebugInfoProvider; import com.oracle.objectfile.elf.dwarf.DwarfARangesSectionImpl; import com.oracle.objectfile.elf.dwarf.DwarfAbbrevSectionImpl; +import com.oracle.objectfile.elf.dwarf.DwarfDebugInfo; import com.oracle.objectfile.elf.dwarf.DwarfFrameSectionImpl; import com.oracle.objectfile.elf.dwarf.DwarfInfoSectionImpl; import com.oracle.objectfile.elf.dwarf.DwarfLineSectionImpl; -import com.oracle.objectfile.elf.dwarf.DwarfDebugInfo; import com.oracle.objectfile.elf.dwarf.DwarfStrSectionImpl; import com.oracle.objectfile.io.AssemblyBuffer; import com.oracle.objectfile.io.OutputAssembler; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; /** * Represents an ELF object file (of any kind: relocatable, shared library, executable, core, ...). @@ -469,9 +470,9 @@ public class ELFHeader extends ObjectFile.Header { */ class Struct { - IdentStruct ident = new IdentStruct(); - ELFType type; - ELFMachine machine; + final IdentStruct ident; + final ELFType type; + final ELFMachine machine; int version; long entry; long phoff; @@ -484,10 +485,10 @@ class Struct { short shnum; short shstrndx; - Struct() { + Struct(ELFType type, ELFMachine machine) { ident = new IdentStruct(); - type = ELFType.NONE; - machine = ELFMachine.NONE; + this.type = type; + this.machine = machine; } /** @@ -618,7 +619,8 @@ public Iterable getDependencies(Map public byte[] getOrDecideContent(Map alreadyDecided, byte[] contentHint) { // we serialize ourselves by writing a Struct to a bytebuffer OutputAssembler oa = AssemblyBuffer.createOutputAssembler(getDataEncoding().toByteOrder()); - Struct contents = new Struct(); // also creates ident struct, which we need to populate + /* Also creates ident struct, which we need to populate. */ + Struct contents = new Struct(getType(), getMachine()); // don't assign magic -- its default value is correct contents.ident.fileClass = getFileClass(); @@ -626,8 +628,6 @@ public byte[] getOrDecideContent(Map alreadyDecided, contents.ident.version = getVersion(); contents.ident.osabi = getOsAbi(); contents.ident.abiVersion = (char) getAbiVersion(); - contents.type = getType(); - contents.machine = getMachine(); contents.version = getVersion(); contents.entry = 0; contents.shoff = (int) alreadyDecided.get(sht).getDecidedValue(LayoutDecision.Kind.OFFSET); @@ -668,7 +668,7 @@ public int getOrDecideOffset(Map alreadyDecided, int @Override public int getOrDecideSize(Map alreadyDecided, int sizeHint) { - int size = (new Struct()).getWrittenSize(); + int size = (new Struct(getType(), getMachine())).getWrittenSize(); assert sizeHint == -1 || sizeHint == size; return size; } @@ -1193,13 +1193,19 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) { * decision set and causes an NPE during reloc section write. So we need to create the * relevant reloc sections here in advance. */ - elfStrSectionImpl.getOrCreateRelocationElement(false); - elfAbbrevSectionImpl.getOrCreateRelocationElement(false); - frameSectionImpl.getOrCreateRelocationElement(false); - elfInfoSectionImpl.getOrCreateRelocationElement(false); - elfARangesSectionImpl.getOrCreateRelocationElement(false); - elfLineSectionImpl.getOrCreateRelocationElement(false); + elfStrSectionImpl.getOrCreateRelocationElement(0); + elfAbbrevSectionImpl.getOrCreateRelocationElement(0); + frameSectionImpl.getOrCreateRelocationElement(0); + elfInfoSectionImpl.getOrCreateRelocationElement(0); + elfARangesSectionImpl.getOrCreateRelocationElement(0); + elfLineSectionImpl.getOrCreateRelocationElement(0); /* Ok now we can populate the debug info model. */ dwarfSections.installDebugInfo(debugInfoProvider); } + + @SuppressWarnings("unused") + static boolean useExplicitAddend(long addend) { + // For now, we are always using explicit addends + return true; + } } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFProgbitsSection.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFProgbitsSection.java index c08176850a51..d06775fb809a 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFProgbitsSection.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFProgbitsSection.java @@ -69,7 +69,7 @@ public void setContent(byte[] c) { } @Override - public void markRelocationSite(int offset, ObjectFile.RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { - markRelocationSite(offset, ByteBuffer.wrap(getContent()).order(getOwner().getByteOrder()), k, symbolName, useImplicitAddend, explicitAddend); + public void markRelocationSite(int offset, ObjectFile.RelocationKind k, String symbolName, long addend) { + markRelocationSite(offset, ByteBuffer.wrap(getContent()).order(getOwner().getByteOrder()), k, symbolName, addend); } } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFRelocationSection.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFRelocationSection.java index 538a2bf4352e..52a10326b91d 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFRelocationSection.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFRelocationSection.java @@ -108,6 +108,19 @@ int getWrittenSize() { interface ELFRelocationMethod extends RelocationMethod { + /* + * For now, ELF relocations are always using explicit addends. This can change in the + * future. + */ + + default boolean canUseImplicitAddend() { + return false; + } + + default boolean canUseExplicitAddend() { + return true; + } + long toLong(); } @@ -172,8 +185,8 @@ public int hashCode() { } } - public Entry addEntry(ELFSection s, long offset, ELFRelocationMethod t, ELFSymtab.Entry sym, Long explicitAddend) { - if (explicitAddend != null) { + void addEntry(ELFSection s, long offset, ELFRelocationMethod t, ELFSymtab.Entry sym, long addend) { + if (ELFObjectFile.useExplicitAddend(addend)) { if (!t.canUseExplicitAddend()) { throw new IllegalArgumentException("cannot use relocation method " + t + " with explicit addends"); } @@ -181,6 +194,7 @@ public Entry addEntry(ELFSection s, long offset, ELFRelocationMethod t, ELFSymta throw new IllegalStateException("cannot create relocation with addend in .rel section"); } } else { + // use implicit addend if (!t.canUseImplicitAddend()) { throw new IllegalArgumentException("cannot use relocation method " + t + " with implicit addends"); } @@ -188,8 +202,7 @@ public Entry addEntry(ELFSection s, long offset, ELFRelocationMethod t, ELFSymta throw new IllegalStateException("cannot create relocation without addend in .rela section"); } } - long addend = (explicitAddend != null) ? explicitAddend : 0L; - return entries.computeIfAbsent(new Entry(s, offset, t, sym, addend), Function.identity()); + entries.computeIfAbsent(new Entry(s, offset, t, sym, addend), Function.identity()); } public boolean isDynamic() { diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFUserDefinedSection.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFUserDefinedSection.java index 6d3f29be036b..e8a3df3e4444 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFUserDefinedSection.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFUserDefinedSection.java @@ -126,36 +126,35 @@ public LayoutDecisionMap getDecisions(LayoutDecisionMap copyingIn) { } @Override - public Element getOrCreateRelocationElement(boolean useImplicitAddend) { + public Element getOrCreateRelocationElement(long addend) { ELFSymtab syms = (ELFSymtab) getOwner().elementForName(".symtab"); if (syms == null) { throw new IllegalStateException("cannot create a relocation section without corresponding symtab"); } - boolean withExplicitAddends = !useImplicitAddend; - ELFRelocationSection rs = withExplicitAddends ? rela : rel; - if (rs == null) { - // we have to create the section if it doesn't exist - rs = getOwner().getOrCreateRelocSection(this, syms, withExplicitAddends); - assert rs != null; - if (withExplicitAddends) { - rela = rs; - } else { - rel = rs; + + if (ELFObjectFile.useExplicitAddend(addend)) { + if (rela == null) { + rela = getOwner().getOrCreateRelocSection(this, syms, true); + assert rela != null; + } + return rela; + } else { + // use implicit addend + if (rel == null) { + rel = getOwner().getOrCreateRelocSection(this, syms, false); + assert rel != null; } + return rel; } - return rs; } @Override - public void markRelocationSite(int offset, ByteBuffer bb, ObjectFile.RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { - if (useImplicitAddend != (explicitAddend == null)) { - throw new IllegalArgumentException("must have either an explicit or implicit addend"); - } + public void markRelocationSite(int offset, ByteBuffer bb, ObjectFile.RelocationKind k, String symbolName, long addend) { ELFSymtab syms = (ELFSymtab) getOwner().elementForName(".symtab"); - ELFRelocationSection rs = (ELFRelocationSection) getOrCreateRelocationElement(useImplicitAddend); + ELFRelocationSection rs = (ELFRelocationSection) getOrCreateRelocationElement(addend); assert symbolName != null; ELFSymtab.Entry ent = syms.getSymbol(symbolName); assert ent != null; - rs.addEntry(this, offset, ELFMachine.getRelocation(getOwner().getMachine(), k), ent, explicitAddend); + rs.addEntry(this, offset, ELFMachine.getRelocation(getOwner().getMachine(), k), ent, addend); } } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java index ce45876549e2..d4c88a8a5ea1 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfSectionImpl.java @@ -206,7 +206,7 @@ protected int putRelocatableCodeOffset(long l, byte[] buffer, int p) { /* * Mark address so it is relocated relative to the start of the text segment. */ - markRelocationSite(pos, ObjectFile.RelocationKind.DIRECT_8, DwarfDebugInfo.TEXT_SECTION_NAME, false, Long.valueOf(l)); + markRelocationSite(pos, ObjectFile.RelocationKind.DIRECT_8, DwarfDebugInfo.TEXT_SECTION_NAME, l); pos = putLong(0, buffer, pos); return pos; } @@ -216,7 +216,7 @@ protected int putRelocatableHeapOffset(long l, byte[] buffer, int p) { /* * Mark address so it is relocated relative to the start of the heap. */ - markRelocationSite(pos, ObjectFile.RelocationKind.DIRECT_8, DwarfDebugInfo.HEAP_BEGIN_NAME, false, Long.valueOf(l)); + markRelocationSite(pos, ObjectFile.RelocationKind.DIRECT_8, DwarfDebugInfo.HEAP_BEGIN_NAME, l); pos = putLong(0, buffer, pos); return pos; } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachOObjectFile.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachOObjectFile.java index 413614d77c74..f453c86bbdec 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachOObjectFile.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachOObjectFile.java @@ -429,7 +429,7 @@ public MachORelocationElement getRelocationElement() { return relocs; } - public MachORelocationElement getOrCreateRelocationElement(@SuppressWarnings("unused") boolean useImplicitAddend) { + public MachORelocationElement getOrCreateRelocationElement() { if (relocs == null) { final Segment64Command containingSegment = getOrCreateSegment(getUnnamedSegmentName(), null, false, false); relocs = new MachORelocationElement(containingSegment); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORegularSection.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORegularSection.java index 791c4e0f5f55..8ec4fcde87fe 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORegularSection.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORegularSection.java @@ -50,8 +50,8 @@ public byte[] getContent() { } @Override - public void markRelocationSite(int offset, RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { - markRelocationSite(offset, ByteBuffer.wrap(getContent()).order(getOwner().getByteOrder()), k, symbolName, useImplicitAddend, explicitAddend); + public void markRelocationSite(int offset, RelocationKind k, String symbolName, long addend) { + markRelocationSite(offset, ByteBuffer.wrap(getContent()).order(getOwner().getByteOrder()), k, symbolName, addend); } } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORelocationElement.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORelocationElement.java index 12328ce998c7..1c454c06e53e 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORelocationElement.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORelocationElement.java @@ -50,14 +50,14 @@ class MachORelocationElement extends MachOObjectFile.LinkEditElement { * within the section. */ - private static int compareSectionThenOffset(RelocationInfo p, RelocationInfo q) { + private static int compareSectionThenOffset(MachORelocationInfo p, MachORelocationInfo q) { if (!p.getRelocatedSection().equals(q.getRelocatedSection())) { return p.getRelocatedSection().hashCode() - q.getRelocatedSection().hashCode(); } return Math.toIntExact(p.getOffset() - q.getOffset()); } - private Map infos = new TreeMap<>(MachORelocationElement::compareSectionThenOffset); + private Map infos = new TreeMap<>(MachORelocationElement::compareSectionThenOffset); private Set relocatedSections = new HashSet<>(); MachORelocationElement(Segment64Command segment) { @@ -66,7 +66,7 @@ private static int compareSectionThenOffset(RelocationInfo p, RelocationInfo q) segment.getOwner().relocs = this; } - public void add(RelocationInfo rec) { + public void add(MachORelocationInfo rec) { if (infos.putIfAbsent(rec, rec) == null) { relocatedSections.add(rec.getRelocatedSection()); } @@ -79,7 +79,7 @@ public boolean relocatesSegment(Segment64Command seg) { @Override public byte[] getOrDecideContent(Map alreadyDecided, byte[] contentHint) { OutputAssembler out = AssemblyBuffer.createOutputAssembler(getOwner().getByteOrder()); - for (RelocationInfo rec : infos.keySet()) { + for (MachORelocationInfo rec : infos.keySet()) { rec.write(out, alreadyDecided); } assert getOrDecideSize(alreadyDecided, -1) == out.pos(); @@ -98,7 +98,7 @@ public Iterable getDependencies(Map public int startIndexFor(MachOSection s) { int i = 0; - for (RelocationInfo info : infos.keySet()) { + for (MachORelocationInfo info : infos.keySet()) { if (info.getRelocatedSection() == s) { return i; } @@ -108,7 +108,7 @@ public int startIndexFor(MachOSection s) { } public int encodedEntrySize() { - return RelocationInfo.getEncodedSize(); + return MachORelocationInfo.getEncodedSize(); } public int countFor(MachOSection s) { @@ -116,50 +116,60 @@ public int countFor(MachOSection s) { } } +/** + * These are defined as an enum in + * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/x86_64/reloc.h#L173 + * which we reproduce. Of course, take care to preserve the order! + * + * For examples of how these symbols are used, see the linked file above and + * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h. + */ enum X86_64Reloc { - /* - * These are defined as an enum in /usr/include/mach-o/x86-64/reloc.h, which we reproduce. Of - * course, take care to preserve the order! - */ - UNSIGNED, - SIGNED, - BRANCH, - GOT_LOAD, - GOT, - SUBTRACTOR, - SIGNED_1, - SIGNED_2, - SIGNED_4, - TLV; + UNSIGNED, // for absolute addresses + SIGNED, // for signed 32-bit displacement + BRANCH, // a CALL/JMP instruction with 32-bit displacement + GOT_LOAD, // a MOVQ load of a GOT entry + GOT, // other GOT references + SUBTRACTOR, // must be followed by a X86_64_RELOC_UNSIGNED + SIGNED_1, // for signed 32-bit displacement with a -1 addend + SIGNED_2, // for signed 32-bit displacement with a -2 addend + SIGNED_4, // for signed 32-bit displacement with a -4 addend + TLV; // for thread local variables public int getValue() { return ordinal(); } } +/** + * These are defined as an enum in + * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/arm64/reloc.h#L26, + * which we reproduce. Of course, take care to preserve the order! + * + * For examples of how these symbols are used, see + * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/arm/reloc.h + * (for AArch32 information, but does provide some insight) and + * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h. + */ enum ARM64Reloc { - /* - * These are defined as an enum in /usr/include/mach-o/arm64/reloc.h, which we reproduce. Of - * course, take care to preserve the order! - */ - UNSIGNED, - SUBTRACTOR, - BRANCH26, - PAGE21, - PAGEOFF12, - GOT_LOAD_PAGE21, - GOT_LOAD_PAGEOFF12, - POINTER_TO_GOT, - TLVP_LOAD_PAGE21, - TLVP_LOAD_PAGEOFF12, - ADDEND; + UNSIGNED, // for pointers + SUBTRACTOR, // must be followed by a ARM64_RELOC_UNSIGNED + BRANCH26, // a B/BL instruction with 26-bit displacement + PAGE21, // pc-rel distance to page of target + PAGEOFF12, // offset within page, scaled by r_length + GOT_LOAD_PAGE21, // pc-rel distance to page of GOT slot + GOT_LOAD_PAGEOFF12, // offset within page of GOT slot, scaled by r_length + POINTER_TO_GOT, // for pointers to GOT slots + TLVP_LOAD_PAGE21, // pc-rel distance to page of TLVP slot + TLVP_LOAD_PAGEOFF12, // offset within page of TLVP slot, scaled by r_length + ADDEND; // must be followed by PAGE21 or PAGEOFF12 public int getValue() { return ordinal(); } } -final class RelocationInfo implements RelocationRecord, RelocationMethod { +final class MachORelocationInfo implements RelocationRecord, RelocationMethod { private final MachORelocationElement containingElement; private final MachOSection relocatedSection; @@ -179,7 +189,7 @@ final class RelocationInfo implements RelocationRecord, RelocationMethod { * @param kind the kind of relocation to perform at the relocation site * @param symbolName the symbol against which to relocate */ - RelocationInfo(MachORelocationElement containingElement, MachOSection relocatedSection, int offset, int requestedLength, RelocationKind kind, String symbolName, boolean asLocalReloc) { + MachORelocationInfo(MachORelocationElement containingElement, MachOSection relocatedSection, int offset, int requestedLength, RelocationKind kind, String symbolName, boolean asLocalReloc) { this.containingElement = containingElement; this.relocatedSection = relocatedSection; this.sectionOffset = offset; // gets turned into a vaddr on write-out @@ -261,16 +271,6 @@ public Symbol getReferencedSymbol() { return sym; } - @Override - public boolean canUseExplicitAddend() { - return false; - } - - @Override - public boolean canUseImplicitAddend() { - return true; - } - public MachOSection getRelocatedSection() { return relocatedSection; } @@ -341,7 +341,7 @@ public boolean equals(Object obj) { return true; } if (obj != null && getClass() == obj.getClass()) { - RelocationInfo other = (RelocationInfo) obj; + MachORelocationInfo other = (MachORelocationInfo) obj; return sectionOffset == other.sectionOffset && log2length == other.log2length && Objects.equals(containingElement, other.containingElement) && Objects.equals(getRelocatedSection(), other.getRelocatedSection()) && kind == other.kind && Objects.equals(sym, other.sym) && Objects.equals(targetSection, other.targetSection); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachOUserDefinedSection.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachOUserDefinedSection.java index 8a98f5e8448f..33d930f31c76 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachOUserDefinedSection.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachOUserDefinedSection.java @@ -154,35 +154,26 @@ public LayoutDecisionMap getDecisions(LayoutDecisionMap copyingIn) { } @Override - public MachORelocationElement getOrCreateRelocationElement(boolean useImplicitAddend) { - return getOwner().getOrCreateRelocationElement(useImplicitAddend); + public MachORelocationElement getOrCreateRelocationElement(long addend) { + return getOwner().getOrCreateRelocationElement(); } @Override - public void markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { - MachORelocationElement el = getOrCreateRelocationElement(useImplicitAddend); + public void markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, String symbolName, long addend) { + MachORelocationElement el = getOrCreateRelocationElement(addend); AssemblyBuffer sbb = new AssemblyBuffer(bb); sbb.setByteOrder(getOwner().getByteOrder()); sbb.pushSeek(offset); /* * NOTE: Mach-O does not support explicit addends, and inline addends are applied even - * during dynamic linking. So if the caller supplies an explicit addend, we turn it into an - * implicit one by updating our content. + * during dynamic linking. */ int length = ObjectFile.RelocationKind.getRelocationSize(k); - long currentInlineAddendValue = sbb.readTruncatedLong(length); - long desiredInlineAddendValue; - if (explicitAddend != null) { - /* - * This assertion is conservatively disallowing double-addend (could - * "add currentValue to explicitAddend"), because that seems more likely to be a bug - * than a feature. - */ - assert currentInlineAddendValue == 0; - desiredInlineAddendValue = explicitAddend; - } else { - desiredInlineAddendValue = currentInlineAddendValue; - } + /* + * The addend is passed as a method parameter. The initial implicit addend value within the + * instruction does not need to be read, as it is noise. + */ + long desiredInlineAddendValue = addend; /* * One more complication: for PC-relative relocation, at least on x86-64, Mach-O linkers @@ -212,7 +203,7 @@ public void markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, Stri // return ByteBuffer cursor to where it was sbb.pop(); - RelocationInfo rec = new RelocationInfo(el, this, offset, length, k, symbolName, createAsLocalReloc); + MachORelocationInfo rec = new MachORelocationInfo(el, this, offset, length, k, symbolName, createAsLocalReloc); el.add(rec); } } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffMachine.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffMachine.java index 5aa80dce0669..2961926c1a51 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffMachine.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffMachine.java @@ -35,12 +35,6 @@ * PECoff machine type (incomplete). Each machine type also defines its set of relocation types. */ public enum PECoffMachine/* implements Integral */ { - NONE { - @Override - Class> relocationTypes() { - return PECoffDummyRelocation.class; - } - }, X86_64 { @Override Class> relocationTypes() { @@ -69,15 +63,12 @@ public static PECoffRelocationMethod getRelocation(PECoffMachine m, RelocationKi throw new IllegalArgumentException("cannot map unknown relocation kind to an PECoff x86-64 relocation type"); } default: - case NONE: - return PECoffDummyRelocation.R_NONE; + throw new IllegalStateException("unknown PECoff machine type"); } } public static PECoffMachine from(int m) { switch (m) { - case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_UNKNOWN: - return NONE; case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: return X86_64; default: @@ -86,9 +77,7 @@ public static PECoffMachine from(int m) { } public short toShort() { - if (this == NONE) { - return (short) IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_UNKNOWN; - } else if (this == X86_64) { + if (this == X86_64) { return (short) IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64; } else { throw new IllegalStateException("should not reach here"); @@ -104,25 +93,6 @@ public static PECoffMachine getSystemNativeValue() { } } -enum PECoffDummyRelocation implements PECoffRelocationMethod { - R_NONE; - - @Override - public boolean canUseExplicitAddend() { - return true; - } - - @Override - public boolean canUseImplicitAddend() { - return true; - } - - @Override - public long toLong() { - return ordinal(); - } -} - /** * @formatter:off * @@ -176,17 +146,4 @@ public long toLong() { return IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; } }; - - /* - * x86-64 relocs always use explicit addends. - */ - @Override - public boolean canUseExplicitAddend() { - return true; - } - - @Override - public boolean canUseImplicitAddend() { - return false; - } } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffObjectFile.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffObjectFile.java index 138ad8457e33..cc977d3f54bb 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffObjectFile.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffObjectFile.java @@ -662,11 +662,11 @@ public PECoffMachine getMachine() { return machine; } - public PECoffRelocationTable getOrCreateRelocSection(PECoffSymtab syms, boolean withExplicitAddends) { + public PECoffRelocationTable getOrCreateRelocSection(PECoffSymtab syms) { Element el = elementForName(".reloctab"); PECoffRelocationTable rs; if (el == null) { - rs = new PECoffRelocationTable(this, ".reloctab", syms, withExplicitAddends); + rs = new PECoffRelocationTable(this, ".reloctab", syms); } else if (el instanceof PECoffRelocationTable) { rs = (PECoffRelocationTable) el; } else { @@ -719,8 +719,8 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) { // layout constraints included in the layout decision set and causes // an NPE during reloc section write. so we need to create the relevant // reloc sections here in advance - cvSymbolSectionImpl.getOrCreateRelocationElement(false); - cvTypeSectionImpl.getOrCreateRelocationElement(false); + cvSymbolSectionImpl.getOrCreateRelocationElement(0); + cvTypeSectionImpl.getOrCreateRelocationElement(0); // ok now we can populate the implementations cvDebugInfo.installDebugInfo(debugInfoProvider); diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffProgbitsSection.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffProgbitsSection.java index 5bb4740dbeb7..e3f7dccae6f6 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffProgbitsSection.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffProgbitsSection.java @@ -31,8 +31,8 @@ import com.oracle.objectfile.BasicProgbitsSectionImpl; import com.oracle.objectfile.ObjectFile; import com.oracle.objectfile.ObjectFile.ProgbitsSectionImpl; -import com.oracle.objectfile.pecoff.PECoffObjectFile.PECoffSectionFlag; import com.oracle.objectfile.io.InputDisassembler; +import com.oracle.objectfile.pecoff.PECoffObjectFile.PECoffSectionFlag; public class PECoffProgbitsSection extends PECoffUserDefinedSection implements ProgbitsSectionImpl { @@ -69,7 +69,7 @@ public void setContent(byte[] c) { } @Override - public void markRelocationSite(int offset, ObjectFile.RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { - markRelocationSite(offset, ByteBuffer.wrap(getContent()).order(getOwner().getByteOrder()), k, symbolName, useImplicitAddend, explicitAddend); + public void markRelocationSite(int offset, ObjectFile.RelocationKind k, String symbolName, long addend) { + markRelocationSite(offset, ByteBuffer.wrap(getContent()).order(getOwner().getByteOrder()), k, symbolName, addend); } } diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffRelocationTable.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffRelocationTable.java index f9cdd31e701d..163fe5ebdf38 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffRelocationTable.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffRelocationTable.java @@ -55,6 +55,7 @@ public ElementImpl getImpl() { } interface PECoffRelocationMethod extends RelocationMethod { + long toLong(); } @@ -101,19 +102,17 @@ public int hashCode() { } } - private final boolean withExplicitAddends; private final PECoffSymtab syms; private PECoffObjectFile owner = null; - PECoffRelocationTable(PECoffObjectFile owner, String name, PECoffSymtab syms, boolean withExplicitAddends) { + PECoffRelocationTable(PECoffObjectFile owner, String name, PECoffSymtab syms) { owner.super(name, 4); this.owner = owner; - this.withExplicitAddends = withExplicitAddends; this.syms = syms; } - public Entry addEntry(PECoffSection s, long offset, PECoffRelocationMethod t, PECoffSymtab.Entry sym, Long explicitAddend) { + void addEntry(PECoffSection s, long offset, PECoffRelocationMethod t, PECoffSymtab.Entry sym, long addend) { Map entries = (Map) s.getRelocEntries(); if (entries == null) { @@ -121,23 +120,7 @@ public Entry addEntry(PECoffSection s, long offset, PECoffRelocationMethod t, PE s.setRelocEntries(entries); } - if (explicitAddend != null) { - if (!t.canUseExplicitAddend()) { - throw new IllegalArgumentException("cannot use relocation method " + t + " with explicit addends"); - } - if (!withExplicitAddends) { - throw new IllegalStateException("cannot create relocation with addend in .rel section"); - } - } else { - if (!t.canUseImplicitAddend()) { - throw new IllegalArgumentException("cannot use relocation method " + t + " with implicit addends"); - } - if (withExplicitAddends) { - throw new IllegalStateException("cannot create relocation without addend in .rela section"); - } - } - long addend = (explicitAddend != null) ? explicitAddend : 0L; - return entries.computeIfAbsent(new Entry(s, offset, t, sym, addend), Function.identity()); + entries.computeIfAbsent(new Entry(s, offset, t, sym, addend), Function.identity()); } // Returns count of relocation entries for section diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffUserDefinedSection.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffUserDefinedSection.java index 7ffcc1d003e1..4d34aa1ee8a9 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffUserDefinedSection.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffUserDefinedSection.java @@ -49,7 +49,6 @@ public class PECoffUserDefinedSection extends PECoffSection implements ObjectFile.RelocatableSectionImpl { private PECoffRelocationTable rel; // the section holding our relocations without addends - private PECoffRelocationTable rela; // the section holding our relocations with addends protected ElementImpl impl; @@ -119,33 +118,23 @@ public LayoutDecisionMap getDecisions(LayoutDecisionMap copyingIn) { } @Override - public Element getOrCreateRelocationElement(boolean useImplicitAddend) { + public Element getOrCreateRelocationElement(long addend) { PECoffSymtab syms = (PECoffSymtab) getOwner().elementForName(".symtab"); if (syms == null) { throw new IllegalStateException("cannot create a relocation section without corresponding symtab"); } - boolean withExplicitAddends = !useImplicitAddend; - PECoffRelocationTable rs = withExplicitAddends ? rela : rel; - if (rs == null) { - // we have to create the section if it doesn't exist - rs = getOwner().getOrCreateRelocSection(syms, withExplicitAddends); - assert rs != null; - if (withExplicitAddends) { - rela = rs; - } else { - rel = rs; - } + + if (rel == null) { + rel = getOwner().getOrCreateRelocSection(syms); + assert rel != null; } - return rs; + return rel; } @Override - public void markRelocationSite(int offset, ByteBuffer bb, ObjectFile.RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) { - if (useImplicitAddend != (explicitAddend == null)) { - throw new IllegalArgumentException("must have either an explicit or implicit addend"); - } + public void markRelocationSite(int offset, ByteBuffer bb, ObjectFile.RelocationKind k, String symbolName, long addend) { PECoffSymtab syms = (PECoffSymtab) getOwner().elementForName(".symtab"); - PECoffRelocationTable rs = (PECoffRelocationTable) getOrCreateRelocationElement(useImplicitAddend); + PECoffRelocationTable rs = (PECoffRelocationTable) getOrCreateRelocationElement(addend); assert symbolName != null; PECoffSymtab.Entry ent = syms.getSymbol(symbolName); if (ent == null) { @@ -158,23 +147,14 @@ public void markRelocationSite(int offset, ByteBuffer bb, ObjectFile.RelocationK sbb.pushSeek(offset); /* * NOTE: Windows does not support explicit addends, and inline addends are applied even - * during dynamic linking. So if the caller supplies an explicit addend, we turn it into an - * implicit one by updating our content. + * during dynamic linking. */ int length = ObjectFile.RelocationKind.getRelocationSize(k); - long currentInlineAddendValue = sbb.readTruncatedLong(length); - long desiredInlineAddendValue; - if (explicitAddend != null) { - /* - * This assertion is conservatively disallowing double-addend (could - * "add currentValue to explicitAddend"), because that seems more likely to be a bug - * than a feature. - */ - assert currentInlineAddendValue == 0; - desiredInlineAddendValue = explicitAddend; - } else { - desiredInlineAddendValue = currentInlineAddendValue; - } + /* + * The addend is passed as a method parameter. The initial implicit addend value within the + * instruction does not need to be read, as it is noise. + */ + long desiredInlineAddendValue = addend; /* * One more complication: for PC-relative relocation, at least on x86-64, Coff linkers @@ -196,7 +176,7 @@ public void markRelocationSite(int offset, ByteBuffer bb, ObjectFile.RelocationK // return ByteBuffer cursor to where it was sbb.pop(); - rs.addEntry(this, offset, PECoffMachine.getRelocation(getOwner().getMachine(), k), ent, explicitAddend); + rs.addEntry(this, offset, PECoffMachine.getRelocation(getOwner().getMachine(), k), ent, addend); } /** diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/cv/CVLineRecord.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/cv/CVLineRecord.java index 090f30fe4acb..46dc4f9072b7 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/cv/CVLineRecord.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/cv/CVLineRecord.java @@ -92,9 +92,9 @@ private int computeHeader(byte[] buffer, int initialPos) { int pos = initialPos; /* Emit addr:section relocation records. */ - cvDebugInfo.getCVSymbolSection().markRelocationSite(pos, ObjectFile.RelocationKind.SECREL_4, symbolName, false, 1L); + cvDebugInfo.getCVSymbolSection().markRelocationSite(pos, ObjectFile.RelocationKind.SECREL_4, symbolName, 1L); pos = CVUtil.putInt(0, buffer, pos); - cvDebugInfo.getCVSymbolSection().markRelocationSite(pos, ObjectFile.RelocationKind.SECTION_2, symbolName, false, 1L); + cvDebugInfo.getCVSymbolSection().markRelocationSite(pos, ObjectFile.RelocationKind.SECTION_2, symbolName, 1L); pos = CVUtil.putShort((short) 0, buffer, pos); /* Emit flags. */ diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/cv/CVSymbolSubrecord.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/cv/CVSymbolSubrecord.java index ddb43d1039c7..4a2cf1320132 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/cv/CVSymbolSubrecord.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/cv/CVSymbolSubrecord.java @@ -297,11 +297,11 @@ protected int computeContents(byte[] buffer, int initialPos) { pos = CVUtil.putInt(debugEnd, buffer, pos); pos = CVUtil.putInt(typeIndex, buffer, pos); if (buffer != null) { - cvDebugInfo.getCVSymbolSection().markRelocationSite(pos, ObjectFile.RelocationKind.SECREL_4, externalName, false, 1L); + cvDebugInfo.getCVSymbolSection().markRelocationSite(pos, ObjectFile.RelocationKind.SECREL_4, externalName, 1L); } pos = CVUtil.putInt(0, buffer, pos); if (buffer != null) { - cvDebugInfo.getCVSymbolSection().markRelocationSite(pos, ObjectFile.RelocationKind.SECTION_2, externalName, false, 1L); + cvDebugInfo.getCVSymbolSection().markRelocationSite(pos, ObjectFile.RelocationKind.SECTION_2, externalName, 1L); } pos = CVUtil.putShort((short) 0, buffer, pos); pos = CVUtil.putByte(flags, buffer, pos); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcher.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcher.java index 305bf88f262b..90f4d6218115 100755 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcher.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcher.java @@ -119,7 +119,7 @@ class AdrpLdrMacroInstructionHostedPatcher extends CompilationResult.CodeAnnotat public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { int siteOffset = compStart + macroInstruction.instructionPosition; - relocs.addRelocationWithAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADR_PREL_PG_HI21, Long.valueOf(0), ref); + relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADR_PREL_PG_HI21, ref); siteOffset += 4; RelocationKind secondRelocation; switch (macroInstruction.srcSize) { @@ -141,7 +141,7 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { default: throw VMError.shouldNotReachHere("Unknown macro instruction src size of " + macroInstruction.srcSize); } - relocs.addRelocationWithAddend(siteOffset, secondRelocation, Long.valueOf(0), ref); + relocs.addRelocationWithoutAddend(siteOffset, secondRelocation, ref); } @Uninterruptible(reason = ".") @@ -170,9 +170,9 @@ class AdrpAddMacroInstructionHostedPatcher extends CompilationResult.CodeAnnotat public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { int siteOffset = compStart + macroInstruction.instructionPosition; - relocs.addRelocationWithAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADR_PREL_PG_HI21, Long.valueOf(0), ref); + relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADR_PREL_PG_HI21, ref); siteOffset += 4; - relocs.addRelocationWithAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADD_ABS_LO12_NC, Long.valueOf(0), ref); + relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADD_ABS_LO12_NC, ref); } @Uninterruptible(reason = ".") @@ -231,9 +231,9 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { continue; } if (i == lastMovIndex) { - relocs.addRelocationWithAddend(siteOffset, relocations[i], Long.valueOf(0), ref); + relocs.addRelocationWithoutAddend(siteOffset, relocations[i], ref); } else { - relocs.addRelocationWithAddend(siteOffset, noCheckRelocations[i], Long.valueOf(0), ref); + relocs.addRelocationWithoutAddend(siteOffset, noCheckRelocations[i], ref); } siteOffset = siteOffset + 4; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java index b41457106299..f679cf41263d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java @@ -394,7 +394,7 @@ private ObjectFile.Symbol defineRelocationForSymbol(String name, long position) } ProgbitsSectionImpl baseSectionImpl = (ProgbitsSectionImpl) rwDataSection.getImpl(); int offsetInSection = Math.toIntExact(RWDATA_CGLOBALS_PARTITION_OFFSET + position); - baseSectionImpl.markRelocationSite(offsetInSection, wordSize == 8 ? RelocationKind.DIRECT_8 : RelocationKind.DIRECT_4, name, false, 0L); + baseSectionImpl.markRelocationSite(offsetInSection, wordSize == 8 ? RelocationKind.DIRECT_8 : RelocationKind.DIRECT_4, name, 0L); return symbol; } @@ -580,7 +580,7 @@ private void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, f target = metaAccess.lookupJavaMethod(InvalidMethodPointerHandler.METHOD_POINTER_NOT_COMPILED_HANDLER_METHOD); } // A reference to a method. Mark the relocation site using the symbol name. - sectionImpl.markRelocationSite(offset, RelocationKind.getDirect(functionPointerRelocationSize), localSymbolNameForMethod(target), false, 0L); + sectionImpl.markRelocationSite(offset, RelocationKind.getDirect(functionPointerRelocationSize), localSymbolNameForMethod(target), 0L); } private static boolean isAddendAligned(Architecture arch, long addend, RelocationKind kind) { @@ -613,9 +613,8 @@ private void markDataRelocationSite(ProgbitsSectionImpl sectionImpl, int offset, assert targetObjectInfo != null; String targetSectionName = heapSection.getName(); long address = targetObjectInfo.getAddress(); - long relocationInfoAddend = info.hasExplicitAddend() ? info.getExplicitAddend() : 0L; - long relocationAddend = address + relocationInfoAddend; - sectionImpl.markRelocationSite(offset, info.getRelocationKind(), targetSectionName, false, relocationAddend); + long relocationAddend = address + info.getAddend(); + sectionImpl.markRelocationSite(offset, info.getRelocationKind(), targetSectionName, relocationAddend); } private void markDataRelocationSiteFromText(RelocatableBuffer buffer, final ProgbitsSectionImpl sectionImpl, final int offset, final Info info) { @@ -624,23 +623,23 @@ private void markDataRelocationSiteFromText(RelocatableBuffer buffer, final Prog info.getRelocationSize(); Object target = info.getTargetObject(); if (target instanceof DataSectionReference) { - long addend = ((DataSectionReference) target).getOffset() - info.getExplicitAddend(); + long addend = ((DataSectionReference) target).getOffset() - info.getAddend(); assert isAddendAligned(arch, addend, info.getRelocationKind()) : "improper addend alignment"; - sectionImpl.markRelocationSite(offset, info.getRelocationKind(), roDataSection.getName(), false, addend); + sectionImpl.markRelocationSite(offset, info.getRelocationKind(), roDataSection.getName(), addend); } else if (target instanceof CGlobalDataReference) { CGlobalDataReference ref = (CGlobalDataReference) target; CGlobalDataInfo dataInfo = ref.getDataInfo(); CGlobalDataImpl data = dataInfo.getData(); - long addend = RWDATA_CGLOBALS_PARTITION_OFFSET + dataInfo.getOffset() - info.getExplicitAddend(); + long addend = RWDATA_CGLOBALS_PARTITION_OFFSET + dataInfo.getOffset() - info.getAddend(); assert isAddendAligned(arch, addend, info.getRelocationKind()) : "improper addend alignment"; - sectionImpl.markRelocationSite(offset, info.getRelocationKind(), rwDataSection.getName(), false, addend); + sectionImpl.markRelocationSite(offset, info.getRelocationKind(), rwDataSection.getName(), addend); if (dataInfo.isSymbolReference()) { // create relocation for referenced symbol if (objectFile.getSymbolTable().getSymbol(data.symbolName) == null) { objectFile.createUndefinedSymbol(data.symbolName, 0, true); } ProgbitsSectionImpl baseSectionImpl = (ProgbitsSectionImpl) rwDataSection.getImpl(); int offsetInSection = Math.toIntExact(RWDATA_CGLOBALS_PARTITION_OFFSET + dataInfo.getOffset()); - baseSectionImpl.markRelocationSite(offsetInSection, RelocationKind.getDirect(wordSize), data.symbolName, false, 0L); + baseSectionImpl.markRelocationSite(offsetInSection, RelocationKind.getDirect(wordSize), data.symbolName, 0L); } } else if (target instanceof ConstantReference) { // Direct object reference in code that must be patched (not a linker relocation) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/RelocatableBuffer.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/RelocatableBuffer.java index 0412c1c788eb..e6d473f46192 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/RelocatableBuffer.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/RelocatableBuffer.java @@ -53,11 +53,11 @@ public RelocatableBuffer(long size, ByteOrder byteOrder) { } public void addRelocationWithoutAddend(int key, ObjectFile.RelocationKind relocationKind, Object targetObject) { - relocations.put(key, new Info(relocationKind, null, targetObject)); + relocations.put(key, new Info(relocationKind, 0L, targetObject)); } - public void addRelocationWithAddend(int key, ObjectFile.RelocationKind relocationKind, Long explicitAddend, Object targetObject) { - relocations.put(key, new Info(relocationKind, explicitAddend, targetObject)); + public void addRelocationWithAddend(int key, ObjectFile.RelocationKind relocationKind, long addend, Object targetObject) { + relocations.put(key, new Info(relocationKind, addend, targetObject)); } public boolean hasRelocations() { @@ -78,7 +78,7 @@ public ByteBuffer getByteBuffer() { static final class Info { private final ObjectFile.RelocationKind relocationKind; - private final Long explicitAddend; + private final long addend; /** * The referenced object on the heap. If this is an instance of a {@link RelocatedPointer}, * than the relocation is not treated as a data relocation but has a special meaning, e.g. a @@ -86,9 +86,9 @@ static final class Info { */ private final Object targetObject; - Info(ObjectFile.RelocationKind kind, Long explicitAddend, Object targetObject) { + Info(ObjectFile.RelocationKind kind, long addend, Object targetObject) { this.relocationKind = kind; - this.explicitAddend = explicitAddend; + this.addend = addend; this.targetObject = targetObject; } @@ -100,12 +100,8 @@ public ObjectFile.RelocationKind getRelocationKind() { return relocationKind; } - public boolean hasExplicitAddend() { - return (explicitAddend != null); - } - - public Long getExplicitAddend() { - return explicitAddend; + public long getAddend() { + return addend; } public Object getTargetObject() { @@ -114,7 +110,7 @@ public Object getTargetObject() { @Override public String toString() { - return "RelocatableBuffer.Info(targetObject=" + targetObject + " relocationKind=" + relocationKind + " explicitAddend=" + explicitAddend + ")"; + return "RelocatableBuffer.Info(targetObject=" + targetObject + " relocationKind=" + relocationKind + " addend=" + addend + ")"; } } } From 4f647e947075eeec333e2f9fe70f08b1e6b406fa Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Mon, 4 Oct 2021 19:06:26 +0200 Subject: [PATCH 433/681] Add AArch64DarwinUContextRegisterDumper. --- .../AArch64DarwinUContextRegisterDumper.java | 123 +++++++ ...> AArch64LinuxUContextRegisterDumper.java} | 18 +- .../AMD64DarwinUContextRegisterDumper.java} | 20 +- .../AMD64LinuxUContextRegisterDumper.java | 109 ++++++ .../amd64/AMD64UContextRegisterDumper.java | 109 ------ .../oracle/svm/core/posix/headers/Signal.java | 314 ++++++++++-------- .../hosted/c/codegen/CCompilerInvoker.java | 16 +- 7 files changed, 441 insertions(+), 268 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64DarwinUContextRegisterDumper.java rename substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/{AArch64UContextRegisterDumper.java => AArch64LinuxUContextRegisterDumper.java} (90%) rename substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/{darwin/DarwinUContextRegisterDumper.java => amd64/AMD64DarwinUContextRegisterDumper.java} (88%) create mode 100644 substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64LinuxUContextRegisterDumper.java delete mode 100644 substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64UContextRegisterDumper.java diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64DarwinUContextRegisterDumper.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64DarwinUContextRegisterDumper.java new file mode 100644 index 000000000000..5339e5ad84ec --- /dev/null +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64DarwinUContextRegisterDumper.java @@ -0,0 +1,123 @@ +/* + * 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.core.posix.aarch64; + +import static com.oracle.svm.core.RegisterDumper.dumpReg; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.word.PointerBase; +import org.graalvm.word.WordFactory; + +import com.oracle.svm.core.RegisterDumper; +import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.graal.aarch64.AArch64ReservedRegisters; +import com.oracle.svm.core.log.Log; +import com.oracle.svm.core.posix.UContextRegisterDumper; +import com.oracle.svm.core.posix.headers.Signal; +import com.oracle.svm.core.util.VMError; + +import jdk.vm.ci.aarch64.AArch64; + +@Platforms({Platform.DARWIN_AARCH64.class, Platform.IOS_AARCH64.class}) +@AutomaticFeature +class AArch64DarwinUContextRegisterDumperFeature implements Feature { + @Override + public void afterRegistration(AfterRegistrationAccess access) { + VMError.guarantee(AArch64.r27.equals(AArch64ReservedRegisters.HEAP_BASE_REGISTER_CANDIDATE)); + VMError.guarantee(AArch64.r28.equals(AArch64ReservedRegisters.THREAD_REGISTER_CANDIDATE)); + ImageSingletons.add(RegisterDumper.class, new AArch64DarwinUContextRegisterDumper()); + } +} + +public class AArch64DarwinUContextRegisterDumper implements UContextRegisterDumper { + @Override + public void dumpRegisters(Log log, Signal.ucontext_t uContext, boolean printLocationInfo, boolean allowJavaHeapAccess, boolean allowUnsafeOperations) { + Signal.AArch64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_aarch64(); + Signal.GregsPointer regs = sigcontext.regs(); + dumpReg(log, "R0 ", regs.read(0), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R1 ", regs.read(1), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R2 ", regs.read(2), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R3 ", regs.read(3), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R4 ", regs.read(4), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R5 ", regs.read(5), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R6 ", regs.read(6), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R7 ", regs.read(7), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R8 ", regs.read(8), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R9 ", regs.read(9), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R10 ", regs.read(10), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R11 ", regs.read(11), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R12 ", regs.read(12), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R13 ", regs.read(13), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R14 ", regs.read(14), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R15 ", regs.read(15), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R16 ", regs.read(16), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R17 ", regs.read(17), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R18 ", regs.read(18), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R19 ", regs.read(19), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R20 ", regs.read(20), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R21 ", regs.read(21), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R22 ", regs.read(22), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R23 ", regs.read(23), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R24 ", regs.read(24), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R25 ", regs.read(25), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R26 ", regs.read(26), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R27 ", regs.read(27), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R28 ", regs.read(28), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R29 ", sigcontext.fp(), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R30 ", sigcontext.lr(), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "SP ", sigcontext.sp(), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "PC ", sigcontext.pc(), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + } + + @Override + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) + public PointerBase getHeapBase(Signal.ucontext_t uContext) { + Signal.AArch64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_aarch64(); + return WordFactory.pointer(sigcontext.regs().read(27)); + } + + @Override + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) + public PointerBase getThreadPointer(Signal.ucontext_t uContext) { + Signal.AArch64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_aarch64(); + return WordFactory.pointer(sigcontext.regs().read(28)); + } + + @Override + public PointerBase getSP(Signal.ucontext_t uContext) { + Signal.AArch64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_aarch64(); + return WordFactory.pointer(sigcontext.sp()); + } + + @Override + public PointerBase getIP(Signal.ucontext_t uContext) { + Signal.AArch64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_aarch64(); + return WordFactory.pointer(sigcontext.pc()); + } +} diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64UContextRegisterDumper.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64LinuxUContextRegisterDumper.java similarity index 90% rename from substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64UContextRegisterDumper.java rename to substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64LinuxUContextRegisterDumper.java index b3c643e630b6..235d1e157234 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64UContextRegisterDumper.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/aarch64/AArch64LinuxUContextRegisterDumper.java @@ -40,7 +40,7 @@ import com.oracle.svm.core.log.Log; import com.oracle.svm.core.posix.UContextRegisterDumper; import com.oracle.svm.core.posix.headers.Signal.GregsPointer; -import com.oracle.svm.core.posix.headers.Signal.mcontext_t; +import com.oracle.svm.core.posix.headers.Signal.mcontext_linux_aarch64_t; import com.oracle.svm.core.posix.headers.Signal.ucontext_t; import com.oracle.svm.core.util.VMError; @@ -48,19 +48,19 @@ @Platforms({Platform.LINUX_AARCH64.class, Platform.ANDROID_AARCH64.class}) @AutomaticFeature -class AArch64UContextRegisterDumperFeature implements Feature { +class AArch64LinuxUContextRegisterDumperFeature implements Feature { @Override public void afterRegistration(AfterRegistrationAccess access) { VMError.guarantee(AArch64.r27.equals(AArch64ReservedRegisters.HEAP_BASE_REGISTER_CANDIDATE)); VMError.guarantee(AArch64.r28.equals(AArch64ReservedRegisters.THREAD_REGISTER_CANDIDATE)); - ImageSingletons.add(RegisterDumper.class, new AArch64UContextRegisterDumper()); + ImageSingletons.add(RegisterDumper.class, new AArch64LinuxUContextRegisterDumper()); } } -class AArch64UContextRegisterDumper implements UContextRegisterDumper { +class AArch64LinuxUContextRegisterDumper implements UContextRegisterDumper { @Override public void dumpRegisters(Log log, ucontext_t uContext, boolean printLocationInfo, boolean allowJavaHeapAccess, boolean allowUnsafeOperations) { - mcontext_t sigcontext = uContext.uc_mcontext(); + mcontext_linux_aarch64_t sigcontext = uContext.uc_mcontext_linux_aarch64(); GregsPointer regs = sigcontext.regs(); dumpReg(log, "R0 ", regs.read(0), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); dumpReg(log, "R1 ", regs.read(1), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); @@ -100,26 +100,26 @@ public void dumpRegisters(Log log, ucontext_t uContext, boolean printLocationInf @Override @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) public PointerBase getHeapBase(ucontext_t uContext) { - GregsPointer regs = uContext.uc_mcontext().regs(); + GregsPointer regs = uContext.uc_mcontext_linux_aarch64().regs(); return WordFactory.pointer(regs.read(27)); } @Override @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) public PointerBase getThreadPointer(ucontext_t uContext) { - GregsPointer regs = uContext.uc_mcontext().regs(); + GregsPointer regs = uContext.uc_mcontext_linux_aarch64().regs(); return WordFactory.pointer(regs.read(28)); } @Override public PointerBase getSP(ucontext_t uContext) { - mcontext_t sigcontext = uContext.uc_mcontext(); + mcontext_linux_aarch64_t sigcontext = uContext.uc_mcontext_linux_aarch64(); return WordFactory.pointer(sigcontext.sp()); } @Override public PointerBase getIP(ucontext_t uContext) { - mcontext_t sigcontext = uContext.uc_mcontext(); + mcontext_linux_aarch64_t sigcontext = uContext.uc_mcontext_linux_aarch64(); return WordFactory.pointer(sigcontext.pc()); } } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinUContextRegisterDumper.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64DarwinUContextRegisterDumper.java similarity index 88% rename from substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinUContextRegisterDumper.java rename to substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64DarwinUContextRegisterDumper.java index d3005a855363..ee6a6b101245 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinUContextRegisterDumper.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64DarwinUContextRegisterDumper.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.posix.darwin; +package com.oracle.svm.core.posix.amd64; import static com.oracle.svm.core.RegisterDumper.dumpReg; @@ -45,21 +45,21 @@ import jdk.vm.ci.amd64.AMD64; -@Platforms({Platform.DARWIN.class}) +@Platforms({Platform.DARWIN_AMD64.class}) @AutomaticFeature -class DarwinUContextRegisterDumperFeature implements Feature { +class AMD64DarwinUContextRegisterDumperFeature implements Feature { @Override public void afterRegistration(AfterRegistrationAccess access) { VMError.guarantee(AMD64.r14.equals(AMD64ReservedRegisters.HEAP_BASE_REGISTER_CANDIDATE)); VMError.guarantee(AMD64.r15.equals(AMD64ReservedRegisters.THREAD_REGISTER_CANDIDATE)); - ImageSingletons.add(RegisterDumper.class, new DarwinUContextRegisterDumper()); + ImageSingletons.add(RegisterDumper.class, new AMD64DarwinUContextRegisterDumper()); } } -class DarwinUContextRegisterDumper implements UContextRegisterDumper { +class AMD64DarwinUContextRegisterDumper implements UContextRegisterDumper { @Override public void dumpRegisters(Log log, ucontext_t uContext, boolean printLocationInfo, boolean allowJavaHeapAccess, boolean allowUnsafeOperations) { - Signal.MContext64 sigcontext = uContext.uc_mcontext64(); + Signal.AMD64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_amd64(); dumpReg(log, "RAX ", ((Pointer) sigcontext).readLong(sigcontext.rax_offset()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); dumpReg(log, "RBX ", ((Pointer) sigcontext).readLong(sigcontext.rbx_offset()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); dumpReg(log, "RCX ", ((Pointer) sigcontext).readLong(sigcontext.rcx_offset()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); @@ -83,26 +83,26 @@ public void dumpRegisters(Log log, ucontext_t uContext, boolean printLocationInf @Override @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) public PointerBase getHeapBase(ucontext_t uContext) { - Signal.MContext64 sigcontext = uContext.uc_mcontext64(); + Signal.AMD64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_amd64(); return ((Pointer) sigcontext).readWord(sigcontext.r14_offset()); } @Override @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) public PointerBase getThreadPointer(ucontext_t uContext) { - Signal.MContext64 sigcontext = uContext.uc_mcontext64(); + Signal.AMD64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_amd64(); return ((Pointer) sigcontext).readWord(sigcontext.r15_offset()); } @Override public PointerBase getSP(ucontext_t uContext) { - Signal.MContext64 sigcontext = uContext.uc_mcontext64(); + Signal.AMD64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_amd64(); return ((Pointer) sigcontext).readWord(sigcontext.rsp_offset()); } @Override public PointerBase getIP(ucontext_t uContext) { - Signal.MContext64 sigcontext = uContext.uc_mcontext64(); + Signal.AMD64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_amd64(); return ((Pointer) sigcontext).readWord(sigcontext.rip_offset()); } } 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 new file mode 100644 index 000000000000..ca6a660c6bb9 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64LinuxUContextRegisterDumper.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018, 2019, 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.core.posix.amd64; + +import static com.oracle.svm.core.RegisterDumper.dumpReg; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.word.PointerBase; +import org.graalvm.word.WordFactory; + +import com.oracle.svm.core.RegisterDumper; +import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.graal.amd64.AMD64ReservedRegisters; +import com.oracle.svm.core.log.Log; +import com.oracle.svm.core.posix.UContextRegisterDumper; +import com.oracle.svm.core.posix.headers.Signal.GregEnumLinuxAMD64; +import com.oracle.svm.core.posix.headers.Signal.GregsPointer; +import com.oracle.svm.core.posix.headers.Signal.ucontext_t; +import com.oracle.svm.core.util.VMError; + +import jdk.vm.ci.amd64.AMD64; + +@Platforms({Platform.LINUX_AMD64.class}) +@AutomaticFeature +class AMD64LinuxUContextRegisterDumperFeature implements Feature { + @Override + public void afterRegistration(AfterRegistrationAccess access) { + VMError.guarantee(AMD64.r14.equals(AMD64ReservedRegisters.HEAP_BASE_REGISTER_CANDIDATE)); + VMError.guarantee(AMD64.r15.equals(AMD64ReservedRegisters.THREAD_REGISTER_CANDIDATE)); + ImageSingletons.add(RegisterDumper.class, new AMD64LinuxUContextRegisterDumper()); + } +} + +class AMD64LinuxUContextRegisterDumper implements UContextRegisterDumper { + @Override + public void dumpRegisters(Log log, ucontext_t uContext, boolean printLocationInfo, boolean allowJavaHeapAccess, boolean allowUnsafeOperations) { + GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs(); + dumpReg(log, "RAX ", gregs.read(GregEnumLinuxAMD64.REG_RAX()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "RBX ", gregs.read(GregEnumLinuxAMD64.REG_RBX()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "RCX ", gregs.read(GregEnumLinuxAMD64.REG_RCX()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "RDX ", gregs.read(GregEnumLinuxAMD64.REG_RDX()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "RBP ", gregs.read(GregEnumLinuxAMD64.REG_RBP()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "RSI ", gregs.read(GregEnumLinuxAMD64.REG_RSI()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "RDI ", gregs.read(GregEnumLinuxAMD64.REG_RDI()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "RSP ", gregs.read(GregEnumLinuxAMD64.REG_RSP()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R8 ", gregs.read(GregEnumLinuxAMD64.REG_R8()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R9 ", gregs.read(GregEnumLinuxAMD64.REG_R9()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R10 ", gregs.read(GregEnumLinuxAMD64.REG_R10()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R11 ", gregs.read(GregEnumLinuxAMD64.REG_R11()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R12 ", gregs.read(GregEnumLinuxAMD64.REG_R12()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R13 ", gregs.read(GregEnumLinuxAMD64.REG_R13()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R14 ", gregs.read(GregEnumLinuxAMD64.REG_R14()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "R15 ", gregs.read(GregEnumLinuxAMD64.REG_R15()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "EFL ", gregs.read(GregEnumLinuxAMD64.REG_EFL()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + dumpReg(log, "RIP ", gregs.read(GregEnumLinuxAMD64.REG_RIP()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); + } + + @Override + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true, calleeMustBe = false) + 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) + public PointerBase getThreadPointer(ucontext_t uContext) { + GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs(); + return WordFactory.pointer(gregs.read(GregEnumLinuxAMD64.REG_R15())); + } + + @Override + public PointerBase getSP(ucontext_t uContext) { + GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs(); + return WordFactory.pointer(gregs.read(GregEnumLinuxAMD64.REG_RSP())); + } + + @Override + public PointerBase getIP(ucontext_t uContext) { + GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs(); + return WordFactory.pointer(gregs.read(GregEnumLinuxAMD64.REG_RIP())); + } +} diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64UContextRegisterDumper.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64UContextRegisterDumper.java deleted file mode 100644 index a4c6a205dd14..000000000000 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/amd64/AMD64UContextRegisterDumper.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2018, 2019, 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.core.posix.amd64; - -import static com.oracle.svm.core.RegisterDumper.dumpReg; - -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.hosted.Feature; -import org.graalvm.word.PointerBase; -import org.graalvm.word.WordFactory; - -import com.oracle.svm.core.RegisterDumper; -import com.oracle.svm.core.annotate.AutomaticFeature; -import com.oracle.svm.core.annotate.Uninterruptible; -import com.oracle.svm.core.graal.amd64.AMD64ReservedRegisters; -import com.oracle.svm.core.log.Log; -import com.oracle.svm.core.posix.UContextRegisterDumper; -import com.oracle.svm.core.posix.headers.Signal.GregEnum; -import com.oracle.svm.core.posix.headers.Signal.GregsPointer; -import com.oracle.svm.core.posix.headers.Signal.ucontext_t; -import com.oracle.svm.core.util.VMError; - -import jdk.vm.ci.amd64.AMD64; - -@Platforms({Platform.LINUX_AMD64.class}) -@AutomaticFeature -class AMD64UContextRegisterDumperFeature implements Feature { - @Override - public void afterRegistration(AfterRegistrationAccess access) { - VMError.guarantee(AMD64.r14.equals(AMD64ReservedRegisters.HEAP_BASE_REGISTER_CANDIDATE)); - VMError.guarantee(AMD64.r15.equals(AMD64ReservedRegisters.THREAD_REGISTER_CANDIDATE)); - ImageSingletons.add(RegisterDumper.class, new AMD64UContextRegisterDumper()); - } -} - -class AMD64UContextRegisterDumper implements UContextRegisterDumper { - @Override - public void dumpRegisters(Log log, ucontext_t uContext, boolean printLocationInfo, boolean allowJavaHeapAccess, boolean allowUnsafeOperations) { - GregsPointer gregs = uContext.uc_mcontext_gregs(); - dumpReg(log, "RAX ", gregs.read(GregEnum.REG_RAX()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "RBX ", gregs.read(GregEnum.REG_RBX()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "RCX ", gregs.read(GregEnum.REG_RCX()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "RDX ", gregs.read(GregEnum.REG_RDX()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "RBP ", gregs.read(GregEnum.REG_RBP()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "RSI ", gregs.read(GregEnum.REG_RSI()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "RDI ", gregs.read(GregEnum.REG_RDI()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "RSP ", gregs.read(GregEnum.REG_RSP()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "R8 ", gregs.read(GregEnum.REG_R8()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "R9 ", gregs.read(GregEnum.REG_R9()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "R10 ", gregs.read(GregEnum.REG_R10()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "R11 ", gregs.read(GregEnum.REG_R11()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "R12 ", gregs.read(GregEnum.REG_R12()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "R13 ", gregs.read(GregEnum.REG_R13()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "R14 ", gregs.read(GregEnum.REG_R14()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "R15 ", gregs.read(GregEnum.REG_R15()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "EFL ", gregs.read(GregEnum.REG_EFL()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - dumpReg(log, "RIP ", gregs.read(GregEnum.REG_RIP()), printLocationInfo, allowJavaHeapAccess, allowUnsafeOperations); - } - - @Override - @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true, calleeMustBe = false) - public PointerBase getHeapBase(ucontext_t uContext) { - GregsPointer gregs = uContext.uc_mcontext_gregs(); - return WordFactory.pointer(gregs.read(GregEnum.REG_R14())); - } - - @Override - @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true, calleeMustBe = false) - public PointerBase getThreadPointer(ucontext_t uContext) { - GregsPointer gregs = uContext.uc_mcontext_gregs(); - return WordFactory.pointer(gregs.read(GregEnum.REG_R15())); - } - - @Override - public PointerBase getSP(ucontext_t uContext) { - GregsPointer gregs = uContext.uc_mcontext_gregs(); - return WordFactory.pointer(gregs.read(GregEnum.REG_RSP())); - } - - @Override - public PointerBase getIP(ucontext_t uContext) { - GregsPointer gregs = uContext.uc_mcontext_gregs(); - return WordFactory.pointer(gregs.read(GregEnum.REG_RIP())); - } -} diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Signal.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Signal.java index d73b4df2b867..c469a16d391a 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Signal.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Signal.java @@ -110,19 +110,149 @@ public interface siginfo_t extends PointerBase { VoidPointer si_addr(); } - @Platforms(Platform.LINUX.class) + @Platforms({Platform.LINUX.class, Platform.DARWIN_AARCH64.class, Platform.IOS_AARCH64.class}) @CPointerTo(nameOfCType = "long long int") public interface GregsPointer extends PointerBase { long read(int index); } + @CStruct + public interface ucontext_t extends RegisterDumper.Context { + @CFieldAddress("uc_mcontext.gregs") + @Platforms({Platform.LINUX_AMD64.class}) + GregsPointer uc_mcontext_linux_amd64_gregs(); + + @CFieldAddress("uc_mcontext") + @Platforms({Platform.LINUX_AARCH64.class, Platform.ANDROID_AARCH64.class}) + mcontext_linux_aarch64_t uc_mcontext_linux_aarch64(); + + @CField("uc_mcontext") + @Platforms({Platform.DARWIN_AMD64.class}) + AMD64DarwinMContext64 uc_mcontext_darwin_amd64(); + + @CField("uc_mcontext") + @Platforms({Platform.DARWIN_AARCH64.class, Platform.IOS_AARCH64.class}) + AArch64DarwinMContext64 uc_mcontext_darwin_aarch64(); + } + + public interface AdvancedSignalDispatcher extends CFunctionPointer { + @InvokeCFunctionPointer + void dispatch(int signum, siginfo_t siginfo, WordPointer opaque); + } + + @CConstant + public static native int SA_RESTART(); + + @CConstant + public static native int SA_SIGINFO(); + + @CConstant + public static native int SA_NODEFER(); + + @CStruct(addStructKeyword = true) + public interface sigaction extends PointerBase { + @CField + SignalDispatcher sa_handler(); + + @CField + void sa_handler(SignalDispatcher value); + + @CField + AdvancedSignalDispatcher sa_sigaction(); + + @CField + void sa_sigaction(AdvancedSignalDispatcher value); + + @CField + int sa_flags(); + + @CField + void sa_flags(int value); + + @CFieldAddress + sigset_tPointer sa_mask(); + } + + /** @param signum from {@link SignalEnum#getCValue()} */ + @CFunction + public static native int sigaction(int signum, sigaction act, sigaction oldact); + + @CEnum + @CContext(PosixDirectives.class) + public enum SignalEnum { + SIGABRT, + SIGALRM, + SIGBUS, + SIGCHLD, + SIGCONT, + SIGFPE, + SIGHUP, + SIGILL, + SIGINT, + SIGIO, + SIGIOT, + SIGKILL, + SIGPIPE, + SIGPROF, + SIGQUIT, + SIGSEGV, + SIGSTOP, + SIGSYS, + SIGTERM, + SIGTRAP, + SIGTSTP, + SIGTTIN, + SIGTTOU, + SIGURG, + SIGUSR1, + SIGUSR2, + SIGVTALRM, + SIGWINCH, + SIGXCPU, + SIGXFSZ; + + @CEnumValue + public native int getCValue(); + } + + @Platforms(Platform.LINUX.class) + @CEnum + @CContext(PosixDirectives.class) + public enum LinuxSignalEnum { + SIGPOLL, + SIGPWR; + + @CEnumValue + public native int getCValue(); + } + + @Platforms(Platform.DARWIN.class) + @CEnum + @CContext(PosixDirectives.class) + public enum DarwinSignalEnum { + SIGINFO, + SIGEMT; + + @CEnumValue + public native int getCValue(); + } + + @CFunction + public static native int sigemptyset(sigset_tPointer set); + + @CFunction + public static native int sigaddset(sigset_tPointer set, int signum); + /** * Used in {@link SubstrateSegfaultHandler}. So, this must not be a {@link CEnum} as this would * result in machine code that needs a proper a heap base. + * + * Information about Linux's AMD64 struct sigcontext_64 uc_mcontext can be found at + * https://github.com/torvalds/linux/blob/9e1ff307c779ce1f0f810c7ecce3d95bbae40896/arch/x86/include/uapi/asm/sigcontext.h#L238 */ @Platforms({Platform.LINUX_AMD64.class}) @CContext(PosixDirectives.class) - public static final class GregEnum { + public static final class GregEnumLinuxAMD64 { @CConstant public static native int REG_R8(); @@ -193,25 +323,39 @@ public static final class GregEnum { public static native int REG_CR2(); } - @CStruct - public interface ucontext_t extends RegisterDumper.Context { - @CFieldAddress("uc_mcontext.gregs") - @Platforms({Platform.LINUX_AMD64.class}) - GregsPointer uc_mcontext_gregs(); + /** + * Information about Linux's AArch64 struct sigcontext uc_mcontext can be found at + * https://github.com/torvalds/linux/blob/9e1ff307c779ce1f0f810c7ecce3d95bbae40896/arch/arm64/include/uapi/asm/sigcontext.h#L28 + */ + @CStruct(value = "mcontext_t") + @Platforms({Platform.LINUX_AARCH64.class, Platform.ANDROID_AARCH64.class}) + public interface mcontext_linux_aarch64_t extends PointerBase { + @CField + long fault_address(); - @CFieldAddress("uc_mcontext") - @Platforms({Platform.LINUX_AARCH64.class, Platform.ANDROID_AARCH64.class}) - mcontext_t uc_mcontext(); + @CFieldAddress + GregsPointer regs(); - @CField("uc_mcontext") - @Platforms({Platform.DARWIN.class}) - MContext64 uc_mcontext64(); + @CField + long sp(); + + @CField + long pc(); + + @CField + long pstate(); } - @Platforms({Platform.DARWIN.class}) + /** + * Information about Darwin's AMD64 mcontext64 can be found at + * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/i386/_mcontext.h#L147 + * + * Information about _STRUCT_X86_THREAD_STATE64 can be found at + * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/osfmk/mach/i386/_structs.h#L739 + */ + @Platforms({Platform.DARWIN_AMD64.class}) @CStruct(value = "__darwin_mcontext64", addStructKeyword = true) - public interface MContext64 extends PointerBase { - + public interface AMD64DarwinMContext64 extends PointerBase { @CFieldOffset("__ss.__rax") int rax_offset(); @@ -267,130 +411,30 @@ public interface MContext64 extends PointerBase { int efl_offset(); } - @CStruct - @Platforms({Platform.LINUX_AARCH64.class, Platform.ANDROID_AARCH64.class}) - public interface mcontext_t extends PointerBase { - @CField - long fault_address(); - - @CFieldAddress + /** + * Information about Darwin's AArch64 mcontext64 can be found at + * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/arm/_mcontext.h#L70 + * + * Information about _STRUCT_ARM_THREAD_STATE64 can be found at + * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/osfmk/mach/arm/_structs.h#L102 + */ + @Platforms({Platform.DARWIN_AARCH64.class, Platform.IOS_AARCH64.class}) + @CStruct(value = "__darwin_mcontext64", addStructKeyword = true) + public interface AArch64DarwinMContext64 extends PointerBase { + @CFieldAddress("__ss.__x") GregsPointer regs(); - @CField - long sp(); - - @CField - long pc(); - - @CField - long pstate(); - } - - public interface AdvancedSignalDispatcher extends CFunctionPointer { - @InvokeCFunctionPointer - void dispatch(int signum, siginfo_t siginfo, WordPointer opaque); - } - - @CConstant - public static native int SA_RESTART(); - - @CConstant - public static native int SA_SIGINFO(); - - @CConstant - public static native int SA_NODEFER(); - - @CStruct(addStructKeyword = true) - public interface sigaction extends PointerBase { - @CField - SignalDispatcher sa_handler(); - - @CField - void sa_handler(SignalDispatcher value); - - @CField - AdvancedSignalDispatcher sa_sigaction(); + @CField("__ss.__fp") + long fp(); - @CField - void sa_sigaction(AdvancedSignalDispatcher value); - - @CField - int sa_flags(); + @CField("__ss.__lr") + long lr(); - @CField - void sa_flags(int value); - - @CFieldAddress - sigset_tPointer sa_mask(); - } - - /** @param signum from {@link SignalEnum#getCValue()} */ - @CFunction - public static native int sigaction(int signum, sigaction act, sigaction oldact); - - @CEnum - @CContext(PosixDirectives.class) - public enum SignalEnum { - SIGABRT, - SIGALRM, - SIGBUS, - SIGCHLD, - SIGCONT, - SIGFPE, - SIGHUP, - SIGILL, - SIGINT, - SIGIO, - SIGIOT, - SIGKILL, - SIGPIPE, - SIGPROF, - SIGQUIT, - SIGSEGV, - SIGSTOP, - SIGSYS, - SIGTERM, - SIGTRAP, - SIGTSTP, - SIGTTIN, - SIGTTOU, - SIGURG, - SIGUSR1, - SIGUSR2, - SIGVTALRM, - SIGWINCH, - SIGXCPU, - SIGXFSZ; - - @CEnumValue - public native int getCValue(); - } - - @Platforms(Platform.LINUX.class) - @CEnum - @CContext(PosixDirectives.class) - public enum LinuxSignalEnum { - SIGPOLL, - SIGPWR; - - @CEnumValue - public native int getCValue(); - } - - @Platforms(Platform.DARWIN.class) - @CEnum - @CContext(PosixDirectives.class) - public enum DarwinSignalEnum { - SIGINFO, - SIGEMT; + @CField("__ss.__sp") + long sp(); - @CEnumValue - public native int getCValue(); + @CField("__ss.__pc") + long pc(); } - @CFunction - public static native int sigemptyset(sigset_tPointer set); - - @CFunction - public static native int sigaddset(sigset_tPointer set, int signum); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java index f2ddc74f7c7d..b32d97e584a0 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java @@ -258,10 +258,10 @@ protected void verify() { Class substrateTargetArch = ImageSingletons.lookup(SubstrateTargetDescription.class).arch.getClass(); Class guessed = guessArchitecture(compilerInfo.targetArch); if (guessed == null) { - UserError.abort("Native toolchain (%s) has no matching native-image target architecture.", compilerInfo.targetArch); + UserError.abort("Linux native toolchain (%s) has no matching native-image target architecture.", compilerInfo.targetArch); } if (guessed != substrateTargetArch) { - UserError.abort("Native toolchain (%s) implies native-image target architecture %s but configured native-image target architecture is %s.", + UserError.abort("Linux native toolchain (%s) implies native-image target architecture %s but configured native-image target architecture is %s.", compilerInfo.targetArch, guessed, substrateTargetArch); } } @@ -302,9 +302,14 @@ protected CompilerInfo createCompilerInfo(Path compilerPath, Scanner scanner) { @Override protected void verify() { - if (guessArchitecture(compilerInfo.targetArch) != AMD64.class) { - UserError.abort("Native-image building on Darwin currently only supports target architecture: %s (%s unsupported)", - AMD64.class.getSimpleName(), compilerInfo.targetArch); + Class substrateTargetArch = ImageSingletons.lookup(SubstrateTargetDescription.class).arch.getClass(); + Class guessed = guessArchitecture(compilerInfo.targetArch); + if (guessed == null) { + UserError.abort("Darwin native toolchain (%s) has no matching native-image target architecture.", compilerInfo.targetArch); + } + if (guessed != substrateTargetArch) { + UserError.abort("Darwin native toolchain (%s) implies native-image target architecture %s but configured native-image target architecture is %s.", + compilerInfo.targetArch, guessed, substrateTargetArch); } } @@ -427,6 +432,7 @@ protected static Class guessArchitecture(String archStr) case "x64": /* Windows notation */ return AMD64.class; case "aarch64": + case "arm64": /* Darwin notation */ return AArch64.class; case "i686": case "80x86": /* Windows notation */ From 1b56a183092d77c9b764d3dbe00058ba21af7e3a Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Mon, 4 Oct 2021 19:46:30 +0200 Subject: [PATCH 434/681] Reserve register on Darwin AArch64. --- .../graal/aarch64/SubstrateAArch64RegisterConfig.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64RegisterConfig.java b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64RegisterConfig.java index d8990cb864bf..b39ba697c41c 100755 --- a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64RegisterConfig.java +++ b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64RegisterConfig.java @@ -28,6 +28,7 @@ import static jdk.vm.ci.aarch64.AArch64.allRegisters; import static jdk.vm.ci.aarch64.AArch64.r0; import static jdk.vm.ci.aarch64.AArch64.r1; +import static jdk.vm.ci.aarch64.AArch64.r18; import static jdk.vm.ci.aarch64.AArch64.r19; import static jdk.vm.ci.aarch64.AArch64.r2; import static jdk.vm.ci.aarch64.AArch64.r20; @@ -68,6 +69,7 @@ import java.util.ArrayList; +import com.oracle.svm.core.OS; import com.oracle.svm.core.ReservedRegisters; import com.oracle.svm.core.config.ObjectLayout; import com.oracle.svm.core.graal.code.SubstrateCallingConvention; @@ -138,6 +140,13 @@ public SubstrateAArch64RegisterConfig(ConfigKind config, MetaAccessProvider meta */ regs.remove(ReservedRegisters.singleton().getHeapBaseRegister()); regs.remove(ReservedRegisters.singleton().getThreadRegister()); + /* + * Darwin specifies that r18 is a platform-reserved register: + * https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms + */ + if (OS.getCurrent() == OS.DARWIN) { + regs.remove(r18); + } allocatableRegs = new RegisterArray(regs); switch (config) { From 8dcf51febac87c9cc60d320b56c1d7cce9e8121b Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Mon, 4 Oct 2021 19:57:56 +0200 Subject: [PATCH 435/681] Add CPUFeature detection for darwin aarch64. --- .../src/cpuid.c | 54 ++++++++++++++++--- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c b/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c index 61fbc311b0ed..1c63fe3ae3af 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c +++ b/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c @@ -25,8 +25,8 @@ #if defined(__x86_64__) || defined(_WIN64) -#include -#include +#include +#include #include "amd64cpufeatures.h" #include "amd64hotspotcpuinfo.h" @@ -550,17 +550,56 @@ void determineCPUFeatures(CPUFeatures *features) #elif defined(__aarch64__) -#include -#include -#include -#include -#include +/* + * The corresponding HotSpot code can be found in vm_version_bsd_aarch64. + */ +#if defined(__APPLE__) + +#include +#include #include "aarch64cpufeatures.h" +static uint32_t cpu_has(const char* optional) { + uint32_t val; + size_t len = sizeof(val); + if (sysctlbyname(optional, &val, &len, NULL, 0)) { + return 0; + } + return val; +} + +void determineCPUFeatures(CPUFeatures* features) { + features->fFP = !!(cpu_has("hw.optional.floatingpoint")); + features->fASIMD = !!(cpu_has("hw.optional.neon")); + features->fEVTSTRM = 0; + features->fAES = 0; + features->fPMULL = 0; + features->fSHA1 = 0; + features->fSHA2 = 0; + features->fCRC32 = !!(cpu_has("hw.optional.armv8_crc32")); + features->fLSE = !!(cpu_has("hw.optional.armv8_1_atomics")); + features->fDCPOP = 0; + features->fSHA3 = 0; + features->fSHA512 = 0; + features->fSVE = 0; + features->fSVE2 = 0; + features->fSTXRPREFETCH = 0; + features->fA53MAC = 0; + features->fDMBATOMICS = 0; +} + /* * The corresponding HotSpot code can be found in vm_version_aarch64 and * vm_version_linux_aarch64. */ +#elif defined(__linux__) + +#include +#include +#include +#include +#include +#include "aarch64cpufeatures.h" #ifndef HWCAP_FP #define HWCAP_FP (1L << 0) @@ -675,6 +714,7 @@ void determineCPUFeatures(CPUFeatures* features) { if (_cpu == CPU_CAVIUM && _model == 0xA1 && _variant == 0) features->fDMBATOMICS = 1; } +#endif #else /* From 9dc465f42a699600057439e7c1cbdf6ca2b11a5d Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Tue, 12 Oct 2021 16:20:05 +0200 Subject: [PATCH 436/681] Remember previous options to reinitialize the isolate if needed. --- .../LibGraalHotSpotTruffleCompiler.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalHotSpotTruffleCompiler.java b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalHotSpotTruffleCompiler.java index b17238329ec9..423c0f8ba73a 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalHotSpotTruffleCompiler.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalHotSpotTruffleCompiler.java @@ -59,6 +59,7 @@ static final class Handle extends LibGraalObject { private final ThreadLocal activeCompilation = new ThreadLocal<>(); private final LibGraalTruffleRuntime runtime; + private volatile Map previousOptions; private long handle(Supplier> optionsSupplier, CompilableTruffleAST compilable, boolean firstInitialization) { return handleImpl(() -> { @@ -92,6 +93,14 @@ private static long handleImpl(Supplier handleSupplier) { @SuppressWarnings("try") @Override public void initialize(Map options, CompilableTruffleAST compilable, boolean firstInitialization) { + /* + * There can only be a single set of options a compiler can be configured with. The first + * Truffle engine of a process typically initializes the compiler which also determines the + * compiler configuration. Any options specified after that will be ignored. So it is safe + * to store the previous options here and reuse later for recreating a disposed isolate if + * needed. + */ + previousOptions = options; // Force installation of the Truffle call boundary methods. // See AbstractHotSpotTruffleRuntime.setDontInlineCallBoundaryMethod // for further details. @@ -144,7 +153,9 @@ public void shutdown() { @SuppressWarnings("try") public void installTruffleCallBoundaryMethod(ResolvedJavaMethod method) { try (LibGraalScope scope = new LibGraalScope(LibGraalScope.DetachAction.DETACH_RUNTIME_AND_RELEASE)) { - TruffleToLibGraalCalls.installTruffleCallBoundaryMethod(getIsolateThread(), handle(), LibGraal.translate(method)); + Map options = previousOptions; + assert options != null : "truffle compiler was never initialized"; + TruffleToLibGraalCalls.installTruffleCallBoundaryMethod(getIsolateThread(), handle(options, null), LibGraal.translate(method)); } } @@ -152,7 +163,9 @@ public void installTruffleCallBoundaryMethod(ResolvedJavaMethod method) { @SuppressWarnings("try") public void installTruffleReservedOopMethod(ResolvedJavaMethod method) { try (LibGraalScope scope = new LibGraalScope(LibGraalScope.DetachAction.DETACH_RUNTIME_AND_RELEASE)) { - TruffleToLibGraalCalls.installTruffleReservedOopMethod(getIsolateThread(), handle(), LibGraal.translate(method)); + Map options = previousOptions; + assert options != null : "truffle compiler was never initialized"; + TruffleToLibGraalCalls.installTruffleReservedOopMethod(getIsolateThread(), handle(options, null), LibGraal.translate(method)); } } From 078769fa0241dd736d1c972cb5256dcaa8e5b990 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Tue, 12 Oct 2021 16:39:58 +0200 Subject: [PATCH 437/681] mx eclipseformat. --- .../isolated/IsolatedTruffleCompilerEventForwarder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java index 464c1f797cef..3ee487c86458 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/isolated/IsolatedTruffleCompilerEventForwarder.java @@ -124,7 +124,8 @@ private static void onFailure0(@SuppressWarnings("unused") ClientIsolateThread c @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class) @CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished) - private static void onCompilationRetry0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle contextHandle, @SuppressWarnings("unused") ClientHandle task) { + private static void onCompilationRetry0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle contextHandle, + @SuppressWarnings("unused") ClientHandle task) { IsolatedEventContext context = IsolatedCompileClient.get().unhand(contextHandle); context.listener.onCompilationRetry(context.compilable, context.task); } From 2d3e6016d1ce2935e46e93a0a9a0636a05e61740 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Tue, 12 Oct 2021 15:10:33 +0200 Subject: [PATCH 438/681] New formatting for tracing. --- .../runtime/GraalTruffleRuntimeListener.java | 6 +- .../debug/TraceCompilationListener.java | 74 +++++++++++++------ 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java index 1aad23ad9cac..c0671be40338 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListener.java @@ -127,11 +127,7 @@ default void onCompilationStarted(OptimizedCallTarget target, int tier) { * Notifies this object when compilation of {@code target} is about to start. * * @param target the call target about to be compiled - * @param tier which compilation tier is in question. - * @param weight the parameter by which we choose this compilation among others form the queue. - * @param rate the dynamic component that contributes to weight. - * @param queueChange how has starting this compilation impacted the number of compilations in - * the queue. + * @param task which compilation task is in question. */ @SuppressWarnings({"unused", "deprecated"}) default void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) { diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java index 633127f71d48..e030f2ee385d 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/debug/TraceCompilationListener.java @@ -56,17 +56,18 @@ public static void install(GraalTruffleRuntime runtime) { runtime.addListener(new TraceCompilationListener(runtime)); } - public static final String TIER_FORMAT = " Tier %d "; - private static final String QUEUE_FORMAT = "Queue: Size %4d Change %c%-2d Scale %5.2f Elapsed %4dus "; + public static final String TIER_FORMAT = "Tier %d"; + private static final String QUEUE_FORMAT = "Queue: Size %4d Change %c%-2d Load %5.2f Time %5dus"; private static final String TARGET_FORMAT = "id=%-5d %-50s "; + public static final String COUNT_THRESHOLD_FORMAT = "Count/Thres %9d/%9d"; // @formatter:off - private static final String QUEUED_FORMAT = "opt queued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Src %s | Time %d"; - private static final String UNQUEUED_FORMAT = "opt unqueued " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Count/Thres %8d/%8d | " + QUEUE_FORMAT + "| Reason: %s | Src %s | Time %d"; - private static final String START_FORMAT = "opt start " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Weight %8d | Rate %.5f | " + QUEUE_FORMAT + "| Src %s | Time %d"; - private static final String DONE_FORMAT = "opt done " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Src %s | Time %d"; - private static final String FAILED_FORMAT = "opt failed " + TARGET_FORMAT + "|" + TIER_FORMAT + "| Elapsed %22s | Reason: %s | Src %s | Time %d"; - private static final String INV_FORMAT = "opt inv " + TARGET_FORMAT + "| Reason %s | Src %s | Time %d"; - private static final String DEOPT_FORMAT = "opt deopt " + TARGET_FORMAT + "| Src %s | Time %d"; + private static final String QUEUED_FORMAT = "opt queued " + TARGET_FORMAT + "|" + TIER_FORMAT + "|" + COUNT_THRESHOLD_FORMAT + "|" + QUEUE_FORMAT + "|Timestamp %d|Src %s"; + private static final String UNQUEUED_FORMAT = "opt unque. " + TARGET_FORMAT + "|" + TIER_FORMAT + "|" + COUNT_THRESHOLD_FORMAT + "|" + QUEUE_FORMAT + "|Timestamp %d|Src %s|Reason %s"; + private static final String START_FORMAT = "opt start " + TARGET_FORMAT + "|" + TIER_FORMAT + "|Priority %9d|Rate %.6f|" + QUEUE_FORMAT + "|Timestamp %d|Src %s"; + private static final String DONE_FORMAT = "opt done " + TARGET_FORMAT + "|" + TIER_FORMAT + "|Time %18s|AST %4d|Inlined %3dY %3dN|IR %6d/%6d|CodeSize %7d|Timestamp %d|Src %s"; + private static final String FAILED_FORMAT = "opt failed " + TARGET_FORMAT + "|" + TIER_FORMAT + "|Time %18s|Reason: %s|Timestamp %d|Src %s"; + private static final String INV_FORMAT = "opt inval. " + TARGET_FORMAT + " |Timestamp %d|Src %s|Reason %s"; + private static final String DEOPT_FORMAT = "opt deopt " + TARGET_FORMAT + " |Timestamp %d|Src %s"; // @formatter:on @Override @@ -85,8 +86,8 @@ public void onCompilationQueued(OptimizedCallTarget target, int tier) { 1, FixedPointMath.toDouble(scale), 0, - formatSourceSection(target.getRootNode().getSourceSection()), - System.nanoTime())); + System.nanoTime(), + formatSourceSection(target.getRootNode().getSourceSection()))); } } @@ -106,9 +107,9 @@ public void onCompilationDequeued(OptimizedCallTarget target, Object source, Cha 0, FixedPointMath.toDouble(scale), 0, - reason, + System.nanoTime(), formatSourceSection(target.getRootNode().getSourceSection()), - System.nanoTime())); + reason)); } } @@ -124,8 +125,8 @@ public void onCompilationFailed(OptimizedCallTarget target, String reason, boole tier, compilationTime(), reason, - formatSourceSection(target.getRootNode().getSourceSection()), - System.nanoTime())); + System.nanoTime(), + formatSourceSection(target.getRootNode().getSourceSection()))); } currentCompilation.set(null); } @@ -145,8 +146,8 @@ public void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationT Math.abs(task.queueChange()), FixedPointMath.toDouble(runtime.compilationThresholdScale()), task.time() / 1000, - formatSourceSection(target.getRootNode().getSourceSection()), - System.nanoTime())); + System.nanoTime(), + formatSourceSection(target.getRootNode().getSourceSection()))); } if (target.engine.traceCompilation || target.engine.traceCompilationDetails) { @@ -164,8 +165,8 @@ public void onCompilationDeoptimized(OptimizedCallTarget target, Frame frame) { log(target, String.format(DEOPT_FORMAT, target.id, target.getName(), - formatSourceSection(target.getRootNode().getSourceSection()), - System.nanoTime())); + System.nanoTime(), + formatSourceSection(target.getRootNode().getSourceSection()))); } } @@ -183,16 +184,43 @@ public void onCompilationSuccess(OptimizedCallTarget target, TruffleInlining inl if (!target.engine.traceCompilation && !target.engine.traceCompilationDetails) { return; } + int[] inlinedAndDispatched = inlinedAndDispatched(target, inliningDecision); + Times compilation = currentCompilation.get(); log(target, String.format(DONE_FORMAT, target.id, target.getName(), tier, compilationTime(), - formatSourceSection(target.getRootNode().getSourceSection()), - System.nanoTime())); + target.getNonTrivialNodeCount(), + inlinedAndDispatched[0], + inlinedAndDispatched[1], + compilation.nodeCountPartialEval, + graph == null ? 0 : graph.getNodeCount(), + result == null ? 0 : result.getTargetCodeSize(), + System.nanoTime(), + formatSourceSection(target.getRootNode().getSourceSection()))); currentCompilation.set(null); } + private static int[] inlinedAndDispatched(OptimizedCallTarget target, TruffleInlining inliningDecision) { + int calls = 0; + int inlinedCalls; + if (inliningDecision == null) { + CallCountVisitor visitor = new CallCountVisitor(); + target.accept(visitor); + calls = visitor.calls; + inlinedCalls = 0; + } else { + calls = inliningDecision.countCalls(); + inlinedCalls = inliningDecision.countInlinedCalls(); + } + int dispatchedCalls = calls - inlinedCalls; + int[] inlinedAndDispatched = new int[2]; + inlinedAndDispatched[0] = inlinedCalls; + inlinedAndDispatched[1] = dispatchedCalls; + return inlinedAndDispatched; + } + private String compilationTime() { long timeCompilationFinished = System.nanoTime(); Times compilation = currentCompilation.get(); @@ -215,9 +243,9 @@ public void onCompilationInvalidated(OptimizedCallTarget target, Object source, log(target, String.format(INV_FORMAT, target.id, target.getName(), - reason, + System.nanoTime(), formatSourceSection(target.getRootNode().getSourceSection()), - System.nanoTime())); + reason)); } } From f2b57ae2a29332c83f4d2d47985c2250773ea5e0 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Tue, 12 Oct 2021 08:53:48 -0500 Subject: [PATCH 439/681] Update macOS 10.12 to 10.13 --- espresso/ci_common/common.jsonnet | 4 ++-- sulong/mx.sulong/suite.py | 6 +++--- vm/ci_common/common.hocon | 2 +- .../commands/license.ruby/jre/languages/ruby/README.md | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/espresso/ci_common/common.jsonnet b/espresso/ci_common/common.jsonnet index 8a2342c75db4..4c60f706718c 100644 --- a/espresso/ci_common/common.jsonnet +++ b/espresso/ci_common/common.jsonnet @@ -50,8 +50,8 @@ local benchmark_suites = ['dacapo', 'renaissance', 'scala-dacapo']; darwin: self.common + { environment+: { - // for compatibility with macOS Sierra - MACOSX_DEPLOYMENT_TARGET: '10.12', + // for compatibility with macOS High Sierra + MACOSX_DEPLOYMENT_TARGET: '10.13', }, capabilities: ['darwin', 'amd64'], }, diff --git a/sulong/mx.sulong/suite.py b/sulong/mx.sulong/suite.py index e9829b53129e..79e2f8365e05 100644 --- a/sulong/mx.sulong/suite.py +++ b/sulong/mx.sulong/suite.py @@ -653,7 +653,7 @@ "SULONG_BOOTSTRAP_TOOLCHAIN_NO_HOME", ], "cmakeConfig" : { - "CMAKE_OSX_DEPLOYMENT_TARGET" : "10.12", + "CMAKE_OSX_DEPLOYMENT_TARGET" : "10.13", "CMAKE_C_COMPILER" : "/bin/", "CMAKE_CXX_COMPILER" : "/bin/", "GRAALVM_LLVM_INCLUDE_DIR" : "/include", @@ -704,7 +704,7 @@ "com.oracle.truffle.llvm.libraries.graalvm.llvm", ], "cmakeConfig" : { - "CMAKE_OSX_DEPLOYMENT_TARGET" : "10.12", + "CMAKE_OSX_DEPLOYMENT_TARGET" : "10.13", "CMAKE_C_COMPILER" : "/bin/", "GRAALVM_LLVM_INCLUDE_DIR" : "/include", "LLVM_LINK" : "/bin/", @@ -729,7 +729,7 @@ "sdk:LLVM_TOOLCHAIN", ], "cmakeConfig" : { - "CMAKE_OSX_DEPLOYMENT_TARGET" : "10.12", + "CMAKE_OSX_DEPLOYMENT_TARGET" : "10.13", "CMAKE_C_COMPILER" : "/bin/", "TRUFFLE_NFI_NATIVE_INCLUDE" : "/include", "CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS" : "YES", diff --git a/vm/ci_common/common.hocon b/vm/ci_common/common.hocon index 745a324a577a..c9cf45498857 100644 --- a/vm/ci_common/common.hocon +++ b/vm/ci_common/common.hocon @@ -19,7 +19,7 @@ common_vm_darwin: ${common_vm} ${darwin} { environment: { LANG: en_US.UTF-8 # for compatibility with macOS Sierra - MACOSX_DEPLOYMENT_TARGET: "10.12" + MACOSX_DEPLOYMENT_TARGET: "10.13" } setup: ${common_vm.setup} } diff --git a/vm/src/org.graalvm.component.installer.test/src/org/graalvm/component/installer/commands/license.ruby/jre/languages/ruby/README.md b/vm/src/org.graalvm.component.installer.test/src/org/graalvm/component/installer/commands/license.ruby/jre/languages/ruby/README.md index b9a13a49f91a..9cec298cd331 100644 --- a/vm/src/org.graalvm.component.installer.test/src/org/graalvm/component/installer/commands/license.ruby/jre/languages/ruby/README.md +++ b/vm/src/org.graalvm.component.installer.test/src/org/graalvm/component/installer/commands/license.ruby/jre/languages/ruby/README.md @@ -46,7 +46,7 @@ TruffleRuby is actively tested on these systems: * Ubuntu 16.04 LTS * Fedora 26 -* macOS 10.12 +* macOS 10.13 You need to [install LLVM](doc/user/installing-llvm.md) to build and run C extensions and [`libssl`](doc/user/installing-libssl.md) to use `openssl`. You From 68c13d95c1c9dafc70f62c7f0bf5ce0e8b73dae2 Mon Sep 17 00:00:00 2001 From: "thomas.garcia" Date: Tue, 12 Oct 2021 17:06:06 +0200 Subject: [PATCH 440/681] Fix comment --- .../src/com/oracle/truffle/espresso/threads/ThreadsAccess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java index 9dd1a643052e..395e5d29592a 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/threads/ThreadsAccess.java @@ -443,7 +443,7 @@ void handleStop(Meta meta) { } else if (s == KILL) { throw new EspressoExitException(meta.getContext().getExitStatus()); } - // Stop status has been + // Stop status has been cleared somewhere else. assert s == NORMAL || s == EXITING; return; } From 87401b8f5c2d6015e395ed66b47af550d245588e Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 12 Oct 2021 19:08:48 +0200 Subject: [PATCH 441/681] Fix link --- .../graalvm-enterprise/get-started-graalvm-enterprise.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md index f7ea8016c2fd..90b61d5e0258 100644 --- a/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md +++ b/docs/getting-started/graalvm-enterprise/get-started-graalvm-enterprise.md @@ -196,7 +196,7 @@ ruby [options] program.rb ``` GraalVM Ruby runtime environment uses the -[same options as the standard implementation of Ruby](../../reference-manual/ruby/Options.md), +[same options as the standard implementation of Ruby](../../reference-manual/ruby/options.md), with some additions. For example: ```shell gem install chunky_png From df04e9d641403289010fb66e290ca80199eda0a4 Mon Sep 17 00:00:00 2001 From: David Kozak Date: Mon, 11 Oct 2021 16:39:41 +0200 Subject: [PATCH 442/681] move localization related code from com.oracle.svm.core to com.oracle.svm.hosted --- substratevm/mx.substratevm/suite.py | 11 +- .../Target_java_util_ResourceBundle.java | 2 +- .../Target_sun_util_resources_Bundles.java | 2 +- ...ContentSubstitutedLocalizationSupport.java | 10 +- .../jdk/localization/LocalizationFeature.java | 533 +---------------- .../jdk/localization/LocalizationSupport.java | 15 +- .../OptimizedLocalizationSupport.java | 10 +- .../substitutions/modes/JvmLocaleMode.java | 3 +- .../modes/OptimizedLocaleMode.java | 3 +- .../modes/SubstituteLoadLookup.java | 5 +- .../LocalizationFeatureJDK11OrLater.java | 4 +- .../hosted}/jdk8/LocalizationFeatureJDK8.java | 4 +- .../svm/hosted/NativeImageGenerator.java | 2 +- .../oracle/svm/hosted/ResourcesFeature.java | 2 +- .../CharsetSubstitutionsFeature.java | 2 +- .../jdk/localization/LocalizationFeature.java | 560 ++++++++++++++++++ 16 files changed, 619 insertions(+), 549 deletions(-) rename substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/{ => localization}/substitutions/Target_java_util_ResourceBundle.java (97%) rename substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/{ => substitutions}/Target_sun_util_resources_Bundles.java (97%) rename substratevm/src/{com.oracle.svm.core.jdk11/src/com/oracle/svm/core => com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted}/jdk11/localization/LocalizationFeatureJDK11OrLater.java (95%) rename substratevm/src/{com.oracle.svm.core.jdk8/src/com/oracle/svm/core => com.oracle.svm.hosted.jdk8/src/com/oracle/svm/hosted}/jdk8/LocalizationFeatureJDK8.java (93%) rename substratevm/src/{com.oracle.svm.core/src/com/oracle/svm/core => com.oracle.svm.hosted/src/com/oracle/svm/hosted}/jdk/localization/CharsetSubstitutionsFeature.java (97%) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index a5d6c42463ab..c1b7e79a15bf 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -405,8 +405,11 @@ "com.oracle.svm.core", "com.oracle.graal.pointsto", ], + "requiresConcealed": { + "java.base": ["sun.util.resources"], + }, "javaCompliance": "8+", - "checkstyleVersion" : "8.36.1", + "checkstyleVersion": "8.36.1", "annotationProcessors": [ "compiler:GRAAL_PROCESSOR", ], @@ -438,7 +441,11 @@ "requires" : ["java.instrument"], "requiresConcealed" : { "jdk.internal.vm.ci": ["jdk.vm.ci.meta"], - "java.base" : ["jdk.internal.module"], + "java.base": [ + "jdk.internal.module", + "sun.text.spi", + "sun.util.resources" + ], }, "javaCompliance": "11+", "checkstyle" : "com.oracle.svm.hosted", diff --git a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/substitutions/Target_java_util_ResourceBundle.java b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/substitutions/Target_java_util_ResourceBundle.java similarity index 97% rename from substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/substitutions/Target_java_util_ResourceBundle.java rename to substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/substitutions/Target_java_util_ResourceBundle.java index 12a6b1459b19..a6b5f95b2b17 100644 --- a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/substitutions/Target_java_util_ResourceBundle.java +++ b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/substitutions/Target_java_util_ResourceBundle.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.jdk11.substitutions; +package com.oracle.svm.core.jdk11.localization.substitutions; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; diff --git a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/Target_sun_util_resources_Bundles.java b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/substitutions/Target_sun_util_resources_Bundles.java similarity index 97% rename from substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/Target_sun_util_resources_Bundles.java rename to substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/substitutions/Target_sun_util_resources_Bundles.java index e51e8a004f10..a30c9a5b4524 100644 --- a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/Target_sun_util_resources_Bundles.java +++ b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/substitutions/Target_sun_util_resources_Bundles.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.jdk11.localization; +package com.oracle.svm.core.jdk11.localization.substitutions; import java.util.Locale; import java.util.ResourceBundle; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java index ea7742149315..b46692dd9afd 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java @@ -42,6 +42,7 @@ import com.oracle.svm.core.jdk.localization.bundles.StoredBundle; import com.oracle.svm.core.jdk.localization.compression.GzipBundleCompression; import com.oracle.svm.core.util.UserError; +import com.oracle.svm.core.jdk.localization.compression.utils.BundleSerializationUtils; import org.graalvm.compiler.debug.GraalError; // Checkstyle: stop @@ -51,8 +52,6 @@ import sun.util.resources.ParallelListResourceBundle; // Checkstyle: resume -import static com.oracle.svm.core.jdk.localization.compression.utils.BundleSerializationUtils.extractContent; - public class BundleContentSubstitutedLocalizationSupport extends LocalizationSupport { @Platforms(Platform.HOSTED_ONLY.class)// @@ -72,6 +71,11 @@ public BundleContentSubstitutedLocalizationSupport(Locale defaultLocale, Set content = extractContent(bundle); + Map content = BundleSerializationUtils.extractContent(bundle); return new ExtractedBundle(content); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationFeature.java index 2243cc09d93e..bf793b3bf4e9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,533 +24,26 @@ */ package com.oracle.svm.core.jdk.localization; -// Checkstyle: stop - -import java.lang.reflect.Field; -import java.nio.charset.Charset; -import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.StandardCharsets; -import java.nio.charset.UnsupportedCharsetException; -import java.text.spi.BreakIteratorProvider; -import java.text.spi.CollatorProvider; -import java.text.spi.DateFormatProvider; -import java.text.spi.DateFormatSymbolsProvider; -import java.text.spi.DecimalFormatSymbolsProvider; -import java.text.spi.NumberFormatProvider; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.IllformedLocaleException; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.MissingResourceException; -import java.util.Objects; -import java.util.ResourceBundle; -import java.util.Set; -import java.util.concurrent.ForkJoinPool; -import java.util.function.Function; -import java.util.spi.CalendarDataProvider; -import java.util.spi.CalendarNameProvider; -import java.util.spi.CurrencyNameProvider; -import java.util.spi.LocaleNameProvider; -import java.util.spi.LocaleServiceProvider; -import java.util.spi.TimeZoneNameProvider; - -import org.graalvm.collections.Pair; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.serviceprovider.JavaVersionUtil; +import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.configure.ResourcesRegistry; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.hosted.Feature; - -import com.oracle.svm.core.ClassLoaderSupport; -import com.oracle.svm.core.annotate.Substitute; -import com.oracle.svm.core.jdk.localization.compression.GzipBundleCompression; -import com.oracle.svm.core.jdk.localization.substitutions.Target_sun_util_locale_provider_LocaleServiceProviderPool_OptimizedLocaleMode; -import com.oracle.svm.core.option.HostedOptionKey; -import com.oracle.svm.core.option.LocatableMultiOptionValue; -import com.oracle.svm.core.option.OptionUtils; -import com.oracle.svm.core.util.UserError; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.util.ReflectionUtil; - -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import sun.util.locale.provider.LocaleProviderAdapter; -import sun.util.locale.provider.ResourceBundleBasedAdapter; -import sun.util.resources.LocaleData; -// Checkstyle: resume +import org.graalvm.nativeimage.impl.ConfigurationCondition; /** - * LocalizationFeature is the core class of SVM localization support. It contains all the options - * that can be used to configure how localization in the resulting image should work. One can - * specify what charsets, locales and resource bundles should be accessible. The runtime data for - * localization is stored in an image singleton of type {@link LocalizationSupport} or one of its - * subtypes. - * - * In case of ResourceBundles, one can also specify how bundles should be handled, because currently - * there are two different modes. - * - * The first approach is using a simple in memory map instead of the original JDK lookup. This - * simpler implementation leads to image size savings for smaller images such as hello world, but - * could cause compatibility issues and maintenance overhead. It is implemented in - * {@link OptimizedLocalizationSupport}. - * - * The second approach relies on the original JVM implementation instead. This approach is - * consistent by design, which solves compatibility issues and reduces maintenance overhead. - * Unfortunately, the default way of storing bundle data in getContents methods, see - * {@link sun.text.resources.FormatData} for example, is not very AOT friendly. Compiling these - * methods is time consuming and results in a bloated image (183 MB HelloWorld with all locales). - * Therefore, the bundle content itself is again stored in the image heap by default and furthermore - * is compressed to reduce the image size, see {@link BundleContentSubstitutedLocalizationSupport} - * and {@link GzipBundleCompression}. - * - * @author d-kozak - * @see LocalizationSupport - * @see OptimizedLocalizationSupport - * @see BundleContentSubstitutedLocalizationSupport + * This class is just a delegate. The real LocalizationFeature is now in + * com.oracle.svm.hosted.jdk.localization. It was created in order to ensure backwards compatibility + * for code depending on the location of the feature. */ -public abstract class LocalizationFeature implements Feature { - - protected final boolean optimizedMode = LocalizationSupport.optimizedMode(); - - private final boolean substituteLoadLookup = Options.LocalizationSubstituteLoadLookup.getValue(); - - protected final boolean trace = Options.TraceLocalizationFeature.getValue(); - - private final ForkJoinPool compressionPool = Options.LocalizationCompressInParallel.getValue() ? new ForkJoinPool(Runtime.getRuntime().availableProcessors()) : null; - - /** - * The Locale that the native image is built for. Currently, switching the Locale at run time is - * not supported because the resource bundles are only included for one Locale. We use the - * Locale that is set for the image generator. - */ - protected Locale defaultLocale = Locale.getDefault(); - - private Charset defaultCharset; - - protected Set allLocales; - - protected LocalizationSupport support; - - private Function> findClassByName; - - public static class Options { - @Option(help = "Comma separated list of bundles to be included into the image.", type = OptionType.User)// - public static final HostedOptionKey IncludeResourceBundles = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings()); - - @Option(help = "Make all hosted charsets available at run time")// - public static final HostedOptionKey AddAllCharsets = new HostedOptionKey<>(false); - - @Option(help = "Default locale of the image, by the default it is the same as the default locale of the image builder.", type = OptionType.User)// - public static final HostedOptionKey DefaultLocale = new HostedOptionKey<>(Locale.getDefault().toLanguageTag()); - - @Option(help = "Default charset of the image, by the default it is the same as the default charset of the image builder.", type = OptionType.User)// - public static final HostedOptionKey DefaultCharset = new HostedOptionKey<>(Charset.defaultCharset().name()); - - @Option(help = "Comma separated list of locales to be included into the image. The default locale is included in the list automatically if not present.", type = OptionType.User)// - public static final HostedOptionKey IncludeLocales = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings()); - - @Option(help = "Make all hosted locales available at run time.", type = OptionType.User)// - public static final HostedOptionKey IncludeAllLocales = new HostedOptionKey<>(false); - - @Option(help = "Optimize the resource bundle lookup using a simple map.", type = OptionType.User)// - public static final HostedOptionKey LocalizationOptimizedMode = new HostedOptionKey<>(JavaVersionUtil.JAVA_SPEC == 8); - - @Option(help = "Store the resource bundle content more efficiently in the fallback mode.", type = OptionType.User)// - public static final HostedOptionKey LocalizationSubstituteLoadLookup = new HostedOptionKey<>(true); - - @Option(help = "Regular expressions matching which bundles should be compressed.", type = OptionType.User)// - public static final HostedOptionKey LocalizationCompressBundles = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings()); - - @Option(help = "Compress the bundles in parallel.", type = OptionType.Expert)// - public static final HostedOptionKey LocalizationCompressInParallel = new HostedOptionKey<>(true); - - @Option(help = "When enabled, localization feature details are printed.", type = OptionType.Debug)// - public static final HostedOptionKey TraceLocalizationFeature = new HostedOptionKey<>(false); - } +@AutomaticFeature +public class LocalizationFeature implements Feature { /** - * Many subclasses of {@link Charset} initialize encoding and decoding tables lazily. They all - * follow the same pattern: the methods "initc2b" and/or "initb2c" perform the initialization, - * and then set a field "c2bInitialized" or "b2cInitialized" to true. We run the initialization - * eagerly by creating an encoder and decoder during image generation in - * {@link LocalizationFeature#addCharset}. So we know that the "init*" methods do nothing, and - * we replace calls to them with nothing, i.e,, remove calls to them. - * - * We could do all this with individual {@link Substitute method substitutions}, but it would - * require a lot of substitution methods that all look the same. + * @deprecated Use {@link ResourcesRegistry#addResourceBundles(ConfigurationCondition, String)} + * instead. */ - public static final class CharsetNodePlugin implements NodePlugin { - - @Override - public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - if ((method.getName().equals("initc2b") || method.getName().equals("initb2c")) && - b.getMetaAccess().lookupJavaType(Charset.class).isAssignableFrom(method.getDeclaringClass())) { - - /* - * Verify that the "*Initialized" field corresponding with the method was set to - * true, i.e., that initialization was done eagerly. - */ - ResolvedJavaType charsetType = method.getDeclaringClass(); - ResolvedJavaField initializedField = findStaticField(charsetType, method.getName().substring(4, 7) + "Initialized"); - if (!b.getConstantReflection().readFieldValue(initializedField, null).asBoolean()) { - String charsetName = charsetType.getUnqualifiedName(); - try { - Charset charset = Charset.forName(charsetName); - addCharset(charset); - } catch (UnsupportedCharsetException e) { - throw VMError.shouldNotReachHere("Could not find non-initialized charset " + charsetType.getSourceFileName(), e); - } - } - - /* We "handled" the method invocation by doing nothing. */ - return true; - } - return false; - } - - private static ResolvedJavaField findStaticField(ResolvedJavaType declaringClass, String name) { - for (ResolvedJavaField field : declaringClass.getStaticFields()) { - if (field.getName().equals(name)) { - return field; - } - } - throw VMError.shouldNotReachHere(); - } - } - - @Override - public void afterRegistration(AfterRegistrationAccess access) { - findClassByName = access::findClassByName; - allLocales = processLocalesOption(); - defaultLocale = parseLocaleFromTag(Options.DefaultLocale.getValue()); - UserError.guarantee(defaultLocale != null, "Invalid default locale %s", Options.DefaultLocale.getValue()); - try { - defaultCharset = Charset.forName(Options.DefaultCharset.getValue()); - VMError.guarantee(defaultCharset.name().equals(Options.DefaultCharset.getValue()), - "Failed to locate charset " + Options.DefaultCharset.getValue() + ", instead " + defaultCharset.name() + " was provided"); - } catch (IllegalCharsetNameException | UnsupportedCharsetException ex) { - throw UserError.abort(ex, "Invalid default charset %s", Options.DefaultCharset.getValue()); - } - allLocales.add(defaultLocale); - support = selectLocalizationSupport(); - ImageSingletons.add(LocalizationSupport.class, support); - ImageSingletons.add(LocalizationFeature.class, this); - - addCharsets(); - if (optimizedMode) { - /* - * Providers are only preprocessed in the optimized mode. - */ - addProviders(); - } - } - - @Platforms(Platform.HOSTED_ONLY.class) - private LocalizationSupport selectLocalizationSupport() { - if (optimizedMode) { - return new OptimizedLocalizationSupport(defaultLocale, allLocales, defaultCharset); - } else if (substituteLoadLookup) { - List requestedPatterns = Options.LocalizationCompressBundles.getValue().values(); - return new BundleContentSubstitutedLocalizationSupport(defaultLocale, allLocales, defaultCharset, requestedPatterns, compressionPool); - } - return new LocalizationSupport(defaultLocale, allLocales, defaultCharset); - } - - @Override - public void beforeAnalysis(BeforeAnalysisAccess access) { - addResourceBundles(); - } - - @Override - public void afterAnalysis(AfterAnalysisAccess access) { - if (compressionPool != null) { - compressionPool.shutdown(); - } - } - - /** - * @return locale for given tag or null for invalid ones - */ - @Platforms(Platform.HOSTED_ONLY.class) - private static Locale parseLocaleFromTag(String tag) { - try { - return new Locale.Builder().setLanguageTag(tag).build(); - } catch (IllformedLocaleException ex) { - /*- Custom made locales consisting of at most three parts separated by '-' are also supported */ - String[] parts = tag.split("-"); - switch (parts.length) { - case 1: - return new Locale(parts[0]); - case 2: - return new Locale(parts[0], parts[1]); - case 3: - return new Locale(parts[0], parts[1], parts[2]); - default: - return null; - } - } - } - - @Platforms(Platform.HOSTED_ONLY.class) - private static Set processLocalesOption() { - Set locales = new HashSet<>(); - if (Options.IncludeAllLocales.getValue()) { - Collections.addAll(locales, Locale.getAvailableLocales()); - /*- Fallthrough to also allow adding custom locales */ - } - List invalid = new ArrayList<>(); - for (String tag : OptionUtils.flatten(",", Options.IncludeLocales.getValue().values())) { - Locale locale = parseLocaleFromTag(tag); - if (locale != null) { - locales.add(locale); - } else { - invalid.add(tag); - } - } - if (!invalid.isEmpty()) { - throw UserError.abort("Invalid locales specified: %s", invalid); - } - return locales; - } - - /** - * The JDK performs dynamic lookup of charsets by name, which leads to dynamic class loading. We - * cannot do that, because we need to know all classes ahead of time to perform our static - * analysis. Therefore, we load and register all standard charsets here. Features that require - * more than this can add additional charsets. - */ - @Platforms(Platform.HOSTED_ONLY.class) - private void addCharsets() { - if (Options.AddAllCharsets.getValue()) { - for (Charset c : Charset.availableCharsets().values()) { - addCharset(c); - } - } else { - addCharset(defaultCharset); - addCharset(StandardCharsets.US_ASCII); - addCharset(StandardCharsets.ISO_8859_1); - addCharset(StandardCharsets.UTF_8); - addCharset(StandardCharsets.UTF_16BE); - addCharset(StandardCharsets.UTF_16LE); - addCharset(StandardCharsets.UTF_16); - } - } - - @Platforms(Platform.HOSTED_ONLY.class) - public static void addCharset(Charset charset) { - Map charsets = ImageSingletons.lookup(LocalizationSupport.class).charsets; - charsets.put(charset.name().toLowerCase(), charset); - for (String name : charset.aliases()) { - charsets.put(name.toLowerCase(), charset); - } - - /* Eagerly initialize all the tables necessary for decoding / encoding. */ - charset.newDecoder(); - if (charset.canEncode()) { - charset.newEncoder(); - } - } - - /* - * LocaleServiceProviderPool.spiClasses does not contain all the classes we need, so we list - * them manually here. - */ - private static final List> spiClasses = Arrays.asList( - BreakIteratorProvider.class, - CollatorProvider.class, - DateFormatProvider.class, - DateFormatSymbolsProvider.class, - DecimalFormatSymbolsProvider.class, - NumberFormatProvider.class, - CurrencyNameProvider.class, - LocaleNameProvider.class, - TimeZoneNameProvider.class, - CalendarDataProvider.class, - CalendarNameProvider.class); - - @Platforms(Platform.HOSTED_ONLY.class) - protected List> getSpiClasses() { - return spiClasses; - } - - @Platforms(Platform.HOSTED_ONLY.class) - private void addProviders() { - OptimizedLocalizationSupport optimizedLocalizationSupport = support.asOptimizedSupport(); - for (Class providerClass : getSpiClasses()) { - LocaleProviderAdapter adapter = Objects.requireNonNull(LocaleProviderAdapter.getAdapter(providerClass, defaultLocale)); - LocaleServiceProvider provider = Objects.requireNonNull(adapter.getLocaleServiceProvider(providerClass)); - optimizedLocalizationSupport.providerPools.put(providerClass, new Target_sun_util_locale_provider_LocaleServiceProviderPool_OptimizedLocaleMode(provider)); - } - - for (Locale locale : allLocales) { - for (Locale candidateLocale : optimizedLocalizationSupport.control.getCandidateLocales("", locale)) { - for (Class providerClass : getSpiClasses()) { - LocaleProviderAdapter adapter = Objects.requireNonNull(LocaleProviderAdapter.getAdapter(providerClass, candidateLocale)); - - optimizedLocalizationSupport.adaptersByClass.put(Pair.create(providerClass, candidateLocale), adapter); - LocaleProviderAdapter existing = optimizedLocalizationSupport.adaptersByType.put(adapter.getAdapterType(), adapter); - assert existing == null || existing == adapter : "Overwriting adapter type with a different adapter"; - - } - } - } - } - - @Platforms(Platform.HOSTED_ONLY.class) - protected void addResourceBundles() { - for (Locale locale : allLocales) { - prepareBundle(localeData(java.util.spi.CalendarDataProvider.class, locale).getCalendarData(locale), locale); - prepareBundle(localeData(java.util.spi.CurrencyNameProvider.class, locale).getCurrencyNames(locale), locale); - prepareBundle(localeData(java.util.spi.LocaleNameProvider.class, locale).getLocaleNames(locale), locale); - prepareBundle(localeData(java.util.spi.TimeZoneNameProvider.class, locale).getTimeZoneNames(locale), locale); - prepareBundle(localeData(java.text.spi.BreakIteratorProvider.class, locale).getBreakIteratorInfo(locale), locale); - prepareBundle(localeData(java.text.spi.BreakIteratorProvider.class, locale).getCollationData(locale), locale); - prepareBundle(localeData(java.text.spi.DateFormatProvider.class, locale).getDateFormatData(locale), locale); - prepareBundle(localeData(java.text.spi.NumberFormatProvider.class, locale).getNumberFormatData(locale), locale); - /* Note that JDK 11 support overrides this method to register more bundles. */ - } - - final String[] alwaysRegisteredResourceBundles = new String[]{ - "sun.util.logging.resources.logging", - "sun.util.resources.TimeZoneNames" - }; - for (String bundleName : alwaysRegisteredResourceBundles) { - prepareBundle(bundleName); - } - - for (String bundleName : OptionUtils.flatten(",", Options.IncludeResourceBundles.getValue())) { - processRequestedBundle(bundleName); - } - } - - @Platforms(Platform.HOSTED_ONLY.class) - protected LocaleData localeData(Class providerClass, Locale locale) { - return ((ResourceBundleBasedAdapter) LocaleProviderAdapter.getAdapter(providerClass, locale)).getLocaleData(); - } - - @Platforms(Platform.HOSTED_ONLY.class) - private void processRequestedBundle(String input) { - int splitIndex = input.indexOf('_'); - boolean specificLocaleRequested = splitIndex != -1; - if (!specificLocaleRequested) { - prepareBundle(input, allLocales); - return; - } - Locale locale = splitIndex + 1 < input.length() ? parseLocaleFromTag(input.substring(splitIndex + 1)) : Locale.ROOT; - if (locale == null) { - trace("Cannot parse wanted locale " + input.substring(splitIndex + 1) + ", default will be used instead."); - locale = defaultLocale; - } - /*- Get rid of locale specific suffix. */ - String baseName = input.substring(0, splitIndex); - prepareBundle(baseName, Collections.singletonList(locale)); - } - - @Platforms(Platform.HOSTED_ONLY.class) + @Deprecated public void prepareBundle(String baseName) { - prepareBundle(baseName, allLocales); - } - - @Platforms(Platform.HOSTED_ONLY.class) - public void prepareBundle(String baseName, Collection wantedLocales) { - if (baseName.isEmpty()) { - return; - } - - boolean somethingFound = false; - for (Locale locale : wantedLocales) { - List resourceBundle; - try { - resourceBundle = ImageSingletons.lookup(ClassLoaderSupport.class).getResourceBundle(baseName, locale); - } catch (MissingResourceException mre) { - continue; - } - somethingFound = !resourceBundle.isEmpty(); - for (ResourceBundle bundle : resourceBundle) { - prepareBundle(baseName, bundle, locale); - } - } - - if (!somethingFound) { - /* - * Try non-compliant class-based bundles. These bundles can't be looked up by the normal - * ResourceBundle lookup process, e.g. because they don't have default constructors. - */ - Class clazz = findClassByName.apply(baseName); - if (clazz != null && ResourceBundle.class.isAssignableFrom(clazz)) { - trace("Found non-compliant class-based bundle " + clazz); - somethingFound = true; - support.prepareNonCompliant(clazz); - } - } - - if (!somethingFound) { - String errorMessage = "The bundle named: " + baseName + ", has not been found. " + - "If the bundle is part of a module, verify the bundle name is a fully qualified class name. Otherwise " + - "verify the bundle path is accessible in the classpath."; - // Checkstyle: stop - System.out.println(errorMessage); - // Checkstyle: resume - } - } - - @Platforms(Platform.HOSTED_ONLY.class) - protected void prepareBundle(ResourceBundle bundle, Locale locale) { - prepareBundle(bundle.getBaseBundleName(), bundle, locale); - } - - @Platforms(Platform.HOSTED_ONLY.class) - private void prepareBundle(String bundleName, ResourceBundle bundle, Locale locale) { - trace("Adding bundle " + bundleName + ", locale " + locale); - /* - * Ensure that the bundle contents are loaded. We need to walk the whole bundle parent chain - * down to the root. - */ - for (ResourceBundle cur = bundle; cur != null; cur = getParent(cur)) { - /* Register all bundles with their corresponding locales */ - support.prepareBundle(bundleName, cur, cur.getLocale()); - } - - /* - * Finally, register the requested bundle with requested locale (Requested might be more - * specific than the actual bundle locale - */ - support.prepareBundle(bundleName, bundle, locale); - } - - /* - * The field ResourceBundle.parent is not public. There is a backdoor to access it via - * SharedSecrets, but the package of SharedSecrets changed from JDK 8 to JDK 11 so it is - * inconvenient to use it. Reflective access is easier. - */ - private static final Field PARENT_FIELD = ReflectionUtil.lookupField(ResourceBundle.class, "parent"); - - @Platforms(Platform.HOSTED_ONLY.class) - private static ResourceBundle getParent(ResourceBundle bundle) { - try { - return (ResourceBundle) PARENT_FIELD.get(bundle); - } catch (ReflectiveOperationException ex) { - throw VMError.shouldNotReachHere(ex); - } - } - - @Platforms(Platform.HOSTED_ONLY.class) - protected void trace(String msg) { - if (trace) { - // Checkstyle: stop - System.out.println(msg); - // Checkstyle: resume - } + ImageSingletons.lookup(ResourcesRegistry.class).addResourceBundles(ConfigurationCondition.alwaysTrue(), baseName); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java index f5a95b1cd59d..cca533de556c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java @@ -34,7 +34,6 @@ import java.util.Set; import java.util.stream.Collectors; -import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.debug.GraalError; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; @@ -49,7 +48,7 @@ * Holder for localization information that is computed during image generation and used at run * time. * - * @see LocalizationFeature + * For more details, see LocalizationFeature */ public class LocalizationSupport { @@ -72,16 +71,18 @@ public LocalizationSupport(Locale defaultLocale, Set locales, Charset de this.supportedLanguageTags = locales.stream().map(Locale::toString).collect(Collectors.toSet()); } - @Fold - public static boolean optimizedMode() { - return LocalizationFeature.Options.LocalizationOptimizedMode.getValue(); + public boolean optimizedMode() { + return false; } - @Fold - public static boolean jvmMode() { + public boolean jvmMode() { return !optimizedMode(); } + public boolean substituteLoadLookup() { + return false; + } + public OptimizedLocalizationSupport asOptimizedSupport() { GraalError.guarantee(optimizedMode(), "Optimized support only available in optimized localization mode."); return ((OptimizedLocalizationSupport) this); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/OptimizedLocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/OptimizedLocalizationSupport.java index d064ac0cf0c3..68474bb2e938 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/OptimizedLocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/OptimizedLocalizationSupport.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.jdk.localization; -import com.oracle.svm.core.option.SubstrateOptionsParser; import org.graalvm.collections.Pair; import java.nio.charset.Charset; @@ -49,12 +48,15 @@ public class OptimizedLocalizationSupport extends LocalizationSupport { final Map, ResourceBundle> resourceBundles = new HashMap<>(); - private final String includeResourceBundlesOption = SubstrateOptionsParser.commandArgument(LocalizationFeature.Options.IncludeResourceBundles, ""); - public OptimizedLocalizationSupport(Locale defaultLocale, Set locales, Charset defaultCharset) { super(defaultLocale, locales, defaultCharset); } + @Override + public boolean optimizedMode() { + return true; + } + /** * Get cached resource bundle. * @@ -69,7 +71,7 @@ public ResourceBundle getCached(String baseName, Locale locale) throws MissingRe } } String errorMessage = "Resource bundle not found " + baseName + ", locale " + locale + ". " + - "Register the resource bundle using the option " + includeResourceBundlesOption + baseName + "."; + "Register the resource bundle using the option -H:IncludeResourceBundles=" + baseName + "."; throw new MissingResourceException(errorMessage, this.getClass().getName(), baseName); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/JvmLocaleMode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/JvmLocaleMode.java index 47946f6de718..98db7778ed07 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/JvmLocaleMode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/JvmLocaleMode.java @@ -26,6 +26,7 @@ import java.util.function.BooleanSupplier; +import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -35,6 +36,6 @@ public class JvmLocaleMode implements BooleanSupplier { @Override public boolean getAsBoolean() { - return LocalizationSupport.jvmMode(); + return ImageSingletons.lookup(LocalizationSupport.class).jvmMode(); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/OptimizedLocaleMode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/OptimizedLocaleMode.java index 4a824d4549e9..1ef9e78fef70 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/OptimizedLocaleMode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/OptimizedLocaleMode.java @@ -27,10 +27,11 @@ import java.util.function.BooleanSupplier; import com.oracle.svm.core.jdk.localization.LocalizationSupport; +import org.graalvm.nativeimage.ImageSingletons; public class OptimizedLocaleMode implements BooleanSupplier { @Override public boolean getAsBoolean() { - return LocalizationSupport.optimizedMode(); + return ImageSingletons.lookup(LocalizationSupport.class).optimizedMode(); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/SubstituteLoadLookup.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/SubstituteLoadLookup.java index 06ae2a19cdaf..a29d643342e0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/SubstituteLoadLookup.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/modes/SubstituteLoadLookup.java @@ -26,10 +26,10 @@ import java.util.function.Predicate; +import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import com.oracle.svm.core.jdk.localization.LocalizationFeature; import com.oracle.svm.core.jdk.localization.LocalizationSupport; @Platforms(Platform.HOSTED_ONLY.class) @@ -37,7 +37,8 @@ public class SubstituteLoadLookup implements Predicate { @Override public boolean test(String className) { - return LocalizationSupport.optimizedMode() || LocalizationFeature.Options.LocalizationSubstituteLoadLookup.getValue(); + LocalizationSupport support = ImageSingletons.lookup(LocalizationSupport.class); + return support.optimizedMode() || support.substituteLoadLookup(); } } diff --git a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/LocalizationFeatureJDK11OrLater.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/localization/LocalizationFeatureJDK11OrLater.java similarity index 95% rename from substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/LocalizationFeatureJDK11OrLater.java rename to substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/localization/LocalizationFeatureJDK11OrLater.java index a61cd2cff607..82b5f01b8582 100644 --- a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/localization/LocalizationFeatureJDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/jdk11/localization/LocalizationFeatureJDK11OrLater.java @@ -23,7 +23,7 @@ * questions. */ -package com.oracle.svm.core.jdk11.localization; +package com.oracle.svm.hosted.jdk11.localization; import java.util.ArrayList; import java.util.Collections; @@ -34,7 +34,7 @@ import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import com.oracle.svm.core.annotate.AutomaticFeature; -import com.oracle.svm.core.jdk.localization.LocalizationFeature; +import com.oracle.svm.hosted.jdk.localization.LocalizationFeature; //Checkstyle: stop import sun.text.spi.JavaTimeDateTimePatternProvider; diff --git a/substratevm/src/com.oracle.svm.core.jdk8/src/com/oracle/svm/core/jdk8/LocalizationFeatureJDK8.java b/substratevm/src/com.oracle.svm.hosted.jdk8/src/com/oracle/svm/hosted/jdk8/LocalizationFeatureJDK8.java similarity index 93% rename from substratevm/src/com.oracle.svm.core.jdk8/src/com/oracle/svm/core/jdk8/LocalizationFeatureJDK8.java rename to substratevm/src/com.oracle.svm.hosted.jdk8/src/com/oracle/svm/hosted/jdk8/LocalizationFeatureJDK8.java index b5645bbb0204..b242c230d693 100644 --- a/substratevm/src/com.oracle.svm.core.jdk8/src/com/oracle/svm/core/jdk8/LocalizationFeatureJDK8.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk8/src/com/oracle/svm/hosted/jdk8/LocalizationFeatureJDK8.java @@ -23,12 +23,12 @@ * questions. */ -package com.oracle.svm.core.jdk8; +package com.oracle.svm.hosted.jdk8; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import com.oracle.svm.core.annotate.AutomaticFeature; -import com.oracle.svm.core.jdk.localization.LocalizationFeature; +import com.oracle.svm.hosted.jdk.localization.LocalizationFeature; @AutomaticFeature final class LocalizationFeatureJDK8 extends LocalizationFeature { 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 b01843f59fa6..0ddee26f57a1 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 @@ -200,7 +200,7 @@ import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.hub.LayoutEncoding; import com.oracle.svm.core.image.ImageHeapLayouter; -import com.oracle.svm.core.jdk.localization.LocalizationFeature; +import com.oracle.svm.hosted.jdk.localization.LocalizationFeature; import com.oracle.svm.core.option.HostedOptionValues; import com.oracle.svm.core.option.OptionUtils; import com.oracle.svm.core.option.RuntimeOptionValues; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java index 4ad543dc9683..767adf4bba53 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java @@ -64,7 +64,7 @@ import com.oracle.svm.core.configure.ResourceConfigurationParser; import com.oracle.svm.core.configure.ResourcesRegistry; import com.oracle.svm.core.jdk.Resources; -import com.oracle.svm.core.jdk.localization.LocalizationFeature; +import com.oracle.svm.hosted.jdk.localization.LocalizationFeature; import com.oracle.svm.core.jdk.resources.NativeImageResourceFileAttributes; import com.oracle.svm.core.jdk.resources.NativeImageResourceFileAttributesView; import com.oracle.svm.core.jdk.resources.NativeImageResourceFileSystem; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/CharsetSubstitutionsFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/CharsetSubstitutionsFeature.java similarity index 97% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/CharsetSubstitutionsFeature.java rename to substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/CharsetSubstitutionsFeature.java index 686e9aa10f63..15d2773d6202 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/CharsetSubstitutionsFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/CharsetSubstitutionsFeature.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.jdk.localization; +package com.oracle.svm.hosted.jdk.localization; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java new file mode 100644 index 000000000000..3d38100016f8 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2015, 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.jdk.localization; + +// Checkstyle: stop + +import java.lang.reflect.Field; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.StandardCharsets; +import java.nio.charset.UnsupportedCharsetException; +import java.text.spi.BreakIteratorProvider; +import java.text.spi.CollatorProvider; +import java.text.spi.DateFormatProvider; +import java.text.spi.DateFormatSymbolsProvider; +import java.text.spi.DecimalFormatSymbolsProvider; +import java.text.spi.NumberFormatProvider; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.IllformedLocaleException; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.Objects; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.concurrent.ForkJoinPool; +import java.util.function.Function; +import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; +import java.util.spi.CurrencyNameProvider; +import java.util.spi.LocaleNameProvider; +import java.util.spi.LocaleServiceProvider; +import java.util.spi.TimeZoneNameProvider; + +import com.oracle.svm.core.jdk.localization.BundleContentSubstitutedLocalizationSupport; +import com.oracle.svm.core.jdk.localization.LocalizationSupport; +import com.oracle.svm.core.jdk.localization.OptimizedLocalizationSupport; +import com.oracle.svm.hosted.NativeImageOptions; +import com.oracle.svm.core.jdk.localization.compression.GzipBundleCompression; +import com.oracle.svm.core.jdk.localization.substitutions.Target_sun_util_locale_provider_LocaleServiceProviderPool_OptimizedLocaleMode; +import org.graalvm.collections.Pair; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.Feature; + +import com.oracle.svm.core.ClassLoaderSupport; +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.option.HostedOptionKey; +import com.oracle.svm.core.option.LocatableMultiOptionValue; +import com.oracle.svm.core.option.OptionUtils; +import com.oracle.svm.core.util.UserError; +import com.oracle.svm.core.util.VMError; +import com.oracle.svm.util.ReflectionUtil; + +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import sun.util.locale.provider.LocaleProviderAdapter; +import sun.util.locale.provider.ResourceBundleBasedAdapter; +import sun.util.resources.LocaleData; +// Checkstyle: resume + +/** + * LocalizationFeature is the core class of SVM localization support. It contains all the options + * that can be used to configure how localization in the resulting image should work. One can + * specify what charsets, locales and resource bundles should be accessible. The runtime data for + * localization is stored in an image singleton of type {@link LocalizationSupport} or one of its + * subtypes. + * + * In case of ResourceBundles, one can also specify how bundles should be handled, because currently + * there are two different modes. + * + * The first approach is using a simple in memory map instead of the original JDK lookup. This + * simpler implementation leads to image size savings for smaller images such as hello world, but + * could cause compatibility issues and maintenance overhead. It is implemented in + * {@link OptimizedLocalizationSupport}. + * + * The second approach relies on the original JVM implementation instead. This approach is + * consistent by design, which solves compatibility issues and reduces maintenance overhead. + * Unfortunately, the default way of storing bundle data in getContents methods, see + * {@link sun.text.resources.FormatData} for example, is not very AOT friendly. Compiling these + * methods is time consuming and results in a bloated image (183 MB HelloWorld with all locales). + * Therefore, the bundle content itself is again stored in the image heap by default and furthermore + * is compressed to reduce the image size, see {@link BundleContentSubstitutedLocalizationSupport} + * and {@link GzipBundleCompression}. + * + * @author d-kozak + * @see LocalizationSupport + * @see OptimizedLocalizationSupport + * @see BundleContentSubstitutedLocalizationSupport + */ +public abstract class LocalizationFeature implements Feature { + + protected final boolean optimizedMode = Options.LocalizationOptimizedMode.getValue(); + + private final boolean substituteLoadLookup = Options.LocalizationSubstituteLoadLookup.getValue(); + + protected final boolean trace = Options.TraceLocalizationFeature.getValue(); + + private final ForkJoinPool compressionPool = Options.LocalizationCompressInParallel.getValue() ? new ForkJoinPool(NativeImageOptions.NumberOfThreads.getValue()) : null; + + /** + * The Locale that the native image is built for. Currently, switching the Locale at run time is + * not supported because the resource bundles are only included for one Locale. We use the + * Locale that is set for the image generator. + */ + protected Locale defaultLocale = Locale.getDefault(); + + private Charset defaultCharset; + + protected Set allLocales; + + protected LocalizationSupport support; + + private Function> findClassByName; + + public static class Options { + @Option(help = "Comma separated list of bundles to be included into the image.", type = OptionType.User)// + public static final HostedOptionKey IncludeResourceBundles = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings()); + + @Option(help = "Make all hosted charsets available at run time")// + public static final HostedOptionKey AddAllCharsets = new HostedOptionKey<>(false); + + @Option(help = "Default locale of the image, by the default it is the same as the default locale of the image builder.", type = OptionType.User)// + public static final HostedOptionKey DefaultLocale = new HostedOptionKey<>(Locale.getDefault().toLanguageTag()); + + @Option(help = "Default charset of the image, by the default it is the same as the default charset of the image builder.", type = OptionType.User)// + public static final HostedOptionKey DefaultCharset = new HostedOptionKey<>(Charset.defaultCharset().name()); + + @Option(help = "Comma separated list of locales to be included into the image. The default locale is included in the list automatically if not present.", type = OptionType.User)// + public static final HostedOptionKey IncludeLocales = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings()); + + @Option(help = "Make all hosted locales available at run time.", type = OptionType.User)// + public static final HostedOptionKey IncludeAllLocales = new HostedOptionKey<>(false); + + @Option(help = "Optimize the resource bundle lookup using a simple map.", type = OptionType.User)// + public static final HostedOptionKey LocalizationOptimizedMode = new HostedOptionKey<>(JavaVersionUtil.JAVA_SPEC == 8); + + @Option(help = "Store the resource bundle content more efficiently in the fallback mode.", type = OptionType.User)// + public static final HostedOptionKey LocalizationSubstituteLoadLookup = new HostedOptionKey<>(true); + + @Option(help = "Regular expressions matching which bundles should be compressed.", type = OptionType.User)// + public static final HostedOptionKey LocalizationCompressBundles = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings()); + + @Option(help = "Compress the bundles in parallel.", type = OptionType.Expert)// + public static final HostedOptionKey LocalizationCompressInParallel = new HostedOptionKey<>(true); + + @Option(help = "When enabled, localization feature details are printed.", type = OptionType.Debug)// + public static final HostedOptionKey TraceLocalizationFeature = new HostedOptionKey<>(false); + } + + /** + * Many subclasses of {@link Charset} initialize encoding and decoding tables lazily. They all + * follow the same pattern: the methods "initc2b" and/or "initb2c" perform the initialization, + * and then set a field "c2bInitialized" or "b2cInitialized" to true. We run the initialization + * eagerly by creating an encoder and decoder during image generation in + * {@link LocalizationFeature#addCharset}. So we know that the "init*" methods do nothing, and + * we replace calls to them with nothing, i.e,, remove calls to them. + * + * We could do all this with individual {@link Substitute method substitutions}, but it would + * require a lot of substitution methods that all look the same. + */ + public static final class CharsetNodePlugin implements NodePlugin { + + @Override + public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + if ((method.getName().equals("initc2b") || method.getName().equals("initb2c")) && + b.getMetaAccess().lookupJavaType(Charset.class).isAssignableFrom(method.getDeclaringClass())) { + + /* + * Verify that the "*Initialized" field corresponding with the method was set to + * true, i.e., that initialization was done eagerly. + */ + ResolvedJavaType charsetType = method.getDeclaringClass(); + ResolvedJavaField initializedField = findStaticField(charsetType, method.getName().substring(4, 7) + "Initialized"); + if (!b.getConstantReflection().readFieldValue(initializedField, null).asBoolean()) { + String charsetName = charsetType.getUnqualifiedName(); + try { + Charset charset = Charset.forName(charsetName); + addCharset(charset); + } catch (UnsupportedCharsetException e) { + throw VMError.shouldNotReachHere("Could not find non-initialized charset " + charsetType.getSourceFileName(), e); + } + } + + /* We "handled" the method invocation by doing nothing. */ + return true; + } + return false; + } + + private static ResolvedJavaField findStaticField(ResolvedJavaType declaringClass, String name) { + for (ResolvedJavaField field : declaringClass.getStaticFields()) { + if (field.getName().equals(name)) { + return field; + } + } + throw VMError.shouldNotReachHere(); + } + } + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + findClassByName = access::findClassByName; + allLocales = processLocalesOption(); + defaultLocale = parseLocaleFromTag(Options.DefaultLocale.getValue()); + UserError.guarantee(defaultLocale != null, "Invalid default locale %s", Options.DefaultLocale.getValue()); + try { + defaultCharset = Charset.forName(Options.DefaultCharset.getValue()); + VMError.guarantee(defaultCharset.name().equals(Options.DefaultCharset.getValue()), + "Failed to locate charset " + Options.DefaultCharset.getValue() + ", instead " + defaultCharset.name() + " was provided"); + } catch (IllegalCharsetNameException | UnsupportedCharsetException ex) { + throw UserError.abort(ex, "Invalid default charset %s", Options.DefaultCharset.getValue()); + } + allLocales.add(defaultLocale); + support = selectLocalizationSupport(); + ImageSingletons.add(LocalizationSupport.class, support); + ImageSingletons.add(LocalizationFeature.class, this); + + addCharsets(); + if (optimizedMode) { + /* + * Providers are only preprocessed in the optimized mode. + */ + addProviders(); + } + } + + @Platforms(Platform.HOSTED_ONLY.class) + private LocalizationSupport selectLocalizationSupport() { + if (optimizedMode) { + return new OptimizedLocalizationSupport(defaultLocale, allLocales, defaultCharset); + } else if (substituteLoadLookup) { + List requestedPatterns = Options.LocalizationCompressBundles.getValue().values(); + return new BundleContentSubstitutedLocalizationSupport(defaultLocale, allLocales, defaultCharset, requestedPatterns, compressionPool); + } + return new LocalizationSupport(defaultLocale, allLocales, defaultCharset); + } + + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + addResourceBundles(); + } + + @Override + public void afterAnalysis(AfterAnalysisAccess access) { + if (compressionPool != null) { + compressionPool.shutdown(); + } + } + + /** + * @return locale for given tag or null for invalid ones + */ + @Platforms(Platform.HOSTED_ONLY.class) + private static Locale parseLocaleFromTag(String tag) { + try { + return new Locale.Builder().setLanguageTag(tag).build(); + } catch (IllformedLocaleException ex) { + /*- Custom made locales consisting of at most three parts separated by '-' are also supported */ + String[] parts = tag.split("-"); + switch (parts.length) { + case 1: + return new Locale(parts[0]); + case 2: + return new Locale(parts[0], parts[1]); + case 3: + return new Locale(parts[0], parts[1], parts[2]); + default: + return null; + } + } + } + + @Platforms(Platform.HOSTED_ONLY.class) + private static Set processLocalesOption() { + Set locales = new HashSet<>(); + if (Options.IncludeAllLocales.getValue()) { + Collections.addAll(locales, Locale.getAvailableLocales()); + /*- Fallthrough to also allow adding custom locales */ + } + List invalid = new ArrayList<>(); + for (String tag : OptionUtils.flatten(",", Options.IncludeLocales.getValue().values())) { + Locale locale = parseLocaleFromTag(tag); + if (locale != null) { + locales.add(locale); + } else { + invalid.add(tag); + } + } + if (!invalid.isEmpty()) { + throw UserError.abort("Invalid locales specified: %s", invalid); + } + return locales; + } + + /** + * The JDK performs dynamic lookup of charsets by name, which leads to dynamic class loading. We + * cannot do that, because we need to know all classes ahead of time to perform our static + * analysis. Therefore, we load and register all standard charsets here. Features that require + * more than this can add additional charsets. + */ + @Platforms(Platform.HOSTED_ONLY.class) + private void addCharsets() { + if (Options.AddAllCharsets.getValue()) { + for (Charset c : Charset.availableCharsets().values()) { + addCharset(c); + } + } else { + addCharset(defaultCharset); + addCharset(StandardCharsets.US_ASCII); + addCharset(StandardCharsets.ISO_8859_1); + addCharset(StandardCharsets.UTF_8); + addCharset(StandardCharsets.UTF_16BE); + addCharset(StandardCharsets.UTF_16LE); + addCharset(StandardCharsets.UTF_16); + } + } + + @Platforms(Platform.HOSTED_ONLY.class) + public static void addCharset(Charset charset) { + Map charsets = ImageSingletons.lookup(LocalizationSupport.class).charsets; + charsets.put(charset.name().toLowerCase(), charset); + for (String name : charset.aliases()) { + charsets.put(name.toLowerCase(), charset); + } + + /* Eagerly initialize all the tables necessary for decoding / encoding. */ + charset.newDecoder(); + if (charset.canEncode()) { + charset.newEncoder(); + } + } + + /* + * LocaleServiceProviderPool.spiClasses does not contain all the classes we need, so we list + * them manually here. + */ + private static final List> spiClasses = Arrays.asList( + BreakIteratorProvider.class, + CollatorProvider.class, + DateFormatProvider.class, + DateFormatSymbolsProvider.class, + DecimalFormatSymbolsProvider.class, + NumberFormatProvider.class, + CurrencyNameProvider.class, + LocaleNameProvider.class, + TimeZoneNameProvider.class, + CalendarDataProvider.class, + CalendarNameProvider.class); + + @Platforms(Platform.HOSTED_ONLY.class) + protected List> getSpiClasses() { + return spiClasses; + } + + @Platforms(Platform.HOSTED_ONLY.class) + private void addProviders() { + OptimizedLocalizationSupport optimizedLocalizationSupport = support.asOptimizedSupport(); + for (Class providerClass : getSpiClasses()) { + LocaleProviderAdapter adapter = Objects.requireNonNull(LocaleProviderAdapter.getAdapter(providerClass, defaultLocale)); + LocaleServiceProvider provider = Objects.requireNonNull(adapter.getLocaleServiceProvider(providerClass)); + optimizedLocalizationSupport.providerPools.put(providerClass, new Target_sun_util_locale_provider_LocaleServiceProviderPool_OptimizedLocaleMode(provider)); + } + + for (Locale locale : allLocales) { + for (Locale candidateLocale : optimizedLocalizationSupport.control.getCandidateLocales("", locale)) { + for (Class providerClass : getSpiClasses()) { + LocaleProviderAdapter adapter = Objects.requireNonNull(LocaleProviderAdapter.getAdapter(providerClass, candidateLocale)); + + optimizedLocalizationSupport.adaptersByClass.put(Pair.create(providerClass, candidateLocale), adapter); + LocaleProviderAdapter existing = optimizedLocalizationSupport.adaptersByType.put(adapter.getAdapterType(), adapter); + assert existing == null || existing == adapter : "Overwriting adapter type with a different adapter"; + + } + } + } + } + + @Platforms(Platform.HOSTED_ONLY.class) + protected void addResourceBundles() { + for (Locale locale : allLocales) { + prepareBundle(localeData(java.util.spi.CalendarDataProvider.class, locale).getCalendarData(locale), locale); + prepareBundle(localeData(java.util.spi.CurrencyNameProvider.class, locale).getCurrencyNames(locale), locale); + prepareBundle(localeData(java.util.spi.LocaleNameProvider.class, locale).getLocaleNames(locale), locale); + prepareBundle(localeData(java.util.spi.TimeZoneNameProvider.class, locale).getTimeZoneNames(locale), locale); + prepareBundle(localeData(java.text.spi.BreakIteratorProvider.class, locale).getBreakIteratorInfo(locale), locale); + prepareBundle(localeData(java.text.spi.BreakIteratorProvider.class, locale).getCollationData(locale), locale); + prepareBundle(localeData(java.text.spi.DateFormatProvider.class, locale).getDateFormatData(locale), locale); + prepareBundle(localeData(java.text.spi.NumberFormatProvider.class, locale).getNumberFormatData(locale), locale); + /* Note that JDK 11 support overrides this method to register more bundles. */ + } + + final String[] alwaysRegisteredResourceBundles = new String[]{ + "sun.util.logging.resources.logging", + "sun.util.resources.TimeZoneNames" + }; + for (String bundleName : alwaysRegisteredResourceBundles) { + prepareBundle(bundleName); + } + + for (String bundleName : OptionUtils.flatten(",", Options.IncludeResourceBundles.getValue())) { + processRequestedBundle(bundleName); + } + } + + @Platforms(Platform.HOSTED_ONLY.class) + protected LocaleData localeData(Class providerClass, Locale locale) { + return ((ResourceBundleBasedAdapter) LocaleProviderAdapter.getAdapter(providerClass, locale)).getLocaleData(); + } + + @Platforms(Platform.HOSTED_ONLY.class) + private void processRequestedBundle(String input) { + int splitIndex = input.indexOf('_'); + boolean specificLocaleRequested = splitIndex != -1; + if (!specificLocaleRequested) { + prepareBundle(input, allLocales); + return; + } + Locale locale = splitIndex + 1 < input.length() ? parseLocaleFromTag(input.substring(splitIndex + 1)) : Locale.ROOT; + if (locale == null) { + trace("Cannot parse wanted locale " + input.substring(splitIndex + 1) + ", default will be used instead."); + locale = defaultLocale; + } + /*- Get rid of locale specific suffix. */ + String baseName = input.substring(0, splitIndex); + prepareBundle(baseName, Collections.singletonList(locale)); + } + + @Platforms(Platform.HOSTED_ONLY.class) + public void prepareBundle(String baseName) { + prepareBundle(baseName, allLocales); + } + + @Platforms(Platform.HOSTED_ONLY.class) + public void prepareBundle(String baseName, Collection wantedLocales) { + if (baseName.isEmpty()) { + return; + } + + boolean somethingFound = false; + for (Locale locale : wantedLocales) { + List resourceBundle; + try { + resourceBundle = ImageSingletons.lookup(ClassLoaderSupport.class).getResourceBundle(baseName, locale); + } catch (MissingResourceException mre) { + continue; + } + somethingFound = !resourceBundle.isEmpty(); + for (ResourceBundle bundle : resourceBundle) { + prepareBundle(baseName, bundle, locale); + } + } + + if (!somethingFound) { + /* + * Try non-compliant class-based bundles. These bundles can't be looked up by the normal + * ResourceBundle lookup process, e.g. because they don't have default constructors. + */ + Class clazz = findClassByName.apply(baseName); + if (clazz != null && ResourceBundle.class.isAssignableFrom(clazz)) { + trace("Found non-compliant class-based bundle " + clazz); + somethingFound = true; + support.prepareNonCompliant(clazz); + } + } + + if (!somethingFound) { + String errorMessage = "The bundle named: " + baseName + ", has not been found. " + + "If the bundle is part of a module, verify the bundle name is a fully qualified class name. Otherwise " + + "verify the bundle path is accessible in the classpath."; + // Checkstyle: stop + System.out.println(errorMessage); + // Checkstyle: resume + } + } + + @Platforms(Platform.HOSTED_ONLY.class) + protected void prepareBundle(ResourceBundle bundle, Locale locale) { + prepareBundle(bundle.getBaseBundleName(), bundle, locale); + } + + @Platforms(Platform.HOSTED_ONLY.class) + private void prepareBundle(String bundleName, ResourceBundle bundle, Locale locale) { + trace("Adding bundle " + bundleName + ", locale " + locale); + /* + * Ensure that the bundle contents are loaded. We need to walk the whole bundle parent chain + * down to the root. + */ + for (ResourceBundle cur = bundle; cur != null; cur = getParent(cur)) { + /* Register all bundles with their corresponding locales */ + support.prepareBundle(bundleName, cur, cur.getLocale()); + } + + /* + * Finally, register the requested bundle with requested locale (Requested might be more + * specific than the actual bundle locale + */ + support.prepareBundle(bundleName, bundle, locale); + } + + /* + * The field ResourceBundle.parent is not public. There is a backdoor to access it via + * SharedSecrets, but the package of SharedSecrets changed from JDK 8 to JDK 11 so it is + * inconvenient to use it. Reflective access is easier. + */ + private static final Field PARENT_FIELD = ReflectionUtil.lookupField(ResourceBundle.class, "parent"); + + @Platforms(Platform.HOSTED_ONLY.class) + private static ResourceBundle getParent(ResourceBundle bundle) { + try { + return (ResourceBundle) PARENT_FIELD.get(bundle); + } catch (ReflectiveOperationException ex) { + throw VMError.shouldNotReachHere(ex); + } + } + + @Platforms(Platform.HOSTED_ONLY.class) + protected void trace(String msg) { + if (trace) { + // Checkstyle: stop + System.out.println(msg); + // Checkstyle: resume + } + } +} From 6869fe3e00f4f67a61aee9d42bca421c19da5c3a Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 13 Oct 2021 02:30:09 +0000 Subject: [PATCH 443/681] [GR-19768] Update Truffle import. PullRequest: fastr/2667 --- vm/mx.vm/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 18842643c9a6..ffa902906316 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -66,7 +66,7 @@ }, { "name": "fastr", - "version": "0292d0263e2abe0508505e19351d7e85282ab831", + "version": "e80a7bc4bec3cfb18754b578212cf0d5e8122058", "dynamic": True, "urls": [ {"url": "https://github.com/oracle/fastr.git", "kind": "git"}, From 6a0febe77c5c661b9e6b15523200c3b8d9da53fb Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Wed, 13 Oct 2021 05:13:52 +0000 Subject: [PATCH 444/681] [GR-34241] ContextifyScript::EvalMachine() should pause the execution when break_on_first_line only. PullRequest: js/2190 --- vm/mx.vm/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index ffa902906316..0d8060ac5c01 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -39,7 +39,7 @@ "name": "graal-nodejs", "subdir": True, "dynamic": True, - "version": "43f5bc397a09a45f6f6c34ed5b283e58eca1e7ae", + "version": "70dbd4073a01b5482bdfb0075fa99ff8afd1954f", "urls" : [ {"url" : "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, @@ -49,7 +49,7 @@ "name": "graal-js", "subdir": True, "dynamic": True, - "version": "43f5bc397a09a45f6f6c34ed5b283e58eca1e7ae", + "version": "70dbd4073a01b5482bdfb0075fa99ff8afd1954f", "urls": [ {"url": "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, From db5edf9ee41d6cd662c409951d83fd5903b5d509 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Wed, 13 Oct 2021 11:25:20 +0200 Subject: [PATCH 445/681] Remove useless cast. --- .../truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java index b3e341250f1b..6b2295933c72 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime/src/org/graalvm/compiler/truffle/runtime/GraalTruffleRuntimeListenerDispatcher.java @@ -170,6 +170,6 @@ public void onFailure(CompilableTruffleAST compilable, String reason, boolean ba @Override public void onCompilationRetry(CompilableTruffleAST compilable, TruffleCompilationTask task) { onCompilationQueued((OptimizedCallTarget) compilable, task.tier()); - onCompilationStarted((OptimizedCallTarget) compilable, (CompilationTask) task); + onCompilationStarted((OptimizedCallTarget) compilable, task); } } From d090dccdaa41801f80a02b1d2e615650a4992a42 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 29 Sep 2021 16:33:15 +0200 Subject: [PATCH 446/681] compiler: Node#updatePredecessor should also notify the new successor about changed edges --- .../src/org/graalvm/compiler/graph/Node.java | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index d2bbcf3cbf9c..8f1622c8e2ed 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -631,6 +631,7 @@ protected void updatePredecessor(Node oldSuccessor, Node newSuccessor) { if (newSuccessor != null) { assert assertTrue(newSuccessor.predecessor == null, "unexpected non-null predecessor in new successor (%s): %s, this=%s", newSuccessor, newSuccessor.predecessor, this); newSuccessor.predecessor = this; + maybeNotifyInputChanged(newSuccessor); } maybeNotifyInputChanged(this); } From 04e88ef64a5b00a5a8bb7bc1d84dc66b8818be39 Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Wed, 13 Oct 2021 14:28:19 +0200 Subject: [PATCH 447/681] Update changelog and docs. --- truffle/CHANGELOG.md | 1 + truffle/docs/Optimizing.md | 53 ++++++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 962c7f6eac5f..3a93002f468d 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -11,6 +11,7 @@ This changelog summarizes major changes between Truffle versions relevant to lan No active inner context is allowed after `TruffleLanguage.finalizeContext(Object)` returns. Not complying with this requirement will result in an internal error. Please note that inactive inner contexts are still closed implicitly by the parent context. * Added `TruffleContext.closeExited(Node, int)` to hard exit an entered truffle context. See [the documentation](https://github.com/oracle/graal/blob/master/truffle/docs/Exit.md). * Added `TruffleLanguage.exitContext(Object, ExitMode, int)` to allow languages perform actions before natural/hard context exit. Languages are encouraged to run all their shutdown hooks in exitContext instead of finalizeContext. +* Improved the output format for `engine.TraceCompilation` and `engine.TraceCompilationDetails`. See [Optimizing.md](https://github.com/oracle/graal/blob/master/truffle/docs/Optimizing.md) for details. ## Version 21.3.0 * Added a `@GenerateWrapper.Ignore` annotation to prevent methods from being instrumented in wrapper classes. diff --git a/truffle/docs/Optimizing.md b/truffle/docs/Optimizing.md index 071700057d5d..abbe72835a63 100644 --- a/truffle/docs/Optimizing.md +++ b/truffle/docs/Optimizing.md @@ -43,24 +43,55 @@ Note: Most options also require the additional `--experimental-options` flag set The `--engine.TraceCompilation` command prints a line each time a method is compiled: ```shell -[engine] opt done EqualityConstraint.execute |AST 17|Tier 2|Time 152( 143+9 )ms|Inlined 2Y 0N|IR 266/ 300|CodeSize 1010|Addr 0x7f60068c82d0|Src octane-deltablue.js:528 +[engine] opt done id=244 EqualityConstraint.execute |Tier 1|Time 268( 220+47 )ms|AST 17|Inlined 0Y 2N|IR 238/ 437|CodeSize 1874|Timestamp 758868036671903|Src octane-deltablue.js:528 ``` -The `--engine.TraceCompilationDetails` command prints a line when compilation is queued, started, or completed: +Here is a quick overview of the information provided in these logs: +- `id` - Unique identifier of the call target. +- `Tier` - For which compilation tier was the targed scheduled. +- `Time` - How long did the compilation last, with separation between the Truffle tier (mainly partial evaluation) and the Graal Tiers. +- `AST` - The targets non-trivial node count. +- `Inlined` - How many calls were inlined and how many remained calls after inlining. +- `IR` - Graal node count after partial evaluation and after compilation. +- `CodeSize` - The size of the code generated for the call target. +- `Timestamp` - The time when the event happened as reported by `System.nanoTime()`. +- `Src` - Abbreviated source section of the call target. + +The `--engine.TraceCompilationDetails` command prints a line when compilation is queued, unqueued, started, or completed: ```shell -[engine] opt queued id=237 BinaryConstraint.output | Tier 1 | Count/Thres 25/ 25 | Queue: Size 1 Change +1 Scale 0.06 Elapsed 0us | Src octane-deltablue.js:416 | Time 317044280158387 -[engine] opt start id=237 BinaryConstraint.output | Tier 1 | Weight 25 | Rate 0.00000 | Queue: Size 0 Change +0 Scale 0.06 Elapsed 0us | Src octane-deltablue.js:416 | Time 317044278139824 -[engine] opt queued id=239 OrderedCollection.size | Tier 1 | Count/Thres 25/ 25 | Queue: Size 1 Change +1 Scale 0.06 Elapsed 0us | Src octane-deltablue.js:71 | Time 317044313989575 -[engine] opt queued id=52 Array.prototype.push | Tier 1 | Count/Thres 25/ 50 | Queue: Size 2 Change +1 Scale 0.13 Elapsed 0us | Src :1 | Time 317044336408392 -[engine] opt start id=239 OrderedCollection.size | Tier 1 | Weight 88875 | Rate 0.00000 | Queue: Size 6 Change -1 Scale 0.31 Elapsed 328us | Src octane-deltablue.js:71 | Time 317045054478062 +[engine] opt queued id=237 BinaryConstraint.output |Tier 1|Count/Thres 25/ 25|Queue: Size 1 Change +1 Load 0.06 Time 0us|Timestamp 758865671350686|Src octane-deltablue.js:416 +[engine] opt start id=237 BinaryConstraint.output |Tier 1|Priority 25|Rate 0.000000|Queue: Size 0 Change +0 Load 0.06 Time 0us|Timestamp 758865708273384|Src octane-deltablue.js:416 +[engine] opt queued id=239 OrderedCollection.size |Tier 1|Count/Thres 25/ 25|Queue: Size 1 Change +1 Load 0.06 Time 0us|Timestamp 758865727664193|Src octane-deltablue.js:71 +[engine] opt queued id=52 Array.prototype.push |Tier 1|Count/Thres 25/ 50|Queue: Size 2 Change +1 Load 0.13 Time 0us|Timestamp 758865744191674|Src :1 +... more log ... +[engine] opt start id=239 OrderedCollection.size |Tier 1|Priority 181875|Rate 0.000001|Queue: Size 11 Change -1 Load 0.63 Time 575us|Timestamp 758866381654116|Src octane-deltablue.js:71 +[engine] opt done id=237 BinaryConstraint.output |Tier 1|Time 717( 654+64 )ms|AST 19|Inlined 0Y 0N|IR 143/ 220|CodeSize 882|Timestamp 758866435391354|Src octane-deltablue.js:416 +[engine] opt start id=236 BinaryConstraint.input |Tier 1|Priority 144000|Rate 0.000001|Queue: Size 10 Change -1 Load 0.56 Time 48us|Timestamp 758866452554530|Src octane-deltablue.js:409 +... more log ... +[engine] opt queued id=239 OrderedCollection.size |Tier 2|Count/Thres 8750/ 8125|Queue: Size 18 Change +1 Load 0.81 Time 0us|Timestamp 758867756295139|Src octane-deltablue.js:71 +[engine] opt queued id=237 BinaryConstraint.output |Tier 2|Count/Thres 8499/ 8750|Queue: Size 19 Change +1 Load 0.88 Time 0us|Timestamp 758867758263099|Src octane-deltablue.js:416 +[engine] opt start id=244 EqualityConstraint.execute |Tier 1|Priority 2618289|Rate 0.000015|Queue: Size 19 Change -1 Load 0.88 Time 180us|Timestamp 758867767116908|Src octane-deltablue.js:528 ... more log ... -[engine] opt start id=237 BinaryConstraint.output | Tier 2 | Weight 256510 | Rate 0.00007 | Queue: Size 21 Change -1 Scale 1.00 Elapsed 17us | Src octane-deltablue.js:416 | Time 317056014011223 -[engine] opt done id=293 change | Tier 1 | Elapsed 271( 186+86 )ms | Src octane-deltablue.js:867 | Time 317056063627727 -[engine] opt start id=271 Plan.size | Tier 2 | Weight 233921 | Rate 0.00008 | Queue: Size 20 Change -1 Scale 1.00 Elapsed 26us | Src octane-deltablue.js:770 | Time 317056067292754 -[engine] opt done id=237 BinaryConstraint.output | Tier 2 | Elapsed 140( 124+17 )ms | Src octane-deltablue.js:416 | Time 317056154362876 +[engine] opt done id=246 OrderedCollection.at |Tier 2|Time 89( 80+9 )ms|AST 15|Inlined 0Y 0N|IR 50/ 110|CodeSize 582|Timestamp 758873628915755|Src octane-deltablue.js:67 +[engine] opt start id=237 BinaryConstraint.output |Tier 2|Priority 173536|Rate 0.000054|Queue: Size 18 Change -1 Load 0.94 Time 18us|Timestamp 758873629411012|Src octane-deltablue.js:416 +[engine] opt queued id=238 Planner.addPropagate |Tier 2|Count/Thres 9375/ 8750|Queue: Size 19 Change +1 Load 0.88 Time 0us|Timestamp 758873663196884|Src octane-deltablue.js:696 +[engine] opt queued id=226 Variable.addConstraint |Tier 2|Count/Thres 8771/ 9375|Queue: Size 20 Change +1 Load 0.94 Time 0us|Timestamp 758873665823697|Src octane-deltablue.js:556 +[engine] opt done id=293 change |Tier 1|Time 167( 130+37 )ms|AST 60|Inlined 0Y 6N|IR 576/ 1220|CodeSize 5554|Timestamp 758873669483749|Src octane-deltablue.js:867 +[engine] opt start id=270 Plan.execute |Tier 2|Priority 157871|Rate 0.000072|Queue: Size 19 Change -1 Load 1.00 Time 17us|Timestamp 758873669912101|Src octane-deltablue.js:778 +[engine] opt done id=237 BinaryConstraint.output |Tier 2|Time 58( 52+6 )ms|AST 19|Inlined 0Y 0N|IR 103/ 181|CodeSize 734|Timestamp 758873687678394|Src octane-deltablue.js:416 +... more log ... +[engine] opt unque. id=304 Date.prototype.valueOf |Tier 2|Count/Thres 80234/ 3125|Queue: Size 4 Change 0 Load 0.31 Time 0us|Timestamp 758899904132076|Src :1|Reason Target inlined into only caller ``` +Here is a quick overview of the information added in these logs: +- `Count/Thres` - What is the call and loop count of the target and what is the threshold needed to add the compilation to the queue. +- `Queue: Size` - How many compilations are in the compilation queue. +- `Queue: Change` - How did this event impact the compilation queue (e.g. certain events can prune the queue of unneeded compilation tasks). +- `Queue: Load` - A metric of whether the queue is over/under loaded. Normal load is represented with 1, less then 1 is underloaded and greater than 1 is overloaded. +- `Queue: Time` - How long did the event take. +- `Reason` - The runtime reported reason for the event. + The `--engine.TraceCompilationAST` command prints the Truffle AST for each compilation: ```shell From 25b5ca4d1bbd516c2504ce9b5fa110afb9468971 Mon Sep 17 00:00:00 2001 From: Francois Farquet Date: Wed, 13 Oct 2021 14:52:47 +0200 Subject: [PATCH 448/681] Fix db-shootout not found on JDK11 --- java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py index 4a68c7e4b5bb..dca79cad7239 100644 --- a/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py +++ b/java-benchmarks/mx.java-benchmarks/mx_java_benchmarks.py @@ -1850,16 +1850,16 @@ def renaissanceIterations(self): del benchmarks["naive-bayes"] del benchmarks["page-rank"] - if mx.get_arch() != "amd64" or mx.get_jdk().javaCompliance >= '11': + if mx.get_arch() != "amd64" or mx.get_jdk().javaCompliance > '11': # GR-33879 # JNA libraries needed are currently limited to amd64: renaissance-benchmarks/renaissance #153 del benchmarks["db-shootout"] if self.version() in ["0.9.0", "0.10.0", "0.11.0"]: - if mx.get_jdk().javaCompliance >= '11': + if mx.get_jdk().javaCompliance > '11': del benchmarks["neo4j-analytics"] else: - if mx.get_jdk().javaCompliance < '11' or mx.get_jdk().javaCompliance >= '15': + if mx.get_jdk().javaCompliance < '11' or mx.get_jdk().javaCompliance > '15': del benchmarks["neo4j-analytics"] return benchmarks From 3835a8cf14ba965ce8464e9732f11af5908356fc Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Wed, 13 Oct 2021 15:29:39 +0200 Subject: [PATCH 449/681] Ignore push events for mirrored PRs. --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8ae3f6512a89..502bdf800d84 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,6 +2,8 @@ name: GraalVM Gate on: push: + branches-ignore: + - 'github/**' paths-ignore: - '.travis.yml' - '.github/workflows/quarkus.yml' From 83e31860ae8c8287b01f3edcbd62bcab015ac116 Mon Sep 17 00:00:00 2001 From: Marjana Solajic Date: Sun, 10 Oct 2021 19:57:49 +0200 Subject: [PATCH 450/681] Collect information about call edges and print it with other analysis results statistics. --- .../reports/AnalysisReportsOptions.java | 14 +++++++++++++ .../pointsto/reports/StatisticsPrinter.java | 20 +++++++++++++++++++ vm/mx.vm/mx_vm_benchmark.py | 12 +++++++++++ 3 files changed, 46 insertions(+) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReportsOptions.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReportsOptions.java index 62b9e9d5780f..7bf1b7268946 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReportsOptions.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/AnalysisReportsOptions.java @@ -24,9 +24,12 @@ */ package com.oracle.graal.pointsto.reports; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; +import static com.oracle.graal.pointsto.api.PointstoOptions.TrackAccessChain; + public class AnalysisReportsOptions { @Option(help = "Print analysis results statistics.")// @@ -38,6 +41,17 @@ public class AnalysisReportsOptions { @Option(help = "Print analysis call tree, a breadth-first tree reduction of the call graph.")// public static final OptionKey PrintAnalysisCallTree = new OptionKey<>(false); + @Option(help = "Print call edges with other analysis results statistics.")// + public static final OptionKey PrintCallEdges = new OptionKey(false) { + @Override + protected void onValueUpdate(EconomicMap, Object> values, Boolean oldValue, Boolean newValue) { + if (newValue) { + PrintAnalysisStatistics.update(values, true); + TrackAccessChain.update(values, true); + } + } + }; + @Option(help = "Print image object hierarchy.")// public static final OptionKey PrintImageObjectTree = new OptionKey<>(false); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/StatisticsPrinter.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/StatisticsPrinter.java index 65ef2eb74e12..b9f6c3c4bd8c 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/StatisticsPrinter.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/StatisticsPrinter.java @@ -70,6 +70,11 @@ private void printStats(PrintWriter out) { beginObject(out); + if (AnalysisReportsOptions.PrintCallEdges.getValue(bb.getOptions())) { + int[] callEdges = getNumCallEdges(bb); + print(out, "total_call_edges", callEdges[0]); + print(out, "app_call_edges", callEdges[1]); + } print(out, "total_reachable_types", reachableTypes[0]); print(out, "app_reachable_types", reachableTypes[1]); print(out, "total_reachable_methods", reachableMethods[0]); @@ -108,6 +113,21 @@ public static void printLast(PrintWriter out, String key, long value) { out.format("%s\"%s\": %d%n", INDENT, key, value); } + private static int[] getNumCallEdges(BigBang bb) { + int callEdges = 0; + int appCallEdges = 0; + for (AnalysisMethod method : bb.getUniverse().getMethods()) { + if (method.isImplementationInvoked()) { + int callers = method.getCallers().size(); + callEdges += callers; + if (!isRuntimeLibraryType(method.getDeclaringClass())) { + appCallEdges += callers; + } + } + } + return new int[]{callEdges, appCallEdges}; + } + private static int[] getNumReachableTypes(BigBang bb) { int reachable = 0; int appReachable = 0; diff --git a/vm/mx.vm/mx_vm_benchmark.py b/vm/mx.vm/mx_vm_benchmark.py index 5482415a82d4..8756fcc9e073 100644 --- a/vm/mx.vm/mx_vm_benchmark.py +++ b/vm/mx.vm/mx_vm_benchmark.py @@ -161,6 +161,7 @@ def __init__(self, vm, bm_suite, args): self.base_image_build_args += ['-H:Path=' + self.output_dir] self.base_image_build_args += ['-H:ConfigurationFileDirectories=' + self.config_dir] self.base_image_build_args += ['-H:+PrintAnalysisStatistics', '-H:AnalysisStatisticsFile=' + self.analysis_report_path] + self.base_image_build_args += ['-H:+PrintCallEdges'] self.base_image_build_args += ['-H:+CollectImageBuildStatistics', '-H:ImageBuildStatisticsFile=' + self.image_build_report_path] self.base_image_build_args += ['-H:+ConfigureReflectionMetadata'] if vm.is_llvm: @@ -581,6 +582,17 @@ def __call__(self, *args, **kwargs): "metric.iteration": 0, "metric.object": ("
    ", str), }), + mx_benchmark.JsonStdOutFileRule(r'^# Printing analysis results stats to: (?P\S+?)$', 'path', { + "benchmark": benchmarks[0], + "metric.name": "analysis-stats", + "metric.type": "numeric", + "metric.unit": "#", + "metric.value": ("", int), + "metric.score-function": "id", + "metric.better": "lower", + "metric.iteration": 0, + "metric.object": "call-edges", + }, ['total_call_edges']), mx_benchmark.JsonStdOutFileRule(r'^# Printing analysis results stats to: (?P\S+?)$', 'path', { "benchmark": benchmarks[0], "metric.name": "analysis-stats", From e18ca33c1212acc27ab32b29c5cfdeb72554e4bb Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 23 Sep 2021 18:27:30 +0200 Subject: [PATCH 451/681] Cleanup shift constant folding and isNarrowable criteria. --- .../asm/aarch64/AArch64ASIMDAssembler.java | 25 +++++++--------- .../core/common/type/IntegerStamp.java | 30 ++++++++++++------- .../compiler/nodes/calc/RightShiftNode.java | 11 +++++-- .../compiler/nodes/calc/ShiftNode.java | 4 +-- .../nodes/calc/UnsignedRightShiftNode.java | 13 ++++++-- 5 files changed, 50 insertions(+), 33 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64ASIMDAssembler.java b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64ASIMDAssembler.java index aa7caaa48bd3..25870750d06a 100644 --- a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64ASIMDAssembler.java +++ b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64ASIMDAssembler.java @@ -2417,9 +2417,8 @@ public void scvtfVV(ASIMDSize size, ElementSize eSize, Register dst, Register sr * for i in 0..n-1 do dst[i] = src[i] << imm * * @param size register size. - * @param eSize element size. Must be ElementSize.Word or ElementSize.DoubleWord. Note - * ElementSize.DoubleWord is only applicable when size is 128 (i.e. the operation is - * performed on more than one element). + * @param eSize element size. ElementSize.DoubleWord is only applicable when size is 128 (i.e. + * the operation is performed on more than one element). * @param dst SIMD register. * @param src SIMD register. * @param shiftAmt shift amount. @@ -2554,9 +2553,8 @@ public void smovGX(ElementSize dstESize, ElementSize srcESize, Register dst, Reg * dst[i] = (src1[i] >> byte(src2[i]) * * @param size register size. - * @param eSize element size. Must be ElementSize.Word or ElementSize.DoubleWord. Note - * ElementSize.DoubleWord is only applicable when size is 128 (i.e. the operation is - * performed on more than one element). + * @param eSize element size. ElementSize.DoubleWord is only applicable when size is 128 (i.e. + * the operation is performed on more than one element). * @param dst SIMD register. * @param src1 SIMD register. * @param src2 SIMD register. @@ -2604,9 +2602,8 @@ public void sshllVVI(ElementSize srcESize, Register dst, Register src, int shift * for i in 0..n-1 do dst[i] = src[i] >> imm * * @param size register size. - * @param eSize element size. Must be ElementSize.Word or ElementSize.DoubleWord. Note - * ElementSize.DoubleWord is only applicable when size is 128 (i.e. the operation is - * performed on more than one element). + * @param eSize element size. ElementSize.DoubleWord is only applicable when size is 128 (i.e. + * the operation is performed on more than one element). * @param dst SIMD register. * @param src SIMD register. * @param shiftAmt shift right amount. @@ -2984,9 +2981,8 @@ public void umovGX(ElementSize eSize, Register dst, Register src, int index) { * dst[i] = (src1[i] >>> byte(src2[i]) * * @param size register size. - * @param eSize element size. Must be ElementSize.Word or ElementSize.DoubleWord. Note - * ElementSize.DoubleWord is only applicable when size is 128 (i.e. the operation is - * performed on more than one element). + * @param eSize element size. ElementSize.DoubleWord is only applicable when size is 128 (i.e. + * the operation is performed on more than one element). * @param dst SIMD register. * @param src1 SIMD register. * @param src2 SIMD register. @@ -3057,9 +3053,8 @@ public void ushrSSI(ElementSize eSize, Register dst, Register src, int shiftAmt) * dst = src >>> imm * * @param size register size. - * @param eSize element size. Must be ElementSize.Word or ElementSize.DoubleWord. Note - * ElementSize.DoubleWord is only applicable when size is 128 (i.e. the operation is - * performed on more than one element). + * @param eSize element size. ElementSize.DoubleWord is only applicable when size is 128 (i.e. + * the operation is performed on more than one element). * @param dst SIMD register. * @param src SIMD register. * @param shiftAmt shift right amount. diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java index abc5b5b156d6..9dcc2cad9222 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java @@ -1313,8 +1313,12 @@ public Constant getZero(Stamp s) { public Constant foldConstant(Constant value, int amount) { PrimitiveConstant c = (PrimitiveConstant) value; switch (c.getJavaKind()) { + case Byte: + return JavaConstant.forByte((byte) (c.asInt() << amount)); + case Char: + return JavaConstant.forChar((char) (c.asInt() << amount)); case Short: - return JavaConstant.forShort((short) (c.asLong() << amount)); + return JavaConstant.forShort((short) (c.asInt() << amount)); case Int: return JavaConstant.forInt(c.asInt() << amount); case Long: @@ -1381,9 +1385,7 @@ public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { @Override public int getShiftAmountMask(Stamp s) { - IntegerStamp stamp = (IntegerStamp) s; - assert CodeUtil.isPowerOf2(stamp.getBits()); - return stamp.getBits() - 1; + return s.getStackKind().getBitCount() - 1; } }, @@ -1393,8 +1395,12 @@ public int getShiftAmountMask(Stamp s) { public Constant foldConstant(Constant value, int amount) { PrimitiveConstant c = (PrimitiveConstant) value; switch (c.getJavaKind()) { + case Byte: + return JavaConstant.forByte((byte) (c.asInt() >> amount)); + case Char: + return JavaConstant.forChar((char) (c.asInt() >> amount)); case Short: - return JavaConstant.forShort((short) (c.asLong() >> amount)); + return JavaConstant.forShort((short) (c.asInt() >> amount)); case Int: return JavaConstant.forInt(c.asInt() >> amount); case Long: @@ -1431,9 +1437,7 @@ public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { @Override public int getShiftAmountMask(Stamp s) { - IntegerStamp stamp = (IntegerStamp) s; - assert CodeUtil.isPowerOf2(stamp.getBits()); - return stamp.getBits() - 1; + return s.getStackKind().getBitCount() - 1; } }, @@ -1443,6 +1447,12 @@ public int getShiftAmountMask(Stamp s) { public Constant foldConstant(Constant value, int amount) { PrimitiveConstant c = (PrimitiveConstant) value; switch (c.getJavaKind()) { + case Byte: + return JavaConstant.forByte((byte) (c.asInt() >>> amount)); + case Char: + return JavaConstant.forChar((char) (c.asInt() >>> amount)); + case Short: + return JavaConstant.forShort((short) (c.asInt() >>> amount)); case Int: return JavaConstant.forInt(c.asInt() >>> amount); case Long: @@ -1482,9 +1492,7 @@ public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { @Override public int getShiftAmountMask(Stamp s) { - IntegerStamp stamp = (IntegerStamp) s; - assert CodeUtil.isPowerOf2(stamp.getBits()); - return stamp.getBits() - 1; + return s.getStackKind().getBitCount() - 1; } }, diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java index 572b30db7277..9294d4e03166 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java @@ -32,12 +32,12 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import jdk.vm.ci.code.CodeUtil; @@ -163,7 +163,14 @@ public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool @Override public boolean isNarrowable(int resultBits) { - if (super.isNarrowable(resultBits)) { + /* + * Note that inserting a narrow before this node can change the input's stamp, as it can + * cause a preceding (Zero|Sign)ExtendNode to be canonicalized away. + * + * Therefore, since the scalar shift on the underlying hardware will be on either a 32 or 64 + * bit operation, if resultBits < Integer.SIZE, the input to the shift cannot be narrowed. + */ + if (resultBits >= Integer.SIZE && super.isNarrowable(resultBits)) { /* * For signed right shifts, the narrow can be done before the shift if the cut off bits * are all equal to the sign bit of the input. That's equivalent to the condition that diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java index a4642bda8761..90ee93522cb1 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java @@ -33,13 +33,13 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ArithmeticOperation; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.JavaConstant; @@ -107,7 +107,7 @@ public int getShiftAmountMask() { @Override public boolean isNarrowable(int resultBits) { assert CodeUtil.isPowerOf2(resultBits); - int narrowMask = resultBits - 1; + int narrowMask = resultBits <= 32 ? Integer.SIZE - 1 : Long.SIZE - 1; int wideMask = getShiftAmountMask(); assert (wideMask & narrowMask) == narrowMask : String.format("wideMask %x should be wider than narrowMask %x", wideMask, narrowMask); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java index 7e2e0456945f..df0d7f921e88 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java @@ -32,12 +32,12 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import jdk.vm.ci.code.CodeUtil; @@ -146,13 +146,20 @@ public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool @Override public boolean isNarrowable(int resultBits) { - if (super.isNarrowable(resultBits)) { + /* + * Note that inserting a narrow before this node can change the input's stamp, as it can + * cause a preceding (Zero|Sign)ExtendNode to be canonicalized away. + * + * Therefore, since the scalar shift on the underlying hardware will be on either a 32 or 64 + * bit operation, if resultBits < Integer.SIZE, the input to the shift cannot be narrowed. + */ + if (resultBits >= Integer.SIZE && super.isNarrowable(resultBits)) { /* * For unsigned right shifts, the narrow can be done before the shift if the cut off * bits are all zero. */ IntegerStamp inputStamp = (IntegerStamp) getX().stamp(NodeView.DEFAULT); - return (inputStamp.upMask() & ~(resultBits - 1)) == 0; + return (inputStamp.upMask() & ~(CodeUtil.mask(resultBits))) == 0; } else { return false; } From 263f8ade98619ee273daeca9804d7ee20daaf31c Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Mon, 11 Oct 2021 12:35:00 +0200 Subject: [PATCH 452/681] Use toolchains for musl cross-compilation and improve docs for building static native-images. --- .../native-image/StaticImages.md | 55 ++++++++----------- substratevm/ci_includes/gate.hocon | 7 +-- substratevm/mx.substratevm/mx_substratevm.py | 17 +----- .../svm/core/posix/linux/libc/MuslLibC.java | 2 +- 4 files changed, 28 insertions(+), 53 deletions(-) diff --git a/docs/reference-manual/native-image/StaticImages.md b/docs/reference-manual/native-image/StaticImages.md index 73bfbb34e228..fe152f33a0b3 100644 --- a/docs/reference-manual/native-image/StaticImages.md +++ b/docs/reference-manual/native-image/StaticImages.md @@ -7,19 +7,32 @@ permalink: /reference-manual/native-image/StaticImages/ # Static Native Images Static native images are statically linked binaries which can be used without any additional library dependencies. -This makes them suitable for use in a Docker container. +This makes them suitable for use in a Docker container. Static native images are created by statically linking against [musl-libc](https://www.musl-libc.org/), an alternative libc implementation. ## Prerequisites - Right now, this only works on Linux AMD64 on Java 11. - - You will need `gcc`, `make`, and `configure`. - - Create a directory that will hold the libraries you build. You will refer to this directory as `${RESULT_DIR}`. - - Download the latest `musl` release [here](https://musl.libc.org/). This document will use `musl-1.2.0`. - - Download the latest `zlib` release [here](https://zlib.net/). This document will use `zlib-1.2.11`. - - ## Build a Static Native Image + - You will need a 64-bit `musl` toolchain, `make`, and `configure`. + - You can download the musl toolchain from [musl.cc](musl.cc), specifically [this one](http://musl.cc/x86_64-linux-musl-native.tgz) + - Download the latest `zlib` release sources [here](https://zlib.net/). This document will use `zlib-1.2.11`. + +## Preparing The Toolchain And Compiling Zlib + - Extract the toolchain to a directory of your choice. We will refer to this directory as `$TOOLCHAIN_DIR`. + - Extract the zlib sources. + - Set the following environment variable: `CC=$TOOLCHAIN_DIR/bin/gcc`. + - Move into the zlib directory, and then run the following to compile and install zlib into the toolchain: +``` +./configure --prefix=$TOOLCHAIN_DIR --static +make +make install +``` +## Build a Static Native Image -If you have `musl-gcc` on the path, you can build a native image statically linked against `muslc` with the following options: `--static --libc=musl`. -To verify that `musl-gcc` is on the path, run `musl-gcc -v`. +First, ensure `$TOOLCHAIN_DIR/bin` is present on your `PATH` variable. To verify this, try running: +``` +$ x86_64-linux-musl-gcc +x86_64-linux-musl-gcc: fatal error: no input files +compilation terminated. +``` To build a static native image, use: ```shell @@ -36,26 +49,4 @@ To build a mostly-static native image native image, use: native-image -H:+StaticExecutableWithDynamicLibC [other arguments] Class ``` -#### Building musl - - Extract the musl release `tarball` and `cd` into the extracted directory. - - Run `./configure --disable-shared --prefix=${RESULT_DIR}`. - - Run `make`. - - Run `make install`. -Other than building `musl` libraries, the build also creates a `gcc` wrapper called `musl-gcc` in the `${RESULT_DIR}/bin` directory. -You should now put this wrapper on your `PATH` by running `export PATH=$PATH:${RESULT_DIR}/bin`. - -#### Building zlib - - Extract the zlib release `tarball` and `cd` into the extracted directory. - - You need to compile zlib and link it against musl so set `CC` to `musl-gcc`: `export CC=musl-gcc`. - - Run `./configure --static --prefix=${RESULT_DIR}`. - - Run `make`. - - Run `make install`. - -#### Getting libstdc++ -`libstdc++` is obtained by building gcc. There are multiple approaches to obtaining it: - 1. Build gcc with `musl-gcc`. - 2. Use `libstdc++.a` from your distribution. If you choose this path, check the [FAQs](https://www.musl-libc.org/faq.html) page, "How do I use the musl-gcc wrapper?": - > The existing libstdc++ is actually compatible with musl in most cases and could be used by copying it into the musl library path, but the C++ header files are usually not compatible. - > Since you do not need C++ header files, this approach should work. If you run into issues, make sure they are not caused by your ditribution's `libstdc++.a`. - 3. Take `libstdc++.a` from Alpine. -In each case, `libstdc++.a` must be placed in `${RESULT_DIR}/lib`. +Note that this currently only works for `glibc`. diff --git a/substratevm/ci_includes/gate.hocon b/substratevm/ci_includes/gate.hocon index e5cd60e10be3..74c9522d1c5d 100644 --- a/substratevm/ci_includes/gate.hocon +++ b/substratevm/ci_includes/gate.hocon @@ -28,17 +28,16 @@ builds += [ ${labsjdk-ce-11} ${svm-common-linux-gate} ${linux-deploy} { name: "gate-svm-build-ce-11" downloads: { - "MUSL_LIBS": { - "name": "musl-libs", + "MUSL_TOOLCHAIN": { + "name": "musl-toolchain", "version": "1.0", "platformspecific": true } } environment : { - PATH : "$MUSL_LIBS/bin:$PATH" + PATH : "$PATH:$MUSL_TOOLCHAIN/bin" } run: [ - ["$MUSL_LIBS/fix_paths.sh"] ${svm-cmd-gate} ["build,helloworld,test,nativeimagehelp,muslcbuild"] ] } diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 37dd06192c7a..2d468388df9e 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -116,16 +116,6 @@ def svmbuild_dir(suite=None): return join(suite.dir, 'svmbuild') -def is_musl_gcc_wrapper_on_path(): - mx.logv('Probing if musl-gcc exists on path.') - throwaway_capture = mx.LinesOutputCapture() - try: - ret_code = mx.run(['musl-gcc', '-v'], nonZeroIsFatal=False, out=throwaway_capture, err=throwaway_capture) - return ret_code == 0 - except OSError as _: - return False - - def is_musl_supported(): jdk = mx.get_jdk(tag='default') if mx.is_linux() and mx.get_arch() == "amd64" and mx.get_jdk(tag='default').javaCompliance == '11': @@ -243,10 +233,7 @@ def vm_executable_path(executable, config=None): def run_musl_basic_tests(): if is_musl_supported(): - if is_musl_gcc_wrapper_on_path(): - helloworld(['--output-path', svmbuild_dir(), '--static', '--libc=musl']) - else: - mx.abort('Attempted to run musl tests without a musl-gcc wrapper.') + helloworld(['--output-path', svmbuild_dir(), '--static', '--libc=musl']) @contextmanager @@ -1578,7 +1565,5 @@ def javac_image(args): doc_string = "Runs a musl based Hello World static native-image with custom build arguments." @mx.command(suite.name, command_name='muslhelloworld', usage_msg='[options]', doc_function=lambda: doc_string) def musl_helloworld(args, config=None): - if not is_musl_gcc_wrapper_on_path(): - mx.abort('musl-gcc wrapper not detected on path. Cannot run musl helloworld. Please consult substratevm/StaticImages.md') final_args = ['--static', '--libc=musl'] + args run_helloworld_command(final_args, config, 'muslhelloworld') diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/libc/MuslLibC.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/libc/MuslLibC.java index 3d6dd56c86a1..34921859d4b1 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/libc/MuslLibC.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/libc/MuslLibC.java @@ -49,7 +49,7 @@ public List getAdditionalQueryCodeCompilerOptions() { @Override public String getTargetCompiler() { - return "musl-gcc"; + return "x86_64-linux-musl-gcc"; } @Override From 63cc1fbc25ac714f8bb8eee17b75cab4fbbbebef Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 12 Oct 2021 12:33:17 +0300 Subject: [PATCH 453/681] Review the Static Native Images guide --- .../native-image/StaticImages.md | 62 ++++++++++++------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/docs/reference-manual/native-image/StaticImages.md b/docs/reference-manual/native-image/StaticImages.md index fe152f33a0b3..b23b3bf5a742 100644 --- a/docs/reference-manual/native-image/StaticImages.md +++ b/docs/reference-manual/native-image/StaticImages.md @@ -6,47 +6,63 @@ permalink: /reference-manual/native-image/StaticImages/ --- # Static Native Images -Static native images are statically linked binaries which can be used without any additional library dependencies. -This makes them suitable for use in a Docker container. Static native images are created by statically linking against [musl-libc](https://www.musl-libc.org/), an alternative libc implementation. +Static native images are statically linked binaries which can be used without any additional library dependencies, which makes them suitable for use in containers. +They are created by statically linking against [musl-libc](https://musl.libc.org/), an alternative `libc` implementation. + + ## Prerequisites - - Right now, this only works on Linux AMD64 on Java 11. - - You will need a 64-bit `musl` toolchain, `make`, and `configure`. - - You can download the musl toolchain from [musl.cc](musl.cc), specifically [this one](http://musl.cc/x86_64-linux-musl-native.tgz) - - Download the latest `zlib` release sources [here](https://zlib.net/). This document will use `zlib-1.2.11`. - -## Preparing The Toolchain And Compiling Zlib - - Extract the toolchain to a directory of your choice. We will refer to this directory as `$TOOLCHAIN_DIR`. - - Extract the zlib sources. - - Set the following environment variable: `CC=$TOOLCHAIN_DIR/bin/gcc`. - - Move into the zlib directory, and then run the following to compile and install zlib into the toolchain: -``` -./configure --prefix=$TOOLCHAIN_DIR --static -make -make install -``` + +- Linux AMD64 operating system +- GraalVM distribution for Java 11 with [Native Image support](README.md#install-native-image) +- A 64-bit `musl` toolchain, `make`, and `configure` +- The latest `zlib` library + +## Preparation + +You should get the `musl` toolchain first, and then compile and install `zlib` into the toolchain. + +1. Download the `musl` toolchain from [musl.cc](musl.cc). [This one](http://musl.cc/x86_64-linux-musl-native.tgz) is recommended. Extract the toolchain to a directory of your choice. This directory will be referred as `$TOOLCHAIN_DIR`. +2. Download the latest `zlib` library sources from [here](https://zlib.net/) and extract them. This guide uses `zlib-1.2.11`. +3. Set the following environment variable: + ```bash + CC=$TOOLCHAIN_DIR/bin/gcc + ``` +4. Change into the `zlib` directory, and then run the following commands to compile and install `zlib` into the toolchain: + ```bash + ./configure --prefix=$TOOLCHAIN_DIR --static + make + make install + ``` + ## Build a Static Native Image -First, ensure `$TOOLCHAIN_DIR/bin` is present on your `PATH` variable. To verify this, try running: +First, ensure `$TOOLCHAIN_DIR/bin` is present on your `PATH` variable. +To verify this, run: + +```bash +x86_64-linux-musl-gcc ``` -$ x86_64-linux-musl-gcc +You should get a similar output printed: +```bash x86_64-linux-musl-gcc: fatal error: no input files compilation terminated. ``` -To build a static native image, use: +To build a static native image, use this command: ```shell native-image --static --libc=musl [other arguments] Class ``` ## Build a Mostly Static Native Image -As of GraalVM version 20.2, you can build a “mostly static” native image which link statically everything except `libc`. Native images built this way are convenient to run in Docker containers, for example, based on +As of GraalVM version 20.2, you can build a “mostly static” native image which link statically everything except `libc`. +Native images built this way are convenient to run in Docker containers, for example, based on [distroless minimal Linux, glibc-based systems](https://github.com/GoogleContainerTools/distroless/blob/master/base/README.md). -To build a mostly-static native image native image, use: +To build a mostly-static native image native image, use this command: ```shell native-image -H:+StaticExecutableWithDynamicLibC [other arguments] Class ``` -Note that this currently only works for `glibc`. +> Note: This currently only works for `glibc`. From d7d9812d4cd23944b63d68796a6c13a33cfd1fa4 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 12 Oct 2021 12:38:01 +0300 Subject: [PATCH 454/681] Review the Reflection Use in Native Images guide --- .../native-image/Reflection.md | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/reference-manual/native-image/Reflection.md b/docs/reference-manual/native-image/Reflection.md index 86176c7e3a16..dbd09af22744 100644 --- a/docs/reference-manual/native-image/Reflection.md +++ b/docs/reference-manual/native-image/Reflection.md @@ -4,6 +4,12 @@ toc_group: native-image link_title: Reflection on Native Image permalink: /reference-manual/native-image/Reflection/ --- + +* [Automatic Detection](#automatic-detection) +* [Manual Configuration](#manual-configuration) +* [Conditional Configuration](#conditional-configuration) +* [Configuration with Features](#configuration-with-features) + # Reflection Use in Native Images Java reflection support (the `java.lang.reflect.*` API) enables Java code to examine its own classes, methods, fields and their properties at run time. @@ -128,7 +134,9 @@ Also, `-H:ReflectionConfigurationResources` can be specified to load one or seve ### Conditional Configuration -With conditional configuraiton, a class configuration entry is applied only if a provided `condition` is satisfied. The only currently supported condition is `typeReachable`, which enables the configuration entry if the specified type is reachable through other code. For example, to support reflective access to `sun.misc.Unsafe.theUnsafe` only when `io.netty.util.internal.PlatformDependent0` is reachable, the configuration should look like: +With conditional configuration, a class configuration entry is applied only if a provided `condition` is satisfied. +The only currently supported condition is `typeReachable`, which enables the configuration entry if the specified type is reachable through other code. +For example, to support reflective access to `sun.misc.Unsafe.theUnsafe` only when `io.netty.util.internal.PlatformDependent0` is reachable, the configuration should look like: ```json { @@ -140,11 +148,14 @@ With conditional configuraiton, a class configuration entry is applied only if a } ``` -Conditional configuration is the *preferred* way to specify reflection configuration: if code doing a reflective access is not reachable, it is unnecessary to include its corresponding reflection entry. The consistent usage of `condition` results in *smaller binaries* and *better build times* as the image builder can selectively include reflectively accessed code. +Conditional configuration is the **preferred** way to specify reflection configuration: if code doing a reflective access is not reachable, it is unnecessary to include its corresponding reflection entry. +The consistent usage of `condition` results in *smaller binaries* and *better build times* as the image builder can selectively include reflectively accessed code. -If a `condition` is omitted, the element is always included. When the same `condition` is used for two distinct elements in two configuration entries, both elements will be included when the condition is satisfied. When a configuration entry should be enabled if one of several types are reachable, it is necessary to add two configuration entries: one entry for each condition. +If a `condition` is omitted, the element is always included. +When the same `condition` is used for two distinct elements in two configuration entries, both elements will be included when the condition is satisfied. +When a configuration entry should be enabled if one of several types are reachable, it is necessary to add two configuration entries: one entry for each condition. -When used with [assisted configuration](BuildConfiguration.md#assisted-configuration-of-native-image-builds), conditional entries of existing configuration will not be fused with agent-collected entries as agent-collected entries. +When used with [assisted configuration](BuildConfiguration.md#assisted-configuration-of-native-image-builds), conditional entries of existing configuration will not be fused with agent-collected entries. ### Configuration with Features @@ -173,4 +184,6 @@ Reflection can be used without restrictions during a native image generation, fo At this point, code can collect information about methods and fields and store them in their own data structures, which are then reflection-free at run time. ### Unsafe Accesses -The `Unsafe` class, although its use is discouraged, provides direct access to the memory of Java objects. The `Unsafe.objectFieldOffset()` method provides the offset of a field within a Java object. Note that the offsets that are queried during native image generation can be different from the offsets at run time. +The `Unsafe` class, although its use is discouraged, provides direct access to the memory of Java objects. +The `Unsafe.objectFieldOffset()` method provides the offset of a field within a Java object. +Note that the offsets that are queried during native image generation can be different from the offsets at run time. From 3ca5b5c169a0fb89989ae22dbc041a39fe29c8c5 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Tue, 12 Oct 2021 14:29:40 +0300 Subject: [PATCH 455/681] Include FAQ --- docs/reference-manual/native-image/StaticImages.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/reference-manual/native-image/StaticImages.md b/docs/reference-manual/native-image/StaticImages.md index b23b3bf5a742..23fd0db94bfe 100644 --- a/docs/reference-manual/native-image/StaticImages.md +++ b/docs/reference-manual/native-image/StaticImages.md @@ -66,3 +66,16 @@ native-image -H:+StaticExecutableWithDynamicLibC [other arguments] Class ``` > Note: This currently only works for `glibc`. + +## Frequently Asked Questions + +### What Docker image type is recommended to build a static native image? +There are different docker images types you can convert a Java application into: +* Slim +* Distroless +* Alpine +* Scratch + +Whatever base image you choose is determined by what you want to run in container. +Basically, with a static native image statically linked against `muslc`, you can dockerize into anything: from scratch, Alpine, Ubuntu, Oracle Linux, etc. +With mostly static native image (distroless) linking statically everything except `libc`, you can dockerize into a distribution with the matching `libc` (currently `glibc` only), so Ubuntu, Oracle Linux,etc. From 43290c11e031ea2048d53465cde99b511ad9f541 Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Tue, 12 Oct 2021 14:22:48 +0200 Subject: [PATCH 456/681] Add a comment explaining why the toolchain has to be added at the end of the PATH --- .../native-image/StaticImages.md | 27 +++++++++---------- substratevm/ci_includes/gate.hocon | 3 +++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docs/reference-manual/native-image/StaticImages.md b/docs/reference-manual/native-image/StaticImages.md index 23fd0db94bfe..21d43db3f845 100644 --- a/docs/reference-manual/native-image/StaticImages.md +++ b/docs/reference-manual/native-image/StaticImages.md @@ -6,8 +6,13 @@ permalink: /reference-manual/native-image/StaticImages/ --- # Static Native Images -Static native images are statically linked binaries which can be used without any additional library dependencies, which makes them suitable for use in containers. -They are created by statically linking against [musl-libc](https://musl.libc.org/), an alternative `libc` implementation. +Static native images are statically linked binaries which can be used without any additional library dependencies, which makes them easier to distribute and to deploy on slim or distroless container images. +They are created by statically linking against [musl-libc](https://musl.libc.org/), a lightweight, fast and simple `libc` implementation. + +# Mostly Static Native Images + +Mostly static native images statically link against all libraries except libc. This approach is ideal for deploying such a native-image +on distroless container images. Note that this currently only works when linking against `glibc`. @@ -56,9 +61,8 @@ native-image --static --libc=musl [other arguments] Class ## Build a Mostly Static Native Image -As of GraalVM version 20.2, you can build a “mostly static” native image which link statically everything except `libc`. -Native images built this way are convenient to run in Docker containers, for example, based on -[distroless minimal Linux, glibc-based systems](https://github.com/GoogleContainerTools/distroless/blob/master/base/README.md). +As of GraalVM version 20.2, you can build a “mostly static” native image which statically links everything except `libc`. +Statically linking all your libraries except glibc ensures your application has all the libraries it needs to run on any Linux glibc-based distro. To build a mostly-static native image native image, use this command: ```shell @@ -69,13 +73,8 @@ native-image -H:+StaticExecutableWithDynamicLibC [other arguments] Class ## Frequently Asked Questions -### What Docker image type is recommended to build a static native image? -There are different docker images types you can convert a Java application into: -* Slim -* Distroless -* Alpine -* Scratch +### What is the recommended base Docker image for deploying a static/mostly static native image? -Whatever base image you choose is determined by what you want to run in container. -Basically, with a static native image statically linked against `muslc`, you can dockerize into anything: from scratch, Alpine, Ubuntu, Oracle Linux, etc. -With mostly static native image (distroless) linking statically everything except `libc`, you can dockerize into a distribution with the matching `libc` (currently `glibc` only), so Ubuntu, Oracle Linux,etc. +A fully static native-image gives you the most flexibility to choose a base image - it can run on anything including a `FROM scratch` image. +A mostly static native-image requires a container image that provides glibc, but has no additional requirements. +In both cases, choosing the base image mostly depends on what your particular native-image needs without having to worry about runtime library dependencies. diff --git a/substratevm/ci_includes/gate.hocon b/substratevm/ci_includes/gate.hocon index 74c9522d1c5d..4635d21048e2 100644 --- a/substratevm/ci_includes/gate.hocon +++ b/substratevm/ci_includes/gate.hocon @@ -35,6 +35,9 @@ builds += [ } } environment : { + # Note that we must add the toolchain to the end of the PATH so that the system gcc still remains the first choice + # for building the rest of GraalVM. The musl toolchain also provides a gcc executable that would shadow the system one + # if it were added at the start of the PATH. PATH : "$PATH:$MUSL_TOOLCHAIN/bin" } run: [ From 46eb9678aca66d79194765cdb49fb0ac2be18b85 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Wed, 13 Oct 2021 18:29:00 +0300 Subject: [PATCH 457/681] Proofread Certificate Management in Native Image doc --- .../embedding/embed-languages.md | 4 +- .../native-image/CertificateManagement.md | 68 +++++++------------ 2 files changed, 26 insertions(+), 46 deletions(-) diff --git a/docs/reference-manual/embedding/embed-languages.md b/docs/reference-manual/embedding/embed-languages.md index af23ca87db09..78391fc3e7e3 100644 --- a/docs/reference-manual/embedding/embed-languages.md +++ b/docs/reference-manual/embedding/embed-languages.md @@ -19,7 +19,7 @@ permalink: /reference-manual/embed-languages/ * [Embed languages in Guest Languages](#embed-languages-in-guest-languages) * [Build a Shell for Many Languages](#build-a-shell-for-many-languages) * [Step Through with Execution Listeners](#step-through-with-execution-listeners) -* [Configure Sandbox Resource Limits](#configure-sandbox-resource-limits) +* [Enterprise Sandbox Resource Limits](#enterprise-sandbox-resource-limits) The GraalVM Polyglot API lets you embed and run code from guest languages in JVM-based host applications. @@ -632,5 +632,5 @@ In this code: - The `context.eval()` call evaluates a specified snippet of guest language code. - The `listener.close()` closes a listener earlier, however execution listeners are automatically closed with the engine. - + {% include_relative sandbox-options.md %} diff --git a/docs/reference-manual/native-image/CertificateManagement.md b/docs/reference-manual/native-image/CertificateManagement.md index bf75632ad19e..e5cfd436e51a 100644 --- a/docs/reference-manual/native-image/CertificateManagement.md +++ b/docs/reference-manual/native-image/CertificateManagement.md @@ -6,60 +6,40 @@ permalink: /reference-manual/native-image/CertificateManagement/ --- # Certificate Management in Native Image -Native-image provides multiple ways to specify the certificate file used to -define the default TrustStore. In the following sections we describe the -available buildtime and runtime options. Note the default behavior for -native-image is to capture and use the default TrustStore from the buildtime -host environment. +Native Image provides multiple ways to specify the certificate file used to define the default TrustStore. +In the following sections we describe the available build-time and run-time options. +Note: The default behavior for `native-image` is to capture and use the default TrustStore from the build-time host environment. -## Buildtime Options +## Build-time Options -During the image building process, native-image captures the host environment's -default TrustStore and embeds it into the native image. This TrustStore is -by default created from the root certificate file provided within the JDK, but -can be changed to use a different certificate file by setting the buildtime -system property "javax.net.ssl.trustStore" (see [Properties](Properties.md) for -how to do so). +During the image building process, the `native-image` builder captures the host environment's default TrustStore and embeds it into the native executable. +This TrustStore is by default created from the root certificate file provided within the JDK, but can be changed to use a different certificate file by setting the build-time system property `javax.net.ssl.trustStore` (see [Properties](Properties.md) for how to do it). -Since the contents of the buildtime certificate file is embedded into the image -executable, the file itself does not need to present in the target environment. +Since the contents of the build-time certificate file is embedded into the native executable, the file itself does not need to be present in the target environment. -## Runtime Options +## Run-time Options -The certificate file can also be changed dynamically at runtime via setting -the "javax.net.ssl.trustStore\*" system properties. +The certificate file can also be changed dynamically at run time via setting the `javax.net.ssl.trustStore\*` system properties. -If any of the following system properties are set during image execution, -native-image also requires "javax.net.ssl.trustStore" to be set and for it -to point to an accessible certificate file: -- javax.net.ssl.trustStore -- javax.net.ssl.trustStoreType -- javax.net.ssl.trustStoreProvider -- javax.net.ssl.trustStorePassword +If any of the following system properties are set during the image execution, `native-image` also requires `javax.net.ssl.trustStore` to be set, and for it to point to an accessible certificate file: +- `javax.net.ssl.trustStore` +- `javax.net.ssl.trustStoreType` +- `javax.net.ssl.trustStoreProvider` +- `javax.net.ssl.trustStorePassword` -If any of these properties are set and "javax.net.ssl.trustStore" does not point -to an accessible file, then an UnsupportedFeatureError will be thrown. +If any of these properties are set and `javax.net.ssl.trustStore` does not point to an accessible file, then an `UnsupportedFeatureError` will be thrown. -Note that this behavior is different than OpenJDK. When the -"javax.net.ssl.trustStore" system property is unset/invalid, OpenJDK will -fallback to using a certificate file shipped within the JDK; however, such -files will not be present alongside the image executable and hence cannot be -used as a fallback. +Note that this behavior is different than OpenJDK. +When the `javax.net.ssl.trustStore` system property is unset or invalid, OpenJDK will fallback to using a certificate file shipped within the JDK. +However, such files will not be present alongside the image executable and hence cannot be used as a fallback. -During the execution, it also possible to dynamically change the -"javax.net.ssl.trustStore\*" properties and for the default TrustStore to be -updated accordingly. +During the execution, it also possible to dynamically change the `javax.net.ssl.trustStore\*` properties and for the default TrustStore to be updated accordingly. -Finally, whenever all of the "javax.net.ssl.trustStore\*" system properties -listed above are unset, the default TrustStore will be the one captured during -buildtime, as described in the [prior section](#buildtime-options). +Finally, whenever all of the `javax.net.ssl.trustStore\*` system properties listed above are unset, the default TrustStore will be the one captured during the build time, as described in the [prior section](#build-time-options). ## Untrusted Certificates -During the image building process, a list of untrusted certificates is loaded -from the file /lib/security/blacklisted.certs. This file is used -when validating certificates at both buildtime and runtime. In other words, -when a new certificate file is specified at runtime via setting the -"javax.net.ssl.trustStore\*" system properties, the new certificates will still -be checked against the /lib/security/blacklisted.certs loaded at -image buildtime. +During the image building process, a list of untrusted certificates is loaded from the file `/lib/security/blacklisted.certs`. +This file is used when validating certificates at both build time and run time. +In other words, when a new certificate file is specified at run time via setting the `javax.net.ssl.trustStore\*` system properties, the new certificates will still be checked against the `/lib/security/blacklisted.certs` loaded at +image build time. From 852ceca8f612fa6dfce096a77ee80b1ff88083cc Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Wed, 13 Oct 2021 18:56:47 +0300 Subject: [PATCH 458/681] Proofread StaticImages.md guide --- .../native-image/StaticImages.md | 59 +++++++++---------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/docs/reference-manual/native-image/StaticImages.md b/docs/reference-manual/native-image/StaticImages.md index 21d43db3f845..c97ae1447308 100644 --- a/docs/reference-manual/native-image/StaticImages.md +++ b/docs/reference-manual/native-image/StaticImages.md @@ -4,17 +4,17 @@ toc_group: native-image link_title: Static Native Images permalink: /reference-manual/native-image/StaticImages/ --- -# Static Native Images +# Static and Mostly Static Images -Static native images are statically linked binaries which can be used without any additional library dependencies, which makes them easier to distribute and to deploy on slim or distroless container images. -They are created by statically linking against [musl-libc](https://musl.libc.org/), a lightweight, fast and simple `libc` implementation. - -# Mostly Static Native Images +With GraalVM Native Image you can create static or mostly static images, depending on the purposes. -Mostly static native images statically link against all libraries except libc. This approach is ideal for deploying such a native-image -on distroless container images. Note that this currently only works when linking against `glibc`. +**Static native images** are statically linked binaries which can be used without any additional library dependencies. +This makes them easier to distribute and to deploy on slim or distroless container images. +They are created by statically linking against [musl-libc](https://musl.libc.org/), a lightweight, fast and simple `libc` implementation. - +**Mostly static native images** statically link against all libraries except `libc`. +This approach is ideal for deploying such native images on distroless container images. +Note that it currently only works when linking against `glibc`. ## Prerequisites @@ -40,29 +40,28 @@ You should get the `musl` toolchain first, and then compile and install `zlib` i make install ``` -## Build a Static Native Image - -First, ensure `$TOOLCHAIN_DIR/bin` is present on your `PATH` variable. -To verify this, run: +## Build Static Native Image -```bash -x86_64-linux-musl-gcc -``` -You should get a similar output printed: -```bash -x86_64-linux-musl-gcc: fatal error: no input files -compilation terminated. -``` +1. First, ensure `$TOOLCHAIN_DIR/bin` is present on your `PATH` variable. + To verify this, run: + ```bash + x86_64-linux-musl-gcc + ``` + You should get a similar output printed: + ```bash + x86_64-linux-musl-gcc: fatal error: no input files + compilation terminated. + ``` -To build a static native image, use this command: -```shell -native-image --static --libc=musl [other arguments] Class -``` +2. Build a static native image by using this command: + ```shell + native-image --static --libc=musl [other arguments] Class + ``` -## Build a Mostly Static Native Image +## Build Mostly Static Native Image As of GraalVM version 20.2, you can build a “mostly static” native image which statically links everything except `libc`. -Statically linking all your libraries except glibc ensures your application has all the libraries it needs to run on any Linux glibc-based distro. +Statically linking all your libraries except `glibc` ensures your application has all the libraries it needs to run on any Linux `glibc`-based distribution. To build a mostly-static native image native image, use this command: ```shell @@ -73,8 +72,8 @@ native-image -H:+StaticExecutableWithDynamicLibC [other arguments] Class ## Frequently Asked Questions -### What is the recommended base Docker image for deploying a static/mostly static native image? +### What is the recommended base Docker image for deploying a static or mostly static native image? -A fully static native-image gives you the most flexibility to choose a base image - it can run on anything including a `FROM scratch` image. -A mostly static native-image requires a container image that provides glibc, but has no additional requirements. -In both cases, choosing the base image mostly depends on what your particular native-image needs without having to worry about runtime library dependencies. +A fully static native image gives you the most flexibility to choose a base image - it can run on anything including a `FROM scratch` image. +A mostly static native image requires a container image that provides `glibc`, but has no additional requirements. +In both cases, choosing the base image mostly depends on what your particular native image needs without having to worry about run-time library dependencies. From d94afac581417e942a4532306badd1db30b037de Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Wed, 13 Oct 2021 20:35:35 +0200 Subject: [PATCH 459/681] Fix fetch-jdk invocation. --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 502bdf800d84..665791851b83 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -125,7 +125,7 @@ jobs: env: ${{ matrix.env }} run: | mkdir jdk-dl - ${MX_PATH}/mx fetch-jdk --jdk-id ${JDK} --to jdk-dl --alias ${JAVA_HOME} + ${MX_PATH}/mx --java-home= fetch-jdk --jdk-id ${JDK} --to jdk-dl --alias ${JAVA_HOME} - name: Update dependency cache if: ${{ contains(matrix.env.GATE, 'debug') || contains(matrix.env.GATE, 'style') }} run: sudo apt update From 410c10dae6db0243370455aaafdf1a79ebe0f020 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 13 Oct 2021 23:05:30 +0200 Subject: [PATCH 460/681] added OnShutdownCallback option to libgraal --- .../hotspot/test/CompileTheWorld.java | 2 +- .../org/graalvm/libgraal/LibGraalScope.java | 11 ++++++++++ .../org/graalvm/nativebridge/jni/JNIUtil.java | 22 +++++++++++++++++++ .../hotspot/libgraal/LibGraalEntryPoints.java | 9 ++++++-- .../hotspot/libgraal/LibGraalFeature.java | 21 +++++++++++++++++- 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java index fa0691b85692..c962fdf8f8d6 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java @@ -1081,7 +1081,7 @@ private void addCompilation(HotSpotResolvedJavaMethod method, Map CrashAtIsFatal = new RuntimeOptionKey<>(false); + @Option(help = "The fully qualified name of a no-arg, void, static method to be invoked " + + "in HotSpot from libgraal when the libgraal isolate is being shutdown." + + "This option exists for the purpose of testing callbacks in this context.") + static final RuntimeOptionKey OnShutdownCallback = new RuntimeOptionKey<>(null); // @formatter:on } @@ -678,7 +682,7 @@ public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, @Substitute private static void shutdownLibGraal(HotSpotGraalRuntime runtime) { try { - // Unregister this isolate if it was create as a peer + // Unregister this isolate if it was created as a peer if (LibGraalEntryPoints.hasLibGraalIsolatePeer()) { long offset = runtime.getVMConfig().jniEnvironmentOffset; long javaThreadAddr = HotSpotJVMCIRuntime.runtime().getCurrentJavaThread(); @@ -690,6 +694,21 @@ private static void shutdownLibGraal(HotSpotGraalRuntime runtime) { args.setLong(IsolateUtil.getIsolateID()); env.getFunctions().getCallStaticVoidMethodA().call(env, libGraalIsolateClass, unregisterMethod, args); JNIExceptionWrapper.wrapAndThrowPendingJNIException(env); + + String callback = LibGraalOptions.OnShutdownCallback.getValue(); + if (callback != null) { + int lastDot = callback.lastIndexOf('.'); + if (lastDot < 1 || lastDot == callback.length() - 1) { + throw new IllegalArgumentException(LibGraalOptions.OnShutdownCallback.getName() + " value does not have . format: " + callback); + } + String cbClassName = callback.substring(0, lastDot); + String cbMethodName = callback.substring(lastDot + 1); + JNI.JClass cbClass = JNIUtil.findClass(env, JNIUtil.getSystemClassLoader(env), + JNIUtil.getBinaryName(cbClassName), true); + JNI.JMethodID cbMethod = JNIUtil.findMethod(env, cbClass, true, cbMethodName, "()V"); + env.getFunctions().getCallStaticVoidMethodA().call(env, cbClass, cbMethod, StackValue.get(0)); + JNIExceptionWrapper.wrapAndThrowPendingJNIException(env); + } } } catch (Throwable t) { t.printStackTrace(TTY.out); From 7a627ee14fe1404ca63b065e4caa7662ec739697 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 12 Oct 2021 21:19:57 -0700 Subject: [PATCH 461/681] Add BuildPhaseProvider. --- .../oracle/svm/core/BuildPhaseProvider.java | 63 +++++++++++++++++++ .../oracle/svm/core/util/ImageHeapMap.java | 11 +--- .../svm/hosted/NativeImageGenerator.java | 6 ++ .../methodhandles/MethodHandleFeature.java | 9 +-- 4 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/BuildPhaseProvider.java diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/BuildPhaseProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/BuildPhaseProvider.java new file mode 100644 index 000000000000..ab4441065e87 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/BuildPhaseProvider.java @@ -0,0 +1,63 @@ +/* + * 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.core; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +@Platforms(Platform.HOSTED_ONLY.class) +public final class BuildPhaseProvider { + + private boolean analysisFinished; + private boolean hostedUniverseBuilt; + + public static void init() { + ImageSingletons.add(BuildPhaseProvider.class, new BuildPhaseProvider()); + } + + static BuildPhaseProvider singleton() { + return ImageSingletons.lookup(BuildPhaseProvider.class); + } + + BuildPhaseProvider() { + } + + public static void markAnalysisFinished() { + singleton().analysisFinished = true; + } + + public static boolean isAnalysisFinished() { + return singleton().analysisFinished; + } + + public static void markHostedUniverseBuilt() { + singleton().hostedUniverseBuilt = true; + } + + public static boolean isHostedUniverseBuilt() { + return singleton().hostedUniverseBuilt; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java index ff398062c114..948c228a3224 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java @@ -34,6 +34,7 @@ import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.hosted.Feature; +import com.oracle.svm.core.BuildPhaseProvider; import com.oracle.svm.core.annotate.AutomaticFeature; /** @@ -60,6 +61,7 @@ private ImageHeapMap() { */ @Platforms(Platform.HOSTED_ONLY.class) // public static EconomicMap create() { + VMError.guarantee(!BuildPhaseProvider.isAnalysisFinished(), "Trying to create an ImageHeapMap after analysis."); return new HostedImageHeapMap<>(); } } @@ -78,8 +80,6 @@ final class HostedImageHeapMap extends EconomicMapWrap { @AutomaticFeature final class ImageHeapMapFeature implements Feature { - private boolean afterAnalysis; - private final Set> allInstances = ConcurrentHashMap.newKeySet(); @Override @@ -90,7 +90,7 @@ public void duringSetup(DuringSetupAccess config) { private Object imageHeapMapTransformer(Object obj) { if (obj instanceof HostedImageHeapMap) { HostedImageHeapMap hostedImageHeapMap = (HostedImageHeapMap) obj; - if (afterAnalysis) { + if (BuildPhaseProvider.isAnalysisFinished()) { VMError.guarantee(allInstances.contains(hostedImageHeapMap), "ImageHeapMap reachable after analysis that was not seen during analysis"); } else { allInstances.add(hostedImageHeapMap); @@ -110,11 +110,6 @@ public void duringAnalysis(DuringAnalysisAccess access) { } } - @Override - public void afterAnalysis(AfterAnalysisAccess access) { - afterAnalysis = true; - } - @Override public void afterImageWrite(AfterImageWriteAccess access) { for (HostedImageHeapMap hostedImageHeapMap : allInstances) { 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 0ddee26f57a1..218aa4bb2da5 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 @@ -154,6 +154,7 @@ import com.oracle.graal.pointsto.util.Timer.StopTimer; import com.oracle.svm.core.BuildArtifacts; import com.oracle.svm.core.BuildArtifacts.ArtifactType; +import com.oracle.svm.core.BuildPhaseProvider; import com.oracle.svm.core.FrameAccess; import com.oracle.svm.core.JavaMainWrapper.JavaMainSupport; import com.oracle.svm.core.LinkerInvocation; @@ -547,6 +548,7 @@ private void doRun(Map entryPoints, new UniverseBuilder(aUniverse, bb.getMetaAccess(), hUniverse, hMetaAccess, HostedConfiguration.instance().createStaticAnalysisResultsBuilder(bb, hUniverse), bb.getUnsupportedFeatures()).build(debug); + BuildPhaseProvider.markHostedUniverseBuilt(); ClassInitializationSupport classInitializationSupport = bb.getHostVM().getClassInitializationSupport(); runtime = new HostedRuntimeConfigurationBuilder(options, bb.getHostVM(), hUniverse, hMetaAccess, bb.getProviders(), nativeLibraries, classInitializationSupport, GraalAccess.getOriginalProviders().getLoopsDataProvider()).build(); @@ -748,6 +750,7 @@ private boolean runPointsToAnalysis(String imageName, OptionValues options, Debu */ nativeLibraries.processAnnotated(); + BuildPhaseProvider.markAnalysisFinished(); AfterAnalysisAccessImpl postConfig = new AfterAnalysisAccessImpl(featureHandler, loader, bb, debug); featureHandler.forEachFeature(feature -> feature.afterAnalysis(postConfig)); @@ -823,6 +826,9 @@ private void setupNativeImage(String imageName, OptionValues options, Map feature.afterRegistration(access)); diff --git a/substratevm/src/com.oracle.svm.methodhandles/src/com/oracle/svm/methodhandles/MethodHandleFeature.java b/substratevm/src/com.oracle.svm.methodhandles/src/com/oracle/svm/methodhandles/MethodHandleFeature.java index ffd3d1f857cb..f2537e0e2ffc 100644 --- a/substratevm/src/com.oracle.svm.methodhandles/src/com/oracle/svm/methodhandles/MethodHandleFeature.java +++ b/substratevm/src/com.oracle.svm.methodhandles/src/com/oracle/svm/methodhandles/MethodHandleFeature.java @@ -41,6 +41,7 @@ import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.RuntimeReflection; +import com.oracle.svm.core.BuildPhaseProvider; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.annotate.AutomaticFeature; import com.oracle.svm.core.invoke.MethodHandleIntrinsic; @@ -81,7 +82,6 @@ @SuppressWarnings("unused") public class MethodHandleFeature implements Feature { - private boolean analysisFinished = false; private Set seenMethodHandles; private Class directMethodHandleClass; private Class boundMethodHandleClass; @@ -176,11 +176,6 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { access.findClassByName("java.lang.invoke.VarHandle")); } - @Override - public void afterAnalysis(AfterAnalysisAccess access) { - analysisFinished = true; - } - private static void registerMHImplFunctionsForReflection(DuringAnalysisAccess access) { Class mhImplClazz = access.findClassByName("java.lang.invoke.MethodHandleImpl"); RuntimeReflection.register(ReflectionUtil.lookupMethod(mhImplClazz, "checkSpreadArgument", Object.class, int.class)); @@ -283,7 +278,7 @@ private static void registerVarHandleMethodsForReflection(DuringAnalysisAccess a } private Object registerMethodHandle(Object obj) { - if (!analysisFinished) { + if (!BuildPhaseProvider.isAnalysisFinished()) { registerMethodHandleRecurse(obj); } return obj; From f82773c13ddae19cc7ffc322e53cd1b4290f8bb4 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Wed, 13 Oct 2021 16:10:10 -0700 Subject: [PATCH 462/681] Expand the use of ImageHeapMap. --- .../org.graalvm.collections/snapshot.sigtest | 1 + .../org/graalvm/collections/EconomicMap.java | 28 +++++++++ .../c/CGlobalDataNonConstantRegistry.java | 13 +++-- .../oracle/svm/core/util/ImageHeapMap.java | 13 ++++- .../oracle/svm/jni/JNILibraryInitializer.java | 36 ++++++------ .../svm/jni/access/JNIAccessibleClass.java | 39 +++++++------ .../jni/access/JNIReflectionDictionary.java | 57 ++++++++++--------- 7 files changed, 120 insertions(+), 67 deletions(-) diff --git a/sdk/src/org.graalvm.collections/snapshot.sigtest b/sdk/src/org.graalvm.collections/snapshot.sigtest index 3c22fbe84336..6067a5fb781c 100644 --- a/sdk/src/org.graalvm.collections/snapshot.sigtest +++ b/sdk/src/org.graalvm.collections/snapshot.sigtest @@ -34,6 +34,7 @@ meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> or meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> create(org.graalvm.collections.Equivalence,org.graalvm.collections.UnmodifiableEconomicMap<{%%0},{%%1}>) meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> create(org.graalvm.collections.UnmodifiableEconomicMap<{%%0},{%%1}>) meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> wrapMap(java.util.Map<{%%0},{%%1}>) +meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.MapCursor<{%%0},{%%1}> emptyCursor() meth public void putAll(org.graalvm.collections.EconomicMap<{org.graalvm.collections.EconomicMap%0},{org.graalvm.collections.EconomicMap%1}>) meth public void putAll(org.graalvm.collections.UnmodifiableEconomicMap) meth public {org.graalvm.collections.EconomicMap%1} putIfAbsent({org.graalvm.collections.EconomicMap%0},{org.graalvm.collections.EconomicMap%1}) diff --git a/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java b/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java index 2f4290aa395e..baac845ede4a 100644 --- a/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java +++ b/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java @@ -230,4 +230,32 @@ static EconomicMap create(Equivalence strategy, int initialCapacity static EconomicMap wrapMap(Map map) { return new EconomicMapWrap<>(map); } + + /** + * Return an empty {@link MapCursor}. + * + * @since 22.0 + */ + static MapCursor emptyCursor() { + return new MapCursor() { + @Override + public void remove() { + } + + @Override + public boolean advance() { + return false; + } + + @Override + public K getKey() { + return null; + } + + @Override + public V getValue() { + return null; + } + }; + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/CGlobalDataNonConstantRegistry.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/CGlobalDataNonConstantRegistry.java index c6879b5258db..97f95d797859 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/CGlobalDataNonConstantRegistry.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/CGlobalDataNonConstantRegistry.java @@ -24,14 +24,16 @@ */ package com.oracle.svm.core.c; -import com.oracle.svm.core.graal.code.CGlobalDataInfo; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; +import com.oracle.svm.core.graal.code.CGlobalDataInfo; +import com.oracle.svm.core.util.ImageHeapMap; /* * The following class is a helper registry, that contains only CGlobalDataInfo for @@ -40,11 +42,14 @@ */ public class CGlobalDataNonConstantRegistry { - private final EconomicMap, CGlobalDataInfo> cGlobalDataInfos = EconomicMap.create(Equivalence.IDENTITY); + private final EconomicMap, CGlobalDataInfo> cGlobalDataInfos = ImageHeapMap.create(Equivalence.IDENTITY); @Platforms(Platform.HOSTED_ONLY.class) // private final Lock lock = new ReentrantLock(); + /** + * Invoked at runtime via com.oracle.svm.hosted.c.CGlobalDataFeature#getCGlobalDataInfoMethod. + */ public CGlobalDataInfo getCGlobalDataInfo(CGlobalDataImpl cGlobalData) { return cGlobalDataInfos.get(cGlobalData); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java index 948c228a3224..654b0206a3c0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java @@ -29,6 +29,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicMapWrap; +import org.graalvm.collections.Equivalence; import org.graalvm.collections.MapCursor; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -62,7 +63,13 @@ private ImageHeapMap() { @Platforms(Platform.HOSTED_ONLY.class) // public static EconomicMap create() { VMError.guarantee(!BuildPhaseProvider.isAnalysisFinished(), "Trying to create an ImageHeapMap after analysis."); - return new HostedImageHeapMap<>(); + return new HostedImageHeapMap<>(Equivalence.DEFAULT); + } + + @Platforms(Platform.HOSTED_ONLY.class) // + public static EconomicMap create(Equivalence strategy) { + VMError.guarantee(!BuildPhaseProvider.isAnalysisFinished(), "Trying to create an ImageHeapMap after analysis."); + return new HostedImageHeapMap<>(strategy); } } @@ -71,9 +78,9 @@ final class HostedImageHeapMap extends EconomicMapWrap { final EconomicMap runtimeMap; - HostedImageHeapMap() { + HostedImageHeapMap(Equivalence strategy) { super(new ConcurrentHashMap<>()); - this.runtimeMap = EconomicMap.create(); + this.runtimeMap = EconomicMap.create(strategy); } } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNILibraryInitializer.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNILibraryInitializer.java index 2e01394009ab..9ba751fe7934 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNILibraryInitializer.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/JNILibraryInitializer.java @@ -24,12 +24,17 @@ */ package com.oracle.svm.jni; -import com.oracle.svm.core.c.CGlobalData; -import com.oracle.svm.core.c.CGlobalDataFactory; -import com.oracle.svm.core.jdk.NativeLibrarySupport; -import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport; -import com.oracle.svm.jni.functions.JNIFunctionTables; -import com.oracle.svm.jni.nativeapi.JNIJavaVM; +import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_1; +import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_2; +import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_4; +import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_6; +import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_8; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; import org.graalvm.nativeimage.c.function.CFunctionPointer; @@ -38,16 +43,13 @@ import org.graalvm.word.PointerBase; import org.graalvm.word.WordFactory; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_1; -import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_2; -import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_4; -import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_6; -import static com.oracle.svm.jni.nativeapi.JNIVersion.JNI_VERSION_1_8; +import com.oracle.svm.core.c.CGlobalData; +import com.oracle.svm.core.c.CGlobalDataFactory; +import com.oracle.svm.core.jdk.NativeLibrarySupport; +import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport; +import com.oracle.svm.core.util.ImageHeapMap; +import com.oracle.svm.jni.functions.JNIFunctionTables; +import com.oracle.svm.jni.nativeapi.JNIJavaVM; interface JNIOnLoadFunctionPointer extends CFunctionPointer { @InvokeCFunctionPointer @@ -56,7 +58,7 @@ interface JNIOnLoadFunctionPointer extends CFunctionPointer { public class JNILibraryInitializer implements NativeLibrarySupport.LibraryInitializer { - private final EconomicMap> onLoadCGlobalDataMap = EconomicMap.create(Equivalence.IDENTITY); + private final EconomicMap> onLoadCGlobalDataMap = ImageHeapMap.create(Equivalence.IDENTITY); public static String getOnLoadName(String libName, boolean isBuiltIn) { String name = "JNI_OnLoad"; diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessibleClass.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessibleClass.java index d7ceb27e6b96..ff87a61be8c0 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessibleClass.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIAccessibleClass.java @@ -24,15 +24,16 @@ */ package com.oracle.svm.jni.access; -import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import java.util.function.Function; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.MapCursor; import org.graalvm.nativeimage.Platform.HOSTED_ONLY; import org.graalvm.nativeimage.Platforms; +import com.oracle.svm.core.util.ImageHeapMap; + import jdk.vm.ci.meta.MetaUtil; /** @@ -40,8 +41,8 @@ */ public final class JNIAccessibleClass { private final Class classObject; - private Map methods; - private Map fields; + private EconomicMap methods; + private EconomicMap fields; JNIAccessibleClass(Class clazz) { this.classObject = clazz; @@ -51,12 +52,12 @@ public Class getClassObject() { return classObject; } - public Collection getFields() { - return (fields != null) ? fields.values() : Collections.emptySet(); + public Iterable getFields() { + return (fields != null) ? fields.getValues() : Collections::emptyIterator; } - Map getFieldsByName() { - return (fields != null) ? fields : Collections.emptyMap(); + MapCursor getFieldsByName() { + return (fields != null) ? fields.getEntries() : EconomicMap.emptyCursor(); } public JNIAccessibleField getField(String name) { @@ -66,25 +67,29 @@ public JNIAccessibleField getField(String name) { @Platforms(HOSTED_ONLY.class) void addFieldIfAbsent(String name, Function mappingFunction) { if (fields == null) { - fields = new HashMap<>(); + fields = ImageHeapMap.create(); + } + if (!fields.containsKey(name)) { + fields.put(name, mappingFunction.apply(name)); } - fields.computeIfAbsent(name, mappingFunction); } @Platforms(HOSTED_ONLY.class) void addMethodIfAbsent(JNIAccessibleMethodDescriptor descriptor, Function mappingFunction) { if (methods == null) { - methods = new HashMap<>(); + methods = ImageHeapMap.create(); + } + if (!methods.containsKey(descriptor)) { + methods.put(descriptor, mappingFunction.apply(descriptor)); } - methods.computeIfAbsent(descriptor, mappingFunction); } - public Collection getMethods() { - return (methods != null) ? methods.values() : Collections.emptySet(); + public Iterable getMethods() { + return (methods != null) ? methods.getValues() : Collections::emptyIterator; } - public Map getMethodsByDescriptor() { - return (methods != null) ? methods : Collections.emptyMap(); + public MapCursor getMethodsByDescriptor() { + return (methods != null) ? methods.getEntries() : EconomicMap.emptyCursor(); } public JNIAccessibleMethod getMethod(JNIAccessibleMethodDescriptor descriptor) { diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIReflectionDictionary.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIReflectionDictionary.java index 596a54a85f47..e09288ec28dd 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIReflectionDictionary.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/access/JNIReflectionDictionary.java @@ -27,13 +27,11 @@ import static com.oracle.svm.core.SubstrateOptions.JNIVerboseLookupErrors; import java.io.PrintStream; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import java.util.Map.Entry; import java.util.function.Function; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.ImageSingletons; @@ -47,6 +45,7 @@ import com.oracle.svm.core.Isolates; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.log.Log; +import com.oracle.svm.core.util.ImageHeapMap; import com.oracle.svm.jni.nativeapi.JNIFieldId; import com.oracle.svm.jni.nativeapi.JNIMethodId; @@ -68,9 +67,9 @@ public static JNIReflectionDictionary singleton() { return ImageSingletons.lookup(JNIReflectionDictionary.class); } - private final Map classesByName = new HashMap<>(); - private final Map, JNIAccessibleClass> classesByClassObject = new HashMap<>(); - private final Map nativeLinkages = new HashMap<>(); + private final EconomicMap classesByName = ImageHeapMap.create(); + private final EconomicMap, JNIAccessibleClass> classesByClassObject = ImageHeapMap.create(); + private final EconomicMap nativeLinkages = ImageHeapMap.create(); private JNIReflectionDictionary() { } @@ -80,26 +79,30 @@ private void dump(boolean condition, String label) { PrintStream ps = Log.logStream(); ps.println(label); ps.println(" classesByName:"); - for (Map.Entry e : classesByName.entrySet()) { + MapCursor nameCursor = classesByName.getEntries(); + while (nameCursor.advance()) { ps.print(" "); - ps.println(e.getKey()); - JNIAccessibleClass clazz = e.getValue(); + ps.println(nameCursor.getKey()); + JNIAccessibleClass clazz = nameCursor.getValue(); ps.println(" methods:"); - for (Map.Entry m : clazz.getMethodsByDescriptor().entrySet()) { + MapCursor methodsCursor = clazz.getMethodsByDescriptor(); + while (methodsCursor.advance()) { ps.print(" "); - ps.println(m.getKey().getNameAndSignature()); + ps.println(methodsCursor.getKey().getNameAndSignature()); } ps.println(" fields:"); - for (Map.Entry f : clazz.getFieldsByName().entrySet()) { + MapCursor fieldsCursor = clazz.getFieldsByName(); + while (fieldsCursor.advance()) { ps.print(" "); - ps.println(f.getKey()); + ps.println(fieldsCursor.getKey()); } } ps.println(" classesByClassObject:"); - for (Map.Entry, JNIAccessibleClass> e : classesByClassObject.entrySet()) { + MapCursor, JNIAccessibleClass> cursor = classesByClassObject.getEntries(); + while (cursor.advance()) { ps.print(" "); - ps.println(e.getKey()); + ps.println(cursor.getKey()); } } } @@ -116,11 +119,11 @@ JNIAccessibleClass addClassIfAbsent(Class classObj, Function, JNIAcc @Platforms(HOSTED_ONLY.class) void addLinkages(Map linkages) { - nativeLinkages.putAll(linkages); + nativeLinkages.putAll(EconomicMap.wrapMap(linkages)); } - public Collection getClasses() { - return Collections.unmodifiableCollection(classesByClassObject.values()); + public Iterable getClasses() { + return classesByClassObject.getValues(); } public Class getClassObjectByName(String name) { @@ -145,7 +148,7 @@ public JNINativeLinkage getLinkage(String declaringClass, String name, String de } public void unsetEntryPoints(String declaringClass) { - for (JNINativeLinkage linkage : nativeLinkages.keySet()) { + for (JNINativeLinkage linkage : nativeLinkages.getKeys()) { if (declaringClass.equals(linkage.getDeclaringClassName())) { linkage.unsetEntryPoint(); } @@ -276,10 +279,11 @@ public JNIFieldId getFieldID(Class clazz, String name, boolean isStatic) { public String getFieldNameByID(Class classObject, JNIFieldId id) { JNIAccessibleClass clazz = classesByClassObject.get(classObject); if (clazz != null) { - for (Entry entry : clazz.getFieldsByName().entrySet()) { - JNIAccessibleField field = entry.getValue(); + MapCursor fieldsCursor = clazz.getFieldsByName(); + while (fieldsCursor.advance()) { + JNIAccessibleField field = fieldsCursor.getValue(); if (id.equal(field.getId())) { - return entry.getKey(); + return fieldsCursor.getKey(); } } } @@ -289,9 +293,10 @@ public String getFieldNameByID(Class classObject, JNIFieldId id) { public static JNIAccessibleMethodDescriptor getMethodDescriptor(JNIAccessibleMethod method) { if (method != null) { JNIAccessibleClass clazz = method.getDeclaringClass(); - for (Entry entry : clazz.getMethodsByDescriptor().entrySet()) { - if (entry.getValue() == method) { - return entry.getKey(); + MapCursor methodsCursor = clazz.getMethodsByDescriptor(); + while (methodsCursor.advance()) { + if (methodsCursor.getValue() == method) { + return methodsCursor.getKey(); } } } From e0049bc2b1538100b664d1d571a6d3e88d46c4ed Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 12 Oct 2021 16:56:15 -0700 Subject: [PATCH 463/681] Clean-up error and assert messages. --- .../src/com/oracle/graal/pointsto/PointsToAnalysis.java | 1 + .../src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java | 3 ++- .../svm/hosted/analysis/NativeImagePointsToAnalysis.java | 2 +- .../src/com/oracle/svm/hosted/image/NativeImageHeap.java | 1 + .../src/com/oracle/svm/hosted/meta/HostedField.java | 1 + .../src/com/oracle/svm/hosted/meta/HostedUniverse.java | 3 ++- .../com/oracle/svm/hosted/substitute/ComputedValueField.java | 4 +++- 7 files changed, 11 insertions(+), 4 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 d73228a53fc1..a902c2c5936e 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 @@ -435,6 +435,7 @@ public AnalysisMethod addRootMethod(Executable method) { @Override @SuppressWarnings("try") public AnalysisMethod addRootMethod(AnalysisMethod aMethod) { + assert !universe.sealed() : "Cannot register root methods after analysis universe is sealed."; if (aMethod.isRootMethod()) { return aMethod; } 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 49637e572588..2e5fb0c12ade 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 @@ -397,7 +397,8 @@ public AnalysisMethod lookup(JavaMethod method) { } else if (result instanceof ResolvedJavaMethod) { return (AnalysisMethod) result; } - throw new UnsupportedFeatureException("Unresolved method found. Probably there are some compilation or classpath problems. " + method.format("%H.%n(%p)")); + throw new UnsupportedFeatureException("Unresolved method found: " + (method != null ? method.format("%H.%n(%p)") : "null") + + ". Probably there are some compilation or classpath problems. "); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java index 5aa4d03db3d4..2278867cf597 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java @@ -210,7 +210,7 @@ private List extractAnnotationTypes(AnalysisField field, UnknownOb " | 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 + + assert aAnnotationType.isArray() || (aAnnotationType.isInstanceClass() && !Modifier.isAbstract(aAnnotationType.getModifiers())) : "Annotation type cannot be abstract: field: " + field + " | annotation type " + aAnnotationType; aAnnotationTypes.add(aAnnotationType); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java index 22afc4b3ebf1..ef5e14f0e7bc 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java @@ -418,6 +418,7 @@ private void addObjectToImageHeap(final Object object, boolean immutableFromPare written = true; } + assert hybridArray != null : "Cannot read value for field " + hybridArrayField.format("%H.%n"); size = hybridLayout.getTotalSize(Array.getLength(hybridArray)); } else { size = LayoutEncoding.getInstanceSize(hub.getLayoutEncoding()).rawValue(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedField.java index 6b9e2e9d8ae0..e0d9f51c1cb7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedField.java @@ -151,6 +151,7 @@ public JavaConstant readValue(JavaConstant receiver) { public JavaConstant readStorageValue(JavaConstant receiver) { JavaConstant result = readValue(receiver); + assert result != null : "Cannot read value for field " + this.format("%H.%n"); assert result.getJavaKind() == getType().getStorageKind() : this; return result; } 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 13c3f3f4b0c0..2551b7cba9b4 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 @@ -163,7 +163,8 @@ public HostedMethod lookup(JavaMethod method) { if (result instanceof ResolvedJavaMethod) { return (HostedMethod) result; } - throw new UnsupportedFeatureException("Unresolved method found. Probably there are some compilation or classpath problems. " + method.format("%H.%n(%p)")); + throw new UnsupportedFeatureException("Unresolved method found: " + (method != null ? method.format("%H.%n(%p)") : "null") + + ". Probably there are some compilation or classpath problems. "); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java index fa3b5f9fc3f3..dd582a5032c2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java @@ -296,7 +296,9 @@ public JavaConstant readValue(MetaAccessProvider metaAccess, JavaConstant receiv } break; default: - throw shouldNotReachHere("Field recomputation of kind " + kind + " specified by alias " + annotated.format("%H.%n") + " not yet supported"); + throw shouldNotReachHere("Field recomputation of kind " + kind + " for field " + original.format("%H.%n") + + (annotated != null ? " specified by alias " + annotated.format("%H.%n") : "") + + " not yet supported"); } putCached(receiver, result); return result; From e560f2919602b4cd56d4c3bd6b935eb58dd4d317 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 12 Oct 2021 17:14:45 -0700 Subject: [PATCH 464/681] Move GraalAccess to the points-to project. It is needed by the heap scanning refactoring. --- .../graal/pointsto/util}/GraalAccess.java | 11 ++++++---- .../oracle/svm/graal/hosted/GraalFeature.java | 2 +- .../svm/hosted/NativeImageGenerator.java | 2 +- .../hosted/NativeImageGeneratorRunner.java | 2 +- .../src/com/oracle/svm/hosted/SVMHost.java | 2 +- .../svm/hosted/SubstitutionReportFeature.java | 20 ++++++++++--------- ...stantAnnotationMarkerSubstitutionType.java | 2 +- .../annotation/CustomSubstitutionMethod.java | 2 +- .../annotation/CustomSubstitutionType.java | 2 +- .../svm/hosted/c/info/InfoTreeBuilder.java | 2 +- .../ConfigurableClassInitialization.java | 2 +- .../EarlyClassInitializerAnalysis.java | 2 +- ...bdaProxyRenamingSubstitutionProcessor.java | 7 ++++--- .../hosted/lambda/LambdaSubstitutionType.java | 2 +- ...trinsifyMethodHandlesInvocationPlugin.java | 4 ++-- .../hosted/snippets/ReflectionPlugins.java | 2 +- .../svm/hosted/substitute/AnnotatedField.java | 2 +- .../hosted/substitute/AnnotatedMethod.java | 2 +- .../hosted/substitute/ComputedValueField.java | 2 +- .../substitute/InjectedAccessorsField.java | 2 +- .../hosted/substitute/InjectedFieldsType.java | 2 +- .../hosted/substitute/SubstitutionField.java | 2 +- .../hosted/substitute/SubstitutionMethod.java | 2 +- .../hosted/substitute/SubstitutionType.java | 2 +- .../UnsafeAutomaticSubstitutionProcessor.java | 2 +- .../oracle/svm/jfr/JfrEventSubstitution.java | 2 +- .../svm/truffle/TruffleBaseFeature.java | 6 +++--- .../truffle/api/SubstrateTruffleRuntime.java | 2 +- 28 files changed, 50 insertions(+), 44 deletions(-) rename substratevm/src/{com.oracle.svm.hosted/src/com/oracle/svm/hosted/c => com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util}/GraalAccess.java (89%) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/GraalAccess.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/GraalAccess.java similarity index 89% rename from substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/GraalAccess.java rename to substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/GraalAccess.java index 295871bc5191..5cf94bbe3c41 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/GraalAccess.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/GraalAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.hosted.c; +package com.oracle.graal.pointsto.util; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; @@ -32,7 +32,10 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.runtime.JVMCI; -public class GraalAccess { +public final class GraalAccess { + + private GraalAccess() { + } public static TargetDescription getOriginalTarget() { return getGraalCapability(RuntimeProvider.class).getHostBackend().getTarget(); @@ -46,7 +49,7 @@ public static SnippetReflectionProvider getOriginalSnippetReflection() { return getGraalCapability(SnippetReflectionProvider.class); } - private static T getGraalCapability(Class clazz) { + public static T getGraalCapability(Class clazz) { GraalJVMCICompiler compiler = (GraalJVMCICompiler) JVMCI.getRuntime().getCompiler(); return compiler.getGraalRuntime().getCapability(clazz); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java index 31f4833af6b5..d046c5c7f9f1 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java @@ -89,6 +89,7 @@ import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.HostedProviders; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.SubstrateUtil; @@ -120,7 +121,6 @@ import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl; import com.oracle.svm.hosted.NativeImageGenerator; import com.oracle.svm.hosted.analysis.Inflation; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; import com.oracle.svm.hosted.code.CompilationInfoSupport; import com.oracle.svm.hosted.code.SharedRuntimeConfigurationBuilder; 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 218aa4bb2da5..ba1b940e062e 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 @@ -150,6 +150,7 @@ import com.oracle.graal.pointsto.reports.AnalysisReporter; import com.oracle.graal.pointsto.reports.ReportUtils; import com.oracle.graal.pointsto.typestate.TypeState; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.graal.pointsto.util.Timer; import com.oracle.graal.pointsto.util.Timer.StopTimer; import com.oracle.svm.core.BuildArtifacts; @@ -230,7 +231,6 @@ import com.oracle.svm.hosted.annotation.AnnotationSupport; import com.oracle.svm.hosted.c.CAnnotationProcessorCache; import com.oracle.svm.hosted.c.CConstantValueSupportImpl; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.c.NativeLibraries; import com.oracle.svm.hosted.c.OffsetOfSupportImpl; import com.oracle.svm.hosted.c.SizeOfSupportImpl; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java index 4c7f6f0e60cd..67096fe11c59 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java @@ -53,6 +53,7 @@ import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor; import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.graal.pointsto.util.AnalysisError.ParsingError; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.graal.pointsto.util.ParallelExecutionException; import com.oracle.graal.pointsto.util.Timer; import com.oracle.graal.pointsto.util.Timer.StopTimer; @@ -67,7 +68,6 @@ import com.oracle.svm.core.util.UserError.UserException; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.analysis.NativeImagePointsToAnalysis; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.code.CEntryPointData; import com.oracle.svm.hosted.image.AbstractImage.NativeImageKind; import com.oracle.svm.hosted.option.HostedOptionParser; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index c7416f4be096..734a7a3c45ce 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -79,6 +79,7 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.phases.InlineBeforeAnalysisPolicy; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.RuntimeAssertionsSupport; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.SubstrateUtil; @@ -102,7 +103,6 @@ import com.oracle.svm.core.option.SubstrateOptionsParser; import com.oracle.svm.core.util.HostedStringDeduplication; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; import com.oracle.svm.hosted.code.InliningUtilities; import com.oracle.svm.hosted.meta.HostedType; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SubstitutionReportFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SubstitutionReportFeature.java index 26b4d8b89c50..0fcfc866c73c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SubstitutionReportFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SubstitutionReportFeature.java @@ -24,29 +24,31 @@ */ package com.oracle.svm.hosted; +import java.security.CodeSource; +import java.util.Comparator; +import java.util.Map; +import java.util.TreeMap; +import java.util.function.Function; + +import org.graalvm.compiler.options.Option; +import org.graalvm.nativeimage.hosted.Feature; + import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; 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.reports.ReportUtils; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.annotate.AutomaticFeature; import com.oracle.svm.core.option.HostedOptionKey; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.substitute.SubstitutionField; import com.oracle.svm.hosted.substitute.SubstitutionMethod; import com.oracle.svm.hosted.substitute.SubstitutionType; + import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import org.graalvm.compiler.options.Option; -import org.graalvm.nativeimage.hosted.Feature; - -import java.security.CodeSource; -import java.util.Comparator; -import java.util.Map; -import java.util.TreeMap; -import java.util.function.Function; @AutomaticFeature public class SubstitutionReportFeature implements Feature { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/ConstantAnnotationMarkerSubstitutionType.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/ConstantAnnotationMarkerSubstitutionType.java index 33f9dd3579dc..a684606fa4d9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/ConstantAnnotationMarkerSubstitutionType.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/ConstantAnnotationMarkerSubstitutionType.java @@ -28,7 +28,7 @@ import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor; -import com.oracle.svm.hosted.c.GraalAccess; +import com.oracle.graal.pointsto.util.GraalAccess; import jdk.vm.ci.meta.Assumptions; import jdk.vm.ci.meta.JavaConstant; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/CustomSubstitutionMethod.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/CustomSubstitutionMethod.java index 7f3dd9c347cd..3a1691dc10fa 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/CustomSubstitutionMethod.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/CustomSubstitutionMethod.java @@ -32,7 +32,7 @@ import com.oracle.graal.pointsto.infrastructure.GraphProvider; import com.oracle.graal.pointsto.infrastructure.OriginalMethodProvider; -import com.oracle.svm.hosted.c.GraalAccess; +import com.oracle.graal.pointsto.util.GraalAccess; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantPool; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/CustomSubstitutionType.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/CustomSubstitutionType.java index 6cbee9e255ac..fcff66ac0f29 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/CustomSubstitutionType.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/CustomSubstitutionType.java @@ -31,7 +31,7 @@ import java.util.Map; import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; -import com.oracle.svm.hosted.c.GraalAccess; +import com.oracle.graal.pointsto.util.GraalAccess; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.meta.Assumptions.AssumptionResult; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/info/InfoTreeBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/info/InfoTreeBuilder.java index 2e4518a42d8d..f4665899d460 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/info/InfoTreeBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/info/InfoTreeBuilder.java @@ -56,10 +56,10 @@ import com.oracle.graal.pointsto.infrastructure.WrappedElement; import com.oracle.graal.pointsto.infrastructure.WrappedJavaType; import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.c.CTypedef; import com.oracle.svm.core.c.struct.PinnedObjectField; import com.oracle.svm.hosted.c.BuiltinDirectives; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.c.NativeCodeContext; import com.oracle.svm.hosted.c.NativeLibraries; import com.oracle.svm.hosted.c.info.AccessorInfo.AccessorKind; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ConfigurableClassInitialization.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ConfigurableClassInitialization.java index 9572bdbd759d..96d6211b6298 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ConfigurableClassInitialization.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ConfigurableClassInitialization.java @@ -46,13 +46,13 @@ import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; import com.oracle.graal.pointsto.reports.ReportUtils; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.option.SubstrateOptionsParser; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.ImageClassLoader; import com.oracle.svm.hosted.NativeImageOptions; -import com.oracle.svm.hosted.c.GraalAccess; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/EarlyClassInitializerAnalysis.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/EarlyClassInitializerAnalysis.java index 85aca69ae2a8..4e69489f4c9a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/EarlyClassInitializerAnalysis.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/EarlyClassInitializerAnalysis.java @@ -55,12 +55,12 @@ import org.graalvm.compiler.phases.util.Providers; import com.oracle.graal.pointsto.phases.NoClassInitializationPlugin; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.classinitialization.EnsureClassInitializedNode; import com.oracle.svm.core.graal.thread.VMThreadLocalAccess; import com.oracle.svm.core.option.HostedOptionValues; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.phases.EarlyConstantFoldLoadFieldPlugin; import com.oracle.svm.hosted.snippets.ReflectionPlugins; import com.oracle.svm.hosted.snippets.SubstrateGraphBuilderPlugins; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java index fe47e4c1bc1d..7f0fcb1f9566 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaProxyRenamingSubstitutionProcessor.java @@ -24,22 +24,23 @@ */ package com.oracle.svm.hosted.lambda; -import org.graalvm.compiler.java.LambdaUtils; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext.Builder; +import org.graalvm.compiler.java.LambdaUtils; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor; import com.oracle.graal.pointsto.phases.NoClassInitializationPlugin; -import com.oracle.svm.hosted.c.GraalAccess; +import com.oracle.graal.pointsto.util.GraalAccess; + import jdk.vm.ci.meta.ResolvedJavaType; -import org.graalvm.compiler.phases.util.Providers; /** * This substitution replaces all lambda proxy types with types that have a stable names. The name diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaSubstitutionType.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaSubstitutionType.java index 3e30f126d84c..84942e4bbbf6 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaSubstitutionType.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaSubstitutionType.java @@ -27,8 +27,8 @@ import java.lang.annotation.Annotation; import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.jdk.LambdaFormHiddenMethod; -import com.oracle.svm.hosted.c.GraalAccess; import jdk.vm.ci.meta.Assumptions.AssumptionResult; import jdk.vm.ci.meta.JavaConstant; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java index d796dce91fbd..131fceac2399 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java @@ -37,7 +37,6 @@ import java.util.Set; import java.util.stream.StreamSupport; -import com.oracle.graal.pointsto.phases.NoClassInitializationPlugin; import org.graalvm.collections.Pair; import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; @@ -105,6 +104,8 @@ import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.graal.pointsto.phases.NoClassInitializationPlugin; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.FrameAccess; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.SubstrateOptions; @@ -118,7 +119,6 @@ import com.oracle.svm.hosted.NativeImageOptions; import com.oracle.svm.hosted.NativeImageUtil; import com.oracle.svm.hosted.SVMHost; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.meta.HostedUniverse; import com.oracle.svm.hosted.snippets.IntrinsificationPluginRegistry; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java index 154209e821ea..1a8bd9e723a7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java @@ -60,6 +60,7 @@ import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.TypeResult; @@ -69,7 +70,6 @@ import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.ExceptionSynthesizer; import com.oracle.svm.hosted.ImageClassLoader; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor; import com.oracle.svm.hosted.substitute.DeletedElementException; import com.oracle.svm.util.ModuleSupport; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedField.java index 7c5d68a4b897..37a1af797f1b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedField.java @@ -29,10 +29,10 @@ import java.util.Arrays; import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.annotate.Delete; import com.oracle.svm.core.annotate.InjectAccessors; import com.oracle.svm.core.meta.ReadableJavaField; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.util.ClassUtil; import jdk.vm.ci.meta.JavaConstant; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedMethod.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedMethod.java index efb3761b19f9..873cb69b7c4f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedMethod.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotatedMethod.java @@ -38,9 +38,9 @@ import com.oracle.graal.pointsto.infrastructure.GraphProvider; import com.oracle.graal.pointsto.infrastructure.OriginalMethodProvider; import com.oracle.graal.pointsto.meta.HostedProviders; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.annotate.AnnotateOriginal; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.c.GraalAccess; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantPool; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java index dd582a5032c2..c5d75b307b96 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java @@ -44,6 +44,7 @@ import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.annotate.RecomputeFieldValue; import com.oracle.svm.core.annotate.RecomputeFieldValue.CustomFieldValueComputer; import com.oracle.svm.core.annotate.RecomputeFieldValue.CustomFieldValueTransformer; @@ -51,7 +52,6 @@ import com.oracle.svm.core.meta.ReadableJavaField; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.util.ReflectionUtil; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/InjectedAccessorsField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/InjectedAccessorsField.java index 3ed62d84f6fa..281c1d33877d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/InjectedAccessorsField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/InjectedAccessorsField.java @@ -29,10 +29,10 @@ import java.util.Arrays; import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.annotate.InjectAccessors; import com.oracle.svm.core.meta.ReadableJavaField; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.c.GraalAccess; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaType; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/InjectedFieldsType.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/InjectedFieldsType.java index 4af972e84e4e..4620cb2bf8a4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/InjectedFieldsType.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/InjectedFieldsType.java @@ -28,7 +28,7 @@ import java.util.Arrays; import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; -import com.oracle.svm.hosted.c.GraalAccess; +import com.oracle.graal.pointsto.util.GraalAccess; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.meta.Assumptions.AssumptionResult; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionField.java index 23a7b1beca8b..54c2d365a718 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionField.java @@ -28,8 +28,8 @@ import java.lang.reflect.Field; import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.meta.ReadableJavaField; -import com.oracle.svm.hosted.c.GraalAccess; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaType; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionMethod.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionMethod.java index b28fc46cb0df..d66751657378 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionMethod.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionMethod.java @@ -37,7 +37,7 @@ import com.oracle.graal.pointsto.infrastructure.GraphProvider; import com.oracle.graal.pointsto.infrastructure.OriginalMethodProvider; import com.oracle.graal.pointsto.meta.HostedProviders; -import com.oracle.svm.hosted.c.GraalAccess; +import com.oracle.graal.pointsto.util.GraalAccess; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantPool; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionType.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionType.java index 4c70180a5e66..a3f3d336b96e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionType.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionType.java @@ -29,7 +29,7 @@ import java.util.Arrays; import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; -import com.oracle.svm.hosted.c.GraalAccess; +import com.oracle.graal.pointsto.util.GraalAccess; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.meta.Assumptions.AssumptionResult; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/UnsafeAutomaticSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/UnsafeAutomaticSubstitutionProcessor.java index 7dd4c5130974..903a2575b465 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/UnsafeAutomaticSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/UnsafeAutomaticSubstitutionProcessor.java @@ -75,6 +75,7 @@ import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.phases.NoClassInitializationPlugin; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.annotate.AutomaticFeature; @@ -86,7 +87,6 @@ import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; import com.oracle.svm.hosted.ImageClassLoader; import com.oracle.svm.hosted.SVMHost; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.classinitialization.ClassInitializerGraphBuilderPhase; import com.oracle.svm.hosted.snippets.ReflectionPlugins; diff --git a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrEventSubstitution.java b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrEventSubstitution.java index b44f203846d1..776913eeab95 100644 --- a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrEventSubstitution.java +++ b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrEventSubstitution.java @@ -37,8 +37,8 @@ import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.c.GraalAccess; import jdk.jfr.Event; import jdk.jfr.internal.EventWriter; diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleBaseFeature.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleBaseFeature.java index a98dac8449c5..40cb4b3c19be 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleBaseFeature.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleBaseFeature.java @@ -44,8 +44,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.BooleanSupplier; -import com.oracle.svm.core.config.ConfigurationValues; -import com.oracle.truffle.api.staticobject.StaticProperty; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ValueNode; @@ -62,6 +60,7 @@ import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.annotate.Alias; import com.oracle.svm.core.annotate.AnnotateOriginal; @@ -71,6 +70,7 @@ import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; @@ -82,7 +82,6 @@ import com.oracle.svm.hosted.FeatureImpl; import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.snippets.SubstrateGraphBuilderPlugins; import com.oracle.svm.truffle.api.SubstrateTruffleRuntime; @@ -103,6 +102,7 @@ import com.oracle.truffle.api.nodes.NodeClass; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.profiles.Profile; +import com.oracle.truffle.api.staticobject.StaticProperty; import com.oracle.truffle.api.staticobject.StaticShape; import jdk.vm.ci.meta.JavaKind; diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateTruffleRuntime.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateTruffleRuntime.java index f3782dbac6ff..0a82b746a8ca 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateTruffleRuntime.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateTruffleRuntime.java @@ -50,6 +50,7 @@ import org.graalvm.nativeimage.Platform.HOSTED_ONLY; import org.graalvm.nativeimage.Platforms; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.deopt.Deoptimizer; @@ -60,7 +61,6 @@ import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.option.RuntimeOptionValues; import com.oracle.svm.core.stack.SubstrateStackIntrospection; -import com.oracle.svm.hosted.c.GraalAccess; import com.oracle.svm.truffle.TruffleSupport; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.impl.AbstractFastThreadLocal; From ee87ab35f595452f7df9624c49299e03f48ac7b6 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 12 Oct 2021 18:55:47 -0700 Subject: [PATCH 465/681] Various additions. --- .../AnalysisObjectScanningObserver.java | 4 +-- .../graal/pointsto/util/AnalysisFuture.java | 25 +++++++++---------- .../src/com/oracle/svm/hosted/SVMHost.java | 6 +++++ 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanningObserver.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanningObserver.java index f07d0707c0f4..3dca19404a31 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanningObserver.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanningObserver.java @@ -33,11 +33,11 @@ import jdk.vm.ci.meta.JavaConstant; -class AnalysisObjectScanningObserver implements ObjectScanningObserver { +public class AnalysisObjectScanningObserver implements ObjectScanningObserver { private final BigBang bb; - AnalysisObjectScanningObserver(BigBang bb) { + public AnalysisObjectScanningObserver(BigBang bb) { this.bb = bb; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/AnalysisFuture.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/AnalysisFuture.java index 3d6ebb5b3e93..cceb2af8e7b0 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/AnalysisFuture.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/AnalysisFuture.java @@ -49,23 +49,22 @@ protected void setException(Throwable t) { throw new GraalError(t); } - /** Run the task and wait for it to complete, if necessary. */ - public void ensureDone() { + /** Run the task, wait for it to complete if necessary, then retrieve its result. */ + public V ensureDone() { try { /* - * If the task is not done yet trigger its execution and call get(), which waits for the - * computation to complete, if necessary. - * - * A task is "done" even if it failed with an exception. The exception is only reported - * when get() is invoked. That's why, to support this execution pattern without miss any - * exceptions, we report the error eagerly as a GraalError as soon as it is encountered. + * Trigger the task execution and call get(), which waits for the computation to + * complete, if necessary. + * + * A task is done even if it failed with an exception. The exception is only reported + * when get() is invoked. We report any error eagerly as a GraalError as soon as it is + * encountered. */ - if (!isDone()) { - run(); - get(); - } + run(); + return get(); } catch (InterruptedException | ExecutionException e) { - AnalysisError.shouldNotReachHere(e); + throw AnalysisError.shouldNotReachHere(e); } } + } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index 734a7a3c45ce..357e0d28d858 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -742,6 +742,12 @@ public boolean platformSupported(AnalysisUniverse universe, AnnotatedElement ele return false; } } + if (element instanceof Class) { + Package p = ((Class) element).getPackage(); + if (p != null && !platformSupported(universe, p)) { + return false; + } + } Platforms platformsAnnotation = GuardedAnnotationAccess.getAnnotation(element, Platforms.class); if (platform == null || platformsAnnotation == null) { From ce35fa37a41010480416cdbdd30b2808ed64754d Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 13 Oct 2021 21:42:17 +0200 Subject: [PATCH 466/681] prevent inner LibGraalScope from using detached and destroyed isolate thread of an outer LibGraalScope that is in the process of closing --- .../org/graalvm/libgraal/LibGraalScope.java | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/compiler/src/org.graalvm.libgraal/src/org/graalvm/libgraal/LibGraalScope.java b/compiler/src/org.graalvm.libgraal/src/org/graalvm/libgraal/LibGraalScope.java index 1729e451ae00..11472e02566b 100644 --- a/compiler/src/org.graalvm.libgraal/src/org/graalvm/libgraal/LibGraalScope.java +++ b/compiler/src/org.graalvm.libgraal/src/org/graalvm/libgraal/LibGraalScope.java @@ -43,13 +43,31 @@ public final class LibGraalScope implements AutoCloseable { static class Shared { final DetachAction detachAction; final LibGraalIsolate isolate; - final long isolateThread; + private long isolateThread; Shared(DetachAction detachAction, LibGraalIsolate isolate, long isolateThread) { this.detachAction = detachAction; this.isolate = isolate; this.isolateThread = isolateThread; } + + public long getIsolateThread() { + if (isolateThread == 0L) { + throw new IllegalStateException(Thread.currentThread() + " is no longer attached to " + isolate); + } + return isolateThread; + } + + public long detach() { + long res = getIsolateThread(); + isolateThread = 0L; + return res; + } + + @Override + public String toString() { + return String.format("isolate=%s, isolateThread=0x%x, detachAction=%s", isolate, isolateThread, detachAction); + } } private final LibGraalScope parent; @@ -82,7 +100,7 @@ public static LibGraalScope current() { * @throws IllegalStateException if the current thread is not attached to libgraal */ public static long getIsolateThread() { - return current().shared.isolateThread; + return current().shared.getIsolateThread(); } /** @@ -150,7 +168,7 @@ public LibGraalScope(DetachAction detachAction) { @Override public String toString() { - return String.format("LibGraalScope@%d[isolate=%s, isolateThread=0x%x, parent=%s]", id, shared.isolate, shared.isolateThread, parent); + return String.format("LibGraalScope@%d[%s, parent=%s]", id, shared, parent); } /** @@ -234,19 +252,26 @@ public LibGraalIsolate getIsolate() { * Gets the address of the isolate thread associated with this scope. */ public long getIsolateThreadAddress() { - return shared.isolateThread; + return shared.getIsolateThread(); } @Override public void close() { + // Reset the currentScope thread local before detaching. Detaching may trigger HotSpot to + // shutdown the libgraal isolate. That involves re-attaching the current thread to the + // libgraal isolate with a *new* isolate thread for calling + // HotSpotJVMCIRuntime.shutdown(). In the scope of the latter call, if a new LibGraalScope + // is opened, it must not see this LibGraalScope as its parent otherwise it will use the + // closed and discarded isolate thread (i.e. this.shared.isolateThread). + currentScope.set(parent); if (parent == null && shared.detachAction != null) { + long isolateThread = shared.detach(); if (shared.detachAction == DetachAction.DETACH) { - detachThreadFrom(shared.isolateThread); + detachThreadFrom(isolateThread); } else { LibGraal.detachCurrentThread(shared.detachAction == DetachAction.DETACH_RUNTIME_AND_RELEASE); } } - currentScope.set(parent); } // Shared support for the LibGraal overlays From 723c29316b4e2a605281512e4bef6fa154a6f933 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 14 Oct 2021 10:08:28 +0200 Subject: [PATCH 467/681] Disallow Java heap allocation if safepoint checks are disabled. --- .../src/com/oracle/svm/core/genscavenge/HeapImpl.java | 3 ++- .../src/com/oracle/svm/core/heap/NoAllocationVerifier.java | 4 ---- .../src/com/oracle/svm/core/thread/VMThreads.java | 4 +++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java index 129d35bcd0e8..c99c23ecebb1 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java @@ -172,6 +172,7 @@ public boolean isInPrimaryImageHeap(Pointer objPointer) { } @Override + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public void suspendAllocation() { ThreadLocalAllocation.suspendInCurrentThread(); } @@ -237,7 +238,7 @@ GCImpl getGCImpl() { @Override @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean isAllocationDisallowed() { - return NoAllocationVerifier.isActive() || gcImpl.isCollectionInProgress(); + return NoAllocationVerifier.isActive() || !VMThreads.SafepointBehavior.safepointChecksEnabled() || gcImpl.isCollectionInProgress(); } /** A guard to place before an allocation, giving the call site and the allocation type. */ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/NoAllocationVerifier.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/NoAllocationVerifier.java index 047ca080dbc2..cc558b6f1cd5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/NoAllocationVerifier.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/NoAllocationVerifier.java @@ -37,10 +37,6 @@ * Design: There shouldn't be tests for a locked heap on the allocation fast-path, so the key is * that creating one of these sets top to end in the young space, so allocation attempts fail over * to the slow-path, and there can be a test for a locked heap on the slow path. - * - * TODO: When SVM becomes multi-threaded, this should only prevent allocation on a particular - * thread. That could be done by setting the thread's TLAB to null, which should force it on to the - * slow-path to allocation a new TLAB. */ public class NoAllocationVerifier implements AutoCloseable { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java index 95f2eda2fd57..02f16bbbeeef 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java @@ -871,6 +871,7 @@ public static int getSafepointBehavior(IsolateThread vmThread) { public static void setPreventVMFromReachingSafepoint() { assert safepointChecksEnabled(); safepointBehaviorTL.setVolatile(PREVENT_VM_FROM_REACHING_SAFEPOINT); + Heap.getHeap().suspendAllocation(); } /** @@ -888,13 +889,14 @@ public static void setPreventVMFromReachingSafepoint() { static void setIgnoreThreadInSafepointHandling() { assert safepointChecksEnabled(); safepointBehaviorTL.setVolatile(IGNORE_THREAD_IN_SAFEPOINT_HANDLING); + Heap.getHeap().suspendAllocation(); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static String toString(int safepointBehavior) { switch (safepointBehavior) { case ALLOW_SAFEPOINT: - return ""; + return "ALLOW_SAFEPOINT"; case PREVENT_VM_FROM_REACHING_SAFEPOINT: return "PREVENT_VM_FROM_REACHING_SAFEPOINT"; case IGNORE_THREAD_IN_SAFEPOINT_HANDLING: From 7b40f7d1d47313ed17f56656ebdc677b7e977edc Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Wed, 13 Oct 2021 13:40:49 +0200 Subject: [PATCH 468/681] Make updating context locals and context thread locals work for inner contexts. --- .../api/test/polyglot/ContextLocalTest.java | 104 +++++++++++++++++- .../truffle/polyglot/PolyglotContextImpl.java | 54 +++++++-- .../truffle/polyglot/PolyglotEngineImpl.java | 14 +-- .../truffle/polyglot/PolyglotInstrument.java | 15 +-- 4 files changed, 152 insertions(+), 35 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextLocalTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextLocalTest.java index a4dcd0a0678d..e9c47e83e179 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextLocalTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextLocalTest.java @@ -61,12 +61,16 @@ import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.Instrument; +import org.graalvm.polyglot.PolyglotAccess; import org.graalvm.polyglot.PolyglotException; import org.junit.Assert; import org.junit.Test; +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.ContextLocal; import com.oracle.truffle.api.ContextThreadLocal; +import com.oracle.truffle.api.InstrumentInfo; import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; @@ -74,8 +78,13 @@ import com.oracle.truffle.api.instrumentation.EventContext; import com.oracle.truffle.api.instrumentation.ExecutionEventListener; import com.oracle.truffle.api.instrumentation.SourceSectionFilter; +import com.oracle.truffle.api.instrumentation.ThreadsActivationListener; import com.oracle.truffle.api.instrumentation.TruffleInstrument; +import com.oracle.truffle.api.nodes.IndirectCallNode; import com.oracle.truffle.api.nodes.LanguageInfo; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.source.Source; public class ContextLocalTest extends AbstractPolyglotTest { @@ -687,8 +696,11 @@ public void testUnstableContextThreadLocalValue() { } } - public void testInstrumentCreatedBeforeContextsInitialized() { - + @Test + public void testInnerContextLocals() { + try (Context ctx = Context.newBuilder().allowPolyglotAccess(PolyglotAccess.ALL).build()) { + Assert.assertEquals(0, ctx.eval(VALID_SHARED_LANGUAGE, "").asInt()); + } } @TruffleLanguage.Registration(id = VALID_EXCLUSIVE_LANGUAGE, name = VALID_EXCLUSIVE_LANGUAGE) @@ -710,6 +722,17 @@ protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { return true; } + @Override + protected CallTarget parse(ParsingRequest request) throws Exception { + RootNode rootNode = new RootNode(this) { + @Override + public Object execute(VirtualFrame frame) { + return 0; + } + }; + return rootNode.getCallTarget(); + } + static final ContextReference CONTEXT_REF = ContextReference.create(ValidExclusiveLanguage.class); static final LanguageReference REFERENCE = LanguageReference.create(ValidExclusiveLanguage.class); @@ -782,11 +805,71 @@ public ContextThreadLocal createContextThreadLocal0(String value) { return createContextThreadLocal((e, t) -> value); } + @Override + protected CallTarget parse(ParsingRequest request) throws Exception { + return (new VSLRootNode(this)).getCallTarget(); + } + static final ContextReference CONTEXT_REF = ContextReference.create(ValidSharedLanguage.class); static final LanguageReference REFERENCE = LanguageReference.create(ValidSharedLanguage.class); } + public static class VSLRootNode extends RootNode { + + @Node.Child private VSLNode node = new VSLNode(); + + public VSLRootNode(ValidSharedLanguage language) { + super(language); + } + + @Override + public Object execute(VirtualFrame virtualFrame) { + return node.execute(virtualFrame); + } + + } + + public static class VSLNode extends Node { + + private final Source source = Source.newBuilder(VALID_EXCLUSIVE_LANGUAGE, "", "").build(); + + private final IndirectCallNode callNode = IndirectCallNode.create(); + + @SuppressWarnings("unused") + public Object execute(VirtualFrame virtualFrame) { + Env outerLanguageOuterEnv = ValidSharedLanguage.CONTEXT_REF.get(this); + TruffleContext innerTruffleContext = createInnerContext(outerLanguageOuterEnv); + Object outerTruffleContext = innerTruffleContext.enter(this); + try { + Env outerLanguageInnerEnv = ValidSharedLanguage.CONTEXT_REF.get(this); + createInstrument(outerLanguageInnerEnv); + CallTarget callTarget = parse(outerLanguageInnerEnv); + return callNode.call(callTarget); + } finally { + innerTruffleContext.leave(this, outerTruffleContext); + innerTruffleContext.close(); + } + } + + @CompilerDirectives.TruffleBoundary + private CallTarget parse(Env env) { + return env.parsePublic(source); + } + + @CompilerDirectives.TruffleBoundary + private static TruffleContext createInnerContext(Env env) { + return env.newContextBuilder().build(); + } + + @CompilerDirectives.TruffleBoundary + private static void createInstrument(Env env) { + InstrumentInfo instrumentInfo = env.getInstruments().get(VALID_INSTRUMENT); + env.lookup(instrumentInfo, ValidInstrument.class); + } + + } + @TruffleInstrument.Registration(id = VALID_INSTRUMENT, name = VALID_INSTRUMENT, services = ValidInstrument.class) public static class ValidInstrument extends TruffleInstrument { @@ -804,6 +887,23 @@ public static class ValidInstrument extends TruffleInstrument { protected void onCreate(Env env) { this.environment = env; env.registerService(this); + env.getInstrumenter().attachThreadsActivationListener(new ThreadsActivationListener() { + @Override + public void onEnterThread(TruffleContext c) { + if (threadLocalDynamicValue != null && contextLocalDynamicValue != null) { + local0.get(c); + threadLocal0.get(c); + } + } + + @Override + public void onLeaveThread(TruffleContext c) { + if (threadLocalDynamicValue != null && contextLocalDynamicValue != null) { + local0.get(c); + threadLocal0.get(c); + } + } + }); } InstrumentThreadLocalValue newInstrumentThreadLocal(TruffleContext context, Thread t) { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java index 45a108f6df0a..6123f27f52eb 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java @@ -2624,13 +2624,39 @@ void initializeInstrumentContextThreadLocals() { } } - /** - * Updates the current thread locals from {@link PolyglotThreadInfo#contextThreadLocals}. - */ - synchronized Object[] updateThreadLocals() { - assert Thread.holdsLock(this); - Object[] newThreadLocals = getThreadLocals(Thread.currentThread()); - return newThreadLocals; + void invokeLocalsFactories(LocalLocation[] contextLocalLocations, LocalLocation[] contextThreadLocalLocations) { + PolyglotContextImpl[] localChildContexts; + synchronized (this) { + if (localsCleared) { + return; + } + /* + * contextLocals might not be initialized yet, in which case the context local factory + * for this instrument will be invoked during contextLocals initialization. + */ + if (contextLocals != null) { + invokeContextLocalsFactory(contextLocals, contextLocalLocations); + invokeContextThreadLocalFactory(contextThreadLocalLocations); + } + localChildContexts = PolyglotContextImpl.this.childContexts.toArray(new PolyglotContextImpl[0]); + } + for (PolyglotContextImpl childCtx : localChildContexts) { + childCtx.invokeLocalsFactories(contextLocalLocations, contextThreadLocalLocations); + } + } + + void resizeThreadLocals(StableLocalLocations locations) { + PolyglotContextImpl[] localChildContexts; + synchronized (this) { + if (localsCleared) { + return; + } + resizeContextThreadLocals(locations); + localChildContexts = PolyglotContextImpl.this.childContexts.toArray(new PolyglotContextImpl[0]); + } + for (PolyglotContextImpl childCtx : localChildContexts) { + childCtx.resizeThreadLocals(locations); + } } void resizeContextThreadLocals(StableLocalLocations locations) { @@ -2643,6 +2669,20 @@ void resizeContextThreadLocals(StableLocalLocations locations) { } } + void resizeLocals(StableLocalLocations locations) { + PolyglotContextImpl[] localChildContexts; + synchronized (this) { + if (localsCleared) { + return; + } + resizeContextLocals(locations); + localChildContexts = PolyglotContextImpl.this.childContexts.toArray(new PolyglotContextImpl[0]); + } + for (PolyglotContextImpl childCtx : localChildContexts) { + childCtx.resizeLocals(locations); + } + } + void resizeContextLocals(StableLocalLocations locations) { assert Thread.holdsLock(this); Object[] oldLocals = this.contextLocals; diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java index c067870b1239..fc90dbea4417 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java @@ -1982,12 +1982,7 @@ LocalLocation[] addContextLocals(List> newLoca newLocations = Arrays.copyOfRange(locationsCopy, stableLocations.locations.length, index); } for (PolyglotContextImpl context : aliveContexts) { - synchronized (context) { - if (context.localsCleared) { - continue; - } - context.resizeContextLocals(newStableLocations); - } + context.resizeLocals(newStableLocations); } return newLocations; } @@ -2015,12 +2010,7 @@ LocalLocation[] addContextThreadLocals(List Date: Tue, 7 Sep 2021 14:48:04 +0200 Subject: [PATCH 469/681] compiler: PlaceholderWithExceptionNode must be a memory kill --- .../org/graalvm/compiler/replacements/SnippetTemplate.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index f553c5da39b3..c1209f60104f 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -2216,7 +2216,7 @@ public void setMayRemoveLocation(boolean mayRemoveLocation) { * CFG edges for select snippet lowerings. */ @NodeInfo(size = NodeSize.SIZE_0, cycles = NodeCycles.CYCLES_0, cyclesRationale = "This node is immediately removed on next simplification pass") -final class PlaceholderWithExceptionNode extends WithExceptionNode implements Simplifiable { +final class PlaceholderWithExceptionNode extends WithExceptionNode implements Simplifiable, SingleMemoryKill { static final NodeClass TYPE = NodeClass.create(PlaceholderWithExceptionNode.class); protected PlaceholderWithExceptionNode() { @@ -2230,6 +2230,11 @@ public void simplify(SimplifierTool tool) { } graph().removeSplit(this, next()); } + + @Override + public LocationIdentity getKilledLocationIdentity() { + return LocationIdentity.any(); + } } @NodeInfo(size = NodeSize.SIZE_0, cycles = NodeCycles.CYCLES_0, cyclesRationale = "This node is immediately removed on next simplification pass") From 4f7fdf83174c1cb242eb4dd518dfc3cda4d827dd Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 8 Sep 2021 16:33:23 +0200 Subject: [PATCH 470/681] compiler: verify that WithExceptionNodes do not have memory usages in SnippetTemplate --- .../src/org/graalvm/compiler/graph/Node.java | 18 ++++++++++++++++++ .../compiler/replacements/SnippetTemplate.java | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index 8f1622c8e2ed..2c0855746db9 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -456,6 +456,24 @@ public final boolean hasOnlyUsagesOfType(InputType type) { return true; } + /** + * Checks whether this node has usages of that type. + * + * @param type the type of usages to look for + */ + public final boolean hasUsagesOfType(InputType type) { + for (Node usage : usages()) { + for (Position pos : usage.inputPositions()) { + if (pos.get(usage) == this) { + if (pos.getInputType() == type) { + return true; + } + } + } + } + return false; + } + /** * Adds a given node to this node's {@linkplain #usages() usages}. * diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index c1209f60104f..822c1bd5ba71 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -1546,6 +1546,7 @@ public Collection getLocations() { } private void rewireMemoryGraph(ValueNode replacee, UnmodifiableEconomicMap duplicates) { + verifyWithExceptionNode(replacee); if (replacee.graph().isAfterStage(StageFlag.FLOATING_READS)) { // rewire outgoing memory edges replaceMemoryUsages(replacee, new MemoryOutputMap(replacee, duplicates)); @@ -1578,6 +1579,19 @@ private void rewireMemoryGraph(ValueNode replacee, UnmodifiableEconomicMap Date: Tue, 28 Sep 2021 17:36:14 +0200 Subject: [PATCH 471/681] compiler: canonicalize KillingBeginNode to BeginNode ... if the predecessor is no longer a WithExceptionNode and it has no memory edges. --- .../compiler/nodes/KillingBeginNode.java | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java index f02b7a832908..f804e2b8cdb8 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java @@ -29,12 +29,12 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.compiler.nodes.spi.Simplifiable; -import org.graalvm.compiler.nodes.spi.SimplifierTool; +import org.graalvm.compiler.nodes.spi.Canonicalizable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.word.LocationIdentity; /** @@ -44,7 +44,7 @@ * @see WithExceptionNode for more details */ @NodeInfo(allowedUsageTypes = {Memory}, cycles = CYCLES_0, size = SIZE_0) -public final class KillingBeginNode extends AbstractBeginNode implements SingleMemoryKill, Simplifiable { +public final class KillingBeginNode extends AbstractBeginNode implements SingleMemoryKill, Canonicalizable { public static final NodeClass TYPE = NodeClass.create(KillingBeginNode.class); protected LocationIdentity locationIdentity; @@ -73,28 +73,23 @@ public LocationIdentity getKilledLocationIdentity() { } @Override - public void simplify(SimplifierTool tool) { - if (predecessor() instanceof FixedWithNextNode && predecessor() instanceof SingleMemoryKill) { - SingleMemoryKill predecessor = (SingleMemoryKill) predecessor(); - if (getKilledLocationIdentity().equals(predecessor.getKilledLocationIdentity())) { - // This killing begin node can be removed. - tool.addToWorkList(next()); - graph().removeFixed(this); - } - } + public void prepareDelete() { + GraalError.guarantee(graph().isBeforeStage(StructuredGraph.StageFlag.FLOATING_READS) || !hasUsagesOfType(Memory), "Cannot delete %s with memory usages %s", this, usages().snapshot()); + super.prepareDelete(); } @Override - public void prepareDelete() { - GraalError.guarantee(predecessor() instanceof SingleMemoryKill, "Cannot delete %s as its predecessor %s is not a SingleMemoryKill", this, predecessor()); - GraalError.guarantee(getKilledLocationIdentity().equals(((SingleMemoryKill) predecessor()).getKilledLocationIdentity()), - "Cannot delete %s as its predecessor %s kills a different location (%s vs. %s)", this, predecessor(), getKilledLocationIdentity(), - ((SingleMemoryKill) predecessor()).getKilledLocationIdentity()); - if (hasUsages()) { - // Memory edges are moved to the predecessor. - replaceAtUsages(predecessor(), InputType.Memory); + public Node canonical(CanonicalizerTool tool) { + if (graph().isBeforeStage(StructuredGraph.StageFlag.FLOATING_READS)) { + if (!(predecessor() instanceof WithExceptionNode)) { + return new BeginNode(); + } + } else { + // after floating read - we need to check the memory graph + if (tool.allUsagesAvailable() && !(predecessor() instanceof WithExceptionNode) && !hasUsagesOfType(Memory)) { + return new BeginNode(); + } } - // The guards are moved up to the preceding begin node. - super.prepareDelete(); + return this; } } From ef1eac1956f90aed2795163cead274a976308f2a Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 29 Sep 2021 16:36:01 +0200 Subject: [PATCH 472/681] compiler: InvokeWithExceptionNode should killKillingBegin() when replaceWithInvoke() --- .../nodes/InvokeWithExceptionNode.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java index 141f756bfac4..93067d8447e6 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java @@ -178,9 +178,12 @@ public Map getDebugProperties(Map map) { return debugProperties; } - @SuppressWarnings("try") public AbstractBeginNode killKillingBegin() { - AbstractBeginNode begin = next(); + return killKillingBegin(next()); + } + + @SuppressWarnings("try") + public AbstractBeginNode killKillingBegin(AbstractBeginNode begin) { if (begin instanceof KillingBeginNode) { try (DebugCloseable position = begin.withNodeSourcePosition()) { AbstractBeginNode newBegin = new BeginNode(); @@ -256,7 +259,19 @@ public InvokeNode replaceWithNonThrowing() { @Override public void simplify(SimplifierTool tool) { if (exceptionEdge() instanceof UnreachableBeginNode) { - replaceWithInvoke(); + AbstractBeginNode storedNext = next(); + InvokeNode replacement = replaceWithInvoke(); + if (graph().isAfterStage(StructuredGraph.StageFlag.FLOATING_READS)) { + if (!tool.allUsagesAvailable()) { + // we don't know about the usages - do nothing + return; + } + storedNext.replaceAtUsages(replacement, Memory); + } + // kill the killing begin + AbstractBeginNode newBegin = killKillingBegin(storedNext); + tool.addToWorkList(newBegin.next()); + tool.addToWorkList(newBegin); } } } From 26f35306258c687a1e7697180610a9ceb8ef2d6e Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 9 Sep 2021 11:57:25 +0200 Subject: [PATCH 473/681] compiler: support WithExceptionNode in node intrinsic plugins --- .../graalvm/compiler/java/BytecodeParser.java | 18 +++++ .../PluginReplacementWithExceptionNode.java | 75 +++++++++++++++++++ .../graphbuilderconf/GraphBuilderContext.java | 13 ++++ .../processor/GeneratedFoldPlugin.java | 2 +- .../GeneratedNodeIntrinsicPlugin.java | 16 +++- .../processor/GeneratedPlugin.java | 13 +++- .../processor/PluginGenerator.java | 6 +- .../compiler/replacements/PEGraphDecoder.java | 31 +++++++- 8 files changed, 166 insertions(+), 8 deletions(-) create mode 100644 compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementWithExceptionNode.java diff --git a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index 2abb4da4d865..82fc408977ed 100644 --- a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -349,6 +349,7 @@ import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.PluginReplacementNode; +import org.graalvm.compiler.nodes.PluginReplacementWithExceptionNode; import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; import org.graalvm.compiler.nodes.ProfileData.ProfileSource; import org.graalvm.compiler.nodes.ProfileData.SwitchProbabilityData; @@ -2156,6 +2157,23 @@ public void replacePlugin(GeneratedInvocationPlugin plugin, ResolvedJavaMethod t } } + @Override + public void replacePluginWithException(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, + PluginReplacementWithExceptionNode.ReplacementWithExceptionFunction replacementFunction) { + assert replacementFunction != null; + JavaType returnType = maybeEagerlyResolve(targetMethod.getSignature().getReturnType(method.getDeclaringClass()), targetMethod.getDeclaringClass()); + StampPair returnStamp = getReplacements().getGraphBuilderPlugins().getOverridingStamp(this, returnType, false); + if (returnStamp == null) { + returnStamp = StampFactory.forDeclaredType(getAssumptions(), returnType, false); + } + WithExceptionNode node = new PluginReplacementWithExceptionNode(returnStamp.getTrustedStamp(), args, replacementFunction, plugin.getClass().getSimpleName()); + if (returnType.getJavaKind() == JavaKind.Void) { + add(node); + } else { + addPush(returnType.getJavaKind(), node); + } + } + protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) { InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod, true); if (plugin != null) { diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementWithExceptionNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementWithExceptionNode.java new file mode 100644 index 000000000000..6a675ea84c0e --- /dev/null +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementWithExceptionNode.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020, 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 org.graalvm.compiler.nodes; + +import java.util.Map; + +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.nodeinfo.NodeCycles; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.NodeSize; +import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; + +@NodeInfo(nameTemplate = "PluginReplacementWithException/{p#pluginName}", cycles = NodeCycles.CYCLES_IGNORED, size = NodeSize.SIZE_IGNORED) +public final class PluginReplacementWithExceptionNode extends WithExceptionNode { + public static final NodeClass TYPE = NodeClass.create(PluginReplacementWithExceptionNode.class); + + @Input protected NodeInputList args; + private final ReplacementWithExceptionFunction function; + private final String pluginName; + + public PluginReplacementWithExceptionNode(Stamp stamp, ValueNode[] args, ReplacementWithExceptionFunction function, String pluginName) { + super(TYPE, stamp); + this.args = new NodeInputList<>(this, args); + this.function = function; + this.pluginName = pluginName; + } + + public boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection) { + return function.replace(b, injection, stamp, args); + } + + public interface ReplacementWithExceptionFunction { + boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection, Stamp stamp, NodeInputList args); + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Short) { + return super.toString(verbosity) + "/" + pluginName; + } + return super.toString(verbosity); + } + + @Override + public Map getDebugProperties(Map map) { + map.put("name", pluginName); + return super.getDebugProperties(map); + } +} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java index d1f3122b2188..98e78541206b 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java @@ -51,6 +51,7 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.PluginReplacementNode; +import org.graalvm.compiler.nodes.PluginReplacementWithExceptionNode; import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.StructuredGraph; @@ -475,6 +476,18 @@ default AbstractBeginNode genExplicitExceptionEdge(BytecodeExceptionKind excepti default void replacePlugin(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, PluginReplacementNode.ReplacementFunction replacementFunction) { throw GraalError.unimplemented(); } + + /** + * + * @param plugin + * @param targetMethod + * @param args + * @param replacementFunction + */ + default void replacePluginWithException(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, + PluginReplacementWithExceptionNode.ReplacementWithExceptionFunction replacementFunction) { + throw GraalError.unimplemented(); + } } class GraphBuilderContextUtil { diff --git a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java index 1a3c1f8e21c8..595574be3f41 100644 --- a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java +++ b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java @@ -74,7 +74,7 @@ protected void createExecute(AbstractProcessor processor, PrintWriter out, Injec List params = intrinsicMethod.getParameters(); out.printf(" if (b.shouldDeferPlugin(this)) {\n"); - out.printf(" b.replacePlugin(this, targetMethod, args, %s.FUNCTION);\n", getReplacementName()); + out.printf(" b.replacePlugin%s(this, targetMethod, args, %s.FUNCTION);\n", getReplacementFunctionSuffix(processor), getReplacementName()); out.printf(" return true;\n"); out.printf(" }\n"); diff --git a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java index 8d1690f72393..bb43edba67d1 100644 --- a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java +++ b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java @@ -186,7 +186,7 @@ protected void factoryCall(AbstractProcessor processor, PrintWriter out, Injecte out.printf(" }\n"); if (needsReplacement(processor) && !inReplacement) { out.printf(" if (b.canDeferPlugin(this)) {\n"); - out.printf(" b.replacePlugin(this, targetMethod, args, %s.FUNCTION);\n", getReplacementName()); + out.printf(" b.replacePlugin%s(this, targetMethod, args, %s.FUNCTION);\n", getReplacementFunctionSuffix(processor), getReplacementName()); out.printf(" return true;\n"); out.printf(" }\n"); out.printf(" throw GraalError.shouldNotReachHere(\"Can't inline plugin \" + b.getClass().toString());\n"); @@ -206,7 +206,19 @@ protected void verifyConstantArgument(PrintWriter out, String argName, TypeMirro @Override protected void createOtherClasses(AbstractProcessor processor, PrintWriter out) { if (needsReplacement(processor)) { - super.createOtherClasses(processor, out); + if (isWithExceptionReplacement(processor)) { + /* + * We need a WithExceptionNode replacement. + */ + String name = getReplacementName(); + out.printf("final class %s implements PluginReplacementWithExceptionNode.ReplacementWithExceptionFunction {\n", name); + out.printf(" static PluginReplacementWithExceptionNode.ReplacementWithExceptionFunction FUNCTION = new %s();\n", name); + InjectedDependencies deps = new InjectedDependencies(false, intrinsicMethod); + createHelpers(processor, out, deps); + out.printf("}\n"); + } else { + super.createOtherClasses(processor, out); + } } } diff --git a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java index 0649c60ac9e1..b691ea63db8c 100644 --- a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java +++ b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java @@ -28,6 +28,7 @@ import java.util.Set; import java.util.function.Function; +import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; @@ -215,6 +216,12 @@ protected boolean needsReplacement(AbstractProcessor processor) { return true; } + protected boolean isWithExceptionReplacement(AbstractProcessor processor) { + Element nodeElement = intrinsicMethod.getEnclosingElement(); + TypeMirror withExceptionNodeType = processor.getType("org.graalvm.compiler.nodes.WithExceptionNode"); + return processor.env().getTypeUtils().isAssignable(nodeElement.asType(), withExceptionNodeType); + } + protected static String getReturnKind(ExecutableElement method) { switch (method.getReturnType().getKind()) { case BOOLEAN: @@ -304,7 +311,7 @@ protected String constantArgument(AbstractProcessor processor, out.printf(" } else {\n"); if (!isReplacement) { out.printf(" if (b.shouldDeferPlugin(this)) {\n"); - out.printf(" b.replacePlugin(this, targetMethod, args, %s.FUNCTION);\n", getReplacementName()); + out.printf(" b.replacePlugin%s(this, targetMethod, args, %s.FUNCTION);\n", getReplacementFunctionSuffix(processor), getReplacementName()); out.printf(" return true;\n"); out.printf(" }\n"); out.printf(" assert b.canDeferPlugin(this) : b.getClass().toString() + \" \" + %s;\n", argFormatter.apply(nodeIdx)); @@ -314,4 +321,8 @@ protected String constantArgument(AbstractProcessor processor, out.printf(" }\n"); return argName; } + + protected String getReplacementFunctionSuffix(AbstractProcessor processor) { + return isWithExceptionReplacement(processor) ? "WithException" : ""; + } } diff --git a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java index d93dd69ef7d2..4cc14fa9327b 100644 --- a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java +++ b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java @@ -158,7 +158,11 @@ protected static void createImports(PrintWriter out, AbstractProcessor processor extra.add("org.graalvm.compiler.nodes.graphbuilderconf." + plugin.pluginSuperclass()); if (plugin.needsReplacement(processor)) { extra.add("org.graalvm.compiler.graph.NodeInputList"); - extra.add("org.graalvm.compiler.nodes.PluginReplacementNode"); + if (plugin.isWithExceptionReplacement(processor)) { + extra.add("org.graalvm.compiler.nodes.PluginReplacementWithExceptionNode"); + } else { + extra.add("org.graalvm.compiler.nodes.PluginReplacementNode"); + } } } Pattern packageClassBoundary = Pattern.compile("\\.([A-Z])"); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java index 5c726a6b1de4..c44119aec9a2 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java @@ -85,6 +85,7 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PluginReplacementNode; +import org.graalvm.compiler.nodes.PluginReplacementWithExceptionNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; import org.graalvm.compiler.nodes.StateSplit; @@ -120,6 +121,7 @@ import org.graalvm.compiler.nodes.java.NewMultiArrayNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; +import org.graalvm.compiler.nodes.memory.MemoryKill; import org.graalvm.compiler.nodes.spi.Canonicalizable; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.CoreProvidersDelegate; @@ -633,10 +635,10 @@ public GraphBuilderContext getNonIntrinsicAncestor() { } protected class PEPluginGraphBuilderContext extends PENonAppendGraphBuilderContext { - protected FixedWithNextNode insertBefore; + protected final FixedNode insertBefore; protected ValueNode pushedNode; - public PEPluginGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode insertBefore) { + public PEPluginGraphBuilderContext(PEMethodScope inlineScope, FixedNode insertBefore) { super(inlineScope, inlineScope.invokeData != null ? inlineScope.invokeData.invoke : null); this.insertBefore = insertBefore; } @@ -685,9 +687,22 @@ private void updateLastInstruction(T value) { if (value instanceof FixedWithNextNode) { FixedWithNextNode fixed = (FixedWithNextNode) value; graph.addBeforeFixed(insertBefore, fixed); + } else if (value instanceof WithExceptionNode) { + WithExceptionNode withExceptionNode = (WithExceptionNode) value; + GraalError.guarantee(insertBefore instanceof WithExceptionNode, "Cannot replace %s with %s which is a %s", insertBefore, value, WithExceptionNode.class.getSimpleName()); + WithExceptionNode replacee = (WithExceptionNode) insertBefore; + graph.replaceWithExceptionSplit(replacee, withExceptionNode); + AbstractBeginNode next = withExceptionNode.next(); + if (withExceptionNode instanceof MemoryKill) { + /* Insert the correct memory killing begin node at the next edge. */ + GraalError.guarantee(next instanceof BeginNode, "Not a BeginNode %s", next); + AbstractBeginNode beginNode = graph.add(withExceptionNode.createNextBegin()); + withExceptionNode.setNext(beginNode); + beginNode.setNext(next); + } } else if (value instanceof FixedNode) { // Block terminating fixed nodes shouldn't be inserted - throw GraalError.shouldNotReachHere(); + throw GraalError.shouldNotReachHere(String.format("value: %s, insertBefore: %s", value, insertBefore)); } } } @@ -1492,6 +1507,16 @@ protected Node canonicalizeFixedNode(MethodScope s, Node node) { } else if (pluginReplacementMustSucceed()) { throw new GraalError("Plugin failed:" + node); } + } else if (node instanceof PluginReplacementWithExceptionNode) { + PluginReplacementWithExceptionNode pluginReplacementNode = (PluginReplacementWithExceptionNode) node; + PEPluginGraphBuilderContext graphBuilderContext = new PEPluginGraphBuilderContext(methodScope, + pluginReplacementNode); + boolean success = pluginReplacementNode.replace(graphBuilderContext, providers.getReplacements()); + if (success) { + replacedNode = graphBuilderContext.pushedNode; + } else if (pluginReplacementMustSucceed()) { + throw new GraalError("Plugin failed:" + node); + } } return super.canonicalizeFixedNode(methodScope, replacedNode); From 203d062d43892b9ae5c689f36c4904e666fa1541 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 2 Sep 2021 15:54:18 +0200 Subject: [PATCH 474/681] compiler: make BasicArrayCopyNode a WithExceptionNode --- .../nodes/BasicArrayCopyNode.java | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java index 2f82eca0aa12..3e6d5680eafc 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -32,12 +32,14 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; +import org.graalvm.compiler.nodes.WithExceptionNode; import org.graalvm.compiler.nodes.memory.MemoryKill; import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; import org.graalvm.word.LocationIdentity; @@ -49,7 +51,7 @@ * Base class for nodes that intrinsify {@link System#arraycopy}. */ @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = SIZE_64) -public class BasicArrayCopyNode extends AbstractMemoryCheckpoint implements ArrayCopy { +public class BasicArrayCopyNode extends WithExceptionNode implements ArrayCopy, StateSplit { public static final NodeClass TYPE = NodeClass.create(BasicArrayCopyNode.class); @@ -59,18 +61,20 @@ public class BasicArrayCopyNode extends AbstractMemoryCheckpoint implements Arra @OptionalInput(Memory) protected MemoryKill lastLocationAccess; + @OptionalInput(InputType.State) protected FrameState stateAfter; + protected JavaKind elementKind; protected int bci; - public BasicArrayCopyNode(NodeClass type, ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, JavaKind elementKind, int bci) { + public BasicArrayCopyNode(NodeClass type, ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, JavaKind elementKind, int bci) { super(type, StampFactory.forKind(JavaKind.Void)); this.bci = bci; this.args = new NodeInputList<>(this, new ValueNode[]{src, srcPos, dest, destPos, length}); this.elementKind = elementKind != JavaKind.Illegal ? elementKind : null; } - public BasicArrayCopyNode(NodeClass type, ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, JavaKind elementKind) { + public BasicArrayCopyNode(NodeClass type, ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, JavaKind elementKind) { this(type, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI); } @@ -123,4 +127,21 @@ public void setStateDuring(FrameState stateDuring) { updateUsages(this.stateDuring, stateDuring); this.stateDuring = stateDuring; } + + @Override + public FrameState stateAfter() { + return stateAfter; + } + + @Override + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + @Override + public boolean hasSideEffect() { + return true; + } } From 635ec249a22e2971552773538497e01f066a31a6 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 2 Sep 2021 15:54:35 +0200 Subject: [PATCH 475/681] compiler: allow lowering of Unwind nodes after floating read phase (for WithExceptionNodes) --- .../org/graalvm/compiler/replacements/SnippetTemplate.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index 822c1bd5ba71..918c21df08fc 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -1732,8 +1732,8 @@ public UnmodifiableEconomicMap instantiate(MetaAccessProvider metaAc } } if (unwindPath != null) { - GraalError.guarantee(replacee.graph().isBeforeStage(StageFlag.FLOATING_READS), - "Using a snippet with an UnwindNode after floating reads would require support for the memory graph"); + GraalError.guarantee(replacee.graph().isBeforeStage(StageFlag.FLOATING_READS) || replacee instanceof WithExceptionNode, + "Using a snippet with an UnwindNode after floating reads would require support for the memory graph (unless the replacee has an exception edge)"); GraalError.guarantee(replacee instanceof WithExceptionNode, "Snippet has an UnwindNode, but replacee is not a node with an exception handler"); FixedWithNextNode unwindPathDuplicate = (FixedWithNextNode) duplicates.get(unwindPath); @@ -1751,8 +1751,6 @@ public UnmodifiableEconomicMap instantiate(MetaAccessProvider metaAc * because lowering should not remove edges from the original CFG. */ if (replacee instanceof WithExceptionNode) { - GraalError.guarantee(replacee.graph().isBeforeStage(StageFlag.FLOATING_READS), - "Using a snippet with an UnwindNode after floating reads would require support for the memory graph"); GraalError.guarantee(originalWithExceptionNextNode != null, "Need to have next node to link placeholder to."); WithExceptionNode newExceptionNode = replacee.graph().add(new PlaceholderWithExceptionNode()); From 279a960c4a5f83f175b8246a184637e3c4751127 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 21 Sep 2021 11:42:43 +0200 Subject: [PATCH 476/681] compiler: SnippetTemplate diagnostics --- .../src/org/graalvm/compiler/replacements/SnippetTemplate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index 918c21df08fc..c3db6134268f 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -1751,7 +1751,7 @@ public UnmodifiableEconomicMap instantiate(MetaAccessProvider metaAc * because lowering should not remove edges from the original CFG. */ if (replacee instanceof WithExceptionNode) { - GraalError.guarantee(originalWithExceptionNextNode != null, "Need to have next node to link placeholder to."); + GraalError.guarantee(originalWithExceptionNextNode != null, "Need to have next node to link placeholder to: %s", replacee); WithExceptionNode newExceptionNode = replacee.graph().add(new PlaceholderWithExceptionNode()); From 9aa5c25c53d84dbbaa63900aa4bcbba58d6c5419 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 11 Oct 2021 13:37:54 +0200 Subject: [PATCH 477/681] compiler: introduce PluginReplacementInterface --- .../nodes/PluginReplacementInterface.java | 32 +++++++++++++++++++ .../compiler/nodes/PluginReplacementNode.java | 3 +- .../PluginReplacementWithExceptionNode.java | 3 +- .../compiler/replacements/PEGraphDecoder.java | 19 +++-------- 4 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementInterface.java diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementInterface.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementInterface.java new file mode 100644 index 000000000000..4ec77200478b --- /dev/null +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementInterface.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 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 org.graalvm.compiler.nodes; + +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; + +public interface PluginReplacementInterface extends FixedNodeInterface { + boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection); +} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementNode.java index d861cbb6519d..72789b34b98a 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementNode.java @@ -37,7 +37,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @NodeInfo(nameTemplate = "PluginReplacement/{p#pluginName}", cycles = NodeCycles.CYCLES_IGNORED, size = NodeSize.SIZE_IGNORED) -public final class PluginReplacementNode extends FixedWithNextNode { +public final class PluginReplacementNode extends FixedWithNextNode implements PluginReplacementInterface { public static final NodeClass TYPE = NodeClass.create(PluginReplacementNode.class); @Input protected NodeInputList args; @@ -51,6 +51,7 @@ public PluginReplacementNode(Stamp stamp, ValueNode[] args, ReplacementFunction this.pluginName = pluginName; } + @Override public boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection) { return function.replace(b, injection, stamp, args); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementWithExceptionNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementWithExceptionNode.java index 6a675ea84c0e..f08352c41b92 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementWithExceptionNode.java @@ -37,7 +37,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @NodeInfo(nameTemplate = "PluginReplacementWithException/{p#pluginName}", cycles = NodeCycles.CYCLES_IGNORED, size = NodeSize.SIZE_IGNORED) -public final class PluginReplacementWithExceptionNode extends WithExceptionNode { +public final class PluginReplacementWithExceptionNode extends WithExceptionNode implements PluginReplacementInterface { public static final NodeClass TYPE = NodeClass.create(PluginReplacementWithExceptionNode.class); @Input protected NodeInputList args; @@ -51,6 +51,7 @@ public PluginReplacementWithExceptionNode(Stamp stamp, ValueNode[] args, Replace this.pluginName = pluginName; } + @Override public boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection) { return function.replace(b, injection, stamp, args); } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java index c44119aec9a2..9bf4c2381dcf 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java @@ -84,8 +84,7 @@ import org.graalvm.compiler.nodes.MergeNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; -import org.graalvm.compiler.nodes.PluginReplacementNode; -import org.graalvm.compiler.nodes.PluginReplacementWithExceptionNode; +import org.graalvm.compiler.nodes.PluginReplacementInterface; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; import org.graalvm.compiler.nodes.StateSplit; @@ -1497,20 +1496,10 @@ protected Node canonicalizeFixedNode(MethodScope s, Node node) { } } } - if (node instanceof PluginReplacementNode) { - PluginReplacementNode pluginReplacementNode = (PluginReplacementNode) node; + if (node instanceof PluginReplacementInterface) { + PluginReplacementInterface pluginReplacementNode = (PluginReplacementInterface) node; PEPluginGraphBuilderContext graphBuilderContext = new PEPluginGraphBuilderContext(methodScope, - pluginReplacementNode); - boolean success = pluginReplacementNode.replace(graphBuilderContext, providers.getReplacements()); - if (success) { - replacedNode = graphBuilderContext.pushedNode; - } else if (pluginReplacementMustSucceed()) { - throw new GraalError("Plugin failed:" + node); - } - } else if (node instanceof PluginReplacementWithExceptionNode) { - PluginReplacementWithExceptionNode pluginReplacementNode = (PluginReplacementWithExceptionNode) node; - PEPluginGraphBuilderContext graphBuilderContext = new PEPluginGraphBuilderContext(methodScope, - pluginReplacementNode); + pluginReplacementNode.asFixedNode()); boolean success = pluginReplacementNode.replace(graphBuilderContext, providers.getReplacements()); if (success) { replacedNode = graphBuilderContext.pushedNode; From d774ff3a7491b229b381f1b847f76d242e8b9d5d Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 13 Oct 2021 11:00:53 +0200 Subject: [PATCH 478/681] compiler: WithExceptionNode#killExceptionEdge should check for null edge --- .../src/org/graalvm/compiler/nodes/WithExceptionNode.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/WithExceptionNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/WithExceptionNode.java index eee80b7218c2..7a9b94683406 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/WithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/WithExceptionNode.java @@ -90,8 +90,10 @@ public void setExceptionEdge(AbstractBeginNode x) { public void killExceptionEdge() { AbstractBeginNode edge = exceptionEdge(); - setExceptionEdge(null); - GraphUtil.killCFG(edge); + if (edge != null) { + setExceptionEdge(null); + GraphUtil.killCFG(edge); + } } @Override From 3adbc2f016f84ca2430ac182d2fe2a06fe9ecba8 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 14 Oct 2021 10:46:40 +0200 Subject: [PATCH 479/681] compiler: document GraphBuilderContext#replace*Plugin --- .../graphbuilderconf/GraphBuilderContext.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java index 98e78541206b..674c9d515032 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java @@ -467,22 +467,31 @@ default AbstractBeginNode genExplicitExceptionEdge(BytecodeExceptionKind excepti } /** + * Replaces an invocation of a given method by inserting a {@link PluginReplacementNode} that + * {@linkplain GraphBuilderContext#shouldDeferPlugin defers} the application of an + * {@link InvocationPlugin}. * - * @param plugin - * @param targetMethod - * @param args - * @param replacementFunction + * @param plugin the {@link InvocationPlugin} that is deferred + * @param targetMethod the target of the replacement invocation + * @param args the arguments to the replacement invocation + * @param replacementFunction the replacement function for deferred application of the + * {@code plugin} */ default void replacePlugin(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, PluginReplacementNode.ReplacementFunction replacementFunction) { throw GraalError.unimplemented(); } /** + * Replaces an invocation of a given method by inserting a + * {@link PluginReplacementWithExceptionNode} that + * {@linkplain GraphBuilderContext#shouldDeferPlugin defers} the application of an + * {@link InvocationPlugin}. * - * @param plugin - * @param targetMethod - * @param args - * @param replacementFunction + * @param plugin the {@link InvocationPlugin} that is deferred + * @param targetMethod the target of the replacement invocation + * @param args the arguments to the replacement invocation + * @param replacementFunction the replacement function for deferred application of the + * {@code plugin} */ default void replacePluginWithException(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, PluginReplacementWithExceptionNode.ReplacementWithExceptionFunction replacementFunction) { From a9e0bcccd452aa1f61a05b3a89de9448ce834803 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 14 Oct 2021 10:55:23 +0200 Subject: [PATCH 480/681] compiler: document PluginReplacementInterface --- .../compiler/nodes/PluginReplacementInterface.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementInterface.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementInterface.java index 4ec77200478b..78b9a1c0f502 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementInterface.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementInterface.java @@ -27,6 +27,14 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +/** + * Interface for nodes responsible for {@linkplain GraphBuilderContext#shouldDeferPlugin deferring} + * {@linkplain org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin invocation plugin} + * application. + */ public interface PluginReplacementInterface extends FixedNodeInterface { + /** + * Replaces this node by applying the stored plugin. + */ boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection); } From 94e4d4a28f10cde4e6b3235846b49a5857ced58b Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 14 Oct 2021 11:04:27 +0200 Subject: [PATCH 481/681] compiler: improve javadoc for SnippetTemplate#verifyWithExceptionNode --- .../graalvm/compiler/replacements/SnippetTemplate.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index c3db6134268f..6b95b1cc30b8 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -1584,7 +1584,13 @@ private void rewireMemoryGraph(ValueNode replacee, UnmodifiableEconomicMap Date: Thu, 14 Oct 2021 11:09:06 +0200 Subject: [PATCH 482/681] compiler: improve javadoc of Node#has*UsagesOfType --- .../src/org/graalvm/compiler/graph/Node.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index 2c0855746db9..c11b1531a2c9 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -439,7 +439,7 @@ public final boolean hasExactlyOneUsage() { } /** - * Checks whether this node has only usages of that type. + * Checks whether this node has only usages of a given {@link InputType}. * * @param type the type of usages to look for */ @@ -457,7 +457,7 @@ public final boolean hasOnlyUsagesOfType(InputType type) { } /** - * Checks whether this node has usages of that type. + * Checks whether this node has usages of a given {@link InputType}. * * @param type the type of usages to look for */ From 98249172ba586a8ff174cc2c82099c51863671ca Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Thu, 14 Oct 2021 11:29:28 +0200 Subject: [PATCH 483/681] fix debugger not displaying frame variables as strings when the debugger does not request the specific STRING tag for the variables --- .../src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java index c51f0ee87f58..6a4020703150 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java @@ -3067,7 +3067,12 @@ private static Object readValue(PacketStream input, JDWPContext context) { public static void writeValue(byte tag, Object value, PacketStream reply, boolean tagged, JDWPContext context) { if (tagged) { - reply.writeByte(tag); + if (tag == TagConstants.OBJECT) { + // get specific tag type for things like strings and classloaders etc. + reply.writeByte(context.getTag(value)); + } else { + reply.writeByte(tag); + } } switch (tag) { case BOOLEAN: From 3033eaf3c3d7617ee33d521b23da7b2ecf637042 Mon Sep 17 00:00:00 2001 From: Allan Gregersen Date: Thu, 14 Oct 2021 13:08:16 +0200 Subject: [PATCH 484/681] let callsite handle tag conversion for object type tags --- .../truffle/espresso/jdwp/impl/JDWP.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java index 6a4020703150..5218f9db540c 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java @@ -22,9 +22,6 @@ */ package com.oracle.truffle.espresso.jdwp.impl; -import static com.oracle.truffle.espresso.jdwp.api.TagConstants.BOOLEAN; -import static com.oracle.truffle.espresso.jdwp.api.TagConstants.VOID; - import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; @@ -2641,7 +2638,7 @@ static CommandResult createReply(Packet packet, JDWPContext context) { private static void setArrayValues(JDWPContext context, PacketStream input, int index, int values, Object array, byte tag) { for (int i = index; i < index + values; i++) { switch (tag) { - case BOOLEAN: + case TagConstants.BOOLEAN: boolean bool = input.readBoolean(); byte[] boolArray = context.getUnboxedArray(array); boolArray[i] = bool ? (byte) 1 : (byte) 0; @@ -2776,6 +2773,9 @@ static CommandResult createReply(Packet packet, JDWPContext context) { } byte sigbyte = input.readByte(); + if (sigbyte == TagConstants.OBJECT) { + sigbyte = context.getTag(value); + } writeValue(sigbyte, value, reply, true, context); } @@ -3034,9 +3034,9 @@ private static Object readValue(byte valueKind, PacketStream input, JDWPContext private static Object readValue(PacketStream input, JDWPContext context) { byte valueKind = input.readByte(); switch (valueKind) { - case VOID: + case TagConstants.VOID: return Void.TYPE; - case BOOLEAN: + case TagConstants.BOOLEAN: return input.readBoolean(); case TagConstants.BYTE: return input.readByte(); @@ -3067,15 +3067,10 @@ private static Object readValue(PacketStream input, JDWPContext context) { public static void writeValue(byte tag, Object value, PacketStream reply, boolean tagged, JDWPContext context) { if (tagged) { - if (tag == TagConstants.OBJECT) { - // get specific tag type for things like strings and classloaders etc. - reply.writeByte(context.getTag(value)); - } else { - reply.writeByte(tag); - } + reply.writeByte(tag); } switch (tag) { - case BOOLEAN: + case TagConstants.BOOLEAN: if (value.getClass() == Long.class) { long unboxed = (long) value; reply.writeBoolean(unboxed > 0 ? true : false); From e5fe19b5143862fd62ab0e1a0cbe31960b447879 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 14 Oct 2021 13:09:33 +0200 Subject: [PATCH 485/681] Link libsulong to stdlib if on Darwin --- .../com.oracle.truffle.llvm.libraries.bitcode/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.libraries.bitcode/CMakeLists.txt b/sulong/projects/com.oracle.truffle.llvm.libraries.bitcode/CMakeLists.txt index 418bd5d509c4..dab618129eb3 100644 --- a/sulong/projects/com.oracle.truffle.llvm.libraries.bitcode/CMakeLists.txt +++ b/sulong/projects/com.oracle.truffle.llvm.libraries.bitcode/CMakeLists.txt @@ -101,7 +101,9 @@ else() endif() target_include_directories(sulong PRIVATE ${GRAALVM_LLVM_INCLUDE_DIR}) -target_link_options(sulong PRIVATE -nostdlib) +if(NOT MX_OS STREQUAL "darwin") + target_link_options(sulong PRIVATE -nostdlib) +endif() install(TARGETS sulong DESTINATION bin) if(NOT WIN32) From 8cec100616d0101352df2aea2f6dba01bc046ad1 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Fri, 8 Oct 2021 13:07:17 -0500 Subject: [PATCH 486/681] Update truffleruby import in vm --- vm/mx.vm/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 0d8060ac5c01..4b38cb8f6dfa 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -57,7 +57,7 @@ }, { "name": "truffleruby", - "version": "bbd2a3362f8e84b9bcda5eda6cd3ad36f15d1966", + "version": "b5454b64b6aa113ef2c091f50a4e1211e5ecdcea", "dynamic": True, "urls": [ {"url": "https://github.com/oracle/truffleruby.git", "kind": "git"}, From c0f35240b0b4e4b6bca570f2c21b7261ff674125 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Sun, 10 Oct 2021 21:31:51 -0700 Subject: [PATCH 487/681] c1visualizer launcher requires JDK 8 --- compiler/mx.compiler/mx_graal_tools.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/mx.compiler/mx_graal_tools.py b/compiler/mx.compiler/mx_graal_tools.py index 7fc38543e848..3dd5c7bd7b27 100644 --- a/compiler/mx.compiler/mx_graal_tools.py +++ b/compiler/mx.compiler/mx_graal_tools.py @@ -73,9 +73,9 @@ def run_netbeans_app(app_name, env=None, args=None): def netbeans_jdk(appName): v8u20 = mx.VersionSpec("1.8.0_20") v8u40 = mx.VersionSpec("1.8.0_40") - def _igvJdkVersionCheck(version): - return version < v8u20 or version >= v8u40 - return mx.get_jdk(_igvJdkVersionCheck, versionDescription='(< 1.8.0u20 or >= 1.8.0u40)', purpose="running " + appName).home + def _c1vJdkVersionCheck(version): + return version >= v8u40 and str(version).startswith('1.8.0') + return mx.get_jdk(_c1vJdkVersionCheck, versionDescription='(1.8 JDK that is >= 1.8.0u40 )', purpose="running " + appName).home def igv(args): """(obsolete) informs about IGV""" @@ -165,7 +165,7 @@ def hsdis(args, copyToDir=None): except IOError as e: mx.warn('Could not copy {} to {}: {}'.format(path, dest, str(e))) -def hcfdis(args): +def hcfdis(args, library='HCFDIS'): """disassemble HexCodeFiles embedded in text files Run a tool over the input files to convert all embedded HexCodeFiles @@ -177,7 +177,7 @@ def hcfdis(args): args = parser.parse_args(args) - path = mx.library('HCFDIS').get_path(resolve=True) + path = mx.library(library).get_path(resolve=True) mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files) if args.map is not None: From 1bcf79613becfc607992ef59776d6a45e76cc4aa Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Thu, 14 Oct 2021 11:11:46 -0700 Subject: [PATCH 488/681] Fix SubstrateGraphBuilderPlugins.extractClassArray(). Ignore stores to a different array. --- .../SubstrateGraphBuilderPlugins.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java index 7653a2be1f22..40fac0f35a43 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java @@ -378,20 +378,21 @@ static Class[] extractClassArray(AnnotationSubstitutionProcessor annotationSu } while (successor instanceof StoreIndexedNode) { StoreIndexedNode store = (StoreIndexedNode) successor; - assert getDeoptProxyOriginalValue(store.array()).equals(newArray); - ValueNode valueNode = store.value(); - if (valueNode.isConstant() && !valueNode.isNullConstant()) { - Class clazz = snippetReflection.asObject(Class.class, valueNode.asJavaConstant()); - /* - * It is possible that the returned class is a substitution class, e.g., - * DynamicHub returned for a Class.class constant. Get the target class of the - * substitution class. - */ - classList.add(annotationSubstitutions == null ? clazz : annotationSubstitutions.getTargetClass(clazz)); - } else { - /* If not all classes are non-null constants we bail out. */ - classList = null; - break; + if (getDeoptProxyOriginalValue(store.array()).equals(newArray)) { + ValueNode valueNode = store.value(); + if (valueNode.isConstant() && !valueNode.isNullConstant()) { + Class clazz = snippetReflection.asObject(Class.class, valueNode.asJavaConstant()); + /* + * It is possible that the returned class is a substitution class, e.g., + * DynamicHub returned for a Class.class constant. Get the target class of + * the substitution class. + */ + classList.add(annotationSubstitutions == null ? clazz : annotationSubstitutions.getTargetClass(clazz)); + } else { + /* If not all classes are non-null constants we bail out. */ + classList = null; + break; + } } successor = unwrapNode(store.next()); } From 3f4eefd51048f46be84aae74d0ba75f76d1b7ded Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 14 Oct 2021 22:03:30 +0200 Subject: [PATCH 489/681] change c1visualizer and hcfdis methods for downstream usage --- compiler/mx.compiler/mx_graal_tools.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/mx.compiler/mx_graal_tools.py b/compiler/mx.compiler/mx_graal_tools.py index 3dd5c7bd7b27..be37f3389d38 100644 --- a/compiler/mx.compiler/mx_graal_tools.py +++ b/compiler/mx.compiler/mx_graal_tools.py @@ -71,7 +71,6 @@ def run_netbeans_app(app_name, env=None, args=None): mx.run(launch+args, env=env) def netbeans_jdk(appName): - v8u20 = mx.VersionSpec("1.8.0_20") v8u40 = mx.VersionSpec("1.8.0_40") def _c1vJdkVersionCheck(version): return version >= v8u40 and str(version).startswith('1.8.0') @@ -91,7 +90,7 @@ def c1visualizer(args): """run the C1 Compiler Visualizer""" env = dict(os.environ) env['jdkhome'] = netbeans_jdk("C1 Visualizer") - run_netbeans_app('C1Visualizer', env, args) + run_netbeans_app('C1Visualizer', env, args() if callable(args) else args) def hsdis(args, copyToDir=None): """download the hsdis library @@ -165,7 +164,7 @@ def hsdis(args, copyToDir=None): except IOError as e: mx.warn('Could not copy {} to {}: {}'.format(path, dest, str(e))) -def hcfdis(args, library='HCFDIS'): +def hcfdis(args, cp=None): """disassemble HexCodeFiles embedded in text files Run a tool over the input files to convert all embedded HexCodeFiles @@ -177,7 +176,7 @@ def hcfdis(args, library='HCFDIS'): args = parser.parse_args(args) - path = mx.library(library).get_path(resolve=True) + path = cp or mx.library('HCFDIS').get_path(resolve=True) mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files) if args.map is not None: From 8ca4d20dd038aba47eacdbb32291e7349b8ffc13 Mon Sep 17 00:00:00 2001 From: Andrew Craik Date: Wed, 13 Oct 2021 12:42:37 +1000 Subject: [PATCH 490/681] Always validate loop fragments as acyclic. This change converts an assert in LoopFragment into a guarantee since the check is very cheap and a cyclic graph will not be compiled correctly - failing early with a good error is preferred. --- .../compiler/nodes/loop/LoopFragment.java | 59 +++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragment.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragment.java index 99988f4b7a1b..ef350b98ed63 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragment.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragment.java @@ -31,6 +31,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.MapCursor; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; import org.graalvm.compiler.graph.Node; @@ -248,7 +249,7 @@ protected static void computeNodes(NodeBitMap nodes, Graph graph, LoopEx loop, I } final NodeBitMap nonLoopNodes = graph.createNodeBitMap(); - Deque worklist = new ArrayDeque<>(); + WorkQueue worklist = new WorkQueue(graph); for (AbstractBeginNode b : blocks) { if (b.isDeleted()) { continue; @@ -307,6 +308,56 @@ public int hashCode() { } } + static class WorkQueue implements Iterable { + Deque worklist; + NodeBitMap contents; + + WorkQueue(Graph graph) { + worklist = new ArrayDeque<>(); + contents = new NodeBitMap(graph); + } + + public void addFirst(WorkListEntry e) { + worklist.addFirst(e); + GraalError.guarantee(!contents.isMarked(e.n), "Trying to addFirst an entry that is already in the work queue!"); + contents.mark(e.n); + } + + public void push(WorkListEntry e) { + worklist.push(e); + GraalError.guarantee(!contents.isMarked(e.n), "Trying to push an entry that is already in the work queue!"); + contents.mark(e.n); + } + + public WorkListEntry peek() { + return worklist.peek(); + } + + public WorkListEntry pop() { + WorkListEntry e = worklist.pop(); + contents.clear(e.n); + return e; + } + + public boolean isEmpty() { + return worklist.isEmpty(); + } + + public boolean contains(WorkListEntry e) { + return contents.contains(e.n); + } + + public void clear() { + worklist.clear(); + contents.clearAll(); + } + + @Override + public Iterator iterator() { + return worklist.iterator(); + } + } + static TriState isLoopNode(Node n, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) { if (loopNodes.isMarked(n)) { return TriState.TRUE; @@ -321,13 +372,13 @@ static TriState isLoopNode(Node n, NodeBitMap loopNodes, NodeBitMap nonLoopNodes return TriState.UNKNOWN; } - private static void pushWorkList(Deque workList, Node node, NodeBitMap loopNodes) { + private static void pushWorkList(WorkQueue workList, Node node, NodeBitMap loopNodes) { WorkListEntry entry = new WorkListEntry(node, loopNodes); - assert !workList.contains(entry) : "node " + node + " added to worklist twice"; + GraalError.guarantee(!workList.contains(entry), "node %s added to worklist twice", node); workList.push(entry); } - private static void markFloating(Deque workList, LoopEx loop, Node start, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) { + private static void markFloating(WorkQueue workList, LoopEx loop, Node start, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) { if (isLoopNode(start, loopNodes, nonLoopNodes).isKnown()) { return; } From f012ece17e8ad33f9236de0882fe581e4a25db8f Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Fri, 8 Oct 2021 16:46:53 +0200 Subject: [PATCH 491/681] resort to loop frequencies computed based on loop exit frequencies and not loop end ones (this effectively assumes a deopt is never contributing to a loop frequency because a deopt from compiled code never results in a loop exit node being executed) --- .../compiler/nodes/cfg/ControlFlowGraph.java | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java index bc751a9c5e68..b24ec6bfa5f7 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java @@ -685,16 +685,9 @@ private void finishLocalLoopFrequency(LoopBeginNode lb) { Block lexBlock = blockFor(lex); assert lexBlock != null; final double lexFrequency = lexBlock.getRelativeFrequency(); - final double localLoopFrequency = localLoopFrequencyData.get(lb).getLoopFrequency(); - /* - * While the local loop frequency is calculated without the predecessor frequency, the - * exit frequency needs to be adjusted already to compute any outer loop local - * frequencies correctly. - */ final double loopPredFrequency = blockFor(lb.forwardEnd()).relativeFrequency; - final double virginExitFrequency = multiplyRelativeFrequencies(lexFrequency, localLoopFrequency, loopPredFrequency); - // exit path, we set the exit probability - lexBlock.setRelativeFrequency(virginExitFrequency); + final double loopExitFrequencyScaled = multiplyRelativeFrequencies(lexFrequency, loopPredFrequency); + lexBlock.setRelativeFrequency(loopExitFrequencyScaled); } } @@ -709,29 +702,36 @@ private void computeLocalLoopFrequencies() { private double calculateLocalLoopFrequency(LoopBeginNode lb) { Block header = blockFor(lb); assert header != null; - double loopEndFrequency = 0D; + /* + * Ideally we would like to take the loop end frequency sum here because it respects control + * flow sinks (unwinds and deopts) inside the loop. However, semantically, if we ever exit a + * loop in compiled code it means we did not do so by an unwind or deopt but a loop exit, + * thus we ignore the end (and sink) frequencies and compute loop frequency purely based on + * the exit frequencies. + */ + double loopExitFrequencySum = 0D; ProfileSource source = ProfileSource.UNKNOWN; - for (LoopEndNode len : lb.loopEnds()) { - Block endBlock = blockFor(len); - assert endBlock != null; - assert endBlock.relativeFrequency >= 0D; - loopEndFrequency += endBlock.relativeFrequency; - source = source.combine(endBlock.frequencySource); + + for (LoopExitNode lex : lb.loopExits()) { + Block lexBlock = blockFor(lex); + assert lexBlock != null; + assert lexBlock.relativeFrequency >= 0D; + loopExitFrequencySum += lexBlock.relativeFrequency; + source = source.combine(lexBlock.frequencySource); } - loopEndFrequency = Math.min(1, loopEndFrequency); - loopEndFrequency = Math.max(ControlFlowGraph.MIN_RELATIVE_FREQUENCY, loopEndFrequency); + loopExitFrequencySum = Math.min(1, loopExitFrequencySum); + loopExitFrequencySum = Math.max(ControlFlowGraph.MIN_RELATIVE_FREQUENCY, loopExitFrequencySum); double loopFrequency = -1; - if (loopEndFrequency == 1D) { - // endless loop, loop with exit and deopt unconditionally after the exit + if (loopExitFrequencySum == 0D) { + // loop without loop exit nodes (deopt or throw exited) loopFrequency = MAX_RELATIVE_FREQUENCY; } else { - double exitFrequency = 1D - loopEndFrequency; - loopFrequency = 1D / exitFrequency; + loopFrequency = 1D / loopExitFrequencySum; - assert Double.isFinite(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " endFrequency=" + loopEndFrequency; - assert !Double.isNaN(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " endFrequency=" + loopEndFrequency; + assert Double.isFinite(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum; + assert !Double.isNaN(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum; } localLoopFrequencyData.put(lb, LoopFrequencyData.create(loopFrequency, source)); return loopFrequency; From 1d2fd73b0f19ce09388147b8294048e64c5fbebc Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Tue, 12 Oct 2021 11:40:34 +0200 Subject: [PATCH 492/681] cfg: weigh loop exit frequencies properly and add debug capabilites for end vs exit frequencies to the CFG --- .../compiler/nodes/cfg/ControlFlowGraph.java | 122 +++++++++++++++++- 1 file changed, 118 insertions(+), 4 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java index b24ec6bfa5f7..a003542748ab 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.nodes.cfg; import static org.graalvm.compiler.core.common.cfg.AbstractBlockBase.BLOCK_ID_COMPARATOR; +import static org.graalvm.compiler.options.OptionType.Expert; import java.util.ArrayList; import java.util.Arrays; @@ -43,6 +44,7 @@ import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FixedNode; @@ -54,8 +56,22 @@ import org.graalvm.compiler.nodes.ProfileData.ProfileSource; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; public final class ControlFlowGraph implements AbstractControlFlowGraph { + + public static class CFGOptions { + //@formatter:off + @Option(help = "Debug flag to dump loop frequency differences computed based on loop end or exit nodes." + + "If the frequencies diverge a lot, this may indicate missing profiles on control flow" + + "inside the loop body.", type = Expert) + public static final OptionKey ForceDumpEndVsExitLoopFrequencies = new OptionKey<>(false); + @Option(help = "Scaling factor of frequency difference computed based on loop ends or exits", type = Expert) + public static final OptionKey LoopExitVsLoopEndFrequencyDiff = new OptionKey<>(1000D); + //@formatter:on + } + /** * Don't allow relative frequency values to be become too small or too high as this makes * frequency calculations over- or underflow the range of a double. This commonly happens with @@ -89,12 +105,20 @@ public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlo cfg.identifyBlocks(); + boolean loopInfoComputed = false; + if (CFGOptions.ForceDumpEndVsExitLoopFrequencies.getValue(graph.getOptions())) { + // additional loop info for sink frequencies inside the loop body + cfg.computeLoopInformation(); + cfg.computeDominators(); + loopInfoComputed = true; + } + cfg.computeFrequencies(); - if (computeLoops) { + if (computeLoops && !loopInfoComputed) { cfg.computeLoopInformation(); } - if (computeDominators) { + if (computeDominators && !loopInfoComputed) { cfg.computeDominators(); assert cfg.verifyRPOInnerLoopsFirst(); } @@ -681,13 +705,22 @@ private void identifyBlock(Block block) { private void finishLocalLoopFrequency(LoopBeginNode lb) { calculateLocalLoopFrequency(lb); + + double sumAllLexFrequency = 0; + for (LoopExitNode lex : lb.loopExits()) { + sumAllLexFrequency += blockFor(lex).relativeFrequency; + } + for (LoopExitNode lex : lb.loopExits()) { Block lexBlock = blockFor(lex); assert lexBlock != null; final double lexFrequency = lexBlock.getRelativeFrequency(); + final double scaleLexFrequency = lexFrequency / sumAllLexFrequency; final double loopPredFrequency = blockFor(lb.forwardEnd()).relativeFrequency; - final double loopExitFrequencyScaled = multiplyRelativeFrequencies(lexFrequency, loopPredFrequency); - lexBlock.setRelativeFrequency(loopExitFrequencyScaled); + final double exitFrequency = multiplyRelativeFrequencies(scaleLexFrequency, loopPredFrequency); + // exit path, we set the exit probability + lexBlock.setRelativeFrequency(exitFrequency); + GraalError.guarantee(blockFor(lex).relativeFrequency <= loopPredFrequency, "Lex frequency %f must be below pred frequency %f", loopPredFrequency, exitFrequency); } } @@ -730,6 +763,86 @@ private double calculateLocalLoopFrequency(LoopBeginNode lb) { } else { loopFrequency = 1D / loopExitFrequencySum; + if (CFGOptions.ForceDumpEndVsExitLoopFrequencies.getValue(lb.getOptions())) { + + // verify integrity of the CFG so far + + outer: for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + for (Block succ : loopBlock.getSuccessors()) { + if (isDominatorTreeLoopExit(succ)) { + // loop exit successor frequency is weighted differently + continue outer; + } + if (succ.isLoopHeader()) { + // header frequency is set to 1 artificially to compute local + // frequencies + continue outer; + } + } + if (loopBlock.isLoopHeader()) { + // loop exit successor frequency is weighted differently + continue; + } + final double selfFrequency = loopBlock.relativeFrequency; + double succFrequency = 0D; + for (Block succ : loopBlock.getSuccessors()) { + succFrequency += succ.relativeFrequency; + } + if (loopBlock.getSuccessorCount() == 0) { + GraalError.guarantee(loopBlock.getEndNode() instanceof ControlSinkNode, "Must sink if there is no successor"); + // frequency "lost" + continue; + } + String message = String.format("Successors must add up for block %s with begin %s, selfF=%f succF=%f", loopBlock, loopBlock.getBeginNode(), selfFrequency, succFrequency); + GraalError.guarantee(succFrequency >= selfFrequency - 0.01D, message); + } + + double loopEndFrequencySum = 0D; + for (LoopEndNode len : lb.loopEnds()) { + Block lenBlock = blockFor(len); + loopEndFrequencySum += lenBlock.relativeFrequency; + } + final double endBasedFrequency = 1 / (1 - loopEndFrequencySum); + /* + * For loops without loop exit nodes we may only have deopt loop exit paths, they + * are however not part of the loop data structure of a Loop, thus it might be + * that the reverse post order did not yet visit all sinks + */ + @SuppressWarnings("unused") // use for debugging only + boolean sinkingImplicitExitsFullyVisited = true; + double loopSinkFrequencySum = 0D; + for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + FixedNode blockEndNode = loopBlock.getEndNode(); + if (blockEndNode instanceof ControlSinkNode) { + double sinkBlockFrequency = blockFor(blockEndNode).relativeFrequency; + loopSinkFrequencySum += sinkBlockFrequency; + if (sinkBlockFrequency == -1D) { + sinkingImplicitExitsFullyVisited = false; + } + } + } + for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + if (loopBlock.isLoopHeader() && loopBlock.getBeginNode() != lb) { + LoopBeginNode otherLoop = (LoopBeginNode) loopBlock.getBeginNode(); + double otherLoopExitFrequencySum = 0D; + for (LoopExitNode lex : otherLoop.loopExits()) { + otherLoopExitFrequencySum += blockFor(lex).relativeFrequency; + } + // forward end + final double predFrequency = loopBlock.getFirstPredecessor().relativeFrequency; + GraalError.guarantee(Math.abs(predFrequency - otherLoopExitFrequencySum) <= 0.01D, "Frequencies diverge too much"); + } + } + + if (Math.abs(endBasedFrequency - loopFrequency) > CFGOptions.LoopExitVsLoopEndFrequencyDiff.getValue(lb.getOptions())) { + String message = String.format("Frequency divergence for loop %s,exitBasedFrequency=%.4f endBasedFrequency=%.4f, exitFSum=%.2f / endFSum=%.2f/ sinkSum=%.2f [allSum=%f]", lb, + loopFrequency, endBasedFrequency, loopExitFrequencySum, loopEndFrequencySum, + loopSinkFrequencySum, + (loopExitFrequencySum + loopEndFrequencySum + loopSinkFrequencySum)); + graph.getDebug().forceDump(graph, message); + } + + } assert Double.isFinite(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum; assert !Double.isNaN(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum; } @@ -794,6 +907,7 @@ private void perBasicBlockFrequencyAction(Block b, boolean computingLocalLoopFre } else if (relativeFrequency > MAX_RELATIVE_FREQUENCY) { relativeFrequency = MAX_RELATIVE_FREQUENCY; } + b.setRelativeFrequency(relativeFrequency); if (computingLocalLoopFrequencies) { b.setFrequencySource(source); From 5a6cb2661af809817af671d38d27a7c48209aa4a Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Wed, 13 Oct 2021 10:27:24 +0200 Subject: [PATCH 493/681] cfg:add dumping options to dump loop end vs loop exit derived frequenies --- .../phases/ConvertDeoptimizeToGuardPhase.java | 5 + .../compiler/nodes/StructuredGraph.java | 1 + .../compiler/nodes/cfg/ControlFlowGraph.java | 108 ++++++++++-------- 3 files changed, 67 insertions(+), 47 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java index ead822210245..be62206c5710 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java @@ -110,6 +110,11 @@ protected void run(final StructuredGraph graph, final CoreProviders context) { } new DeadCodeEliminationPhase(Optional).apply(graph); + + if (!graph.isAfterStage(StageFlag.DEOPT_TO_GUARD)) { + // ran multiple times, we just wanna set it the first time + graph.setAfterStage(StageFlag.DEOPT_TO_GUARD); + } } private static void trySplitFixedGuard(FixedGuardNode fixedGuard, CoreProviders context, LazyValue lazyLoops) { diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 4e0905ba1a90..54b0d0bbfb0e 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -157,6 +157,7 @@ public static AllowAssumptions ifNonNull(Assumptions assumptions) { * Different stages of the compilation regarding the status of various graph properties. */ public enum StageFlag { + DEOPT_TO_GUARD, PARTIAL_ESCAPE, HIGH_TIER, FLOATING_READS, diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java index a003542748ab..fe093becfce3 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java @@ -54,6 +54,7 @@ import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.ProfileData.LoopFrequencyData; import org.graalvm.compiler.nodes.ProfileData.ProfileSource; +import org.graalvm.compiler.nodes.StructuredGraph.StageFlag; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.Option; @@ -705,12 +706,14 @@ private void identifyBlock(Block block) { private void finishLocalLoopFrequency(LoopBeginNode lb) { calculateLocalLoopFrequency(lb); - double sumAllLexFrequency = 0; + /* + * Take the sum of all exit frequencies and scale each exit with the importance in relation + * to the other exits. This factor is multiplied with the real predecessor frequency. + */ for (LoopExitNode lex : lb.loopExits()) { sumAllLexFrequency += blockFor(lex).relativeFrequency; } - for (LoopExitNode lex : lb.loopExits()) { Block lexBlock = blockFor(lex); assert lexBlock != null; @@ -718,7 +721,6 @@ private void finishLocalLoopFrequency(LoopBeginNode lb) { final double scaleLexFrequency = lexFrequency / sumAllLexFrequency; final double loopPredFrequency = blockFor(lb.forwardEnd()).relativeFrequency; final double exitFrequency = multiplyRelativeFrequencies(scaleLexFrequency, loopPredFrequency); - // exit path, we set the exit probability lexBlock.setRelativeFrequency(exitFrequency); GraalError.guarantee(blockFor(lex).relativeFrequency <= loopPredFrequency, "Lex frequency %f must be below pred frequency %f", loopPredFrequency, exitFrequency); } @@ -763,52 +765,17 @@ private double calculateLocalLoopFrequency(LoopBeginNode lb) { } else { loopFrequency = 1D / loopExitFrequencySum; - if (CFGOptions.ForceDumpEndVsExitLoopFrequencies.getValue(lb.getOptions())) { - - // verify integrity of the CFG so far - - outer: for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { - for (Block succ : loopBlock.getSuccessors()) { - if (isDominatorTreeLoopExit(succ)) { - // loop exit successor frequency is weighted differently - continue outer; - } - if (succ.isLoopHeader()) { - // header frequency is set to 1 artificially to compute local - // frequencies - continue outer; - } - } - if (loopBlock.isLoopHeader()) { - // loop exit successor frequency is weighted differently - continue; - } - final double selfFrequency = loopBlock.relativeFrequency; - double succFrequency = 0D; - for (Block succ : loopBlock.getSuccessors()) { - succFrequency += succ.relativeFrequency; - } - if (loopBlock.getSuccessorCount() == 0) { - GraalError.guarantee(loopBlock.getEndNode() instanceof ControlSinkNode, "Must sink if there is no successor"); - // frequency "lost" - continue; - } - String message = String.format("Successors must add up for block %s with begin %s, selfF=%f succF=%f", loopBlock, loopBlock.getBeginNode(), selfFrequency, succFrequency); - GraalError.guarantee(succFrequency >= selfFrequency - 0.01D, message); - } + /* + * Wait until deopt to guard ran to "complain" about frequency mismatches to avoid false + * positives for loop optimizations + */ + if (CFGOptions.ForceDumpEndVsExitLoopFrequencies.getValue(lb.getOptions()) && lb.graph().isAfterStage(StageFlag.DEOPT_TO_GUARD)) { - double loopEndFrequencySum = 0D; - for (LoopEndNode len : lb.loopEnds()) { - Block lenBlock = blockFor(len); - loopEndFrequencySum += lenBlock.relativeFrequency; - } - final double endBasedFrequency = 1 / (1 - loopEndFrequencySum); /* * For loops without loop exit nodes we may only have deopt loop exit paths, they * are however not part of the loop data structure of a Loop, thus it might be * that the reverse post order did not yet visit all sinks */ - @SuppressWarnings("unused") // use for debugging only boolean sinkingImplicitExitsFullyVisited = true; double loopSinkFrequencySum = 0D; for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { @@ -816,11 +783,53 @@ private double calculateLocalLoopFrequency(LoopBeginNode lb) { if (blockEndNode instanceof ControlSinkNode) { double sinkBlockFrequency = blockFor(blockEndNode).relativeFrequency; loopSinkFrequencySum += sinkBlockFrequency; - if (sinkBlockFrequency == -1D) { - sinkingImplicitExitsFullyVisited = false; + } + if (blockFor(blockEndNode).relativeFrequency == -1D) { + sinkingImplicitExitsFullyVisited = false; + } + } + if (sinkingImplicitExitsFullyVisited) { + // verify integrity of the CFG so far + outer: for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + for (Block succ : loopBlock.getSuccessors()) { + if (isDominatorTreeLoopExit(succ)) { + // loop exit successor frequency is weighted differently + continue outer; + } + if (succ.isLoopHeader()) { + // header frequency is set to 1 artificially to compute local + // frequencies + continue outer; + } + } + if (loopBlock.isLoopHeader()) { + // loop exit successor frequency is weighted differently + continue; + } + final double selfFrequency = loopBlock.relativeFrequency; + double succFrequency = 0D; + for (Block succ : loopBlock.getSuccessors()) { + succFrequency += succ.relativeFrequency; + } + if (loopBlock.getSuccessorCount() == 0) { + GraalError.guarantee(loopBlock.getEndNode() instanceof ControlSinkNode, "Must sink if there is no successor"); + // frequency "lost" + continue; + } + String message = String.format("Successors must add up for block %s with begin %s, selfF=%f succF=%f", loopBlock, loopBlock.getBeginNode(), selfFrequency, succFrequency); + if (succFrequency < selfFrequency - 0.001D/* delta */) { + graph.getDebug().forceDump(graph, message); + throw GraalError.shouldNotReachHere(message); } } } + double loopEndFrequencySum = 0D; + for (LoopEndNode len : lb.loopEnds()) { + Block lenBlock = blockFor(len); + loopEndFrequencySum += lenBlock.relativeFrequency; + } + final double endBasedFrequency = 1 / (1 - loopEndFrequencySum); + // verify inner loop frequency calculations used sane loop exit frequencies for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { if (loopBlock.isLoopHeader() && loopBlock.getBeginNode() != lb) { LoopBeginNode otherLoop = (LoopBeginNode) loopBlock.getBeginNode(); @@ -833,8 +842,13 @@ private double calculateLocalLoopFrequency(LoopBeginNode lb) { GraalError.guarantee(Math.abs(predFrequency - otherLoopExitFrequencySum) <= 0.01D, "Frequencies diverge too much"); } } - - if (Math.abs(endBasedFrequency - loopFrequency) > CFGOptions.LoopExitVsLoopEndFrequencyDiff.getValue(lb.getOptions())) { + /* + * "Endless" looking loops, i.e., loops without exit nodes (only deopt exits) look + * like inifinite loops if we take an exit frequency of "0", which results in max + * frequency + */ + final boolean hasLoopExits = lb.loopExits().count() > 0; + if (Math.abs(endBasedFrequency - loopFrequency) > CFGOptions.LoopExitVsLoopEndFrequencyDiff.getValue(lb.getOptions()) && hasLoopExits) { String message = String.format("Frequency divergence for loop %s,exitBasedFrequency=%.4f endBasedFrequency=%.4f, exitFSum=%.2f / endFSum=%.2f/ sinkSum=%.2f [allSum=%f]", lb, loopFrequency, endBasedFrequency, loopExitFrequencySum, loopEndFrequencySum, loopSinkFrequencySum, From 2ef8ca7ea49730302785b0fd71be1707b6f22808 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Fri, 15 Oct 2021 11:16:05 +0300 Subject: [PATCH 494/681] Fix a merge conflict in docs/tools/profiling.md --- docs/tools/profiling.md | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/docs/tools/profiling.md b/docs/tools/profiling.md index 14d9a3ceaee9..1b07d5bd0528 100644 --- a/docs/tools/profiling.md +++ b/docs/tools/profiling.md @@ -86,42 +86,21 @@ algorithm. Total Time: Time spent somewhere on the stack. ---------------------------------------------------------------------------------------------- Thread[main,5,main] -<<<<<<< HEAD Name || Total Time || Self Time || Location ---------------------------------------------------------------------------------------------- accept || 2150ms 86.0% || 2150ms 86.0% || primes.js~13-22:191-419 next || 2470ms 98.8% || 320ms 12.8% || primes.js~31-37:537-737 :program || 2500ms 100.0% || 30ms 1.2% || primes.js~1-46:0-982 ---------------------------------------------------------------------------------------------- -======= - Name | Total Time || Self Time || Location - ---------------------------------------------------------------------------------------------------- - accept | 7330ms 88.8% || 7330ms 88.8% || primes.js~13-22:191-419 - :program | 8250ms 100.0% || 420ms 5.1% || primes.js~1-46:0-982 - next | 7820ms 94.8% || 250ms 3.0% || primes.js~31-37:537-737 - DivisibleByFilter | 440ms 5.3% || 240ms 2.9% || primes.js~7-23:66-421 - AcceptFilter | 20ms 0.2% || 10ms 0.1% || primes.js~1-5:0-63 - Primes | 20ms 0.2% || 0ms 0.0% || primes.js~25-38:424-739 - ---------------------------------------------------------------------------------------------------- ->>>>>>> 7bc06f81a03378c93f5528526281564089dc89d8 ``` By default the sampler prints an execution time histogram for each JavaScript function. -<<<<<<< HEAD - You can produce a flame graph in SVG format by specifying that with the `--cpusampler.Output=flamegraph` option: + You can produce a flame graph in SVG format by requesting that with the `--cpusampler.Output=flamegraph` option: ```shell js primes.js --cpusampler --cpusampler.Output=flamegraph --cpusampler.OutputFile=primes.svg ``` - It should produce something like this: -======= - You can produce a flame graph in SVG format by doing - ```shell - js primes.js --cpusampler --cpusampler.Output=flamegraph --cpusampler.OutputFile=primes.svg - ``` - which should produce something like this ->>>>>>> 7bc06f81a03378c93f5528526281564089dc89d8 ![](img/profiler_flamegraph.png) @@ -144,12 +123,7 @@ algorithm. ``` Now use the CPU Tracer to collect execution counts of each statement: -<<<<<<< HEAD -4. Run `js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=accept` -to collect execution counts for all statements in methods ending with `accept`: -======= 4. Run `js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=*accept` to collect execution counts for all statements in methods ending with `accept`: ->>>>>>> 7bc06f81a03378c93f5528526281564089dc89d8 ```shell js primes.js --cputracer --cputracer.TraceStatements --cputracer.FilterRootName=accept Computed 5000 prime numbers. The last 5 are 48563,48571,48589,48593,48611. From b22011d80b60ee31b71b912f8961646da6d6b30c Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Fri, 15 Oct 2021 11:50:59 +0200 Subject: [PATCH 495/681] only apply JDK version check when launching C1Visualizer --- compiler/mx.compiler/mx_graal_tools.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/mx.compiler/mx_graal_tools.py b/compiler/mx.compiler/mx_graal_tools.py index be37f3389d38..f4e36ea9955a 100644 --- a/compiler/mx.compiler/mx_graal_tools.py +++ b/compiler/mx.compiler/mx_graal_tools.py @@ -70,12 +70,6 @@ def run_netbeans_app(app_name, env=None, args=None): launch.append('-J-Dnetbeans.logger.console=false') mx.run(launch+args, env=env) -def netbeans_jdk(appName): - v8u40 = mx.VersionSpec("1.8.0_40") - def _c1vJdkVersionCheck(version): - return version >= v8u40 and str(version).startswith('1.8.0') - return mx.get_jdk(_c1vJdkVersionCheck, versionDescription='(1.8 JDK that is >= 1.8.0u40 )', purpose="running " + appName).home - def igv(args): """(obsolete) informs about IGV""" mx.warn( @@ -88,8 +82,11 @@ def igv(args): def c1visualizer(args): """run the C1 Compiler Visualizer""" + v8u40 = mx.VersionSpec("1.8.0_40") + def _c1vJdkVersionCheck(version): + return version >= v8u40 and str(version).startswith('1.8.0') env = dict(os.environ) - env['jdkhome'] = netbeans_jdk("C1 Visualizer") + env['jdkhome'] = mx.get_jdk(_c1vJdkVersionCheck, versionDescription='(1.8 JDK that is >= 1.8.0u40 )', purpose="running C1 Visualizer").home run_netbeans_app('C1Visualizer', env, args() if callable(args) else args) def hsdis(args, copyToDir=None): From d9e24688c089d89cbf05ff38ac4b2503b5b79dd8 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Fri, 15 Oct 2021 13:15:37 +0300 Subject: [PATCH 496/681] Follow Gilles D. comments --- docs/getting-started/graalvm-community/linux-aarch64.md | 1 - .../graalvm-enterprise/installation-linux-aarch64.md | 1 - docs/reference-manual/polyglot-programming.md | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/getting-started/graalvm-community/linux-aarch64.md b/docs/getting-started/graalvm-community/linux-aarch64.md index ccfd9e44186b..21a1123332a6 100644 --- a/docs/getting-started/graalvm-community/linux-aarch64.md +++ b/docs/getting-started/graalvm-community/linux-aarch64.md @@ -10,7 +10,6 @@ permalink: /docs/getting-started/linux-aarch64/ As of version 21.0, we provide GraalVM Community Edition for Linux on ARM 64-bit system, based on OpenJDK 11 and OpenJDK 17 for AArch64 architecture. This distribution can be installed on Linux systems for AArch64 CPU architecture. - You can install the GraalVM distribution for Linux ARM64 systems from an archive file (_.tar.gz_). This allows you to install GraalVM for the current user into any location, without affecting other JDK installations. diff --git a/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md b/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md index 26f0978d7a76..9e21e0b69611 100644 --- a/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md +++ b/docs/getting-started/graalvm-enterprise/installation-linux-aarch64.md @@ -8,7 +8,6 @@ permalink: /getting-started/installation-linux-aarch64/ As of version 21.0, Oracle provides GraalVM Enterprise distributions based on Oracle JDK11 and Oracle JDK17 for AArch64 architecture. 
This distribution can be installed on Oracle Linux and Red Hat Enterprise Linux(RHEL) systems for AArch64 CPU architecture. - You can install the GraalVM distribution for Linux ARM64 systems from an archive file (_.tar.gz_). This allows you to install GraalVM for the current user into any location, without affecting other JDK installations. diff --git a/docs/reference-manual/polyglot-programming.md b/docs/reference-manual/polyglot-programming.md index c0a21c2383ec..1d4bb3455a75 100644 --- a/docs/reference-manual/polyglot-programming.md +++ b/docs/reference-manual/polyglot-programming.md @@ -233,7 +233,7 @@ You can configure a language engine for better throughput or startup. ## Passing Options for Language Launchers Every language launcher has been extended with a set of so called _polyglot options_. -Polyglot options allow users of any language launcher to access theoptions of other languages supported by GraalVM (implemented with the Truffle language implementation framework). +Polyglot options allow users of any language launcher to access the options of other languages supported by GraalVM (implemented with the Truffle language implementation framework). The format is: `--.=`. For example, the `R` launcher also supports the `--js.atomics=true` JavaScript option. From 70b6c9f7404585227484da50c96f8523638ff6de Mon Sep 17 00:00:00 2001 From: Katja Goltsova Date: Fri, 15 Oct 2021 12:29:19 +0200 Subject: [PATCH 497/681] Refactor handleRemovedMethod by only taking receiver's klass --- .../espresso/nodes/bytecodes/InvokeInterface.java | 2 +- .../truffle/espresso/nodes/bytecodes/InvokeSpecial.java | 2 +- .../truffle/espresso/nodes/bytecodes/InvokeStatic.java | 2 +- .../truffle/espresso/nodes/bytecodes/InvokeVirtual.java | 2 +- .../espresso/nodes/interop/InvokeEspressoNode.java | 2 +- .../espresso/nodes/methodhandle/MHLinkToNode.java | 2 +- .../truffle/espresso/redefinition/ClassRedefinition.java | 9 ++++++--- .../Target_sun_reflect_NativeMethodAccessorImpl.java | 2 +- 8 files changed, 13 insertions(+), 10 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeInterface.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeInterface.java index 4c1129951d7e..db1cd7bf015d 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeInterface.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeInterface.java @@ -125,7 +125,7 @@ static Method.MethodVersion methodLookup(Method resolutionSeed, StaticObject rec * Accept a slow path once the method has been removed put method behind a boundary to * avoid a deopt loop */ - return ClassRedefinition.handleRemovedMethod(resolutionSeed, receiver.getKlass(), receiver).getMethodVersion(); + return ClassRedefinition.handleRemovedMethod(resolutionSeed, receiver.getKlass()).getMethodVersion(); } int iTableIndex = resolutionSeed.getITableIndex(); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeSpecial.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeSpecial.java index 212e29c84733..9063ece5b3d4 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeSpecial.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeSpecial.java @@ -74,7 +74,7 @@ static Method.MethodVersion methodLookup(Method method, StaticObject receiver) { * Accept a slow path once the method has been removed put method behind a boundary to * avoid a deopt loop. */ - return ClassRedefinition.handleRemovedMethod(method, receiver.getKlass(), receiver).getMethodVersion(); + return ClassRedefinition.handleRemovedMethod(method, receiver.getKlass()).getMethodVersion(); } return method.getMethodVersion(); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeStatic.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeStatic.java index 7ff6fa79257f..8777af830f12 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeStatic.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeStatic.java @@ -104,7 +104,7 @@ static Method.MethodVersion methodLookup(Method staticMethod) { * Accept a slow path once the method has been removed put method behind a boundary to * avoid a deopt loop. */ - return ClassRedefinition.handleRemovedMethod(staticMethod, staticMethod.getDeclaringKlass(), null).getMethodVersion(); + return ClassRedefinition.handleRemovedMethod(staticMethod, staticMethod.getDeclaringKlass()).getMethodVersion(); } return staticMethod.getMethodVersion(); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeVirtual.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeVirtual.java index 508d74fea763..cf864a902c1f 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeVirtual.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/bytecodes/InvokeVirtual.java @@ -162,7 +162,7 @@ static Method.MethodVersion methodLookup(Method resolutionSeed, StaticObject rec * Accept a slow path once the method has been removed put method behind a boundary to * avoid a deopt loop. */ - return ClassRedefinition.handleRemovedMethod(resolutionSeed, receiver.getKlass(), receiver).getMethodVersion(); + return ClassRedefinition.handleRemovedMethod(resolutionSeed, receiver.getKlass()).getMethodVersion(); } /* * Surprisingly, INVOKEVIRTUAL can try to invoke interface methods, even non-default ones. diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/InvokeEspressoNode.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/InvokeEspressoNode.java index 3cd008142326..8d7f0bbb86a7 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/InvokeEspressoNode.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/InvokeEspressoNode.java @@ -47,7 +47,7 @@ public abstract class InvokeEspressoNode extends Node { public final Object execute(Method method, Object receiver, Object[] arguments) throws ArityException, UnsupportedTypeException { Method resolutionSeed = method; if (resolutionSeed.isRemovedByRedefition()) { - resolutionSeed = ClassRedefinition.handleRemovedMethod(method, method.isStatic() ? method.getDeclaringKlass() : ((StaticObject) receiver).getKlass(), (StaticObject) receiver); + resolutionSeed = ClassRedefinition.handleRemovedMethod(method, method.isStatic() ? method.getDeclaringKlass() : ((StaticObject) receiver).getKlass()); } Object result = executeMethod(resolutionSeed.getMethodVersion(), receiver, arguments); /* diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/methodhandle/MHLinkToNode.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/methodhandle/MHLinkToNode.java index 84cf7c747181..a8b2e3afc941 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/methodhandle/MHLinkToNode.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/methodhandle/MHLinkToNode.java @@ -83,7 +83,7 @@ public Object call(Object[] args) { // method might have been redefined or removed by redefinition if (resolutionSeed.isRemovedByRedefition()) { Klass receiverKlass = hasReceiver ? ((StaticObject) basicArgs[0]).getKlass() : resolutionSeed.getDeclaringKlass(); - resolutionSeed = ClassRedefinition.handleRemovedMethod(resolutionSeed, receiverKlass, hasReceiver ? ((StaticObject) basicArgs[0]) : null); + resolutionSeed = ClassRedefinition.handleRemovedMethod(resolutionSeed, receiverKlass); } Method target = linker.linkTo(resolutionSeed, args); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java index e782be2555ab..02866d682172 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java @@ -594,12 +594,15 @@ private void doRedefineClass(ChangePacket packet, List refreshSubCl } } + /** + * @param accessingKlass the receiver's klass when the method is not static, resolutionSeed's + * declaring klass otherwise + */ @TruffleBoundary - public static Method handleRemovedMethod(Method resolutionSeed, Klass accessingKlass, StaticObject receiver) { + public static Method handleRemovedMethod(Method resolutionSeed, Klass accessingKlass) { // wait for potential ongoing redefinition to complete check(); - Klass lookupKlass = receiver != null ? receiver.getKlass() : resolutionSeed.getDeclaringKlass(); - Method replacementMethod = lookupKlass.lookupMethod(resolutionSeed.getName(), resolutionSeed.getRawSignature(), accessingKlass); + Method replacementMethod = accessingKlass.lookupMethod(resolutionSeed.getName(), resolutionSeed.getRawSignature(), accessingKlass); Meta meta = resolutionSeed.getMeta(); if (replacementMethod == null) { throw meta.throwExceptionWithMessage(meta.java_lang_NoSuchMethodError, diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_reflect_NativeMethodAccessorImpl.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_reflect_NativeMethodAccessorImpl.java index 4919e1404fd2..c243dd436f6d 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_reflect_NativeMethodAccessorImpl.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/Target_sun_reflect_NativeMethodAccessorImpl.java @@ -253,7 +253,7 @@ public static Object checkAndWiden(Meta meta, StaticObject arg, Klass targetKlas Method reflectedMethod = m; if (reflectedMethod.isRemovedByRedefition()) { - reflectedMethod = ClassRedefinition.handleRemovedMethod(reflectedMethod, reflectedMethod.isStatic() ? reflectedMethod.getDeclaringKlass() : receiver.getKlass(), receiver); + reflectedMethod = ClassRedefinition.handleRemovedMethod(reflectedMethod, reflectedMethod.isStatic() ? reflectedMethod.getDeclaringKlass() : receiver.getKlass()); } Method method; // actual method to invoke From 874f7fd35ca8f697301c06b68c2d07dcb1c69ffd Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Thu, 14 Oct 2021 12:00:01 +0200 Subject: [PATCH 498/681] refactor cfg debug with regular dump --- .../graalvm/compiler/debug/DebugContext.java | 24 +++ .../phases/ConvertDeoptimizeToGuardPhase.java | 7 - .../compiler/nodes/StructuredGraph.java | 1 - .../compiler/nodes/cfg/ControlFlowGraph.java | 191 +++++++++--------- 4 files changed, 119 insertions(+), 104 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java b/compiler/src/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java index fab940ca425f..d884bef2a8b7 100644 --- a/compiler/src/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java +++ b/compiler/src/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java @@ -1375,6 +1375,30 @@ public void dump(int dumpLevel, Object object, String format, Object arg1, Objec } } + public void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2, Object arg3, Object arg4) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg1, arg2, arg3, arg4); + } + } + + public void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg1, arg2, arg3, arg4, arg5); + } + } + + public void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg1, arg2, arg3, arg4, arg5, arg6); + } + } + + public void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + } + /** * This override exists to catch cases when {@link #dump(int, Object, String, Object)} is called * with one argument bound to a varargs method parameter. It will bind to this method instead of diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java index be62206c5710..45ae54366be8 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java @@ -100,7 +100,6 @@ protected void run(final StructuredGraph graph, final CoreProviders context) { propagateFixed(d, d, context, lazyLoops); } } - if (context != null) { for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.TYPE)) { try (DebugCloseable closable = fixedGuard.withNodeSourcePosition()) { @@ -108,13 +107,7 @@ protected void run(final StructuredGraph graph, final CoreProviders context) { } } } - new DeadCodeEliminationPhase(Optional).apply(graph); - - if (!graph.isAfterStage(StageFlag.DEOPT_TO_GUARD)) { - // ran multiple times, we just wanna set it the first time - graph.setAfterStage(StageFlag.DEOPT_TO_GUARD); - } } private static void trySplitFixedGuard(FixedGuardNode fixedGuard, CoreProviders context, LazyValue lazyLoops) { diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 54b0d0bbfb0e..4e0905ba1a90 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -157,7 +157,6 @@ public static AllowAssumptions ifNonNull(Assumptions assumptions) { * Different stages of the compilation regarding the status of various graph properties. */ public enum StageFlag { - DEOPT_TO_GUARD, PARTIAL_ESCAPE, HIGH_TIER, FLOATING_READS, diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java index fe093becfce3..ce69e5e45147 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java @@ -25,7 +25,6 @@ package org.graalvm.compiler.nodes.cfg; import static org.graalvm.compiler.core.common.cfg.AbstractBlockBase.BLOCK_ID_COMPARATOR; -import static org.graalvm.compiler.options.OptionType.Expert; import java.util.ArrayList; import java.util.Arrays; @@ -54,11 +53,11 @@ import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.ProfileData.LoopFrequencyData; import org.graalvm.compiler.nodes.ProfileData.ProfileSource; -import org.graalvm.compiler.nodes.StructuredGraph.StageFlag; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; public final class ControlFlowGraph implements AbstractControlFlowGraph { @@ -66,9 +65,9 @@ public static class CFGOptions { //@formatter:off @Option(help = "Debug flag to dump loop frequency differences computed based on loop end or exit nodes." + "If the frequencies diverge a lot, this may indicate missing profiles on control flow" - + "inside the loop body.", type = Expert) - public static final OptionKey ForceDumpEndVsExitLoopFrequencies = new OptionKey<>(false); - @Option(help = "Scaling factor of frequency difference computed based on loop ends or exits", type = Expert) + + "inside the loop body.", type = OptionType.Debug) + public static final OptionKey DumpEndVersusExitLoopFrequencies = new OptionKey<>(false); + @Option(help = "Scaling factor of frequency difference computed based on loop ends or exits", type = OptionType.Debug) public static final OptionKey LoopExitVsLoopEndFrequencyDiff = new OptionKey<>(1000D); //@formatter:on } @@ -107,7 +106,7 @@ public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlo cfg.identifyBlocks(); boolean loopInfoComputed = false; - if (CFGOptions.ForceDumpEndVsExitLoopFrequencies.getValue(graph.getOptions())) { + if (CFGOptions.DumpEndVersusExitLoopFrequencies.getValue(graph.getOptions())) { // additional loop info for sink frequencies inside the loop body cfg.computeLoopInformation(); cfg.computeDominators(); @@ -759,109 +758,109 @@ private double calculateLocalLoopFrequency(LoopBeginNode lb) { loopExitFrequencySum = Math.max(ControlFlowGraph.MIN_RELATIVE_FREQUENCY, loopExitFrequencySum); double loopFrequency = -1; - if (loopExitFrequencySum == 0D) { - // loop without loop exit nodes (deopt or throw exited) - loopFrequency = MAX_RELATIVE_FREQUENCY; - } else { - loopFrequency = 1D / loopExitFrequencySum; + loopFrequency = 1D / loopExitFrequencySum; + assert Double.isFinite(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum; + assert !Double.isNaN(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum; + if (CFGOptions.DumpEndVersusExitLoopFrequencies.getValue(lb.getOptions())) { + debugLocalLoopFrequencies(lb, loopFrequency, loopExitFrequencySum); + } + localLoopFrequencyData.put(lb, LoopFrequencyData.create(loopFrequency, source)); + return loopFrequency; + } + + @SuppressWarnings("try") + private void debugLocalLoopFrequencies(LoopBeginNode lb, final double loopFrequency, final double loopExitFrequencySum) { + try (DebugContext.Scope s = lb.getDebug().scope("CFGFrequencyInfo")) { /* - * Wait until deopt to guard ran to "complain" about frequency mismatches to avoid false - * positives for loop optimizations + * For loops without loop exit nodes we may only have deopt loop exit paths, they are + * however not part of the loop data structure of a Loop, thus it might be that the + * reverse post order did not yet visit all sinks */ - if (CFGOptions.ForceDumpEndVsExitLoopFrequencies.getValue(lb.getOptions()) && lb.graph().isAfterStage(StageFlag.DEOPT_TO_GUARD)) { - - /* - * For loops without loop exit nodes we may only have deopt loop exit paths, they - * are however not part of the loop data structure of a Loop, thus it might be - * that the reverse post order did not yet visit all sinks - */ - boolean sinkingImplicitExitsFullyVisited = true; - double loopSinkFrequencySum = 0D; - for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { - FixedNode blockEndNode = loopBlock.getEndNode(); - if (blockEndNode instanceof ControlSinkNode) { - double sinkBlockFrequency = blockFor(blockEndNode).relativeFrequency; - loopSinkFrequencySum += sinkBlockFrequency; - } - if (blockFor(blockEndNode).relativeFrequency == -1D) { - sinkingImplicitExitsFullyVisited = false; - } + boolean sinkingImplicitExitsFullyVisited = true; + double loopSinkFrequencySum = 0D; + for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + FixedNode blockEndNode = loopBlock.getEndNode(); + if (blockEndNode instanceof ControlSinkNode) { + double sinkBlockFrequency = blockFor(blockEndNode).relativeFrequency; + loopSinkFrequencySum += sinkBlockFrequency; } - if (sinkingImplicitExitsFullyVisited) { - // verify integrity of the CFG so far - outer: for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { - for (Block succ : loopBlock.getSuccessors()) { - if (isDominatorTreeLoopExit(succ)) { - // loop exit successor frequency is weighted differently - continue outer; - } - if (succ.isLoopHeader()) { - // header frequency is set to 1 artificially to compute local - // frequencies - continue outer; - } - } - if (loopBlock.isLoopHeader()) { + if (blockFor(blockEndNode).relativeFrequency == -1D) { + sinkingImplicitExitsFullyVisited = false; + } + } + final double delta = 0.001D; + if (sinkingImplicitExitsFullyVisited) { + // verify integrity of the CFG so far + outer: for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + if (loopBlock.isLoopHeader()) { + // loop exit successor frequency is weighted differently + continue; + } + for (Block succ : loopBlock.getSuccessors()) { + if (isDominatorTreeLoopExit(succ)) { // loop exit successor frequency is weighted differently - continue; - } - final double selfFrequency = loopBlock.relativeFrequency; - double succFrequency = 0D; - for (Block succ : loopBlock.getSuccessors()) { - succFrequency += succ.relativeFrequency; - } - if (loopBlock.getSuccessorCount() == 0) { - GraalError.guarantee(loopBlock.getEndNode() instanceof ControlSinkNode, "Must sink if there is no successor"); - // frequency "lost" - continue; + continue outer; } - String message = String.format("Successors must add up for block %s with begin %s, selfF=%f succF=%f", loopBlock, loopBlock.getBeginNode(), selfFrequency, succFrequency); - if (succFrequency < selfFrequency - 0.001D/* delta */) { - graph.getDebug().forceDump(graph, message); - throw GraalError.shouldNotReachHere(message); + if (succ.isLoopHeader()) { + // header frequency is set to 1 artificially to compute local + // frequencies + continue outer; } } - } - double loopEndFrequencySum = 0D; - for (LoopEndNode len : lb.loopEnds()) { - Block lenBlock = blockFor(len); - loopEndFrequencySum += lenBlock.relativeFrequency; - } - final double endBasedFrequency = 1 / (1 - loopEndFrequencySum); - // verify inner loop frequency calculations used sane loop exit frequencies - for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { - if (loopBlock.isLoopHeader() && loopBlock.getBeginNode() != lb) { - LoopBeginNode otherLoop = (LoopBeginNode) loopBlock.getBeginNode(); - double otherLoopExitFrequencySum = 0D; - for (LoopExitNode lex : otherLoop.loopExits()) { - otherLoopExitFrequencySum += blockFor(lex).relativeFrequency; - } - // forward end - final double predFrequency = loopBlock.getFirstPredecessor().relativeFrequency; - GraalError.guarantee(Math.abs(predFrequency - otherLoopExitFrequencySum) <= 0.01D, "Frequencies diverge too much"); + final double selfFrequency = loopBlock.relativeFrequency; + double succFrequency = 0D; + for (Block succ : loopBlock.getSuccessors()) { + succFrequency += succ.relativeFrequency; + } + if (loopBlock.getSuccessorCount() == 0) { + GraalError.guarantee(loopBlock.getEndNode() instanceof ControlSinkNode, "Must sink if there is no successor"); + // frequency "lost" + continue; + } + if (succFrequency < selfFrequency - delta) { + String format = "Successors must add up for block %s with begin %s, selfF=%f succF=%f"; + graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, graph, format, loopBlock, loopBlock.getBeginNode(), selfFrequency, succFrequency); + throw GraalError.shouldNotReachHere(String.format(format, loopBlock, loopBlock.getBeginNode(), selfFrequency, succFrequency)); } } - /* - * "Endless" looking loops, i.e., loops without exit nodes (only deopt exits) look - * like inifinite loops if we take an exit frequency of "0", which results in max - * frequency - */ - final boolean hasLoopExits = lb.loopExits().count() > 0; - if (Math.abs(endBasedFrequency - loopFrequency) > CFGOptions.LoopExitVsLoopEndFrequencyDiff.getValue(lb.getOptions()) && hasLoopExits) { - String message = String.format("Frequency divergence for loop %s,exitBasedFrequency=%.4f endBasedFrequency=%.4f, exitFSum=%.2f / endFSum=%.2f/ sinkSum=%.2f [allSum=%f]", lb, - loopFrequency, endBasedFrequency, loopExitFrequencySum, loopEndFrequencySum, - loopSinkFrequencySum, - (loopExitFrequencySum + loopEndFrequencySum + loopSinkFrequencySum)); - graph.getDebug().forceDump(graph, message); + } + double loopEndFrequencySum = 0D; + for (LoopEndNode len : lb.loopEnds()) { + Block lenBlock = blockFor(len); + loopEndFrequencySum += lenBlock.relativeFrequency; + } + double endBasedFrequency = 1 / (1 - loopEndFrequencySum); + if (loopEndFrequencySum == 1D) { + // loop without any loop exits (and no sinks) + endBasedFrequency = MAX_RELATIVE_FREQUENCY; + } + // verify inner loop frequency calculations used sane loop exit frequencies + for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + if (loopBlock.isLoopHeader() && loopBlock.getBeginNode() != lb) { + LoopBeginNode otherLoop = (LoopBeginNode) loopBlock.getBeginNode(); + double otherLoopExitFrequencySum = 0D; + for (LoopExitNode lex : otherLoop.loopExits()) { + otherLoopExitFrequencySum += blockFor(lex).relativeFrequency; + } + // forward end + final double predFrequency = loopBlock.getFirstPredecessor().relativeFrequency; + GraalError.guarantee(Math.abs(predFrequency - otherLoopExitFrequencySum) <= delta, "Frequencies diverge too much"); } - } - assert Double.isFinite(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum; - assert !Double.isNaN(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum; + /* + * "Endless" looking loops, i.e., loops without exit nodes (only deopt exits) look like + * inifinite loops if we take an exit frequency of "0", which results in max frequency + */ + final boolean hasLoopExits = lb.loopExits().count() > 0; + if (Math.abs(endBasedFrequency - loopFrequency) > CFGOptions.LoopExitVsLoopEndFrequencyDiff.getValue(lb.getOptions()) && hasLoopExits) { + graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, graph, + "Frequency divergence for loop %s,exitBasedFrequency=%.4f endBasedFrequency=%.4f, exitFSum=%.2f / endFSum=%.2f/ sinkSum=%.2f [allSum=%f]", lb, + loopFrequency, endBasedFrequency, loopExitFrequencySum, loopEndFrequencySum, + loopSinkFrequencySum, + (loopExitFrequencySum + loopEndFrequencySum + loopSinkFrequencySum)); + } } - localLoopFrequencyData.put(lb, LoopFrequencyData.create(loopFrequency, source)); - return loopFrequency; } private void resetBlockFrequencies() { From ce25b6a9b81bdc918f4263004f0ebe652824ebad Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Fri, 15 Oct 2021 16:15:40 +0200 Subject: [PATCH 499/681] Make the code that detaches a thread fully uninterruptible. --- .../oracle/svm/core/genscavenge/HeapImpl.java | 1 + .../graal/snippets/CEntryPointSnippets.java | 1 - .../src/com/oracle/svm/core/heap/Heap.java | 1 + .../oracle/svm/core/thread/JavaThreads.java | 15 ++---- .../com/oracle/svm/core/thread/ParkEvent.java | 8 ++++ .../com/oracle/svm/core/thread/VMThreads.java | 48 ++++++------------- 6 files changed, 28 insertions(+), 46 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java index c99c23ecebb1..c957d1a1f0de 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java @@ -385,6 +385,7 @@ public void attachThread(IsolateThread isolateThread) { } @Override + @Uninterruptible(reason = "Thread is detaching and holds the THREAD_MUTEX.") public void detachThread(IsolateThread isolateThread) { ThreadLocalAllocation.disableAndFlushForThread(isolateThread); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index 08bfdf6ca930..ba44d90ffdc4 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -426,7 +426,6 @@ public static int detachThreadSnippet() { @SubstrateForeignCallTarget(stubCallingConvention = false) @Uninterruptible(reason = "Thread state going away.") - @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not (thread-local) allocate while detaching a thread.") private static int detachThreadMT(IsolateThread currentThread) { try { VMThreads.singleton().detachThread(currentThread); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java index b7a938af6eca..477a52857046 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java @@ -69,6 +69,7 @@ protected Heap() { * heap-specific resources, e.g., the TLAB. This method is called for every thread except the * main thread (i.e., the one that maps the image heap). */ + @Uninterruptible(reason = "Thread is detaching and holds the THREAD_MUTEX.") public abstract void detachThread(IsolateThread isolateThread); public abstract void suspendAllocation(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java index 7a5f25aa3ffe..65a1751c30ac 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java @@ -184,10 +184,12 @@ public static boolean isInterrupted(Thread thread) { return toTarget(thread).interrupted; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) protected static AtomicReference getUnsafeParkEvent(Thread thread) { return toTarget(thread).unsafeParkEvent; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) protected static AtomicReference getSleepParkEvent(Thread thread) { return toTarget(thread).sleepParkEvent; } @@ -416,18 +418,9 @@ public boolean tearDown() { return tearDownJavaThreads(); } - /** - * Detach the provided Java thread. - * - * When this method is being executed, we expect that the current thread owns - * {@linkplain VMThreads#THREAD_MUTEX}. This is fine even though this method is not - * {@linkplain Uninterruptible} because this method is either executed as part of a VM operation - * or {@linkplain SafepointBehavior#setIgnoreThreadInSafepointHandling()} was called. - */ - @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate while detaching a thread.") + @Uninterruptible(reason = "Thread is detaching and holds the THREAD_MUTEX.") public static void detachThread(IsolateThread vmThread) { - VMThreads.THREAD_MUTEX.assertIsOwner("Must hold the VMThreads mutex"); - assert SafepointBehavior.isIgnoredBySafepointHandling(vmThread) || VMOperation.isInProgress(); + VMThreads.THREAD_MUTEX.assertIsOwner("Must hold the THREAD_MUTEX."); Thread thread = currentThread.get(vmThread); ParkEvent.detach(getUnsafeParkEvent(thread)); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ParkEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ParkEvent.java index 8e8088306f67..24ddca3b3b97 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ParkEvent.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ParkEvent.java @@ -24,8 +24,10 @@ */ package com.oracle.svm.core.thread; +import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.nativeimage.ImageSingletons; +import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicReference; import com.oracle.svm.core.util.VMError; @@ -80,6 +82,7 @@ protected ParkEvent() { protected abstract void unpark(); /** Use up the cons-cell for this ParkEvent. */ + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) ParkEventConsCell consumeConsCell() { assert consCell != null : "Consuming null cons cell."; ParkEventConsCell result = consCell; @@ -129,6 +132,7 @@ private static ParkEvent acquire() { return result; } + @Uninterruptible(reason = "Thread is detaching and holds the THREAD_MUTEX.") static void detach(AtomicReference ref) { /* * We must not reset the AtomicReference back to null, because a racing thread could @@ -141,6 +145,7 @@ static void detach(AtomicReference ref) { } } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static void release(ParkEvent event) { ParkEventList.getSingleton().push(event); } @@ -190,6 +195,7 @@ final class ParkEventList { private static final ParkEventList SINGLETON = new ParkEventList(); + @Fold public static ParkEventList getSingleton() { return SINGLETON; } @@ -203,6 +209,7 @@ private ParkEventList() { } /** Push an element on to the free-list. */ + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) protected void push(ParkEvent element) { ParkEventConsCell sampleHead; /* Use up the cons-cell for each attempted push to avoid the ABA problem on pops. */ @@ -250,6 +257,7 @@ protected ParkEventConsCell getNext() { return next; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) protected void setNext(ParkEventConsCell next) { this.next = next; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java index 02f16bbbeeef..1e5ee537db6e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java @@ -337,7 +337,10 @@ public void detachThread(IsolateThread thread) { cleanupBeforeDetach(thread); - setIgnoreThreadInSafepointHandlingAndLock(); + // From this point on, all code must be fully uninterruptible because this thread either + // holds the THREAD_MUTEX (see the JavaDoc on THREAD_MUTEX) or because the IsolateThread was + // already freed. + THREAD_MUTEX.lockNoTransition(); OSThreadHandle threadToCleanup; try { detachThreadInSafeContext(thread); @@ -363,25 +366,7 @@ public void detachThread(IsolateThread thread) { cleanupExitedOsThread(threadToCleanup); } - /* - * Make me immune to safepoints and make the safepoint mechanism ignore me. We are calling - * functions that are not marked as @Uninterruptible during the detach process. We hold the - * THREAD_MUTEX, so we know that we are not going to be interrupted by a safepoint. But a - * safepoint can already be requested, or our safepoint counter can reach 0 - so it is still - * possible that we enter the safepoint slow path. - * - * Between setting the status and acquiring the TREAD_MUTEX, we must not access the heap. - * Otherwise, we risk a race with the GC as this thread will continue executing even though the - * VM is at a safepoint. - */ - @Uninterruptible(reason = "Called from uninterruptible code.") - @NeverInline("Prevent that anything floats between setting the status and acquiring the mutex.") - private static void setIgnoreThreadInSafepointHandlingAndLock() { - SafepointBehavior.setIgnoreThreadInSafepointHandling(); - THREAD_MUTEX.lockNoTransition(); - } - - @Uninterruptible(reason = "Isolate thread will be freed.", calleeMustBe = false) + @Uninterruptible(reason = "Thread is detaching and holds the THREAD_MUTEX.") private static void releaseThread(IsolateThread thread) { THREAD_MUTEX.guaranteeIsOwner("This mutex must be locked to prevent that a GC is triggered while detaching a thread from the heap"); Heap.getHeap().detachThread(thread); @@ -407,15 +392,15 @@ private void cleanupExitedOsThread(OSThreadHandle threadToCleanup) { } } - @Uninterruptible(reason = "Manipulates the threads list; broadcasts on changes.") + @Uninterruptible(reason = "Thread is detaching and holds the THREAD_MUTEX.") private static void detachThreadInSafeContext(IsolateThread thread) { - detachJavaThread(thread); + JavaThreads.detachThread(thread); removeFromThreadList(thread); // Signal that the VMThreads list has changed. THREAD_LIST_CONDITION.broadcast(); } - @Uninterruptible(reason = "Called from uninterruptible code.") + @Uninterruptible(reason = "Thread is detaching and holds the THREAD_MUTEX.") private static void removeFromThreadList(IsolateThread thread) { IsolateThread previous = WordFactory.nullPointer(); IsolateThread current = head; @@ -457,13 +442,7 @@ private void waitUntilLastOsThreadExited() { cleanupExitedOsThreads(); } - @Uninterruptible(reason = "For calling interruptible code from uninterruptible code.", calleeMustBe = false) - private static void detachJavaThread(IsolateThread thread) { - JavaThreads.detachThread(thread); - } - @Uninterruptible(reason = "Called from uninterruptible code, but still safe at this point.", calleeMustBe = false, mayBeInlined = true) - @RestrictHeapAccess(access = RestrictHeapAccess.Access.UNRESTRICTED, overridesCallers = true, reason = "Still safe at this point.") private static void cleanupBeforeDetach(IsolateThread thread) { JavaThreads.cleanupBeforeDetach(thread); } @@ -801,7 +780,7 @@ public static void assertStatusVM() { // This method will be removed in GR-34435. @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void setStatusIgnoreSafepoints() { - SafepointBehavior.setPreventVMFromReachingSafepoint(); + SafepointBehavior.setIgnoreThreadInSafepointHandling(); } public static boolean isValidStatus(int status) { @@ -867,11 +846,14 @@ public static int getSafepointBehavior(IsolateThread vmThread) { return safepointBehaviorTL.getVolatile(vmThread); } + /** + * Changes the safepoint behavior so that this thread won't freeze at a safepoint. The + * thread will also actively prevent the VM from reaching a safepoint (regardless of its + * thread status). + */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void setPreventVMFromReachingSafepoint() { - assert safepointChecksEnabled(); safepointBehaviorTL.setVolatile(PREVENT_VM_FROM_REACHING_SAFEPOINT); - Heap.getHeap().suspendAllocation(); } /** @@ -887,9 +869,7 @@ public static void setPreventVMFromReachingSafepoint() { */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) static void setIgnoreThreadInSafepointHandling() { - assert safepointChecksEnabled(); safepointBehaviorTL.setVolatile(IGNORE_THREAD_IN_SAFEPOINT_HANDLING); - Heap.getHeap().suspendAllocation(); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) From c8ac0e4075b41a5ee58d02193535250406a8e2c0 Mon Sep 17 00:00:00 2001 From: Martin Entlicher Date: Fri, 15 Oct 2021 16:50:55 +0200 Subject: [PATCH 500/681] Prevent from attaching a disposed breakpoint. [GR-34454] --- .../src/com/oracle/truffle/api/debug/Breakpoint.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/Breakpoint.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/Breakpoint.java index d4436b32034d..49ff0986580b 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/Breakpoint.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/Breakpoint.java @@ -596,8 +596,13 @@ private void assignBinding(SourceSectionFilter locationFilter) { boolean attaching = breakpointBindingAttaching.getAndSet(true); if (!attaching) { EventBinding newBinding = null; + Debugger dbg = debugger; + if (dbg == null) { + // Disposed + return; + } try { - breakpointBinding = newBinding = debugger.getInstrumenter().attachExecutionEventFactory(locationFilter, new BreakpointNodeFactory()); + breakpointBinding = newBinding = dbg.getInstrumenter().attachExecutionEventFactory(locationFilter, new BreakpointNodeFactory()); } finally { breakpointBindingAttaching.set(false); synchronized (this) { From 84c12108432677eabc0eeaa7b3b1d86b56247ad2 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 8 Oct 2021 11:11:09 +0200 Subject: [PATCH 501/681] Delete legacy GC compatibility classes. --- .../svm/core/genscavenge/HeapPolicy.java | 63 ------------------- .../core/genscavenge/HeapPolicyOptions.java | 37 ----------- 2 files changed, 100 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapPolicy.java delete mode 100644 substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapPolicyOptions.java diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapPolicy.java deleted file mode 100644 index 6e6f97503b87..000000000000 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapPolicy.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013, 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.core.genscavenge; - -import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.word.UnsignedWord; - -/** - * Only for compatibility with legacy code, replaced by {@link CollectionPolicy} and - * {@link HeapParameters}. - */ -public final class HeapPolicy { - public static UnsignedWord getMaximumHeapSize() { - return GCImpl.getPolicy().getMaximumHeapSize(); - } - - public static UnsignedWord getMinimumHeapSize() { - return GCImpl.getPolicy().getMinimumHeapSize(); - } - - public static void setMaximumHeapSize(UnsignedWord value) { - HeapParameters.setMaximumHeapSize(value); - } - - public static void setMinimumHeapSize(UnsignedWord value) { - HeapParameters.setMinimumHeapSize(value); - } - - @Fold - public static UnsignedWord getAlignedHeapChunkSize() { - return HeapParameters.getAlignedHeapChunkSize(); - } - - @Fold - public static UnsignedWord getLargeArrayThreshold() { - return HeapParameters.getLargeArrayThreshold(); - } - - private HeapPolicy() { - } -} diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapPolicyOptions.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapPolicyOptions.java deleted file mode 100644 index 8801d8d1cf23..000000000000 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapPolicyOptions.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2017, 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.core.genscavenge; - -import com.oracle.svm.core.option.HostedOptionKey; - -/** - * Only for compatibility with legacy code, replaced by {@link HeapParameters.Options}. - */ -public final class HeapPolicyOptions { - public static final HostedOptionKey AlignedHeapChunkSize = HeapParameters.Options.AlignedHeapChunkSize; - - private HeapPolicyOptions() { - } -} From f5c444ddd75d0b2f301e190c3511858f027108dd Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Fri, 15 Oct 2021 21:06:32 +0000 Subject: [PATCH 502/681] Update truffleruby import. --- vm/mx.vm/suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 4b38cb8f6dfa..f96ef6286e63 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -57,7 +57,7 @@ }, { "name": "truffleruby", - "version": "b5454b64b6aa113ef2c091f50a4e1211e5ecdcea", + "version": "d4945821ec84d8b498a9a4bb30825f7087886b3d", "dynamic": True, "urls": [ {"url": "https://github.com/oracle/truffleruby.git", "kind": "git"}, From fce53c9d78a87543399fb7ed7357daa85d141224 Mon Sep 17 00:00:00 2001 From: Martin Entlicher Date: Sat, 16 Oct 2021 01:11:14 +0200 Subject: [PATCH 503/681] In TruffleLogger use null parameters instead of Object[]{null} when parameters are not specified. [GR-34556] --- .../api/test/polyglot/LoggingTest.java | 57 +++++++++++++++++++ .../com/oracle/truffle/api/TruffleLogger.java | 18 ++---- 2 files changed, 61 insertions(+), 14 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LoggingTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LoggingTest.java index 33c8e09915dd..088317f22518 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LoggingTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LoggingTest.java @@ -364,6 +364,63 @@ public void testLogRecordImmutable() { } } + @Test + public void testNoParameters() { + String message = "Test{0}"; + AbstractLoggingLanguage.action = new BiPredicate() { + @Override + public boolean test(final LoggingContext context, final TruffleLogger[] loggers) { + for (TruffleLogger logger : loggers) { + logger.log(Level.WARNING, message); + logger.log(Level.WARNING, () -> message); + logger.logp(Level.WARNING, "C", "M", message); + logger.logp(Level.WARNING, "C", "M", () -> message); + } + return false; + } + }; + final TestHandler handler = new TestHandler(); + try (Context ctx1 = newContextBuilder().logHandler(handler).build()) { + ctx1.eval(LoggingLanguageFirst.ID, ""); + int loggedCount = 0; + for (LogRecord r : handler.getRawLog()) { + loggedCount++; + Assert.assertEquals(message, r.getMessage()); + Assert.assertNull(r.getParameters()); + } + Assert.assertEquals(4 * AbstractLoggingLanguage.LOGGER_NAMES.length, loggedCount); + } + } + + @Test + public void testParametersOutput() { + String message = "Test{0} {1}"; + assertLoggerOutput(message, logger -> logger.log(Level.WARNING, message)); + assertLoggerOutput(message, logger -> logger.log(Level.WARNING, () -> message)); + assertLoggerOutput(message, logger -> logger.logp(Level.WARNING, "C", "M", message)); + assertLoggerOutput(message, logger -> logger.logp(Level.WARNING, "C", "M", () -> message)); + assertLoggerOutput("TestA {1}", logger -> logger.log(Level.WARNING, message, "A")); + assertLoggerOutput("TestA {1}", logger -> logger.logp(Level.WARNING, "C", "M", message, "A")); + assertLoggerOutput("TestA B", logger -> logger.log(Level.WARNING, message, new String[]{"A", "B"})); + assertLoggerOutput("TestA B", logger -> logger.logp(Level.WARNING, "C", "M", message, new String[]{"A", "B"})); + } + + private static void assertLoggerOutput(String expected, Consumer log) { + AbstractLoggingLanguage.action = new BiPredicate() { + @Override + public boolean test(final LoggingContext context, final TruffleLogger[] loggers) { + log.accept(loggers[0]); + return false; + } + }; + final ByteArrayOutputStream err = new ByteArrayOutputStream(); + try (Context ctx1 = Context.newBuilder().err(err).build()) { + ctx1.eval(LoggingLanguageFirst.ID, ""); + final String output = new String(err.toByteArray()); + Assert.assertTrue(output, output.indexOf(expected) > 0); + } + } + @Test public void testParametersPrimitive() { final Object[] expected = new Object[]{1, 1L, null, 1.1, 1.1d, "test", 't', null, true}; diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLogger.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLogger.java index 9bd8d98369c6..c75c40120644 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLogger.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLogger.java @@ -472,7 +472,7 @@ public void log(final Level level, final String message) { if (!isLoggable(level)) { return; } - doLog(level, message, null, null, (Object) null); + doLog(level, message, null, null, (Object[]) null); } /** @@ -490,7 +490,7 @@ public void log(final Level level, final Supplier messageSupplier) { if (!isLoggable(level)) { return; } - doLog(level, messageSupplier, null, null, (Object) null); + doLog(level, messageSupplier, null, null, null); } /** @@ -582,7 +582,7 @@ public void logp(final Level level, final String sourceClass, final String sourc if (!isLoggable(level)) { return; } - doLog(level, message, sourceClass, sourceMethod, (Object) null); + doLog(level, message, sourceClass, sourceMethod, (Object[]) null); } /** @@ -602,7 +602,7 @@ public void logp(final Level level, final String sourceClass, final String sourc if (!isLoggable(level)) { return; } - doLog(level, messageSupplier, sourceClass, sourceMethod, (Object) null); + doLog(level, messageSupplier, sourceClass, sourceMethod, null); } /** @@ -775,16 +775,6 @@ private void doLog( callHandlers(logRecord); } - @CompilerDirectives.TruffleBoundary - private void doLog( - final Level level, - final Supplier messageSupplier, - final String className, - final String methodName, - final Object param) { - doLog(level, messageSupplier.get(), className, methodName, new Object[]{param}); - } - @CompilerDirectives.TruffleBoundary private void doLog( final Level level, From 211ce3b70ceb09a79b2e8c1b6e63b9cb03494aa0 Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Sat, 16 Oct 2021 22:48:01 +0000 Subject: [PATCH 504/681] [GR-23997] Periodic update of the graal import (2021-10-15). PullRequest: js/2195 --- vm/mx.vm/suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index f96ef6286e63..49694328a713 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -39,7 +39,7 @@ "name": "graal-nodejs", "subdir": True, "dynamic": True, - "version": "70dbd4073a01b5482bdfb0075fa99ff8afd1954f", + "version": "c69f662f3e3cdce492999c328532cbf20c425dd1", "urls" : [ {"url" : "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, @@ -49,7 +49,7 @@ "name": "graal-js", "subdir": True, "dynamic": True, - "version": "70dbd4073a01b5482bdfb0075fa99ff8afd1954f", + "version": "c69f662f3e3cdce492999c328532cbf20c425dd1", "urls": [ {"url": "https://github.com/graalvm/graaljs.git", "kind" : "git"}, {"url": "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind": "binary"}, From aadd1cda98ec1dad01bfa6ca1802e5d1c68debb8 Mon Sep 17 00:00:00 2001 From: "cengfeng.lzy" Date: Wed, 11 Aug 2021 15:18:47 +0800 Subject: [PATCH 505/681] Parse pointsto options for standalone pointsto The standalone pointsto need to take the input options. The options and parsing should follow the same way as native image's hosted options. So we extract the commom part of SubstrateOptionsParser to a new project where both pointsto and svm can share. --- compiler/mx.compiler/suite.py | 2 +- substratevm/mx.substratevm/mx_substratevm.py | 1 + substratevm/mx.substratevm/suite.py | 47 +- .../graal/pointsto/util/AnalysisError.java | 12 + .../pointsto/util/PointsToOptionParser.java | 140 +++++ .../svm/common/option/CommonOptionParser.java | 522 ++++++++++++++++++ .../svm/common/option/CommonOptions.java | 39 ++ .../svm/common}/option/LocatableOption.java | 3 +- .../svm/common}/option/MultiOptionValue.java | 7 +- .../common/option/OptionParsingException.java | 35 ++ .../UnsupportedOptionClassException.java | 35 ++ .../com/oracle/svm/core/SubstrateOptions.java | 6 - .../com/oracle/svm/core/SubstrateUtil.java | 28 +- .../svm/core/option/HostedOptionKey.java | 2 + .../option/LocatableMultiOptionValue.java | 2 + .../svm/core/option/RuntimeOptionParser.java | 7 +- .../core/option/SubstrateOptionsParser.java | 500 ++--------------- .../com/oracle/svm/driver/NativeImage.java | 5 +- .../config/ConfigurationParserUtils.java | 2 +- .../svm/hosted/option/HostedOptionParser.java | 40 +- .../src/com/oracle/svm/util/StringUtil.java | 72 +++ 21 files changed, 970 insertions(+), 537 deletions(-) create mode 100644 substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/PointsToOptionParser.java create mode 100644 substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java create mode 100644 substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptions.java rename substratevm/src/{com.oracle.svm.core/src/com/oracle/svm/core => com.oracle.svm.common/src/com/oracle/svm/common}/option/LocatableOption.java (96%) rename substratevm/src/{com.oracle.svm.core/src/com/oracle/svm/core => com.oracle.svm.common/src/com/oracle/svm/common}/option/MultiOptionValue.java (84%) create mode 100644 substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/OptionParsingException.java create mode 100644 substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/UnsupportedOptionClassException.java create mode 100644 substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/StringUtil.java diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index 44c8551c3b11..c528d0471775 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -2168,7 +2168,7 @@ "jdk.unsupported" # sun.misc.Unsafe ], "exports" : [ - "* to com.oracle.graal.graal_enterprise,org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.builder,org.graalvm.nativeimage.llvm,com.oracle.svm.svm_enterprise", + "* to com.oracle.graal.graal_enterprise,org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.builder,org.graalvm.nativeimage.llvm,com.oracle.svm.svm_enterprise,org.graalvm.nativeimage.base", "org.graalvm.compiler.core.common to jdk.internal.vm.compiler.management,org.graalvm.nativeimage.agent.tracing", "org.graalvm.compiler.debug to jdk.internal.vm.compiler.management,org.graalvm.nativeimage.objectfile", "org.graalvm.compiler.hotspot to jdk.internal.vm.compiler.management", diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 2d468388df9e..061b9a99ad02 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -769,6 +769,7 @@ def native_image_context_run(func, func_args=None, config=None, build_if_missing 'substratevm:SVM', 'substratevm:OBJECTFILE', 'substratevm:POINTSTO', + 'substratevm:NATIVE_IMAGE_BASE', ], support_distributions=['substratevm:SVM_GRAALVM_SUPPORT'], stability="earlyadopter", diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index c1b7e79a15bf..f8b4f7afa75e 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -147,6 +147,19 @@ "checkstyle": "com.oracle.svm.core", "workingSets": "SVM", }, + "com.oracle.svm.common": { + "subDir": "src", + "sourceDirs": ["src"], + "dependencies": [ + "com.oracle.svm.util" + ], + "javaCompliance": "8+", + "annotationProcessors": [ + "compiler:GRAAL_PROCESSOR", + ], + "checkstyle": "com.oracle.svm.core", + "workingSets": "SVM", + }, "com.oracle.svm.util.jdk11": { "subDir": "src", "sourceDirs": ["src"], @@ -174,7 +187,7 @@ "headers", ], "dependencies": [ - "com.oracle.svm.util", + "com.oracle.svm.common", ], "javaCompliance": "8+", "checkstyleVersion" : "8.36.1", @@ -387,7 +400,7 @@ "subDir": "src", "sourceDirs": ["src"], "dependencies": [ - "com.oracle.svm.util", + "com.oracle.svm.common", ], "checkstyle": "com.oracle.graal.pointsto", "javaCompliance": "8+", @@ -1106,6 +1119,7 @@ "OBJECTFILE", "POINTSTO", "compiler:GRAAL", + "NATIVE_IMAGE_BASE", ], "moduleInfo" : { "name" : "org.graalvm.nativeimage.builder", @@ -1119,7 +1133,7 @@ "com.oracle.svm.hosted to java.base", "com.oracle.svm.hosted.agent to java.instrument", "com.oracle.svm.truffle.api to org.graalvm.truffle", - "* to jdk.internal.vm.compiler,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.configure,org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.junitsupport,org.graalvm.nativeimage.llvm,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.agent.diagnostics,com.oracle.svm.svm_enterprise", + "* to org.graalvm.nativeimage.base,jdk.internal.vm.compiler,org.graalvm.nativeimage.driver,org.graalvm.nativeimage.configure,org.graalvm.nativeimage.librarysupport,org.graalvm.nativeimage.junitsupport,org.graalvm.nativeimage.llvm,org.graalvm.nativeimage.agent.jvmtibase,org.graalvm.nativeimage.agent.tracing,org.graalvm.nativeimage.agent.diagnostics,com.oracle.svm.svm_enterprise", ], "opens" : [ "com.oracle.svm.core to jdk.internal.vm.compiler", @@ -1254,6 +1268,9 @@ "static junit", "static hamcrest", ], + "exports" : [ + "* to org.graalvm.nativeimage.base,org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.builder", + ], }, }, @@ -1421,6 +1438,26 @@ }, }, + "NATIVE_IMAGE_BASE": { + "subDir": "src", + "description" : "Native Image base that can be shared by native image building and pointsto.", + "dependencies": [ + "com.oracle.svm.common", + "com.oracle.svm.util", + ], + "distDependencies": [ + "compiler:GRAAL", + ], + "exclude": [ + ], + "moduleInfo" : { + "name" : "org.graalvm.nativeimage.base", + "exports" : [ + "com.oracle.svm.util", + "com.oracle.svm.common.option", + ], + } + }, "POINTSTO": { "subDir": "src", @@ -1431,13 +1468,13 @@ ], "distDependencies": [ "compiler:GRAAL", + "NATIVE_IMAGE_BASE", ], "exclude": [ ], "moduleInfo" : { "name" : "org.graalvm.nativeimage.pointsto", "exports" : [ - "com.oracle.svm.util", "com.oracle.graal.pointsto", "com.oracle.graal.pointsto.api", "com.oracle.graal.pointsto.reports", @@ -1614,7 +1651,7 @@ "moduleInfo" : { "name" : "org.graalvm.nativeimage.llvm", "exports" : [ - "* to org.graalvm.nativeimage.builder", + "* to org.graalvm.nativeimage.builder,org.graalvm.nativeimage.base", ], }, "maven" : False, diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/AnalysisError.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/AnalysisError.java index b9f58533b894..8d59e33cd5a3 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/AnalysisError.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/AnalysisError.java @@ -125,6 +125,14 @@ private static String message(PointsToAnalysis bb, TypeFlow objectFlow, Bytec } } + public static class InterruptAnalysis extends AnalysisError { + private static final long serialVersionUID = 7126612141948542452L; + + InterruptAnalysis(String msg) { + super(msg); + } + } + public static TypeNotFoundError typeNotFound(ResolvedJavaType type) { throw new TypeNotFoundError(type); } @@ -166,4 +174,8 @@ public static void guarantee(boolean condition, String format, Object... args) { // Checkstyle: resume } } + + public static RuntimeException interruptAnalysis(String msg) { + throw new InterruptAnalysis(msg); + } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/PointsToOptionParser.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/PointsToOptionParser.java new file mode 100644 index 000000000000..b2a93a85768d --- /dev/null +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/PointsToOptionParser.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Alibaba Group Holding Limited. 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.util; + +import com.oracle.svm.common.option.CommonOptionParser; +import com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat; +import com.oracle.svm.common.option.CommonOptionParser.OptionParseResult; +import com.oracle.svm.common.option.UnsupportedOptionClassException; +import org.graalvm.collections.EconomicMap; +import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.function.Predicate; + +import static com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat.PLUS_MINUS; + +public final class PointsToOptionParser { + + private static PointsToOptionParser instance = new PointsToOptionParser(); + + private OptionValues optionValues = null; + private EconomicMap, Object> analysisValues = OptionValues.newOptionMap(); + private EconomicMap allAnalysisOptions = EconomicMap.create(); + + public static PointsToOptionParser getInstance() { + return instance; + } + + @SuppressWarnings("unchecked") + private PointsToOptionParser() { + ClassLoader appClassLoader = PointsToOptionParser.class.getClassLoader(); + CommonOptionParser.collectOptions(ServiceLoader.load(OptionDescriptors.class, appClassLoader), descriptor -> { + String name = descriptor.getName(); + if (descriptor.getOptionKey() instanceof OptionKey) { + OptionDescriptor existing = allAnalysisOptions.put(name, descriptor); + if (existing != null) { + AnalysisError.shouldNotReachHere("Option name \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + descriptor.getLocation()); + } + } + }); + } + + public void setOptionValue(OptionKey optionKey, Object value) { + if (optionValues == null) { + parse(new String[0]); + } + optionKey.update((EconomicMap, Object>) optionValues.getMap(), value); + } + + public OptionValues parse(String[] args) { + List remainingArgs = new ArrayList<>(); + Set errors = new HashSet<>(); + for (String arg : args) { + boolean isAnalysisOption = false; + isAnalysisOption |= parseOption(CommonOptionParser.HOSTED_OPTION_PREFIX, allAnalysisOptions, analysisValues, PLUS_MINUS, errors, arg, System.out); + if (!isAnalysisOption) { + remainingArgs.add(arg); + } + } + optionValues = new OptionValues(analysisValues); + if (!remainingArgs.isEmpty()) { + AnalysisError.interruptAnalysis(String.format("Unknown options: %s", Arrays.toString(remainingArgs.toArray(new String[0])))); + } + if (!errors.isEmpty()) { + StringBuilder errMsg = new StringBuilder("Option format error:\n"); + for (String err : errors) { + errMsg.append(err).append("\n"); + } + AnalysisError.interruptAnalysis(errMsg.toString()); + } + return optionValues; + } + + private static boolean parseOption(String optionPrefix, EconomicMap options, EconomicMap, Object> valuesMap, + BooleanOptionFormat booleanOptionFormat, Set errors, String arg, PrintStream out) { + if (!arg.startsWith(optionPrefix)) { + return false; + } + try { + Predicate> optionKeyPredicate = optionKey -> { + Class clazz = optionKey.getClass(); + // All classes from com.oracle.graal.pointsto.api.PointstoOptions are taken as non-hosted options. + if (clazz.getName().startsWith("com.oracle.graal.pointsto.api.PointstoOptions")) { + return false; + } + if (!clazz.equals(OptionKey.class) && OptionKey.class.isAssignableFrom(clazz)) { + return true; + } else { + return false; + } + }; + OptionParseResult optionParseResult = CommonOptionParser.parseOption(options, optionKeyPredicate, arg.substring(optionPrefix.length()), valuesMap, + optionPrefix, booleanOptionFormat); + if (optionParseResult.printFlags() || optionParseResult.printFlagsWithExtraHelp()) { + CommonOptionParser.printFlags(d -> optionParseResult.matchesFlags(d, () -> true), options, optionPrefix, out, optionParseResult.printFlagsWithExtraHelp()); + System.out.println("Abort analysis due to print flags are requested"); + System.exit(1); + } + if (!optionParseResult.isValid()) { + errors.add(optionParseResult.getError()); + } + } catch (UnsupportedOptionClassException e) { + AnalysisError.shouldNotReachHere(e); + } + return true; + } +} diff --git a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java new file mode 100644 index 000000000000..823a67bee2c9 --- /dev/null +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Alibaba Group Holding Limited. 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.common.option; + +// Checkstyle: allow reflection + +import com.oracle.svm.util.ClassUtil; +import com.oracle.svm.util.StringUtil; +import org.graalvm.collections.EconomicMap; +import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.options.OptionsParser; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class CommonOptionParser { + public static final String HOSTED_OPTION_PREFIX = "-H:"; + public static final String RUNTIME_OPTION_PREFIX = "-R:"; + + public static final int PRINT_OPTION_INDENTATION = 2; + public static final int PRINT_OPTION_WIDTH = 45; + public static final int PRINT_OPTION_WRAP_WIDTH = 120; + + /** + * The result of {@link CommonOptionParser#parseOption}. + */ + public static final class OptionParseResult { + private final EnumSet printFlags; + private final Set optionNameFilter; + private final String error; + private final OptionKey optionKey; + private static final String EXTRA_HELP_OPTIONS_WILDCARD = "*"; + + OptionParseResult(EnumSet printFlags, String error, Set optionNameFilter, OptionKey optionKey) { + this.printFlags = printFlags; + this.error = error; + this.optionNameFilter = optionNameFilter; + this.optionKey = optionKey; + } + + private OptionParseResult(EnumSet printFlags, String error, OptionKey optionKey) { + this(printFlags, error, new HashSet<>(), optionKey); + } + + static OptionParseResult error(String message) { + return new OptionParseResult(EnumSet.noneOf(OptionType.class), message, null); + } + + static OptionParseResult correct(OptionKey optionKey) { + return new OptionParseResult(EnumSet.noneOf(OptionType.class), null, optionKey); + } + + static OptionParseResult printFlags(EnumSet selectedOptionTypes) { + return new OptionParseResult(selectedOptionTypes, null, null); + } + + static OptionParseResult printFlagsWithExtraHelp(Set optionNameFilter) { + Set optionNames = optionNameFilter; + if (optionNames.contains(EXTRA_HELP_OPTIONS_WILDCARD)) { + optionNames = new HashSet<>(); + optionNames.add(EXTRA_HELP_OPTIONS_WILDCARD); + } + return new OptionParseResult(EnumSet.noneOf(OptionType.class), null, optionNames, null); + } + + public boolean printFlags() { + return !printFlags.isEmpty(); + } + + public boolean printFlagsWithExtraHelp() { + return !optionNameFilter.isEmpty(); + } + + public boolean isValid() { + boolean result = optionKey != null; + assert result == (printFlags.isEmpty() && optionNameFilter.isEmpty() && error == null); + return result; + } + + public String getError() { + return error; + } + + public OptionKey getOptionKey() { + return optionKey; + } + + public boolean matchesFlags(OptionDescriptor d, BooleanSupplier svmOption) { + if (!printFlags.isEmpty()) { + boolean showAll = printFlags.equals(EnumSet.allOf(OptionType.class)); + return showAll || svmOption.getAsBoolean() && printFlags.contains(d.getOptionType()); + } + if (!optionNameFilter.isEmpty()) { + if (optionNameFilter.contains(EXTRA_HELP_OPTIONS_WILDCARD) && !d.getExtraHelp().isEmpty()) { + return true; + } + return optionNameFilter.contains(d.getName()); + } + return false; + } + } + + /** + * Constants denoting supported boolean option formats. + */ + public enum BooleanOptionFormat { + NAME_VALUE("="), + PLUS_MINUS("+/-"); + + BooleanOptionFormat(String help) { + this.help = help; + } + + private final String help; + + @Override + public String toString() { + return help; + } + } + + public static void collectOptions(ServiceLoader optionDescriptors, Consumer optionDescriptorConsumer) { + for (OptionDescriptors optionDescriptor : optionDescriptors) { + for (OptionDescriptor descriptor : optionDescriptor) { + optionDescriptorConsumer.accept(descriptor); + } + } + } + + public static OptionParseResult parseOption(EconomicMap options, Predicate> isHosted, String option, EconomicMap, Object> valuesMap, + String optionPrefix, BooleanOptionFormat booleanOptionFormat) throws UnsupportedOptionClassException { + if (option.length() == 0) { + return OptionParseResult.error("Option name must be specified"); + } + + String optionName; + Object value = null; + String valueString = null; + + char first = option.charAt(0); + int eqIndex = option.indexOf('='); + if (first == '+' || first == '-') { + if (eqIndex != -1) { + return OptionParseResult.error("Cannot mix +/- with = format: '" + optionPrefix + option + "'"); + } + optionName = option.substring(1); + if (booleanOptionFormat == BooleanOptionFormat.NAME_VALUE) { + return OptionParseResult.error("Option " + LocatableOption.from(optionName) + " must use = format, not +/- prefix"); + } + value = (first == '+'); + } else { + if (eqIndex == -1) { + optionName = option; + valueString = null; + } else { + optionName = option.substring(0, eqIndex); + valueString = option.substring(eqIndex + 1); + } + } + + LocatableOption current = LocatableOption.from(optionName); + OptionDescriptor desc = options.get(current.name); + if (desc == null && value != null) { + if (eqIndex != -1) { + optionName = option.substring(1, eqIndex); + current = LocatableOption.from(optionName); + desc = options.get(current.name); + } + } + + optionName = current.name; + + if (desc == null) { + List matches = new ArrayList<>(); + OptionsParser.collectFuzzyMatches(options.getValues(), optionName, matches); + StringBuilder msg = new StringBuilder("Could not find option ").append(current); + if (!matches.isEmpty()) { + msg.append(". Did you mean one of these:"); + for (OptionDescriptor match : matches) { + msg.append(' ').append(match.getName()); + } + } + msg.append(". Use ").append(optionPrefix).append(CommonOptions.PrintFlags.getName()).append("= to list all available options."); + return OptionParseResult.error(msg.toString()); + } + + OptionKey optionKey = desc.getOptionKey(); + boolean hostedOption = isHosted.test(optionKey); + Class optionValueType = getMultiOptionValueElementType(optionKey); + Class optionType = hostedOption && optionValueType != null ? optionValueType : desc.getOptionValueType(); + + if (value == null) { + if (optionType == Boolean.class && booleanOptionFormat == BooleanOptionFormat.PLUS_MINUS) { + return OptionParseResult.error("Boolean option " + current + " must have +/- prefix"); + } + if (valueString == null) { + return OptionParseResult.error("Missing value for option " + current); + } + try { + value = parseValue(optionType, current, valueString); + if (value instanceof OptionParseResult) { + return (OptionParseResult) value; + } + } catch (NumberFormatException ex) { + return OptionParseResult.error("Invalid value for option " + current + ": '" + valueString + "' is not a valid number"); + } + } else { + if (optionType != Boolean.class) { + return OptionParseResult.error("Non-boolean option " + current + " can not use +/- prefix. Use '" + current.name + "=' format"); + } + } + + optionKey.update(valuesMap, hostedOption ? LocatableOption.value(value, current.origin) : value); + + if (CommonOptions.PrintFlags.getName().equals(optionName)) { + String optionValue = (String) value; + EnumSet selectedOptionTypes; + if (optionValue.isEmpty()) { + selectedOptionTypes = EnumSet.allOf(OptionType.class); + } else { + selectedOptionTypes = EnumSet.noneOf(OptionType.class); + String enumString = null; + try { + String[] enumStrings = StringUtil.split(optionValue, ","); + + for (String string : enumStrings) { + enumString = string; + selectedOptionTypes.add(OptionType.valueOf(enumString)); + } + } catch (IllegalArgumentException e) { + StringBuilder sb = new StringBuilder(); + boolean firstValue = true; + for (OptionType ot : OptionType.values()) { + if (firstValue) { + firstValue = false; + } else { + sb.append(", "); + } + sb.append(ot.name()); + } + String possibleValues = sb.toString(); + return OptionParseResult.error("Invalid value for option " + current + ". '" + enumString + "' is not one of: " + possibleValues); + } + } + return OptionParseResult.printFlags(selectedOptionTypes); + } + + if (CommonOptions.PrintFlagsWithExtraHelp.getName().equals(optionName)) { + String optionValue = (String) value; + String[] optionNames = StringUtil.split(optionValue, ","); + HashSet selectedOptionNames = new HashSet<>(Arrays.asList(optionNames)); + return OptionParseResult.printFlagsWithExtraHelp(selectedOptionNames); + } + return OptionParseResult.correct(optionKey); + } + + @SuppressWarnings("unchecked") + static Object parseValue(Class optionType, LocatableOption option, String valueString) throws NumberFormatException, UnsupportedOptionClassException { + Object value; + if (optionType == Integer.class) { + long longValue = parseLong(valueString); + if ((int) longValue != longValue) { + return OptionParseResult.error("Wrong value for option " + option + ": '" + valueString + "' is not a valid number"); + } + value = (int) longValue; + } else if (optionType == Long.class) { + value = parseLong(valueString); + } else if (optionType == String.class) { + value = valueString; + } else if (optionType == Double.class) { + value = parseDouble(valueString); + } else if (optionType == Boolean.class) { + if (valueString.equals("true")) { + value = true; + } else if (valueString.equals("false")) { + value = false; + } else { + return OptionParseResult.error("Boolean option " + option + " must have value 'true' or 'false'"); + } + } else if (optionType.isEnum()) { + value = Enum.valueOf(optionType.asSubclass(Enum.class), valueString); + } else { + throw new UnsupportedOptionClassException(option + " uses unsupported option value class: " + ClassUtil.getUnqualifiedName(optionType)); + } + return value; + } + + private static Class getMultiOptionValueElementType(OptionKey optionKey) { + Object defaultValue = optionKey.getDefaultValue(); + if (defaultValue instanceof MultiOptionValue) { + return ((MultiOptionValue) defaultValue).getValueType(); + } + return null; + } + + public static long parseLong(String v) { + String valueString = v.trim().toLowerCase(); + long scale = 1; + if (valueString.endsWith("k")) { + scale = 1024L; + } else if (valueString.endsWith("m")) { + scale = 1024L * 1024L; + } else if (valueString.endsWith("g")) { + scale = 1024L * 1024L * 1024L; + } else if (valueString.endsWith("t")) { + scale = 1024L * 1024L * 1024L * 1024L; + } + + if (scale != 1) { + /* Remove trailing scale character. */ + valueString = valueString.substring(0, valueString.length() - 1); + } + + return Long.parseLong(valueString) * scale; + } + + /** + * Parses the provide string to a double number, avoiding the JDK dependencies (which pull in a + * lot of classes, including the regular expression library). Only simple numbers are supported, + * without fancy exponent styles. + */ + public static double parseDouble(String v) { + String valueString = v.trim(); + + int dotPos = valueString.indexOf('.'); + if (dotPos == -1) { + return parseLong(valueString); + } + + String beforeDot = valueString.substring(0, dotPos); + String afterDot = valueString.substring(dotPos + 1); + + double sign = 1; + if (beforeDot.startsWith("-")) { + sign = -1; + beforeDot = beforeDot.substring(1); + } else if (beforeDot.startsWith("+")) { + beforeDot = beforeDot.substring(1); + } + + if (beforeDot.startsWith("-") || beforeDot.startsWith("+") || afterDot.startsWith("-") || afterDot.startsWith("+") || + (beforeDot.length() == 0 && afterDot.length() == 0)) { + throw new NumberFormatException(v); + } + + double integral = 0; + if (beforeDot.length() > 0) { + integral = Long.parseLong(beforeDot); + } + + double fraction = 0; + if (afterDot.length() > 0) { + fraction = Long.parseLong(afterDot) * Math.pow(10, -afterDot.length()); + } + + return sign * (integral + fraction); + } + + private static String spaces(int length) { + return new String(new char[length]).replace('\0', ' '); + } + + private static String wrap(String s, int width) { + StringBuilder sb = new StringBuilder(s); + int cursor = 0; + while (cursor + width < sb.length()) { + int i = sb.lastIndexOf(" ", cursor + width); + if (i == -1 || i < cursor) { + i = sb.indexOf(" ", cursor + width); + } + if (i != -1) { + sb.replace(i, i + 1, System.lineSeparator()); + cursor = i; + } else { + break; + } + } + return sb.toString(); + } + + private static void printOption(PrintStream out, String option, String description, int wrap) { + printOption(out::println, option, description, PRINT_OPTION_INDENTATION, PRINT_OPTION_WIDTH, wrap); + } + + public static void printOption(Consumer println, String option, String description, int indentation, int optionWidth, int wrapWidth) { + String indent = spaces(indentation); + String desc = description != null ? description : ""; + desc = wrapWidth > 0 ? wrap(desc, wrapWidth) : desc; + String nl = System.lineSeparator(); + String[] descLines = StringUtil.split(desc, nl); + if (option.length() >= optionWidth && description != null) { + println.accept(indent + option + nl + indent + spaces(optionWidth) + descLines[0]); + } else { + println.accept(indent + option + spaces(optionWidth - option.length()) + descLines[0]); + } + for (int i = 1; i < descLines.length; i++) { + println.accept(indent + spaces(optionWidth) + descLines[i]); + } + } + + public static void printFlags(Predicate filter, EconomicMap options, String prefix, PrintStream out, boolean verbose) { + List sortedDescriptors = new ArrayList<>(); + for (OptionDescriptor option : options.getValues()) { + if (filter.test(option)) { + sortedDescriptors.add(option); + } + } + sortedDescriptors.sort(Comparator.comparing(OptionDescriptor::getName)); + + for (OptionDescriptor descriptor : sortedDescriptors) { + String helpMsg = verbose && !descriptor.getExtraHelp().isEmpty() ? "" : descriptor.getHelp(); + int helpLen = helpMsg.length(); + if (helpLen > 0 && helpMsg.charAt(helpLen - 1) != '.') { + helpMsg += '.'; + } + boolean stringifiedArrayValue = false; + Object defaultValue = descriptor.getOptionKey().getDefaultValue(); + if (defaultValue != null && defaultValue.getClass().isArray()) { + Object[] defaultValues = (Object[]) defaultValue; + if (defaultValues.length == 1) { + defaultValue = defaultValues[0]; + } else { + List stringList = new ArrayList<>(); + String optionPrefix = prefix + descriptor.getName() + "="; + for (Object rawValue : defaultValues) { + String value; + if (rawValue instanceof String) { + value = '"' + String.valueOf(rawValue) + '"'; + } else { + value = String.valueOf(rawValue); + } + stringList.add(optionPrefix + value); + } + if (helpLen != 0) { + helpMsg += ' '; + } + helpMsg += "Default: "; + if (stringList.isEmpty()) { + helpMsg += "None"; + } else { + helpMsg += String.join(" ", stringList); + } + stringifiedArrayValue = true; + } + } + String verboseHelp = ""; + if (verbose) { + verboseHelp = System.lineSeparator() + descriptor.getHelp() + System.lineSeparator() + String.join(System.lineSeparator(), descriptor.getExtraHelp()); + } else if (!descriptor.getExtraHelp().isEmpty()) { + verboseHelp = " [Extra help available]"; + } + int wrapWidth = verbose ? 0 : PRINT_OPTION_WRAP_WIDTH; + if (descriptor.getOptionValueType() == Boolean.class) { + Boolean val = (Boolean) defaultValue; + if (helpLen != 0) { + helpMsg += ' '; + } + if (val != null) { + if (val) { + helpMsg += "Default: + (enabled)."; + } else { + helpMsg += "Default: - (disabled)."; + } + } + printOption(out, prefix + "\u00b1" + descriptor.getName(), helpMsg + verboseHelp, wrapWidth); + } else { + if (defaultValue == null) { + if (helpLen != 0) { + helpMsg += ' '; + } + helpMsg += "Default: None"; + } + helpMsg += verboseHelp; + if (stringifiedArrayValue || defaultValue == null) { + printOption(out, prefix + descriptor.getName() + "=...", helpMsg, wrapWidth); + } else { + if (defaultValue instanceof String) { + defaultValue = '"' + String.valueOf(defaultValue) + '"'; + } + printOption(out, prefix + descriptor.getName() + "=" + defaultValue, helpMsg, wrapWidth); + } + } + } + } +} diff --git a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptions.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptions.java new file mode 100644 index 000000000000..6b2f9e88b5d6 --- /dev/null +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptions.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Alibaba Group Holding Limited. 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.common.option; + +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; + +public class CommonOptions { + + @Option(help = "Show available options based on comma-separated option-types (allowed categories: User, Expert, Debug).")// + public static final OptionKey PrintFlags = new OptionKey<>(null); + + @Option(help = "Print extra help, if available, based on comma-separated option names. Pass * to show all options that contain extra help.")// + public static final OptionKey PrintFlagsWithExtraHelp = new OptionKey<>(null); +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/LocatableOption.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/LocatableOption.java similarity index 96% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/LocatableOption.java rename to substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/LocatableOption.java index d675521de43d..62927c9a3a31 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/LocatableOption.java +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/LocatableOption.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Alibaba Group Holding Limited. 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 @@ -22,7 +23,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.option; +package com.oracle.svm.common.option; public final class LocatableOption { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/MultiOptionValue.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/MultiOptionValue.java similarity index 84% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/MultiOptionValue.java rename to substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/MultiOptionValue.java index ad6207f9036e..0f678439903c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/MultiOptionValue.java +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/MultiOptionValue.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Alibaba Group Holding Limited. 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 @@ -22,11 +23,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.option; +package com.oracle.svm.common.option; import java.util.List; -interface MultiOptionValue { +public interface MultiOptionValue { Class getValueType(); @@ -34,7 +35,7 @@ interface MultiOptionValue { * @return a list of option values, one for each place where the option is used * @implSpec Note that it DOES NOT perform any splitting of string values based on a delimiter. * If you want to perform this split, use a utility - * {@link OptionUtils#flatten(String, LocatableMultiOptionValue.Strings)} + * {@link com.oracle.svm.core.option.OptionUtils#flatten(String, com.oracle.svm.core.option.LocatableMultiOptionValue.Strings)} */ List values(); diff --git a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/OptionParsingException.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/OptionParsingException.java new file mode 100644 index 000000000000..87e2d281bdd8 --- /dev/null +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/OptionParsingException.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Alibaba Group Holding Limited. 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.common.option; + +public class OptionParsingException extends Exception { + private static final long serialVersionUID = 1413275434484971842L; + + public OptionParsingException(Exception e) { + super(e); + } +} diff --git a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/UnsupportedOptionClassException.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/UnsupportedOptionClassException.java new file mode 100644 index 000000000000..c92195df9443 --- /dev/null +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/UnsupportedOptionClassException.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Alibaba Group Holding Limited. 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.common.option; + +public class UnsupportedOptionClassException extends Exception { + private static final long serialVersionUID = -3105370072461246590L; + + public UnsupportedOptionClassException(String msg) { + super(msg); + } +} 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 399eb506bfe0..0ceb845846fa 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 @@ -125,12 +125,6 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o private static ValueUpdateHandler optimizeValueUpdateHandler; private static ValueUpdateHandler debugInfoValueUpdateHandler = SubstrateOptions::defaultDebugInfoValueUpdateHandler; - @Option(help = "Show available options based on comma-separated option-types (allowed categories: User, Expert, Debug).")// - public static final OptionKey PrintFlags = new OptionKey<>(null); - - @Option(help = "Print extra help, if available, based on comma-separated option names. Pass * to show all options that contain extra help.")// - public static final OptionKey PrintFlagsWithExtraHelp = new OptionKey<>(null); - @Option(help = "Control native-image code optimizations: 0 - no optimizations, 1 - basic optimizations, 2 - aggressive optimizations.", type = OptionType.User)// public static final HostedOptionKey Optimize = new HostedOptionKey(2) { @Override diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateUtil.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateUtil.java index 0cb5e35fdeb1..fc52b1c7a2d7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateUtil.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateUtil.java @@ -34,11 +34,11 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.oracle.svm.util.StringUtil; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.java.LambdaUtils; import org.graalvm.compiler.nodes.BreakpointNode; @@ -270,31 +270,7 @@ public static String[] split(String value, String separator) { * regular expression. This avoids making regular expression code reachable. */ public static String[] split(String value, String separator, int limit) { - int offset = 0; - int next; - ArrayList list = null; - while ((next = value.indexOf(separator, offset)) != -1) { - if (list == null) { - list = new ArrayList<>(); - } - boolean limited = limit > 0; - if (!limited || list.size() < limit - 1) { - list.add(value.substring(offset, next)); - offset = next + separator.length(); - } else { - break; - } - } - - if (offset == 0) { - /* No match found. */ - return new String[]{value}; - } - - /* Add remaining segment. */ - list.add(value.substring(offset)); - - return list.toArray(new String[list.size()]); + return StringUtil.split(value, separator, limit); } public static String toHex(byte[] data) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/HostedOptionKey.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/HostedOptionKey.java index 70c23993eec9..4816367709d2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/HostedOptionKey.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/HostedOptionKey.java @@ -24,6 +24,8 @@ */ package com.oracle.svm.core.option; +import com.oracle.svm.common.option.LocatableOption; +import com.oracle.svm.common.option.MultiOptionValue; import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.options.Option; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/LocatableMultiOptionValue.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/LocatableMultiOptionValue.java index bf43136b21d2..176087b6115f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/LocatableMultiOptionValue.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/LocatableMultiOptionValue.java @@ -29,6 +29,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.oracle.svm.common.option.LocatableOption; +import com.oracle.svm.common.option.MultiOptionValue; import org.graalvm.collections.Pair; import com.oracle.svm.core.util.VMError; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/RuntimeOptionParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/RuntimeOptionParser.java index ff5a104b6fe2..9dc6007070c4 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/RuntimeOptionParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/RuntimeOptionParser.java @@ -41,8 +41,8 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.log.Log; -import com.oracle.svm.core.option.SubstrateOptionsParser.BooleanOptionFormat; -import com.oracle.svm.core.option.SubstrateOptionsParser.OptionParseResult; +import com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat; +import com.oracle.svm.common.option.CommonOptionParser.OptionParseResult; import com.oracle.svm.core.properties.RuntimePropertyParser; import com.oracle.svm.core.util.ImageHeapMap; @@ -163,7 +163,8 @@ private void parseOptionAtRuntime(String arg, String optionPrefix, BooleanOption Predicate> isHosted = optionKey -> false; OptionParseResult parseResult = SubstrateOptionsParser.parseOption(options, isHosted, arg.substring(optionPrefix.length()), values, optionPrefix, booleanOptionFormat); if (parseResult.printFlags() || parseResult.printFlagsWithExtraHelp()) { - SubstrateOptionsParser.printFlags(parseResult::matchesFlagsRuntime, options, optionPrefix, Log.logStream(), parseResult.printFlagsWithExtraHelp()); + SubstrateOptionsParser.printFlags(d -> parseResult.matchesFlags(d, () -> d.getOptionKey() instanceof RuntimeOptionKey), + options, optionPrefix, Log.logStream(), parseResult.printFlagsWithExtraHelp()); System.exit(0); } if (!parseResult.isValid()) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java index f049bd43c7e9..81436ccd784c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java @@ -26,31 +26,28 @@ // Checkstyle: allow reflection +import com.oracle.svm.core.util.InterruptImageBuilding; +import com.oracle.svm.core.util.VMError; +import com.oracle.svm.common.option.CommonOptionParser; +import com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat; +import com.oracle.svm.common.option.CommonOptionParser.OptionParseResult; +import com.oracle.svm.common.option.UnsupportedOptionClassException; +import org.graalvm.collections.EconomicMap; +import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + import java.io.PrintStream; import java.lang.reflect.Field; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; +import java.util.ServiceLoader; import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; -import org.graalvm.collections.EconomicMap; -import org.graalvm.compiler.options.OptionDescriptor; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionsParser; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - -import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.SubstrateUtil; -import com.oracle.svm.core.util.InterruptImageBuilding; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.util.ClassUtil; +import static com.oracle.svm.core.util.VMError.shouldNotReachHere; /** * This class contains methods for parsing options and matching them against @@ -58,283 +55,17 @@ */ public class SubstrateOptionsParser { - public static final String HOSTED_OPTION_PREFIX = "-H:"; - public static final String RUNTIME_OPTION_PREFIX = "-R:"; - public static final int PRINT_OPTION_INDENTATION = 2; - public static final int PRINT_OPTION_WIDTH = 45; - public static final int PRINT_OPTION_WRAP_WIDTH = 120; - - /** - * The result of {@link SubstrateOptionsParser#parseOption}. - */ - static final class OptionParseResult { - private final EnumSet printFlags; - private final Set optionNameFilter; - private final String error; - private final OptionKey optionKey; - private static final String EXTRA_HELP_OPTIONS_WILDCARD = "*"; - - private OptionParseResult(EnumSet printFlags, String error, Set optionNameFilter, OptionKey optionKey) { - this.printFlags = printFlags; - this.error = error; - this.optionNameFilter = optionNameFilter; - this.optionKey = optionKey; - } - - private OptionParseResult(EnumSet printFlags, String error, OptionKey optionKey) { - this(printFlags, error, new HashSet<>(), optionKey); - } - - static OptionParseResult error(String message) { - return new OptionParseResult(EnumSet.noneOf(OptionType.class), message, null); - } - - static OptionParseResult correct(OptionKey optionKey) { - return new OptionParseResult(EnumSet.noneOf(OptionType.class), null, optionKey); - } - - static OptionParseResult printFlags(EnumSet selectedOptionTypes) { - return new OptionParseResult(selectedOptionTypes, null, null); - } - - static OptionParseResult printFlagsWithExtraHelp(Set optionNameFilter) { - Set optionNames = optionNameFilter; - if (optionNames.contains(EXTRA_HELP_OPTIONS_WILDCARD)) { - optionNames = new HashSet<>(); - optionNames.add(EXTRA_HELP_OPTIONS_WILDCARD); - } - return new OptionParseResult(EnumSet.noneOf(OptionType.class), null, optionNames, null); - } - - boolean printFlags() { - return !printFlags.isEmpty(); - } - - boolean printFlagsWithExtraHelp() { - return !optionNameFilter.isEmpty(); - } - - public boolean isValid() { - boolean result = optionKey != null; - assert result == (printFlags.isEmpty() && optionNameFilter.isEmpty() && error == null); - return result; - } - - public String getError() { - return error; - } - - public OptionKey getOptionKey() { - return optionKey; - } - - private boolean matchesFlags(OptionDescriptor d, boolean svmOption) { - if (!printFlags.isEmpty()) { - boolean showAll = printFlags.equals(EnumSet.allOf(OptionType.class)); - return showAll || svmOption && printFlags.contains(d.getOptionType()); - } - if (!optionNameFilter.isEmpty()) { - if (optionNameFilter.contains(EXTRA_HELP_OPTIONS_WILDCARD) && !d.getExtraHelp().isEmpty()) { - return true; - } - return optionNameFilter.contains(d.getName()); - } - return false; - } - - boolean matchesFlagsRuntime(OptionDescriptor d) { - return matchesFlags(d, d.getOptionKey() instanceof RuntimeOptionKey); - } - - boolean matchesFlagsHosted(OptionDescriptor d) { - OptionKey key = d.getOptionKey(); - return matchesFlags(d, key instanceof RuntimeOptionKey || key instanceof HostedOptionKey); - } - } - - /** - * Constants denoting supported boolean option formats. - */ - public enum BooleanOptionFormat { - NAME_VALUE("="), - PLUS_MINUS("+/-"); - - BooleanOptionFormat(String help) { - this.help = help; - } - - private final String help; - - @Override - public String toString() { - return help; - } - } + public static final String HOSTED_OPTION_PREFIX = CommonOptionParser.HOSTED_OPTION_PREFIX; + public static final String RUNTIME_OPTION_PREFIX = CommonOptionParser.RUNTIME_OPTION_PREFIX; static OptionParseResult parseOption(EconomicMap options, Predicate> isHosted, String option, EconomicMap, Object> valuesMap, String optionPrefix, BooleanOptionFormat booleanOptionFormat) { - if (option.length() == 0) { - return OptionParseResult.error("Option name must be specified"); - } - - String optionName; - Object value = null; - String valueString = null; - - char first = option.charAt(0); - int eqIndex = option.indexOf('='); - if (first == '+' || first == '-') { - if (eqIndex != -1) { - return OptionParseResult.error("Cannot mix +/- with = format: '" + optionPrefix + option + "'"); - } - optionName = option.substring(1); - if (booleanOptionFormat == BooleanOptionFormat.NAME_VALUE) { - return OptionParseResult.error("Option " + LocatableOption.from(optionName) + " must use = format, not +/- prefix"); - } - value = (first == '+'); - } else { - if (eqIndex == -1) { - optionName = option; - valueString = null; - } else { - optionName = option.substring(0, eqIndex); - valueString = option.substring(eqIndex + 1); - } - } - - LocatableOption current = LocatableOption.from(optionName); - OptionDescriptor desc = options.get(current.name); - if (desc == null && value != null) { - if (eqIndex != -1) { - optionName = option.substring(1, eqIndex); - current = LocatableOption.from(optionName); - desc = options.get(current.name); - } - } - - optionName = current.name; - - if (desc == null) { - List matches = new ArrayList<>(); - OptionsParser.collectFuzzyMatches(options.getValues(), optionName, matches); - StringBuilder msg = new StringBuilder("Could not find option ").append(current); - if (!matches.isEmpty()) { - msg.append(". Did you mean one of these:"); - for (OptionDescriptor match : matches) { - msg.append(' ').append(match.getName()); - } - } - msg.append(". Use ").append(optionPrefix).append(SubstrateOptions.PrintFlags.getName()).append("= to list all available options."); - return OptionParseResult.error(msg.toString()); - } - - OptionKey optionKey = desc.getOptionKey(); - boolean hostedOption = isHosted.test(optionKey); - Class optionValueType = getMultiOptionValueElementType(optionKey); - Class optionType = hostedOption && optionValueType != null ? optionValueType : desc.getOptionValueType(); - - if (value == null) { - if (optionType == Boolean.class && booleanOptionFormat == BooleanOptionFormat.PLUS_MINUS) { - return OptionParseResult.error("Boolean option " + current + " must have +/- prefix"); - } - if (valueString == null) { - return OptionParseResult.error("Missing value for option " + current); - } - try { - value = parseValue(optionType, current, valueString); - if (value instanceof OptionParseResult) { - return (OptionParseResult) value; - } - } catch (NumberFormatException ex) { - return OptionParseResult.error("Invalid value for option " + current + ": '" + valueString + "' is not a valid number"); - } - } else { - if (optionType != Boolean.class) { - return OptionParseResult.error("Non-boolean option " + current + " can not use +/- prefix. Use '" + current.name + "=' format"); - } - } - - optionKey.update(valuesMap, hostedOption ? LocatableOption.value(value, current.origin) : value); - - if (SubstrateOptions.PrintFlags.getName().equals(optionName)) { - String optionValue = (String) value; - EnumSet selectedOptionTypes; - if (optionValue.isEmpty()) { - selectedOptionTypes = EnumSet.allOf(OptionType.class); - } else { - selectedOptionTypes = EnumSet.noneOf(OptionType.class); - String enumString = null; - try { - String[] enumStrings = SubstrateUtil.split(optionValue, ","); - - for (String string : enumStrings) { - enumString = string; - selectedOptionTypes.add(OptionType.valueOf(enumString)); - } - } catch (IllegalArgumentException e) { - StringBuilder sb = new StringBuilder(); - boolean firstValue = true; - for (OptionType ot : OptionType.values()) { - if (firstValue) { - firstValue = false; - } else { - sb.append(", "); - } - sb.append(ot.name()); - } - String possibleValues = sb.toString(); - return OptionParseResult.error("Invalid value for option " + current + ". '" + enumString + "' is not one of: " + possibleValues); - } - } - return OptionParseResult.printFlags(selectedOptionTypes); - } - if (SubstrateOptions.PrintFlagsWithExtraHelp.getName().equals(optionName)) { - String optionValue = (String) value; - String[] optionNames = SubstrateUtil.split(optionValue, ","); - HashSet selectedOptionNames = new HashSet<>(Arrays.asList(optionNames)); - return OptionParseResult.printFlagsWithExtraHelp(selectedOptionNames); - } - - return OptionParseResult.correct(optionKey); - } - - private static Class getMultiOptionValueElementType(OptionKey optionKey) { - Object defaultValue = optionKey.getDefaultValue(); - if (defaultValue instanceof MultiOptionValue) { - return ((MultiOptionValue) defaultValue).getValueType(); - } - return null; - } - - @SuppressWarnings("unchecked") - static Object parseValue(Class optionType, LocatableOption option, String valueString) throws NumberFormatException { - Object value; - if (optionType == Integer.class) { - long longValue = parseLong(valueString); - if ((int) longValue != longValue) { - return OptionParseResult.error("Wrong value for option " + option + ": '" + valueString + "' is not a valid number"); - } - value = (int) longValue; - } else if (optionType == Long.class) { - value = parseLong(valueString); - } else if (optionType == String.class) { - value = valueString; - } else if (optionType == Double.class) { - value = parseDouble(valueString); - } else if (optionType == Boolean.class) { - if (valueString.equals("true")) { - value = true; - } else if (valueString.equals("false")) { - value = false; - } else { - return OptionParseResult.error("Boolean option " + option + " must have value 'true' or 'false'"); - } - } else if (optionType.isEnum()) { - value = Enum.valueOf(optionType.asSubclass(Enum.class), valueString); - } else { - throw VMError.shouldNotReachHere(option + " uses unsupported option value class: " + ClassUtil.getUnqualifiedName(optionType)); + try { + return CommonOptionParser.parseOption(options, isHosted, option, valuesMap, optionPrefix, booleanOptionFormat); + } catch (UnsupportedOptionClassException e) { + VMError.shouldNotReachHere(e.getMessage()); + return null; } - return value; } /** @@ -359,7 +90,10 @@ public static boolean parseHostedOption(String optionPrefix, EconomicMap optionParseResult.matchesFlags(d, () -> { + OptionKey key = d.getOptionKey(); + return key instanceof RuntimeOptionKey || key instanceof HostedOptionKey; + }), options, optionPrefix, out, optionParseResult.printFlagsWithExtraHelp()); throw new InterruptImageBuilding(""); } if (!optionParseResult.isValid()) { @@ -383,46 +117,12 @@ public static boolean parseHostedOption(String optionPrefix, EconomicMap optionDescriptors, Consumer optionDescriptorConsumer) { + CommonOptionParser.collectOptions(optionDescriptors, optionDescriptorConsumer); } public static void printOption(Consumer println, String option, String description, int indentation, int optionWidth, int wrapWidth) { - String indent = spaces(indentation); - String desc = description != null ? description : ""; - desc = wrapWidth > 0 ? wrap(desc, wrapWidth) : desc; - String nl = System.lineSeparator(); - String[] descLines = SubstrateUtil.split(desc, nl); - if (option.length() >= optionWidth && description != null) { - println.accept(indent + option + nl + indent + spaces(optionWidth) + descLines[0]); - } else { - println.accept(indent + option + spaces(optionWidth - option.length()) + descLines[0]); - } - for (int i = 1; i < descLines.length; i++) { - println.accept(indent + spaces(optionWidth) + descLines[i]); - } + CommonOptionParser.printOption(println, option, description, indentation, optionWidth, wrapWidth); } /** @@ -441,151 +141,15 @@ public static void printOption(Consumer println, String option, String d * between space and execution efficiency is acceptable. */ static void printFlags(Predicate filter, EconomicMap options, String prefix, PrintStream out, boolean verbose) { - List sortedDescriptors = new ArrayList<>(); - for (OptionDescriptor option : options.getValues()) { - if (filter.test(option)) { - sortedDescriptors.add(option); - } - } - sortedDescriptors.sort(Comparator.comparing(OptionDescriptor::getName)); - - for (OptionDescriptor descriptor : sortedDescriptors) { - String helpMsg = verbose && !descriptor.getExtraHelp().isEmpty() ? "" : descriptor.getHelp(); - int helpLen = helpMsg.length(); - if (helpLen > 0 && helpMsg.charAt(helpLen - 1) != '.') { - helpMsg += '.'; - } - boolean stringifiedArrayValue = false; - Object defaultValue = descriptor.getOptionKey().getDefaultValue(); - if (defaultValue != null && defaultValue.getClass().isArray()) { - Object[] defaultValues = (Object[]) defaultValue; - if (defaultValues.length == 1) { - defaultValue = defaultValues[0]; - } else { - List stringList = new ArrayList<>(); - String optionPrefix = prefix + descriptor.getName() + "="; - for (Object rawValue : defaultValues) { - String value; - if (rawValue instanceof String) { - value = '"' + String.valueOf(rawValue) + '"'; - } else { - value = String.valueOf(rawValue); - } - stringList.add(optionPrefix + value); - } - if (helpLen != 0) { - helpMsg += ' '; - } - helpMsg += "Default: "; - if (stringList.isEmpty()) { - helpMsg += "None"; - } else { - helpMsg += String.join(" ", stringList); - } - stringifiedArrayValue = true; - } - } - String verboseHelp = ""; - if (verbose) { - verboseHelp = System.lineSeparator() + descriptor.getHelp() + System.lineSeparator() + String.join(System.lineSeparator(), descriptor.getExtraHelp()); - } else if (!descriptor.getExtraHelp().isEmpty()) { - verboseHelp = " [Extra help available]"; - } - int wrapWidth = verbose ? 0 : PRINT_OPTION_WRAP_WIDTH; - if (descriptor.getOptionValueType() == Boolean.class) { - Boolean val = (Boolean) defaultValue; - if (helpLen != 0) { - helpMsg += ' '; - } - if (val != null) { - if (val) { - helpMsg += "Default: + (enabled)."; - } else { - helpMsg += "Default: - (disabled)."; - } - } - printOption(out, prefix + "\u00b1" + descriptor.getName(), helpMsg + verboseHelp, wrapWidth); - } else { - if (defaultValue == null) { - if (helpLen != 0) { - helpMsg += ' '; - } - helpMsg += "Default: None"; - } - helpMsg += verboseHelp; - if (stringifiedArrayValue || defaultValue == null) { - printOption(out, prefix + descriptor.getName() + "=...", helpMsg, wrapWidth); - } else { - if (defaultValue instanceof String) { - defaultValue = '"' + String.valueOf(defaultValue) + '"'; - } - printOption(out, prefix + descriptor.getName() + "=" + defaultValue, helpMsg, wrapWidth); - } - } - } + CommonOptionParser.printFlags(filter, options, prefix, out, verbose); } public static long parseLong(String v) { - String valueString = v.trim().toLowerCase(); - long scale = 1; - if (valueString.endsWith("k")) { - scale = 1024L; - } else if (valueString.endsWith("m")) { - scale = 1024L * 1024L; - } else if (valueString.endsWith("g")) { - scale = 1024L * 1024L * 1024L; - } else if (valueString.endsWith("t")) { - scale = 1024L * 1024L * 1024L * 1024L; - } - - if (scale != 1) { - /* Remove trailing scale character. */ - valueString = valueString.substring(0, valueString.length() - 1); - } - - return Long.parseLong(valueString) * scale; + return CommonOptionParser.parseLong(v); } - /** - * Parses the provide string to a double number, avoiding the JDK dependencies (which pull in a - * lot of classes, including the regular expression library). Only simple numbers are supported, - * without fancy exponent styles. - */ public static double parseDouble(String v) { - String valueString = v.trim(); - - int dotPos = valueString.indexOf('.'); - if (dotPos == -1) { - return parseLong(valueString); - } - - String beforeDot = valueString.substring(0, dotPos); - String afterDot = valueString.substring(dotPos + 1); - - double sign = 1; - if (beforeDot.startsWith("-")) { - sign = -1; - beforeDot = beforeDot.substring(1); - } else if (beforeDot.startsWith("+")) { - beforeDot = beforeDot.substring(1); - } - - if (beforeDot.startsWith("-") || beforeDot.startsWith("+") || afterDot.startsWith("-") || afterDot.startsWith("+") || - (beforeDot.length() == 0 && afterDot.length() == 0)) { - throw new NumberFormatException(v); - } - - double integral = 0; - if (beforeDot.length() > 0) { - integral = Long.parseLong(beforeDot); - } - - double fraction = 0; - if (afterDot.length() > 0) { - fraction = Long.parseLong(afterDot) * Math.pow(10, -afterDot.length()); - } - - return sign * (integral + fraction); + return CommonOptionParser.parseDouble(v); } /** diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java index 1373baa0d0c9..c7c7e5b08aa8 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java @@ -64,6 +64,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.oracle.svm.common.option.CommonOptions; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.nativeimage.Platform; @@ -188,8 +189,8 @@ void addFallbackBuildArgs(@SuppressWarnings("unused") List buildArgs) { public static final String oH = "-H:"; static final String oR = "-R:"; - final String enablePrintFlags = SubstrateOptions.PrintFlags.getName(); - final String enablePrintFlagsWithExtraHelp = SubstrateOptions.PrintFlagsWithExtraHelp.getName(); + final String enablePrintFlags = CommonOptions.PrintFlags.getName(); + final String enablePrintFlagsWithExtraHelp = CommonOptions.PrintFlagsWithExtraHelp.getName(); private static String oH(OptionKey option) { return oH + option.getName() + "="; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ConfigurationParserUtils.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ConfigurationParserUtils.java index f5e2a1b5d56f..193c309a935a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ConfigurationParserUtils.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ConfigurationParserUtils.java @@ -24,7 +24,7 @@ */ package com.oracle.svm.hosted.config; -import static com.oracle.svm.core.SubstrateOptions.PrintFlags; +import static com.oracle.svm.common.option.CommonOptions.PrintFlags; import java.io.IOException; import java.io.InputStreamReader; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java index 657da655ed43..e9a795dc44a3 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java @@ -24,7 +24,7 @@ */ package com.oracle.svm.hosted.option; -import static com.oracle.svm.core.option.SubstrateOptionsParser.BooleanOptionFormat.PLUS_MINUS; +import static com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat.PLUS_MINUS; import static com.oracle.svm.core.util.VMError.shouldNotReachHere; import java.util.ArrayList; @@ -59,30 +59,28 @@ public HostedOptionParser(ClassLoader imageClassLoader) { } public static void collectOptions(ServiceLoader optionDescriptors, EconomicMap allHostedOptions, - EconomicMap allRuntimeOptions) { - for (OptionDescriptors optionDescriptor : optionDescriptors) { - for (OptionDescriptor descriptor : optionDescriptor) { - String name = descriptor.getName(); - - if (descriptor.getDeclaringClass().getAnnotation(Platforms.class) != null) { - throw UserError.abort("Options must not be declared in a class that has a @%s annotation: option %s declared in %s", - Platforms.class.getSimpleName(), name, descriptor.getDeclaringClass().getTypeName()); - } + EconomicMap allRuntimeOptions) { + SubstrateOptionsParser.collectOptions(optionDescriptors, descriptor -> { + String name = descriptor.getName(); + + if (descriptor.getDeclaringClass().getAnnotation(Platforms.class) != null) { + throw UserError.abort("Options must not be declared in a class that has a @%s annotation: option %s declared in %s", + Platforms.class.getSimpleName(), name, descriptor.getDeclaringClass().getTypeName()); + } - if (!(descriptor.getOptionKey() instanceof RuntimeOptionKey)) { - OptionDescriptor existing = allHostedOptions.put(name, descriptor); - if (existing != null) { - throw shouldNotReachHere("Option name \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + descriptor.getLocation()); - } + if (!(descriptor.getOptionKey() instanceof RuntimeOptionKey)) { + OptionDescriptor existing = allHostedOptions.put(name, descriptor); + if (existing != null) { + throw shouldNotReachHere("Option name \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + descriptor.getLocation()); } - if (!(descriptor.getOptionKey() instanceof HostedOptionKey)) { - OptionDescriptor existing = allRuntimeOptions.put(name, descriptor); - if (existing != null) { - throw shouldNotReachHere("Option name \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + descriptor.getLocation()); - } + } + if (!(descriptor.getOptionKey() instanceof HostedOptionKey)) { + OptionDescriptor existing = allRuntimeOptions.put(name, descriptor); + if (existing != null) { + throw shouldNotReachHere("Option name \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + descriptor.getLocation()); } } - } + }); } public List parse(List args) { diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/StringUtil.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/StringUtil.java new file mode 100644 index 000000000000..602484d32ab5 --- /dev/null +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/StringUtil.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Alibaba Group Holding Limited. 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.util; + +import java.util.ArrayList; + +public class StringUtil { + + /** + * Similar to {@link String#split(String)} but with a fixed separator string instead of a + * regular expression. This avoids making regular expression code reachable. + */ + public static String[] split(String value, String separator) { + return split(value, separator, 0); + } + + /** + * Similar to {@link String#split(String, int)} but with a fixed separator string instead of a + * regular expression. This avoids making regular expression code reachable. + */ + public static String[] split(String value, String separator, int limit) { + int offset = 0; + int next; + ArrayList list = null; + while ((next = value.indexOf(separator, offset)) != -1) { + if (list == null) { + list = new ArrayList<>(); + } + boolean limited = limit > 0; + if (!limited || list.size() < limit - 1) { + list.add(value.substring(offset, next)); + offset = next + separator.length(); + } else { + break; + } + } + + if (offset == 0) { + /* No match found. */ + return new String[]{value}; + } + + /* Add remaining segment. */ + list.add(value.substring(offset)); + + return list.toArray(new String[list.size()]); + } +} From f4fb25aac09632ea7c695e1c533a55aba239ddcf Mon Sep 17 00:00:00 2001 From: Boris Spasojevic Date: Mon, 11 Oct 2021 13:45:53 +0200 Subject: [PATCH 506/681] Remove the warmup estimator tool. --- tools/mx.tools/suite.py | 32 --- .../warmup/test/WarmupEstimatorTest.java | 125 -------- .../impl/WarmupEstimatorInstrument.java | 271 ------------------ 3 files changed, 428 deletions(-) delete mode 100644 tools/src/com.oracle.truffle.tools.warmup.test/src/com/oracle/truffle/tools/warmup/test/WarmupEstimatorTest.java delete mode 100644 tools/src/com.oracle.truffle.tools.warmup/src/com/oracle/truffle/tools/warmup/impl/WarmupEstimatorInstrument.java diff --git a/tools/mx.tools/suite.py b/tools/mx.tools/suite.py index c1194e2f16f7..636bd906fee3 100644 --- a/tools/mx.tools/suite.py +++ b/tools/mx.tools/suite.py @@ -588,38 +588,6 @@ "native-image.properties" : "file:mx.tools/tools-dap.properties", }, }, - "TRUFFLE_WARMUP_ESTIMATOR": { - "subDir": "src", - "dependencies": [ - "com.oracle.truffle.tools.warmup", - ], - "distDependencies" : [ - "truffle:TRUFFLE_API", - ], - "maven" : { - "artifactId" : "warmup", - }, - "description" : "Truffle warmup estimation tool.", - }, - "TRUFFLE_WARMUP_ESTIMATOR_TEST": { - "subDir": "src", - "dependencies": [ - "com.oracle.truffle.tools.warmup.test", - ], - "distDependencies" : [ - "truffle:TRUFFLE_TEST", - "TRUFFLE_WARMUP_ESTIMATOR", - ], - "description" : "Tests for the truffle warmup estimator tool.", - "maven" : False, - }, - "TRUFFLE_WARMUP_ESTIMATOR_GRAALVM_SUPPORT" : { - "native" : True, - "description" : "Truffle Profiler support distribution for the GraalVM", - "layout" : { - "native-image.properties" : "file:mx.tools/tools-profiler.properties", - }, - }, "VISUALVM_GRAALVM_SUPPORT": { "native": True, "platformDependent": True, diff --git a/tools/src/com.oracle.truffle.tools.warmup.test/src/com/oracle/truffle/tools/warmup/test/WarmupEstimatorTest.java b/tools/src/com.oracle.truffle.tools.warmup.test/src/com/oracle/truffle/tools/warmup/test/WarmupEstimatorTest.java deleted file mode 100644 index e3e6ce25444f..000000000000 --- a/tools/src/com.oracle.truffle.tools.warmup.test/src/com/oracle/truffle/tools/warmup/test/WarmupEstimatorTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2020, 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.truffle.tools.warmup.test; - -import java.io.ByteArrayOutputStream; - -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Source; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.oracle.truffle.api.instrumentation.test.InstrumentationTestLanguage; -import com.oracle.truffle.tools.warmup.impl.WarmupEstimatorInstrument; - -public class WarmupEstimatorTest { - private static final String defaultSourceString = "ROOT(\n" + - "DEFINE(foo,ROOT(STATEMENT)),\n" + - "DEFINE(bar,ROOT(BLOCK(STATEMENT,LOOP(10, CALL(foo))))),\n" + - "DEFINE(neverCalled,ROOT(BLOCK(STATEMENT,LOOP(10, CALL(bar))))),\n" + - "CALL(bar)\n" + - ")"; - private static final Source defaultSource = makeSource(defaultSourceString); - private ByteArrayOutputStream out; - private ByteArrayOutputStream err; - - private static Source makeSource(String s) { - return Source.newBuilder(InstrumentationTestLanguage.ID, s, "test").buildLiteral(); - } - - @Before - public void setUp() { - out = new ByteArrayOutputStream(); - err = new ByteArrayOutputStream(); - } - - @Test - public void testBasic() { - try (Context context = defaultContext().option(WarmupEstimatorInstrument.ID + ".Root", "foo").build()) { - context.eval(defaultSource); - } - final String output = out.toString(); - assertContains(output, "Best time |"); - assertContains(output, "Best iter |"); - assertContains(output, "Epsilon | 1.05"); - assertContains(output, "Peak Start Iter |"); - assertContains(output, "Peak Start Time |"); - assertContains(output, "Warmup time |"); - assertContains(output, "Warmup cost |"); - assertContains(output, "Iterations | 10"); - } - - @Test - public void testMultiRootName() { - try (Context context = defaultContext().option(WarmupEstimatorInstrument.ID + ".Root", "foo,bar").build()) { - context.eval(defaultSource); - } - final String output = out.toString(); - assertContains(output, "foo"); - assertContains(output, "bar"); - } - - @Test - public void testMultiRootLine() { - try (Context context = defaultContext().option(WarmupEstimatorInstrument.ID + ".Root", "::2,::3").build()) { - context.eval(defaultSource); - } - final String output = out.toString(); - assertContains(output, "::2"); - assertContains(output, "::3"); - } - - @Test - public void testMultiRootNameLine() { - try (Context context = defaultContext().option(WarmupEstimatorInstrument.ID + ".Root", "foo::2,bar::3").build()) { - context.eval(defaultSource); - } - final String output = out.toString(); - assertContains(output, "foo::2"); - assertContains(output, "bar::3"); - } - - @Test - public void testRawOutput() { - try (Context context = defaultContext().option(WarmupEstimatorInstrument.ID + ".Root", "foo").option(WarmupEstimatorInstrument.ID + ".Output", "raw").build()) { - context.eval(defaultSource); - } - final String output = out.toString(); - Assert.assertTrue(output.startsWith("[")); - Assert.assertTrue(output.endsWith("]")); - assertContains(output, "{"); - assertContains(output, "}"); - Assert.assertEquals(11, output.split(",").length); - } - - private static void assertContains(String output, String expected) { - Assert.assertTrue(output.contains(expected)); - } - - private Context.Builder defaultContext() { - return Context.newBuilder().in(System.in).out(out).err(err).option(WarmupEstimatorInstrument.ID, "true").allowExperimentalOptions(true); - } -} diff --git a/tools/src/com.oracle.truffle.tools.warmup/src/com/oracle/truffle/tools/warmup/impl/WarmupEstimatorInstrument.java b/tools/src/com.oracle.truffle.tools.warmup/src/com/oracle/truffle/tools/warmup/impl/WarmupEstimatorInstrument.java deleted file mode 100644 index 19a9cb14ad7e..000000000000 --- a/tools/src/com.oracle.truffle.tools.warmup/src/com/oracle/truffle/tools/warmup/impl/WarmupEstimatorInstrument.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2020, 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.truffle.tools.warmup.impl; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.logging.Level; - -import org.graalvm.options.OptionCategory; -import org.graalvm.options.OptionDescriptors; -import org.graalvm.options.OptionKey; -import org.graalvm.options.OptionStability; -import org.graalvm.options.OptionType; -import org.graalvm.options.OptionValues; - -import com.oracle.truffle.api.Option; -import com.oracle.truffle.api.TruffleLogger; -import com.oracle.truffle.api.instrumentation.EventContext; -import com.oracle.truffle.api.instrumentation.ExecutionEventNode; -import com.oracle.truffle.api.instrumentation.Instrumenter; -import com.oracle.truffle.api.instrumentation.SourceSectionFilter; -import com.oracle.truffle.api.instrumentation.StandardTags; -import com.oracle.truffle.api.instrumentation.TruffleInstrument; - -@TruffleInstrument.Registration(id = WarmupEstimatorInstrument.ID, name = "Warmup Estimator", version = WarmupEstimatorInstrument.VERSION) -public class WarmupEstimatorInstrument extends TruffleInstrument { - - public static final String ID = "warmup"; - public static final String VERSION = "0.0.1"; - - static final OptionType CLI_OUTPUT_TYPE = new OptionType<>("Output", optionString -> { - try { - return Output.valueOf(optionString.toUpperCase()); - } catch (IllegalArgumentException e) { - StringBuilder message = new StringBuilder("Wrong output specified. Output can be one of:"); - for (Output output : Output.values()) { - message.append(" "); - message.append(output.toString().toLowerCase()); - } - message.append(". For example: --warmup.Output=" + Output.SIMPLE.toString()); - throw new IllegalArgumentException(message.toString()); - } - }); - - static final OptionType> LOCATION_OPTION_TYPE = new OptionType<>("Location", optionString -> { - if (optionString.isEmpty()) { - throw new IllegalArgumentException("Root option must be set. " + - "If no root is set nothing can be instrumented. " + - "Root must be specified as 'rootName:fileName:lineNumber' e.g. --" + ID + "Root=foo:foo.js:14"); - } - final String[] split = optionString.split(","); - final List locations = new ArrayList<>(); - for (String locationString : split) { - locations.add(Location.parseLocation(locationString)); - } - return Collections.unmodifiableList(locations); - }); - - @Option(name = "", help = "Enable the Warmup Estimator (default: false).", category = OptionCategory.USER) // - static final OptionKey ENABLED = new OptionKey<>(false); - @Option(help = "Specifies the root representing a benchmark iteration as 'rootName:fileName:lineNumber' where any of the parts are optional. " + - "Multiple entries can be specified separated by commas. (e.g. 'main::,foo:foo.js:,fact:factorial.js:14').", category = OptionCategory.USER) // - static final OptionKey> Root = new OptionKey<>(Collections.emptyList(), LOCATION_OPTION_TYPE); - @Option(name = "OutputFile", help = "Save output to the given file. Output is printed to stdout by default.", category = OptionCategory.USER) // - static final OptionKey OUTPUT_FILE = new OptionKey<>(""); - @Option(name = "Output", help = "Can be: 'raw' for json array of raw samples; 'json' for included post processing of samples; 'simple' for just the human-readable post-processed result (default: simple)", // - category = OptionCategory.USER) // - static final OptionKey OUTPUT = new OptionKey<>(Output.SIMPLE, CLI_OUTPUT_TYPE); - @Option(name = "Epsilon", help = "Sets the epsilon value which specifies the tolerance for peak performance detection. It's inferred if the value is 0. (default: 1.05)", category = OptionCategory.USER, stability = OptionStability.EXPERIMENTAL) // - static final OptionKey EPSILON = new OptionKey<>(1.05); - private final Map> locationsToTimes = new HashMap<>(); - private boolean enabled; - - private static int parseInt(String string) { - try { - return Integer.parseInt(string); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Unable to parse line number from given input: " + string); - } - } - - private static SourceSectionFilter filter(Location location) { - final SourceSectionFilter.Builder builder = SourceSectionFilter.newBuilder().// - includeInternal(false).// - tagIs(StandardTags.RootTag.class); - if (!Objects.equals(location.rootName, "")) { - builder.rootNameIs(location.rootName::equals); - } - if (!Objects.equals(location.fileName, "")) { - builder.sourceIs(s -> location.fileName.equals(s.getName())); - } - if (location.line != null) { - builder.lineStartsIn(SourceSectionFilter.IndexRange.byLength(location.line, 1)); - } - return builder.build(); - } - - private static PrintStream outputStream(Env env, OptionValues options) { - final String outputPath = OUTPUT_FILE.getValue(options); - if ("".equals(outputPath)) { - return new PrintStream(env.out()); - } - final File file = new File(outputPath); - if (file.exists()) { - throw new IllegalArgumentException("Cannot redirect output to an existing file!"); - } - try { - return new PrintStream(new FileOutputStream(file)); - } catch (FileNotFoundException e) { - throw new IllegalArgumentException("File not found for argument " + outputPath, e); - } - } - - @Override - protected OptionDescriptors getOptionDescriptors() { - return new WarmupEstimatorInstrumentOptionDescriptors(); - } - - @Override - protected void onCreate(Env env) { - final OptionValues options = env.getOptions(); - enabled = options.get(WarmupEstimatorInstrument.ENABLED); - if (enabled) { - final List locations = options.get(Root); - if (locations.size() == 0) { - throw new IllegalArgumentException("Locations must be set"); - } - final Instrumenter instrumenter = env.getInstrumenter(); - for (Location location : locations) { - instrumenter.attachExecutionEventFactory(filter(location), context -> createNode(env, context, location)); - } - } - } - - private synchronized ExecutionEventNode createNode(Env env, EventContext context, Location location) { - final TruffleLogger logger = env.getLogger(this.getClass()); - List times = locationsToTimes.get(location); - if (times == null) { - logger.log(Level.INFO, "Instrumenting root like " + location + " on " + context.getInstrumentedSourceSection()); - times = new ArrayList<>(); - locationsToTimes.put(location, times); - return new WarmupEstimatorNode(times); - } - logger.log(Level.WARNING, "Ignoring multiple roots like " + location + " on " + context.getInstrumentedSourceSection()); - return null; - } - - @Override - protected void onDispose(Env env) { - if (locationsToTimes.isEmpty()) { - env.getLogger(this.getClass()).log(Level.WARNING, "No roots like " + Root.getValue(env.getOptions()) + " found during execution."); - } - final OptionValues options = env.getOptions(); - final List results = results(EPSILON.getValue(options)); - try (PrintStream stream = outputStream(env, options)) { - final ResultsPrinter printer = new ResultsPrinter(results, stream); - switch (OUTPUT.getValue(options)) { - case SIMPLE: - printer.printSimpleResults(); - break; - case JSON: - printer.printJsonResults(); - break; - case RAW: - printer.printRawResults(); - break; - } - } - super.onDispose(env); - } - - private List results(Double epsilon) { - final List results = new ArrayList<>(); - for (Location location : locationsToTimes.keySet()) { - final List times = locationsToTimes.get(location); - results.add(new Results(location.toString(), times, epsilon)); - } - return results; - } - - enum Output { - SIMPLE, - JSON, - RAW, - } - - static final class Location { - final String rootName; - final String fileName; - final Integer line; - - Location(String rootName, String fileName, Integer line) { - this.rootName = rootName; - this.fileName = fileName; - this.line = line; - } - - private static Location parseLocation(String locationString) { - final String[] strings = locationString.split(":"); - final String rootName = strings[0]; - final String fileName = strings.length > 1 ? strings[1] : ""; - final Integer line = strings.length == 3 && !Objects.equals(strings[2], "") ? parseInt(strings[2]) : null; - return new Location(rootName, fileName, line); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || o instanceof Location) { - return false; - } - Location location = (Location) o; - return Objects.equals(rootName, location.rootName) && - Objects.equals(fileName, location.fileName) && - Objects.equals(line, location.line); - } - - @Override - public int hashCode() { - return Objects.hash(rootName, fileName, line); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(rootName); - if (!Objects.equals(fileName, "")) { - builder.append(':'); - builder.append(fileName); - } else if (line != null) { - builder.append(':'); - } - if (line != null) { - builder.append(':'); - builder.append(line); - } - return builder.toString(); - } - } -} From 9fd855baf09b4788ff471a97acae2440112c3202 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Mon, 18 Oct 2021 10:47:03 +0300 Subject: [PATCH 507/681] Fix fetch-jdk invocation Co-authored-by: Fabio Niephaus --- .github/workflows/quarkus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quarkus.yml b/.github/workflows/quarkus.yml index f4ceb8ea570d..2f6668d51798 100644 --- a/.github/workflows/quarkus.yml +++ b/.github/workflows/quarkus.yml @@ -63,7 +63,7 @@ jobs: - name: Get JDK run: | mkdir jdk-dl - ${MX_PATH}/mx fetch-jdk --jdk-id labsjdk-ce-11 --to jdk-dl --alias ${JAVA_HOME} + ${MX_PATH}/mx --java-home= fetch-jdk --jdk-id labsjdk-ce-11 --to jdk-dl --alias ${JAVA_HOME} - name: Build graalvm native-image run: | cd substratevm From 8521def98638634a137a2431d55dfc267c8a603d Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Thu, 14 Oct 2021 13:12:02 +0200 Subject: [PATCH 508/681] speculative guard movement: force hoist guards in inverted loops if the anchor is actually inside the loop --- .../loop/phases/SpeculativeGuardMovementPhase.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java index b162697cc935..fa934c5b800f 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java @@ -182,6 +182,7 @@ private Block earliestBlock(Node node) { if (node instanceof GuardNode) { GuardNode guard = (GuardNode) node; LogicNode condition = guard.getCondition(); + Loop forcedHoisting = null; if (condition instanceof IntegerLessThanNode || condition instanceof IntegerBelowNode) { forcedHoisting = tryOptimizeCompare(guard, (CompareNode) condition); @@ -253,17 +254,12 @@ private Loop tryOptimizeCompare(GuardNode guard, CompareNode compare) { bound = compare.getY(); mirrored = false; } + if (tryOptimizeCompare(compare, iv, bound, mirrored, guard)) { - if (isInverted(iv.getLoop())) { - return null; - } return iv.getLoop().loop(); } if (otherIV != null) { if (tryOptimizeCompare(compare, otherIV, iv.valueNode(), !mirrored, guard)) { - if (isInverted(iv.getLoop())) { - return null; - } return otherIV.getLoop().loop(); } } From f7cd09e82f2a0b32193d6ec2a81f99e322f84ac5 Mon Sep 17 00:00:00 2001 From: Olga Gupalo Date: Mon, 18 Oct 2021 17:31:05 +0300 Subject: [PATCH 509/681] Update documentation for VS Code extensions required for 21.3 release --- docs/tools/vscode/graalvm/README.md | 56 ++++-- .../vscode/graalvm/visualvm-integration.md | 2 +- docs/tools/vscode/micronaut/README.md | 21 ++- docs/tools/vscode/micronaut/k8s-support.md | 177 ++++++++++++++++++ 4 files changed, 227 insertions(+), 29 deletions(-) create mode 100644 docs/tools/vscode/micronaut/k8s-support.md diff --git a/docs/tools/vscode/graalvm/README.md b/docs/tools/vscode/graalvm/README.md index 7e547ea330c0..f2c752c46310 100644 --- a/docs/tools/vscode/graalvm/README.md +++ b/docs/tools/vscode/graalvm/README.md @@ -16,7 +16,7 @@ The extension is Technology Preview. - [Installation and Setup](#installation-and-setup) - [Java Development and Debugging](#java-development-and-debugging) - [Native Image Agent](#native-image-agent) -- [Native Image Debugger](#native-image-debugger) +- [Native Image Debugging](#native-image-debugging) - [Integration with VisualVM](#integration-with-visualvm) - [JavaScript and Node.js Debugging](#javascript-and-nodejs-debugging) - [Python Debugging](#python-debugging) @@ -125,7 +125,7 @@ The "Download & Install GraalVM" action is a preferable way, as it eliminates th ## Java Development and Debugging -To start developing or debugging Java applications, ensure GraalVM is used as your Java runtime in VS Code. +To start developing Java applications, ensure GraalVM is used as your Java runtime in VS Code. If the current path is not pointing to the GraalVM folder, go to the User Settings window and use the `netbeans.jdkhome` value in the _settings.json_ file. This configuration is then used to launch the Java Language Server. @@ -192,32 +192,48 @@ Open the _launch.json_ file and click the Add Configuration... button in the bot 5. Generate load to the running process to invoke more code and generate the best configuration. Once all possible execution paths have been executed, terminate the process. At this point the Native Image agent dumps the collected configuration to the selected output directory. -Once the configuration for Native Image has been generated, follow the documentation on how to [generate a native image for a project](https://www.graalvm.org/reference-manual/native-image#build-a-native-image) from the command line, or how to [build native images right from VS Code](../micronaut/README.md#generate-native-images-of-micronaut-projects). +Once the configuration for Native Image has been generated, follow the documentation on how to [generate a native image for a project](https://www.graalvm.org/reference-manual/native-image/#build-a-native-image) from the command line, or how to [build native images right from VS Code](../micronaut/README.md#generate-native-images-of-micronaut-projects). -## Native Image Debugger +## Native Image Debugging GraalVM Extension Pack for Java provides Java like debugging of platform native executables produced by [GraalVM Native Image](https://www.graalvm.org/reference-manual/native-image/). It is provided using the GNU Debugger (GDB) and via a new Run configuration named __Launch Native Image__. GraalVM Enterprise Edition is required as it produces full debug information for a native image. -> Note: This feature is experimental. It currently works only on Linux with GDB 7.11 or GDB 10.1+ due to known issue [#26139](https://sourceware.org/bugzilla/show_bug.cgi?id=26139) in GDB 8 and 9. +![Native Image debugging](images/ni_debugging.png) + +> Note: Native Image debugging requires `gdb` debugger (GDB 7.11 or GDB 10.1+), it currently works only on Linux. The feature is experimental. In order to debug native images of Java applications, it is necessary to build such images with debug information available. It can be done by providing following switches for the `native-image` builder: - `-g -O0` or - `-H:Debug=2 -H:Optimize=0`. -The resulting images will contain debug records in a format GDB understands. +The resulting images will contain debug records in a format `gdb` debugger understands. + +### Debug Native Image “Real” Code + +Since recently you can attach the debugger to a Native Image process and step over the image “real” code. + +Attaching of debugger to a Native Image process is done via adding a configuration into the _launch.json_ file. + +1. Select **Native Image: Attach to Process** from the configurations autocompletion in _launch.json_. It generates the **Attach to Native Image** configuration. When that configuration is selected and executed, a list of running processes opens. +2. Select the running process that corresponds to the Native Image you intend to debug. +3. when the source file opens, start debugging: + ![Native Image debugging source code](images/NativeImageExecutableLocations.png) + +The step over the image “real” code” is mostly about UI differentiation of code which is compiled in the native image and which is not used. +The shaded code is not a part of the Native Image. ## Integration with VisualVM -As of GraalVM 21.2.0, the GraalVM Tools for Java extension introduced a new feature in this version - the integration with [VisualVM](https://visualvm.github.io), which is the all-in-one Java (and polyglot) monitoring and troubleshooting tool. +As of GraalVM 21.2.0, the GraalVM Tools for Java extension introduced a new feature in this version - the integration with VisualVM (https://visualvm.github.io), which is the all-in-one Java (and polyglot) monitoring and troubleshooting tool. This brings the visual Java tooling to VS Code. ![VisualVM and VS Code Integration](images/vscode_visualvm.png) -To get started, you need to get the latest stable GraalVM release using the **Download & Install GraalVM** action from the **Gr** activity view, as described in the [Installation and Setup](#installation-and-setup) section. -Make sure the GraalVM is set as **active**. +To get started, you need to get the latest stable GraalVM release using the **Download & Install GraalVM** action from the **Gr** activity view, as described in the [Installation and Setup](README.md#installation-and-setup) section. +Make sure the GraalVM is set as the **active**. Once a GraalVM installation is set as active, the Command Palette contains the following commands related to VisualVM: @@ -236,7 +252,7 @@ Follow these steps to start VisualVM automatically from within the VS Code: 4. Select the **Launch VisualVM & Java 8+ Application** launch configuration in the Run and Debug activity. Use the Start Debugging or Run Without Debugging action to start the current project. -While the project is starting, the Process node in VisualVM pane displays a project name with a "pid pending" label. +While the project is starting, the Process node in VisualVM pane displays project name with a "pid pending" label. Once the project process starts, the Process node is updated to show its process ID (PID) and the action defined in step 3 is performed. > Note: This feature was introduced with the GraalVM 21.2.0 release. Please make sure to get the latest GraalVM Tools for Java extension from the VS Code Marketplace, preferably by downloading the [GraalVM Extension Pack for Java](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm-pack). @@ -461,7 +477,7 @@ For example, to connect to the Chrome Dev Tools protocol port, the content of th Alternatively, to pass the `--polyglot` option to any of the existing application launchers, add the `runtimeArgs` attribute containing the `--polyglot` value to their respective debug configurations. -> Note: In some cases (polyglot application calls Java or R, or native launcher accesses languages installed with `gu` without [rebuilding images](https://www.graalvm.org/reference-manual/graalvm-updater#component-uninstallation)), also passing the `--jvm` option is necessary. +> Note: In some cases (polyglot application calls Java or R, or native launcher accesses languages installed with `gu` without [rebuilding images](https://www.graalvm.org/reference-manual/graalvm-updater/#component-uninstallation)), also passing the `--jvm` option is necessary. ![Image Debug Configuration for Python](images/polyglot-debug-config.png) @@ -502,14 +518,14 @@ GraalVM supports smart editing features of development tools used to create gues This allows you to attach compatible development tools such as VS Code to GraalVM and to get features like auto complete, go to declaration, or documentation on hover. Currently, [GraalVM's Language Server Protocol](https://www.graalvm.org/tools/lsp/) implementation supports the following services: -* [Text Document Synchronization](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_synchronization) -* [Hover Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_hover) -* [Completion Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_completion) -* [Signature Help Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_signatureHelp) -* [Document Highlight Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_documentHighlight) -* [Code Action Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_codeAction) -* [Code Lens Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_codeLens) -* [Execute Command Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current#workspace_executeCommand) +* [Text Document Synchronization](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_synchronization) +* [Hover Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover) +* [Completion Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion) +* [Signature Help Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp) +* [Document Highlight Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight) +* [Code Action Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction) +* [Code Lens Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeLens) +* [Execute Command Provider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand) > Note: The Language Server Protocol is offered as a technology preview and requires to pass the `--experimental-options` option for its activation. @@ -552,7 +568,7 @@ Once the `solargraph` gem is installed, the Ruby Language Server is automaticall ### Additional Editor Features -Since the easy writing of [polyglot applications](https://www.graalvm.org/reference-manual/polyglot-programming/) is one of the defining features of GraalVM, the code completion invoked inside JavaScript sources provides items for `Polyglot.eval(...)`, `Polyglot.evalFile(...)`, and `Java.type(...)` calls. +Since the easy writing of [polyglot](https://www.graalvm.org/docs/reference-manual/polyglot) applications is one of the defining features of GraalVM, the code completion invoked inside JavaScript sources provides items for `Polyglot.eval(...)`, `Polyglot.evalFile(...)`, and `Java.type(...)` calls. ![Image Code Completion](images/code-completion-js.png) diff --git a/docs/tools/vscode/graalvm/visualvm-integration.md b/docs/tools/vscode/graalvm/visualvm-integration.md index 9e1a2abd036b..456c96edf047 100644 --- a/docs/tools/vscode/graalvm/visualvm-integration.md +++ b/docs/tools/vscode/graalvm/visualvm-integration.md @@ -2,7 +2,7 @@ layout: docs toc_group: vscode link_title: VisualVM and VS Code Integration -permalink: /tools/vscode/visualvm-integration/ +permalink: /tools/vscode/graalvm/visualvm-integration/ --- # VisualVM and VS Code Integration diff --git a/docs/tools/vscode/micronaut/README.md b/docs/tools/vscode/micronaut/README.md index 8f7a736296ce..3a8afcaac37b 100644 --- a/docs/tools/vscode/micronaut/README.md +++ b/docs/tools/vscode/micronaut/README.md @@ -22,10 +22,9 @@ In combination with the [GraalVM Tools for Java extension](https://marketplace.v - [Extension Settings](#extension-settings) - [Create Micronaut Project](#create-micronaut-project) - [Generate Native Images of Micronaut Projects](#generate-native-images-of-micronaut-projects) -- [Deploy Micronaut Projects](#deploy-micronaut-projects) -- [Feedback](#feedback) -- [Privacy Policy](#privacy-policy) -- [Known Issues](#known-issues) +- [Deploy Micronaut Projects to Docker Registry](#deploy-micronaut-projects-to-docker-registry) +- [Deploy Micronaut Applications to Oracle Container Engine for Kubernetes](#deploy-micronaut-applications-to-oracle-container-engine-for-kubernetes) +- [Debug Micronaut Applications in Remote Kubernetes](#debug-micronaut-applications-in-remote-kubernetes) ## Installation and Setup @@ -107,12 +106,18 @@ That will run the `mvnw package -Dpackaging=native-image` job. For more details, continue reading to the [Micronaut documentation](https://guides.micronaut.io/micronaut-creating-first-graal-app/guide/index.html#creatingGraalImage). -## Deploy Micronaut Projects +## Deploy Micronaut Projects to Docker Registry -The Micronaut support in VSCode also allows to build and deploy Docker image to a Docker Registry. -Use action View > Command Palette > Micronaut: Deploy... and select **dockerPush** to deploy dockerized Micronaut application or **dockerPushNative** to build and push docker with a native executable of Micronaut application. +The Micronaut support in VS Code allows to build and deploy Docker images to Docker registry. +Use action **View** > **Command Palette** > **Micronaut: Deploy...** and select **dockerPush** to deploy a dockerized Micronaut application or **dockerPushNative** to build and push docker with a native executable of Micronaut application. -Besides that, you can also push a Micronaut application or a native executable to a Docker Registry from the VS Code terminal window. A particular Docker Registry can be configured in the build, see the [Micronaut Deploying Application](https://micronaut-projects.github.io/micronaut-maven-plugin/latest/examples/deploy.html) documentation. +![Micronaut Deploy Commands](images/micronaut-deploy-commands.png) + +Besides that, you can also push a Micronaut application or a native executable to the Docker Registry from the VS Code Terminal window. +A particular Docker Registry can be configured in the build, see the [Micronaut Deploying Application](https://micronaut-projects.github.io/micronaut-maven-plugin/latest/examples/deploy.html) documentation. + + +{% include_relative k8s-support.md %} ### Feedback diff --git a/docs/tools/vscode/micronaut/k8s-support.md b/docs/tools/vscode/micronaut/k8s-support.md new file mode 100644 index 000000000000..283533a0c6a0 --- /dev/null +++ b/docs/tools/vscode/micronaut/k8s-support.md @@ -0,0 +1,177 @@ +--- +layout: docs +toc_group: vscode +link_title: Deploy Micronaut Applications to Oracle Container Engine for Kubernetes +permalink: /tools/vscode/micronaut/kubernetes-support/ +--- + +# Deploy Micronaut Applications to Oracle Container Engine for Kubernetes + +GraalVM Tools for Micronaut Extension added support for working with Kubernetes clusters based on Microsofts’s [Visual Studio Code Kubernetes Tools](https://marketplace.visualstudio.com/items?itemName=ms-kubernetes-tools.vscode-kubernetes-tools). + +It is now possible to deploy and debug a Micronaut project to Kubernetes on Oracle Cloud with Oracle Container Engine for Kubernetes (OKE)](https://www.oracle.com/uk/cloud-native/container-engine-kubernetes/) environment. +OKE is a fully-managed, scalable, and highly available service that you can use to deploy your containerized applications to the cloud. + +This guide will walk you through the process of deploying a Micronaut application to OKE from VS Code and debugging it. + +### Prerequisites +- [Visual Studio Code Kubernetes Tools](https://marketplace.visualstudio.com/items?itemName=ms-kubernetes-tools.vscode-kubernetes-tools) +- [Docker](https://docs.docker.com/engine/reference/run/) +- [Oracle Cloud Account](https://www.oracle.com/uk/cloud/free/) +- [Access to Oracle Container Engine for Kubernetes (OKE)](https://oracle.github.io/learning-library/oci-library/oci-hol/OKE/workshops/freetier/index.html?lab=intro) + +## Preparation + +### Visual Studio Code Kubernetes Tools +Micronaut's extension support for Kubernetes is based on Microsofts’s [Visual Studio Code Kubernetes Tools](https://marketplace.visualstudio.com/items?itemName=ms-kubernetes-tools.vscode-kubernetes-tools). It has to be installed. + +Open Extensions tab, search for "Kubernetes" and install the one from Microsoft. +Once installed, you should see the Kubernetes icon in the left sidebar: +![Kubernetes extension installed](images/kubernetes_icon.png) + +### Oracle Cloud Account + +If you have not got an active Oracle Cloud account, create one by following this [link](https://docs.oracle.com/en/cloud/get-started/subscriptions-cloud/csgsg/get-oracle-com-account.html). + +### Access to Oracle Container Engine for Kubernetes (OKE) + +Supposedly, you have signed in to your Oracle Cloud account. +To be able to deploy Docker images to Oracle Container Registry, you need to setup the access to Oracle Container Engine for Kubernetes (OKE). + +#### Step 1: Create a Kubernetes cluster in OCI + +Using the Oracle Cloud Console, create a Kubernetes cluster with default settings using the *Quick Create* workflow: + +1. In the Oracle Cloud Console, open the navigation menu and click **Developer Services**. +2. Under Containers, click **Kubernetes Clusters (OKE)**. +3. Then click **Create Cluster**. + +For more information, check this [guide](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengcreatingclusterusingoke_topic-Using_the_Console_to_create_a_Quick_Cluster_with_Default_Settings.htm). + +#### Step 2: Set up access to Kubernetes cluster + +You can access your Kubernetes cluster and manage it using `kubectl`. +The `kubectl` command-line tool must be configured to communicate with your cluster. +To do that you have to set up a Kubernetes configuration file, _kubeconfig_. +The kubeconfig file (by default stored and can be found in the _$HOME/.kube/config_) provides the necessary details to access the cluster. + +See the [Setting Up Local Access to Clusters](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengdownloadkubeconfigfile.htm#localdownload) guide for step-by-step instructions. + +### Log in to Docker + +To be able to dockerize your Micronaut project, push and pull images on a local machine, and deploy to Oracle Container Registry, you will need [Docker](https://docs.docker.com/engine/reference/run/). +To check whether [Docker](https://docs.docker.com/engine/reference/run/) is started and running on your computer, go to VS Code Terminal and type: `docker --help`. + +Next you need to login with Docker to your Oracle Container Registry. +Prepare following Oracle Cloud account credentials: + +- Oracle Cloud Infrastructure (OCI) tenancy name +- User email address used for your OCI account +- OCI authentification token +- OCI region key + +From VS Code Terminal window, log in using the following command: +```bash +docker login -u / -p .ocir.io +``` +For example, if your OCI region is US East (Ashburn), then the key will be `iad`, and the region endpoint will be `https://iad.ocir.io`. +The list of available regions and their keys is available [here](https://docs.oracle.com/en-us/iaas/Content/Registry/Concepts/registryprerequisites.htm). + +> NOTE: If the Docker registry is private you will need a Docker registry secret. + +This [guide](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengpullingimagesfromocir.htm) describes how to create a Docker registry secret and describes how to specify the image to pull from Oracle Cloud Infrastructure Registry (along with the Docker secret to use) during application deployment to a cluster you've created using OKE. + +### Specify the Location for Docker Image in Oracle Container Registry + +The location where to push your Docker image in Oracle Container Registry should be specified in the project configuration file. + +If you used Gradle to build your Micronaut project, open the _gradle.build_ file and update image location: + ```xml + dockerBuild { + images = [".ocir.io///:"] + } + ``` + +See, for example, this example project configuration: +![Docker image location](images/docker_image_location.png) + + + +## Deploy a Micronaut Application to OKE + +To deploy, run and debug a Micronaut application in Oracle Container Engine for Kubernetes (OKE), the following quick actions for Micronaut are available: + +![Kubernetes quick actions](images/k8s_quick_actions.png) + +You should start by creating a Kubernetes deployment file that will be applied at the deployment stage. + +1. Go to View > Command Palette, search for "Kubernetes" and invoke the **Micronaut: Create Kubernetes Deployment Resource** action. It will start the "Create Kubernetes Deployment File" process. + +2. Pick the Docker repository. Since you are using Oracle Container Registry, select **OCIR + region name**. For example: + + ![Pick Docker repository](images/pick_docker_repository.png) + +3. Provide your Docker image name and version: + + ![Provide Docker image name and version](images/provide_image_name_version.png) + + Currently, available images are not automatically detected, so you need to type it manually. + Grab the image location from _gradle.build_ or _pom.xml_ you specified in the **Specify the Location for Docker Image in Oracle Container Registry** step. + +4. Then you are prompted to select the namespace. Choose default: + + ![Select namespace](images/select_namespace.png) + +5. Lastly, select a secret for your container registry in OCI (needed only if the Docker registry is private, described in the **Preparation** > **Log in to Docker** section): + + ![Select a secret for Docker registry](images/select_secret.png) + + The `Deploy.yaml` will be created. It will look similar to the following: + + ![Deploy.yaml](images/deploy_yaml.png) + +Now you are ready to deploy your Micronaut application to OKE. + +1. Go to View > Command Palette, search for **Micronaut: Deploy to Kubernetes** action and invoke it. + You could have skipped steps 1-3 from above, but if no Kubernetes deployment file exists, VS Code will suggest you to create one at this step. + +2. Once you invoke the action, the Output window will open and the "Starting deploy of project" message will be printed. + +When you hit this action, the project is packaged with Gradle/Maven to a runnable JAR file, built into a Docker image. +Then Docker pushes this image to the OKE repository (Oracle Container Registry), by applying the _deploy.yaml_ script. +The Kubernetes extension starts port forwarding to connect to the server running in a Kubernetes cluster (`kubectl port-forward` forwards a local port to a port on the Pod). +A direct URL to access your Micronaut REST application from a browser is printed. +Read more on Kubernetes port forwarding [here](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/). + +All this can be tracked in the Output window. +If the deployment succeeds, you should see a similar status bar: + +![Kubernetes deploy status](images/k8s_deply_output.png) + +To otherwise check the deployment's status, run: +```bash +kubectl get deployment +``` + +You can work on other projects, deploy them to another Kubernetes clusters, and they will all be deployed and running from Oracle Container Registry. + +## Debug Micronaut Applications in Remote Kubernetes Cluster + +In addition to being able to deploy and run Micronaut applications in Kubernetes, you can also debug your Java application in a cluster directly from VS. + +> Note: To allow complete Java debugging experience, you need to ensure the [GraalVM Extension Pack for Java](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm) is installed. It is not needed if you have installed [GraalVM Tools for Java Extension pack](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm-pack), it already includes a full-fledged support for the Java and Micronaut. + +With the connection made to a local port (thanks to [Kubernetes port forwarding feature](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/)), you can use your local workstation to debug the application that is running in the Pod. +Having set some breakpoints in your applciation, do the following to start debugging: + +1. Go to View > Command Palette, search for **Micronaut: Debug in Kubernetes** action and invoke it. +2. Confirm port forwarding. First time you start debugging your application deployed in Kubernetes, a popup window will open in the right bottom corner asking to confirm port forwarding. This will setup a `JAVA_TOOLS_OPTIONS` environment variable in the deployment script file. +3. Then you will be prompted to choose a port forwarding session: + + ![Choose a port forwarding session](images/k8s_port_forwarding.png) + +4. Connect the Kubernetes extension to your Kubernetes cluster using **Set Kubeconfig** action. +5. Click on Kubernetes icon in the left sidebar and select the node you are developing. +6. Right-click invoke action Debug (**Attach using Java 8+**): + +![Attach a remote debugger](images/attach-remote-debugger.png) From 6a64550a82d62d93a27c50208eeb542fb49d0e38 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 18 Oct 2021 14:38:00 +0200 Subject: [PATCH 510/681] Various improvements for the error handling. Fixed a race that could happen in the safepoint handling. --- .../posix/pthread/PthreadVMLockSupport.java | 5 +- .../core/windows/WindowsVMLockSupport.java | 5 +- .../svm/core/InvalidMethodPointerHandler.java | 4 +- .../oracle/svm/core/SubstrateDiagnostics.java | 2 +- .../svm/core/SubstrateSegfaultHandler.java | 2 +- .../graal/snippets/CEntryPointSnippets.java | 4 +- .../svm/core/jdk/VMErrorSubstitutions.java | 4 +- .../oracle/svm/core/thread/JavaThreads.java | 2 - .../com/oracle/svm/core/thread/Safepoint.java | 20 ++- .../com/oracle/svm/core/thread/VMThreads.java | 116 ++++++------------ .../svm/jni/functions/JNIFunctions.java | 6 +- 11 files changed, 73 insertions(+), 97 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java index f19e589eef9d..f473152e3073 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.posix.pthread; +import com.oracle.svm.core.stack.StackOverflowCheck; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.word.Word; @@ -166,7 +167,9 @@ protected static void checkResult(int result, String functionName) { * Functions are called very early and late during our execution, so there is not much * we can do when they fail. */ - VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); + VMThreads.SafepointBehavior.preventSafepoints(); + StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); + Log.log().string(functionName).string(" returned ").signed(result).newline(); ImageSingletons.lookup(LogHandler.class).fatalError(); } diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java index 44ddefc253e6..868f3f6f12c8 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.windows; +import com.oracle.svm.core.stack.StackOverflowCheck; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.word.Word; @@ -161,7 +162,9 @@ static void checkResult(int result, String functionName) { * Functions are called very early and late during our execution, so there is not much * we can do when they fail. */ - VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); + VMThreads.SafepointBehavior.preventSafepoints(); + StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); + int lastError = WinBase.GetLastError(); Log.log().string(functionName).string(" failed with error ").hex(lastError).newline(); ImageSingletons.lookup(LogHandler.class).fatalError(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java index d6061d66f714..7db44647c79d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java @@ -28,6 +28,7 @@ import java.lang.reflect.Method; +import com.oracle.svm.core.annotate.Uninterruptible; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.LogHandler; import org.graalvm.nativeimage.c.function.CodePointer; @@ -69,8 +70,9 @@ private static void methodPointerNotCompiledHandler() { failFatally(callerSP, callerIP, METHOD_POINTER_NOT_COMPILED_MSG); } + @Uninterruptible(reason = "Prevent safepoints until everything is set up for printing the fatal error.", calleeMustBe = false) private static void failFatally(Pointer callerSP, CodePointer callerIP, String message) { - VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); + VMThreads.SafepointBehavior.preventSafepoints(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); /* diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java index ff6ef10c845e..fcfae79277ce 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java @@ -617,7 +617,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev log.string("Threads:").indent(true); for (IsolateThread thread = VMThreads.firstThreadUnsafe(); thread.isNonNull(); thread = VMThreads.nextThread(thread)) { log.zhex(thread).spaces(1).string(VMThreads.StatusSupport.getStatusString(thread)); - int safepointBehavior = SafepointBehavior.getSafepointBehavior(thread); + int safepointBehavior = SafepointBehavior.getSafepointBehaviorVolatile(thread); if (safepointBehavior != SafepointBehavior.ALLOW_SAFEPOINT) { log.string(" (").string(SafepointBehavior.toString(safepointBehavior)).string(")"); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java index 94ac2f378480..369354fc0388 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java @@ -153,7 +153,7 @@ protected static boolean tryEnterIsolate(RegisterDumper.Context context) { @Uninterruptible(reason = "Must be uninterruptible until we get immune to safepoints.", calleeMustBe = false) @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in segfault handler.", overridesCallers = true) protected static void dump(PointerBase signalInfo, RegisterDumper.Context context) { - VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); + VMThreads.SafepointBehavior.preventSafepoints(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); dumpInterruptibly(signalInfo, context); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index ba44d90ffdc4..ad7c1d3dda11 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -71,7 +71,6 @@ import com.oracle.svm.core.RuntimeAssertionsSupport; import com.oracle.svm.core.SubstrateDiagnostics; import com.oracle.svm.core.SubstrateUtil; -import com.oracle.svm.core.annotate.RestrictHeapAccess; import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.c.CGlobalData; import com.oracle.svm.core.c.CGlobalDataFactory; @@ -564,10 +563,11 @@ public static int reportExceptionSnippet(Throwable exception) { @Uninterruptible(reason = "Avoid StackOverflowError and safepoints until they are disabled permanently", calleeMustBe = false) @SubstrateForeignCallTarget(stubCallingConvention = false) private static int reportException(Throwable exception) { - VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); + VMThreads.SafepointBehavior.preventSafepoints(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); logException(exception); + ImageSingletons.lookup(LogHandler.class).fatalError(); return CEntryPointErrors.UNSPECIFIED; // unreachable } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java index a6957ee1ee75..6604c9d85498 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java @@ -99,8 +99,10 @@ public class VMErrorSubstitutions { @Uninterruptible(reason = "Allow VMError to be used in uninterruptible code.") static RuntimeException shouldNotReachHere(CodePointer callerIP, String msg, Throwable ex) { ThreadStackPrinter.printBacktrace(); - VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); + + VMThreads.SafepointBehavior.preventSafepoints(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); + VMErrorSubstitutions.shutdown(callerIP, msg, ex); throw UnreachableNode.unreachable(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java index 65a1751c30ac..cf0e80f7bb46 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java @@ -36,7 +36,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import com.oracle.svm.core.thread.VMThreads.SafepointBehavior; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; @@ -57,7 +56,6 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.annotate.NeverInline; -import com.oracle.svm.core.annotate.RestrictHeapAccess; import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.heap.Heap; import com.oracle.svm.core.heap.ReferenceHandler; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java index 30bb4e0273b8..074076393a4e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java @@ -713,14 +713,22 @@ private static void waitForSafepoints(String reason) { continue; } - int safepointBehavior = SafepointBehavior.getSafepointBehavior(vmThread); + /*- + * The status must be read before the safepoint behavior to prevent races + * like the following: + * - thread A reads the safepoint behavior of thread B. + * - thread B sets the safepoint behavior to PREVENT_VM_FROM_REACHING_SAFEPOINT. + * - thread B sets the status to STATUS_IN_NATIVE. + * - thread A reads the status and the VM reaches a safepoint. + */ + int status = StatusSupport.getStatusVolatile(vmThread); + int safepointBehavior = SafepointBehavior.getSafepointBehaviorVolatile(vmThread); if (safepointBehavior == SafepointBehavior.PREVENT_VM_FROM_REACHING_SAFEPOINT) { notAtSafepoint++; - } else if (safepointBehavior == SafepointBehavior.IGNORE_THREAD_IN_SAFEPOINT_HANDLING) { + } else if (safepointBehavior == SafepointBehavior.THREAD_CRASHED) { ignoreSafepoints++; } else { assert safepointBehavior == SafepointBehavior.ALLOW_SAFEPOINT; - int status = StatusSupport.getStatusVolatile(vmThread); switch (status) { case StatusSupport.STATUS_IN_JAVA: case StatusSupport.STATUS_IN_VM: { @@ -864,15 +872,15 @@ public static int countingVMOperation() { int notAtSafepoint = 0; for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { - int safepointBehavior = SafepointBehavior.getSafepointBehavior(vmThread); + int safepointBehavior = SafepointBehavior.getSafepointBehaviorVolatile(vmThread); + int status = StatusSupport.getStatusVolatile(vmThread); if (safepointBehavior == SafepointBehavior.PREVENT_VM_FROM_REACHING_SAFEPOINT) { notAtSafepoint++; - } else if (safepointBehavior == SafepointBehavior.IGNORE_THREAD_IN_SAFEPOINT_HANDLING) { + } else if (safepointBehavior == SafepointBehavior.THREAD_CRASHED) { ignoreSafepoints += 1; } else { assert safepointBehavior == SafepointBehavior.ALLOW_SAFEPOINT; // Check if the thread is at a safepoint or in native code. - int status = StatusSupport.getStatusVolatile(vmThread); switch (status) { case StatusSupport.STATUS_IN_SAFEPOINT: atSafepoint += 1; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java index 1e5ee537db6e..e78ccd36a33c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java @@ -44,8 +44,6 @@ import org.graalvm.word.WordFactory; import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.annotate.NeverInline; -import com.oracle.svm.core.annotate.RestrictHeapAccess; import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.c.function.CEntryPointErrors; import com.oracle.svm.core.c.function.CFunctionOptions; @@ -86,8 +84,6 @@ public static VMThreads singleton() { * already acquired for safepoint reasons. *
  • Acquire the mutex outside of a VM operation but only execute uninterruptible code. This * is safe as the uninterruptible code cannot trigger a safepoint.
  • - *
  • Acquire the mutex from a thread that previously called - * {@link SafepointBehavior#setIgnoreThreadInSafepointHandling()}.
  • * * * Deadlock example 1: @@ -120,9 +116,7 @@ public static VMThreads singleton() { */ protected static final VMCondition THREAD_LIST_CONDITION = new VMCondition(THREAD_MUTEX); - /** - * The first element in the linked list of {@link IsolateThread}s. - */ + /** The first element in the linked list of {@link IsolateThread}s. */ private static IsolateThread head; /** * This field is used to guarantee that all isolate threads that were started by SVM have exited @@ -144,9 +138,7 @@ public static VMThreads singleton() { private static final FastThreadLocalWord OSThreadIdTL = FastThreadLocalFactory.createWord("VMThreads.OSThreadIdTL"); protected static final FastThreadLocalWord OSThreadHandleTL = FastThreadLocalFactory.createWord("VMThreads.OSThreadHandleTL"); public static final FastThreadLocalWord IsolateTL = FastThreadLocalFactory.createWord("VMThreads.IsolateTL"); - /** - * The highest stack address. - */ + /** The highest stack address. */ public static final FastThreadLocalWord StackBase = FastThreadLocalFactory.createWord("VMThreads.StackBase"); /** * The lowest stack address. Note that this value does not necessarily match the value that is @@ -165,17 +157,13 @@ public static boolean isInitialized() { return initializationState.get() >= STATE_INITIALIZED; } - /** - * Is threading being torn down? - */ + /** Is threading being torn down? */ @Uninterruptible(reason = "Called from uninterruptible code during tear down.") public static boolean isTearingDown() { return initializationState.get() >= STATE_TEARING_DOWN; } - /** - * Note that threading is being torn down. - */ + /** Note that threading is being torn down. */ static void setTearingDown() { initializationState.set(STATE_TEARING_DOWN); } @@ -594,40 +582,26 @@ public static boolean printLocationInfo(Log log, UnsignedWord value, boolean all * Access to platform-specific implementations. */ - /** - * A thread-local enum giving the thread status of a VMThread. And supporting methods. - */ + /** A thread-local enum giving the thread status of a VMThread. And supporting methods. */ public static class StatusSupport { - /** - * The status of a {@link IsolateThread}. - */ + /** The status of a {@link IsolateThread}. */ public static final FastThreadLocalInt statusTL = FastThreadLocalFactory.createInt("StatusSupport.statusTL").setMaxOffset(FastThreadLocal.FIRST_CACHE_LINE); - /** - * An illegal thread state for places where we need to pass a value. - */ + /** An illegal thread state for places where we need to pass a value. */ public static final int STATUS_ILLEGAL = -1; /** * {@link IsolateThread} memory has been allocated for the thread, but the thread is not on * the VMThreads list yet. */ public static final int STATUS_CREATED = 0; - /** - * The thread is running in Java code. - */ + /** The thread is running in Java code. */ public static final int STATUS_IN_JAVA = STATUS_CREATED + 1; - /** - * The thread has been requested to stop at a safepoint. - */ + /** The thread has been requested to stop at a safepoint. */ public static final int STATUS_IN_SAFEPOINT = STATUS_IN_JAVA + 1; - /** - * The thread is running in native code. - */ + /** The thread is running in native code. */ public static final int STATUS_IN_NATIVE = STATUS_IN_SAFEPOINT + 1; - /** - * The thread is running in trusted native code that was linked into the image. - */ + /** The thread is running in trusted native code that was linked into the image. */ public static final int STATUS_IN_VM = STATUS_IN_NATIVE + 1; private static final int MAX_STATUS = STATUS_IN_VM; @@ -651,9 +625,7 @@ private static String statusToString(int status) { /* Access methods to treat VMThreads.statusTL as a volatile int. */ - /** - * For debugging. - */ + /** For debugging. */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static String getStatusString(IsolateThread vmThread) { return statusToString(statusTL.getVolatile(vmThread)); @@ -679,16 +651,12 @@ public static void setStatusNative(IsolateThread vmThread) { statusTL.setVolatile(vmThread, STATUS_IN_NATIVE); } - /** - * There is no unguarded change to safepoint. - */ + /** There is no unguarded change to safepoint. */ public static boolean compareAndSetNativeToSafepoint(IsolateThread vmThread) { return statusTL.compareAndSet(vmThread, STATUS_IN_NATIVE, STATUS_IN_SAFEPOINT); } - /** - * An unguarded transition to Java. - */ + /** An unguarded transition to Java. */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void setStatusJavaUnguarded() { statusTL.setVolatile(STATUS_IN_JAVA); @@ -698,9 +666,7 @@ public static void setStatusVM() { statusTL.setVolatile(STATUS_IN_VM); } - /** - * A guarded transition from native to another status. - */ + /** A guarded transition from native to another status. */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean compareAndSetNativeToNewStatus(int newStatus) { return statusTL.compareAndSet(STATUS_IN_NATIVE, newStatus); @@ -780,7 +746,7 @@ public static void assertStatusVM() { // This method will be removed in GR-34435. @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void setStatusIgnoreSafepoints() { - SafepointBehavior.setIgnoreThreadInSafepointHandling(); + SafepointBehavior.markThreadAsCrashed(); } public static boolean isValidStatus(int status) { @@ -825,11 +791,7 @@ public static class SafepointBehavior { * The thread won't freeze at a safepoint and the safepoint handling will ignore the thread. * So, the VM will be able to reach a safepoint regardless of the status of this thread. */ - static final int IGNORE_THREAD_IN_SAFEPOINT_HANDLING = 2; - - public static boolean isIgnoredBySafepointHandling(IsolateThread vmThread) { - return safepointBehaviorTL.getVolatile(vmThread) == IGNORE_THREAD_IN_SAFEPOINT_HANDLING; - } + static final int THREAD_CRASHED = 2; @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean safepointChecksEnabled() { @@ -842,7 +804,7 @@ public static boolean safepointChecksEnabled(IsolateThread vmThread) { } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public static int getSafepointBehavior(IsolateThread vmThread) { + public static int getSafepointBehaviorVolatile(IsolateThread vmThread) { return safepointBehaviorTL.getVolatile(vmThread); } @@ -852,24 +814,26 @@ public static int getSafepointBehavior(IsolateThread vmThread) { * thread status). */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public static void setPreventVMFromReachingSafepoint() { + public static void preventSafepoints() { safepointBehaviorTL.setVolatile(PREVENT_VM_FROM_REACHING_SAFEPOINT); } /** - * Changes the safepoint behavior so that this thread won't freeze at a safepoint and the - * safepoint handling will ignore the thread. So, the VM will be able to reach a safepoint - * regardless of the status of this thread. + * Marks the thread as crashed. This method may only be used in places where it is no longer + * possible to safely detach a thread. + * + * Calling this method changes the safepoint behavior so that this thread won't freeze at a + * safepoint. The safepoint handling will ignore the thread so that the VM can reach a + * safepoint regardless of the status of this thread. * * Be careful with this. If a thread is ignored by the safepoint handling, it means that it - * can continue executing while a safepoint (and therefore a GC) is in progress. So, either - * prevent that a safepoint can be initiated (by holding the {@link #THREAD_MUTEX}) or make - * sure that this thread does not access any movable heap objects (even executing write - * barriers can already cause issues). + * can continue executing while a safepoint (and therefore a GC) is in progress. So, make + * sure that this thread does not allocate or access any movable heap objects (even + * executing write barriers can already cause issues). */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - static void setIgnoreThreadInSafepointHandling() { - safepointBehaviorTL.setVolatile(IGNORE_THREAD_IN_SAFEPOINT_HANDLING); + public static void markThreadAsCrashed() { + safepointBehaviorTL.setVolatile(THREAD_CRASHED); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @@ -879,8 +843,8 @@ public static String toString(int safepointBehavior) { return "ALLOW_SAFEPOINT"; case PREVENT_VM_FROM_REACHING_SAFEPOINT: return "PREVENT_VM_FROM_REACHING_SAFEPOINT"; - case IGNORE_THREAD_IN_SAFEPOINT_HANDLING: - return "IGNORE_THREAD_IN_SAFEPOINT_HANDLING"; + case THREAD_CRASHED: + return "THREAD_CRASHED"; default: return "Invalid safepoint behavior"; } @@ -892,18 +856,12 @@ public static String toString(int safepointBehavior) { */ public static class ActionOnTransitionToJavaSupport { - /** - * The actions to be performed. - */ + /** The actions to be performed. */ private static final FastThreadLocalInt actionTL = FastThreadLocalFactory.createInt("ActionOnTransitionToJavaSupport.actionTL"); - /** - * The thread does not need to take any action. - */ + /** The thread does not need to take any action. */ private static final int NO_ACTION = 0; - /** - * Code synchronization should be performed due to newly installed code. - */ + /** Code synchronization should be performed due to newly installed code. */ private static final int SYNCHRONIZE_CODE = NO_ACTION + 1; @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @@ -951,9 +909,7 @@ public static class ActionOnExitSafepointSupport { */ private static final int SWITCH_STACK = NO_ACTION + 1; - /** - * Target of stack switching. - */ + /** Target of stack switching. */ private static final FastThreadLocalWord returnSP = FastThreadLocalFactory.createWord("ActionOnExitSafepointSupport.returnSP"); private static final FastThreadLocalWord returnIP = FastThreadLocalFactory.createWord("ActionOnExitSafepointSupport.returnIP"); diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java index d6df15bb1676..f341108a898b 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java @@ -36,6 +36,7 @@ import java.nio.ByteBuffer; import java.util.Arrays; +import com.oracle.svm.core.stack.StackOverflowCheck; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import org.graalvm.nativeimage.ImageSingletons; @@ -825,14 +826,17 @@ static int ThrowNew(JNIEnvironment env, JNIObjectHandle clazzHandle, CCharPointe @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) @NeverInline("Access of caller frame.") + @Uninterruptible(reason = "Prevent safepoints until everything is set up for the fatal error printing.", calleeMustBe = false) static void FatalError(JNIEnvironment env, CCharPointer message) { + VMThreads.SafepointBehavior.preventSafepoints(); + StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); + CodePointer callerIP = KnownIntrinsics.readReturnAddress(); LogHandler logHandler = ImageSingletons.lookup(LogHandler.class); Log log = Log.enterFatalContext(logHandler, callerIP, CTypeConversion.toJavaString(message), null); if (log != null) { try { log.string("Fatal error reported via JNI: ").string(message).newline(); - VMThreads.SafepointBehavior.setPreventVMFromReachingSafepoint(); SubstrateDiagnostics.printFatalError(log, KnownIntrinsics.readCallerStackPointer(), callerIP); } catch (Throwable ignored) { /* From 1d83777fc68b0343be5dd036a708e08a106f24cd Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Mon, 18 Oct 2021 19:04:21 +0200 Subject: [PATCH 511/681] [GR-34556] Fixed libgraal gate. --- .../com/oracle/truffle/api/test/polyglot/LoggingTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LoggingTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LoggingTest.java index 088317f22518..d5d2559e2a82 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LoggingTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LoggingTest.java @@ -413,10 +413,10 @@ public boolean test(final LoggingContext context, final TruffleLogger[] loggers) return false; } }; - final ByteArrayOutputStream err = new ByteArrayOutputStream(); - try (Context ctx1 = Context.newBuilder().err(err).build()) { + final ByteArrayOutputStream logStream = new ByteArrayOutputStream(); + try (Context ctx1 = Context.newBuilder().logHandler(logStream).build()) { ctx1.eval(LoggingLanguageFirst.ID, ""); - final String output = new String(err.toByteArray()); + final String output = new String(logStream.toByteArray()); Assert.assertTrue(output, output.indexOf(expected) > 0); } } From cd0c592cc6bc1a95039ab5034d402cdad9d4a6e2 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 14 Oct 2021 17:00:32 +0200 Subject: [PATCH 512/681] Fold extended loads into AArch64Move.LoadOp and pass around access size in more places. --- .../AArch64ArithmeticLIRGenerator.java | 24 +-- .../core/aarch64/AArch64MoveFactory.java | 5 +- .../lir/aarch64/AArch64ControlFlow.java | 2 +- .../compiler/lir/aarch64/AArch64Move.java | 204 ++++++++++-------- .../aarch64/AArch64RestoreRegistersOp.java | 3 +- .../lir/aarch64/AArch64SaveRegistersOp.java | 3 +- .../compiler/lir/aarch64/AArch64Unary.java | 107 --------- .../lir/aarch64/AArch64ZapRegistersOp.java | 4 +- .../lir/aarch64/AArch64ZapStackOp.java | 4 +- .../aarch64/SubstrateAArch64Backend.java | 16 +- .../graal/amd64/SubstrateAMD64Backend.java | 16 +- .../JNIPrimitiveArrayOperationMethod.java | 4 +- 12 files changed, 172 insertions(+), 220 deletions(-) delete mode 100644 compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java diff --git a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java index 4843f0724b70..a9f8c5d91238 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java @@ -56,7 +56,6 @@ import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; import org.graalvm.compiler.lir.aarch64.AArch64ReinterpretOp; -import org.graalvm.compiler.lir.aarch64.AArch64Unary; import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; @@ -117,23 +116,16 @@ protected Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlag } } - public Value emitExtendMemory(boolean isSigned, AArch64Kind memoryKind, int resultBits, AArch64AddressValue address, LIRFrameState state) { - // Issue a zero extending load of the proper bit size and set the result to - // the proper kind. + public Value emitExtendMemory(boolean isSigned, AArch64Kind accessKind, int resultBits, AArch64AddressValue address, LIRFrameState state) { + /* + * Issue an extending load of the proper bit size and set the result to the proper kind. + */ + GraalError.guarantee(accessKind.isInteger(), "can only extend integer kinds"); Variable result = getLIRGen().newVariable(LIRKind.value(resultBits == 32 ? AArch64Kind.DWORD : AArch64Kind.QWORD)); - int targetSize = resultBits <= 32 ? 32 : 64; - switch (memoryKind) { - case BYTE: - case WORD: - case DWORD: - case QWORD: - getLIRGen().append(new AArch64Unary.MemoryOp(isSigned, targetSize, - memoryKind.getSizeInBytes() * Byte.SIZE, result, address, state)); - break; - default: - throw GraalError.shouldNotReachHere(); - } + int dstBitSize = resultBits <= 32 ? 32 : 64; + AArch64Move.ExtendKind extend = isSigned ? AArch64Move.ExtendKind.SIGN_EXTEND : AArch64Move.ExtendKind.ZERO_EXTEND; + getLIRGen().append(new AArch64Move.LoadOp(accessKind, dstBitSize, extend, result, address, state)); return result; } diff --git a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java index 2fc3878e3145..11c042c55f27 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadAddressOp; import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory; +import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; @@ -59,14 +60,14 @@ public LIRInstruction createMove(AllocatableValue dst, Value src) { if (srcIsSlot && dstIsSlot) { throw GraalError.shouldNotReachHere(src.getClass() + " " + dst.getClass()); } else { - return new AArch64Move.Move(dst, (AllocatableValue) src); + return new AArch64Move.Move((AArch64Kind) dst.getPlatformKind(), dst, (AllocatableValue) src); } } } @Override public LIRInstruction createStackMove(AllocatableValue result, AllocatableValue input) { - return new AArch64Move.Move(result, input); + return new AArch64Move.Move((AArch64Kind) result.getPlatformKind(), result, input); } @Override diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java index 105d18685613..360253ba167c 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java @@ -370,7 +370,7 @@ private static void emitCompareHelper(CompilationResultBuilder crb, AArch64Macro } else { try (ScratchRegister scratch = masm.getScratchRegister()) { Register scratchReg = scratch.getRegister(); - AArch64Move.const2reg(crb, masm, scratchReg, jc); + AArch64Move.const2reg((AArch64Kind) key.getPlatformKind(), crb, masm, scratchReg, jc); masm.cmp(cmpSize, asRegister(key), scratchReg); } } diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java index d68cc6521533..e75a5e0b09c5 100755 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java @@ -28,7 +28,6 @@ import static jdk.vm.ci.aarch64.AArch64.SIMD; import static jdk.vm.ci.aarch64.AArch64.sp; import static jdk.vm.ci.aarch64.AArch64.zr; -import static jdk.vm.ci.code.ValueUtil.asAllocatableValue; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.asStackSlot; import static jdk.vm.ci.code.ValueUtil.isRegister; @@ -71,7 +70,7 @@ import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.PlatformKind; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; public class AArch64Move { @@ -90,11 +89,11 @@ public LoadInlineConstant(JavaConstant constant, AllocatableValue result) { @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + AArch64Kind moveKind = (AArch64Kind) result.getPlatformKind(); if (isRegister(result)) { - const2reg(crb, masm, asRegister(result), constant); + const2reg(moveKind, crb, masm, asRegister(result), constant); } else if (isStackSlot(result)) { - StackSlot slot = asStackSlot(result); - const2stack(crb, masm, slot, constant); + const2stack(moveKind, crb, masm, asStackSlot(result), constant); } } @@ -116,16 +115,22 @@ public static class Move extends AArch64LIRInstruction implements ValueMoveOp { @Def({REG, STACK, HINT}) protected AllocatableValue result; @Use({REG, STACK}) protected AllocatableValue input; - public Move(AllocatableValue result, AllocatableValue input) { + private AArch64Kind moveKind; + + public Move(AArch64Kind moveKind, AllocatableValue result, AllocatableValue input) { super(TYPE); this.result = result; this.input = input; + this.moveKind = moveKind; + int resultSize = result.getPlatformKind().getSizeInBytes(); + int inputSize = input.getPlatformKind().getSizeInBytes(); + assert resultSize == moveKind.getSizeInBytes() && resultSize <= inputSize; assert !(isStackSlot(result) && isStackSlot(input)); } @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - move(crb, masm, getResult(), getInput()); + move(moveKind, crb, masm, getResult(), getInput()); } @Override @@ -230,17 +235,17 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { abstract static class MemOp extends AArch64LIRInstruction implements StandardOp.ImplicitNullCheck { - protected final AArch64Kind kind; + protected final AArch64Kind accessKind; @Use({COMPOSITE}) protected AArch64AddressValue addressValue; @State protected LIRFrameState state; - MemOp(LIRInstructionClass c, AArch64Kind kind, AArch64AddressValue address, LIRFrameState state) { + MemOp(LIRInstructionClass c, AArch64Kind accessKind, AArch64AddressValue address, LIRFrameState state) { super(c); int size = address.getBitMemoryTransferSize(); - assert size == AArch64Address.ANY_SIZE || size == kind.getSizeInBytes() * Byte.SIZE; + assert size == AArch64Address.ANY_SIZE || size == accessKind.getSizeInBytes() * Byte.SIZE; - this.kind = kind; + this.accessKind = accessKind; this.addressValue = address; this.state = state; } @@ -275,28 +280,68 @@ public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int i } } - public static final class LoadOp extends MemOp { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LoadOp.class); + public enum ExtendKind { + NONE, + ZERO_EXTEND, + SIGN_EXTEND; + } - @Def protected AllocatableValue result; + abstract static class ExtendableLoadOp extends MemOp { - public LoadOp(AArch64Kind kind, AllocatableValue result, AArch64AddressValue address, LIRFrameState state) { - super(TYPE, kind, address, state); + @Def({REG}) protected AllocatableValue result; + + protected int dstBitSize; + protected ExtendKind extend; + + ExtendableLoadOp(LIRInstructionClass c, AArch64Kind kind, int dstBitSize, ExtendKind extend, AllocatableValue result, AArch64AddressValue address, + LIRFrameState state) { + super(c, kind, address, state); + this.dstBitSize = dstBitSize; + this.extend = extend; this.result = result; } + } + + public static final class LoadOp extends ExtendableLoadOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LoadOp.class); + + public LoadOp(AArch64Kind accessKind, AllocatableValue result, AArch64AddressValue address, LIRFrameState state) { + this(accessKind, accessKind.getSizeInBytes() * Byte.SIZE, ExtendKind.NONE, result, address, state); + } + + public LoadOp(AArch64Kind accessKind, int dstBitSize, ExtendKind extend, AllocatableValue result, AArch64AddressValue address, LIRFrameState state) { + super(TYPE, accessKind, dstBitSize, extend, result, address, state); + } @Override protected void emitMemAccess(CompilationResultBuilder crb, AArch64MacroAssembler masm) { AArch64Address address = addressValue.toAddress(); Register dst = asRegister(result); - int destSize = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; - int srcSize = kind.getSizeInBytes() * Byte.SIZE; - if (kind.isInteger()) { - masm.ldr(srcSize, dst, address); + int srcBitSize = accessKind.getSizeInBytes() * Byte.SIZE; + if (accessKind.isInteger()) { + switch (extend) { + case NONE: + assert dstBitSize == srcBitSize; + masm.ldr(srcBitSize, dst, address); + break; + case ZERO_EXTEND: + assert dstBitSize >= srcBitSize; + // ldr zeros out remaining bits + masm.ldr(srcBitSize, dst, address); + break; + case SIGN_EXTEND: + assert dstBitSize >= srcBitSize; + // ldrs will sign extend value to required length + masm.ldrs(dstBitSize, srcBitSize, dst, address); + break; + default: + throw GraalError.shouldNotReachHere(); + } } else { - assert srcSize == destSize; - masm.fldr(srcSize, dst, address); + assert extend == ExtendKind.NONE; + assert srcBitSize == dstBitSize && dstBitSize == result.getPlatformKind().getSizeInBytes() * Byte.SIZE; + masm.fldr(srcBitSize, dst, address); } } } @@ -351,7 +396,7 @@ public StoreOp(AArch64Kind kind, AArch64AddressValue address, AllocatableValue i @Override protected void emitMemAccess(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - emitStore(crb, masm, kind, addressValue.toAddress(), input); + emitStore(crb, masm, accessKind, addressValue.toAddress(), input); } } @@ -370,7 +415,7 @@ public StoreConstantOp(AArch64Kind kind, AArch64AddressValue address, JavaConsta @Override public void emitMemAccess(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - emitStore(crb, masm, kind, addressValue.toAddress(), zr.asValue(LIRKind.combine(addressValue))); + emitStore(crb, masm, accessKind, addressValue.toAddress(), zr.asValue(LIRKind.combine(addressValue))); } } @@ -458,26 +503,28 @@ private static void emitStore(@SuppressWarnings("unused") CompilationResultBuild } } - private static void move(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, Value input) { + private static void move(AArch64Kind moveKind, CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, Value input) { if (isRegister(input)) { + Register src = asRegister(input); if (isRegister(result)) { - reg2reg(crb, masm, result, asAllocatableValue(input)); + reg2reg(moveKind, masm, asRegister(result), src); } else if (isStackSlot(result)) { - reg2stack(crb, masm, asStackSlot(result), asRegister(input)); + reg2stack(moveKind, crb, masm, asStackSlot(result), src); } else { throw GraalError.shouldNotReachHere(); } } else if (isStackSlot(input)) { + StackSlot src = asStackSlot(input); if (isRegister(result)) { - stack2reg(crb, masm, result, asStackSlot(input)); + stack2reg(moveKind, crb, masm, asRegister(result), src); } else if (isStackSlot(result)) { - emitStackMove(crb, masm, result, input); + stack2stack(moveKind, crb, masm, asStackSlot(result), src); } else { throw GraalError.shouldNotReachHere(); } } else if (isJavaConstant(input)) { if (isRegister(result)) { - const2reg(crb, masm, asRegister(result), asJavaConstant(input)); + const2reg(moveKind, crb, masm, asRegister(result), asJavaConstant(input)); } else { throw GraalError.shouldNotReachHere(); } @@ -486,51 +533,43 @@ private static void move(CompilationResultBuilder crb, AArch64MacroAssembler mas } } - private static void emitStackMove(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, Value input) { + private static void stack2stack(AArch64Kind moveKind, CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot result, StackSlot input) { try (ScratchRegister r1 = masm.getScratchRegister()) { try (ScratchRegister r2 = masm.getScratchRegister()) { Register rscratch1 = r1.getRegister(); Register rscratch2 = r2.getRegister(); - // use the slot kind to define the operand size - PlatformKind kind = input.getPlatformKind(); - final int size = kind.getSizeInBytes() * Byte.SIZE; + final int size = moveKind.getSizeInBytes() * Byte.SIZE; // Always perform stack -> stack copies through integer registers crb.blockComment("[stack -> stack copy]"); - AArch64Address src = loadStackSlotAddress(crb, masm, asStackSlot(input), rscratch2); + AArch64Address src = loadStackSlotAddress(size, crb, masm, input, rscratch2); masm.ldr(size, rscratch1, src); - AArch64Address dst = loadStackSlotAddress(crb, masm, asStackSlot(result), rscratch2); + AArch64Address dst = loadStackSlotAddress(size, crb, masm, result, rscratch2); masm.str(size, rscratch1, dst); } } } - private static void reg2reg(@SuppressWarnings("unused") CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { - Register dst = asRegister(result); - Register src = asRegister(input); - - if (src.equals(dst)) { + private static void reg2reg(AArch64Kind moveKind, AArch64MacroAssembler masm, Register result, Register input) { + if (input.equals(result)) { return; } - AArch64Kind inputKind = (AArch64Kind) input.getPlatformKind(); - AArch64Kind resultKind = (AArch64Kind) result.getPlatformKind(); - final int size = Math.max(Math.min(inputKind.getSizeInBytes(), resultKind.getSizeInBytes()) * Byte.SIZE, 32); - if (dst.getRegisterCategory().equals(CPU) && src.getRegisterCategory().equals(CPU)) { - masm.mov(size, dst, src); + final int size = moveKind.getSizeInBytes() * Byte.SIZE; + assert size == 32 || size == 64 || size == 128; + if (result.getRegisterCategory().equals(CPU) && input.getRegisterCategory().equals(CPU)) { + masm.mov(size, result, input); } else if (size == 128) { - assert dst.getRegisterCategory().equals(SIMD) && src.getRegisterCategory().equals(SIMD); - masm.neon.moveVV(AArch64ASIMDAssembler.ASIMDSize.FullReg, dst, src); + assert result.getRegisterCategory().equals(SIMD) && input.getRegisterCategory().equals(SIMD); + masm.neon.moveVV(AArch64ASIMDAssembler.ASIMDSize.FullReg, result, input); } else { - masm.fmov(size, dst, src); + masm.fmov(size, result, input); } } - static void reg2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot result, Register input) { + static void reg2stack(AArch64Kind moveKind, CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot result, Register input) { try (ScratchRegister scratch = masm.getScratchRegister()) { - AArch64Address dest = loadStackSlotAddress(crb, masm, result, scratch.getRegister()); - // use the slot kind to define the operand size - AArch64Kind kind = (AArch64Kind) result.getPlatformKind(); - final int size = kind.getSizeInBytes() * Byte.SIZE; + final int size = moveKind.getSizeInBytes() * Byte.SIZE; + AArch64Address dest = loadStackSlotAddress(size, crb, masm, result, scratch.getRegister()); if (input.getRegisterCategory().equals(CPU)) { masm.str(size, input, dest); } else { @@ -540,25 +579,31 @@ static void reg2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, } } - static void stack2reg(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, StackSlot input) { - AArch64Kind kind = (AArch64Kind) input.getPlatformKind(); - // use the slot kind to define the operand size - final int size = kind.getSizeInBytes() * Byte.SIZE; - Register dst = asRegister(result); - if (dst.getRegisterCategory().equals(CPU)) { - AArch64Address src = loadStackSlotAddress(crb, masm, input, result); - masm.ldr(size, dst, src); + static void stack2reg(AArch64Kind moveKind, CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, StackSlot input) { + /* + * Since AArch64ArithmeticLIRGenerator.emitNarrow creates a move from a QWORD to DWORD, it + * is possible that the stack slot is an aligned QWORD while the moveKind is a DWORD. When + * this happens, it is better treat the move as a QWORD, as this allows an immediate + * addressing mode to be used more often. + */ + final int size = input.getPlatformKind().getSizeInBytes() * Byte.SIZE; + assert moveKind.getSizeInBytes() * Byte.SIZE <= size; + if (result.getRegisterCategory().equals(CPU)) { + AArch64Address src = loadStackSlotAddress(size, crb, masm, input, result); + masm.ldr(size, result, src); } else { - assert dst.getRegisterCategory().equals(SIMD); + assert result.getRegisterCategory().equals(SIMD); try (ScratchRegister sc = masm.getScratchRegister()) { - AArch64Address src = loadStackSlotAddress(crb, masm, input, sc.getRegister()); - masm.fldr(size, dst, src); + AArch64Address src = loadStackSlotAddress(size, crb, masm, input, sc.getRegister()); + masm.fldr(size, result, src); } } } - static void const2reg(CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, JavaConstant input) { - switch (input.getJavaKind().getStackKind()) { + static void const2reg(AArch64Kind moveKind, CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, JavaConstant input) { + JavaKind stackKind = input.getJavaKind().getStackKind(); + assert stackKind.isObject() || moveKind.getSizeInBytes() <= stackKind.getByteCount(); + switch (stackKind) { case Int: masm.mov(result, input.asInt()); break; @@ -611,14 +656,14 @@ static void const2reg(CompilationResultBuilder crb, AArch64MacroAssembler masm, } } - static void const2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, Value result, JavaConstant constant) { + static void const2stack(AArch64Kind moveKind, CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot result, JavaConstant constant) { if (constant.isNull() && !crb.mustReplaceWithUncompressedNullRegister(constant)) { - reg2stack(crb, masm, asStackSlot(result), zr); + reg2stack(moveKind, crb, masm, result, zr); } else { try (ScratchRegister sc = masm.getScratchRegister()) { Register scratch = sc.getRegister(); - const2reg(crb, masm, scratch, constant); - reg2stack(crb, masm, asStackSlot(result), scratch); + const2reg(moveKind, crb, masm, scratch, constant); + reg2stack(moveKind, crb, masm, result, scratch); } } } @@ -632,19 +677,12 @@ static void const2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm * transfersize, which gives us a 15-bit address range (for longs/doubles) respectively a 14-bit * range (for everything else). * - * @param scratch Scratch register that can be used to load address. If Value.ILLEGAL this - * instruction fails if we try to access a StackSlot that is too large to be loaded - * directly. + * @param scratchReg Scratch register that can be used to load address. * @return AArch64Address of given StackSlot. Uses scratch register if necessary to do so. */ - private static AArch64Address loadStackSlotAddress(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot slot, AllocatableValue scratch) { - Register scratchReg = Value.ILLEGAL.equals(scratch) ? zr : asRegister(scratch); - return loadStackSlotAddress(crb, masm, slot, scratchReg); - } - - private static AArch64Address loadStackSlotAddress(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot slot, Register scratchReg) { + private static AArch64Address loadStackSlotAddress(int size, CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot slot, Register scratchReg) { int displacement = crb.frameMap.offsetForStackSlot(slot); - int size = slot.getPlatformKind().getSizeInBytes() * Byte.SIZE; + assert size == slot.getPlatformKind().getSizeInBytes() * Byte.SIZE; return masm.makeAddress(size, sp, displacement, scratchReg); } @@ -693,10 +731,6 @@ protected final Register getBaseRegister() { protected final int getShift() { return encoding.getShift(); } - - protected final void move(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - AArch64Move.move(crb, masm, result, input); - } } public static class CompressPointerOp extends PointerCompressionOp { diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64RestoreRegistersOp.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64RestoreRegistersOp.java index edc9b5ba39aa..b0c44ef3bea2 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64RestoreRegistersOp.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64RestoreRegistersOp.java @@ -31,6 +31,7 @@ import java.util.Arrays; +import jdk.vm.ci.aarch64.AArch64Kind; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LIRValueUtil; @@ -75,7 +76,7 @@ protected Register[] getSavedRegisters() { } protected void restoreRegister(CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, StackSlot input) { - AArch64Move.stack2reg(crb, masm, result.asValue(), input); + AArch64Move.stack2reg((AArch64Kind) input.getPlatformKind(), crb, masm, result, input); } @Override diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SaveRegistersOp.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SaveRegistersOp.java index ea22ff8a131d..a81c4fd6a5a3 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SaveRegistersOp.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SaveRegistersOp.java @@ -27,6 +27,7 @@ import static jdk.vm.ci.code.ValueUtil.asStackSlot; import static jdk.vm.ci.code.ValueUtil.isStackSlot; +import jdk.vm.ci.aarch64.AArch64Kind; import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; @@ -56,7 +57,7 @@ public AArch64SaveRegistersOp(Register[] savedRegisters, AllocatableValue[] save } protected void saveRegister(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot result, Register input) { - AArch64Move.reg2stack(crb, masm, result, input); + AArch64Move.reg2stack((AArch64Kind) result.getPlatformKind(), crb, masm, result, input); } @Override diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java deleted file mode 100644 index 1b95d3875941..000000000000 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2015, 2019, 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 org.graalvm.compiler.lir.aarch64; - -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; - -import org.graalvm.compiler.asm.aarch64.AArch64Address; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.lir.LIRFrameState; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.ImplicitNullCheck; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.Value; - -/** - * AARCH64 LIR instructions that have one input and one output. - */ -public class AArch64Unary { - - /** - * Instruction with a {@link AArch64AddressValue memory} operand. - */ - public static class MemoryOp extends AArch64LIRInstruction implements ImplicitNullCheck { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MemoryOp.class); - - private final boolean isSigned; - - @Def({REG}) protected AllocatableValue result; - @Use({COMPOSITE}) protected AArch64AddressValue input; - - @State protected LIRFrameState state; - - private int targetSize; - private int srcSize; - - public MemoryOp(boolean isSigned, int targetSize, int srcSize, AllocatableValue result, AArch64AddressValue input, LIRFrameState state) { - super(TYPE); - this.targetSize = targetSize; - this.srcSize = srcSize; - this.isSigned = isSigned; - this.result = result; - this.input = input; - this.state = state; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - int prePosition = masm.position(); - AArch64Address address = input.toAddress(); - Register dst = asRegister(result); - if (isSigned) { - masm.ldrs(targetSize, srcSize, dst, address); - } else { - masm.ldr(srcSize, dst, address); - } - - if (state != null) { - int implicitExceptionPosition = prePosition; - // Adjust implicit exception position if this ldr/str has been merged to ldp/stp. - if (prePosition == masm.position() && masm.isImmLoadStoreMerged()) { - implicitExceptionPosition = prePosition - 4; - if (crb.isImplicitExceptionExist(implicitExceptionPosition)) { - return; - } - } - crb.recordImplicitException(implicitExceptionPosition, state); - } - } - - @Override - public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { - int displacement = input.getDisplacement(); - if (state == null && value.equals(input.getBase()) && input.getOffset().equals(Value.ILLEGAL) && displacement >= 0 && displacement < implicitNullCheckLimit) { - state = nullCheckState; - return true; - } - return false; - } - } -} diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ZapRegistersOp.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ZapRegistersOp.java index 296ada715090..7418ec28cd49 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ZapRegistersOp.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ZapRegistersOp.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.lir.aarch64; +import jdk.vm.ci.aarch64.AArch64Kind; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; @@ -60,7 +61,8 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { for (int i = 0; i < zappedRegisters.length; i++) { Register reg = zappedRegisters[i]; if (reg != null) { - AArch64Move.const2reg(crb, masm, reg, zapValues[i]); + AArch64Kind moveKind = (AArch64Kind) crb.target.arch.getPlatformKind(zapValues[i].getJavaKind()); + AArch64Move.const2reg(moveKind, crb, masm, reg, zapValues[i]); } } } diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ZapStackOp.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ZapStackOp.java index 5e267a5a63ed..4a5534f916bd 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ZapStackOp.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ZapStackOp.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.meta.JavaConstant; @@ -59,7 +60,8 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { for (int i = 0; i < zappedStack.length; i++) { StackSlot slot = zappedStack[i]; if (slot != null) { - AArch64Move.const2stack(crb, masm, slot, zapValues[i]); + AArch64Kind moveKind = (AArch64Kind) crb.target.arch.getPlatformKind(zapValues[i].getJavaKind()); + AArch64Move.const2stack(moveKind, crb, masm, slot, zapValues[i]); } } } diff --git a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java index f710a2bccc67..6dc8e9d46846 100755 --- a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java @@ -821,10 +821,22 @@ public boolean allowConstantToStackMove(Constant constant) { return super.allowConstantToStackMove(constant); } + private static JavaConstant getZeroConstant(AllocatableValue dst) { + int size = dst.getPlatformKind().getSizeInBytes() * Byte.SIZE; + switch (size) { + case 32: + return JavaConstant.INT_0; + case 64: + return JavaConstant.LONG_0; + default: + throw VMError.shouldNotReachHere(); + } + } + @Override public AArch64LIRInstruction createLoad(AllocatableValue dst, Constant src) { if (CompressedNullConstant.COMPRESSED_NULL.equals(src)) { - return super.createLoad(dst, JavaConstant.INT_0); + return super.createLoad(dst, getZeroConstant(dst)); } else if (src instanceof SubstrateObjectConstant) { return loadObjectConstant(dst, (SubstrateObjectConstant) src); } @@ -834,7 +846,7 @@ public AArch64LIRInstruction createLoad(AllocatableValue dst, Constant src) { @Override public LIRInstruction createStackLoad(AllocatableValue dst, Constant src) { if (CompressedNullConstant.COMPRESSED_NULL.equals(src)) { - return super.createStackLoad(dst, JavaConstant.INT_0); + return super.createStackLoad(dst, getZeroConstant(dst)); } else if (src instanceof SubstrateObjectConstant) { return loadObjectConstant(dst, (SubstrateObjectConstant) src); } diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java index 2d87bba507d3..635736397285 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java @@ -901,10 +901,22 @@ public boolean allowConstantToStackMove(Constant constant) { return super.allowConstantToStackMove(constant); } + private static JavaConstant getZeroConstant(AllocatableValue dst) { + int size = dst.getPlatformKind().getSizeInBytes() * Byte.SIZE; + switch (size) { + case 32: + return JavaConstant.INT_0; + case 64: + return JavaConstant.LONG_0; + default: + throw VMError.shouldNotReachHere(); + } + } + @Override public AMD64LIRInstruction createLoad(AllocatableValue dst, Constant src) { if (CompressedNullConstant.COMPRESSED_NULL.equals(src)) { - return super.createLoad(dst, JavaConstant.INT_0); + return super.createLoad(dst, getZeroConstant(dst)); } else if (src instanceof SubstrateObjectConstant) { return loadObjectConstant(dst, (SubstrateObjectConstant) src); } @@ -914,7 +926,7 @@ public AMD64LIRInstruction createLoad(AllocatableValue dst, Constant src) { @Override public LIRInstruction createStackLoad(AllocatableValue dst, Constant src) { if (CompressedNullConstant.COMPRESSED_NULL.equals(src)) { - return super.createStackLoad(dst, JavaConstant.INT_0); + return super.createStackLoad(dst, getZeroConstant(dst)); } else if (src instanceof SubstrateObjectConstant) { return loadObjectConstant(dst, (SubstrateObjectConstant) src); } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNIPrimitiveArrayOperationMethod.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNIPrimitiveArrayOperationMethod.java index f0ecdba39d55..37a78674568e 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNIPrimitiveArrayOperationMethod.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNIPrimitiveArrayOperationMethod.java @@ -262,7 +262,9 @@ private ValueNode newArray(HostedProviders providers, JNIGraphKit kit, List Date: Mon, 18 Oct 2021 21:10:36 +0300 Subject: [PATCH 513/681] Follow Gilles D. comments; Sync up with vscode-extensions repo --- docs/enterprise-overview/architecture-overview.md | 2 +- docs/tools/vscode/graalvm/README.md | 5 +++-- docs/tools/vscode/graalvm/visualvm-integration.md | 2 +- docs/tools/vscode/micronaut/README.md | 12 ++++++------ docs/tools/vscode/micronaut/k8s-support.md | 11 +++++++---- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/enterprise-overview/architecture-overview.md b/docs/enterprise-overview/architecture-overview.md index a5227e09ad76..86be95af91ad 100644 --- a/docs/enterprise-overview/architecture-overview.md +++ b/docs/enterprise-overview/architecture-overview.md @@ -15,7 +15,7 @@ The conceptual overview and advantages of GraalVM Enterprise are described on th * [GraalVM Enterprise Architecture](#graalvm-enterprise-architecture) * [Runtime Modes](#runtime-modes) * [Available Distributions](#available-distributions) -* [Supported Platforms](#supported-platforms) +* [Certified Platforms](#certified-platforms) * [Distribution Components List](#distribution-components-list) * [Licensing and Support](#licensing-and-support) * [Experimental and Early Adopter Features](#experimental-and-early-adopter-features) diff --git a/docs/tools/vscode/graalvm/README.md b/docs/tools/vscode/graalvm/README.md index f2c752c46310..28dc70cc90e9 100644 --- a/docs/tools/vscode/graalvm/README.md +++ b/docs/tools/vscode/graalvm/README.md @@ -209,6 +209,7 @@ It can be done by providing following switches for the `native-image` builder: - `-g -O0` or - `-H:Debug=2 -H:Optimize=0`. + The resulting images will contain debug records in a format `gdb` debugger understands. ### Debug Native Image “Real” Code @@ -233,7 +234,7 @@ This brings the visual Java tooling to VS Code. ![VisualVM and VS Code Integration](images/vscode_visualvm.png) To get started, you need to get the latest stable GraalVM release using the **Download & Install GraalVM** action from the **Gr** activity view, as described in the [Installation and Setup](README.md#installation-and-setup) section. -Make sure the GraalVM is set as the **active**. +Make sure the GraalVM is set as the **active** installation. Once a GraalVM installation is set as active, the Command Palette contains the following commands related to VisualVM: @@ -252,7 +253,7 @@ Follow these steps to start VisualVM automatically from within the VS Code: 4. Select the **Launch VisualVM & Java 8+ Application** launch configuration in the Run and Debug activity. Use the Start Debugging or Run Without Debugging action to start the current project. -While the project is starting, the Process node in VisualVM pane displays project name with a "pid pending" label. +While the project is starting, the Process node in VisualVM pane displays the project name with a "pid pending" label. Once the project process starts, the Process node is updated to show its process ID (PID) and the action defined in step 3 is performed. > Note: This feature was introduced with the GraalVM 21.2.0 release. Please make sure to get the latest GraalVM Tools for Java extension from the VS Code Marketplace, preferably by downloading the [GraalVM Extension Pack for Java](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm-pack). diff --git a/docs/tools/vscode/graalvm/visualvm-integration.md b/docs/tools/vscode/graalvm/visualvm-integration.md index 456c96edf047..501d645fc309 100644 --- a/docs/tools/vscode/graalvm/visualvm-integration.md +++ b/docs/tools/vscode/graalvm/visualvm-integration.md @@ -5,7 +5,7 @@ link_title: VisualVM and VS Code Integration permalink: /tools/vscode/graalvm/visualvm-integration/ --- -# VisualVM and VS Code Integration +## VisualVM and VS Code Integration As of GraalVM 21.2.0, the GraalVM Tools for Java extension introduced a new feature in this version - the integration with VisualVM (https://visualvm.github.io), which is the all-in-one Java (and polyglot) monitoring and troubleshooting tool. This brings the visual Java tooling to VS Code. diff --git a/docs/tools/vscode/micronaut/README.md b/docs/tools/vscode/micronaut/README.md index 3a8afcaac37b..883beb4b0e24 100644 --- a/docs/tools/vscode/micronaut/README.md +++ b/docs/tools/vscode/micronaut/README.md @@ -11,9 +11,9 @@ permalink: /tools/vscode/micronaut-extension/ The extension is Technology Preview. The extension also enables the [Micronaut Launch](https://micronaut.io/launch/) application that allows you to create Micronaut projects through an interface inside VS Code, in addition to using the console CLI. -There are, of course, other ways to create a new Micronaut application. If you provide a path to the [Micronaut CLI installation](https://micronaut-projects.github.io/micronaut-starter/latest/guide#installation), you can create a project using the `mn` executable. If you prefer not to install the Micronaut CLI, and you are running on Linux or macOS, you can `curl` the project. Lastly, you can navigate to Micronaut Launch in a browser, create a new project, download it and open in VS Code. +There are, of course, other ways to create a new Micronaut application. If you provide a path to the [Micronaut CLI installation](https://micronaut-projects.github.io/micronaut-starter/latest/guide/#installation), you can create a project using the `mn` executable. If you prefer not to install the Micronaut CLI, and you are running on Linux or macOS, you can `curl` the project. Lastly, you can navigate to Micronaut Launch in a browser, create a new project, download it and open in VS Code. -In combination with the [GraalVM Tools for Java extension](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm), you can run Micronaut projects on GraalVM, and debug them directly from the VS Code development environment with different debugging protocols enabled with the extension. This extension for Micronaut was also developed to help developers build native images directly from VS Code. +In combination with the [GraalVM Tools for Java extension](https://marketplace.visualstudio.com/items?itemName=oracle-labs-graalvm.graalvm), you can run Micronaut projects on GraalVM, and debug them directly from the VS Code development environment with different debugging protocols enabled with the extension. This extension for Micronaut was also developed to help developers build native images right from VS Code. #### Table of contents - [Installation and Setup](#installation-and-setup) @@ -51,7 +51,7 @@ The GraalVM Tools for Micronaut extension provides: * code completion and navigation for Micronaut configuration (YAML) files and Java (available with [Apache NetBeans Language Server extension](https://marketplace.visualstudio.com/items?itemName=asf.apache-netbeans-java)). * ability to build Micronaut projects ahead-of-time into native images with GraalVM * __Run main with Continuous Mode__ CodeLens runs Micronaut project and reloads it automatically when source code is changed. It is not available as Debugger. - * __Launch Java: Continuous Mode__ is the name of the launch configuration. +* __Launch Java: Continuous Mode__ is the name of the launch configuration. ### Micronaut VS Code Commands @@ -106,14 +106,14 @@ That will run the `mvnw package -Dpackaging=native-image` job. For more details, continue reading to the [Micronaut documentation](https://guides.micronaut.io/micronaut-creating-first-graal-app/guide/index.html#creatingGraalImage). -## Deploy Micronaut Projects to Docker Registry +## Deploy Micronaut Projects to a Docker Registry -The Micronaut support in VS Code allows to build and deploy Docker images to Docker registry. +The Micronaut support in VS Code allows to build and deploy Docker images to a Docker registry. Use action **View** > **Command Palette** > **Micronaut: Deploy...** and select **dockerPush** to deploy a dockerized Micronaut application or **dockerPushNative** to build and push docker with a native executable of Micronaut application. ![Micronaut Deploy Commands](images/micronaut-deploy-commands.png) -Besides that, you can also push a Micronaut application or a native executable to the Docker Registry from the VS Code Terminal window. +Besides that, you can also push a Micronaut application or a native executable to a Docker Registry from the VS Code Terminal window. A particular Docker Registry can be configured in the build, see the [Micronaut Deploying Application](https://micronaut-projects.github.io/micronaut-maven-plugin/latest/examples/deploy.html) documentation. diff --git a/docs/tools/vscode/micronaut/k8s-support.md b/docs/tools/vscode/micronaut/k8s-support.md index 283533a0c6a0..aa641c0659ca 100644 --- a/docs/tools/vscode/micronaut/k8s-support.md +++ b/docs/tools/vscode/micronaut/k8s-support.md @@ -5,12 +5,13 @@ link_title: Deploy Micronaut Applications to Oracle Container Engine for Kuberne permalink: /tools/vscode/micronaut/kubernetes-support/ --- -# Deploy Micronaut Applications to Oracle Container Engine for Kubernetes +## Deploy, Run and Debug Micronaut Applications in Kubernetes Cluster GraalVM Tools for Micronaut Extension added support for working with Kubernetes clusters based on Microsofts’s [Visual Studio Code Kubernetes Tools](https://marketplace.visualstudio.com/items?itemName=ms-kubernetes-tools.vscode-kubernetes-tools). +It is now possible to deploy, run and debug a Micronaut application in a Kubernetes cluster from VS Code. -It is now possible to deploy and debug a Micronaut project to Kubernetes on Oracle Cloud with Oracle Container Engine for Kubernetes (OKE)](https://www.oracle.com/uk/cloud-native/container-engine-kubernetes/) environment. -OKE is a fully-managed, scalable, and highly available service that you can use to deploy your containerized applications to the cloud. +This guide is focused on and tested with Oracle Container Engine for Kubernetes (OKE)](https://www.oracle.com/uk/cloud-native/container-engine-kubernetes/) and Oracle Container Registry, but Kubernetes features should work in other environments. +OKE is a fully-managed, scalable, and highly available service that you can use to deploy your containerized applications to Oracle Cloud. This guide will walk you through the process of deploying a Micronaut application to OKE from VS Code and debugging it. @@ -23,7 +24,9 @@ This guide will walk you through the process of deploying a Micronaut applicatio ## Preparation ### Visual Studio Code Kubernetes Tools -Micronaut's extension support for Kubernetes is based on Microsofts’s [Visual Studio Code Kubernetes Tools](https://marketplace.visualstudio.com/items?itemName=ms-kubernetes-tools.vscode-kubernetes-tools). It has to be installed. + +GraalVM Tools for Micronaut Extension uses `kubectl` provided by Microsoft's [Visual Studio Code Kubernetes Tools](https://marketplace.visualstudio.com/items?itemName=ms-kubernetes-tools.vscode-kubernetes-tools). +It has to be installed. Open Extensions tab, search for "Kubernetes" and install the one from Microsoft. Once installed, you should see the Kubernetes icon in the left sidebar: From 659b5fb2961e97d1a617432657a0ad7902d04ed9 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Mon, 18 Oct 2021 11:41:39 -0700 Subject: [PATCH 514/681] Style fix. --- substratevm/mx.substratevm/suite.py | 7 ++--- .../pointsto/util/PointsToOptionParser.java | 27 ++++++++++--------- .../svm/common/option/CommonOptionParser.java | 21 ++++++++------- .../svm/common/option/MultiOptionValue.java | 5 +--- .../core/option/SubstrateOptionsParser.java | 27 +++++++++---------- .../svm/hosted/option/HostedOptionParser.java | 4 +-- 6 files changed, 43 insertions(+), 48 deletions(-) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index f8b4f7afa75e..c3669be6eb91 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1261,16 +1261,13 @@ "moduleInfo" : { "name" : "org.graalvm.nativeimage.junitsupport", "exports" : [ - "* to org.graalvm.nativeimage.builder", + "* to org.graalvm.nativeimage.builder,org.graalvm.nativeimage.base,org.graalvm.nativeimage.pointsto" ], "requires" : [ "static com.oracle.mxtool.junit", "static junit", "static hamcrest", - ], - "exports" : [ - "* to org.graalvm.nativeimage.base,org.graalvm.nativeimage.pointsto,org.graalvm.nativeimage.builder", - ], + ] }, }, diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/PointsToOptionParser.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/PointsToOptionParser.java index b2a93a85768d..3a1997d13be2 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/PointsToOptionParser.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/PointsToOptionParser.java @@ -26,15 +26,7 @@ package com.oracle.graal.pointsto.util; -import com.oracle.svm.common.option.CommonOptionParser; -import com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat; -import com.oracle.svm.common.option.CommonOptionParser.OptionParseResult; -import com.oracle.svm.common.option.UnsupportedOptionClassException; -import org.graalvm.collections.EconomicMap; -import org.graalvm.compiler.options.OptionDescriptor; -import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionValues; +import static com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat.PLUS_MINUS; import java.io.PrintStream; import java.util.ArrayList; @@ -45,7 +37,16 @@ import java.util.Set; import java.util.function.Predicate; -import static com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat.PLUS_MINUS; +import org.graalvm.collections.EconomicMap; +import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; + +import com.oracle.svm.common.option.CommonOptionParser; +import com.oracle.svm.common.option.UnsupportedOptionClassException; +import com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat; +import com.oracle.svm.common.option.CommonOptionParser.OptionParseResult; public final class PointsToOptionParser { @@ -59,12 +60,11 @@ public static PointsToOptionParser getInstance() { return instance; } - @SuppressWarnings("unchecked") private PointsToOptionParser() { ClassLoader appClassLoader = PointsToOptionParser.class.getClassLoader(); CommonOptionParser.collectOptions(ServiceLoader.load(OptionDescriptors.class, appClassLoader), descriptor -> { String name = descriptor.getName(); - if (descriptor.getOptionKey() instanceof OptionKey) { + if (descriptor.getOptionKey() != null) { OptionDescriptor existing = allAnalysisOptions.put(name, descriptor); if (existing != null) { AnalysisError.shouldNotReachHere("Option name \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + descriptor.getLocation()); @@ -112,7 +112,8 @@ private static boolean parseOption(String optionPrefix, EconomicMap> optionKeyPredicate = optionKey -> { Class clazz = optionKey.getClass(); - // All classes from com.oracle.graal.pointsto.api.PointstoOptions are taken as non-hosted options. + // All classes from com.oracle.graal.pointsto.api.PointstoOptions are taken as + // non-hosted options. if (clazz.getName().startsWith("com.oracle.graal.pointsto.api.PointstoOptions")) { return false; } diff --git a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java index 823a67bee2c9..fcd6a9c53bd6 100644 --- a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java @@ -28,15 +28,6 @@ // Checkstyle: allow reflection -import com.oracle.svm.util.ClassUtil; -import com.oracle.svm.util.StringUtil; -import org.graalvm.collections.EconomicMap; -import org.graalvm.compiler.options.OptionDescriptor; -import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionsParser; - import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; @@ -50,6 +41,16 @@ import java.util.function.Consumer; import java.util.function.Predicate; +import org.graalvm.collections.EconomicMap; +import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.options.OptionsParser; + +import com.oracle.svm.util.ClassUtil; +import com.oracle.svm.util.StringUtil; + public class CommonOptionParser { public static final String HOSTED_OPTION_PREFIX = "-H:"; public static final String RUNTIME_OPTION_PREFIX = "-R:"; @@ -352,7 +353,7 @@ public static long parseLong(String v) { } /** - * Parses the provide string to a double number, avoiding the JDK dependencies (which pull in a + * Parses the provided string to a double number, avoiding the JDK dependencies (which pull in a * lot of classes, including the regular expression library). Only simple numbers are supported, * without fancy exponent styles. */ diff --git a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/MultiOptionValue.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/MultiOptionValue.java index 0f678439903c..2c44d2ce4997 100644 --- a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/MultiOptionValue.java +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/MultiOptionValue.java @@ -32,10 +32,7 @@ public interface MultiOptionValue { Class getValueType(); /** - * @return a list of option values, one for each place where the option is used - * @implSpec Note that it DOES NOT perform any splitting of string values based on a delimiter. - * If you want to perform this split, use a utility - * {@link com.oracle.svm.core.option.OptionUtils#flatten(String, com.oracle.svm.core.option.LocatableMultiOptionValue.Strings)} + * @return a list of option values, one for each place where the option is used. */ List values(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java index 81436ccd784c..8d70ac470839 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java @@ -26,19 +26,6 @@ // Checkstyle: allow reflection -import com.oracle.svm.core.util.InterruptImageBuilding; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.common.option.CommonOptionParser; -import com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat; -import com.oracle.svm.common.option.CommonOptionParser.OptionParseResult; -import com.oracle.svm.common.option.UnsupportedOptionClassException; -import org.graalvm.collections.EconomicMap; -import org.graalvm.compiler.options.OptionDescriptor; -import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - import java.io.PrintStream; import java.lang.reflect.Field; import java.util.Arrays; @@ -47,7 +34,19 @@ import java.util.function.Consumer; import java.util.function.Predicate; -import static com.oracle.svm.core.util.VMError.shouldNotReachHere; +import org.graalvm.collections.EconomicMap; +import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +import com.oracle.svm.common.option.CommonOptionParser; +import com.oracle.svm.common.option.CommonOptionParser.BooleanOptionFormat; +import com.oracle.svm.common.option.CommonOptionParser.OptionParseResult; +import com.oracle.svm.common.option.UnsupportedOptionClassException; +import com.oracle.svm.core.util.InterruptImageBuilding; +import com.oracle.svm.core.util.VMError; /** * This class contains methods for parsing options and matching them against diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java index e9a795dc44a3..46fa77d41fa6 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/option/HostedOptionParser.java @@ -59,13 +59,13 @@ public HostedOptionParser(ClassLoader imageClassLoader) { } public static void collectOptions(ServiceLoader optionDescriptors, EconomicMap allHostedOptions, - EconomicMap allRuntimeOptions) { + EconomicMap allRuntimeOptions) { SubstrateOptionsParser.collectOptions(optionDescriptors, descriptor -> { String name = descriptor.getName(); if (descriptor.getDeclaringClass().getAnnotation(Platforms.class) != null) { throw UserError.abort("Options must not be declared in a class that has a @%s annotation: option %s declared in %s", - Platforms.class.getSimpleName(), name, descriptor.getDeclaringClass().getTypeName()); + Platforms.class.getSimpleName(), name, descriptor.getDeclaringClass().getTypeName()); } if (!(descriptor.getOptionKey() instanceof RuntimeOptionKey)) { From dfd8388896004441ced75759b98b99b41abe06f3 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Wed, 13 Oct 2021 18:49:11 +0200 Subject: [PATCH 515/681] Set java compliance of com.oracle.svm.truffle.tck to 8+. --- substratevm/mx.substratevm/suite.py | 2 +- .../src/com/oracle/svm/truffle/tck/PermissionsFeature.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index c1b7e79a15bf..2dacbcf44a78 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1062,7 +1062,7 @@ "annotationProcessors": [ "compiler:GRAAL_PROCESSOR", ], - "javaCompliance": "1.8", + "javaCompliance": "8+", }, }, diff --git a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/PermissionsFeature.java b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/PermissionsFeature.java index 86ca19b15d05..603181d4d98d 100644 --- a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/PermissionsFeature.java +++ b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/PermissionsFeature.java @@ -881,6 +881,7 @@ private void checkPermission(Permission perm) { } final class SecurityManagerHolder { + @SuppressWarnings("deprecation") // SecurityManager deprecated since 17. static final SecurityManager SECURITY_MANAGER = new SecurityManager(); } From 12dc6d97ca48f11070940ceb8af1ef694e6337af Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Mon, 18 Oct 2021 12:45:22 -0700 Subject: [PATCH 516/681] Refactor comments. --- .../graal/pointsto/PointsToAnalysis.java | 41 ++++++++++--------- .../svm/hosted/NativeImageGenerator.java | 13 +++--- 2 files changed, 28 insertions(+), 26 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 78c3cc170897..d642bb662760 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 @@ -45,7 +45,6 @@ import java.util.concurrent.atomic.AtomicLongArray; import java.util.function.Function; -import com.oracle.graal.pointsto.util.AnalysisError; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; @@ -57,6 +56,7 @@ import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; +import org.graalvm.nativeimage.hosted.Feature; import com.oracle.graal.pointsto.ObjectScanner.ReusableSet; import com.oracle.graal.pointsto.api.HostVM; @@ -80,6 +80,7 @@ import com.oracle.graal.pointsto.reports.StatisticsPrinter; import com.oracle.graal.pointsto.typestate.PointsToStats; import com.oracle.graal.pointsto.typestate.TypeState; +import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.graal.pointsto.util.CompletionExecutor; import com.oracle.graal.pointsto.util.CompletionExecutor.DebugContextRunnable; import com.oracle.graal.pointsto.util.Timer; @@ -708,21 +709,22 @@ public HostVM getHostVM() { /** * Iterate until analysis reaches a fixpoint. * - * * @param debugContext debug context - * @param duringAnalysisAction The action handler taken during analysis, return true if no more iteration is required. - * It could be the {@link org.graalvm.nativeimage.hosted.Feature#duringAnalysis} - * for Native Image generation, but also can be other similar actions for standalone pointsto - * analysis that does not dependent on {@link com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl} - * and {@link com.oracle.svm.hosted.NativeImageGenerator.AnalysisFeatureHandler}. - * - * @return The error message during the analysis. If the analysis ends successfully, an empty String is returned, otherwise - * the actual error message is returned. - * @throws InterruptedException + * @param analysisEndCondition hook for actions to be taken during analysis. It also dictates + * when the analysis should end, i.e., it returns true if no more iterations are + * required. + * + * When the analysis is used for Native Image generation the actions could for + * example be specified via + * {@link org.graalvm.nativeimage.hosted.Feature#duringAnalysis(Feature.DuringAnalysisAccess)}. + * The ending condition could be provided by + * {@link org.graalvm.nativeimage.hosted.Feature.DuringAnalysisAccess#requireAnalysisIteration()}. + * + * @throws AnalysisError if the analysis fails */ @SuppressWarnings("try") @Override - public void runAnalysis(DebugContext debugContext, Function duringAnalysisAction) throws InterruptedException { + public void runAnalysis(DebugContext debugContext, Function analysisEndCondition) throws InterruptedException { int numIterations = 0; while (true) { try (Indent indent2 = debugContext.logAndIndent("new analysis iteration")) { @@ -734,13 +736,13 @@ public void runAnalysis(DebugContext debugContext, Function 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). + * 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). */ - AnalysisError.shouldNotReachHere(String.format("Static analysis did not reach a fix point after %d iterations because a Feature keeps requesting new analysis iterations. " + + 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")); + numIterations, analysisChanged ? "DID" : "DID NOT")); } /* @@ -750,9 +752,10 @@ public void runAnalysis(DebugContext debugContext, Function { - bb.getHostVM().notifyClassReachabilityListener(aUniverse, config); - featureHandler.forEachFeature(feature -> feature.duringAnalysis(config)); - return !config.getAndResetRequireAnalysisIteration(); - }); + bb.runAnalysis(debug, (universe) -> { + bb.getHostVM().notifyClassReachabilityListener(universe, config); + featureHandler.forEachFeature(feature -> feature.duringAnalysis(config)); + return !config.getAndResetRequireAnalysisIteration(); + }); } catch (AnalysisError e) { throw UserError.abort(e, "Analysis step failed. Reason: %s.", e.getMessage()); } From d2d17c1f2bc5fa36a387963aa113ec96cba05c27 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 8 Oct 2021 18:39:36 +0200 Subject: [PATCH 517/681] Update documentation for GC changes. --- .../native-image/MemoryManagement.md | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/docs/reference-manual/native-image/MemoryManagement.md b/docs/reference-manual/native-image/MemoryManagement.md index f39af9332cd5..17d0f4dc3945 100644 --- a/docs/reference-manual/native-image/MemoryManagement.md +++ b/docs/reference-manual/native-image/MemoryManagement.md @@ -62,19 +62,24 @@ It divides the Java heap into a young and an old generation. Each generation consists of a set of equally sized chunks, each a contiguous range of virtual memory. Those chunks are the GC-internal unit for memory allocation and memory reclamation. -The young generation is reserved for the allocation of new objects and when this part becomes full, a young collection is triggered. -Objects that are alive in the young generation, will be moved to the old generation, thus freeing up the young generation for subsequent object allocations. -When the old generation becomes full, a full collection is triggered. -Typically, a young collection is much faster than an full collection, however doing full collections is important for keeping the memory footprint low. -By default, the GC tries to balance the time that is spent in young and full collections. - -If no maximum Java heap size is specified, a native image that uses the Serial GC will set its maximum Java heap size to 80% of the physical memory size. -For example, on a machine with 4GB of RAM, the maximum Java heap size will be set to 3.2GB. -If the same image is executed on a machine that has 32GB of RAM, the maximum Java heap size will be set to 25.6GB. +The young generation contains recently created objects and is divided into the _eden_ and _survivor_ regions. +New objects are allocated in the eden region, and when this region is full, a young collection is triggered. +Objects that are alive in the eden region will be moved to the survivor region, and alive objects in the survivor region stay in that region until they reach a certain age (have survived a certain number of collections), at which time they are moved to the old generation. +When the old generation becomes full, a full collection is triggered that reclaims the space of unused objects in both the young and old generations. +Typically, a young collection is much faster than a full collection, however doing full collections is important for keeping the memory footprint low. +By default, the Serial GC tries to find a size for the generations that provides good throughput, but to not increase sizes further when doing so gives diminishing returns. +It also tries to maintain a ratio between the time spent in young collections and in full collections to keep the footprint small. + +If no maximum Java heap size is specified, a native image that uses the Serial GC will set its maximum Java heap size to 25% of the physical memory size (or 50% for physical memory below 384 MB), but always to at least 96MB. +For example, on a machine with 4GB of RAM, the maximum Java heap size will be set to 1GB. +If the same image is executed on a machine that has 32GB of RAM, the maximum Java heap size will be set to 8GB. Note that this is just the maximum value. Depending on the application, the amount of actually used Java heap memory can be much lower. To override this default behavior, either specify a value for `-XX:MaximumHeapSizePercent` or explicitly set the maximum [Java heap size](#java-heap-size). +Note that GraalVM releases up to (and including) 21.3 use a different default configuration for the Serial GC without survivor regions, a maximum Java heap size of 80% of physical memory, and a default collection policy that balances the time that is spent in young collections and old collections. +This configuration can be enabled with `-H:InitialCollectionPolicy=BySpaceAndTime`. + Be mindful that the GC needs some extra memory when performing a garbage collection (2x of the maximum heap size is the worst case, usually, it is significantly less). Therefore, the resident set size, RSS, can increase temporarily during a garbage collection which can be an issue in any environment with memory constraints (such as a container). @@ -83,28 +88,32 @@ Therefore, the resident set size, RSS, can increase temporarily during a garbage For tuning the GC performance and the memory footprint, the following options can be used: * `-XX:MaximumHeapSizePercent` - the percentage of the physical memory size that is used as the maximum Java heap size if the maximum Java heap size is not specified otherwise. * `-XX:MaximumYoungGenerationSizePercent` - the maximum size of the young generation as a percentage of the maximum Java heap size. -* `-XX:PercentTimeInIncrementalCollection` - determines how much time the GC should spend doing young collections. -With the default value of 50, the GC tries to balance the time spent on young and full collections. -Increasing this value will reduce the number of full GCs, which can improve performance but may worsen the memory footprint. -Decreasing this value will increase the number of full GCs, which can improve the memory footprint but may decrease performance. * `-XX:±CollectYoungGenerationSeparately` (since GraalVM 21.0) - determines if a full GC collects the young generation separately or together with the old generation. If enabled, this may reduce the memory footprint during full GCs. However, full GCs may take more time. +* `-XX:MaxHeapFree` (since GraalVM 21.3) - maximum total size (in bytes) of free memory chunks that remain reserved for allocations after a collection and are therefore not returned to the operating system. * `-H:AlignedHeapChunkSize` (can only be specified at image build time) - the size of a heap chunk in bytes. -* `-H:MaxSurvivorSpaces` (since GraalVM 21.1, can only be specified at image build time) - the number of survivor spaces that are used for the young generation. +* `-H:MaxSurvivorSpaces` (since GraalVM 21.1, can only be specified at image build time) - the number of survivor spaces that are used for the young generation, that is, the maximum age at which an object will be promoted to the old generation. With a value of 0, objects that survive a young collection are directly promoted to the old generation. * `-H:LargeArrayThreshold` (can only be specified at image build time) - the size at or above which an array will be allocated in its own heap chunk. Arrays that are considered as large are more expensive to allocate but they are never copied by the GC, which can reduce the GC overhead. ```shell -# Build and execute a native image that uses the serial GC but does less full GCs -native-image --gc=serial -R:PercentTimeInIncrementalCollection=70 HelloWorld +# Build and execute a native image that uses a maximum heap size of 75% of the physical memory +native-image --gc=serial -R:MaximumHeapSizePercent=75 HelloWorld ./helloworld -# Execute the native image from above but force more full GCs -./helloworld -XX:PercentTimeInIncrementalCollection=40 +# Execute the native image from above but reduce the maximum heap size to 40% of the physical memory +./helloworld -XX:MaximumHeapSizePercent=40 ``` +The following options are available with `-H:InitialCollectionPolicy=BySpaceAndTime` only: + +* `-XX:PercentTimeInIncrementalCollection` - determines how much time the GC should spend doing young collections. + With the default value of 50, the GC tries to balance the time spent on young and full collections. + Increasing this value will reduce the number of full GCs, which can improve performance but may worsen the memory footprint. + Decreasing this value will increase the number of full GCs, which can improve the memory footprint but may decrease performance. + ## G1 Garbage Collector GraalVM Enterprise Edition also provides the Garbage-First (G1) garbage collector, which is based on the G1 GC from the Java HotSpot VM. From 82ced0b17ed84d0a71eaad7cad0d0730c48322c5 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Wed, 13 Oct 2021 13:16:50 +0200 Subject: [PATCH 518/681] Avoid unnecessary SizeParameters allocations. --- .../genscavenge/AbstractCollectionPolicy.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java index 307a0ccc992a..c2b82ac5a737 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java @@ -141,7 +141,7 @@ protected void guaranteeSizeParametersInitialized() { public void updateSizeParameters() { PhysicalMemory.tryInitialize(); - SizeParameters params = computeSizeParameters(); + SizeParameters params = computeSizeParameters(sizes); SizeParameters previous = sizes; if (previous != null && params.equal(previous)) { return; // nothing to do @@ -246,7 +246,7 @@ public UnsignedWord getMinimumHeapSize() { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) protected abstract long gcCount(); - protected SizeParameters computeSizeParameters() { + protected SizeParameters computeSizeParameters(SizeParameters existing) { UnsignedWord addressSpaceSize = ReferenceAccess.singleton().getAddressSpaceSize(); UnsignedWord minYoungSpaces = minSpaceSize(); // eden if (HeapParameters.getMaxSurvivorSpaces() > 0) { @@ -328,7 +328,7 @@ protected SizeParameters computeSizeParameters() { UnsignedWord initialEden = initialYoung.subtract(initialSurvivor.multiply(2)); initialEden = minSpaceSize(alignDown(initialEden)); - return new SizeParameters(maxHeap, maxYoung, initialHeap, initialEden, initialSurvivor, minHeap); + return SizeParameters.get(existing, maxHeap, maxYoung, initialHeap, initialEden, initialSurvivor, minHeap); } protected static final class SizeParameters { @@ -339,7 +339,15 @@ protected static final class SizeParameters { final UnsignedWord initialSurvivorSize; final UnsignedWord minHeapSize; - SizeParameters(UnsignedWord maxHeapSize, UnsignedWord maxYoungSize, UnsignedWord initialHeapSize, + static SizeParameters get(SizeParameters existing, UnsignedWord maxHeap, UnsignedWord maxYoung, UnsignedWord initialHeap, + UnsignedWord initialEden, UnsignedWord initialSurvivor, UnsignedWord minHeap) { + if (existing != null && existing.matches(maxHeap, maxYoung, initialHeap, initialEden, initialSurvivor, minHeap)) { + return existing; + } + return new SizeParameters(maxHeap, maxYoung, initialHeap, initialEden, initialSurvivor, minHeap); + } + + private SizeParameters(UnsignedWord maxHeapSize, UnsignedWord maxYoungSize, UnsignedWord initialHeapSize, UnsignedWord initialEdenSize, UnsignedWord initialSurvivorSize, UnsignedWord minHeapSize) { this.maxHeapSize = maxHeapSize; this.maxYoungSize = maxYoungSize; @@ -385,8 +393,13 @@ UnsignedWord maxOldSize() { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) boolean equal(SizeParameters other) { - return maxHeapSize.equal(other.maxHeapSize) && maxYoungSize.equal(other.maxYoungSize) && initialHeapSize.equal(other.initialHeapSize) && - initialEdenSize.equal(other.initialEdenSize) && initialSurvivorSize.equal(other.initialSurvivorSize) && minHeapSize.equal(other.minHeapSize); + return other == this || other.matches(maxHeapSize, maxYoungSize, initialHeapSize, initialEdenSize, initialSurvivorSize, minHeapSize); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + boolean matches(UnsignedWord maxHeap, UnsignedWord maxYoung, UnsignedWord initialHeap, UnsignedWord initialEden, UnsignedWord initialSurvivor, UnsignedWord minHeap) { + return maxHeapSize.equal(maxHeap) && maxYoungSize.equal(maxYoung) && initialHeapSize.equal(initialHeap) && + initialEdenSize.equal(initialEden) && initialSurvivorSize.equal(initialSurvivor) && minHeapSize.equal(minHeap); } } } From 316eeee50980e1243975a7a255dc1f318c710f39 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 15 Oct 2021 13:59:07 +0200 Subject: [PATCH 519/681] Do not use survivor spaces during full collections. --- .../oracle/svm/core/genscavenge/GCImpl.java | 73 +++++++++---------- .../svm/core/genscavenge/YoungGeneration.java | 9 --- .../remset/CardTableBasedRememberedSet.java | 10 +-- 3 files changed, 39 insertions(+), 53 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index 83f506087d87..7a3918bd50b2 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -260,7 +260,7 @@ private boolean doCollectOnce(GCCause cause, long requestingNanoTime, boolean co if (!followsIncremental) { // we would have verified the heap after the incremental GC verifyBeforeGC(); } - scavenge(!complete, followsIncremental); + scavenge(!complete); verifyAfterGC(); } finally { collectionTimer.close(); @@ -495,7 +495,7 @@ public boolean isCompleteCollection() { } /** Scavenge, either from dirty roots or from all roots, and process discovered references. */ - private void scavenge(boolean incremental, boolean followingIncremental) { + private void scavenge(boolean incremental) { GreyToBlackObjRefVisitor.Counters counters = greyToBlackObjRefVisitor.openCounters(); try { Timer rootScanTimer = timers.rootScan.open(); @@ -503,7 +503,7 @@ private void scavenge(boolean incremental, boolean followingIncremental) { if (incremental) { cheneyScanFromDirtyRoots(); } else { - cheneyScanFromRoots(followingIncremental); + cheneyScanFromRoots(); } } finally { rootScanTimer.close(); @@ -576,7 +576,7 @@ private void cleanRuntimeCodeCache() { } } - private void cheneyScanFromRoots(boolean followingIncremental) { + private void cheneyScanFromRoots() { Timer cheneyScanFromRootsTimer = timers.cheneyScanFromRoots.open(); try { /* Take a snapshot of the heap so that I can visit all the promoted Objects. */ @@ -585,22 +585,7 @@ private void cheneyScanFromRoots(boolean followingIncremental) { * Objects into each of the blackening methods, or even put them around individual * Object reference visits. */ - prepareForPromotion(); - - if (followingIncremental) { - /* - * We just finished an incremental collection, so we could get away with not - * scavenging the young generation again. - * - * However, we don't do this because if objects in the young generation are - * reachable only from garbage objects in the old generation, the young objects - * cannot be reclaimed during this collection. Even worse, if there is a cycle in - * which the young objects in turn keep the old objects alive, none of the objects - * can be reclaimed until these young objects are eventually tenured, or until a - * single complete collection is done before we would run out of memory. - */ - // HeapImpl.getHeapImpl().getYoungGeneration().emptyFromSpacesIntoToSpaces(); - } + prepareForPromotion(false); /* * Make sure all chunks with pinned objects are in toSpace, and any formerly pinned @@ -624,14 +609,14 @@ private void cheneyScanFromRoots(boolean followingIncremental) { blackenImageHeapRoots(); /* Visit all the Objects promoted since the snapshot. */ - scanGreyObjects(); + scanGreyObjects(false); if (DeoptimizationSupport.enabled()) { /* Visit the runtime compiled code, now that we know all the reachable objects. */ walkRuntimeCodeCache(); /* Visit all objects that became reachable because of the compiled code. */ - scanGreyObjects(); + scanGreyObjects(false); } greyToBlackObjectVisitor.reset(); @@ -657,7 +642,7 @@ private void cheneyScanFromDirtyRoots() { * Objects into each of the blackening methods, or even put them around individual * Object reference visits. */ - prepareForPromotion(); + prepareForPromotion(true); /* * Make sure any released objects are in toSpace (because this is an incremental @@ -690,14 +675,14 @@ private void cheneyScanFromDirtyRoots() { blackenDirtyImageHeapRoots(); /* Visit all the Objects promoted since the snapshot, transitively. */ - scanGreyObjects(); + scanGreyObjects(true); if (DeoptimizationSupport.enabled()) { /* Visit the runtime compiled code, now that we know all the reachable objects. */ walkRuntimeCodeCache(); /* Visit all objects that became reachable because of the compiled code. */ - scanGreyObjects(); + scanGreyObjects(true); } greyToBlackObjectVisitor.reset(); @@ -956,28 +941,38 @@ private void blackenDirtyCardRoots() { } } - private static void prepareForPromotion() { + private static void prepareForPromotion(boolean isIncremental) { HeapImpl heap = HeapImpl.getHeapImpl(); heap.getOldGeneration().prepareForPromotion(); - heap.getYoungGeneration().prepareForPromotion(); + if (isIncremental) { + heap.getYoungGeneration().prepareForPromotion(); + } } - private void scanGreyObjects() { - HeapImpl heap = HeapImpl.getHeapImpl(); - YoungGeneration youngGen = heap.getYoungGeneration(); - OldGeneration oldGen = heap.getOldGeneration(); + private void scanGreyObjects(boolean isIncremental) { Timer scanGreyObjectsTimer = timers.scanGreyObjects.open(); try { - boolean hasGrey; - do { - hasGrey = youngGen.scanGreyObjects(); - hasGrey |= oldGen.scanGreyObjects(); - } while (hasGrey); + if (isIncremental) { + scanGreyObjectsLoop(); + } else { + HeapImpl.getHeapImpl().getOldGeneration().scanGreyObjects(); + } } finally { scanGreyObjectsTimer.close(); } } + private static void scanGreyObjectsLoop() { + HeapImpl heap = HeapImpl.getHeapImpl(); + YoungGeneration youngGen = heap.getYoungGeneration(); + OldGeneration oldGen = heap.getOldGeneration(); + boolean hasGrey; + do { + hasGrey = youngGen.scanGreyObjects(); + hasGrey |= oldGen.scanGreyObjects(); + } while (hasGrey); + } + @AlwaysInline("GC performance") @SuppressWarnings("static-method") Object promoteObject(Object original, UnsignedWord header) { @@ -991,7 +986,7 @@ Object promoteObject(Object original, UnsignedWord header) { Object result = null; boolean survivorOverflow = false; - if (originalSpace.getNextAgeForPromotion() < policy.getTenuringAge()) { + if (!completeCollection && originalSpace.getNextAgeForPromotion() < policy.getTenuringAge()) { if (isAligned) { result = heap.getYoungGeneration().promoteAlignedObject(original, (AlignedHeader) originalChunk, originalSpace); } else { @@ -999,7 +994,7 @@ Object promoteObject(Object original, UnsignedWord header) { } survivorOverflow = (result == null); } - if (result == null) { // tenuring age reached or survivor space full + if (result == null) { // complete collection, tenuring age reached, or survivor space full if (isAligned) { result = heap.getOldGeneration().promoteAlignedObject(original, (AlignedHeader) originalChunk, originalSpace); } else { @@ -1031,7 +1026,7 @@ private void promotePinnedObject(PinnedObjectImpl pinned) { Space originalSpace = HeapChunk.getSpace(originalChunk); if (originalSpace.isFromSpace()) { boolean promoted = false; - if (originalSpace.getNextAgeForPromotion() < policy.getTenuringAge()) { + if (!completeCollection && originalSpace.getNextAgeForPromotion() < policy.getTenuringAge()) { promoted = heap.getYoungGeneration().promoteChunk(originalChunk, isAligned, originalSpace); } if (!promoted) { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGeneration.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGeneration.java index bfc13bd95599..209fbad2731d 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGeneration.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGeneration.java @@ -151,15 +151,6 @@ void swapSpaces() { assert survivorsToSpacesAccounting.getChunkBytes().equal(0); } - void emptyFromSpacesIntoToSpaces() { - assert getEden().isEmpty() && getEden().getChunkBytes().equal(0) : "Eden must be empty."; - assert survivorsToSpacesAccounting.getChunkBytes().equal(0) : "Survivor to-spaces must be empty"; - for (int i = 0; i < maxSurvivorSpaces; i++) { - assert getSurvivorToSpaceAt(i).isEmpty() && getSurvivorToSpaceAt(i).getChunkBytes().equal(0) : "Survivor to-space must be empty."; - getSurvivorToSpaceAt(i).absorb(getSurvivorFromSpaceAt(i)); - } - } - boolean walkHeapChunks(MemoryWalker.Visitor visitor) { if (getEden().walkHeapChunks(visitor)) { for (int i = 0; i < maxSurvivorSpaces; i++) { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java index a3e2b060212b..c9f990d84358 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java @@ -136,12 +136,12 @@ public void dirtyCardIfNecessary(Object holderObject, Object object) { return; } // We dirty the cards of ... - if (HeapParameters.getMaxSurvivorSpaces() != 0 && HeapImpl.getHeapImpl().getYoungGeneration().contains(object)) { + if (HeapParameters.getMaxSurvivorSpaces() != 0 && !GCImpl.getGCImpl().isCompleteCollection() && HeapImpl.getHeapImpl().getYoungGeneration().contains(object)) { /* - * ...references from the old generation to the young generation, unless we do not use - * survivor spaces, in which case there will be no such references because all young - * objects are promoted to the old generation. (We avoid an extra old generation check - * and might remark a few image heap cards, too) + * ...references from the old generation to the young generation, unless there cannot be + * any such references if we do not use survivor spaces, or if we do but are doing a + * complete collection: in both cases, all objects are promoted to the old generation. + * (We avoid an extra old generation check and might remark a few image heap cards, too) */ } else if (HeapImpl.usesImageHeapCardMarking() && GCImpl.getGCImpl().isCompleteCollection() && HeapImpl.getHeapImpl().isInImageHeap(holderObject)) { // ...references from the image heap to the runtime heap, but we clean and remark those From 2b564ff7858f900a6f99b18d73628784852175f2 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 15 Oct 2021 16:20:46 +0200 Subject: [PATCH 520/681] Fix Adaptive GC policy accounting. --- .../genscavenge/AdaptiveCollectionPolicy.java | 59 +++++++++++-------- .../svm/core/genscavenge/GCAccounting.java | 29 ++++----- .../oracle/svm/core/genscavenge/GCImpl.java | 10 ++-- 3 files changed, 50 insertions(+), 48 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java index 9e76c13cff97..224262dbdf3a 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java @@ -188,16 +188,14 @@ public boolean shouldCollectCompletely(boolean followingIncrementalCollection) { return promotionEstimate.aboveThan(oldFree); } - private void updateAverages(UnsignedWord survivedChunkBytes, UnsignedWord survivorOverflowObjectBytes, UnsignedWord promotedObjectBytes) { - /* - * Adding the object bytes of overflowed survivor objects does not consider the overhead of - * partially filled chunks in the many survivor spaces, so it underestimates the necessary - * survivors capacity. However, this should self-correct as we expand the survivor space and - * reduce the tenuring age to avoid overflowing survivor objects in the first place. - */ - avgSurvived.sample(survivedChunkBytes.add(survivorOverflowObjectBytes)); + private void updateAverages(boolean isSurvivorOverflow, UnsignedWord survivedChunkBytes, UnsignedWord promotedChunkBytes) { + UnsignedWord survived = survivedChunkBytes; + if (isSurvivorOverflow) { + survived = survived.add(promotedChunkBytes); // guess + } + avgSurvived.sample(survived); - avgPromoted.sample(promotedObjectBytes); + avgPromoted.sample(promotedChunkBytes); } private void computeSurvivorSpaceSizeAndThreshold(boolean isSurvivorOverflow, UnsignedWord survivorLimit) { @@ -424,24 +422,29 @@ public void onCollectionEnd(boolean completeCollection, GCCause cause) { // {maj UnsignedWord oldLive = accounting.getOldGenerationAfterChunkBytes(); oldSizeExceededInPreviousCollection = oldLive.aboveThan(oldSize); - /* - * Update the averages that survivor space and tenured space sizes are derived from. Note - * that we use chunk bytes (not object bytes) for the survivors. This is because they are - * kept in many spaces (one for each age), which potentially results in significant overhead - * from chunks that may only be partially filled, especially when the heap is small. Using - * chunk bytes here ensures that the needed survivor capacity is not underestimated. - */ - UnsignedWord survivedChunkBytes = HeapImpl.getHeapImpl().getYoungGeneration().getSurvivorChunkBytes(); - UnsignedWord survivorOverflowObjectBytes = accounting.getSurvivorOverflowObjectBytes(); - UnsignedWord tenuredObjBytes = accounting.getTenuredObjectBytes(); // includes overflowed - updateAverages(survivedChunkBytes, survivorOverflowObjectBytes, tenuredObjBytes); + if (!completeCollection) { + /* + * Update the averages that survivor space and tenured space sizes are derived from. + * Note that we use chunk bytes (not object bytes) for the survivors. This is because + * they are kept in many spaces (one for each age), which potentially results in + * significant overhead from chunks that may only be partially filled, especially when + * the heap is small. Using chunk bytes here ensures that the needed survivor capacity + * is not underestimated. + */ + boolean survivorOverflow = accounting.hasLastIncrementalCollectionOverflowedSurvivors(); + UnsignedWord survivedChunkBytes = HeapImpl.getHeapImpl().getYoungGeneration().getSurvivorChunkBytes(); + UnsignedWord tenuredChunkBytes = accounting.getLastIncrementalCollectionPromotedChunkBytes(); + updateAverages(survivorOverflow, survivedChunkBytes, tenuredChunkBytes); - computeSurvivorSpaceSizeAndThreshold(survivorOverflowObjectBytes.aboveThan(0), sizes.maxSurvivorSize()); - computeEdenSpaceSize(); - if (completeCollection) { - computeOldGenSpaceSize(oldLive); + computeSurvivorSpaceSizeAndThreshold(survivorOverflow, sizes.maxSurvivorSize()); + } + if (shouldUpdateStats(cause)) { + computeEdenSpaceSize(); + if (completeCollection) { + computeOldGenSpaceSize(oldLive); + } + decaySupplementalGrowth(completeCollection); } - decaySupplementalGrowth(completeCollection); } private void computeOldGenSpaceSize(UnsignedWord oldLive) { // compute_old_gen_free_space @@ -531,9 +534,13 @@ private void decaySupplementalGrowth(boolean completeCollection) { } } + private static boolean shouldUpdateStats(GCCause cause) { // should_update_{eden,promo}_stats + return cause == GenScavengeGCCause.OnAllocation || USE_ADAPTIVE_SIZE_POLICY_WITH_SYSTEM_GC; + } + private static void updateCollectionEndAverages(AdaptiveWeightedAverage costAverage, AdaptivePaddedAverage pauseAverage, ReciprocalLeastSquareFit costEstimator, AdaptiveWeightedAverage intervalSeconds, GCCause cause, long mutatorNanos, long pauseNanos, UnsignedWord sizeBytes) { - if (cause == GenScavengeGCCause.OnAllocation || USE_ADAPTIVE_SIZE_POLICY_WITH_SYSTEM_GC) { + if (shouldUpdateStats(cause)) { double cost = 0; double mutatorInSeconds = TimeUtils.nanosToSecondsDouble(mutatorNanos); double pauseInSeconds = TimeUtils.nanosToSecondsDouble(pauseNanos); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java index e18aaad24b3b..7b312f0fc325 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java @@ -30,7 +30,6 @@ import org.graalvm.word.WordFactory; import com.oracle.svm.core.annotate.AlwaysInline; -import com.oracle.svm.core.hub.LayoutEncoding; import com.oracle.svm.core.log.Log; /** @@ -47,8 +46,8 @@ public final class GCAccounting { private long completeCollectionTotalNanos = 0; private UnsignedWord collectedTotalChunkBytes = WordFactory.zero(); private UnsignedWord allocatedChunkBytes = WordFactory.zero(); - private UnsignedWord tenuredObjectBytes = WordFactory.zero(); - private UnsignedWord survivorOverflowObjectBytes = WordFactory.zero(); + private UnsignedWord lastIncrementalCollectionPromotedChunkBytes = WordFactory.zero(); + private boolean lastIncrementalCollectionOverflowedSurvivors = false; /* Before and after measures. */ private UnsignedWord youngChunkBytesBefore = WordFactory.zero(); @@ -113,15 +112,15 @@ UnsignedWord getYoungChunkBytesAfter() { return youngChunkBytesAfter; } - UnsignedWord getTenuredObjectBytes() { - return tenuredObjectBytes; + UnsignedWord getLastIncrementalCollectionPromotedChunkBytes() { + return lastIncrementalCollectionPromotedChunkBytes; } - UnsignedWord getSurvivorOverflowObjectBytes() { - return survivorOverflowObjectBytes; + public boolean hasLastIncrementalCollectionOverflowedSurvivors() { + return lastIncrementalCollectionOverflowedSurvivors; } - void beforeCollection() { + void beforeCollection(boolean completeCollection) { Log trace = Log.noopLog().string("[GCImpl.Accounting.beforeCollection:").newline(); /* Gather some space statistics. */ HeapImpl heap = HeapImpl.getHeapImpl(); @@ -138,8 +137,9 @@ void beforeCollection() { oldObjectBytesBefore = oldSpace.computeObjectBytes(); allocatedObjectBytes = allocatedObjectBytes.add(edenObjectBytesBefore); } - tenuredObjectBytes = WordFactory.zero(); - survivorOverflowObjectBytes = WordFactory.zero(); + if (!completeCollection) { + lastIncrementalCollectionOverflowedSurvivors = false; + } trace.string(" youngChunkBytesBefore: ").unsigned(youngChunkBytesBefore) .string(" oldChunkBytesBefore: ").unsigned(oldChunkBytesBefore); trace.string("]").newline(); @@ -147,12 +147,8 @@ void beforeCollection() { /** Called after an object has been promoted from the young generation to the old generation. */ @AlwaysInline("GC performance") - void onObjectTenured(Object result, boolean survivorOverflow) { - UnsignedWord size = LayoutEncoding.getSizeFromObjectInline(result); - tenuredObjectBytes = tenuredObjectBytes.add(size); - if (survivorOverflow) { - survivorOverflowObjectBytes = survivorOverflowObjectBytes.add(size); - } + void onSurvivorOverflowed() { + lastIncrementalCollectionOverflowedSurvivors = true; } void afterCollection(boolean completeCollection, Timer collectionTimer) { @@ -172,6 +168,7 @@ private void afterIncrementalCollection(Timer collectionTimer) { */ incrementalCollectionCount += 1; afterCollectionCommon(); + lastIncrementalCollectionPromotedChunkBytes = oldChunkBytesAfter.subtract(oldChunkBytesBefore); incrementalCollectionTotalNanos += collectionTimer.getMeasuredNanos(); trace.string(" incrementalCollectionCount: ").signed(incrementalCollectionCount) .string(" oldChunkBytesAfter: ").unsigned(oldChunkBytesAfter) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index 7a3918bd50b2..19ab1b5ae95d 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -252,7 +252,7 @@ private boolean doCollectOnce(GCCause cause, long requestingNanoTime, boolean co assert !followsIncremental || complete : "An incremental collection cannot be followed by another incremental collection"; completeCollection = complete; - accounting.beforeCollection(); + accounting.beforeCollection(completeCollection); policy.onCollectionBegin(completeCollection, requestingNanoTime); Timer collectionTimer = timers.collection.open(); @@ -985,14 +985,15 @@ Object promoteObject(Object original, UnsignedWord header) { } Object result = null; - boolean survivorOverflow = false; if (!completeCollection && originalSpace.getNextAgeForPromotion() < policy.getTenuringAge()) { if (isAligned) { result = heap.getYoungGeneration().promoteAlignedObject(original, (AlignedHeader) originalChunk, originalSpace); } else { result = heap.getYoungGeneration().promoteUnalignedObject(original, (UnalignedHeader) originalChunk, originalSpace); } - survivorOverflow = (result == null); + if (result == null) { + accounting.onSurvivorOverflowed(); + } } if (result == null) { // complete collection, tenuring age reached, or survivor space full if (isAligned) { @@ -1001,9 +1002,6 @@ Object promoteObject(Object original, UnsignedWord header) { result = heap.getOldGeneration().promoteUnalignedObject(original, (UnalignedHeader) originalChunk, originalSpace); } assert result != null : "promotion failure in old generation must have been handled"; - if (result != original) { - accounting.onObjectTenured(result, survivorOverflow); - } } return result; From cdf17541324e1600c21d1f2be896001dd432fb33 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Sat, 16 Oct 2021 12:09:24 +0200 Subject: [PATCH 521/681] Use a maximum heap size of 80% of physical memory also with the Adaptive policy. --- .../native-image/MemoryManagement.md | 18 +++++++++--------- .../genscavenge/AbstractCollectionPolicy.java | 17 +---------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/docs/reference-manual/native-image/MemoryManagement.md b/docs/reference-manual/native-image/MemoryManagement.md index 17d0f4dc3945..f89dbf37e673 100644 --- a/docs/reference-manual/native-image/MemoryManagement.md +++ b/docs/reference-manual/native-image/MemoryManagement.md @@ -70,15 +70,15 @@ Typically, a young collection is much faster than a full collection, however doi By default, the Serial GC tries to find a size for the generations that provides good throughput, but to not increase sizes further when doing so gives diminishing returns. It also tries to maintain a ratio between the time spent in young collections and in full collections to keep the footprint small. -If no maximum Java heap size is specified, a native image that uses the Serial GC will set its maximum Java heap size to 25% of the physical memory size (or 50% for physical memory below 384 MB), but always to at least 96MB. -For example, on a machine with 4GB of RAM, the maximum Java heap size will be set to 1GB. -If the same image is executed on a machine that has 32GB of RAM, the maximum Java heap size will be set to 8GB. +If no maximum Java heap size is specified, a native image that uses the Serial GC will set its maximum Java heap size to 80% of the physical memory size. +For example, on a machine with 4GB of RAM, the maximum Java heap size will be set to 3.2GB. +If the same image is executed on a machine that has 32GB of RAM, the maximum Java heap size will be set to 25.6GB. Note that this is just the maximum value. Depending on the application, the amount of actually used Java heap memory can be much lower. To override this default behavior, either specify a value for `-XX:MaximumHeapSizePercent` or explicitly set the maximum [Java heap size](#java-heap-size). -Note that GraalVM releases up to (and including) 21.3 use a different default configuration for the Serial GC without survivor regions, a maximum Java heap size of 80% of physical memory, and a default collection policy that balances the time that is spent in young collections and old collections. -This configuration can be enabled with `-H:InitialCollectionPolicy=BySpaceAndTime`. +Note that GraalVM releases up to (and including) 21.3 use a different default configuration for the Serial GC with no survivor regions, a young generation that is limited to 256 MB, and a default collection policy that balances the time that is spent in young collections and old collections. +This configuration can be enabled with: `-H:InitialCollectionPolicy=BySpaceAndTime` Be mindful that the GC needs some extra memory when performing a garbage collection (2x of the maximum heap size is the worst case, usually, it is significantly less). Therefore, the resident set size, RSS, can increase temporarily during a garbage collection which can be an issue in any environment with memory constraints (such as a container). @@ -99,12 +99,12 @@ With a value of 0, objects that survive a young collection are directly promoted Arrays that are considered as large are more expensive to allocate but they are never copied by the GC, which can reduce the GC overhead. ```shell -# Build and execute a native image that uses a maximum heap size of 75% of the physical memory -native-image --gc=serial -R:MaximumHeapSizePercent=75 HelloWorld +# Build and execute a native image that uses a maximum heap size of 25% of the physical memory +native-image --gc=serial -R:MaximumHeapSizePercent=25 HelloWorld ./helloworld -# Execute the native image from above but reduce the maximum heap size to 40% of the physical memory -./helloworld -XX:MaximumHeapSizePercent=40 +# Execute the native image from above but increase the maximum heap size to 75% of the physical memory +./helloworld -XX:MaximumHeapSizePercent=75 ``` The following options are available with `-H:InitialCollectionPolicy=BySpaceAndTime` only: diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java index c2b82ac5a737..35d426993af2 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java @@ -68,8 +68,6 @@ static int getMaxSurvivorSpaces(Integer userValue) { /** HotSpot: -XX:MaxHeapSize default without ergonomics. */ protected static final UnsignedWord SMALL_HEAP_SIZE = WordFactory.unsigned(96 * 1024 * 1024); protected static final int NEW_RATIO = 2; // HotSpot: -XX:NewRatio - protected static final int LARGE_MEMORY_MAX_HEAP_PERCENT = 25; // -XX:MaxRAMPercentage - protected static final int SMALL_MEMORY_MAX_HEAP_PERCENT = 50; // -XX:MinRAMPercentage protected final AdaptiveWeightedAverage avgYoungGenAlignedChunkFraction = new AdaptiveWeightedAverage(DEFAULT_TIME_WEIGHT); @@ -261,20 +259,7 @@ protected SizeParameters computeSizeParameters(SizeParameters existing) { } else if (!PhysicalMemory.isInitialized()) { maxHeap = addressSpaceSize; } else { - UnsignedWord physicalMemorySize = PhysicalMemory.getCachedSize(); - if (HeapParameters.Options.MaximumHeapSizePercent.hasBeenSet(RuntimeOptionValues.singleton())) { - maxHeap = physicalMemorySize.unsignedDivide(100).multiply(HeapParameters.getMaximumHeapSizePercent()); - } else { - UnsignedWord reasonableMax = physicalMemorySize.unsignedDivide(100).multiply(AbstractCollectionPolicy.LARGE_MEMORY_MAX_HEAP_PERCENT); - UnsignedWord reasonableMin = physicalMemorySize.unsignedDivide(100).multiply(AbstractCollectionPolicy.SMALL_MEMORY_MAX_HEAP_PERCENT); - if (reasonableMin.belowThan(AbstractCollectionPolicy.SMALL_HEAP_SIZE)) { - // small physical memory, use a small fraction for the heap - reasonableMax = reasonableMin; - } else { - reasonableMax = UnsignedUtils.max(reasonableMax, AbstractCollectionPolicy.SMALL_HEAP_SIZE); - } - maxHeap = reasonableMax; - } + maxHeap = PhysicalMemory.getCachedSize().unsignedDivide(100).multiply(HeapParameters.getMaximumHeapSizePercent()); } UnsignedWord unadjustedMaxHeap = maxHeap; maxHeap = UnsignedUtils.clamp(alignDown(maxHeap), minAllSpaces, alignDown(addressSpaceSize)); From 63c898181ab92f407184373ab653ff652e3abc2e Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Sat, 16 Oct 2021 12:37:51 +0200 Subject: [PATCH 522/681] Increase initial heap size and its fraction for the young generation. --- .../core/genscavenge/AbstractCollectionPolicy.java | 13 +++++++------ .../core/genscavenge/AdaptiveCollectionPolicy.java | 4 +++- .../core/genscavenge/ProportionateSpacesPolicy.java | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java index 35d426993af2..53791cba5714 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java @@ -65,12 +65,12 @@ static int getMaxSurvivorSpaces(Integer userValue) { protected static final int DEFAULT_TIME_WEIGHT = 25; // -XX:AdaptiveTimeWeight /* Constants to compute defaults for values which can be set through existing options. */ - /** HotSpot: -XX:MaxHeapSize default without ergonomics. */ - protected static final UnsignedWord SMALL_HEAP_SIZE = WordFactory.unsigned(96 * 1024 * 1024); + protected static final UnsignedWord INITIAL_HEAP_SIZE = WordFactory.unsigned(128 * 1024 * 1024); protected static final int NEW_RATIO = 2; // HotSpot: -XX:NewRatio protected final AdaptiveWeightedAverage avgYoungGenAlignedChunkFraction = new AdaptiveWeightedAverage(DEFAULT_TIME_WEIGHT); + private final int initialNewRatio; protected UnsignedWord survivorSize; protected UnsignedWord edenSize; protected UnsignedWord promoSize; @@ -80,8 +80,9 @@ static int getMaxSurvivorSpaces(Integer userValue) { protected volatile SizeParameters sizes; private final ReentrantLock sizesUpdateLock = new ReentrantLock(); - protected AbstractCollectionPolicy(int initialTenuringThreshold) { - tenuringThreshold = UninterruptibleUtils.Math.clamp(initialTenuringThreshold, 1, HeapParameters.getMaxSurvivorSpaces() + 1); + protected AbstractCollectionPolicy(int initialNewRatio, int initialTenuringThreshold) { + this.initialNewRatio = initialNewRatio; + this.tenuringThreshold = UninterruptibleUtils.Math.clamp(initialTenuringThreshold, 1, HeapParameters.getMaxSurvivorSpaces() + 1); } @Override @@ -287,14 +288,14 @@ protected SizeParameters computeSizeParameters(SizeParameters existing) { } minHeap = UnsignedUtils.clamp(alignUp(minHeap), minAllSpaces, maxHeap); - UnsignedWord initialHeap = AbstractCollectionPolicy.SMALL_HEAP_SIZE; + UnsignedWord initialHeap = AbstractCollectionPolicy.INITIAL_HEAP_SIZE; initialHeap = UnsignedUtils.clamp(alignUp(initialHeap), minHeap, maxHeap); UnsignedWord initialYoung; if (initialHeap.equal(maxHeap)) { initialYoung = maxYoung; } else { - initialYoung = initialHeap.unsignedDivide(AbstractCollectionPolicy.NEW_RATIO + 1); + initialYoung = initialHeap.unsignedDivide(initialNewRatio + 1); initialYoung = UnsignedUtils.clamp(alignUp(initialYoung), minYoungSpaces, maxYoung); } UnsignedWord initialSurvivor = WordFactory.zero(); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java index 224262dbdf3a..cdbe856d09dc 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java @@ -107,6 +107,8 @@ final class AdaptiveCollectionPolicy extends AbstractCollectionPolicy { */ private static final double ADAPTIVE_SIZE_COST_ESTIMATOR_GC_COST_LIMIT = 0.5; + private static final int INITIAL_NEW_RATIO = 1; // same size for young and old generation + /* Constants derived from other constants. */ private static final double THROUGHPUT_GOAL = 1.0 - 1.0 / (1.0 + GC_TIME_RATIO); private static final double THRESHOLD_TOLERANCE_PERCENT = 1.0 + THRESHOLD_TOLERANCE / 100.0; @@ -137,7 +139,7 @@ final class AdaptiveCollectionPolicy extends AbstractCollectionPolicy { private long oldGenChangeForMajorThroughput; AdaptiveCollectionPolicy() { - super(INITIAL_TENURING_THRESHOLD); + super(INITIAL_NEW_RATIO, INITIAL_TENURING_THRESHOLD); } @Override diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ProportionateSpacesPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ProportionateSpacesPolicy.java index 53e0354e0773..261013c9164e 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ProportionateSpacesPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ProportionateSpacesPolicy.java @@ -55,7 +55,7 @@ final class ProportionateSpacesPolicy extends AbstractCollectionPolicy { private int shrinkFactor; ProportionateSpacesPolicy() { - super(MAX_TENURING_THRESHOLD); + super(NEW_RATIO, MAX_TENURING_THRESHOLD); } @Override From 55b16bef0995b137c2af933d4e3532c3e36e238c Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 18 Oct 2021 19:09:10 +0200 Subject: [PATCH 523/681] Further improvements and bugfixes. --- .../posix/pthread/PthreadVMLockSupport.java | 4 ++ .../core/windows/WindowsVMLockSupport.java | 4 ++ .../svm/core/InvalidMethodPointerHandler.java | 4 ++ .../graal/snippets/CEntryPointSnippets.java | 4 ++ .../svm/core/jdk/VMErrorSubstitutions.java | 3 ++ .../com/oracle/svm/core/thread/VMThreads.java | 37 +++++++++++++--- .../svm/jni/functions/JNIFunctions.java | 44 ++++++++++++------- 7 files changed, 76 insertions(+), 24 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java index f473152e3073..8e339ff2ec11 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadVMLockSupport.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.posix.pthread; +import com.oracle.svm.core.annotate.RestrictHeapAccess; import com.oracle.svm.core.stack.StackOverflowCheck; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.NumUtil; @@ -56,6 +57,8 @@ import jdk.vm.ci.meta.JavaKind; +import static com.oracle.svm.core.annotate.RestrictHeapAccess.Access.NO_ALLOCATION; + /** * Support of {@link VMMutex} and {@link VMCondition} in multi-threaded environments. Locking is * implemented via pthreads. @@ -161,6 +164,7 @@ public static boolean initialize() { } @Uninterruptible(reason = "Called from uninterruptible code.", calleeMustBe = false) + @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in fatal error handling.", overridesCallers = true) protected static void checkResult(int result, String functionName) { if (result != 0) { /* diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java index 868f3f6f12c8..4101b79d2dd1 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsVMLockSupport.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.windows; +import com.oracle.svm.core.annotate.RestrictHeapAccess; import com.oracle.svm.core.stack.StackOverflowCheck; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.NumUtil; @@ -55,6 +56,8 @@ import jdk.vm.ci.meta.JavaKind; +import static com.oracle.svm.core.annotate.RestrictHeapAccess.Access.NO_ALLOCATION; + //Checkstyle: stop /** @@ -156,6 +159,7 @@ public static void initialize() { } @Uninterruptible(reason = "Called from uninterruptible code.", calleeMustBe = false) + @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in fatal error handling.", overridesCallers = true) static void checkResult(int result, String functionName) { if (result == 0) { /* diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java index 7db44647c79d..9c1c59ec3fef 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/InvalidMethodPointerHandler.java @@ -28,6 +28,7 @@ import java.lang.reflect.Method; +import com.oracle.svm.core.annotate.RestrictHeapAccess; import com.oracle.svm.core.annotate.Uninterruptible; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.LogHandler; @@ -43,6 +44,8 @@ import com.oracle.svm.core.thread.VMThreads; import com.oracle.svm.util.ReflectionUtil; +import static com.oracle.svm.core.annotate.RestrictHeapAccess.Access.NO_ALLOCATION; + /** * Provides stub methods that can be used for uninitialized method pointers. Instead of a segfault, * the stubs provide full diagnostic output with a stack trace. @@ -71,6 +74,7 @@ private static void methodPointerNotCompiledHandler() { } @Uninterruptible(reason = "Prevent safepoints until everything is set up for printing the fatal error.", calleeMustBe = false) + @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in fatal error handling.", overridesCallers = true) private static void failFatally(Pointer callerSP, CodePointer callerIP, String message) { VMThreads.SafepointBehavior.preventSafepoints(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index ad7c1d3dda11..574441ffb58e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -27,12 +27,14 @@ import static com.oracle.svm.core.SubstrateOptions.MultiThreaded; import static com.oracle.svm.core.SubstrateOptions.SpawnIsolates; import static com.oracle.svm.core.SubstrateOptions.UseDedicatedVMOperationThread; +import static com.oracle.svm.core.annotate.RestrictHeapAccess.Access.NO_ALLOCATION; import static com.oracle.svm.core.graal.nodes.WriteCurrentVMThreadNode.writeCurrentVMThread; import static com.oracle.svm.core.graal.nodes.WriteHeapBaseNode.writeCurrentVMHeapBase; import static com.oracle.svm.core.util.VMError.shouldNotReachHere; import java.util.Map; +import com.oracle.svm.core.annotate.RestrictHeapAccess; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; @@ -562,6 +564,7 @@ public static int reportExceptionSnippet(Throwable exception) { @Uninterruptible(reason = "Avoid StackOverflowError and safepoints until they are disabled permanently", calleeMustBe = false) @SubstrateForeignCallTarget(stubCallingConvention = false) + @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in fatal error handling.", overridesCallers = true) private static int reportException(Throwable exception) { VMThreads.SafepointBehavior.preventSafepoints(); StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); @@ -572,6 +575,7 @@ private static int reportException(Throwable exception) { return CEntryPointErrors.UNSPECIFIED; // unreachable } + @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in fatal error handling.", overridesCallers = true) private static void logException(Throwable exception) { try { Log.log().exception(exception); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java index 6604c9d85498..ee1162c1afb3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VMErrorSubstitutions.java @@ -41,6 +41,8 @@ import com.oracle.svm.core.stack.ThreadStackPrinter; import com.oracle.svm.core.thread.VMThreads; +import static com.oracle.svm.core.annotate.RestrictHeapAccess.Access.NO_ALLOCATION; + @TargetClass(com.oracle.svm.core.util.VMError.class) final class Target_com_oracle_svm_core_util_VMError { @@ -97,6 +99,7 @@ public class VMErrorSubstitutions { * uninterruptible */ @Uninterruptible(reason = "Allow VMError to be used in uninterruptible code.") + @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in fatal error handling.", overridesCallers = true) static RuntimeException shouldNotReachHere(CodePointer callerIP, String msg, Throwable ex) { ThreadStackPrinter.printBacktrace(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java index e78ccd36a33c..720dd6ec0441 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java @@ -26,6 +26,9 @@ import static com.oracle.svm.core.SubstrateOptions.UseDedicatedVMOperationThread; +import com.oracle.svm.core.annotate.NeverInline; +import com.oracle.svm.core.nodes.CFunctionEpilogueNode; +import com.oracle.svm.core.nodes.CFunctionPrologueNode; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.replacements.ReplacementsUtil; @@ -82,8 +85,9 @@ public static VMThreads singleton() { * the mutexes are acquired (VMOperation queue mutex first, {@link #THREAD_MUTEX} second). If * the VM operation causes a safepoint, then it is possible that the {@link #THREAD_MUTEX} was * already acquired for safepoint reasons. - *
  • Acquire the mutex outside of a VM operation but only execute uninterruptible code. This - * is safe as the uninterruptible code cannot trigger a safepoint.
  • + *
  • Acquire the mutex from a thread that is either not yet attached + * {@link StatusSupport#STATUS_CREATED} or currently in native code + * ({@link StatusSupport#STATUS_IN_NATIVE}).
  • * * * Deadlock example 1: @@ -328,7 +332,7 @@ public void detachThread(IsolateThread thread) { // From this point on, all code must be fully uninterruptible because this thread either // holds the THREAD_MUTEX (see the JavaDoc on THREAD_MUTEX) or because the IsolateThread was // already freed. - THREAD_MUTEX.lockNoTransition(); + lockVMMutexInNativeCode(); OSThreadHandle threadToCleanup; try { detachThreadInSafeContext(thread); @@ -354,6 +358,20 @@ public void detachThread(IsolateThread thread) { cleanupExitedOsThread(threadToCleanup); } + @Uninterruptible(reason = "Called from uninterruptible code.") + @NeverInline("Must not be inlined in a caller that has an exception handler: We only support InvokeNode and not InvokeWithExceptionNode between a CFunctionPrologueNode and CFunctionEpilogueNode.") + private static void lockVMMutexInNativeCode() { + CFunctionPrologueNode.cFunctionPrologue(StatusSupport.STATUS_IN_NATIVE); + lockVMMutexInNativeCode0(); + CFunctionEpilogueNode.cFunctionEpilogue(StatusSupport.STATUS_IN_NATIVE); + } + + @Uninterruptible(reason = "Must not stop while in native.") + @NeverInline("Provide a return address for the Java frame anchor.") + private static void lockVMMutexInNativeCode0() { + VMThreads.THREAD_MUTEX.lockNoTransition(); + } + @Uninterruptible(reason = "Thread is detaching and holds the THREAD_MUTEX.") private static void releaseThread(IsolateThread thread) { THREAD_MUTEX.guaranteeIsOwner("This mutex must be locked to prevent that a GC is triggered while detaching a thread from the heap"); @@ -812,9 +830,13 @@ public static int getSafepointBehaviorVolatile(IsolateThread vmThread) { * Changes the safepoint behavior so that this thread won't freeze at a safepoint. The * thread will also actively prevent the VM from reaching a safepoint (regardless of its * thread status). + * + * NOTE: Be careful with this and make sure that this thread does not allocate any Java + * objects as this could result deadlocks. */ - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + @Uninterruptible(reason = "Called from uninterruptible code.", callerMustBe = true) public static void preventSafepoints() { + // It would be nice if we could retire the TLAB here but that wouldn't work reliably. safepointBehaviorTL.setVolatile(PREVENT_VM_FROM_REACHING_SAFEPOINT); } @@ -826,13 +848,14 @@ public static void preventSafepoints() { * safepoint. The safepoint handling will ignore the thread so that the VM can reach a * safepoint regardless of the status of this thread. * - * Be careful with this. If a thread is ignored by the safepoint handling, it means that it - * can continue executing while a safepoint (and therefore a GC) is in progress. So, make - * sure that this thread does not allocate or access any movable heap objects (even + * NOTE: Be careful with this. If a thread is ignored by the safepoint handling, it means + * that it can continue executing while a safepoint (and therefore a GC) is in progress. So, + * make sure that this thread does not allocate or access any movable heap objects (even * executing write barriers can already cause issues). */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void markThreadAsCrashed() { + // It would be nice if we could retire the TLAB here but that wouldn't work reliably. safepointBehaviorTL.setVolatile(THREAD_CRASHED); } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java index f341108a898b..f2bf0cd4b88e 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctions.java @@ -36,6 +36,7 @@ import java.nio.ByteBuffer; import java.util.Arrays; +import com.oracle.svm.core.annotate.RestrictHeapAccess; import com.oracle.svm.core.stack.StackOverflowCheck; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; @@ -113,6 +114,8 @@ import jdk.vm.ci.meta.MetaUtil; import sun.misc.Unsafe; +import static com.oracle.svm.core.annotate.RestrictHeapAccess.Access.NO_ALLOCATION; + /** * Implementations of the functions defined by the Java Native Interface. * @@ -826,25 +829,10 @@ static int ThrowNew(JNIEnvironment env, JNIObjectHandle clazzHandle, CCharPointe @CEntryPoint(exceptionHandler = JNIExceptionHandlerVoid.class, include = CEntryPoint.NotIncludedAutomatically.class) @CEntryPointOptions(prologue = JNIEnvEnterFatalOnFailurePrologue.class, publishAs = Publish.NotPublished) @NeverInline("Access of caller frame.") - @Uninterruptible(reason = "Prevent safepoints until everything is set up for the fatal error printing.", calleeMustBe = false) static void FatalError(JNIEnvironment env, CCharPointer message) { - VMThreads.SafepointBehavior.preventSafepoints(); - StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); - CodePointer callerIP = KnownIntrinsics.readReturnAddress(); - LogHandler logHandler = ImageSingletons.lookup(LogHandler.class); - Log log = Log.enterFatalContext(logHandler, callerIP, CTypeConversion.toJavaString(message), null); - if (log != null) { - try { - log.string("Fatal error reported via JNI: ").string(message).newline(); - SubstrateDiagnostics.printFatalError(log, KnownIntrinsics.readCallerStackPointer(), callerIP); - } catch (Throwable ignored) { - /* - * Ignore exceptions reported during error reporting, we are going to exit anyway. - */ - } - } - logHandler.fatalError(); + Pointer callerSP = KnownIntrinsics.readCallerStackPointer(); + Support.fatalError(callerIP, callerSP, CTypeConversion.toJavaString(message)); } /* @@ -1165,6 +1153,28 @@ static void handleException(Throwable t) { */ JNIThreadLocalPendingException.set(t); } + + @Uninterruptible(reason = "Prevent safepoints until everything is set up for the fatal error printing.", calleeMustBe = false) + @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in fatal error handling.", overridesCallers = true) + static void fatalError(CodePointer callerIP, Pointer callerSP, String message) { + VMThreads.SafepointBehavior.preventSafepoints(); + StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError(); + + LogHandler logHandler = ImageSingletons.lookup(LogHandler.class); + Log log = Log.enterFatalContext(logHandler, callerIP, message, null); + if (log != null) { + try { + log.string("Fatal error reported via JNI: ").string(message).newline(); + SubstrateDiagnostics.printFatalError(log, callerSP, callerIP); + } catch (Throwable ignored) { + /* + * Ignore exceptions reported during error reporting, we are going to exit + * anyway. + */ + } + } + logHandler.fatalError(); + } } static final CGlobalData UNIMPLEMENTED_UNATTACHED_ERROR_MESSAGE = CGlobalDataFactory.createCString( From 06df879002b609897537a80bac82b50807388367 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 6 Oct 2021 11:14:38 +0200 Subject: [PATCH 524/681] svm: SubstrateArraycopyWithExceptionNode and use ArrayCopyNode instead --- .../replacements/arraycopy/ArrayCopyNode.java | 4 - .../core/graal/jdk/JDKIntrinsicsFeature.java | 3 +- .../graal/jdk/SubstrateArraycopySnippets.java | 7 +- .../SubstrateArraycopyWithExceptionNode.java | 149 ------------------ 4 files changed, 6 insertions(+), 157 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java index 3515086552b5..ba78296a2f00 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java @@ -63,10 +63,6 @@ public ArrayCopyNode(int bci, ValueNode src, ValueNode srcPos, ValueNode dst, Va } } - public ArrayCopyNode(ArrayCopy arraycopy) { - this(arraycopy.getBci(), arraycopy.getSource(), arraycopy.getSourcePosition(), arraycopy.getDestination(), arraycopy.getDestinationPosition(), arraycopy.getLength()); - } - @Override public LocationIdentity getKilledLocationIdentity() { if (!forceAnyLocation && elementKind == null) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/JDKIntrinsicsFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/JDKIntrinsicsFeature.java index bf6d5ae3ce13..ec05a5642d48 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/JDKIntrinsicsFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/JDKIntrinsicsFeature.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.annotate.AutomaticFeature; @@ -82,7 +83,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec */ ValueNode nonNullSrc = b.nullCheckedValue(src); ValueNode nonNullDst = b.nullCheckedValue(dst); - b.add(new SubstrateArraycopyWithExceptionNode(nonNullSrc, srcPos, nonNullDst, dstPos, length, null, b.bci())); + b.add(new ArrayCopyNode(b.bci(), nonNullSrc, srcPos, nonNullDst, dstPos, length)); return true; } }); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java index 0f181adf717d..5272b023ee37 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.Snippets; +import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode; import org.graalvm.word.LocationIdentity; import com.oracle.svm.core.JavaMemoryUtil; @@ -60,7 +61,7 @@ public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCal protected SubstrateArraycopySnippets(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, Map, NodeLoweringProvider> lowerings) { super(options, factories, providers, snippetReflection); - lowerings.put(SubstrateArraycopyWithExceptionNode.class, new SubstrateArraycopyWithExceptionLowering()); + lowerings.put(ArrayCopyNode.class, new SubstrateArraycopyWithExceptionLowering()); } /** @@ -110,9 +111,9 @@ private static void boundsCheck(Object fromArray, int fromIndex, Object toArray, } } - static final class SubstrateArraycopyWithExceptionLowering implements NodeLoweringProvider { + static final class SubstrateArraycopyWithExceptionLowering implements NodeLoweringProvider { @Override - public void lower(SubstrateArraycopyWithExceptionNode node, LoweringTool tool) { + public void lower(ArrayCopyNode node, LoweringTool tool) { StructuredGraph graph = node.graph(); ForeignCallWithExceptionNode call = graph.add(new ForeignCallWithExceptionNode(ARRAYCOPY, node.getSource(), node.getSourcePosition(), node.getDestination(), node.getDestinationPosition(), node.getLength())); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java deleted file mode 100644 index 4fc947a627cc..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopyWithExceptionNode.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2020, 2020, 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.core.graal.jdk; - -import static org.graalvm.compiler.nodeinfo.InputType.Memory; -import static org.graalvm.compiler.nodeinfo.InputType.State; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.NodeInputList; -import org.graalvm.compiler.nodeinfo.NodeCycles; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.NamedLocationIdentity; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.WithExceptionNode; -import org.graalvm.compiler.nodes.memory.MemoryKill; -import org.graalvm.compiler.nodes.spi.Simplifiable; -import org.graalvm.compiler.nodes.spi.SimplifierTool; -import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; -import org.graalvm.word.LocationIdentity; - -import jdk.vm.ci.meta.JavaKind; - -/** - * Substrate specific intrinisfication for {@link System#arraycopy} with an exception edge. - * - * Lowering is implemented in the platform/VM specific - * {@link org.graalvm.compiler.nodes.spi.LoweringProvider LoweringProvider}. Most of them eventually - * go through {@link SubstrateArraycopySnippets}. - */ -@NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, cyclesRationale = "may be replaced with non-throwing counterpart", size = SIZE_64) -public class SubstrateArraycopyWithExceptionNode extends WithExceptionNode implements ArrayCopy, Simplifiable { - - public static final NodeClass TYPE = NodeClass.create(SubstrateArraycopyWithExceptionNode.class); - - @Input NodeInputList args; - @OptionalInput(State) FrameState stateDuring; - @OptionalInput(State) protected FrameState stateAfter; - @OptionalInput(Memory) protected MemoryKill lastLocationAccess; - - protected JavaKind elementKind; - - protected int bci; - - public SubstrateArraycopyWithExceptionNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, JavaKind elementKind, int bci) { - super(TYPE, StampFactory.forVoid()); - this.bci = bci; - this.args = new NodeInputList<>(this, new ValueNode[]{src, srcPos, dest, destPos, length}); - this.elementKind = elementKind != JavaKind.Illegal ? elementKind : null; - if (this.elementKind == null) { - this.elementKind = ArrayCopy.selectComponentKind(this); - } - } - - @Override - public NodeInputList args() { - return args; - } - - @Override - public LocationIdentity getKilledLocationIdentity() { - return getLocationIdentity(); - } - - @Override - public LocationIdentity getLocationIdentity() { - if (elementKind != null) { - return NamedLocationIdentity.getArrayLocation(elementKind); - } - return LocationIdentity.any(); - } - - @Override - public MemoryKill getLastLocationAccess() { - return lastLocationAccess; - } - - @Override - public void setLastLocationAccess(MemoryKill lla) { - updateUsagesInterface(lastLocationAccess, lla); - lastLocationAccess = lla; - } - - @Override - public FrameState stateDuring() { - return stateDuring; - } - - @Override - public void setStateDuring(FrameState stateDuring) { - updateUsages(this.stateDuring, stateDuring); - this.stateDuring = stateDuring; - } - - @Override - public FrameState stateAfter() { - return stateAfter; - } - - @Override - public void setStateAfter(FrameState stateAfter) { - updateUsages(this.stateAfter, stateAfter); - this.stateAfter = stateAfter; - } - - @Override - public int getBci() { - return bci; - } - - @Override - public JavaKind getElementKind() { - return elementKind; - } - - @Override - public void simplify(SimplifierTool tool) { - if (this.elementKind == null) { - this.elementKind = ArrayCopy.selectComponentKind(this); - if (this.elementKind != null) { - tool.addToWorkList(usages()); - } - } - } -} From c7e533c67c78c1d3f6beff77a79b1754153e7bd2 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 6 Oct 2021 13:59:55 +0200 Subject: [PATCH 525/681] svm: rename SubstrateArraycopyWithExceptionLowering to SubstrateArrayCopyLowering --- .../oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java index 5272b023ee37..7d4555124dab 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateArraycopySnippets.java @@ -61,7 +61,7 @@ public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCal protected SubstrateArraycopySnippets(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, Map, NodeLoweringProvider> lowerings) { super(options, factories, providers, snippetReflection); - lowerings.put(ArrayCopyNode.class, new SubstrateArraycopyWithExceptionLowering()); + lowerings.put(ArrayCopyNode.class, new SubstrateArrayCopyLowering()); } /** @@ -111,7 +111,7 @@ private static void boundsCheck(Object fromArray, int fromIndex, Object toArray, } } - static final class SubstrateArraycopyWithExceptionLowering implements NodeLoweringProvider { + static final class SubstrateArrayCopyLowering implements NodeLoweringProvider { @Override public void lower(ArrayCopyNode node, LoweringTool tool) { StructuredGraph graph = node.graph(); From 37edd340333e703ac5a9a532d58ffad42e4cd474 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 6 Oct 2021 15:02:16 +0200 Subject: [PATCH 526/681] svm: PointstoGraphBuilderPlugins should use ArrayCopyNode --- .../graal/pointsto/plugins/PointstoGraphBuilderPlugins.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/plugins/PointstoGraphBuilderPlugins.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/plugins/PointstoGraphBuilderPlugins.java index 1453aec85c53..5d61d9141561 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/plugins/PointstoGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/plugins/PointstoGraphBuilderPlugins.java @@ -30,7 +30,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; +import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode; import org.graalvm.compiler.replacements.nodes.MacroNode.MacroParams; import com.oracle.graal.pointsto.nodes.AnalysisObjectCloneNode; @@ -45,7 +45,7 @@ public static void registerSystemPlugins(InvocationPlugins plugins) { r.register5("arraycopy", Object.class, int.class, Object.class, int.class, int.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length) { - b.add(new BasicArrayCopyNode(BasicArrayCopyNode.TYPE, src, srcPos, dest, destPos, length, null, b.bci())); + b.add(new ArrayCopyNode(b.bci(), src, srcPos, dest, destPos, length)); return true; } }); From 55dd2bfd8556edf0c3856a8f4cda74dfb932f1e0 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 6 Oct 2021 15:17:27 +0200 Subject: [PATCH 527/681] svm: use BasicArrayCopyNode instead of ArrayCopy --- .../oracle/graal/pointsto/flow/ArrayCopyTypeFlow.java | 9 ++++----- .../graal/pointsto/flow/MethodTypeFlowBuilder.java | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ArrayCopyTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ArrayCopyTypeFlow.java index e9f63856c75c..ed5eef62397c 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ArrayCopyTypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ArrayCopyTypeFlow.java @@ -25,7 +25,6 @@ package com.oracle.graal.pointsto.flow; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.api.PointstoOptions; @@ -36,10 +35,10 @@ import jdk.vm.ci.code.BytecodePosition; /** - * Models the flow transfer of an {@link ArrayCopy} node which intrinsifies calls to - * System.arraycopy(). This flow registers itself as an observer for both the source and the - * destination. When either the source or the destination elements change the element flows from - * source are passed to destination. + * Models the flow transfer of an {@link org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode} + * node which intrinsifies calls to System.arraycopy(). This flow registers itself as an observer + * for both the source and the destination. When either the source or the destination elements + * change the element flows from source are passed to destination. */ public class ArrayCopyTypeFlow extends TypeFlow { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java index 6513291c0751..77c1ccd86672 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java @@ -93,7 +93,7 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.graph.MergeableState; import org.graalvm.compiler.phases.graph.PostOrderNodeIterator; -import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; +import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.MacroInvokable; import org.graalvm.compiler.replacements.nodes.ObjectClone; @@ -1118,8 +1118,8 @@ protected void node(FixedNode n) { AtomicReadAndWriteNode node = (AtomicReadAndWriteNode) n; modelUnsafeReadAndWriteFlow(node, node.object(), node.newValue(), node.offset()); - } else if (n instanceof ArrayCopy) { - ArrayCopy node = (ArrayCopy) n; + } else if (n instanceof BasicArrayCopyNode) { + BasicArrayCopyNode node = (BasicArrayCopyNode) n; TypeFlowBuilder srcBuilder = state.lookup(node.getSource()); TypeFlowBuilder dstBuilder = state.lookup(node.getDestination()); From 5e86ec22fd0a40bd06dc9f3da8413da6b1bbba4d Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 6 Oct 2021 15:04:11 +0200 Subject: [PATCH 528/681] compiler: make BasicArrayCopyNode abstract --- .../graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java index 3e6d5680eafc..0c7ad161c459 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java @@ -51,7 +51,7 @@ * Base class for nodes that intrinsify {@link System#arraycopy}. */ @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = SIZE_64) -public class BasicArrayCopyNode extends WithExceptionNode implements ArrayCopy, StateSplit { +public abstract class BasicArrayCopyNode extends WithExceptionNode implements ArrayCopy, StateSplit { public static final NodeClass TYPE = NodeClass.create(BasicArrayCopyNode.class); From 8943401b5c4f85b8e7a9ce93b27a586eff125f89 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 6 Oct 2021 15:17:39 +0200 Subject: [PATCH 529/681] compiler: use BasicArrayCopyNode instead of ArrayCopy --- .../replacements/arraycopy/ArrayCopy.java | 15 ------------- .../replacements/arraycopy/ArrayCopyNode.java | 4 ++-- .../arraycopy/ArrayCopySnippets.java | 21 +++++++++++-------- .../nodes/BasicArrayCopyNode.java | 19 +++++++++++++++++ 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java index 8abf55d6c0a9..ec0f1cf9ac89 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java @@ -208,19 +208,4 @@ default void computeStateDuring(FrameState currentStateAfter) { setStateDuring(newStateDuring); } - static JavaKind selectComponentKind(ArrayCopy arraycopy) { - ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp(NodeView.DEFAULT)); - ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp(NodeView.DEFAULT)); - - if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) { - return null; - } - if (!destType.getComponentType().isAssignableFrom(srcType.getComponentType())) { - return null; - } - if (!arraycopy.isExact()) { - return null; - } - return srcType.getComponentType().getJavaKind(); - } } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java index ba78296a2f00..a39208936b28 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java @@ -57,7 +57,7 @@ public ArrayCopyNode(int bci, ValueNode src, ValueNode srcPos, ValueNode dst, Va super(TYPE, src, srcPos, dst, dstPos, length, null, bci); this.forceAnyLocation = forceAnyLocation; if (!forceAnyLocation) { - elementKind = ArrayCopy.selectComponentKind(this); + elementKind = selectComponentKind(this); } else { assert elementKind == null; } @@ -66,7 +66,7 @@ public ArrayCopyNode(int bci, ValueNode src, ValueNode srcPos, ValueNode dst, Va @Override public LocationIdentity getKilledLocationIdentity() { if (!forceAnyLocation && elementKind == null) { - elementKind = ArrayCopy.selectComponentKind(this); + elementKind = selectComponentKind(this); } if (elementKind != null) { return NamedLocationIdentity.getArrayLocation(elementKind); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java index 52c8b0d31684..36810e648eea 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java @@ -83,7 +83,7 @@ * object array and the other one a primitive array. *
  • {@link #arraycopyExactStubCallSnippet}: this snippet is used for array copies that do not * require a store check. This is the case if the array copy is either - * {@linkplain ArrayCopy#isExact() exact}, i.e., we can prove that the source array type is + * {@linkplain BasicArrayCopyNode#isExact() exact}, i.e., we can prove that the source array type is * assignable to the destination array type, or if one of the objects is a primitive array (and the * other is unknown). In the latter case, it is sufficient to dynamically check that the array types * are the same. No store check is needed.
  • @@ -146,10 +146,11 @@ protected boolean useOriginalArraycopy() { } /** - * Snippet that performs an {@linkplain ArrayCopy#isExact() exact} array copy. Used when the - * array copy might be {@linkplain Templates#lower(ArrayCopyNode, boolean, LoweringTool) - * expanded}. Lowering is delayed using an {@link ArrayCopyWithDelayedLoweringNode} which will - * dispatch to {@link #exactArraycopyWithExpandedLoopSnippet}. + * Snippet that performs an {@linkplain BasicArrayCopyNode#isExact() exact} array copy. Used + * when the array copy might be + * {@linkplain Templates#lower(ArrayCopyNode, boolean, LoweringTool) expanded}. Lowering is + * delayed using an {@link ArrayCopyWithDelayedLoweringNode} which will dispatch to + * {@link #exactArraycopyWithExpandedLoopSnippet}. * * @see Templates#lower(ArrayCopyNode, boolean, LoweringTool) * @see #exactArraycopyWithExpandedLoopSnippet @@ -174,7 +175,8 @@ public void delayedExactArraycopyWithExpandedLoopSnippet(Object src, int srcPos, } /** - * Snippet that performs a stub call for an {@linkplain ArrayCopy#isExact() exact} array copy. + * Snippet that performs a stub call for an {@linkplain BasicArrayCopyNode#isExact() exact} + * array copy. */ @Snippet public void arraycopyExactStubCallSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @@ -250,8 +252,9 @@ public static void arraycopyNativeExceptionSnippet(Object src, int srcPos, Objec } /** - * Inlines a loop that performs an {@linkplain ArrayCopy#isExact() exact} element-by-element - * array copy. The explict loop allows subsequent phases to optimize the code. + * Inlines a loop that performs an {@linkplain BasicArrayCopyNode#isExact() exact} + * element-by-element array copy. The explict loop allows subsequent phases to optimize the + * code. */ @SuppressWarnings("unused") @Snippet(allowPartialIntrinsicArgumentMismatch = true) @@ -492,7 +495,7 @@ public void lower(ArrayCopyNode arraycopy, LoweringTool tool) { * @see ArrayCopySnippets */ public void lower(ArrayCopyNode arraycopy, boolean mayExpandThisArraycopy, LoweringTool tool) { - JavaKind elementKind = ArrayCopy.selectComponentKind(arraycopy); + JavaKind elementKind = BasicArrayCopyNode.selectComponentKind(arraycopy); SnippetInfo snippetInfo; final ArrayCopyTypeCheck arrayTypeCheck; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java index 0c7ad161c459..0ba9eab929d4 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import static org.graalvm.word.LocationIdentity.any; +import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; @@ -37,10 +38,12 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.WithExceptionNode; import org.graalvm.compiler.nodes.memory.MemoryKill; +import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; import org.graalvm.word.LocationIdentity; @@ -144,4 +147,20 @@ public void setStateAfter(FrameState x) { public boolean hasSideEffect() { return true; } + + public static JavaKind selectComponentKind(BasicArrayCopyNode arraycopy) { + ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp(NodeView.DEFAULT)); + ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp(NodeView.DEFAULT)); + + if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) { + return null; + } + if (!destType.getComponentType().isAssignableFrom(srcType.getComponentType())) { + return null; + } + if (!arraycopy.isExact()) { + return null; + } + return srcType.getComponentType().getJavaKind(); + } } From 577f1943c58230d83cf2645284dea9bc358a0103 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 6 Oct 2021 15:21:04 +0200 Subject: [PATCH 530/681] compiler: move members from ArrayCopy to BasicArrayCopyNode --- .../replacements/arraycopy/ArrayCopy.java | 158 ----------------- .../nodes/BasicArrayCopyNode.java | 162 +++++++++++++++++- 2 files changed, 158 insertions(+), 162 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java index ec0f1cf9ac89..d0cd867547ed 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java @@ -50,162 +50,4 @@ */ public interface ArrayCopy extends Virtualizable, SingleMemoryKill, MemoryAccess, Lowerable, DeoptimizingNode.DeoptDuring { - int SRC_ARG = 0; - int SRC_POS_ARG = 1; - int DEST_ARG = 2; - int DEST_POS_ARG = 3; - int LENGTH_ARG = 4; - - NodeInputList args(); - - default ValueNode getSource() { - return args().get(SRC_ARG); - } - - default ValueNode getSourcePosition() { - return args().get(SRC_POS_ARG); - } - - default ValueNode getDestination() { - return args().get(DEST_ARG); - } - - default ValueNode getDestinationPosition() { - return args().get(DEST_POS_ARG); - } - - default ValueNode getLength() { - return args().get(LENGTH_ARG); - } - - int getBci(); - - JavaKind getElementKind(); - - default boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) { - assert length >= 0; - return position >= 0 && position <= virtualObject.entryCount() - length; - } - - default boolean checkEntryTypes(int srcPos, int length, VirtualObjectNode src, ResolvedJavaType destComponentType, VirtualizerTool tool) { - if (destComponentType.getJavaKind() == JavaKind.Object && !destComponentType.isJavaLangObject()) { - for (int i = 0; i < length; i++) { - ValueNode entry = tool.getEntry(src, srcPos + i); - ResolvedJavaType type = StampTool.typeOrNull(entry); - if (type == null || !destComponentType.isAssignableFrom(type)) { - return false; - } - } - } - return true; - } - - /* - * Returns true if this copy doesn't require store checks. Trivially true for primitive arrays. - */ - default boolean isExact() { - ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp(NodeView.DEFAULT)); - ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp(NodeView.DEFAULT)); - if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) { - return false; - } - if ((srcType.getComponentType().getJavaKind().isPrimitive() && destType.getComponentType().equals(srcType.getComponentType())) || getSource() == getDestination()) { - return true; - } - - if (StampTool.isExactType(getDestination().stamp(NodeView.DEFAULT))) { - if (destType != null && destType.isAssignableFrom(srcType)) { - return true; - } - } - return false; - } - - @Override - default void virtualize(VirtualizerTool tool) { - ValueNode sourcePosition = tool.getAlias(getSourcePosition()); - ValueNode destinationPosition = tool.getAlias(getDestinationPosition()); - ValueNode replacedLength = tool.getAlias(getLength()); - - if (sourcePosition.isConstant() && destinationPosition.isConstant() && replacedLength.isConstant()) { - int srcPosInt = sourcePosition.asJavaConstant().asInt(); - int destPosInt = destinationPosition.asJavaConstant().asInt(); - int len = replacedLength.asJavaConstant().asInt(); - ValueNode destAlias = tool.getAlias(getDestination()); - - if (destAlias instanceof VirtualArrayNode) { - VirtualArrayNode destVirtual = (VirtualArrayNode) destAlias; - if (len < 0 || !checkBounds(destPosInt, len, destVirtual)) { - return; - } - ValueNode srcAlias = tool.getAlias(getSource()); - - if (srcAlias instanceof VirtualObjectNode) { - if (!(srcAlias instanceof VirtualArrayNode)) { - return; - } - VirtualArrayNode srcVirtual = (VirtualArrayNode) srcAlias; - if (destVirtual.componentType().getJavaKind() != srcVirtual.componentType().getJavaKind()) { - return; - } - if (!checkBounds(srcPosInt, len, srcVirtual)) { - return; - } - if (!checkEntryTypes(srcPosInt, len, srcVirtual, destVirtual.type().getComponentType(), tool)) { - return; - } - if (srcVirtual == destVirtual && srcPosInt < destPosInt) { - // must copy backwards to avoid losing elements - for (int i = len - 1; i >= 0; i--) { - tool.setVirtualEntry(destVirtual, destPosInt + i, tool.getEntry(srcVirtual, srcPosInt + i)); - } - } else { - for (int i = 0; i < len; i++) { - tool.setVirtualEntry(destVirtual, destPosInt + i, tool.getEntry(srcVirtual, srcPosInt + i)); - } - } - tool.delete(); - DebugContext debug = this.asNode().getDebug(); - if (debug.isLogEnabled()) { - debug.log("virtualized arraycopy(%s, %d, %s, %d, %d)", getSource(), srcPosInt, getDestination(), destPosInt, len); - } - } else { - ResolvedJavaType sourceType = StampTool.typeOrNull(srcAlias); - if (sourceType == null || !sourceType.isArray()) { - return; - } - ResolvedJavaType sourceComponentType = sourceType.getComponentType(); - ResolvedJavaType destComponentType = destVirtual.type().getComponentType(); - if (!sourceComponentType.equals(destComponentType)) { - return; - } - for (int i = 0; i < len; i++) { - LoadIndexedNode load = new LoadIndexedNode(this.asNode().graph().getAssumptions(), srcAlias, ConstantNode.forInt(i + srcPosInt, this.asNode().graph()), null, - destComponentType.getJavaKind()); - load.setNodeSourcePosition(this.asNode().getNodeSourcePosition()); - tool.addNode(load); - tool.setVirtualEntry(destVirtual, destPosInt + i, load); - } - tool.delete(); - } - } - } - } - - @Override - default boolean canDeoptimize() { - return true; - } - - @Override - default boolean hasSideEffect() { - return !getKilledLocationIdentity().isInit(); - } - - @Override - default void computeStateDuring(FrameState currentStateAfter) { - FrameState newStateDuring = currentStateAfter.duplicateModifiedDuringCall(getBci(), asNode().getStackKind()); - setStateDuring(newStateDuring); - } - } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java index 0ba9eab929d4..bfcbcd7de379 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java @@ -31,19 +31,30 @@ import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.WithExceptionNode; +import org.graalvm.compiler.nodes.java.LoadIndexedNode; +import org.graalvm.compiler.nodes.memory.MemoryAccess; import org.graalvm.compiler.nodes.memory.MemoryKill; +import org.graalvm.compiler.nodes.memory.SingleMemoryKill; +import org.graalvm.compiler.nodes.spi.Lowerable; +import org.graalvm.compiler.nodes.spi.Virtualizable; +import org.graalvm.compiler.nodes.spi.VirtualizerTool; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.nodes.virtual.VirtualArrayNode; +import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; import org.graalvm.word.LocationIdentity; @@ -54,9 +65,14 @@ * Base class for nodes that intrinsify {@link System#arraycopy}. */ @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = SIZE_64) -public abstract class BasicArrayCopyNode extends WithExceptionNode implements ArrayCopy, StateSplit { +public abstract class BasicArrayCopyNode extends WithExceptionNode implements ArrayCopy, StateSplit, Virtualizable, SingleMemoryKill, MemoryAccess, Lowerable, DeoptimizingNode.DeoptDuring { public static final NodeClass TYPE = NodeClass.create(BasicArrayCopyNode.class); + public static final int SRC_ARG = 0; + public static final int SRC_POS_ARG = 1; + public static final int DEST_ARG = 2; + public static final int DEST_POS_ARG = 3; + public static final int LENGTH_ARG = 4; @Input NodeInputList args; @@ -81,17 +97,14 @@ public BasicArrayCopyNode(NodeClass type, ValueNod this(type, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI); } - @Override public NodeInputList args() { return args; } - @Override public int getBci() { return bci; } - @Override public JavaKind getElementKind() { return elementKind; } @@ -163,4 +176,145 @@ public static JavaKind selectComponentKind(BasicArrayCopyNode arraycopy) { } return srcType.getComponentType().getJavaKind(); } + + public ValueNode getSource() { + return args().get(SRC_ARG); + } + + public ValueNode getSourcePosition() { + return args().get(SRC_POS_ARG); + } + + public ValueNode getDestination() { + return args().get(DEST_ARG); + } + + public ValueNode getDestinationPosition() { + return args().get(DEST_POS_ARG); + } + + public ValueNode getLength() { + return args().get(LENGTH_ARG); + } + + public boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) { + assert length >= 0; + return position >= 0 && position <= virtualObject.entryCount() - length; + } + + public boolean checkEntryTypes(int srcPos, int length, VirtualObjectNode src, ResolvedJavaType destComponentType, VirtualizerTool tool) { + if (destComponentType.getJavaKind() == JavaKind.Object && !destComponentType.isJavaLangObject()) { + for (int i = 0; i < length; i++) { + ValueNode entry = tool.getEntry(src, srcPos + i); + ResolvedJavaType type = StampTool.typeOrNull(entry); + if (type == null || !destComponentType.isAssignableFrom(type)) { + return false; + } + } + } + return true; + } + + /* + * Returns true if this copy doesn't require store checks. Trivially true for primitive arrays. + */ + public boolean isExact() { + ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp(NodeView.DEFAULT)); + ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp(NodeView.DEFAULT)); + if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) { + return false; + } + if ((srcType.getComponentType().getJavaKind().isPrimitive() && destType.getComponentType().equals(srcType.getComponentType())) || getSource() == getDestination()) { + return true; + } + + if (StampTool.isExactType(getDestination().stamp(NodeView.DEFAULT))) { + if (destType != null && destType.isAssignableFrom(srcType)) { + return true; + } + } + return false; + } + + @Override + public void virtualize(VirtualizerTool tool) { + ValueNode sourcePosition = tool.getAlias(getSourcePosition()); + ValueNode destinationPosition = tool.getAlias(getDestinationPosition()); + ValueNode replacedLength = tool.getAlias(getLength()); + + if (sourcePosition.isConstant() && destinationPosition.isConstant() && replacedLength.isConstant()) { + int srcPosInt = sourcePosition.asJavaConstant().asInt(); + int destPosInt = destinationPosition.asJavaConstant().asInt(); + int len = replacedLength.asJavaConstant().asInt(); + ValueNode destAlias = tool.getAlias(getDestination()); + + if (destAlias instanceof VirtualArrayNode) { + VirtualArrayNode destVirtual = (VirtualArrayNode) destAlias; + if (len < 0 || !checkBounds(destPosInt, len, destVirtual)) { + return; + } + ValueNode srcAlias = tool.getAlias(getSource()); + + if (srcAlias instanceof VirtualObjectNode) { + if (!(srcAlias instanceof VirtualArrayNode)) { + return; + } + VirtualArrayNode srcVirtual = (VirtualArrayNode) srcAlias; + if (destVirtual.componentType().getJavaKind() != srcVirtual.componentType().getJavaKind()) { + return; + } + if (!checkBounds(srcPosInt, len, srcVirtual)) { + return; + } + if (!checkEntryTypes(srcPosInt, len, srcVirtual, destVirtual.type().getComponentType(), tool)) { + return; + } + if (srcVirtual == destVirtual && srcPosInt < destPosInt) { + // must copy backwards to avoid losing elements + for (int i = len - 1; i >= 0; i--) { + tool.setVirtualEntry(destVirtual, destPosInt + i, tool.getEntry(srcVirtual, srcPosInt + i)); + } + } else { + for (int i = 0; i < len; i++) { + tool.setVirtualEntry(destVirtual, destPosInt + i, tool.getEntry(srcVirtual, srcPosInt + i)); + } + } + tool.delete(); + DebugContext debug = this.asNode().getDebug(); + if (debug.isLogEnabled()) { + debug.log("virtualized arraycopy(%s, %d, %s, %d, %d)", getSource(), srcPosInt, getDestination(), destPosInt, len); + } + } else { + ResolvedJavaType sourceType = StampTool.typeOrNull(srcAlias); + if (sourceType == null || !sourceType.isArray()) { + return; + } + ResolvedJavaType sourceComponentType = sourceType.getComponentType(); + ResolvedJavaType destComponentType = destVirtual.type().getComponentType(); + if (!sourceComponentType.equals(destComponentType)) { + return; + } + for (int i = 0; i < len; i++) { + LoadIndexedNode load = new LoadIndexedNode(this.asNode().graph().getAssumptions(), srcAlias, ConstantNode.forInt(i + srcPosInt, this.asNode().graph()), null, + destComponentType.getJavaKind()); + load.setNodeSourcePosition(this.asNode().getNodeSourcePosition()); + tool.addNode(load); + tool.setVirtualEntry(destVirtual, destPosInt + i, load); + } + tool.delete(); + } + } + } + } + + @Override + public boolean canDeoptimize() { + return true; + } + + @Override + public void computeStateDuring(FrameState currentStateAfter) { + FrameState newStateDuring = currentStateAfter.duplicateModifiedDuringCall(getBci(), asNode().getStackKind()); + setStateDuring(newStateDuring); + } } From 378f6767909dff98cae08000ea1bfb0cf1ff094d Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 6 Oct 2021 15:27:39 +0200 Subject: [PATCH 531/681] compiler: use explicit @Input instead of NodeInputList --- .../nodes/BasicArrayCopyNode.java | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java index bfcbcd7de379..5cc2f821df14 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java @@ -29,11 +29,9 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import static org.graalvm.word.LocationIdentity.any; -import jdk.vm.ci.meta.ResolvedJavaType; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -60,6 +58,7 @@ import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Base class for nodes that intrinsify {@link System#arraycopy}. @@ -68,13 +67,12 @@ public abstract class BasicArrayCopyNode extends WithExceptionNode implements ArrayCopy, StateSplit, Virtualizable, SingleMemoryKill, MemoryAccess, Lowerable, DeoptimizingNode.DeoptDuring { public static final NodeClass TYPE = NodeClass.create(BasicArrayCopyNode.class); - public static final int SRC_ARG = 0; - public static final int SRC_POS_ARG = 1; - public static final int DEST_ARG = 2; - public static final int DEST_POS_ARG = 3; - public static final int LENGTH_ARG = 4; - @Input NodeInputList args; + @Input ValueNode src; + @Input ValueNode srcPos; + @Input ValueNode dest; + @Input ValueNode destPos; + @Input ValueNode length; @OptionalInput(State) FrameState stateDuring; @@ -89,7 +87,11 @@ public abstract class BasicArrayCopyNode extends WithExceptionNode implements Ar public BasicArrayCopyNode(NodeClass type, ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, JavaKind elementKind, int bci) { super(type, StampFactory.forKind(JavaKind.Void)); this.bci = bci; - this.args = new NodeInputList<>(this, new ValueNode[]{src, srcPos, dest, destPos, length}); + this.src = src; + this.srcPos = srcPos; + this.dest = dest; + this.destPos = destPos; + this.length = length; this.elementKind = elementKind != JavaKind.Illegal ? elementKind : null; } @@ -97,10 +99,6 @@ public BasicArrayCopyNode(NodeClass type, ValueNod this(type, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI); } - public NodeInputList args() { - return args; - } - public int getBci() { return bci; } @@ -178,31 +176,31 @@ public static JavaKind selectComponentKind(BasicArrayCopyNode arraycopy) { } public ValueNode getSource() { - return args().get(SRC_ARG); + return src; } public ValueNode getSourcePosition() { - return args().get(SRC_POS_ARG); + return srcPos; } public ValueNode getDestination() { - return args().get(DEST_ARG); + return dest; } public ValueNode getDestinationPosition() { - return args().get(DEST_POS_ARG); + return destPos; } public ValueNode getLength() { - return args().get(LENGTH_ARG); + return length; } - public boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) { + public static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) { assert length >= 0; return position >= 0 && position <= virtualObject.entryCount() - length; } - public boolean checkEntryTypes(int srcPos, int length, VirtualObjectNode src, ResolvedJavaType destComponentType, VirtualizerTool tool) { + public static boolean checkEntryTypes(int srcPos, int length, VirtualObjectNode src, ResolvedJavaType destComponentType, VirtualizerTool tool) { if (destComponentType.getJavaKind() == JavaKind.Object && !destComponentType.isJavaLangObject()) { for (int i = 0; i < length; i++) { ValueNode entry = tool.getEntry(src, srcPos + i); From 5f929d65e3b477638a529837368f45df7263140c Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 6 Oct 2021 15:36:51 +0200 Subject: [PATCH 532/681] compiler: remove ArrayCopy --- .../replacements/arraycopy/ArrayCopy.java | 53 ------------------- .../nodes/BasicArrayCopyNode.java | 3 +- 2 files changed, 1 insertion(+), 55 deletions(-) delete mode 100644 compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java deleted file mode 100644 index d0cd867547ed..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopy.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2013, 2020, 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 org.graalvm.compiler.replacements.arraycopy; - -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.graph.NodeInputList; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.DeoptimizingNode; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.java.LoadIndexedNode; -import org.graalvm.compiler.nodes.memory.MemoryAccess; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.compiler.nodes.spi.Lowerable; -import org.graalvm.compiler.nodes.spi.Virtualizable; -import org.graalvm.compiler.nodes.spi.VirtualizerTool; -import org.graalvm.compiler.nodes.type.StampTool; -import org.graalvm.compiler.nodes.virtual.VirtualArrayNode; -import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaType; - -/** - * Interface for all nodes that implement the {@link System#arraycopy} operation. Provides - * implementations for most operations concerning arraycopy. - */ -public interface ArrayCopy extends Virtualizable, SingleMemoryKill, MemoryAccess, Lowerable, DeoptimizingNode.DeoptDuring { - -} diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java index 5cc2f821df14..4f7b02166950 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java @@ -53,7 +53,6 @@ import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.virtual.VirtualArrayNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; -import org.graalvm.compiler.replacements.arraycopy.ArrayCopy; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.BytecodeFrame; @@ -64,7 +63,7 @@ * Base class for nodes that intrinsify {@link System#arraycopy}. */ @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = SIZE_64) -public abstract class BasicArrayCopyNode extends WithExceptionNode implements ArrayCopy, StateSplit, Virtualizable, SingleMemoryKill, MemoryAccess, Lowerable, DeoptimizingNode.DeoptDuring { +public abstract class BasicArrayCopyNode extends WithExceptionNode implements StateSplit, Virtualizable, SingleMemoryKill, MemoryAccess, Lowerable, DeoptimizingNode.DeoptDuring { public static final NodeClass TYPE = NodeClass.create(BasicArrayCopyNode.class); From f8918bb23d05904a9c5324c5f29399cc5dfe61a6 Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt Date: Wed, 22 Sep 2021 15:31:47 +0200 Subject: [PATCH 533/681] Running LLVM unit tests on OL infrastructure --- sulong/mx.sulong/mx_sulong.py | 3 +- sulong/mx.sulong/mx_sulong_benchmarks.py | 114 +++++++++++++++++++++++ vm/mx.vm/ce-llvm | 4 + 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 vm/mx.vm/ce-llvm diff --git a/sulong/mx.sulong/mx_sulong.py b/sulong/mx.sulong/mx_sulong.py index 94e2fbacd41f..634185973afb 100644 --- a/sulong/mx.sulong/mx_sulong.py +++ b/sulong/mx.sulong/mx_sulong.py @@ -309,7 +309,8 @@ def _open_for_reading(path): mx_benchmark.add_bm_suite(mx_sulong_benchmarks.SulongBenchmarkSuite(False)) # Polybench bm suite mx_benchmark.add_bm_suite(mx_sulong_benchmarks.SulongBenchmarkSuite(True)) - +# LLVM unit tests suite +mx_benchmark.add_bm_suite(mx_sulong_benchmarks.LLVMUnitTestsSuite()) _toolchains = {} diff --git a/sulong/mx.sulong/mx_sulong_benchmarks.py b/sulong/mx.sulong/mx_sulong_benchmarks.py index 3e48d867d96d..1936abeb94b5 100644 --- a/sulong/mx.sulong/mx_sulong_benchmarks.py +++ b/sulong/mx.sulong/mx_sulong_benchmarks.py @@ -597,6 +597,117 @@ def launcher_args(self, args): def hosting_registry(self): return java_vm_registry +class LLVMUnitTestsSuite(VmBenchmarkSuite): + def __init__(self, *args, **kwargs): + super(LLVMUnitTestsSuite, self).__init__(*args, **kwargs) + self.bench_to_exec = {} + + def group(self): + return 'Graal' + + def subgroup(self): + return 'sulong' + + def name(self): + return 'llvm-unit-tests' + + def benchmarkList(self, bmSuiteArgs): + return ['llvm-test-suite'] + + def failurePatterns(self): + return [] + + def successPatterns(self): + return [re.compile(r'Testing Time')] + + def rules(self, out, benchmarks, bmSuiteArgs): + return [ + mx_benchmark.StdOutRule( + r'Passed:(\s+)(?P[\d]+)', + { + "benchmark": ("llvm-unit-tests", str), + # TODO: it's a borrowed metric name, a new one should be registered + "metric.name": "jck-passed", + "metric.type": "numeric", + "metric.value": ("", int), + "metric.score-function": "id", + "metric.better": "higher", + "metric.unit": "#" + }), + mx_benchmark.StdOutRule( + r'Failed:(\s+)(?P[\d]+)', + { + "benchmark": ("llvm-unit-tests", str), + # TODO: it's a borrowed metric name, a new one should be registered + "metric.name": "jck-failed", + "metric.type": "numeric", + "metric.value": ("", int), + "metric.score-function": "id", + "metric.better": "lower", + "metric.unit": "#" + }), + mx_benchmark.StdOutRule( + r'Testing Time:(\s+)(?P