From 0a6d3974a291d76f1e2b75beb87cc46186cdc683 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Fri, 6 Sep 2019 16:23:45 +0200 Subject: [PATCH 001/140] Tweak first license paragraph * Remove (wrong) version number * Remove JVMCI mention * Remove useless first sentence --- vm/LICENSE_GRAALVM_CE | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/vm/LICENSE_GRAALVM_CE b/vm/LICENSE_GRAALVM_CE index e9c485c03466..7b2d5ff39796 100644 --- a/vm/LICENSE_GRAALVM_CE +++ b/vm/LICENSE_GRAALVM_CE @@ -1,12 +1,11 @@ - Product License - GraalVM Community Edition 19.0 - -This is a release of GraalVM Community Edition 19.0. GraalVM Community Edition -19.0 consists of multiple modules. The software as a whole, as well as the JVMCI -are released under version 2 of the GNU General Public License with the -“Classpath” Exception. Certain modules of GraalVM Community Edition 19.0 are -released under separate and/or additional licenses, as follows: Graal.js and -Graal Node.js are released under the Universal Permissive License (UPL) -Version 1.0; Sulong – LLVM is released under a 3-clause BSD license. + Product License - GraalVM Community Edition + +GraalVM Community Edition consists of multiple modules. The software as a +whole, is released under version 2 of the GNU General Public License with the +“Classpath” Exception. Certain modules of GraalVM Community Edition are released +under separate and/or additional licenses, as follows: Graal.js and Graal +Node.js are released under the Universal Permissive License (UPL) Version 1.0; +Sulong – LLVM is released under a 3-clause BSD license. The text of the foregoing licenses is reproduced below. From 747d9b3273c1e48e068e7472e81ee817df0270d8 Mon Sep 17 00:00:00 2001 From: Fred Morcos Date: Wed, 18 Sep 2019 16:38:53 +0200 Subject: [PATCH 002/140] Sulong: Implement 80-bit float -> unsigned short conversion --- .../oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java index c2937650850f..e882657c4fcc 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java @@ -616,6 +616,10 @@ public static LLVM80BitFloat fromUnsignedByte(byte from) { return fromInt(from & Byte.MIN_VALUE); } + public static LLVM80BitFloat fromUnsignedShort(short from) { + return fromUnsignedInt(from & 0xFFFF); + } + public static LLVM80BitFloat fromShort(short from) { return fromInt(from); } From 44b7a5dc49f7f3583e8d76866e77878ffd9648ba Mon Sep 17 00:00:00 2001 From: Fred Morcos Date: Wed, 18 Sep 2019 16:39:30 +0200 Subject: [PATCH 003/140] Sulong: Add missing casts to 80-bit floats Casts from: - Signed and unsigned boolean - Unsigned short --- .../nodes/cast/LLVMTo80BitFloatingNode.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMTo80BitFloatingNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMTo80BitFloatingNode.java index 0dad153d981b..6d3b7e79ac10 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMTo80BitFloatingNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMTo80BitFloatingNode.java @@ -69,6 +69,15 @@ protected LLVMTo80BitFloatingNode createRecursive() { return LLVMSignedCastToLLVM80BitFloatNodeGen.create(null); } + @Specialization + protected LLVM80BitFloat doLLVM80BitFloatNode(boolean from) { + if (from) { + return LLVM80BitFloat.fromShort((short) 1); + } else { + return LLVM80BitFloat.fromShort((short) 0); + } + } + @Specialization protected LLVM80BitFloat do80BitFloat(byte from) { return LLVM80BitFloat.fromByte(from); @@ -118,11 +127,25 @@ protected LLVMTo80BitFloatingNode createRecursive() { return LLVMUnsignedCastToLLVM80BitFloatNodeGen.create(null); } + @Specialization + protected LLVM80BitFloat doLLVM80BitFloatNode(boolean from) { + if (from) { + return LLVM80BitFloat.fromUnsignedShort((short) 1); + } else { + return LLVM80BitFloat.fromUnsignedShort((short) 0); + } + } + @Specialization protected LLVM80BitFloat do80BitFloat(byte from) { return LLVM80BitFloat.fromUnsignedByte(from); } + @Specialization + protected LLVM80BitFloat do80BitFloat(short from) { + return LLVM80BitFloat.fromUnsignedShort(from); + } + @Specialization protected LLVM80BitFloat doLLVM80BitFloatNode(int from) { return LLVM80BitFloat.fromUnsignedInt(from); From d8f385468464d6cdd973e8aee04feec48d89aaa3 Mon Sep 17 00:00:00 2001 From: Fred Morcos Date: Fri, 20 Sep 2019 11:14:11 +0200 Subject: [PATCH 004/140] Sulong: Fix conversion from byte to 80-bit float --- .../oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java index e882657c4fcc..1c0f5edd5cf3 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/floating/LLVM80BitFloat.java @@ -613,7 +613,7 @@ public static LLVM80BitFloat fromByte(byte from) { } public static LLVM80BitFloat fromUnsignedByte(byte from) { - return fromInt(from & Byte.MIN_VALUE); + return fromInt(from & 0xFF); } public static LLVM80BitFloat fromUnsignedShort(short from) { From 224b91f85d30c3bdfdd2a81dad8488c1e4784afc Mon Sep 17 00:00:00 2001 From: Josef Haider Date: Fri, 23 Aug 2019 17:05:07 +0200 Subject: [PATCH 005/140] TRegex: implement NFA-based executors --- .../tregex/matchers/MatcherBuilderTest.java | 16 +- .../truffle/regex/RegexExecRootNode.java | 4 +- .../oracle/truffle/regex/RegexProfile.java | 28 +- .../oracle/truffle/regex/charset/CharSet.java | 10 + .../charset/ImmutableSortedListOfRanges.java | 147 ++++++----- .../literal/LiteralRegexExecRootNode.java | 2 +- .../regex/result/LazyCaptureGroupsResult.java | 33 ++- .../truffle/regex/result/LazyResult.java | 5 + .../truffle/regex/result/NoMatchResult.java | 10 + .../truffle/regex/result/RegexResult.java | 4 + .../regex/result/RegexResultGetStartNode.java | 5 +- .../regex/result/SingleIndexArrayResult.java | 18 ++ .../truffle/regex/result/SingleResult.java | 17 ++ .../regex/result/SingleResultLazyStart.java | 47 +++- .../regex/result/TraceFinderResult.java | 42 ++- .../nodes/TraceFinderGetResultNode.java | 11 +- .../tregex/TRegexCompilationRequest.java | 78 ++++-- .../truffle/regex/tregex/TRegexCompiler.java | 10 +- .../truffle/regex/tregex/TRegexOptions.java | 14 +- .../automaton/StateSetBackingBitSet.java | 2 +- .../tregex/automaton/StateSetBackingSet.java | 2 +- .../automaton/StateSetBackingSortedArray.java | 2 +- .../StateTransitionCanonicalizer.java | 10 +- .../tregex/buffer/ObjectArrayBuffer.java | 12 + .../dfa/DFACaptureGroupTransitionBuilder.java | 4 +- .../regex/tregex/dfa/DFAGenerator.java | 33 +-- .../regex/tregex/dfa/DFAStateNodeBuilder.java | 2 +- .../tregex/matchers/ProfilingCharMatcher.java | 2 +- .../oracle/truffle/regex/tregex/nfa/NFA.java | 6 +- .../regex/tregex/nfa/NFAGenerator.java | 28 +- .../truffle/regex/tregex/nfa/NFAState.java | 121 ++++++--- .../tregex/nfa/NFATraceFinderGenerator.java | 34 +-- .../tregex/nodes/TRegexExecRootNode.java | 248 ++++++++++++------ ...Node.java => TRegexExecutorEntryNode.java} | 28 +- .../tregex/nodes/TRegexExecutorLocals.java | 89 +++++++ .../tregex/nodes/TRegexExecutorNode.java | 63 +++++ .../AllTransitionsInOneTreeMatcher.java | 2 +- .../nodes/{ => dfa}/BackwardDFAStateNode.java | 2 +- .../{ => dfa}/CGTrackingDFAStateNode.java | 24 +- .../nodes/{ => dfa}/DFAAbstractStateNode.java | 2 +- .../DFACaptureGroupLazyTransitionNode.java | 2 +- ...ureGroupPartialTransitionDispatchNode.java | 2 +- .../DFACaptureGroupPartialTransitionNode.java | 5 +- .../DFACaptureGroupTrackingData.java | 2 +- .../DFAFindInnerLiteralStateNode.java | 2 +- .../nodes/{ => dfa}/DFAInitialStateNode.java | 2 +- .../tregex/nodes/{ => dfa}/DFAStateNode.java | 9 +- .../TRegexDFAExecutorDebugRecorder.java | 9 +- .../{ => dfa}/TRegexDFAExecutorLocals.java | 61 +---- .../{ => dfa}/TRegexDFAExecutorNode.java | 43 ++- .../TRegexDFAExecutorProperties.java | 4 +- .../TRegexLazyCaptureGroupsRootNode.java | 11 +- .../TRegexLazyFindStartRootNode.java | 11 +- .../{ => dfa}/TraceFinderDFAStateNode.java | 2 +- .../nodes/input/InputIndexOfStringNode.java | 2 +- .../nodes/input/InputRegionMatchesNode.java | 43 ++- .../TRegexBacktrackingNFAExecutorLocals.java | 124 +++++++++ .../TRegexBacktrackingNFAExecutorNode.java | 136 ++++++++++ .../nodes/nfa/TRegexNFAExecutorLocals.java | 149 +++++++++++ .../nodes/nfa/TRegexNFAExecutorNode.java | 145 ++++++++++ .../tregex/nodesplitter/DFANodeSplit.java | 4 +- .../regex/tregex/nodesplitter/GraphNode.java | 4 +- .../regex/tregex/parser/RegexParser.java | 50 +++- .../truffle/regex/tregex/parser/Token.java | 32 +++ .../tregex/parser/ast/BackReference.java | 11 +- .../tregex/parser/ast/CharacterClass.java | 3 +- .../regex/tregex/parser/ast/Group.java | 12 +- .../tregex/parser/ast/GroupBoundaries.java | 28 +- .../parser/ast/LookBehindAssertion.java | 8 +- .../regex/tregex/parser/ast/RegexAST.java | 2 +- .../regex/tregex/parser/ast/Sequence.java | 55 ++++ .../truffle/regex/tregex/parser/ast/Term.java | 6 + .../ast/visitors/CalcMinPathsVisitor.java | 27 +- .../visitors/NFATraversalRegexASTVisitor.java | 2 +- .../ast/visitors/PreCalcResultVisitor.java | 38 ++- .../truffle/regex/tregex/util/DFAExport.java | 2 +- .../truffle/regex/tregex/util/NFAExport.java | 14 +- 77 files changed, 1771 insertions(+), 508 deletions(-) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{TRegexDFAExecutorEntryNode.java => TRegexExecutorEntryNode.java} (78%) create mode 100644 regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorLocals.java create mode 100644 regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/AllTransitionsInOneTreeMatcher.java (99%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/BackwardDFAStateNode.java (98%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/CGTrackingDFAStateNode.java (95%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/DFAAbstractStateNode.java (98%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/DFACaptureGroupLazyTransitionNode.java (98%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/DFACaptureGroupPartialTransitionDispatchNode.java (99%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/DFACaptureGroupPartialTransitionNode.java (99%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/DFACaptureGroupTrackingData.java (97%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/DFAFindInnerLiteralStateNode.java (98%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/DFAInitialStateNode.java (98%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/DFAStateNode.java (97%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/TRegexDFAExecutorDebugRecorder.java (95%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/TRegexDFAExecutorLocals.java (65%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/TRegexDFAExecutorNode.java (91%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/TRegexDFAExecutorProperties.java (95%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/TRegexLazyCaptureGroupsRootNode.java (86%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/TRegexLazyFindStartRootNode.java (85%) rename regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/{ => dfa}/TraceFinderDFAStateNode.java (98%) create mode 100644 regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorLocals.java create mode 100644 regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java create mode 100644 regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java create mode 100644 regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java diff --git a/regex/src/com.oracle.truffle.regex.test/src/com/oracle/truffle/regex/tregex/matchers/MatcherBuilderTest.java b/regex/src/com.oracle.truffle.regex.test/src/com/oracle/truffle/regex/tregex/matchers/MatcherBuilderTest.java index 9036e76d2e12..4f672ae50e3e 100644 --- a/regex/src/com.oracle.truffle.regex.test/src/com/oracle/truffle/regex/tregex/matchers/MatcherBuilderTest.java +++ b/regex/src/com.oracle.truffle.regex.test/src/com/oracle/truffle/regex/tregex/matchers/MatcherBuilderTest.java @@ -25,6 +25,7 @@ package com.oracle.truffle.regex.tregex.matchers; import com.oracle.truffle.regex.charset.CharSet; +import com.oracle.truffle.regex.charset.ImmutableSortedListOfRanges; import com.oracle.truffle.regex.tregex.buffer.CompilationBuffer; import static org.junit.Assert.assertTrue; @@ -52,6 +53,10 @@ private static CharSet multi(char... values) { return CharSet.create(values); } + private static String matchError(String errorMsg, CharSet m, CharSet expected) { + return String.format("%s: got %s, expected %s", errorMsg, m, expected); + } + private static String matchError(String errorMsg, CharSet m, char[] values) { StringBuilder sb = new StringBuilder(errorMsg).append(": got ").append(m.toString()).append(", expected [ "); for (int i = 0; i < values.length; i += 2) { @@ -61,7 +66,7 @@ private static String matchError(String errorMsg, CharSet m, char[] values) { } private static void checkMatch(String errorMsg, CharSet m, CharSet expected) { - checkMatch(errorMsg, m, expected.getRanges()); + Assert.assertArrayEquals(matchError(errorMsg, m, expected), expected.getRanges(), m.getRanges()); } private static void checkMatch(String errorMsg, CharSet m, char... values) { @@ -81,11 +86,10 @@ private static void checkIntersection(CharSet a, CharSet b, char... values) { CharSet intersection = a.createIntersection(b, new CompilationBuffer()); checkMatch("intersection(" + a + "," + b + ")", intersection, values); assertTrue("intersection(" + a + "," + b + ")", a.intersects(b) == intersection.matchesSomething()); - CharSet[] result = new CharSet[3]; - a.intersectAndSubtract(b, new CompilationBuffer(), result); - checkMatch("intersectAndSubtract(" + a + "," + b + ")[0]", result[0], a.subtract(intersection, new CompilationBuffer())); - checkMatch("intersectAndSubtract(" + a + "," + b + ")[1]", result[1], b.subtract(intersection, new CompilationBuffer())); - checkMatch("intersectAndSubtract(" + a + "," + b + ")[2]", result[2], intersection); + ImmutableSortedListOfRanges.IntersectAndSubtractResult result = a.intersectAndSubtract(b, new CompilationBuffer()); + checkMatch("intersectAndSubtract(" + a + "," + b + ")[0]", result.subtractedA, a.subtract(intersection, new CompilationBuffer())); + checkMatch("intersectAndSubtract(" + a + "," + b + ")[1]", result.subtractedB, b.subtract(intersection, new CompilationBuffer())); + checkMatch("intersectAndSubtract(" + a + "," + b + ")[2]", result.intersection, intersection); } private static void checkSubtraction(CharSet a, CharSet b, char... values) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecRootNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecRootNode.java index c4c5d3edc290..203509442efc 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecRootNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecRootNode.java @@ -59,7 +59,7 @@ private int adjustFromIndex(int fromIndex, Object input) { return fromIndex; } - protected int inputLength(Object input) { + public int inputLength(Object input) { if (lengthNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); lengthNode = insert(InputLengthNode.create()); @@ -67,7 +67,7 @@ protected int inputLength(Object input) { return lengthNode.execute(input); } - protected char inputCharAt(Object input, int i) { + public char inputCharAt(Object input, int i) { if (charAtNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); charAtNode = insert(InputCharAtNode.create()); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexProfile.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexProfile.java index 9e9586b26b2a..1414c2eb16f8 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexProfile.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexProfile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,7 +24,8 @@ */ package com.oracle.truffle.regex; -import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.regex.tregex.TRegexOptions; import com.oracle.truffle.regex.tregex.parser.Counter; /** @@ -34,7 +35,7 @@ * capture groups in a lazy or eager way. * * @see com.oracle.truffle.regex.tregex.nodes.TRegexExecRootNode - * @see com.oracle.truffle.regex.tregex.nodes.TRegexLazyCaptureGroupsRootNode + * @see com.oracle.truffle.regex.tregex.nodes.dfa.TRegexLazyCaptureGroupsRootNode */ public final class RegexProfile { @@ -53,6 +54,10 @@ public void incCalls() { calls.inc(); } + public void resetCalls() { + calls.reset(); + } + /** * Increase the number of times a match for the regular expression was found by one. */ @@ -66,7 +71,7 @@ public void incMatches() { * @param matchLength the length of capture group 0 of the match. * @param numberOfCharsTraversed the number of characters that were traversed between the * initial index (fromIndex) and the end of the match. - * @see com.oracle.truffle.regex.tregex.nodes.TRegexLazyCaptureGroupsRootNode + * @see com.oracle.truffle.regex.tregex.nodes.dfa.TRegexLazyCaptureGroupsRootNode */ public void profileCaptureGroupAccess(int matchLength, int numberOfCharsTraversed) { captureGroupAccesses.inc(); @@ -77,7 +82,7 @@ public void profileCaptureGroupAccess(int matchLength, int numberOfCharsTraverse /** * Check if the profiling information gathered so far is sufficient for making a decision. - * + * * @return {@code true} if the number of times the regular expression was called is divisible by * {@value #EVALUATION_TRIP_POINT}. */ @@ -95,10 +100,18 @@ private double cgAccessRatio() { return (double) captureGroupAccesses.getCount() / matches.getCount(); } + /** + * Decides whether the regular was executed often enough to warrant the costly generation of a + * fully expanded DFA. + */ + public boolean shouldGenerateDFA() { + return calls.getCount() >= TRegexOptions.TRegexGenerateDFAThreshold; + } + /** * Decides whether the capture groups of the regular expression should be matched in an eager * manner. - * + * * @return {@code true} if: *
    *
  • most searches led to a match
  • @@ -111,7 +124,7 @@ public boolean shouldUseEagerMatching() { return matchRatio() > 0.5 && cgAccessRatio() > 0.5 && (avgMatchLength < 5 || avgMatchedPortionOfSearchSpace > 0.4); } - @CompilerDirectives.TruffleBoundary + @TruffleBoundary @Override public String toString() { return String.format("calls: %d, matches: %d (%.2f%%), cg accesses: %d (%.2f%%), avg matched portion of search space: %.2f%%", @@ -121,5 +134,4 @@ public String toString() { public interface TracksRegexProfile { RegexProfile getRegexProfile(); } - } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java index f83fe4122bc9..46005d29fe1a 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java @@ -215,6 +215,16 @@ private static void setRange(char[] arr, int i, int lo, int hi) { arr[i * 2 + 1] = (char) hi; } + @Override + public boolean matchesNothing() { + return this == getEmpty(); + } + + @Override + public boolean matchesEverything() { + return this == getFull(); + } + @SuppressWarnings("unchecked") @Override public CharSet createEmpty() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/ImmutableSortedListOfRanges.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/ImmutableSortedListOfRanges.java index bcbfb639e8ff..a8ac1ea6c5b9 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/ImmutableSortedListOfRanges.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/ImmutableSortedListOfRanges.java @@ -174,23 +174,34 @@ default T subtract(T o, CompilationBuffer compila return create(subtractionRanges); } + final class IntersectAndSubtractResult { + + public final T subtractedA; + public final T subtractedB; + public final T intersection; + + public IntersectAndSubtractResult(T subtractedA, T subtractedB, T intersected) { + this.subtractedA = subtractedA; + this.subtractedB = subtractedB; + this.intersection = intersected; + } + } + /** * Calculates the intersection and the "rest" of this and {@code o}. Uses * {@link #getBuffer1(CompilationBuffer)}, {@link #getBuffer2(CompilationBuffer)} and * {@link #getBuffer3(CompilationBuffer)}. * * @param o MatcherBuilder to intersect with. - * @param result Array of results, where index 0 is equal to {@code this.subtract(intersection)} - * , index 1 is equal to {@code o.subtract(intersection)} and index 2 is equal to - * {@code this.createIntersection(o)}. + * @return a new {@link IntersectAndSubtractResult}, where field {@code subtractedA} is equal to + * {@code this.subtract(intersection)}, {@code subtractedB} is equal to + * {@code o.subtract(intersection)} and {@code intersected} is equal to + * {@code this.createIntersection(o)} */ @SuppressWarnings("unchecked") - default void intersectAndSubtract(T o, CompilationBuffer compilationBuffer, T[] result) { + default IntersectAndSubtractResult intersectAndSubtract(T o, CompilationBuffer compilationBuffer) { if (matchesNothing() || o.matchesNothing()) { - result[0] = (T) this; - result[1] = o; - result[2] = createEmpty(); - return; + return new IntersectAndSubtractResult<>((T) this, o, createEmpty()); } RangesBuffer subtractedA = getBuffer1(compilationBuffer); RangesBuffer subtractedB = getBuffer2(compilationBuffer); @@ -205,23 +216,18 @@ default void intersectAndSubtract(T o, C noIntersection = true; break; } - continue; - } - if (o.leftOf(ib, this, ia)) { + } else if (o.leftOf(ib, this, ia)) { ib++; if (ib >= o.size()) { noIntersection = true; break; } - continue; + } else { + break; } - break; } if (noIntersection) { - result[0] = (T) this; - result[1] = o; - result[2] = createEmpty(); - return; + return new IntersectAndSubtractResult<>((T) this, o, createEmpty()); } appendRangesTo(subtractedA, 0, ia); o.appendRangesTo(subtractedB, 0, ib); @@ -232,82 +238,97 @@ default void intersectAndSubtract(T o, C assert SortedListOfRanges.intersects(raLo, raHi, rbLo, rbHi); ia++; ib++; - boolean advanceA = false; - boolean advanceB = false; - boolean finish = false; while (true) { - if (advanceA) { - advanceA = false; + if (SortedListOfRanges.leftOf(raLo, raHi, rbLo, rbHi)) { + subtractedA.appendRange(raLo, raHi); if (ia < size()) { raLo = getLo(ia); raHi = getHi(ia); ia++; + continue; } else { - if (!advanceB) { - subtractedB.appendRange(rbLo, rbHi); - } + subtractedB.appendRange(rbLo, rbHi); o.appendRangesTo(subtractedB, ib, o.size()); - finish = true; + break; } } - if (advanceB) { - advanceB = false; + if (SortedListOfRanges.leftOf(rbLo, rbHi, raLo, raHi)) { + subtractedB.appendRange(rbLo, rbHi); if (ib < o.size()) { rbLo = o.getLo(ib); rbHi = o.getHi(ib); ib++; + continue; } else { - if (!finish) { - subtractedA.appendRange(raLo, raHi); - } + subtractedA.appendRange(raLo, raHi); appendRangesTo(subtractedA, ia, size()); - finish = true; + break; } } - if (finish) { - break; - } - if (SortedListOfRanges.leftOf(raLo, raHi, rbLo, rbHi)) { - subtractedA.appendRange(raLo, raHi); - advanceA = true; - continue; - } - if (SortedListOfRanges.leftOf(rbLo, rbHi, raLo, raHi)) { - subtractedB.appendRange(rbLo, rbHi); - advanceB = true; - continue; - } assert SortedListOfRanges.intersects(raLo, raHi, rbLo, rbHi); - int intersectionLo = Math.max(raLo, rbLo); - int intersectionHi = Math.min(raHi, rbHi); - intersectionRanges.appendRange(intersectionLo, intersectionHi); - if (raLo < intersectionLo) { + int intersectionLo = raLo; + if (raLo < rbLo) { + intersectionLo = rbLo; subtractedA.appendRange(raLo, intersectionLo - 1); - } - if (raHi > intersectionHi) { - raLo = intersectionHi + 1; - } else { - advanceA = true; - } - if (rbLo < intersectionLo) { + } else if (raLo != rbLo) { subtractedB.appendRange(rbLo, intersectionLo - 1); } - if (rbHi > intersectionHi) { + int intersectionHi = raHi; + if (raHi > rbHi) { + intersectionHi = rbHi; + intersectionRanges.appendRange(intersectionLo, intersectionHi); + raLo = intersectionHi + 1; + if (ib < o.size()) { + rbLo = o.getLo(ib); + rbHi = o.getHi(ib); + ib++; + } else { + subtractedA.appendRange(raLo, raHi); + appendRangesTo(subtractedA, ia, size()); + break; + } + } else if (raHi < rbHi) { + intersectionRanges.appendRange(intersectionLo, intersectionHi); rbLo = intersectionHi + 1; + if (ia < size()) { + raLo = getLo(ia); + raHi = getHi(ia); + ia++; + } else { + subtractedB.appendRange(rbLo, rbHi); + o.appendRangesTo(subtractedB, ib, o.size()); + break; + } } else { - advanceB = true; + assert raHi == rbHi; + intersectionRanges.appendRange(intersectionLo, intersectionHi); + if (ia < size()) { + raLo = getLo(ia); + raHi = getHi(ia); + ia++; + } else { + o.appendRangesTo(subtractedB, ib, o.size()); + break; + } + if (ib < o.size()) { + rbLo = o.getLo(ib); + rbHi = o.getHi(ib); + ib++; + } else { + subtractedA.appendRange(raLo, raHi); + appendRangesTo(subtractedA, ia, size()); + break; + } } } - result[0] = create(subtractedA); - result[1] = create(subtractedB); if (subtractedA.isEmpty()) { assert equalsBuffer(intersectionRanges); - result[2] = (T) this; + return new IntersectAndSubtractResult<>(createEmpty(), create(subtractedB), (T) this); } else if (subtractedB.isEmpty()) { assert o.equalsBuffer(intersectionRanges); - result[2] = o; + return new IntersectAndSubtractResult<>(create(subtractedA), createEmpty(), o); } else { - result[2] = create(intersectionRanges); + return new IntersectAndSubtractResult<>(create(subtractedA), create(subtractedB), create(intersectionRanges)); } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/literal/LiteralRegexExecRootNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/literal/LiteralRegexExecRootNode.java index 13505d9f64e0..2702ae798dfc 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/literal/LiteralRegexExecRootNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/literal/LiteralRegexExecRootNode.java @@ -264,7 +264,7 @@ protected String getImplName() { @Override protected RegexResult execute(Object input, int fromIndex) { - if (regionMatchesNode.execute(input, fromIndex, literal, mask)) { + if (regionMatchesNode.execute(input, fromIndex, literal, 0, literal.length(), mask)) { return resultFactory.createFromStart(fromIndex); } else { return NoMatchResult.getInstance(); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/LazyCaptureGroupsResult.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/LazyCaptureGroupsResult.java index f995b714a1f7..3365ab4b4b57 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/LazyCaptureGroupsResult.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/LazyCaptureGroupsResult.java @@ -24,12 +24,10 @@ */ package com.oracle.truffle.regex.result; -import java.util.Arrays; - import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.regex.tregex.nodes.TRegexLazyCaptureGroupsRootNode; -import com.oracle.truffle.regex.tregex.nodes.TRegexLazyFindStartRootNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexLazyCaptureGroupsRootNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexLazyFindStartRootNode; import com.oracle.truffle.regex.tregex.util.json.Json; import com.oracle.truffle.regex.tregex.util.json.JsonConvertible; import com.oracle.truffle.regex.tregex.util.json.JsonObject; @@ -55,6 +53,16 @@ public LazyCaptureGroupsResult(Object input, int[] result) { this.result = result; } + @Override + public int getStart(int groupNumber) { + return result[groupNumber * 2] - 1; + } + + @Override + public int getEnd(int groupNumber) { + return result[groupNumber * 2 + 1] - 1; + } + public void setResult(int[] result) { this.result = result; } @@ -112,11 +120,14 @@ public Object[] createArgsCGNoFindStart() { * {@link com.oracle.truffle.regex.runtime.nodes.LazyCaptureGroupGetResultNode} instead! */ @TruffleBoundary + @Override public void debugForceEvaluation() { - if (getFindStartCallTarget() == null) { - getCaptureGroupCallTarget().call(createArgsCGNoFindStart()); - } else { - getCaptureGroupCallTarget().call(createArgsCG((int) getFindStartCallTarget().call(createArgsFindStart()))); + if (result == null) { + if (getFindStartCallTarget() == null) { + getCaptureGroupCallTarget().call(createArgsCGNoFindStart()); + } else { + getCaptureGroupCallTarget().call(createArgsCG((int) getFindStartCallTarget().call(createArgsFindStart()))); + } } } @@ -126,7 +137,11 @@ public String toString() { if (result == null) { debugForceEvaluation(); } - return Arrays.toString(result); + StringBuilder sb = new StringBuilder("[").append(result[0] - 1); + for (int i = 1; i < result.length; i++) { + sb.append(", ").append(result[i] - 1); + } + return sb.append("]").toString(); } @TruffleBoundary diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/LazyResult.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/LazyResult.java index cfe7016f8406..4b1858bd5270 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/LazyResult.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/LazyResult.java @@ -53,6 +53,11 @@ public int getEnd() { return end; } + /** + * Forces evaluation of this lazy regex result. For debugging purposes only. + */ + public abstract void debugForceEvaluation(); + @TruffleBoundary @Override public JsonObject toJson() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/NoMatchResult.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/NoMatchResult.java index c6ec06b3244e..fd09e847cbd5 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/NoMatchResult.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/NoMatchResult.java @@ -39,4 +39,14 @@ private NoMatchResult() { public String toString() { return "NO_MATCH"; } + + @Override + public int getStart(int groupNumber) { + return -1; + } + + @Override + public int getEnd(int groupNumber) { + return -1; + } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/RegexResult.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/RegexResult.java index 42a255c4e229..13a597952fde 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/RegexResult.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/RegexResult.java @@ -75,6 +75,10 @@ public abstract class RegexResult extends AbstractConstantKeysObject { private static final TruffleReadOnlyKeysArray KEYS = new TruffleReadOnlyKeysArray(PROP_IS_MATCH, PROP_GET_START, PROP_GET_END); + public abstract int getStart(int groupNumber); + + public abstract int getEnd(int groupNumber); + @Override public TruffleReadOnlyKeysArray getKeys() { return KEYS; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/RegexResultGetStartNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/RegexResultGetStartNode.java index bd15d2fb4dfb..529f637a0708 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/RegexResultGetStartNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/RegexResultGetStartNode.java @@ -64,9 +64,8 @@ static int doSingleResultLazyStart(SingleResultLazyStart receiver, int groupNumb @Cached("createBinaryProfile()") ConditionProfile boundsProfile, @Exclusive @Cached("createBinaryProfile()") ConditionProfile calcLazyProfile) { if (boundsProfile.profile(groupNumber == 0)) { - if (calcLazyProfile.profile(receiver.getStart() == -1)) { - receiver.setStart((int) calcResult.execute(receiver.getFindStartCallTarget(), - new Object[]{receiver.getInput(), receiver.getEnd() - 1, receiver.getFromIndex()}) + 1); + if (calcLazyProfile.profile(!receiver.isStartCalculated())) { + receiver.applyFindStartResult((int) calcResult.execute(receiver.getFindStartCallTarget(), receiver.createArgsFindStart())); } return receiver.getStart(); } else { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleIndexArrayResult.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleIndexArrayResult.java index bd2a3e1eb01c..c1f0a4356ba2 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleIndexArrayResult.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleIndexArrayResult.java @@ -24,7 +24,10 @@ */ package com.oracle.truffle.regex.result; +import java.util.Arrays; + import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; public final class SingleIndexArrayResult extends RegexResult { @@ -38,4 +41,19 @@ public int[] getIndices() { return indices; } + @Override + public int getStart(int groupNumber) { + return indices[groupNumber * 2]; + } + + @Override + public int getEnd(int groupNumber) { + return indices[groupNumber * 2 + 1]; + } + + @TruffleBoundary + @Override + public String toString() { + return Arrays.toString(indices); + } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleResult.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleResult.java index 4164d2684a17..446ee3654788 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleResult.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleResult.java @@ -24,6 +24,8 @@ */ package com.oracle.truffle.regex.result; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; + public final class SingleResult extends RegexResult { private final int start; @@ -42,4 +44,19 @@ public int getEnd() { return end; } + @Override + public int getStart(int groupNumber) { + return groupNumber == 0 ? start : -1; + } + + @Override + public int getEnd(int groupNumber) { + return groupNumber == 0 ? end : -1; + } + + @TruffleBoundary + @Override + public String toString() { + return "[" + start + ", " + end + "]"; + } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleResultLazyStart.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleResultLazyStart.java index 40da6e8a6175..05facf199c53 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleResultLazyStart.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/SingleResultLazyStart.java @@ -25,6 +25,7 @@ package com.oracle.truffle.regex.result; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; public final class SingleResultLazyStart extends LazyResult { @@ -36,16 +37,54 @@ public SingleResultLazyStart(Object input, int fromIndex, int end, CallTarget fi this.findStartCallTarget = findStartCallTarget; } - public int getStart() { - return start; + @Override + public int getStart(int groupNumber) { + return groupNumber == 0 ? start : -1; + } + + @Override + public int getEnd(int groupNumber) { + return groupNumber == 0 ? getEnd() : -1; } - public void setStart(int start) { - this.start = start; + public boolean isStartCalculated() { + return start != -1; + } + + public int getStart() { + return start; } public CallTarget getFindStartCallTarget() { return findStartCallTarget; } + public Object[] createArgsFindStart() { + return new Object[]{getInput(), getEnd() - 1, getFromIndex()}; + } + + public void applyFindStartResult(int findStartResult) { + this.start = findStartResult + 1; + } + + /** + * Forces evaluation of this lazy regex result. Do not use this method on any fast paths, use + * {@link com.oracle.truffle.regex.result.RegexResultGetStartNode} instead! + */ + @TruffleBoundary + @Override + public void debugForceEvaluation() { + if (!isStartCalculated()) { + applyFindStartResult((int) findStartCallTarget.call(createArgsFindStart())); + } + } + + @TruffleBoundary + @Override + public String toString() { + if (!isStartCalculated()) { + debugForceEvaluation(); + } + return "[" + start + ", " + getEnd() + "]"; + } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/TraceFinderResult.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/TraceFinderResult.java index 5ac0a5ec2bfb..27b80c7d1af6 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/TraceFinderResult.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/result/TraceFinderResult.java @@ -24,8 +24,11 @@ */ package com.oracle.truffle.regex.result; +import java.util.Arrays; + import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; public final class TraceFinderResult extends LazyResult { @@ -41,6 +44,16 @@ public TraceFinderResult(Object input, int fromIndex, int end, CallTarget traceF this.preCalculatedResults = preCalculatedResults; } + @Override + public int getStart(int groupNumber) { + return indices[groupNumber * 2]; + } + + @Override + public int getEnd(int groupNumber) { + return indices[groupNumber * 2 + 1]; + } + public int[] getIndices() { return indices; } @@ -57,8 +70,33 @@ public boolean isResultCalculated() { return resultCalculated; } - public void setResultCalculated() { - this.resultCalculated = true; + public Object[] createArgsTraceFinder() { + return new Object[]{getInput(), getEnd() - 1, getFromIndex()}; } + public void applyTraceFinderResult(int preCalcIndex) { + preCalculatedResults[preCalcIndex].applyRelativeToEnd(indices, getEnd()); + resultCalculated = true; + } + + /** + * Forces evaluation of this lazy regex result. Do not use this method on any fast paths, use + * {@link com.oracle.truffle.regex.runtime.nodes.TraceFinderGetResultNode} instead! + */ + @TruffleBoundary + @Override + public void debugForceEvaluation() { + if (!isResultCalculated()) { + applyTraceFinderResult((int) traceFinderCallTarget.call(createArgsTraceFinder())); + } + } + + @TruffleBoundary + @Override + public String toString() { + if (!isResultCalculated()) { + debugForceEvaluation(); + } + return Arrays.toString(indices); + } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/runtime/nodes/TraceFinderGetResultNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/runtime/nodes/TraceFinderGetResultNode.java index 75b4af73c6b4..8e6cd785e07b 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/runtime/nodes/TraceFinderGetResultNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/runtime/nodes/TraceFinderGetResultNode.java @@ -40,14 +40,9 @@ public abstract class TraceFinderGetResultNode extends Node { static int[] doTraceFinderCalc(TraceFinderResult receiver, @Cached("createBinaryProfile()") ConditionProfile conditionProfile, @Cached DispatchNode calcResult) { - if (conditionProfile.profile(receiver.isResultCalculated())) { - return receiver.getIndices(); - } else { - receiver.setResultCalculated(); - final int preCalcIndex = (int) calcResult.execute(receiver.getTraceFinderCallTarget(), - new Object[]{receiver.getInput(), receiver.getEnd() - 1, receiver.getFromIndex()}); - receiver.getPreCalculatedResults()[preCalcIndex].applyRelativeToEnd(receiver.getIndices(), receiver.getEnd()); - return receiver.getIndices(); + if (conditionProfile.profile(!receiver.isResultCalculated())) { + receiver.applyTraceFinderResult((int) calcResult.execute(receiver.getTraceFinderCallTarget(), receiver.createArgsTraceFinder())); } + return receiver.getIndices(); } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompilationRequest.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompilationRequest.java index b83df0ec1296..7b827e85c290 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompilationRequest.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompilationRequest.java @@ -50,9 +50,10 @@ import com.oracle.truffle.regex.tregex.nfa.NFA; import com.oracle.truffle.regex.tregex.nfa.NFAGenerator; import com.oracle.truffle.regex.tregex.nfa.NFATraceFinderGenerator; -import com.oracle.truffle.regex.tregex.nodes.TRegexDFAExecutorNode; -import com.oracle.truffle.regex.tregex.nodes.TRegexDFAExecutorProperties; import com.oracle.truffle.regex.tregex.nodes.TRegexExecRootNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexDFAExecutorNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexDFAExecutorProperties; +import com.oracle.truffle.regex.tregex.nodes.nfa.TRegexNFAExecutorNode; import com.oracle.truffle.regex.tregex.parser.RegexParser; import com.oracle.truffle.regex.tregex.parser.RegexProperties; import com.oracle.truffle.regex.tregex.parser.ast.RegexAST; @@ -80,6 +81,7 @@ public final class TRegexCompilationRequest { private RegexAST ast = null; private NFA nfa = null; private NFA traceFinderNFA = null; + private TRegexExecRootNode root = null; private TRegexDFAExecutorNode executorNodeForward = null; private TRegexDFAExecutorNode executorNodeBackward = null; private TRegexDFAExecutorNode executorNodeCaptureGroups = null; @@ -90,6 +92,17 @@ public final class TRegexCompilationRequest { this.source = source; } + TRegexCompilationRequest(TRegexCompiler tRegexCompiler, NFA nfa) { + this.tRegexCompiler = tRegexCompiler; + this.source = nfa.getAst().getSource(); + this.ast = nfa.getAst(); + this.nfa = nfa; + } + + public TRegexExecRootNode getRoot() { + return root; + } + @TruffleBoundary CompiledRegexObject compile() { try { @@ -107,7 +120,12 @@ CompiledRegexObject compile() { @TruffleBoundary private RegexExecRootNode compileInternal() { LOG_TREGEX_COMPILATIONS.finer(() -> String.format("TRegex compiling %s\n%s", DebugUtil.jsStringEscape(source.toString()), new RegexUnifier(source).getUnifiedPattern())); - createAST(); + RegexParser regexParser = createParser(); + phaseStart("Parser"); + ast = regexParser.parse(); + regexParser.prepareForDFA(); + phaseEnd("Parser"); + debugAST(); RegexProperties properties = ast.getProperties(); checkFeatureSupport(properties); if (ast.getRoot().isDead()) { @@ -117,14 +135,24 @@ private RegexExecRootNode compileInternal() { if (literal != null) { return literal; } - PreCalculatedResultFactory[] preCalculatedResults = null; - if (!(properties.hasAlternations() || properties.hasLookAroundAssertions())) { - preCalculatedResults = new PreCalculatedResultFactory[]{PreCalcResultVisitor.createResultFactory(ast)}; - } createNFA(); if (nfa.isDead()) { return new DeadRegexExecRootNode(tRegexCompiler.getLanguage(), source); } + return new TRegexExecRootNode(tRegexCompiler.getLanguage(), tRegexCompiler, source, ast.getFlags(), tRegexCompiler.getOptions().isRegressionTestMode(), + new TRegexNFAExecutorNode(nfa, ast.getNumberOfCaptureGroups())); + } + + @TruffleBoundary + TRegexExecRootNode.LazyCaptureGroupRegexSearchNode compileLazyDFAExecutor(TRegexExecRootNode rootNode) { + assert ast != null; + assert nfa != null; + this.root = rootNode; + RegexProperties properties = ast.getProperties(); + PreCalculatedResultFactory[] preCalculatedResults = null; + if (!(properties.hasAlternations() || properties.hasLookAroundAssertions())) { + preCalculatedResults = new PreCalculatedResultFactory[]{PreCalcResultVisitor.createResultFactory(ast)}; + } if (preCalculatedResults == null && TRegexOptions.TRegexEnableTraceFinder && !ast.getRoot().hasLoops()) { try { phaseStart("TraceFinder NFA"); @@ -149,16 +177,12 @@ private RegexExecRootNode compileInternal() { } else if (preCalculatedResults == null || !nfa.hasReverseUnAnchoredEntry()) { executorNodeBackward = createDFAExecutor(nfa, false, false, false); } - return new TRegexExecRootNode( - tRegexCompiler.getLanguage(), - tRegexCompiler, - source, - ast.getFlags(), - tRegexCompiler.getOptions().isRegressionTestMode(), - preCalculatedResults, - executorNodeForward, - executorNodeBackward, - executorNodeCaptureGroups); + return new TRegexExecRootNode.LazyCaptureGroupRegexSearchNode( + tRegexCompiler.getLanguage(), source, ast.getFlags(), preCalculatedResults, + rootNode.createEntryNode(executorNodeForward), + rootNode.createEntryNode(executorNodeBackward), + rootNode.createEntryNode(executorNodeCaptureGroups), + rootNode); } @TruffleBoundary @@ -200,6 +224,15 @@ private static boolean isSupported(RegexProperties properties) { } private void createAST() { + RegexParser regexParser = createParser(); + phaseStart("Parser"); + ast = regexParser.parse(); + regexParser.prepareForDFA(); + phaseEnd("Parser"); + debugAST(); + } + + private RegexParser createParser() { RegexOptions options = tRegexCompiler.getOptions(); RegexFlavor flavor = options.getFlavor(); RegexSource ecmascriptSource = source; @@ -209,10 +242,7 @@ private void createAST() { ecmascriptSource = flavorProcessor.toECMAScriptRegex(); phaseEnd("Flavor"); } - phaseStart("Parser"); - ast = new RegexParser(ecmascriptSource, options, compilationBuffer).parse(); - phaseEnd("Parser"); - debugAST(); + return new RegexParser(ecmascriptSource, options, compilationBuffer); } private void createNFA() { @@ -222,15 +252,11 @@ private void createNFA() { debugNFA(); } - public TRegexDFAExecutorNode createDFAExecutor(NFA nfaArg, boolean forward, boolean searching, boolean trackCaptureGroups) { + private TRegexDFAExecutorNode createDFAExecutor(NFA nfaArg, boolean forward, boolean searching, boolean trackCaptureGroups) { return createDFAExecutor(nfaArg, new TRegexDFAExecutorProperties(forward, searching, trackCaptureGroups, tRegexCompiler.getOptions().isRegressionTestMode(), nfaArg.getAst().getNumberOfCaptureGroups(), nfaArg.getAst().getRoot().getMinPath()), null); } - public TRegexDFAExecutorNode createDFAExecutor(NFA nfaArg, TRegexDFAExecutorProperties props) { - return createDFAExecutor(nfaArg, props, null); - } - public TRegexDFAExecutorNode createDFAExecutor(NFA nfaArg, TRegexDFAExecutorProperties props, String debugDumpName) { DFAGenerator dfa = new DFAGenerator(this, nfaArg, props, compilationBuffer, tRegexCompiler.getOptions()); phaseStart(dfa.getDebugDumpName(debugDumpName) + " DFA"); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompiler.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompiler.java index 1d622a7a4e38..595c9f9ee2e3 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompiler.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompiler.java @@ -31,7 +31,10 @@ import com.oracle.truffle.regex.RegexOptions; import com.oracle.truffle.regex.RegexSource; import com.oracle.truffle.regex.RegexSyntaxException; -import com.oracle.truffle.regex.tregex.nodes.TRegexDFAExecutorNode; +import com.oracle.truffle.regex.tregex.nfa.NFA; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecRootNode; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecRootNode.LazyCaptureGroupRegexSearchNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexDFAExecutorNode; public final class TRegexCompiler implements RegexCompiler { @@ -61,4 +64,9 @@ public CompiledRegexObject compile(RegexSource source) throws RegexSyntaxExcepti public TRegexDFAExecutorNode compileEagerDFAExecutor(RegexSource source) { return new TRegexCompilationRequest(this, source).compileEagerDFAExecutor(); } + + @TruffleBoundary + public LazyCaptureGroupRegexSearchNode compileLazyDFAExecutor(NFA nfa, TRegexExecRootNode rootNode) { + return new TRegexCompilationRequest(this, nfa).compileLazyDFAExecutor(rootNode); + } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexOptions.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexOptions.java index bce7b86b2771..3197e5ae2e53 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexOptions.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexOptions.java @@ -29,15 +29,23 @@ import com.oracle.truffle.regex.tregex.nfa.NFA; import com.oracle.truffle.regex.tregex.nfa.NFAGenerator; import com.oracle.truffle.regex.tregex.nfa.NFATraceFinderGenerator; -import com.oracle.truffle.regex.tregex.nodes.DFACaptureGroupPartialTransitionNode; -import com.oracle.truffle.regex.tregex.nodes.TRegexDFAExecutorNode; -import com.oracle.truffle.regex.tregex.nodes.TraceFinderDFAStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFACaptureGroupPartialTransitionNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexDFAExecutorNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TraceFinderDFAStateNode; import com.oracle.truffle.regex.tregex.nodesplitter.DFANodeSplit; import com.oracle.truffle.regex.tregex.parser.RegexParser; import com.oracle.truffle.regex.tregex.parser.ast.RegexAST; public class TRegexOptions { + /** + * Number of regex searches done without generating a DFA for a given regular expression. When + * this threshold is reached, TRegex tries to generate a fully expanded DFA to speed up further + * searches. This threshold is only checked in interpreter mode, so it should be sufficiently + * smaller than the Graal compilation threshold! + */ + public static final int TRegexGenerateDFAThreshold = 100; + /** * Try to pre-calculate results of tree-like expressions (see {@link NFATraceFinderGenerator}). * A regular expression is considered tree-like if it does not contain infinite loops (+ or *). diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingBitSet.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingBitSet.java index a6e4204bedb1..d967477af9de 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingBitSet.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingBitSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSet.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSet.java index 4e9d4169a77d..e96b2df7f1fc 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSet.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSortedArray.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSortedArray.java index c01368f7e4ac..56f572744f3c 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSortedArray.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSortedArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateTransitionCanonicalizer.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateTransitionCanonicalizer.java index f32edc7ff7e0..5d0dec15f4ab 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateTransitionCanonicalizer.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateTransitionCanonicalizer.java @@ -25,6 +25,7 @@ package com.oracle.truffle.regex.tregex.automaton; import com.oracle.truffle.regex.charset.CharSet; +import com.oracle.truffle.regex.charset.ImmutableSortedListOfRanges; import com.oracle.truffle.regex.tregex.buffer.CompilationBuffer; import org.graalvm.collections.EconomicMap; @@ -45,7 +46,6 @@ */ public abstract class StateTransitionCanonicalizer> { - private final CharSet[] intersectionResult = new CharSet[3]; private final ArrayList disjointTransitions = new ArrayList<>(); private final EconomicMap mergeSameTargetsMap = EconomicMap.create(); @@ -127,10 +127,10 @@ private void calcDisjointTransitions(List transitions, CompilationBuffer com for (TB e : transitions) { for (int i = 0; i < disjointTransitions.size(); i++) { TB r = disjointTransitions.get(i); - r.getMatcherBuilder().intersectAndSubtract(e.getMatcherBuilder(), compilationBuffer, intersectionResult); - CharSet rSubtractedMatcher = intersectionResult[0]; - CharSet eSubtractedMatcher = intersectionResult[1]; - CharSet intersection = intersectionResult[2]; + ImmutableSortedListOfRanges.IntersectAndSubtractResult result = r.getMatcherBuilder().intersectAndSubtract(e.getMatcherBuilder(), compilationBuffer); + CharSet rSubtractedMatcher = result.subtractedA; + CharSet eSubtractedMatcher = result.subtractedB; + CharSet intersection = result.intersection; if (intersection.matchesSomething()) { if (rSubtractedMatcher.matchesNothing()) { r.getTransitionSet().addAll(e.getTransitionSet()); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/buffer/ObjectArrayBuffer.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/buffer/ObjectArrayBuffer.java index 29ddd0daccdb..e1bf11498549 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/buffer/ObjectArrayBuffer.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/buffer/ObjectArrayBuffer.java @@ -75,6 +75,10 @@ public Object get(int i) { return buf[i]; } + public Object getLast() { + return buf[length() - 1]; + } + public void add(Object o) { if (length == buf.length) { grow(length * 2); @@ -83,6 +87,10 @@ public void add(Object o) { length++; } + public void addAll(ObjectArrayBuffer other) { + addAll(other.buf, 0, other.length); + } + public void addAll(Object[] arr, int fromIndex, int toIndex) { int len = toIndex - fromIndex; ensureCapacity(length + len); @@ -90,6 +98,10 @@ public void addAll(Object[] arr, int fromIndex, int toIndex) { length += len; } + public Object pop() { + return buf[--length]; + } + @SuppressWarnings("unchecked") public T[] toArray(T[] a) { if (a.length < length) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFACaptureGroupTransitionBuilder.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFACaptureGroupTransitionBuilder.java index 44050a091c1d..82db844a3ffa 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFACaptureGroupTransitionBuilder.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFACaptureGroupTransitionBuilder.java @@ -31,8 +31,8 @@ import com.oracle.truffle.regex.tregex.buffer.CompilationBuffer; import com.oracle.truffle.regex.tregex.buffer.ObjectArrayBuffer; import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; -import com.oracle.truffle.regex.tregex.nodes.DFACaptureGroupLazyTransitionNode; -import com.oracle.truffle.regex.tregex.nodes.DFACaptureGroupPartialTransitionNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFACaptureGroupLazyTransitionNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFACaptureGroupPartialTransitionNode; import com.oracle.truffle.regex.tregex.util.json.Json; import com.oracle.truffle.regex.tregex.util.json.JsonConvertible; import com.oracle.truffle.regex.tregex.util.json.JsonObject; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFAGenerator.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFAGenerator.java index 9c682178a0ba..b2b33984c929 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFAGenerator.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFAGenerator.java @@ -56,19 +56,19 @@ import com.oracle.truffle.regex.tregex.nfa.NFA; import com.oracle.truffle.regex.tregex.nfa.NFAState; import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; -import com.oracle.truffle.regex.tregex.nodes.AllTransitionsInOneTreeMatcher; -import com.oracle.truffle.regex.tregex.nodes.BackwardDFAStateNode; -import com.oracle.truffle.regex.tregex.nodes.CGTrackingDFAStateNode; -import com.oracle.truffle.regex.tregex.nodes.DFAAbstractStateNode; -import com.oracle.truffle.regex.tregex.nodes.DFACaptureGroupLazyTransitionNode; -import com.oracle.truffle.regex.tregex.nodes.DFACaptureGroupPartialTransitionNode; -import com.oracle.truffle.regex.tregex.nodes.DFAFindInnerLiteralStateNode; -import com.oracle.truffle.regex.tregex.nodes.DFAInitialStateNode; -import com.oracle.truffle.regex.tregex.nodes.DFAStateNode; -import com.oracle.truffle.regex.tregex.nodes.TRegexDFAExecutorDebugRecorder; -import com.oracle.truffle.regex.tregex.nodes.TRegexDFAExecutorNode; -import com.oracle.truffle.regex.tregex.nodes.TRegexDFAExecutorProperties; -import com.oracle.truffle.regex.tregex.nodes.TraceFinderDFAStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.AllTransitionsInOneTreeMatcher; +import com.oracle.truffle.regex.tregex.nodes.dfa.BackwardDFAStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.CGTrackingDFAStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFAAbstractStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFACaptureGroupLazyTransitionNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFACaptureGroupPartialTransitionNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFAFindInnerLiteralStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFAInitialStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFAStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexDFAExecutorDebugRecorder; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexDFAExecutorNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexDFAExecutorProperties; +import com.oracle.truffle.regex.tregex.nodes.dfa.TraceFinderDFAStateNode; import com.oracle.truffle.regex.tregex.nodesplitter.DFANodeSplit; import com.oracle.truffle.regex.tregex.nodesplitter.DFANodeSplitBailoutException; import com.oracle.truffle.regex.tregex.parser.Counter; @@ -313,7 +313,7 @@ private void createInitialStatesForward() { nfa.setInitialLoopBack(isSearching() && !nfa.getAst().getFlags().isSticky()); for (int i = 0; i < numberOfEntryPoints; i++) { NFATransitionSet anchoredEntryStateSet = createNFATransitionSet(nfa.getAnchoredEntry()[i]); - if (nfa.getUnAnchoredEntry()[i].getTarget().getNext().isEmpty()) { + if (nfa.getUnAnchoredEntry()[i].getTarget().getNext().length == 0) { entryStates[numberOfEntryPoints + i] = null; } else { NFATransitionSet unAnchoredEntryStateSet = createNFATransitionSet(nfa.getUnAnchoredEntry()[i]); @@ -365,7 +365,7 @@ private void expandState(DFAStateNodeBuilder state) { if (!target.isFinalState(isForward()) && (!state.isBackwardPrefixState() || target.hasPrefixStates())) { anyPrefixStateSuccessors |= target.hasPrefixStates(); allPrefixStateSuccessors &= target.hasPrefixStates(); - expandDFATransitions.add(createTransitionBuilder(target.getMatcherBuilder(), createNFATransitionSet(nfaTransition))); + expandDFATransitions.add(createTransitionBuilder(target.getCharSet(), createNFATransitionSet(nfaTransition))); } else if (isForward() && target.isForwardUnAnchoredFinalState()) { assert target == nfa.getReverseUnAnchoredEntry().getSource(); break outer; @@ -675,6 +675,7 @@ private void optimizeDFA() { nfa.getReverseUnAnchoredEntry().setSource(literalFirstState); prefixMatcher = compilationReqest.createDFAExecutor(nfa, new TRegexDFAExecutorProperties(false, false, false, getOptions().isRegressionTestMode(), nfa.getAst().getNumberOfCaptureGroups(), rootSeq.getTerms().get(literalStart - 1).getMinPath()), "innerLiteralPrefix"); + prefixMatcher.setRoot(compilationReqest.getRoot()); nfa.setInitialLoopBack(true); nfa.getReverseAnchoredEntry().setSource(reverseAnchoredInitialState); nfa.getReverseUnAnchoredEntry().setSource(reverseUnAnchoredInitialState); @@ -710,7 +711,7 @@ private boolean innerLiteralMatchesPrefix(NFAStateSet prefixNFAStates) { if (i == literalStart && !prefixNFAStates.contains(t.getTarget())) { continue; } - if (c.intersects(t.getTarget().getMatcherBuilder())) { + if (c.intersects(t.getTarget().getCharSet())) { nextState.add(t.getTarget()); } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFAStateNodeBuilder.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFAStateNodeBuilder.java index 6c334c2de5b6..d650a917e0ec 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFAStateNodeBuilder.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/dfa/DFAStateNodeBuilder.java @@ -30,7 +30,7 @@ import com.oracle.truffle.regex.tregex.buffer.IntArrayBuffer; import com.oracle.truffle.regex.tregex.nfa.NFAState; import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; -import com.oracle.truffle.regex.tregex.nodes.TraceFinderDFAStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TraceFinderDFAStateNode; import com.oracle.truffle.regex.tregex.util.DebugUtil; import com.oracle.truffle.regex.tregex.util.json.Json; import com.oracle.truffle.regex.tregex.util.json.JsonConvertible; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/matchers/ProfilingCharMatcher.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/matchers/ProfilingCharMatcher.java index 1818cd060134..7c3a4bca87cd 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/matchers/ProfilingCharMatcher.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/matchers/ProfilingCharMatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFA.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFA.java index 6c9da5e9c984..c069b1ee00ac 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFA.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFA.java @@ -110,7 +110,7 @@ public NFAState getAnchoredInitialState() { } public boolean hasReverseUnAnchoredEntry() { - return reverseUnAnchoredEntry != null && !reverseUnAnchoredEntry.getSource().getPrev().isEmpty(); + return reverseUnAnchoredEntry != null && reverseUnAnchoredEntry.getSource().getPrev().length > 0; } public RegexAST getAst() { @@ -212,10 +212,10 @@ public boolean isDead() { } public void setInitialLoopBack(boolean enable) { - if (getUnAnchoredInitialState().getNext().isEmpty()) { + if (getUnAnchoredInitialState().getNext().length == 0) { return; } - NFAStateTransition lastInitTransition = getUnAnchoredInitialState().getNext().get(getUnAnchoredInitialState().getNext().size() - 1); + NFAStateTransition lastInitTransition = getUnAnchoredInitialState().getNext()[getUnAnchoredInitialState().getNext().length - 1]; if (enable) { if (lastInitTransition != initialLoopBack) { getUnAnchoredInitialState().addLoopBackNext(initialLoopBack); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAGenerator.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAGenerator.java index 63575d032758..cb7be080906d 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAGenerator.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAGenerator.java @@ -41,6 +41,7 @@ import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Deque; import java.util.HashMap; @@ -68,6 +69,7 @@ public final class NFAGenerator { private final ASTTransitionCanonicalizer astTransitionCanonicalizer = new ASTTransitionCanonicalizer(); private final CompilationFinalBitSet transitionGBUpdateIndices; private final CompilationFinalBitSet transitionGBClearIndices; + private final ArrayList transitionsBuffer = new ArrayList<>(); private NFAGenerator(RegexAST ast, CompilationBuffer compilationBuffer) { this.ast = ast; @@ -105,12 +107,9 @@ private NFAGenerator(RegexAST ast, CompilationBuffer compilationBuffer) { anchoredEntries[i] = createTransition(dummyInitialState, anchoredInitialState); } } - ArrayList dummyInitNext = new ArrayList<>(nEntries * 2); - Collections.addAll(dummyInitNext, anchoredEntries); - Collections.addAll(dummyInitNext, unAnchoredEntries); - ArrayList dummyInitPrev = new ArrayList<>(2); - dummyInitPrev.add(anchoredReverseEntry); - dummyInitPrev.add(unAnchoredReverseEntry); + NFAStateTransition[] dummyInitNext = Arrays.copyOf(anchoredEntries, nEntries * 2); + System.arraycopy(unAnchoredEntries, 0, dummyInitNext, nEntries, nEntries); + NFAStateTransition[] dummyInitPrev = new NFAStateTransition[]{anchoredReverseEntry, unAnchoredReverseEntry}; dummyInitialState.setNext(dummyInitNext, false); dummyInitialState.setPrev(dummyInitPrev); } @@ -127,6 +126,11 @@ private NFA doCreateNFA() { while (!expansionQueue.isEmpty()) { expandNFAState(expansionQueue.pop()); } + for (NFAState s : nfaStates.values()) { + if (s != dummyInitialState && ast.getHardPrefixNodes().isDisjoint(s.getStateSet())) { + s.linkPrev(); + } + } ArrayList deadStates = new ArrayList<>(); findDeadStates(deadStates); while (!deadStates.isEmpty()) { @@ -172,8 +176,8 @@ private void expandNFAState(NFAState curState) { curState.setNext(createNFATransitions(curState, nextStep), !isHardPrefixState); } - private ArrayList createNFATransitions(NFAState sourceState, ASTStep nextStep) { - ArrayList transitions = new ArrayList<>(); + private NFAStateTransition[] createNFATransitions(NFAState sourceState, ASTStep nextStep) { + transitionsBuffer.clear(); ASTNodeSet stateSetCC; ASTNodeSet finishedLookBehinds; for (ASTSuccessor successor : nextStep.getSuccessors()) { @@ -205,20 +209,20 @@ private ArrayList createNFATransitions(NFAState sourceState, } if (stateSetCC == null) { if (containsPositionAssertion) { - transitions.add(createTransition(sourceState, anchoredFinalState)); + transitionsBuffer.add(createTransition(sourceState, anchoredFinalState)); } else if (containsMatchFound) { - transitions.add(createTransition(sourceState, finalState)); + transitionsBuffer.add(createTransition(sourceState, finalState)); } } else if (!containsPositionAssertion) { assert mergeBuilder.getMatcherBuilder().matchesSomething(); - transitions.add(createTransition(sourceState, + transitionsBuffer.add(createTransition(sourceState, registerMatcherState(stateSetCC, mergeBuilder.getMatcherBuilder(), finishedLookBehinds, containsPrefixStates))); } transitionGBUpdateIndices.clear(); transitionGBClearIndices.clear(); } } - return transitions; + return transitionsBuffer.toArray(new NFAStateTransition[transitionsBuffer.size()]); } private NFAState createFinalState(ASTNodeSet stateSet) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAState.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAState.java index 4497c22cd3b9..e2f5080d13ad 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAState.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAState.java @@ -34,6 +34,7 @@ import com.oracle.truffle.regex.tregex.util.json.JsonObject; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -62,6 +63,8 @@ public class NFAState implements IndexedState, JsonConvertible { private static final byte MASK_FORWARD_FINAL_STATES = FLAG_FORWARD_ANCHORED_FINAL_STATE | FLAG_FORWARD_UN_ANCHORED_FINAL_STATE; private static final byte MASK_REVERSE_FINAL_STATES = FLAG_REVERSE_ANCHORED_FINAL_STATE | FLAG_REVERSE_UN_ANCHORED_FINAL_STATE; + private static final NFAStateTransition[] EMPTY_TRANSITIONS = new NFAStateTransition[0]; + private final short id; private final ASTNodeSet stateSet; private byte flags; @@ -69,8 +72,9 @@ public class NFAState implements IndexedState, JsonConvertible { private short transitionToUnAnchoredFinalState = -1; private short revTransitionToAnchoredFinalState = -1; private short revTransitionToUnAnchoredFinalState = -1; - private List next; - private List prev; + private NFAStateTransition[] next; + private NFAStateTransition[] prev; + private short prevLength = 0; private List possibleResults; private final CharSet matcherBuilder; private final Set finishedLookBehinds; @@ -81,7 +85,7 @@ public NFAState(short id, Set finishedLookBehinds, boolean hasPrefixStates) { this(id, stateSet, hasPrefixStates ? FLAG_HAS_PREFIX_STATES : FLAGS_NONE, - new ArrayList<>(), new ArrayList<>(), null, matcherBuilder, finishedLookBehinds); + EMPTY_TRANSITIONS, EMPTY_TRANSITIONS, null, matcherBuilder, finishedLookBehinds); } private NFAState(short id, @@ -89,14 +93,14 @@ private NFAState(short id, byte flags, CharSet matcherBuilder, Set finishedLookBehinds) { - this(id, stateSet, flags, new ArrayList<>(), new ArrayList<>(), null, matcherBuilder, finishedLookBehinds); + this(id, stateSet, flags, EMPTY_TRANSITIONS, EMPTY_TRANSITIONS, null, matcherBuilder, finishedLookBehinds); } private NFAState(short id, ASTNodeSet stateSet, byte flags, - List next, - List prev, + NFAStateTransition[] next, + NFAStateTransition[] prev, List possibleResults, CharSet matcherBuilder, Set finishedLookBehinds) { @@ -114,7 +118,7 @@ public NFAState createTraceFinderCopy(short copyID) { return new NFAState(copyID, getStateSet(), getFlags(), matcherBuilder, finishedLookBehinds); } - public CharSet getMatcherBuilder() { + public CharSet getCharSet() { return matcherBuilder; } @@ -206,9 +210,13 @@ public boolean hasTransitionToAnchoredFinalState(boolean forward) { return (forward ? transitionToAnchoredFinalState : revTransitionToAnchoredFinalState) >= 0; } + public short getTransitionToAnchoredFinalStateId(boolean forward) { + return forward ? transitionToAnchoredFinalState : revTransitionToAnchoredFinalState; + } + public NFAStateTransition getTransitionToAnchoredFinalState(boolean forward) { assert hasTransitionToAnchoredFinalState(forward); - return forward ? next.get(transitionToAnchoredFinalState) : prev.get(revTransitionToAnchoredFinalState); + return forward ? next[transitionToAnchoredFinalState] : prev[revTransitionToAnchoredFinalState]; } public boolean hasTransitionToUnAnchoredFinalState(boolean forward) { @@ -217,49 +225,48 @@ public boolean hasTransitionToUnAnchoredFinalState(boolean forward) { public NFAStateTransition getTransitionToUnAnchoredFinalState(boolean forward) { assert hasTransitionToUnAnchoredFinalState(forward); - return forward ? next.get(transitionToUnAnchoredFinalState) : prev.get(revTransitionToUnAnchoredFinalState); + return forward ? next[transitionToUnAnchoredFinalState] : prev[revTransitionToUnAnchoredFinalState]; + } + + public short getTransitionToUnAnchoredFinalStateId(boolean forward) { + return forward ? transitionToUnAnchoredFinalState : revTransitionToUnAnchoredFinalState; } /** * List of possible next states, sorted by priority. */ - public List getNext() { + public NFAStateTransition[] getNext() { return next; } - public List getNext(boolean forward) { + public NFAStateTransition[] getNext(boolean forward) { return forward ? next : prev; } public void addLoopBackNext(NFAStateTransition transition) { // loopBack transitions always have minimal priority, so no sorting is necessary - updateFinalStateTransitions(transition, (short) next.size()); - next.add(transition); + updateFinalStateTransitions(transition, (short) next.length); + next = Arrays.copyOf(next, next.length + 1); + next[next.length - 1] = transition; } public void removeLoopBackNext() { - next.remove(next.size() - 1); - if (transitionToAnchoredFinalState == next.size()) { + next = Arrays.copyOf(next, next.length - 1); + if (transitionToAnchoredFinalState == next.length) { transitionToAnchoredFinalState = -1; } - if (transitionToUnAnchoredFinalState == next.size()) { + if (transitionToUnAnchoredFinalState == next.length) { transitionToUnAnchoredFinalState = -1; } } - public void setNext(ArrayList transitions, boolean createReverseTransitions) { + public void setNext(NFAStateTransition[] transitions, boolean createReverseTransitions) { this.next = transitions; - for (short i = 0; i < transitions.size(); i++) { - NFAStateTransition t = transitions.get(i); + for (short i = 0; i < transitions.length; i++) { + NFAStateTransition t = transitions[i]; updateFinalStateTransitions(t, i); if (createReverseTransitions) { - if (isReverseAnchoredFinalState()) { - t.getTarget().revTransitionToAnchoredFinalState = (short) t.getTarget().prev.size(); - } - if (isReverseUnAnchoredFinalState()) { - t.getTarget().revTransitionToUnAnchoredFinalState = (short) t.getTarget().prev.size(); - } - t.getTarget().prev.add(t); + t.getTarget().prevLength++; } } } @@ -274,29 +281,63 @@ private void updateFinalStateTransitions(NFAStateTransition transition, short i) } public void removeNext(NFAState state) { - NFAStateTransition transitionToAFS = hasTransitionToAnchoredFinalState(true) ? getTransitionToAnchoredFinalState(true) : null; - NFAStateTransition transitionToUFS = hasTransitionToUnAnchoredFinalState(true) ? getTransitionToUnAnchoredFinalState(true) : null; - next.removeIf(x -> x.getTarget() == state); - if (hasTransitionToAnchoredFinalState(true)) { - this.transitionToAnchoredFinalState = (short) next.indexOf(transitionToAFS); + int remove = indexOfTransition(state); + if (remove == -1) { + return; + } + NFAStateTransition[] newNext = new NFAStateTransition[next.length - 1]; + System.arraycopy(next, 0, newNext, 0, remove); + System.arraycopy(next, remove + 1, newNext, remove, newNext.length - remove); + next = newNext; + if (transitionToAnchoredFinalState == remove) { + transitionToAnchoredFinalState = -1; + } else if (transitionToAnchoredFinalState > remove) { + transitionToAnchoredFinalState--; + } + if (transitionToUnAnchoredFinalState == remove) { + transitionToUnAnchoredFinalState = -1; + } else if (transitionToUnAnchoredFinalState > remove) { + transitionToUnAnchoredFinalState--; } - if (hasTransitionToUnAnchoredFinalState(true)) { - this.transitionToUnAnchoredFinalState = (short) next.indexOf(transitionToUFS); + } + + private int indexOfTransition(NFAState target) { + for (int i = 0; i < next.length; i++) { + if (next[i].getTarget() == target) { + return i; + } + } + return -1; + } + + public void linkPrev() { + for (NFAStateTransition t : next) { + if (t.getTarget().prev == EMPTY_TRANSITIONS) { + t.getTarget().prev = new NFAStateTransition[t.getTarget().prevLength]; + } + t.getTarget().prevLength--; + if (isReverseAnchoredFinalState()) { + t.getTarget().revTransitionToAnchoredFinalState = t.getTarget().prevLength; + } + if (isReverseUnAnchoredFinalState()) { + t.getTarget().revTransitionToUnAnchoredFinalState = t.getTarget().prevLength; + } + t.getTarget().prev[t.getTarget().prevLength] = t; } } - public void setPrev(ArrayList transitions) { + public void setPrev(NFAStateTransition[] transitions) { this.prev = transitions; } /** * List of possible previous states, unsorted. */ - public List getPrev() { + public NFAStateTransition[] getPrev() { return prev; } - public List getPrev(boolean forward) { + public NFAStateTransition[] getPrev(boolean forward) { return forward ? prev : next; } @@ -335,7 +376,7 @@ public void addPossibleResult(int index) { } public boolean isDead(boolean forward) { - return !isFinalState(forward) && (getNext(forward).isEmpty() || getNext(forward).size() == 1 && getNext(forward).get(0).getTarget(forward) == this); + return !isFinalState(forward) && (getNext(forward).length == 0 || getNext(forward).length == 1 && getNext(forward)[0].getTarget(forward) == this); } @TruffleBoundary @@ -377,8 +418,8 @@ public JsonObject toJson() { Json.prop("forwardUnAnchoredFinalState", isForwardUnAnchoredFinalState()), Json.prop("reverseAnchoredFinalState", isReverseAnchoredFinalState()), Json.prop("reverseUnAnchoredFinalState", isReverseUnAnchoredFinalState()), - Json.prop("next", next.stream().map(x -> Json.val(x.getId()))), - Json.prop("prev", prev.stream().map(x -> Json.val(x.getId())))); + Json.prop("next", Arrays.stream(next).map(x -> Json.val(x.getId()))), + Json.prop("prev", Arrays.stream(prev).map(x -> Json.val(x.getId())))); } @TruffleBoundary @@ -389,6 +430,6 @@ public JsonObject toJson(boolean forward) { Json.prop("matcherBuilder", matcherBuilder.toString()), Json.prop("anchoredFinalState", isAnchoredFinalState(forward)), Json.prop("unAnchoredFinalState", isUnAnchoredFinalState(forward)), - Json.prop("transitions", getNext(forward).stream().map(x -> Json.val(x.getId())))); + Json.prop("transitions", Arrays.stream(getNext(forward)).map(x -> Json.val(x.getId())))); } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFATraceFinderGenerator.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFATraceFinderGenerator.java index f17357e1ff22..cf2b6b687d26 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFATraceFinderGenerator.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFATraceFinderGenerator.java @@ -24,16 +24,16 @@ */ package com.oracle.truffle.regex.tregex.nfa; +import java.util.ArrayList; +import java.util.List; + +import org.graalvm.collections.EconomicMap; + import com.oracle.truffle.regex.UnsupportedRegexException; import com.oracle.truffle.regex.result.PreCalculatedResultFactory; import com.oracle.truffle.regex.tregex.TRegexOptions; import com.oracle.truffle.regex.tregex.parser.Counter; import com.oracle.truffle.regex.tregex.parser.ast.GroupBoundaries; -import org.graalvm.collections.EconomicMap; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; /** * Used for pre-calculating and finding the result of tree-like regular expressions. A regular @@ -116,7 +116,7 @@ private NFATraceFinderGenerator(NFA originalNFA) { *
  • To find the correct pre-calculated result, we simply run the new DFA in reverse * direction, starting from the index we found with the forward searching DFA.
  • *
- * + * *
      *     {@code
      *     Example:
@@ -145,7 +145,7 @@ private NFATraceFinderGenerator(NFA originalNFA) {
      *     g -> result 1
      *     }
      * 
- * + * * We also have to take care of the order in which results are to be found. For example, in the * expression {@code /a(b)c|ab(c)/}, we always have to return the result created from taking the * first branch, never the second. Therefore, we create the reverse tree-shaped NFA while @@ -172,11 +172,11 @@ public NFAStateTransition getTransition() { } public boolean hasNextTransition() { - return i < transition.getTarget().getNext().size(); + return i < transition.getTarget().getNext().length; } public NFAStateTransition getNextTransition() { - return transition.getTarget().getNext().get(i++); + return transition.getTarget().getNext()[i++]; } } @@ -184,10 +184,7 @@ private NFA run() { NFAState dummyInitialState = copy(originalNFA.getDummyInitialState()); NFAStateTransition newAnchoredEntry = copyEntry(dummyInitialState, originalNFA.getReverseAnchoredEntry()); NFAStateTransition newUnAnchoredEntry = copyEntry(dummyInitialState, originalNFA.getReverseUnAnchoredEntry()); - ArrayList dummyInitPrev = new ArrayList<>(2); - dummyInitPrev.add(newAnchoredEntry); - dummyInitPrev.add(newUnAnchoredEntry); - dummyInitialState.setPrev(dummyInitPrev); + dummyInitialState.setPrev(new NFAStateTransition[]{newAnchoredEntry, newUnAnchoredEntry}); ArrayList graphPath = new ArrayList<>(); for (NFAStateTransition entry : new NFAStateTransition[]{originalNFA.getAnchoredEntry()[0], originalNFA.getUnAnchoredEntry()[0]}) { for (NFAStateTransition t : entry.getTarget().getNext()) { @@ -230,10 +227,10 @@ private NFA run() { NFAState treeNode = duplicate; while (!treeNode.isForwardFinalState()) { i++; - assert treeNode.getNext().size() == 1; + assert treeNode.getNext().length == 1; treeNode.addPossibleResult(resultID); - treeNode.getNext().get(0).getGroupBoundaries().applyToResultFactory(result, i); - treeNode = treeNode.getNext().get(0).getTarget(); + treeNode.getNext()[0].getGroupBoundaries().applyToResultFactory(result, i); + treeNode = treeNode.getNext()[0].getTarget(); } treeNode.addPossibleResult(resultID); result.setLength(i); @@ -265,13 +262,16 @@ private NFA run() { } else { preCalculatedResults = resultList.toArray(new PreCalculatedResultFactory[0]); } + for (NFAState s : states) { + s.linkPrev(); + } return new NFA(originalNFA.getAst(), dummyInitialState, null, null, newAnchoredEntry, newUnAnchoredEntry, states, stateID, transitionID, preCalculatedResults); } private void createTransition(NFAState source, NFAState target, NFAStateTransition originalTransition, PreCalculatedResultFactory preCalcResult, int preCalcResultIndex) { originalTransition.getGroupBoundaries().applyToResultFactory(preCalcResult, preCalcResultIndex); - source.setNext(new ArrayList<>(Collections.singletonList(new NFAStateTransition((short) transitionID.inc(), source, target, originalTransition.getGroupBoundaries()))), true); + source.setNext(new NFAStateTransition[]{new NFAStateTransition((short) transitionID.inc(), source, target, originalTransition.getGroupBoundaries())}, true); } private PreCalculatedResultFactory resultFactory() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecRootNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecRootNode.java index 798d1fccd324..534fa85a6a09 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecRootNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecRootNode.java @@ -43,67 +43,102 @@ import com.oracle.truffle.regex.RegexSource; import com.oracle.truffle.regex.UnsupportedRegexException; import com.oracle.truffle.regex.result.LazyCaptureGroupsResult; +import com.oracle.truffle.regex.result.LazyResult; import com.oracle.truffle.regex.result.NoMatchResult; import com.oracle.truffle.regex.result.PreCalculatedResultFactory; import com.oracle.truffle.regex.result.RegexResult; +import com.oracle.truffle.regex.result.SingleIndexArrayResult; import com.oracle.truffle.regex.result.SingleResult; import com.oracle.truffle.regex.result.SingleResultLazyStart; import com.oracle.truffle.regex.result.TraceFinderResult; import com.oracle.truffle.regex.tregex.TRegexCompiler; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexDFAExecutorNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexLazyCaptureGroupsRootNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexLazyFindStartRootNode; +import com.oracle.truffle.regex.tregex.nodes.nfa.TRegexNFAExecutorNode; public class TRegexExecRootNode extends RegexExecRootNode implements RegexProfile.TracksRegexProfile { - private static final EagerCaptureGroupRegexSearchNode EAGER_SEARCH_BAILED_OUT = new EagerCaptureGroupRegexSearchNode(null); + private static final LazyCaptureGroupRegexSearchNode LAZY_DFA_BAILED_OUT = new LazyCaptureGroupRegexSearchNode(null, null, null, null, null, null, null, null); + private static final EagerCaptureGroupRegexSearchNode EAGER_DFA_BAILED_OUT = new EagerCaptureGroupRegexSearchNode(null); - private final LazyCaptureGroupRegexSearchNode lazySearchNode; - private EagerCaptureGroupRegexSearchNode eagerSearchNode; - private RegexProfile regexProfile; private final TRegexCompiler tRegexCompiler; - private final boolean eagerCompilation; - - @Child private RunRegexSearchNode runRegexSearchNode; - - public TRegexExecRootNode(RegexLanguage language, - TRegexCompiler tRegexCompiler, - RegexSource source, - RegexFlags flags, - boolean eagerCompilation, - PreCalculatedResultFactory[] preCalculatedResults, - TRegexDFAExecutorNode forwardExecutor, - TRegexDFAExecutorNode backwardExecutor, - TRegexDFAExecutorNode captureGroupExecutor) { + private LazyCaptureGroupRegexSearchNode lazyDFANode; + private EagerCaptureGroupRegexSearchNode eagerDFANode; + private NFARegexSearchNode nfaNode; + private RegexProfile regexProfile; + private final boolean regressionTestMode; + + @Child private RunRegexSearchNode runnerNode; + + public TRegexExecRootNode(RegexLanguage language, TRegexCompiler tRegexCompiler, RegexSource source, RegexFlags flags, boolean regressionTestMode, TRegexExecutorNode backTrackingExecutor) { super(language, source, flags.isUnicode()); - lazySearchNode = new LazyCaptureGroupRegexSearchNode(language, source, flags, preCalculatedResults, forwardExecutor, backwardExecutor, captureGroupExecutor, this); - runRegexSearchNode = insert(lazySearchNode); this.tRegexCompiler = tRegexCompiler; - this.eagerCompilation = eagerCompilation; - if (canSwitchToEagerSearch()) { - if (eagerCompilation) { - compileEagerSearchNode(); - } - if (tRegexCompiler.getOptions().isAlwaysEager()) { - switchToEagerSearch(null); - } + this.regressionTestMode = regressionTestMode; + this.nfaNode = new NFARegexSearchNode(createEntryNode(backTrackingExecutor)); + this.runnerNode = insert(nfaNode); + if (this.regressionTestMode) { + switchToLazyDFA(); } } @Override public final RegexResult execute(Object input, int fromIndex) { - final RegexResult result = runRegexSearchNode.run(input, fromIndex, inputLength(input)); - assert !eagerCompilation || eagerAndLazySearchNodesProduceSameResult(input, fromIndex, result); - if (CompilerDirectives.inInterpreter() && canSwitchToEagerSearch() && runRegexSearchNode == lazySearchNode) { + final RegexResult result = runnerNode.run(input, fromIndex, inputLength(input)); + assert !regressionTestMode || nfaProducesSameResult(input, fromIndex, result); + assert !regressionTestMode || eagerAndLazyDFAProduceSameResult(input, fromIndex, result); + if (CompilerDirectives.inInterpreter()) { RegexProfile profile = getRegexProfile(); - if (profile.atEvaluationTripPoint() && profile.shouldUseEagerMatching()) { - switchToEagerSearch(profile); - } - profile.incCalls(); - if (result != NoMatchResult.getInstance()) { - profile.incMatches(); + if (lazyDFANode == null) { + assert !regressionTestMode; + profile.incCalls(); + if (profile.shouldGenerateDFA()) { + switchToLazyDFA(); + profile.resetCalls(); + // free the NFA for garbage collection + nfaNode = null; + } + } else if (canSwitchToEagerDFA() && runnerNode == lazyDFANode) { + if (profile.atEvaluationTripPoint() && profile.shouldUseEagerMatching()) { + switchToEagerDFA(profile); + } + profile.incCalls(); + if (result != NoMatchResult.getInstance()) { + profile.incMatches(); + } } } return result; } + private boolean nfaProducesSameResult(Object input, int fromIndex, RegexResult result) { + assert !(runnerNode instanceof NFARegexSearchNode); + RegexResult btResult = nfaNode.run(input, fromIndex, inputLength(input)); + if (resultsEqual(result, btResult, ((TRegexNFAExecutorNode) nfaNode.entryNode.getExecutor()).getNumberOfCaptureGroups())) { + return true; + } + LOG_INTERNAL_ERRORS.severe(() -> String.format("Regex: %s\nInput: %s\nfromIndex: %d\nBacktracker Result: %s\nDFA Result: %s", getSource(), input, fromIndex, btResult, result)); + return false; + } + + private static boolean resultsEqual(RegexResult a, RegexResult b, int numberOfCaptureGroups) { + if (a == NoMatchResult.getInstance()) { + return b == NoMatchResult.getInstance(); + } + if (a instanceof LazyResult) { + ((LazyResult) a).debugForceEvaluation(); + } + if (b instanceof LazyResult) { + ((LazyResult) b).debugForceEvaluation(); + } + for (int i = 0; i < numberOfCaptureGroups; i++) { + if (a.getStart(i) != b.getStart(i) || a.getEnd(i) != b.getEnd(i)) { + return false; + } + } + return true; + } + @Override public RegexProfile getRegexProfile() { if (regexProfile == null) { @@ -112,41 +147,67 @@ public RegexProfile getRegexProfile() { return regexProfile; } - private boolean canSwitchToEagerSearch() { - return lazySearchNode.captureGroupEntryNode != null; + private void switchToLazyDFA() { + compileLazyDFA(); + if (lazyDFANode != LAZY_DFA_BAILED_OUT) { + runnerNode = insert(lazyDFANode); + if (canSwitchToEagerDFA()) { + if (regressionTestMode) { + compileEagerDFA(); + } + if (tRegexCompiler.getOptions().isAlwaysEager()) { + switchToEagerDFA(null); + } + } + } } - private void switchToEagerSearch(RegexProfile profile) { - compileEagerSearchNode(); - if (eagerSearchNode != EAGER_SEARCH_BAILED_OUT) { + private void compileLazyDFA() { + if (lazyDFANode == null) { + try { + lazyDFANode = tRegexCompiler.compileLazyDFAExecutor(((TRegexNFAExecutorNode) nfaNode.entryNode.getExecutor()).getNFA(), this); + } catch (UnsupportedRegexException e) { + LOG_BAILOUT_MESSAGES.fine(() -> e.getReason() + ": " + source); + lazyDFANode = LAZY_DFA_BAILED_OUT; + } + } + } + + private boolean canSwitchToEagerDFA() { + return lazyDFANode.captureGroupEntryNode != null; + } + + private void switchToEagerDFA(RegexProfile profile) { + compileEagerDFA(); + if (eagerDFANode != EAGER_DFA_BAILED_OUT) { LOG_SWITCH_TO_EAGER.fine(() -> "regex " + getSource() + ": switching to eager matching." + (profile == null ? "" : " profile: " + profile)); - runRegexSearchNode = insert(eagerSearchNode); + runnerNode = insert(eagerDFANode); } } - private void compileEagerSearchNode() { - if (eagerSearchNode == null) { + private void compileEagerDFA() { + if (eagerDFANode == null) { try { TRegexDFAExecutorNode executorNode = tRegexCompiler.compileEagerDFAExecutor(getSource()); - eagerSearchNode = new EagerCaptureGroupRegexSearchNode(executorNode); + eagerDFANode = new EagerCaptureGroupRegexSearchNode(createEntryNode(executorNode)); } catch (UnsupportedRegexException e) { LOG_BAILOUT_MESSAGES.fine(() -> e.getReason() + ": " + source); - eagerSearchNode = EAGER_SEARCH_BAILED_OUT; + eagerDFANode = EAGER_DFA_BAILED_OUT; } } } - private boolean eagerAndLazySearchNodesProduceSameResult(Object input, int fromIndex, RegexResult resultOfCurrentSearchNode) { - if (lazySearchNode.captureGroupEntryNode == null || eagerSearchNode == EAGER_SEARCH_BAILED_OUT) { + private boolean eagerAndLazyDFAProduceSameResult(Object input, int fromIndex, RegexResult resultOfCurrentSearchNode) { + if (lazyDFANode.captureGroupEntryNode == null || eagerDFANode == EAGER_DFA_BAILED_OUT) { return true; } RegexResult lazyResult; RegexResult eagerResult; - if (runRegexSearchNode == lazySearchNode) { + if (runnerNode == lazyDFANode) { lazyResult = resultOfCurrentSearchNode; - eagerResult = eagerSearchNode.run(input, fromIndex, inputLength(input)); + eagerResult = eagerDFANode.run(input, fromIndex, inputLength(input)); } else { - lazyResult = lazySearchNode.run(input, fromIndex, inputLength(input)); + lazyResult = lazyDFANode.run(input, fromIndex, inputLength(input)); eagerResult = resultOfCurrentSearchNode; } boolean equal; @@ -162,6 +223,14 @@ private boolean eagerAndLazySearchNodesProduceSameResult(Object input, int fromI return equal; } + public TRegexExecutorEntryNode createEntryNode(TRegexExecutorNode executor) { + if (executor == null) { + return null; + } + executor.setRoot(this); + return TRegexExecutorEntryNode.create(executor); + } + @Override public final String getEngineLabel() { return "TRegex fwd"; @@ -172,47 +241,48 @@ abstract static class RunRegexSearchNode extends Node { abstract RegexResult run(Object input, int fromIndexArg, int inputLength); } - static final class LazyCaptureGroupRegexSearchNode extends RunRegexSearchNode { + public static final class LazyCaptureGroupRegexSearchNode extends RunRegexSearchNode { private final RegexFlags flags; @CompilationFinal(dimensions = 1) private final PreCalculatedResultFactory[] preCalculatedResults; - @Child private TRegexDFAExecutorEntryNode forwardEntryNode; - @Child private TRegexDFAExecutorEntryNode backwardEntryNode; - @Child private TRegexDFAExecutorEntryNode captureGroupEntryNode; + @Child private TRegexExecutorEntryNode forwardEntryNode; + @Child private TRegexExecutorEntryNode backwardEntryNode; + @Child private TRegexExecutorEntryNode captureGroupEntryNode; private final CallTarget backwardCallTarget; private final CallTarget captureGroupCallTarget; - LazyCaptureGroupRegexSearchNode(RegexLanguage language, + public LazyCaptureGroupRegexSearchNode(RegexLanguage language, RegexSource source, RegexFlags flags, PreCalculatedResultFactory[] preCalculatedResults, - TRegexDFAExecutorNode forwardNode, - TRegexDFAExecutorNode backwardNode, - TRegexDFAExecutorNode captureGroupExecutor, - RegexProfile.TracksRegexProfile profiler) { - this.forwardEntryNode = TRegexDFAExecutorEntryNode.create(forwardNode); + TRegexExecutorEntryNode forwardNode, + TRegexExecutorEntryNode backwardNode, + TRegexExecutorEntryNode captureGroupNode, + TRegexExecRootNode rootNode) { + this.forwardEntryNode = insert(forwardNode); this.flags = flags; this.preCalculatedResults = preCalculatedResults; - this.backwardEntryNode = TRegexDFAExecutorEntryNode.create(backwardNode); + this.backwardEntryNode = insert(backwardNode); if (backwardNode == null) { - assert singlePreCalcResult(); + assert singlePreCalcResult() || forwardNode == null; backwardCallTarget = null; } else { - backwardCallTarget = Truffle.getRuntime().createCallTarget(new RegexRootNode(language, new TRegexLazyFindStartRootNode(language, source, forwardNode.getPrefixLength(), backwardNode))); + backwardCallTarget = Truffle.getRuntime().createCallTarget(new RegexRootNode(language, + new TRegexLazyFindStartRootNode(language, source, ((TRegexDFAExecutorNode) forwardNode.getExecutor()).getPrefixLength(), backwardNode))); } - this.captureGroupEntryNode = TRegexDFAExecutorEntryNode.create(captureGroupExecutor); - if (captureGroupExecutor == null) { + this.captureGroupEntryNode = insert(captureGroupNode); + if (captureGroupNode == null) { captureGroupCallTarget = null; } else { - captureGroupCallTarget = Truffle.getRuntime().createCallTarget(new RegexRootNode(language, new TRegexLazyCaptureGroupsRootNode(language, source, captureGroupExecutor, profiler))); + captureGroupCallTarget = Truffle.getRuntime().createCallTarget(new RegexRootNode(language, new TRegexLazyCaptureGroupsRootNode(language, source, captureGroupNode, rootNode))); } } @Override RegexResult run(Object input, int fromIndexArg, int inputLength) { - if (backwardEntryNode != null && backwardEntryNode.getExecutor().isAnchored()) { + if (backwardEntryNode != null && ((TRegexDFAExecutorNode) backwardEntryNode.getExecutor()).isAnchored()) { return executeBackwardAnchored(input, fromIndexArg, inputLength); } else { return executeForward(input, fromIndexArg, inputLength); @@ -231,7 +301,7 @@ private RegexResult executeForward(Object input, int fromIndexArg, int inputLeng if (end == fromIndexArg) { // zero-length match return new SingleResult(end, end); } - if (forwardEntryNode.getExecutor().isAnchored() || flags.isSticky()) { + if (((TRegexDFAExecutorNode) forwardEntryNode.getExecutor()).isAnchored() || flags.isSticky()) { return new SingleResult(fromIndexArg, end); } return new SingleResultLazyStart(input, fromIndexArg, end, backwardCallTarget); @@ -239,8 +309,8 @@ private RegexResult executeForward(Object input, int fromIndexArg, int inputLeng if (preCalculatedResults != null) { // traceFinder return new TraceFinderResult(input, fromIndexArg, end, backwardCallTarget, preCalculatedResults); } else { - if (forwardEntryNode.getExecutor().isAnchored() || - (flags.isSticky() && forwardEntryNode.getExecutor().getPrefixLength() == 0)) { + if (((TRegexDFAExecutorNode) forwardEntryNode.getExecutor()).isAnchored() || + (flags.isSticky() && ((TRegexDFAExecutorNode) forwardEntryNode.getExecutor()).getPrefixLength() == 0)) { return new LazyCaptureGroupsResult(input, fromIndexArg, end, null, captureGroupCallTarget); } return new LazyCaptureGroupsResult(input, fromIndexArg, end, backwardCallTarget, captureGroupCallTarget); @@ -249,14 +319,22 @@ private RegexResult executeForward(Object input, int fromIndexArg, int inputLeng } private RegexResult executeBackwardAnchored(Object input, int fromIndexArg, int inputLength) { - final int backwardResult = (int) backwardEntryNode.execute(input, 0, inputLength - 1, Math.max(-1, fromIndexArg - 1 - forwardEntryNode.getExecutor().getPrefixLength())); + final int backwardResult = (int) backwardEntryNode.execute(input, fromIndexArg, inputLength - 1, + Math.max(-1, fromIndexArg - 1 - ((TRegexDFAExecutorNode) forwardEntryNode.getExecutor()).getPrefixLength())); if (backwardResult == TRegexDFAExecutorNode.NO_MATCH) { return NoMatchResult.getInstance(); } if (multiplePreCalcResults()) { // traceFinder - return preCalculatedResults[backwardResult].createFromEnd(inputLength); + RegexResult preCalcResult = preCalculatedResults[backwardResult].createFromEnd(inputLength); + if (flags.isSticky() && preCalcResult.getStart(0) != fromIndexArg) { + return NoMatchResult.getInstance(); + } + return preCalcResult; } final int start = backwardResult + 1; + if (flags.isSticky() && start != fromIndexArg) { + return NoMatchResult.getInstance(); + } if (singlePreCalcResult()) { return preCalculatedResults[0].createFromStart(start); } @@ -277,10 +355,10 @@ private boolean multiplePreCalcResults() { static final class EagerCaptureGroupRegexSearchNode extends RunRegexSearchNode { - @Child private TRegexDFAExecutorEntryNode entryNode; + @Child private TRegexExecutorEntryNode entryNode; - EagerCaptureGroupRegexSearchNode(TRegexDFAExecutorNode executorNode) { - entryNode = TRegexDFAExecutorEntryNode.create(executorNode); + EagerCaptureGroupRegexSearchNode(TRegexExecutorEntryNode entryNode) { + this.entryNode = insert(entryNode); } @Override @@ -292,4 +370,22 @@ RegexResult run(Object input, int fromIndexArg, int inputLength) { return new LazyCaptureGroupsResult(input, resultArray); } } + + static final class NFARegexSearchNode extends RunRegexSearchNode { + + @Child private TRegexExecutorEntryNode entryNode; + + NFARegexSearchNode(TRegexExecutorEntryNode entryNode) { + this.entryNode = insert(entryNode); + } + + @Override + RegexResult run(Object input, int fromIndexArg, int inputLength) { + final int[] resultArray = (int[]) entryNode.execute(input, fromIndexArg, fromIndexArg, inputLength); + if (resultArray == null) { + return NoMatchResult.getInstance(); + } + return new SingleIndexArrayResult(resultArray); + } + } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorEntryNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorEntryNode.java similarity index 78% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorEntryNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorEntryNode.java index 64a2e44df606..89846fd7cd83 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorEntryNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorEntryNode.java @@ -35,10 +35,10 @@ import sun.misc.Unsafe; /** - * This class wraps {@link TRegexDFAExecutorNode} and specializes on the type of the input strings + * This class wraps {@link TRegexExecutorNode} and specializes on the type of the input strings * provided to {@link TRegexExecRootNode}. */ -public abstract class TRegexDFAExecutorEntryNode extends Node { +public abstract class TRegexExecutorEntryNode extends Node { private static final sun.misc.Unsafe UNSAFE; private static final Field coderField; @@ -83,20 +83,20 @@ private static Unsafe getUnsafe() { } } - @Child TRegexDFAExecutorNode executor; + @Child TRegexExecutorNode executor; - public TRegexDFAExecutorEntryNode(TRegexDFAExecutorNode executor) { + public TRegexExecutorEntryNode(TRegexExecutorNode executor) { this.executor = executor; } - public static TRegexDFAExecutorEntryNode create(TRegexDFAExecutorNode executor) { + public static TRegexExecutorEntryNode create(TRegexExecutorNode executor) { if (executor == null) { return null; } - return TRegexDFAExecutorEntryNodeGen.create(executor); + return TRegexExecutorEntryNodeGen.create(executor); } - public TRegexDFAExecutorNode getExecutor() { + public TRegexExecutorNode getExecutor() { return executor; } @@ -104,12 +104,12 @@ public TRegexDFAExecutorNode getExecutor() { @Specialization(guards = "isCompactString(input)") Object doStringCompact(String input, int fromIndex, int index, int maxIndex) { - return executor.execute(new TRegexDFAExecutorLocals(input, fromIndex, index, maxIndex, createCGData()), true); + return executor.execute(executor.createLocals(input, fromIndex, index, maxIndex), true); } @Specialization(guards = "!isCompactString(input)") Object doStringNonCompact(String input, int fromIndex, int index, int maxIndex) { - return executor.execute(new TRegexDFAExecutorLocals(input, fromIndex, index, maxIndex, createCGData()), false); + return executor.execute(executor.createLocals(input, fromIndex, index, maxIndex), false); } @Specialization @@ -118,15 +118,7 @@ Object doTruffleObject(TruffleObject input, int fromIndex, int index, int maxInd // conservatively disable compact string optimizations. // TODO: maybe add an interface for TruffleObjects to announce if they are compact / ascii // strings? - return executor.execute(new TRegexDFAExecutorLocals(inputClassProfile.profile(input), fromIndex, index, maxIndex, createCGData()), false); - } - - private DFACaptureGroupTrackingData createCGData() { - if (executor.getProperties().isTrackCaptureGroups()) { - return new DFACaptureGroupTrackingData(executor.getMaxNumberOfNFAStates(), executor.getProperties().getNumberOfCaptureGroups()); - } else { - return null; - } + return executor.execute(executor.createLocals(inputClassProfile.profile(input), fromIndex, index, maxIndex), false); } static boolean isCompactString(String str) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorLocals.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorLocals.java new file mode 100644 index 000000000000..7da2d2a52ee4 --- /dev/null +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorLocals.java @@ -0,0 +1,89 @@ +/* + * 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.truffle.regex.tregex.nodes; + +/** + * Base class for local variables used by an executor node called by a {@link TRegexExecRootNode}. + */ +public abstract class TRegexExecutorLocals { + + private final Object input; + private final int fromIndex; + private final int maxIndex; + private int index; + + public TRegexExecutorLocals(Object input, int fromIndex, int maxIndex, int index) { + this.input = input; + this.fromIndex = fromIndex; + this.maxIndex = maxIndex; + this.index = index; + } + + /** + * The {@code input} argument given to {@link TRegexExecRootNode#execute(Object, int)}. + * + * @return the {@code input} argument given to {@link TRegexExecRootNode#execute(Object, int)}. + */ + public Object getInput() { + return input; + } + + /** + * The {@code fromIndex} argument given to {@link TRegexExecRootNode#execute(Object, int)}. + * + * @return the {@code fromIndex} argument given to + * {@link TRegexExecRootNode#execute(Object, int)}. + */ + public int getFromIndex() { + return fromIndex; + } + + /** + * The maximum index as given by the parent {@link TRegexExecRootNode}. + * + * @return the maximum index as given by the parent {@link TRegexExecRootNode}. + */ + public int getMaxIndex() { + return maxIndex; + } + + /** + * The index pointing into {@link #getInput()}. + * + * @return the current index of {@link #getInput()} that is being processed. + */ + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public void incIndex(int i) { + this.index += i; + } +} 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 new file mode 100644 index 000000000000..d8fe8f5d49f4 --- /dev/null +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecutorNode.java @@ -0,0 +1,63 @@ +/* + * 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.truffle.regex.tregex.nodes; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.nodes.Node; + +public abstract class TRegexExecutorNode extends Node { + + @CompilationFinal private TRegexExecRootNode root; + + public void setRoot(TRegexExecRootNode root) { + this.root = root; + } + + /** + * The length of the {@code input} argument given to + * {@link TRegexExecRootNode#execute(Object, int)}. + * + * @return the length of the {@code input} argument given to + * {@link TRegexExecRootNode#execute(Object, int)}. + */ + public int getInputLength(TRegexExecutorLocals locals) { + assert root != null; + return root.inputLength(locals.getInput()); + } + + public char getChar(TRegexExecutorLocals locals) { + assert root != null; + return root.inputCharAt(locals.getInput(), locals.getIndex()); + } + + public char getCharAt(TRegexExecutorLocals locals, int index) { + assert root != null; + return root.inputCharAt(locals.getInput(), index); + } + + public abstract TRegexExecutorLocals createLocals(Object input, int fromIndex, int index, int maxIndex); + + public abstract Object execute(TRegexExecutorLocals locals, boolean compactString); +} diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/AllTransitionsInOneTreeMatcher.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/AllTransitionsInOneTreeMatcher.java similarity index 99% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/AllTransitionsInOneTreeMatcher.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/AllTransitionsInOneTreeMatcher.java index a90c6c4c7845..778b2105a79d 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/AllTransitionsInOneTreeMatcher.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/AllTransitionsInOneTreeMatcher.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import static com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import static com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/BackwardDFAStateNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/BackwardDFAStateNode.java similarity index 98% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/BackwardDFAStateNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/BackwardDFAStateNode.java index c35840f0a21b..4b667da295be 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/BackwardDFAStateNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/BackwardDFAStateNode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import com.oracle.truffle.regex.tregex.matchers.CharMatcher; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/CGTrackingDFAStateNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/CGTrackingDFAStateNode.java similarity index 95% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/CGTrackingDFAStateNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/CGTrackingDFAStateNode.java index c4c58f9dd66e..e001430a9be9 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/CGTrackingDFAStateNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/CGTrackingDFAStateNode.java @@ -22,12 +22,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.regex.tregex.matchers.CharMatcher; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorNode; public class CGTrackingDFAStateNode extends DFAStateNode { @@ -125,9 +127,8 @@ public void executeFindSuccessor(TRegexDFAExecutorLocals locals, TRegexDFAExecut * Finds the first matching transition. If a transition matches, * {@link #successorFound1(TRegexDFAExecutorLocals, TRegexDFAExecutorNode, int)} is called. The * index of the element of {@link #getMatchers()} that matched the current input character ( - * {@link TRegexDFAExecutorNode#getChar(TRegexDFAExecutorLocals)}) or - * {@link #FS_RESULT_NO_SUCCESSOR} is stored via - * {@link TRegexDFAExecutorLocals#setSuccessorIndex(int)}. + * {@link TRegexExecutorNode#getChar(TRegexExecutorLocals)}) or {@link #FS_RESULT_NO_SUCCESSOR} + * is stored via {@link TRegexDFAExecutorLocals#setSuccessorIndex(int)}. * * @param locals a virtual frame as described by {@link TRegexDFAExecutorProperties}. * @param executor this node's parent {@link TRegexDFAExecutorNode}. @@ -166,10 +167,9 @@ private boolean checkMatch1(TRegexDFAExecutorLocals locals, TRegexDFAExecutorNod * the looping transition matches, * {@link #successorFound2(TRegexDFAExecutorLocals, TRegexDFAExecutorNode, int)} is called. The * index of the element of {@link #getMatchers()} that matched the current input character ( - * {@link TRegexDFAExecutorNode#getChar(TRegexDFAExecutorLocals)}) or - * {@link #FS_RESULT_NO_SUCCESSOR} is stored via - * {@link TRegexDFAExecutorLocals#setSuccessorIndex(int)}. If no transition matches, - * {@link #noSuccessor2(TRegexDFAExecutorLocals, TRegexDFAExecutorNode)} is called. + * {@link TRegexExecutorNode#getChar(TRegexExecutorLocals)}) or {@link #FS_RESULT_NO_SUCCESSOR} + * is stored via {@link TRegexDFAExecutorLocals#setSuccessorIndex(int)}. If no transition + * matches, {@link #noSuccessor2(TRegexDFAExecutorLocals, TRegexDFAExecutorNode)} is called. * * @param locals a virtual frame as described by {@link TRegexDFAExecutorProperties}. * @param executor this node's parent {@link TRegexDFAExecutorNode}. @@ -214,10 +214,10 @@ private boolean checkMatch2(TRegexDFAExecutorLocals locals, TRegexDFAExecutorNod * than the looping transition matches, * {@link #successorFound3(TRegexDFAExecutorLocals, TRegexDFAExecutorNode, int, int)} is called. * The index of the element of {@link #getMatchers()} that matched the current input character ( - * {@link TRegexDFAExecutorNode#getChar(TRegexDFAExecutorLocals)}) or - * {@link #FS_RESULT_NO_SUCCESSOR} is stored via - * {@link TRegexDFAExecutorLocals#setSuccessorIndex(int)}. If no transition matches, - * {@link #noSuccessor3(TRegexDFAExecutorLocals, TRegexDFAExecutorNode, int)} is called. + * {@link TRegexExecutorNode#getChar(TRegexExecutorLocals)}) or {@link #FS_RESULT_NO_SUCCESSOR} + * is stored via {@link TRegexDFAExecutorLocals#setSuccessorIndex(int)}. If no transition + * matches, {@link #noSuccessor3(TRegexDFAExecutorLocals, TRegexDFAExecutorNode, int)} is + * called. * * @param locals a virtual frame as described by {@link TRegexDFAExecutorProperties}. * @param executor this node's parent {@link TRegexDFAExecutorNode}. diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAAbstractStateNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAAbstractStateNode.java similarity index 98% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAAbstractStateNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAAbstractStateNode.java index ad60c66ff54c..75bf8287ece6 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAAbstractStateNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAAbstractStateNode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.nodes.Node; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupLazyTransitionNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupLazyTransitionNode.java similarity index 98% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupLazyTransitionNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupLazyTransitionNode.java index 4f7cbffd1e62..408a249cc783 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupLazyTransitionNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupLazyTransitionNode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.regex.tregex.util.json.Json; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupPartialTransitionDispatchNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupPartialTransitionDispatchNode.java similarity index 99% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupPartialTransitionDispatchNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupPartialTransitionDispatchNode.java index 8c0dbf025a4b..94b8b3186ee8 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupPartialTransitionDispatchNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupPartialTransitionDispatchNode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupPartialTransitionNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupPartialTransitionNode.java similarity index 99% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupPartialTransitionNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupPartialTransitionNode.java index b4e33635891f..66b1f4d3ea09 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupPartialTransitionNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupPartialTransitionNode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.nodes.ExplodeLoop; @@ -303,6 +303,7 @@ public int hashCode() { return result; } + @TruffleBoundary @Override public String toString() { StringBuilder sb = new StringBuilder("DfaCGTransition"); @@ -322,6 +323,7 @@ public String toString() { return sb.toString(); } + @TruffleBoundary private static void indexManipulationsToString(StringBuilder sb, byte[][] indexManipulations, String name) { if (indexManipulations.length > 0) { sb.append(System.lineSeparator()).append(name).append(": "); @@ -359,6 +361,7 @@ public JsonValue toJson() { return json; } + @TruffleBoundary private static JsonObject.JsonObjectProperty indexManipulationToProp(String name, byte[] values) { return Json.prop(name, Json.obj( Json.prop("target", Byte.toUnsignedInt(values[0])), diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupTrackingData.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupTrackingData.java similarity index 97% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupTrackingData.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupTrackingData.java index d949f7abf12b..0dac071986b9 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFACaptureGroupTrackingData.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFACaptureGroupTrackingData.java @@ -23,7 +23,7 @@ * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; public final class DFACaptureGroupTrackingData { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAFindInnerLiteralStateNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAFindInnerLiteralStateNode.java similarity index 98% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAFindInnerLiteralStateNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAFindInnerLiteralStateNode.java index 752b54a33cbe..9e8e6e39882f 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAFindInnerLiteralStateNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAFindInnerLiteralStateNode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import java.util.Arrays; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAInitialStateNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAInitialStateNode.java similarity index 98% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAInitialStateNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAInitialStateNode.java index 57b32b084eab..91f108fc012e 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAInitialStateNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAInitialStateNode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import java.util.Arrays; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAStateNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAStateNode.java similarity index 97% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAStateNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAStateNode.java index cec30bdfb0f4..59ab8b2719db 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/DFAStateNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/DFAStateNode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import java.util.Arrays; @@ -34,6 +34,8 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.regex.tregex.matchers.CharMatcher; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorNode; import com.oracle.truffle.regex.tregex.nodes.input.InputIndexOfNode; import com.oracle.truffle.regex.tregex.util.DebugUtil; import com.oracle.truffle.regex.tregex.util.json.Json; @@ -239,9 +241,8 @@ private void runIndexOf(TRegexDFAExecutorLocals locals, TRegexDFAExecutorNode ex /** * Finds the first matching transition. The index of the element of {@link #getMatchers()} that * matched the current input character ( - * {@link TRegexDFAExecutorNode#getChar(TRegexDFAExecutorLocals)}) or - * {@link #FS_RESULT_NO_SUCCESSOR} is stored via - * {@link TRegexDFAExecutorLocals#setSuccessorIndex(int)}. + * {@link TRegexExecutorNode#getChar(TRegexExecutorLocals)}) or {@link #FS_RESULT_NO_SUCCESSOR} + * is stored via {@link TRegexDFAExecutorLocals#setSuccessorIndex(int)}. * * @param locals a virtual frame as described by {@link TRegexDFAExecutorProperties}. * @param executor this node's parent {@link TRegexDFAExecutorNode}. diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorDebugRecorder.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorDebugRecorder.java similarity index 95% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorDebugRecorder.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorDebugRecorder.java index c8ed26a7f096..43e0eede7cca 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorDebugRecorder.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorDebugRecorder.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import java.util.ArrayList; import java.util.List; @@ -32,15 +32,16 @@ import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.regex.RegexLanguage; import com.oracle.truffle.regex.tregex.dfa.DFAGenerator; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; import com.oracle.truffle.regex.tregex.util.json.Json; import com.oracle.truffle.regex.tregex.util.json.JsonConvertible; import com.oracle.truffle.regex.tregex.util.json.JsonValue; /** * This class is used to store a trace of the execution of a - * {@link TRegexDFAExecutorNode#execute(TRegexDFAExecutorLocals, boolean)}. A trace contains the - * arguments received by {@link TRegexDFAExecutorNode#execute(TRegexDFAExecutorLocals, boolean)}, - * and the ID of the DFA transition taken for all characters of the input string that have been + * {@link TRegexDFAExecutorNode#execute(TRegexExecutorLocals, boolean)}. A trace contains the + * arguments received by {@link TRegexDFAExecutorNode#execute(TRegexExecutorLocals, boolean)}, and + * the ID of the DFA transition taken for all characters of the input string that have been * traversed. After execution, the recorded trace can be dumped to disk as JSON with * {@link #finishRecording()}. */ diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorLocals.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorLocals.java similarity index 65% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorLocals.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorLocals.java index fe893e979394..5a856c5ceda7 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorLocals.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorLocals.java @@ -22,18 +22,15 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; + +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; /** - * Container for all local variables used in - * {@link TRegexDFAExecutorNode#execute(TRegexDFAExecutorLocals, boolean)}. + * Container for all local variables used in {@link TRegexDFAExecutorNode}. */ -public final class TRegexDFAExecutorLocals { +public final class TRegexDFAExecutorLocals extends TRegexExecutorLocals { - private final Object input; - private final int fromIndex; - private final int maxIndex; - private int index; private int curMaxIndex; private int successorIndex; private int result; @@ -42,54 +39,10 @@ public final class TRegexDFAExecutorLocals { private final DFACaptureGroupTrackingData cgData; public TRegexDFAExecutorLocals(Object input, int fromIndex, int index, int maxIndex, DFACaptureGroupTrackingData cgData) { - this.input = input; - this.fromIndex = fromIndex; - this.index = index; - this.maxIndex = maxIndex; + super(input, fromIndex, maxIndex, index); this.cgData = cgData; } - /** - * The {@code input} argument given to {@link TRegexExecRootNode#execute(Object, int)}. - * - * @return the {@code input} argument given to {@link TRegexExecRootNode#execute(Object, int)}. - */ - public Object getInput() { - return input; - } - - /** - * The {@code fromIndex} argument given to {@link TRegexExecRootNode#execute(Object, int)}. - * - * @return the {@code fromIndex} argument given to - * {@link TRegexExecRootNode#execute(Object, int)}. - */ - public int getFromIndex() { - return fromIndex; - } - - /** - * The maximum index as given by the parent {@link TRegexExecRootNode}. - * - * @return the maximum index as given by the parent {@link TRegexExecRootNode}. - */ - public int getMaxIndex() { - return maxIndex; - } - - /** - * The index pointing into {@link #getInput()}. - * - * @return the current index of {@link #getInput()} that is being processed. - */ - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - /** * The maximum index as checked by * {@link TRegexDFAExecutorNode#hasNext(TRegexDFAExecutorLocals)}. In most cases this value is @@ -150,6 +103,6 @@ public static int backwardMaxIndex(int fromIndex, int prefixLength) { } public TRegexDFAExecutorLocals toBackwardLocals(int prefixLength) { - return new TRegexDFAExecutorLocals(input, fromIndex, index - 1, backwardMaxIndex(fromIndex, prefixLength), null); + return new TRegexDFAExecutorLocals(getInput(), getFromIndex(), getIndex() - 1, backwardMaxIndex(getFromIndex(), prefixLength), null); } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorNode.java similarity index 91% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorNode.java index e14b7e3711ad..a55e887d358c 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorNode.java @@ -22,25 +22,22 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import java.util.Arrays; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.nodes.ExplodeLoop; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.regex.RegexRootNode; -import com.oracle.truffle.regex.tregex.nodes.input.InputCharAtNode; -import com.oracle.truffle.regex.tregex.nodes.input.InputLengthNode; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorNode; -public final class TRegexDFAExecutorNode extends Node { +public final class TRegexDFAExecutorNode extends TRegexExecutorNode { public static final int NO_MATCH = -2; private final TRegexDFAExecutorProperties props; private final int maxNumberOfNFAStates; - @Child private InputLengthNode lengthNode = InputLengthNode.create(); - @Child private InputCharAtNode charAtNode = InputCharAtNode.create(); @Children private final DFAAbstractStateNode[] states; @Children private final DFACaptureGroupLazyTransitionNode[] cgTransitions; private final TRegexDFAExecutorDebugRecorder debugRecorder; @@ -114,11 +111,26 @@ public TRegexDFAExecutorDebugRecorder getDebugRecorder() { return debugRecorder; } + @Override + public TRegexExecutorLocals createLocals(Object input, int fromIndex, int index, int maxIndex) { + return new TRegexDFAExecutorLocals(input, fromIndex, index, maxIndex, createCGData()); + } + + private DFACaptureGroupTrackingData createCGData() { + if (props.isTrackCaptureGroups()) { + return new DFACaptureGroupTrackingData(getMaxNumberOfNFAStates(), props.getNumberOfCaptureGroups()); + } else { + return null; + } + } + /** * records position of the END of the match found, or -1 if no match exists. */ + @Override @ExplodeLoop(kind = ExplodeLoop.LoopExplosionKind.MERGE_EXPLODE) - protected Object execute(final TRegexDFAExecutorLocals locals, final boolean compactString) { + public Object execute(final TRegexExecutorLocals abstractLocals, final boolean compactString) { + TRegexDFAExecutorLocals locals = (TRegexDFAExecutorLocals) abstractLocals; CompilerDirectives.ensureVirtualized(locals); CompilerAsserts.compilationConstant(states); CompilerAsserts.compilationConstant(states.length); @@ -205,21 +217,6 @@ private void debugRecordTransition(TRegexDFAExecutorLocals locals, DFAStateNode } } - /** - * The length of the {@code input} argument given to - * {@link TRegexExecRootNode#execute(Object, int)}. - * - * @return the length of the {@code input} argument given to - * {@link TRegexExecRootNode#execute(Object, int)}. - */ - public int getInputLength(TRegexDFAExecutorLocals locals) { - return lengthNode.execute(locals.getInput()); - } - - public char getChar(TRegexDFAExecutorLocals locals) { - return charAtNode.execute(locals.getInput(), locals.getIndex()); - } - public void advance(TRegexDFAExecutorLocals locals) { locals.setIndex(props.isForward() ? locals.getIndex() + 1 : locals.getIndex() - 1); } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorProperties.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorProperties.java similarity index 95% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorProperties.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorProperties.java index 6dc5cfcdf0b7..8cfcf405c7cc 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexDFAExecutorProperties.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexDFAExecutorProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; public final class TRegexDFAExecutorProperties { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexLazyCaptureGroupsRootNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexLazyCaptureGroupsRootNode.java similarity index 86% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexLazyCaptureGroupsRootNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexLazyCaptureGroupsRootNode.java index 6585b202cb16..4d3d99eba5e4 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexLazyCaptureGroupsRootNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexLazyCaptureGroupsRootNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; @@ -31,15 +31,16 @@ import com.oracle.truffle.regex.RegexProfile; import com.oracle.truffle.regex.RegexSource; import com.oracle.truffle.regex.result.LazyCaptureGroupsResult; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorEntryNode; public class TRegexLazyCaptureGroupsRootNode extends RegexBodyNode { - @Child private TRegexDFAExecutorEntryNode entryNode; + @Child private TRegexExecutorEntryNode entryNode; private final RegexProfile.TracksRegexProfile profiler; - public TRegexLazyCaptureGroupsRootNode(RegexLanguage language, RegexSource source, TRegexDFAExecutorNode captureGroupNode, RegexProfile.TracksRegexProfile profiler) { + public TRegexLazyCaptureGroupsRootNode(RegexLanguage language, RegexSource source, TRegexExecutorEntryNode captureGroupNode, RegexProfile.TracksRegexProfile profiler) { super(language, source); - this.entryNode = TRegexDFAExecutorEntryNode.create(captureGroupNode); + this.entryNode = insert(captureGroupNode); this.profiler = profiler; } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexLazyFindStartRootNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexLazyFindStartRootNode.java similarity index 85% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexLazyFindStartRootNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexLazyFindStartRootNode.java index 4bcda8b1a884..b6e21ce995cf 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexLazyFindStartRootNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TRegexLazyFindStartRootNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,22 +22,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.regex.RegexBodyNode; import com.oracle.truffle.regex.RegexLanguage; import com.oracle.truffle.regex.RegexSource; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorEntryNode; public class TRegexLazyFindStartRootNode extends RegexBodyNode { private final int prefixLength; - @Child private TRegexDFAExecutorEntryNode entryNode; + @Child private TRegexExecutorEntryNode entryNode; - public TRegexLazyFindStartRootNode(RegexLanguage language, RegexSource source, int prefixLength, TRegexDFAExecutorNode backwardNode) { + public TRegexLazyFindStartRootNode(RegexLanguage language, RegexSource source, int prefixLength, TRegexExecutorEntryNode backwardNode) { super(language, source); this.prefixLength = prefixLength; - this.entryNode = TRegexDFAExecutorEntryNode.create(backwardNode); + this.entryNode = insert(backwardNode); } @Override diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TraceFinderDFAStateNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TraceFinderDFAStateNode.java similarity index 98% rename from regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TraceFinderDFAStateNode.java rename to regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TraceFinderDFAStateNode.java index e388f0fc8ac4..717a2eae110e 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TraceFinderDFAStateNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/dfa/TraceFinderDFAStateNode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.regex.tregex.nodes; +package com.oracle.truffle.regex.tregex.nodes.dfa; import com.oracle.truffle.regex.tregex.matchers.CharMatcher; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/input/InputIndexOfStringNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/input/InputIndexOfStringNode.java index aa79e79b275c..80a72ce14873 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/input/InputIndexOfStringNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/input/InputIndexOfStringNode.java @@ -65,7 +65,7 @@ public int doTruffleObject(TruffleObject input, int fromIndex, int maxIndex, Str if (CompilerDirectives.inInterpreter()) { RegexRootNode.checkThreadInterrupted(); } - if (regionMatchesNode.execute(input, i, match, mask)) { + if (regionMatchesNode.execute(input, i, match, 0, match.length(), mask)) { return i; } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/input/InputRegionMatchesNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/input/InputRegionMatchesNode.java index f51736ca9694..72167967443d 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/input/InputRegionMatchesNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/input/InputRegionMatchesNode.java @@ -36,39 +36,56 @@ public static InputRegionMatchesNode create() { return InputRegionMatchesNodeGen.create(); } - public abstract boolean execute(Object input, int fromIndex, String match, String mask); + public abstract boolean execute(Object input, int fromIndex1, Object match, int fromIndex2, int length, String mask); @Specialization(guards = "mask == null") - public boolean regionMatches(String input, int fromIndex, String match, @SuppressWarnings("unused") String mask) { - return input.regionMatches(fromIndex, match, 0, match.length()); + public boolean regionMatches(String input, int fromIndex1, String match, int fromIndex2, int length, @SuppressWarnings("unused") String mask) { + return input.regionMatches(fromIndex1, match, fromIndex2, length); } @Specialization(guards = "mask != null") - public boolean regionMatchesWithMask(String input, int fromIndex, String match, String mask) { - return ArrayUtils.regionEqualsWithOrMask(input, fromIndex, match, 0, mask.length(), mask); + public boolean regionMatchesWithMask(String input, int fromIndex1, String match, int fromIndex2, int length, String mask) { + return ArrayUtils.regionEqualsWithOrMask(input, fromIndex1, match, fromIndex2, length, mask); } @Specialization(guards = "mask == null") - public boolean regionMatchesTruffleObjNoMask(TruffleObject input, int fromIndex, String match, String mask, + public boolean regionMatchesTruffleObjNoMask(TruffleObject input, int fromIndex1, String match, int fromIndex2, int length, String mask, @Cached("create()") InputLengthNode lengthNode, @Cached("create()") InputCharAtNode charAtNode) { - return regionMatchesTruffleObj(input, fromIndex, match, mask, lengthNode, charAtNode); + return regionMatchesTruffleObj(input, fromIndex1, match, fromIndex2, length, mask, lengthNode, charAtNode); } @Specialization(guards = "mask != null") - public boolean regionMatchesTruffleObjWithMask(TruffleObject input, int fromIndex, String match, String mask, + public boolean regionMatchesTruffleObjWithMask(TruffleObject input, int fromIndex1, String match, int fromIndex2, int length, String mask, @Cached("create()") InputLengthNode lengthNode, @Cached("create()") InputCharAtNode charAtNode) { assert match.length() == mask.length(); - return regionMatchesTruffleObj(input, fromIndex, match, mask, lengthNode, charAtNode); + return regionMatchesTruffleObj(input, fromIndex1, match, fromIndex2, length, mask, lengthNode, charAtNode); } - private static boolean regionMatchesTruffleObj(TruffleObject input, int fromIndex, String match, String mask, InputLengthNode lengthNode, InputCharAtNode charAtNode) { - if (fromIndex + match.length() > lengthNode.execute(input)) { + @Specialization(guards = "mask == null") + public boolean regionMatchesTruffleObjTruffleObjNoMask(TruffleObject input, int fromIndex1, TruffleObject match, int fromIndex2, int length, @SuppressWarnings("unused") String mask, + @Cached("create()") InputLengthNode lengthNode1, + @Cached("create()") InputCharAtNode charAtNode1, + @Cached("create()") InputLengthNode lengthNode2, + @Cached("create()") InputCharAtNode charAtNode2) { + if (fromIndex1 + length > lengthNode1.execute(input) || fromIndex2 + length > lengthNode2.execute(match)) { + return false; + } + for (int i = 0; i < length; i++) { + if (charAtNode1.execute(input, fromIndex1 + i) != charAtNode2.execute(match, fromIndex2 + i)) { + return false; + } + } + return true; + } + + private static boolean regionMatchesTruffleObj(TruffleObject input, int fromIndex1, String match, int fromIndex2, int length, String mask, InputLengthNode lengthNode, InputCharAtNode charAtNode) { + if (fromIndex1 + length > lengthNode.execute(input) || fromIndex2 + length > match.length()) { return false; } - for (int i = 0; i < match.length(); i++) { - if (InputCharAtNode.charAtWithMask(input, fromIndex + i, mask, i, charAtNode) != match.charAt(i)) { + for (int i = 0; i < length; i++) { + if (InputCharAtNode.charAtWithMask(input, fromIndex1 + i, mask, i, charAtNode) != match.charAt(fromIndex2 + i)) { return false; } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorLocals.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorLocals.java new file mode 100644 index 000000000000..1cc67be81197 --- /dev/null +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorLocals.java @@ -0,0 +1,124 @@ +/* + * 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.truffle.regex.tregex.nodes.nfa; + +import java.util.Arrays; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; + +public final class TRegexBacktrackingNFAExecutorLocals extends TRegexExecutorLocals { + + private final int stackFrameSize; + private int[] stack; + private int sp; + private final int[] result; + private int lastResultSp = -1; + private boolean forward = true; + + public TRegexBacktrackingNFAExecutorLocals(Object input, int fromIndex, int index, int maxIndex, int nCaptureGroups) { + super(input, fromIndex, maxIndex, index); + this.stackFrameSize = 2 + nCaptureGroups * 2; + this.stack = new int[stackFrameSize * 8]; + this.sp = 0; + this.result = new int[nCaptureGroups * 2]; + setIndex(fromIndex); + Arrays.fill(stack, sp + 2, stackFrameSize, -1); + } + + public void switchDirection() { + forward = !forward; + } + + public void apply(NFAStateTransition t) { + t.getGroupBoundaries().apply(stack, sp + 2, getIndex()); + } + + public void push(NFAStateTransition t) { + if (stack.length < sp + (stackFrameSize * 2)) { + stack = Arrays.copyOf(stack, stack.length * 2); + } + System.arraycopy(stack, sp, stack, sp + stackFrameSize, stackFrameSize); + t.getGroupBoundaries().apply(stack, sp + 2, getIndex()); + stack[sp]++; + stack[sp + 1] = t.getTarget().getId(); + sp += stackFrameSize; + } + + public void pushResult(NFAStateTransition t) { + System.arraycopy(stack, sp + 2, result, 0, result.length); + t.getGroupBoundaries().apply(result, 0, getIndex()); + lastResultSp = sp; + } + + public boolean canPopResult() { + return lastResultSp == sp; + } + + public int[] popResult() { + return result; + } + + public boolean canPop() { + return sp > 0; + } + + public int pop() { + assert sp > 0; + sp -= stackFrameSize; + return stack[sp + 1]; + } + + @Override + public int getIndex() { + return stack[sp]; + } + + @Override + public void setIndex(int i) { + stack[sp] = i; + } + + @Override + public void incIndex(int i) { + stack[sp] += forward ? i : -i; + } + + public int[] toResult() { + return Arrays.copyOfRange(stack, sp + 2, sp + stackFrameSize); + } + + @TruffleBoundary + public void printStack(int curPc) { + for (int i = sp; i >= 0; i -= stackFrameSize) { + System.out.print(String.format("pc: %3d, i: %3d, cg: [", (i == sp ? curPc : stack[i + 1]), stack[i])); + for (int j = i + 2; j < i + stackFrameSize - 1; j++) { + System.out.print(String.format("%2d, ", stack[j])); + } + System.out.println(String.format("%2d]", stack[i + stackFrameSize - 1])); + } + } +} diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java new file mode 100644 index 000000000000..47fccd191d5b --- /dev/null +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java @@ -0,0 +1,136 @@ +/* + * 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.truffle.regex.tregex.nodes.nfa; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.regex.tregex.nfa.NFA; +import com.oracle.truffle.regex.tregex.nfa.NFAState; +import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorNode; +import com.oracle.truffle.regex.tregex.nodes.input.InputRegionMatchesNode; +import com.oracle.truffle.regex.tregex.parser.ast.GroupBoundaries; + +/** + * This regex executor uses a backtracking algorithm on the NFA. It is used for all expressions that + * cannot be matched with the DFA, such as expressions with backreferences. + */ +public class TRegexBacktrackingNFAExecutorNode extends TRegexExecutorNode { + + private final NFA nfa; + private final int numberOfCaptureGroups; + + @Child InputRegionMatchesNode regionMatchesNode; + + public TRegexBacktrackingNFAExecutorNode(NFA nfa, int numberOfCaptureGroups) { + this.nfa = nfa; + nfa.setInitialLoopBack(!nfa.getAst().getFlags().isSticky()); + this.numberOfCaptureGroups = numberOfCaptureGroups; + for (int i = 0; i < nfa.getAnchoredEntry().length; i++) { + if (nfa.getState(nfa.getUnAnchoredEntry()[i].getTarget().getId()) != null && nfa.getAnchoredEntry()[i].getTarget() != nfa.getUnAnchoredEntry()[i].getTarget()) { + nfa.getAnchoredEntry()[i].getTarget().addLoopBackNext(new NFAStateTransition((short) -1, + nfa.getAnchoredEntry()[i].getTarget(), + nfa.getUnAnchoredEntry()[i].getTarget(), + GroupBoundaries.getEmptyInstance())); + } + } + } + + public int getNumberOfCaptureGroups() { + return numberOfCaptureGroups; + } + + @Override + public TRegexExecutorLocals createLocals(Object input, int fromIndex, int index, int maxIndex) { + return new TRegexBacktrackingNFAExecutorLocals(input, fromIndex, index, maxIndex, numberOfCaptureGroups); + } + + @Override + public Object execute(TRegexExecutorLocals abstractLocals, boolean compactString) { + TRegexBacktrackingNFAExecutorLocals locals = (TRegexBacktrackingNFAExecutorLocals) abstractLocals; + + final int offset = Math.min(locals.getIndex(), nfa.getAnchoredEntry().length - 1); + locals.setIndex(locals.getIndex() - offset); + int pc = (locals.getIndex() == 0 ? nfa.getAnchoredEntry() : nfa.getUnAnchoredEntry())[offset].getTarget().getId(); + if (nfa.getState(pc) == null) { + return null; + } + + while (true) { + NFAState curState = nfa.getState(pc); + if (curState.isFinalState(true)) { + return locals.toResult(); + } + int firstMatch = -1; + if (locals.getIndex() < getInputLength(locals)) { + char c = getChar(locals); + for (int i = getStartingTransition(curState); i >= 0; i--) { + if (curState.getNext()[i].getTarget().isAnchoredFinalState(true)) { + continue; + } + if (curState.getNext()[i].getTarget().getCharSet().contains(c)) { + if (firstMatch >= 0) { + if (curState.getNext()[firstMatch].getTarget().isUnAnchoredFinalState(true)) { + locals.pushResult(curState.getNext()[firstMatch]); + } else { + locals.push(curState.getNext()[firstMatch]); + } + } + firstMatch = i; + } + } + } else if (curState.hasTransitionToAnchoredFinalState(true) || curState.hasTransitionToUnAnchoredFinalState(true)) { + firstMatch = Math.min(Short.toUnsignedInt(curState.getTransitionToAnchoredFinalStateId(true)), + Short.toUnsignedInt(curState.getTransitionToUnAnchoredFinalStateId(true))); + } + if (firstMatch < 0) { + if (locals.canPopResult()) { + return locals.popResult(); + } else if (locals.canPop()) { + pc = locals.pop(); + } else { + return null; + } + } else { + locals.apply(curState.getNext()[firstMatch]); + locals.incIndex(1); + pc = curState.getNext()[firstMatch].getTarget().getId(); + } + } + } + + private static int getStartingTransition(NFAState curState) { + return Math.min(Short.toUnsignedInt(curState.getTransitionToUnAnchoredFinalStateId(true)), curState.getNext().length - 1); + } + + public boolean regionMatches(TRegexExecutorLocals locals, int startIndex1, int startIndex2, int length) { + if (regionMatchesNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + regionMatchesNode = InputRegionMatchesNode.create(); + } + return regionMatchesNode.execute(locals.getInput(), startIndex1, locals.getInput(), startIndex2, length, null); + } +} diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java new file mode 100644 index 000000000000..afe191e57ea2 --- /dev/null +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java @@ -0,0 +1,149 @@ +/* + * 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.truffle.regex.tregex.nodes.nfa; + +import java.util.Arrays; +import java.util.BitSet; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; + +public final class TRegexNFAExecutorLocals extends TRegexExecutorLocals { + + private final int frameSize; + private final int maxSize; + private int[] curStates; + private int[] nextStates; + int curStatesLength = 0; + int nextStatesLength = 0; + int iCurStates = 0; + private final BitSet marks; + private int[] result; + + public TRegexNFAExecutorLocals(Object input, int fromIndex, int index, int maxIndex, int nCaptureGroups, int nStates) { + super(input, fromIndex, maxIndex, index); + this.frameSize = 1 + nCaptureGroups * 2; + this.maxSize = nStates * frameSize; + this.curStates = new int[frameSize * 8]; + this.nextStates = new int[frameSize * 8]; + this.marks = new BitSet(nStates); + } + + public void addInitialState(int stateId) { + curStates[curStatesLength] = stateId; + Arrays.fill(curStates, curStatesLength + 1, curStatesLength + frameSize, -1); + curStatesLength += frameSize; + } + + public boolean successorsEmpty() { + return nextStatesLength == 0; + } + + public boolean hasNext() { + return iCurStates < curStatesLength; + } + + public int next() { + iCurStates += frameSize; + return curStates[iCurStates - frameSize]; + } + + public void clearMarks() { + marks.clear(); + } + + public void markState(int i) { + marks.set(i); + } + + public boolean isMarked(int i) { + return marks.get(i); + } + + public void pushSuccessor(NFAStateTransition t, boolean copy) { + if (nextStatesLength >= nextStates.length) { + nextStates = Arrays.copyOf(nextStates, Math.min(nextStates.length * 2, maxSize)); + } + nextStates[nextStatesLength] = t.getTarget().getId(); + if (copy) { + System.arraycopy(curStates, iCurStates - frameSize + 1, nextStates, nextStatesLength + 1, frameSize - 1); + } else { + Arrays.fill(nextStates, nextStatesLength + 1, nextStatesLength + frameSize, -1); + } + t.getGroupBoundaries().apply(nextStates, nextStatesLength + 1, getIndex()); + nextStatesLength += frameSize; + } + + public void nextChar() { + int[] tmp = curStates; + curStates = nextStates; + nextStates = tmp; + curStatesLength = nextStatesLength; + nextStatesLength = 0; + iCurStates = 0; + incIndex(1); + } + + public void pushResult(NFAStateTransition t, boolean copy) { + if (result == null) { + result = new int[frameSize - 1]; + } + if (copy) { + System.arraycopy(curStates, iCurStates + 1 - frameSize, result, 0, frameSize - 1); + } else { + Arrays.fill(result, -1); + } + t.getGroupBoundaries().apply(result, 0, getIndex()); + } + + public boolean hasResult() { + return result != null; + } + + public int[] getResult() { + return result; + } + + @TruffleBoundary + @Override + public String toString() { + StringBuilder sb = new StringBuilder("curState: ("); + for (int i = 0; i < curStatesLength; i += frameSize) { + if (i > 0) { + sb.append(","); + } + sb.append(curStates[i]); + } + sb.append("), nextState: ("); + for (int i = 0; i < nextStatesLength; i += frameSize) { + if (i > 0) { + sb.append(","); + } + sb.append(nextStates[i]); + } + return sb.append(")").toString(); + } +} diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java new file mode 100644 index 000000000000..05749665c942 --- /dev/null +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java @@ -0,0 +1,145 @@ +/* + * 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.truffle.regex.tregex.nodes.nfa; + +import com.oracle.truffle.regex.tregex.TRegexOptions; +import com.oracle.truffle.regex.tregex.nfa.NFA; +import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; +import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.TRegexDFAExecutorNode; + +/** + * This regex executor matches a given expression by calculating DFA states from the NFA on the fly, + * without any caching. It is used as a placeholder for {@link TRegexDFAExecutorNode} until the + * expression is executed {@link TRegexOptions#TRegexGenerateDFAThreshold} times, in order to avoid + * the costly DFA generation on all expressions that are not on any hot code paths. + */ +public class TRegexNFAExecutorNode extends TRegexExecutorNode { + + private final NFA nfa; + private final int numberOfCaptureGroups; + private final boolean searching; + + public TRegexNFAExecutorNode(NFA nfa, int numberOfCaptureGroups) { + this.nfa = nfa; + nfa.setInitialLoopBack(false); + this.numberOfCaptureGroups = numberOfCaptureGroups; + this.searching = !nfa.getAst().getFlags().isSticky() && !nfa.getAst().getRoot().startsWithCaret(); + } + + public NFA getNFA() { + return nfa; + } + + public int getNumberOfCaptureGroups() { + return numberOfCaptureGroups; + } + + @Override + public TRegexExecutorLocals createLocals(Object input, int fromIndex, int index, int maxIndex) { + return new TRegexNFAExecutorLocals(input, fromIndex, index, maxIndex, numberOfCaptureGroups, nfa.getNumberOfStates()); + } + + @Override + public Object execute(TRegexExecutorLocals abstractLocals, boolean compactString) { + TRegexNFAExecutorLocals locals = (TRegexNFAExecutorLocals) abstractLocals; + + final int offset = Math.min(locals.getIndex(), nfa.getAnchoredEntry().length - 1); + locals.setIndex(locals.getIndex() - offset); + int anchoredInitialState = nfa.getAnchoredEntry()[offset].getTarget().getId(); + int unAnchoredInitialState = nfa.getUnAnchoredEntry()[offset].getTarget().getId(); + if (locals.getIndex() == 0) { + locals.addInitialState(anchoredInitialState); + if (unAnchoredInitialState != anchoredInitialState && nfa.getState(unAnchoredInitialState) != null) { + locals.addInitialState(unAnchoredInitialState); + } + } else if (nfa.getState(unAnchoredInitialState) != null) { + locals.addInitialState(unAnchoredInitialState); + } else { + return null; + } + while (true) { + locals.clearMarks(); + if (locals.getIndex() < getInputLength(locals)) { + findNextStates(locals); + if (locals.successorsEmpty() && (!searching || locals.hasResult())) { + return locals.getResult(); + } + } else { + while (locals.hasNext()) { + if (expandStateAtEnd(locals, locals.next(), false)) { + return locals.getResult(); + } + } + if (searching && !locals.hasResult()) { + expandStateAtEnd(locals, nfa.getInitialLoopBackTransition().getTarget().getId(), true); + } + return locals.getResult(); + } + locals.nextChar(); + } + } + + private void findNextStates(TRegexNFAExecutorLocals locals) { + char c = getChar(locals); + while (locals.hasNext()) { + if (expandState(locals, locals.next(), c, false)) { + return; + } + } + if (searching && !locals.hasResult() && locals.getIndex() >= locals.getFromIndex()) { + expandState(locals, nfa.getInitialLoopBackTransition().getTarget().getId(), c, true); + } + } + + private boolean expandState(TRegexNFAExecutorLocals locals, int stateId, char c, boolean isLoopBack) { + for (NFAStateTransition t : nfa.getState(stateId).getNext()) { + if (locals.isMarked(t.getTarget().getId()) || t.getTarget().isAnchoredFinalState(true)) { + continue; + } + locals.markState(t.getTarget().getId()); + if (t.getTarget().isUnAnchoredFinalState(true)) { + locals.pushResult(t, !isLoopBack); + return true; + } + if (t.getTarget().getCharSet().contains(c)) { + locals.pushSuccessor(t, !isLoopBack); + } + } + return false; + } + + private boolean expandStateAtEnd(TRegexNFAExecutorLocals locals, int stateId, boolean isLoopBack) { + for (NFAStateTransition t : nfa.getState(stateId).getNext()) { + if (t.getTarget().isFinalState(true)) { + locals.pushResult(t, !isLoopBack); + return true; + } + } + return false; + } +} diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/DFANodeSplit.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/DFANodeSplit.java index f53c3c4cdfbc..f129d8702fa9 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/DFANodeSplit.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/DFANodeSplit.java @@ -30,8 +30,8 @@ import com.oracle.truffle.regex.tregex.automaton.StateSetBackingSortedArray; import com.oracle.truffle.regex.tregex.buffer.ShortArrayBuffer; import com.oracle.truffle.regex.tregex.dfa.DFAGenerator; -import com.oracle.truffle.regex.tregex.nodes.DFAAbstractStateNode; -import com.oracle.truffle.regex.tregex.nodes.DFAInitialStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFAAbstractStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFAInitialStateNode; import com.oracle.truffle.regex.util.CompilationFinalBitSet; import java.util.ArrayDeque; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/GraphNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/GraphNode.java index 853a3cc9f07f..e073b76264f8 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/GraphNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/GraphNode.java @@ -29,8 +29,8 @@ import com.oracle.truffle.regex.tregex.automaton.StateSet; import com.oracle.truffle.regex.tregex.automaton.StateSetBackingSortedArray; import com.oracle.truffle.regex.tregex.dfa.DFAGenerator; -import com.oracle.truffle.regex.tregex.nodes.DFAAbstractStateNode; -import com.oracle.truffle.regex.tregex.nodes.DFAInitialStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFAAbstractStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFAInitialStateNode; import java.util.Arrays; import java.util.Iterator; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexParser.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexParser.java index 8bb02ed6b03b..4d0c8515b0ee 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexParser.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexParser.java @@ -145,6 +145,13 @@ public RegexAST parse() throws RegexSyntaxException { break; } } + final CalcMinPathsVisitor calcMinPathsVisitor = new CalcMinPathsVisitor(); + calcMinPathsVisitor.runReverse(ast.getRoot()); + calcMinPathsVisitor.run(ast.getRoot()); + return ast; + } + + public void prepareForDFA() { if (properties.hasQuantifiers() && !properties.hasLargeCountedRepetitions()) { UnrollQuantifiersVisitor.unrollQuantifiers(this, ast.getRoot()); } @@ -160,11 +167,10 @@ public RegexAST parse() throws RegexSyntaxException { } } checkInnerLiteral(); - return ast; } private void checkInnerLiteral() { - if (ast.isLiteralString() || ast.getRoot().startsWithCaret() || ast.getRoot().endsWithDollar() || ast.getRoot().getAlternatives().size() != 1) { + if (ast.isLiteralString() || ast.getRoot().startsWithCaret() || ast.getRoot().endsWithDollar() || ast.getRoot().size() != 1) { return; } ArrayList terms = ast.getRoot().getAlternatives().get(0).getTerms(); @@ -241,7 +247,7 @@ private Group createGroup(Token token, boolean addToSeq, boolean capture, RegexA * sequence. */ private void addSequence(Token token) { - if (!curGroup.getAlternatives().isEmpty()) { + if (!curGroup.isEmpty()) { setComplexLookAround(); } curSequence = curGroup.addSequence(ast); @@ -391,11 +397,11 @@ private Term translateUnicodeCharClass(Token.CharacterClass token) { } } - if (group.getAlternatives().size() > 1) { + if (group.size() > 1) { properties.setAlternations(); } - if (group.getAlternatives().size() == 1 && group.getAlternatives().get(0).getTerms().size() == 1) { + if (group.size() == 1 && group.getAlternatives().get(0).getTerms().size() == 1) { // If we are generating a group with only one alternative consisting of one term, then // we unwrap the group and return the term directly (this makes inspecting the resulting // terms easier). @@ -471,8 +477,8 @@ private void setLoop() { private void expandQuantifier(Term toExpand) { assert toExpand.hasQuantifier(); Token.Quantifier quantifier = toExpand.getQuantifier(); + assert quantifier.getMin() <= TRegexOptions.TRegexMaxCountedRepetition && quantifier.getMax() <= TRegexOptions.TRegexMaxCountedRepetition : toExpand + " in " + source; toExpand.setQuantifier(null); - assert quantifier.getMin() <= TRegexOptions.TRegexMaxCountedRepetition && quantifier.getMax() <= TRegexOptions.TRegexMaxCountedRepetition; curTerm = toExpand; curSequence = (Sequence) curTerm.getParent(); curGroup = curSequence.getParent(); @@ -658,21 +664,49 @@ private void parseQuantifier(Token.Quantifier quantifier) throws RegexSyntaxExce addTerm(createCharClass(CharSet.getEmpty(), null)); return; } - if (quantifier.getMax() == 0 || (curTerm instanceof LookAroundAssertion && quantifier.getMin() == 0)) { + if (quantifier.getMax() == 0 || (quantifier.getMin() == 0 && (curTerm instanceof LookAroundAssertion || (curTerm instanceof CharacterClass && ((CharacterClass) curTerm).isDead())))) { deleteVisitor.run(curSequence.getLastTerm()); curSequence.removeLastTerm(); return; } + if (options.isDumpAutomata()) { + SourceSection src = curTerm.getSourceSection(); + curTerm.setSourceSection(src.getSource().createSection(src.getCharIndex(), src.getCharLength() + quantifier.getSourceSection().getCharLength())); + } if (curTerm instanceof LookAroundAssertion) { // quantifying LookAroundAssertions doesn't do anything if quantifier.getMin() > 0, so // ignore. return; } + if (quantifier.getMin() == 1 && quantifier.getMax() == 1) { + // x{1,1} -> x + return; + } + setQuantifier(curTerm, quantifier); + // merge equal successive quantified character classes + if (curSequence.size() > 1 && curTerm instanceof CharacterClass && curSequence.getTerms().get(curSequence.size() - 2) instanceof CharacterClass) { + CharacterClass prev = (CharacterClass) curSequence.getTerms().get(curSequence.size() - 2); + if (prev.hasQuantifier() && ((CharacterClass) curTerm).getCharSet().equals(prev.getCharSet())) { + setQuantifier(prev, new Token.Quantifier( + prev.getQuantifier().getMin() + quantifier.getMin(), + prev.getQuantifier().isInfiniteLoop() || quantifier.isInfiniteLoop() ? -1 : prev.getQuantifier().getMax() + quantifier.getMax(), + prev.getQuantifier().isGreedy() || quantifier.isGreedy())); + deleteVisitor.run(curSequence.getLastTerm()); + curSequence.removeLastTerm(); + curTerm = prev; + } + } + } + + private void setQuantifier(Term term, Token.Quantifier quantifier) { if (quantifier.getMin() > TRegexOptions.TRegexMaxCountedRepetition || quantifier.getMax() > TRegexOptions.TRegexMaxCountedRepetition) { properties.setLargeCountedRepetitions(); } - curTerm.setQuantifier(quantifier); + term.setQuantifier(quantifier); properties.setQuantifiers(); + if (quantifier.getMin() != quantifier.getMax()) { + properties.setAlternations(); + } } /** diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/Token.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/Token.java index fd3e09a8181b..6d3f5eebc528 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/Token.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/Token.java @@ -178,6 +178,38 @@ public boolean isGreedy() { return greedy; } + @Override + public int hashCode() { + return 31 * min + 31 * max + (greedy ? 1 : 0); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof Quantifier)) { + return false; + } + Quantifier o = (Quantifier) obj; + return min == o.min && max == o.max && greedy == o.greedy; + } + + @TruffleBoundary + @Override + public String toString() { + if (min == 0 && max == 1) { + return "?"; + } + if (min == 0 && isInfiniteLoop()) { + return "*"; + } + if (min == 1 && isInfiniteLoop()) { + return "+"; + } + return String.format("{%d,%s}", min, isInfiniteLoop() ? "" : String.valueOf(max)); + } + @TruffleBoundary @Override public JsonObject toJson() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/BackReference.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/BackReference.java index 3150ad8014bc..8d0363b4c8d2 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/BackReference.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/BackReference.java @@ -54,15 +54,16 @@ public BackReference copy(RegexAST ast, boolean recursive) { return ast.register(new BackReference(this)); } - @Override - public String toString() { - return "\\" + groupNr; - } - public int getGroupNr() { return groupNr; } + @TruffleBoundary + @Override + public String toString() { + return "\\" + groupNr + quantifierToString(); + } + @TruffleBoundary @Override public JsonValue toJson() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/CharacterClass.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/CharacterClass.java index 233695d603e3..bcebcd3e7b64 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/CharacterClass.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/CharacterClass.java @@ -147,9 +147,10 @@ public void extractSingleChar(char[] literal, char[] mask, int i) { } } + @TruffleBoundary @Override public String toString() { - return charSet.toString(); + return charSet.toString() + quantifierToString(); } @TruffleBoundary diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Group.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Group.java index 9d300f74a24b..9127ac955580 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Group.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Group.java @@ -292,6 +292,10 @@ public int size() { return alternatives.size(); } + public boolean isEmpty() { + return size() == 0; + } + /** * Adds a new alternative to this group. The new alternative will be appended to the * end, meaning it will have the lowest priority among all the alternatives. @@ -300,6 +304,7 @@ public int size() { */ public void add(Sequence sequence) { sequence.setParent(this); + sequence.setGroupIndex(alternatives.size()); alternatives.add(sequence); } @@ -313,6 +318,9 @@ public void add(Sequence sequence) { public void insertFirst(Sequence sequence) { sequence.setParent(this); alternatives.add(0, sequence); + for (int i = 0; i < alternatives.size(); i++) { + alternatives.get(i).setGroupIndex(i); + } } /** @@ -356,11 +364,11 @@ public String alternativesToString() { } public String loopToString() { - return isLoop() ? "*" : ""; + return isLoop() ? "*" : quantifierToString(); } - @Override @TruffleBoundary + @Override public String toString() { return "(" + (isCapturing() ? "" : "?:") + alternativesToString() + ")" + loopToString(); } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/GroupBoundaries.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/GroupBoundaries.java index f0b7e31a9a5b..23913e627881 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/GroupBoundaries.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/GroupBoundaries.java @@ -28,7 +28,7 @@ import com.oracle.truffle.regex.tregex.dfa.DFAGenerator; import com.oracle.truffle.regex.tregex.nfa.ASTTransition; import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; -import com.oracle.truffle.regex.tregex.nodes.DFACaptureGroupPartialTransitionNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFACaptureGroupPartialTransitionNode; import com.oracle.truffle.regex.tregex.util.json.Json; import com.oracle.truffle.regex.tregex.util.json.JsonArray; import com.oracle.truffle.regex.tregex.util.json.JsonConvertible; @@ -78,7 +78,7 @@ public static GroupBoundaries getEmptyInstance() { * Creates a byte array suitable to be part of the {@code indexUpdates} parameter passed to * {@link DFACaptureGroupPartialTransitionNode#create(DFAGenerator, byte[], byte[], byte[][], byte[][], byte)} * from this object. - * + * * @param targetArray the index of the row to be targeted. * * @see DFACaptureGroupPartialTransitionNode#create(DFAGenerator, byte[], byte[], byte[][], @@ -92,7 +92,7 @@ public byte[] updatesToPartialTransitionArray(int targetArray) { * Creates a byte array suitable to be part of the {@code indexClears} parameter passed to * {@link DFACaptureGroupPartialTransitionNode#create(DFAGenerator, byte[], byte[], byte[][], byte[][], byte)} * from this object. - * + * * @param targetArray the index of the row to be targeted. * * @see DFACaptureGroupPartialTransitionNode#create(DFAGenerator, byte[], byte[], byte[][], @@ -123,6 +123,15 @@ public CompilationFinalBitSet getUpdateIndices() { return updateIndices; } + /** + * Directly returns the {@link CompilationFinalBitSet} used to store the indices of all capture + * group boundaries that should be cleared when traversed.
+ * CAUTION: Do not alter the returned object! + */ + public CompilationFinalBitSet getClearIndices() { + return clearIndices; + } + public boolean hasIndexUpdates() { return !updateIndices.isEmpty(); } @@ -170,6 +179,19 @@ public void applyToResultFactory(PreCalculatedResultFactory resultFactory, int i } } + @TruffleBoundary + public void apply(int[] array, int offset, int index) { + if (this == EMPTY_INSTANCE) { + return; + } + for (int i : clearIndices) { + array[offset + i] = -1; + } + for (int i : updateIndices) { + array[offset + i] = index; + } + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookBehindAssertion.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookBehindAssertion.java index 9ab08114773e..633e71727743 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookBehindAssertion.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookBehindAssertion.java @@ -45,11 +45,11 @@ public class LookBehindAssertion extends LookAroundAssertion { /** * Creates a new look-behind assertion AST node. - * + * * Note that for this node to be complete, {@link RegexASTSubtreeRootNode#setGroup(Group)} has * to be called with the {@link Group} that represents the contents of this lookbehind * assertion. - * + * * @param negated whether this lookbehind assertion is negative or not */ LookBehindAssertion(boolean negated) { @@ -67,12 +67,12 @@ public LookBehindAssertion copy(RegexAST ast, boolean recursive) { /** * Verifies that the contents of this assertion ({@link #getGroup()}) are in "literal" form. - * + * * This means that there is only a single alternative which is composed of a sequence of * {@link CharacterClass} nodes and terminated by a {@link MatchFound} node. */ public boolean isLiteral() { - if (getGroup().getAlternatives().size() != 1) { + if (getGroup().size() != 1) { return false; } for (Term t : getGroup().getAlternatives().get(0).getTerms()) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexAST.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexAST.java index 79c9e2d0693e..2b62a09514c9 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexAST.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexAST.java @@ -172,7 +172,7 @@ public int getWrappedPrefixLength() { // The single alternative in the wrappedRoot is composed of N non-optional prefix // matchers, 1 group of optional matchers, 1 original root and 1 MatchFound node. By // taking size() - 3, we get the number of non-optional prefix matchers. - return wrappedRoot.getAlternatives().get(0).getTerms().size() - 3; + return wrappedRoot.getAlternatives().get(0).size() - 3; } return 0; } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Sequence.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Sequence.java index 7e52e4cce20f..737acf8afb10 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Sequence.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Sequence.java @@ -46,6 +46,7 @@ public final class Sequence extends RegexASTNode implements RegexASTVisitorIterable { private final ArrayList terms = new ArrayList<>(); + private short groupIndex; private short visitorIterationIndex = 0; Sequence() { @@ -76,6 +77,15 @@ public void setParent(RegexASTNode parent) { super.setParent(parent); } + public short getGroupIndex() { + assert getParent().getAlternatives().get(groupIndex) == this; + return groupIndex; + } + + public void setGroupIndex(int groupIndex) { + this.groupIndex = (short) groupIndex; + } + /** * Returns the list of terms that constitute this {@link Sequence}. *

@@ -131,6 +141,19 @@ public void removeLastTerm() { terms.remove(terms.size() - 1); } + public boolean isFirstInGroup() { + return getParent().getAlternatives().get(0) == this; + } + + public boolean isLastInGroup() { + return getParent().getAlternatives().get(getParent().getAlternatives().size() - 1) == this; + } + + public boolean isPenultimateInGroup() { + ArrayList alt = getParent().getAlternatives(); + return alt.size() > 1 && alt.get(alt.size() - 2) == this; + } + public boolean isLiteral() { if (isEmpty()) { return false; @@ -147,6 +170,38 @@ public boolean isSingleCharClass() { return size() == 1 && isLiteral(); } + public int getEnclosedCaptureGroupsLow() { + int lo = Integer.MAX_VALUE; + for (Term t : terms) { + if (t instanceof Group) { + Group g = (Group) t; + if (g.getEnclosedCaptureGroupsLow() != g.getEnclosedCaptureGroupsHigh()) { + lo = Math.min(lo, g.getEnclosedCaptureGroupsLow()); + } + if (g.isCapturing()) { + lo = Math.min(lo, g.getGroupNumber()); + } + } + } + return lo == Integer.MAX_VALUE ? -1 : lo; + } + + public int getEnclosedCaptureGroupsHigh() { + int hi = Integer.MIN_VALUE; + for (Term t : terms) { + if (t instanceof Group) { + Group g = (Group) t; + if (g.getEnclosedCaptureGroupsLow() != g.getEnclosedCaptureGroupsHigh()) { + hi = Math.max(hi, g.getEnclosedCaptureGroupsHigh()); + } + if (g.isCapturing()) { + hi = Math.max(hi, g.getGroupNumber() + 1); + } + } + } + return hi == Integer.MIN_VALUE ? -1 : hi; + } + @Override public RegexASTSubtreeRootNode getSubTreeParent() { return getParent().getSubTreeParent(); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Term.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Term.java index 29127c3c9888..fe7d5ba218d1 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Term.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Term.java @@ -24,6 +24,7 @@ */ package com.oracle.truffle.regex.tregex.parser.ast; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.regex.tregex.parser.Token; /** @@ -70,6 +71,11 @@ public void setQuantifier(Token.Quantifier quantifier) { this.quantifier = quantifier; } + @TruffleBoundary + protected String quantifierToString() { + return hasQuantifier() ? quantifier.toString() : ""; + } + @Override public RegexASTSubtreeRootNode getSubTreeParent() { RegexASTNode current = this; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/CalcMinPathsVisitor.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/CalcMinPathsVisitor.java index 2a075014f7d3..b5c2f84ef6c7 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/CalcMinPathsVisitor.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/CalcMinPathsVisitor.java @@ -119,6 +119,18 @@ protected void leave(Group group) { minPath = Math.min(minPath, s.getMinPath()); maxPath = Math.max(maxPath, s.getMaxPath()); } + if (group.hasQuantifier()) { + if (group.getQuantifier().getMin() == 0) { + caret = false; + dollar = false; + } + minPath = group.getMinPath() + ((minPath - group.getMinPath()) * group.getQuantifier().getMin()); + if (group.getQuantifier().isInfiniteLoop()) { + hasLoops = true; + } else { + maxPath = group.getMaxPath() + ((minPath - group.getMaxPath()) * group.getQuantifier().getMax()); + } + } group.setStartsWithCaret(caret); group.setEndsWithDollar(dollar); group.setHasLoops(hasLoops); @@ -218,8 +230,19 @@ public void leaveLookAroundAssertion(LookAroundAssertion assertion) { @Override protected void visit(CharacterClass characterClass) { - characterClass.getParent().incMinPath(); - characterClass.getParent().incMaxPath(); + if (characterClass.hasQuantifier()) { + characterClass.getParent().incMinPath(characterClass.getQuantifier().getMin()); + if (characterClass.getQuantifier().isInfiniteLoop()) { + characterClass.getParent().incMaxPath(characterClass.getQuantifier().getMin()); + characterClass.setHasLoops(); + characterClass.getParent().setHasLoops(); + } else { + characterClass.getParent().incMaxPath(characterClass.getQuantifier().getMax()); + } + } else { + characterClass.getParent().incMinPath(); + characterClass.getParent().incMaxPath(); + } characterClass.setMinPath(characterClass.getParent().getMinPath()); characterClass.setMaxPath(characterClass.getParent().getMaxPath()); if (characterClass.isDead()) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/NFATraversalRegexASTVisitor.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/NFATraversalRegexASTVisitor.java index 1a24d31707ae..cddc24445488 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/NFATraversalRegexASTVisitor.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/NFATraversalRegexASTVisitor.java @@ -110,7 +110,7 @@ public RegexASTNode getNode() { public boolean groupHasNextAlternative() { assert node instanceof Group; - return groupAlternativeIndex < ((Group) node).getAlternatives().size(); + return groupAlternativeIndex < ((Group) node).size(); } public Sequence groupGetNextAlternative() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/PreCalcResultVisitor.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/PreCalcResultVisitor.java index faa7c0c0bd55..bb6552a191f6 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/PreCalcResultVisitor.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/PreCalcResultVisitor.java @@ -38,11 +38,13 @@ public final class PreCalcResultVisitor extends DepthFirstTraversalRegexASTVisitor { private final boolean extractLiteral; + private final boolean unrollGroups; private int index = 0; private final char[] literal; private final char[] mask; private final PreCalculatedResultFactory result; + private PreCalcResultVisitor groupUnroller; private PreCalcResultVisitor(RegexAST ast, boolean extractLiteral) { result = new PreCalculatedResultFactory(ast.getNumberOfCaptureGroups()); @@ -54,6 +56,16 @@ private PreCalcResultVisitor(RegexAST ast, boolean extractLiteral) { literal = null; mask = null; } + unrollGroups = true; + } + + private PreCalcResultVisitor(boolean extractLiteral, boolean unrollGroups, int index, char[] literal, char[] mask, PreCalculatedResultFactory result) { + this.extractLiteral = extractLiteral; + this.unrollGroups = unrollGroups; + this.index = index; + this.literal = literal; + this.mask = mask; + this.result = result; } public static PreCalcResultVisitor run(RegexAST ast, boolean extractLiteral) { @@ -103,6 +115,17 @@ protected void leave(Group group) { if (group.isCapturing()) { result.setEnd(group.getGroupNumber(), index); } + if (unrollGroups && group.hasQuantifier()) { + assert group.getQuantifier().getMin() == group.getQuantifier().getMax(); + if (groupUnroller == null) { + groupUnroller = new PreCalcResultVisitor(extractLiteral, false, index, literal, mask, result); + } + groupUnroller.index = index; + for (int i = 0; i < group.getQuantifier().getMin() - 1; i++) { + groupUnroller.run(group); + } + index = groupUnroller.index; + } } @Override @@ -125,14 +148,17 @@ protected void visit(LookAheadAssertion assertion) { @Override protected void visit(CharacterClass characterClass) { - if (extractLiteral) { - if (mask == null) { - literal[index] = (char) characterClass.getCharSet().getLo(0); - } else { - characterClass.extractSingleChar(literal, mask, index); + assert !characterClass.hasQuantifier() || characterClass.getQuantifier().getMin() == characterClass.getQuantifier().getMax(); + for (int i = 0; i < (characterClass.hasQuantifier() ? characterClass.getQuantifier().getMin() : 1); i++) { + if (extractLiteral) { + if (mask == null) { + literal[index] = (char) characterClass.getCharSet().getLo(0); + } else { + characterClass.extractSingleChar(literal, mask, index); + } } + index++; } - index++; } @Override diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/util/DFAExport.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/util/DFAExport.java index 253456f92aa4..73579c133607 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/util/DFAExport.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/util/DFAExport.java @@ -35,7 +35,7 @@ import com.oracle.truffle.regex.tregex.matchers.EmptyMatcher; import com.oracle.truffle.regex.tregex.matchers.SingleCharMatcher; import com.oracle.truffle.regex.tregex.matchers.SingleRangeMatcher; -import com.oracle.truffle.regex.tregex.nodes.DFAStateNode; +import com.oracle.truffle.regex.tregex.nodes.dfa.DFAStateNode; import java.io.BufferedWriter; import java.io.IOException; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/util/NFAExport.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/util/NFAExport.java index 9fca7db94f6a..124a6e712b56 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/util/NFAExport.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/util/NFAExport.java @@ -105,8 +105,8 @@ private void exportDot() throws IOException { writer.newLine(); for (NFAState state : nfa.getStates()) { if (showState(state)) { - for (int i = 0; i < state.getNext(forward).size(); i++) { - NFAStateTransition transition = state.getNext(forward).get(i); + for (int i = 0; i < state.getNext(forward).length; i++) { + NFAStateTransition transition = state.getNext(forward)[i]; DotExport.printConnection(writer, labelState(transition.getSource(forward), true), labelState(transition.getTarget(forward), true), @@ -238,8 +238,8 @@ private void exportLaTex() throws IOException { if (s == null) { continue; } - for (int i = 0; i < s.getNext().size(); i++) { - NFAStateTransition t = s.getNext().get(i); + for (int i = 0; i < s.getNext().length; i++) { + NFAStateTransition t = s.getNext()[i]; if (visited.contains(s) && visited.contains(t.getTarget())) { printLaTexTransition(t, i); } @@ -311,10 +311,10 @@ private boolean showState(NFAState state) { return false; } if (nfa.isEntry(state, forward)) { - return !state.getNext(forward).isEmpty(); + return state.getNext(forward).length > 0; } if (state.isFinalState(forward)) { - return !state.getPrev(forward).isEmpty(); + return state.getPrev(forward).length > 0; } return true; } @@ -374,7 +374,7 @@ private String labelState(NFAState state, boolean markAnchored) { private String labelTransition(NFAStateTransition transition, int priority) { StringBuilder sb = new StringBuilder(); if (!(transition.getTarget(forward).isFinalState(forward))) { - sb.append(transition.getTarget(forward).getMatcherBuilder()); + sb.append(transition.getTarget(forward).getCharSet()); } if (fullLabels) { sb.append(", p").append(priority).append(", ").append(transition.getGroupBoundaries()); From 3895b2a0715ca7a85145a119fcd3c9655e876800 Mon Sep 17 00:00:00 2001 From: Josef Haider Date: Wed, 18 Sep 2019 10:03:35 +0200 Subject: [PATCH 006/140] TRegex: small performance tweaks in TRegexNFAExecutorNode --- .../oracle/truffle/regex/RegexProfile.java | 4 +- .../oracle/truffle/regex/tregex/nfa/NFA.java | 15 ++-- .../truffle/regex/tregex/nfa/NFAState.java | 28 +++++-- .../regex/tregex/nfa/NFAStateTransition.java | 4 +- .../tregex/nodes/TRegexExecRootNode.java | 13 ++-- .../TRegexBacktrackingNFAExecutorNode.java | 5 +- .../nodes/nfa/TRegexNFAExecutorLocals.java | 25 +++---- .../nodes/nfa/TRegexNFAExecutorNode.java | 73 +++++++++++-------- .../tregex/parser/ast/GroupBoundaries.java | 42 ++++++++--- .../ast/visitors/CalcMinPathsVisitor.java | 7 +- 10 files changed, 137 insertions(+), 79 deletions(-) diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexProfile.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexProfile.java index 1414c2eb16f8..32582f3d6681 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexProfile.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexProfile.java @@ -117,11 +117,11 @@ public boolean shouldGenerateDFA() { *

  • most searches led to a match
  • *
  • the capture groups of most search results were queried
  • *
  • the match often covered a big part of the part of the input string that had to be - * traversed in order to find it, or the match was usually very short
  • + * traversed in order to find it. * */ public boolean shouldUseEagerMatching() { - return matchRatio() > 0.5 && cgAccessRatio() > 0.5 && (avgMatchLength < 5 || avgMatchedPortionOfSearchSpace > 0.4); + return matchRatio() > 0.5 && cgAccessRatio() > 0.5 && avgMatchedPortionOfSearchSpace > 0.4; } @TruffleBoundary diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFA.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFA.java index c069b1ee00ac..b08e760698f0 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFA.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFA.java @@ -24,6 +24,7 @@ */ package com.oracle.truffle.regex.tregex.nfa; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.regex.result.PreCalculatedResultFactory; import com.oracle.truffle.regex.tregex.automaton.StateIndex; @@ -43,13 +44,13 @@ public final class NFA implements StateIndex, JsonConvertible { private final RegexAST ast; private final NFAState dummyInitialState; - private final NFAStateTransition[] anchoredEntry; - private final NFAStateTransition[] unAnchoredEntry; + @CompilationFinal(dimensions = 1) private final NFAStateTransition[] anchoredEntry; + @CompilationFinal(dimensions = 1) private final NFAStateTransition[] unAnchoredEntry; private final NFAStateTransition reverseAnchoredEntry; private final NFAStateTransition reverseUnAnchoredEntry; - private final NFAState[] states; - private final NFAStateTransition[] transitions; - private final PreCalculatedResultFactory[] preCalculatedResults; + @CompilationFinal(dimensions = 1) private final NFAState[] states; + @CompilationFinal(dimensions = 1) private final NFAStateTransition[] transitions; + @CompilationFinal(dimensions = 1) private final PreCalculatedResultFactory[] preCalculatedResults; private final NFAStateTransition initialLoopBack; public NFA(RegexAST ast, @@ -207,6 +208,10 @@ public NFAState getState(int id) { return states[id]; } + public int getNumberOfTransitions() { + return transitions.length; + } + public boolean isDead() { return anchoredEntry != null ? getAnchoredInitialState().isDead(true) : (reverseAnchoredEntry.getSource().isDead(false) && reverseUnAnchoredEntry.getSource().isDead(false)); } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAState.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAState.java index e2f5080d13ad..62b2fbb2ae6e 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAState.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAState.java @@ -24,6 +24,7 @@ */ package com.oracle.truffle.regex.tregex.nfa; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.regex.charset.CharSet; import com.oracle.truffle.regex.tregex.automaton.IndexedState; import com.oracle.truffle.regex.tregex.parser.ast.LookBehindAssertion; @@ -67,13 +68,13 @@ public class NFAState implements IndexedState, JsonConvertible { private final short id; private final ASTNodeSet stateSet; - private byte flags; - private short transitionToAnchoredFinalState = -1; - private short transitionToUnAnchoredFinalState = -1; - private short revTransitionToAnchoredFinalState = -1; - private short revTransitionToUnAnchoredFinalState = -1; - private NFAStateTransition[] next; - private NFAStateTransition[] prev; + @CompilationFinal private byte flags; + @CompilationFinal private short transitionToAnchoredFinalState = -1; + @CompilationFinal private short transitionToUnAnchoredFinalState = -1; + @CompilationFinal private short revTransitionToAnchoredFinalState = -1; + @CompilationFinal private short revTransitionToUnAnchoredFinalState = -1; + @CompilationFinal(dimensions = 1) private NFAStateTransition[] next; + @CompilationFinal(dimensions = 1) private NFAStateTransition[] prev; private short prevLength = 0; private List possibleResults; private final CharSet matcherBuilder; @@ -232,6 +233,19 @@ public short getTransitionToUnAnchoredFinalStateId(boolean forward) { return forward ? transitionToUnAnchoredFinalState : revTransitionToUnAnchoredFinalState; } + public boolean hasTransitionToFinalState(boolean forward) { + return hasTransitionToAnchoredFinalState(forward) || hasTransitionToUnAnchoredFinalState(forward); + } + + public int getFirstTransitionToFinalStateIndex(boolean forward) { + assert hasTransitionToFinalState(forward); + return Math.min(Short.toUnsignedInt(getTransitionToAnchoredFinalStateId(forward)), Short.toUnsignedInt(getTransitionToUnAnchoredFinalStateId(forward))); + } + + public NFAStateTransition getFirstTransitionToFinalState(boolean forward) { + return getNext(forward)[getFirstTransitionToFinalStateIndex(forward)]; + } + /** * List of possible next states, sorted by priority. */ diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAStateTransition.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAStateTransition.java index 3ea6e0f49840..51517f2d4240 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAStateTransition.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nfa/NFAStateTransition.java @@ -34,13 +34,15 @@ import static com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; + /** * Provides information about a transition from one NFAState to another state. */ public class NFAStateTransition implements JsonConvertible { private final short id; - private NFAState source; + @CompilationFinal private NFAState source; private final NFAState target; private final GroupBoundaries groupBoundaries; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecRootNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecRootNode.java index 534fa85a6a09..f3fa00ad8b35 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecRootNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/TRegexExecRootNode.java @@ -76,7 +76,7 @@ public TRegexExecRootNode(RegexLanguage language, TRegexCompiler tRegexCompiler, this.tRegexCompiler = tRegexCompiler; this.regressionTestMode = regressionTestMode; this.nfaNode = new NFARegexSearchNode(createEntryNode(backTrackingExecutor)); - this.runnerNode = insert(nfaNode); + this.runnerNode = nfaNode; if (this.regressionTestMode) { switchToLazyDFA(); } @@ -112,6 +112,9 @@ public final RegexResult execute(Object input, int fromIndex) { } private boolean nfaProducesSameResult(Object input, int fromIndex, RegexResult result) { + if (lazyDFANode == LAZY_DFA_BAILED_OUT) { + return true; + } assert !(runnerNode instanceof NFARegexSearchNode); RegexResult btResult = nfaNode.run(input, fromIndex, inputLength(input)); if (resultsEqual(result, btResult, ((TRegexNFAExecutorNode) nfaNode.entryNode.getExecutor()).getNumberOfCaptureGroups())) { @@ -261,10 +264,10 @@ public LazyCaptureGroupRegexSearchNode(RegexLanguage language, TRegexExecutorEntryNode backwardNode, TRegexExecutorEntryNode captureGroupNode, TRegexExecRootNode rootNode) { - this.forwardEntryNode = insert(forwardNode); + this.forwardEntryNode = forwardNode; this.flags = flags; this.preCalculatedResults = preCalculatedResults; - this.backwardEntryNode = insert(backwardNode); + this.backwardEntryNode = backwardNode; if (backwardNode == null) { assert singlePreCalcResult() || forwardNode == null; backwardCallTarget = null; @@ -358,7 +361,7 @@ static final class EagerCaptureGroupRegexSearchNode extends RunRegexSearchNode { @Child private TRegexExecutorEntryNode entryNode; EagerCaptureGroupRegexSearchNode(TRegexExecutorEntryNode entryNode) { - this.entryNode = insert(entryNode); + this.entryNode = entryNode; } @Override @@ -376,7 +379,7 @@ static final class NFARegexSearchNode extends RunRegexSearchNode { @Child private TRegexExecutorEntryNode entryNode; NFARegexSearchNode(TRegexExecutorEntryNode entryNode) { - this.entryNode = insert(entryNode); + this.entryNode = entryNode; } @Override diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java index 47fccd191d5b..89f1b3032b1f 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java @@ -102,9 +102,8 @@ public Object execute(TRegexExecutorLocals abstractLocals, boolean compactString firstMatch = i; } } - } else if (curState.hasTransitionToAnchoredFinalState(true) || curState.hasTransitionToUnAnchoredFinalState(true)) { - firstMatch = Math.min(Short.toUnsignedInt(curState.getTransitionToAnchoredFinalStateId(true)), - Short.toUnsignedInt(curState.getTransitionToUnAnchoredFinalStateId(true))); + } else if (curState.hasTransitionToFinalState(true)) { + firstMatch = curState.getFirstTransitionToFinalStateIndex(true); } if (firstMatch < 0) { if (locals.canPopResult()) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java index afe191e57ea2..6be966d399c8 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java @@ -25,7 +25,6 @@ package com.oracle.truffle.regex.tregex.nodes.nfa; import java.util.Arrays; -import java.util.BitSet; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; @@ -40,8 +39,9 @@ public final class TRegexNFAExecutorLocals extends TRegexExecutorLocals { int curStatesLength = 0; int nextStatesLength = 0; int iCurStates = 0; - private final BitSet marks; + private long[] marks; private int[] result; + private boolean resultPushed = false; public TRegexNFAExecutorLocals(Object input, int fromIndex, int index, int maxIndex, int nCaptureGroups, int nStates) { super(input, fromIndex, maxIndex, index); @@ -49,7 +49,7 @@ public TRegexNFAExecutorLocals(Object input, int fromIndex, int index, int maxIn this.maxSize = nStates * frameSize; this.curStates = new int[frameSize * 8]; this.nextStates = new int[frameSize * 8]; - this.marks = new BitSet(nStates); + this.marks = new long[((nStates - 1) >> 6) + 1]; } public void addInitialState(int stateId) { @@ -71,16 +71,8 @@ public int next() { return curStates[iCurStates - frameSize]; } - public void clearMarks() { - marks.clear(); - } - - public void markState(int i) { - marks.set(i); - } - - public boolean isMarked(int i) { - return marks.get(i); + public long[] getMarks() { + return marks; } public void pushSuccessor(NFAStateTransition t, boolean copy) { @@ -105,9 +97,12 @@ public void nextChar() { nextStatesLength = 0; iCurStates = 0; incIndex(1); + Arrays.fill(marks, 0); + resultPushed = false; } public void pushResult(NFAStateTransition t, boolean copy) { + resultPushed = true; if (result == null) { result = new int[frameSize - 1]; } @@ -123,6 +118,10 @@ public boolean hasResult() { return result != null; } + public boolean isResultPushed() { + return resultPushed; + } + public int[] getResult() { return result; } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java index 05749665c942..d977e6cf426e 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java @@ -25,8 +25,10 @@ package com.oracle.truffle.regex.tregex.nodes.nfa; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.regex.tregex.TRegexOptions; import com.oracle.truffle.regex.tregex.nfa.NFA; +import com.oracle.truffle.regex.tregex.nfa.NFAState; import com.oracle.truffle.regex.tregex.nfa.NFAStateTransition; import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorLocals; import com.oracle.truffle.regex.tregex.nodes.TRegexExecutorNode; @@ -49,6 +51,11 @@ public TRegexNFAExecutorNode(NFA nfa, int numberOfCaptureGroups) { nfa.setInitialLoopBack(false); this.numberOfCaptureGroups = numberOfCaptureGroups; this.searching = !nfa.getAst().getFlags().isSticky() && !nfa.getAst().getRoot().startsWithCaret(); + for (int i = 0; i < nfa.getNumberOfTransitions(); i++) { + if (nfa.getTransitions()[i] != null) { + nfa.getTransitions()[i].getGroupBoundaries().materializeArrays(); + } + } } public NFA getNFA() { @@ -67,6 +74,7 @@ public TRegexExecutorLocals createLocals(Object input, int fromIndex, int index, @Override public Object execute(TRegexExecutorLocals abstractLocals, boolean compactString) { TRegexNFAExecutorLocals locals = (TRegexNFAExecutorLocals) abstractLocals; + CompilerDirectives.ensureVirtualized(locals); final int offset = Math.min(locals.getIndex(), nfa.getAnchoredEntry().length - 1); locals.setIndex(locals.getIndex() - offset); @@ -83,21 +91,13 @@ public Object execute(TRegexExecutorLocals abstractLocals, boolean compactString return null; } while (true) { - locals.clearMarks(); if (locals.getIndex() < getInputLength(locals)) { findNextStates(locals); if (locals.successorsEmpty() && (!searching || locals.hasResult())) { return locals.getResult(); } } else { - while (locals.hasNext()) { - if (expandStateAtEnd(locals, locals.next(), false)) { - return locals.getResult(); - } - } - if (searching && !locals.hasResult()) { - expandStateAtEnd(locals, nfa.getInitialLoopBackTransition().getTarget().getId(), true); - } + findNextStatesAtEnd(locals); return locals.getResult(); } locals.nextChar(); @@ -107,7 +107,8 @@ public Object execute(TRegexExecutorLocals abstractLocals, boolean compactString private void findNextStates(TRegexNFAExecutorLocals locals) { char c = getChar(locals); while (locals.hasNext()) { - if (expandState(locals, locals.next(), c, false)) { + expandState(locals, locals.next(), c, false); + if (locals.isResultPushed()) { return; } } @@ -116,30 +117,44 @@ private void findNextStates(TRegexNFAExecutorLocals locals) { } } - private boolean expandState(TRegexNFAExecutorLocals locals, int stateId, char c, boolean isLoopBack) { - for (NFAStateTransition t : nfa.getState(stateId).getNext()) { - if (locals.isMarked(t.getTarget().getId()) || t.getTarget().isAnchoredFinalState(true)) { - continue; - } - locals.markState(t.getTarget().getId()); - if (t.getTarget().isUnAnchoredFinalState(true)) { - locals.pushResult(t, !isLoopBack); - return true; - } - if (t.getTarget().getCharSet().contains(c)) { - locals.pushSuccessor(t, !isLoopBack); + private void expandState(TRegexNFAExecutorLocals locals, int stateId, char c, boolean isLoopBack) { + NFAState state = nfa.getState(stateId); + for (int i = 0; i < maxTransitionIndex(state); i++) { + NFAStateTransition t = state.getNext()[i]; + NFAState target = t.getTarget(); + int targetId = t.getTarget().getId(); + int markIndex = targetId >> 6; + long markBit = 1L << targetId; + if (!t.getTarget().isAnchoredFinalState(true) && (locals.getMarks()[markIndex] & markBit) == 0) { + locals.getMarks()[markIndex] |= markBit; + if (t.getTarget().isUnAnchoredFinalState(true)) { + locals.pushResult(t, !isLoopBack); + } else if (target.getCharSet().contains(c)) { + locals.pushSuccessor(t, !isLoopBack); + } } } - return false; } - private boolean expandStateAtEnd(TRegexNFAExecutorLocals locals, int stateId, boolean isLoopBack) { - for (NFAStateTransition t : nfa.getState(stateId).getNext()) { - if (t.getTarget().isFinalState(true)) { - locals.pushResult(t, !isLoopBack); - return true; + private static int maxTransitionIndex(NFAState state) { + return state.hasTransitionToUnAnchoredFinalState(true) ? state.getTransitionToUnAnchoredFinalStateId(true) + 1 : state.getNext().length; + } + + private void findNextStatesAtEnd(TRegexNFAExecutorLocals locals) { + while (locals.hasNext()) { + expandStateAtEnd(locals, nfa.getState(locals.next()), false); + if (locals.isResultPushed()) { + return; } } - return false; + if (searching && !locals.hasResult()) { + expandStateAtEnd(locals, nfa.getInitialLoopBackTransition().getTarget(), true); + } + } + + private static void expandStateAtEnd(TRegexNFAExecutorLocals locals, NFAState state, boolean isLoopBack) { + if (state.hasTransitionToFinalState(true)) { + locals.pushResult(state.getFirstTransitionToFinalState(true), !isLoopBack); + } } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/GroupBoundaries.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/GroupBoundaries.java index 23913e627881..df37611e8abe 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/GroupBoundaries.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/GroupBoundaries.java @@ -24,6 +24,10 @@ */ package com.oracle.truffle.regex.tregex.parser.ast; +import java.util.Objects; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.regex.result.PreCalculatedResultFactory; import com.oracle.truffle.regex.tregex.dfa.DFAGenerator; import com.oracle.truffle.regex.tregex.nfa.ASTTransition; @@ -35,10 +39,6 @@ import com.oracle.truffle.regex.tregex.util.json.JsonValue; import com.oracle.truffle.regex.util.CompilationFinalBitSet; -import java.util.Objects; - -import static com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; - /** * Objects of this class represent the capture group boundaries traversed in a single * {@link NFAStateTransition} or {@link ASTTransition}. The boundaries of one capture group @@ -61,6 +61,8 @@ public class GroupBoundaries implements JsonConvertible { private final CompilationFinalBitSet updateIndices; private final CompilationFinalBitSet clearIndices; private final int cachedHash; + @CompilationFinal(dimensions = 1) private byte[] updateArray; + @CompilationFinal(dimensions = 1) private byte[] clearArray; GroupBoundaries(CompilationFinalBitSet updateIndices, CompilationFinalBitSet clearIndices) { this.updateIndices = updateIndices; @@ -106,12 +108,29 @@ private static byte[] createPartialTransitionArray(int targetArray, CompilationF assert !indices.isEmpty() : "should not be called on empty sets"; final byte[] indexUpdate = new byte[indices.numberOfSetBits() + 1]; indexUpdate[0] = (byte) targetArray; - int i = 1; + writeIndicesToArray(indices, indexUpdate, 1); + return indexUpdate; + } + + private static void writeIndicesToArray(CompilationFinalBitSet indices, final byte[] array, int offset) { + int i = offset; for (int j : indices) { assert j < 256; - indexUpdate[i++] = (byte) j; + array[i++] = (byte) j; + } + } + + public void materializeArrays() { + if (this != EMPTY_INSTANCE && updateArray == null) { + updateArray = indicesToArray(updateIndices); + clearArray = indicesToArray(clearIndices); } - return indexUpdate; + } + + private static byte[] indicesToArray(CompilationFinalBitSet indices) { + final byte[] array = new byte[indices.numberOfSetBits()]; + writeIndicesToArray(indices, array, 0); + return array; } /** @@ -179,16 +198,15 @@ public void applyToResultFactory(PreCalculatedResultFactory resultFactory, int i } } - @TruffleBoundary public void apply(int[] array, int offset, int index) { if (this == EMPTY_INSTANCE) { return; } - for (int i : clearIndices) { - array[offset + i] = -1; + for (byte i : clearArray) { + array[offset + Byte.toUnsignedInt(i)] = -1; } - for (int i : updateIndices) { - array[offset + i] = index; + for (byte i : updateArray) { + array[offset + Byte.toUnsignedInt(i)] = index; } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/CalcMinPathsVisitor.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/CalcMinPathsVisitor.java index b5c2f84ef6c7..e56dfeb26a0a 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/CalcMinPathsVisitor.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/visitors/CalcMinPathsVisitor.java @@ -124,11 +124,15 @@ protected void leave(Group group) { caret = false; dollar = false; } + // group.minPath and group.maxPath are summed up from the beginning of the regex to the + // beginning of the group. + // the min and max path of the sequences are further summed up with min and max path of + // the group, so sequence.minPath - group.minPath == the sequence's "own" minPath minPath = group.getMinPath() + ((minPath - group.getMinPath()) * group.getQuantifier().getMin()); if (group.getQuantifier().isInfiniteLoop()) { hasLoops = true; } else { - maxPath = group.getMaxPath() + ((minPath - group.getMaxPath()) * group.getQuantifier().getMax()); + maxPath = group.getMaxPath() + ((maxPath - group.getMaxPath()) * group.getQuantifier().getMax()); } } group.setStartsWithCaret(caret); @@ -233,7 +237,6 @@ protected void visit(CharacterClass characterClass) { if (characterClass.hasQuantifier()) { characterClass.getParent().incMinPath(characterClass.getQuantifier().getMin()); if (characterClass.getQuantifier().isInfiniteLoop()) { - characterClass.getParent().incMaxPath(characterClass.getQuantifier().getMin()); characterClass.setHasLoops(); characterClass.getParent().setHasLoops(); } else { From 071791a11542b66d2d4675d3d1530b004deee8b4 Mon Sep 17 00:00:00 2001 From: Josef Haider Date: Fri, 20 Sep 2019 15:31:09 +0200 Subject: [PATCH 007/140] TRegex: various parser improvements --- .../oracle/truffle/regex/charset/CharSet.java | 5 +- .../truffle/regex/charset/CodePointSet.java | 5 +- .../regex/charset/SortedListOfRanges.java | 2 +- .../tregex/TRegexCompilationRequest.java | 4 +- .../regex/tregex/automaton/StateSet.java | 20 +- .../automaton/StateSetBackingBitSet.java | 16 +- .../tregex/automaton/StateSetBackingSet.java | 13 - .../automaton/StateSetBackingSetFactory.java | 46 ++++ .../automaton/StateSetBackingSortedArray.java | 20 +- .../TRegexBacktrackingNFAExecutorNode.java | 5 + .../nodes/nfa/TRegexNFAExecutorLocals.java | 4 + .../nodes/nfa/TRegexNFAExecutorNode.java | 11 +- .../tregex/nodesplitter/DFANodeSplit.java | 16 +- .../regex/tregex/nodesplitter/GraphNode.java | 12 +- .../regex/tregex/parser/RegexLexer.java | 5 +- .../regex/tregex/parser/RegexParser.java | 251 ++++++++++++++---- .../truffle/regex/tregex/parser/Token.java | 14 +- .../tregex/parser/ast/BackReference.java | 5 + .../tregex/parser/ast/CharacterClass.java | 17 ++ .../regex/tregex/parser/ast/Group.java | 37 ++- .../tregex/parser/ast/LookAheadAssertion.java | 10 +- .../parser/ast/LookAroundAssertion.java | 5 + .../parser/ast/LookBehindAssertion.java | 6 + .../regex/tregex/parser/ast/MatchFound.java | 6 + .../tregex/parser/ast/PositionAssertion.java | 9 +- .../regex/tregex/parser/ast/RegexASTNode.java | 3 + .../tregex/parser/ast/RegexASTRootNode.java | 7 + .../parser/ast/RegexASTSubtreeRootNode.java | 1 + .../regex/tregex/parser/ast/Sequence.java | 30 ++- .../truffle/regex/tregex/parser/ast/Term.java | 13 + 30 files changed, 445 insertions(+), 153 deletions(-) create mode 100644 regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSetFactory.java diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java index 46005d29fe1a..3d37ee82cbcc 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java @@ -549,11 +549,14 @@ public static String rangesToString(char[] ranges, boolean numeric) { @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } if (obj instanceof CharSet) { return Arrays.equals(ranges, ((CharSet) obj).ranges); } if (obj instanceof SortedListOfRanges) { - return equals((SortedListOfRanges) obj); + return equalsListOfRanges((SortedListOfRanges) obj); } return false; } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CodePointSet.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CodePointSet.java index 445b2045a82f..755eda1e42e8 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CodePointSet.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CodePointSet.java @@ -267,11 +267,14 @@ private static void setRange(int[] arr, int i, int lo, int hi) { @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } if (obj instanceof CodePointSet) { return Arrays.equals(ranges, ((CodePointSet) obj).ranges); } if (obj instanceof SortedListOfRanges) { - return equals((SortedListOfRanges) obj); + return equalsListOfRanges((SortedListOfRanges) obj); } return false; } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/SortedListOfRanges.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/SortedListOfRanges.java index 872bec2ad16b..eec619201e9a 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/SortedListOfRanges.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/SortedListOfRanges.java @@ -600,7 +600,7 @@ default boolean matchesEverything() { return size() == 1 && getLo(0) == getMinValue() && getHi(0) == getMaxValue(); } - default boolean equals(SortedListOfRanges o) { + default boolean equalsListOfRanges(SortedListOfRanges o) { if (o == null || size() != o.size()) { return false; } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompilationRequest.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompilationRequest.java index 7b827e85c290..987903204c32 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompilationRequest.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/TRegexCompilationRequest.java @@ -177,6 +177,7 @@ TRegexExecRootNode.LazyCaptureGroupRegexSearchNode compileLazyDFAExecutor(TRegex } else if (preCalculatedResults == null || !nfa.hasReverseUnAnchoredEntry()) { executorNodeBackward = createDFAExecutor(nfa, false, false, false); } + logAutomatonSizes(rootNode); return new TRegexExecRootNode.LazyCaptureGroupRegexSearchNode( tRegexCompiler.getLanguage(), source, ast.getFlags(), preCalculatedResults, rootNode.createEntryNode(executorNodeForward), @@ -334,7 +335,8 @@ private void logAutomatonSizes(RegexExecRootNode result) { Json.prop("flags", source.getFlags()), Json.prop("props", ast == null ? new RegexProperties() : ast.getProperties()), Json.prop("astNodes", ast == null ? 0 : ast.getNumberOfNodes()), - Json.prop("nfaStates", nfa == null ? 0 : nfa.getStates().length), + Json.prop("nfaStates", nfa == null ? 0 : nfa.getNumberOfStates()), + Json.prop("nfaTransitions", nfa == null ? 0 : nfa.getNumberOfTransitions()), Json.prop("dfaStatesFwd", executorNodeForward == null ? 0 : executorNodeForward.getNumberOfStates()), Json.prop("dfaStatesBck", executorNodeBackward == null ? 0 : executorNodeBackward.getNumberOfStates()), Json.prop("dfaStatesCG", executorNodeCaptureGroups == null ? 0 : executorNodeCaptureGroups.getNumberOfStates()), diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSet.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSet.java index e3dddead514b..a18f632cdeee 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSet.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSet.java @@ -24,8 +24,6 @@ */ package com.oracle.truffle.regex.tregex.automaton; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; - import java.util.Collection; import java.util.Iterator; import java.util.PrimitiveIterator; @@ -34,6 +32,8 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; + /** * A specialized set for sequentially indexed objects. The objects stored in this set must implement * {@link IndexedState}, they are referenced by {@link IndexedState#getId()}. Up to a size of four, @@ -51,26 +51,28 @@ public class StateSet implements Set, Iterable { private static final long SHORT_MASK = 0xffff; private final StateIndex stateIndex; - private final StateSetBackingSet backingSet; + private final StateSetBackingSetFactory backingSetFactory; + private StateSetBackingSet backingSet; private byte flags = 0; private int size = 0; private long stateList = 0; private int cachedHash; - public StateSet(StateIndex stateIndex, StateSetBackingSet backingSet) { + public StateSet(StateIndex stateIndex, StateSetBackingSetFactory backingSetFactory) { this.stateIndex = stateIndex; - this.backingSet = backingSet; + this.backingSetFactory = backingSetFactory; } public StateSet(StateIndex stateIndex) { - this(stateIndex, new StateSetBackingBitSet()); + this(stateIndex, StateSetBackingSetFactory.BIT_SET); } protected StateSet(StateSet copy) { this.stateIndex = copy.stateIndex; this.flags = copy.flags; this.size = copy.size; - this.backingSet = copy.backingSet.copy(); + this.backingSetFactory = copy.backingSetFactory; + this.backingSet = copy.backingSet == null ? null : copy.backingSet.copy(); this.stateList = copy.stateList; this.cachedHash = copy.cachedHash; } @@ -85,7 +87,7 @@ public StateIndex getStateIndex() { private void checkSwitchToBitSet(int newSize) { if (!useBackingSet() && newSize > SWITCH_TO_BACKING_SET_THRESHOLD) { - backingSet.create(stateIndex.getNumberOfStates()); + backingSet = backingSetFactory.create(stateIndex.getNumberOfStates()); for (int i = 0; i < size(); i++) { backingSet.addBatch(stateListElement(stateList)); stateList >>>= Short.SIZE; @@ -105,7 +107,7 @@ public int size() { } private boolean useBackingSet() { - return backingSet.isActive(); + return backingSet != null; } private void setFlag(byte flag, boolean value) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingBitSet.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingBitSet.java index d967477af9de..e50db3df212f 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingBitSet.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingBitSet.java @@ -30,9 +30,10 @@ public class StateSetBackingBitSet implements StateSetBackingSet { - private CompilationFinalBitSet bitSet; + private final CompilationFinalBitSet bitSet; - public StateSetBackingBitSet() { + public StateSetBackingBitSet(int stateIndexSize) { + bitSet = new CompilationFinalBitSet(stateIndexSize); } private StateSetBackingBitSet(StateSetBackingBitSet copy) { @@ -44,17 +45,6 @@ public StateSetBackingSet copy() { return new StateSetBackingBitSet(this); } - @Override - public void create(int stateIndexSize) { - assert bitSet == null; - bitSet = new CompilationFinalBitSet(stateIndexSize); - } - - @Override - public boolean isActive() { - return bitSet != null; - } - @Override public boolean contains(short id) { return bitSet.get(id); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSet.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSet.java index e96b2df7f1fc..20a4361e6906 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSet.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSet.java @@ -36,19 +36,6 @@ public interface StateSetBackingSet extends Iterable { */ StateSetBackingSet copy(); - /** - * Initialize the backing set. This method must be called before calling any other method of the - * set. After this method is called, {@link #isActive()} will return {@code true}. - * - * @param stateIndexSize the maximum {@code short} value to be expected. - */ - void create(int stateIndexSize); - - /** - * @return {@code true} if the set was initialized by {@link #create(int)}. - */ - boolean isActive(); - /** * Analogous to {@link java.util.Set#contains(Object)}. */ diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSetFactory.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSetFactory.java new file mode 100644 index 000000000000..e347f0823ec8 --- /dev/null +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSetFactory.java @@ -0,0 +1,46 @@ +/* + * 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.truffle.regex.tregex.automaton; + +public interface StateSetBackingSetFactory { + + StateSetBackingSet create(int stateIndexSize); + + StateSetBackingSetFactory BIT_SET = new StateSetBackingSetFactory() { + + @Override + public StateSetBackingSet create(int stateIndexSize) { + return new StateSetBackingBitSet(stateIndexSize); + } + }; + + StateSetBackingSetFactory SORTED_ARRAY = new StateSetBackingSetFactory() { + + @Override + public StateSetBackingSet create(int stateIndexSize) { + return new StateSetBackingSortedArray(); + } + }; +} diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSortedArray.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSortedArray.java index 56f572744f3c..2f74e9afb160 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSortedArray.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/automaton/StateSetBackingSortedArray.java @@ -33,12 +33,11 @@ public class StateSetBackingSortedArray implements StateSetBackingSet { private short size; public StateSetBackingSortedArray() { + array = new short[8]; } private StateSetBackingSortedArray(StateSetBackingSortedArray copy) { - if (copy.isActive()) { - array = Arrays.copyOf(copy.array, copy.array.length); - } + array = Arrays.copyOf(copy.array, copy.array.length); size = copy.size; } @@ -47,16 +46,6 @@ public StateSetBackingSet copy() { return new StateSetBackingSortedArray(this); } - @Override - public void create(int stateIndexSize) { - array = new short[8]; - } - - @Override - public boolean isActive() { - return array != null; - } - private int find(short id) { return Arrays.binarySearch(array, 0, size, id); } @@ -198,12 +187,9 @@ public boolean equals(Object obj) { return false; } StateSetBackingSortedArray o = (StateSetBackingSortedArray) obj; - if (size != o.size || isActive() != o.isActive()) { + if (size != o.size) { return false; } - if (!isActive()) { - return true; - } for (int i = 0; i < size; i++) { if (array[i] != o.array[i]) { return false; diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java index 89f1b3032b1f..8e966669779a 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexBacktrackingNFAExecutorNode.java @@ -57,6 +57,11 @@ public TRegexBacktrackingNFAExecutorNode(NFA nfa, int numberOfCaptureGroups) { GroupBoundaries.getEmptyInstance())); } } + for (int i = 0; i < nfa.getNumberOfTransitions(); i++) { + if (nfa.getTransitions()[i] != null) { + nfa.getTransitions()[i].getGroupBoundaries().materializeArrays(); + } + } } public int getNumberOfCaptureGroups() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java index 6be966d399c8..941e409981dc 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java @@ -58,6 +58,10 @@ public void addInitialState(int stateId) { curStatesLength += frameSize; } + public boolean curStatesEmpty() { + return curStatesLength == 0; + } + public boolean successorsEmpty() { return nextStatesLength == 0; } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java index d977e6cf426e..f50817ca3c5c 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java @@ -80,14 +80,13 @@ public Object execute(TRegexExecutorLocals abstractLocals, boolean compactString locals.setIndex(locals.getIndex() - offset); int anchoredInitialState = nfa.getAnchoredEntry()[offset].getTarget().getId(); int unAnchoredInitialState = nfa.getUnAnchoredEntry()[offset].getTarget().getId(); - if (locals.getIndex() == 0) { + if (unAnchoredInitialState != anchoredInitialState && locals.getIndex() == 0) { locals.addInitialState(anchoredInitialState); - if (unAnchoredInitialState != anchoredInitialState && nfa.getState(unAnchoredInitialState) != null) { - locals.addInitialState(unAnchoredInitialState); - } - } else if (nfa.getState(unAnchoredInitialState) != null) { + } + if (nfa.getState(unAnchoredInitialState) != null) { locals.addInitialState(unAnchoredInitialState); - } else { + } + if (locals.curStatesEmpty()) { return null; } while (true) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/DFANodeSplit.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/DFANodeSplit.java index f129d8702fa9..5e1c5a87c68a 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/DFANodeSplit.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/DFANodeSplit.java @@ -24,22 +24,22 @@ */ package com.oracle.truffle.regex.tregex.nodesplitter; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.Set; + import com.oracle.truffle.regex.tregex.TRegexOptions; import com.oracle.truffle.regex.tregex.automaton.StateIndex; import com.oracle.truffle.regex.tregex.automaton.StateSet; -import com.oracle.truffle.regex.tregex.automaton.StateSetBackingSortedArray; +import com.oracle.truffle.regex.tregex.automaton.StateSetBackingSetFactory; import com.oracle.truffle.regex.tregex.buffer.ShortArrayBuffer; import com.oracle.truffle.regex.tregex.dfa.DFAGenerator; import com.oracle.truffle.regex.tregex.nodes.dfa.DFAAbstractStateNode; import com.oracle.truffle.regex.tregex.nodes.dfa.DFAInitialStateNode; import com.oracle.truffle.regex.util.CompilationFinalBitSet; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.Set; - /** * Implementation of a node splitting algorithm presented by Sebastian Unger and Frank Mueller in * "Handling Irreducible Loops: Optimized Node Splitting vs. DJ-Graphs" (2001) and "Transforming @@ -230,7 +230,7 @@ private void scc2(Set scc, GraphNode curNode, int level) { } private void handleScc(GraphNode topNode, Set scc) throws DFANodeSplitBailoutException { - StateSet msed = new StateSet<>(this, new StateSetBackingSortedArray()); + StateSet msed = new StateSet<>(this, StateSetBackingSetFactory.SORTED_ARRAY); for (GraphNode n : scc) { if (n.getDomTreeDepth() == topNode.getDomTreeDepth() + 1) { n.setWeightAndHeaders(this, n, scc); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/GraphNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/GraphNode.java index e073b76264f8..448cf7aaba20 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/GraphNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodesplitter/GraphNode.java @@ -24,18 +24,18 @@ */ package com.oracle.truffle.regex.tregex.nodesplitter; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Set; + import com.oracle.truffle.regex.tregex.automaton.IndexedState; import com.oracle.truffle.regex.tregex.automaton.StateIndex; import com.oracle.truffle.regex.tregex.automaton.StateSet; -import com.oracle.truffle.regex.tregex.automaton.StateSetBackingSortedArray; +import com.oracle.truffle.regex.tregex.automaton.StateSetBackingSetFactory; import com.oracle.truffle.regex.tregex.dfa.DFAGenerator; import com.oracle.truffle.regex.tregex.nodes.dfa.DFAAbstractStateNode; import com.oracle.truffle.regex.tregex.nodes.dfa.DFAInitialStateNode; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Set; - /** * Abstract graph node wrapper with lots of extra fields used by the dominator tree algorithm in * {@link DominatorTree} and the node splitting algorithm implemented in {@link DFANodeSplit}. @@ -64,7 +64,7 @@ final class GraphNode implements Comparable, IndexedState { GraphNode(DFANodeSplit graph, DFAAbstractStateNode dfaNode, short[] successorSet) { this.dfaNode = dfaNode; this.successorSet = successorSet; - predecessorSet = new StateSet<>(graph, new StateSetBackingSortedArray()); + predecessorSet = new StateSet<>(graph, StateSetBackingSetFactory.SORTED_ARRAY); backEdges = new StateSet<>(graph); domChildren = NO_DOM_CHILDREN; } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexLexer.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexLexer.java index f39e90ced594..663d459f1df3 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexLexer.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexLexer.java @@ -221,7 +221,7 @@ private Token charClass(int codePoint) { curCharClass.appendRange(codePoint, codePoint); return charClass(false); } else { - return Token.createCharClass(CodePointSet.create(codePoint, codePoint)); + return Token.createCharClass(CodePointSet.create(codePoint, codePoint), true); } } @@ -236,11 +236,12 @@ private Token charClass(CodePointSet codePointSet) { } private Token charClass(boolean invert) { + boolean wasSingleChar = !invert && curCharClass.get().matchesSingleChar(); if (flags.isIgnoreCase()) { CaseFoldTable.CaseFoldingAlgorithm caseFolding = flags.isUnicode() ? CaseFoldTable.CaseFoldingAlgorithm.ECMAScriptUnicode : CaseFoldTable.CaseFoldingAlgorithm.ECMAScriptNonUnicode; CaseFoldTable.applyCaseFold(curCharClass, caseFolding); } - return Token.createCharClass(invert ? CodePointSet.createInverse(curCharClass.get()) : CodePointSet.create(curCharClass.get())); + return Token.createCharClass(invert ? CodePointSet.createInverse(curCharClass.get()) : CodePointSet.create(curCharClass.get()), wasSingleChar); } /* lexer */ diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexParser.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexParser.java index 4d0c8515b0ee..faf89f98bb4a 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexParser.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/RegexParser.java @@ -36,7 +36,6 @@ import com.oracle.truffle.regex.charset.CharSet; import com.oracle.truffle.regex.charset.CodePointSet; import com.oracle.truffle.regex.charset.Constants; -import com.oracle.truffle.regex.charset.SortedListOfRanges; import com.oracle.truffle.regex.tregex.TRegexOptions; import com.oracle.truffle.regex.tregex.buffer.CompilationBuffer; import com.oracle.truffle.regex.tregex.buffer.IntRangesBuffer; @@ -145,9 +144,6 @@ public RegexAST parse() throws RegexSyntaxException { break; } } - final CalcMinPathsVisitor calcMinPathsVisitor = new CalcMinPathsVisitor(); - calcMinPathsVisitor.runReverse(ast.getRoot()); - calcMinPathsVisitor.run(ast.getRoot()); return ast; } @@ -301,6 +297,9 @@ private void addLookAheadAssertion(Token token, boolean negate) { private Term translateUnicodeCharClass(Token.CharacterClass token) { CodePointSet codePointSet = token.getCodePointSet(); SourceSection src = token.getSourceSection(); + if (Constants.BMP_WITHOUT_SURROGATES.contains(token.getCodePointSet())) { + return createCharClass(codePointSet, src, token.wasSingleChar()); + } Group group = ast.createGroup(); group.setEnclosedCaptureGroupsLow(groupCount.getCount()); group.setEnclosedCaptureGroupsHigh(groupCount.getCount()); @@ -310,6 +309,8 @@ private Term translateUnicodeCharClass(Token.CharacterClass token) { CodePointSet loneLeadSurrogateRanges = codePointSet.createIntersection(Constants.LEAD_SURROGATES, tmp); CodePointSet loneTrailSurrogateRanges = codePointSet.createIntersection(Constants.TRAIL_SURROGATES, tmp); + assert astralRanges.matchesSomething() || loneLeadSurrogateRanges.matchesSomething() || loneTrailSurrogateRanges.matchesSomething(); + if (bmpRanges.matchesSomething()) { Sequence bmpAlternative = group.addSequence(ast); bmpAlternative.add(createCharClass(bmpRanges, src)); @@ -400,15 +401,7 @@ private Term translateUnicodeCharClass(Token.CharacterClass token) { if (group.size() > 1) { properties.setAlternations(); } - - if (group.size() == 1 && group.getAlternatives().get(0).getTerms().size() == 1) { - // If we are generating a group with only one alternative consisting of one term, then - // we unwrap the group and return the term directly (this makes inspecting the resulting - // terms easier). - // NB: This happens when the codePointSet contains only elements from the BMP which are - // not surrogates. - return group.getAlternatives().get(0).getTerms().get(0); - } + assert !(group.size() == 1 && group.getAlternatives().get(0).getTerms().size() == 1); return group; } @@ -422,17 +415,32 @@ private void addCharClass(Token.CharacterClass token) { addTerm(translateUnicodeCharClass(token)); } } else { - addTerm(createCharClass(codePointSet, token.getSourceSection())); + addTerm(createCharClass(codePointSet, token.getSourceSection(), token.wasSingleChar())); } } - private CharacterClass createCharClass(SortedListOfRanges codePointSet, SourceSection sourceSection) { + private CharacterClass createCharClass(IntRangesBuffer buf, SourceSection sourceSection) { + return createCharClass(CharSet.fromSortedRanges(buf), sourceSection); + } + + private CharacterClass createCharClass(CodePointSet codePointSet, SourceSection sourceSection) { return createCharClass(CharSet.fromSortedRanges(codePointSet), sourceSection); } - private CharacterClass createCharClass(CharSet matcherBuilder, SourceSection sourceSection) { - CharacterClass characterClass = ast.createCharacterClass(matcherBuilder); + private CharacterClass createCharClass(CodePointSet codePointSet, SourceSection sourceSection, boolean wasSingleChar) { + return createCharClass(CharSet.fromSortedRanges(codePointSet), sourceSection, wasSingleChar); + } + + private CharacterClass createCharClass(CharSet charSet, SourceSection sourceSection) { + return createCharClass(charSet, sourceSection, false); + } + + private CharacterClass createCharClass(CharSet charSet, SourceSection sourceSection, boolean wasSingleChar) { + CharacterClass characterClass = ast.createCharacterClass(charSet); characterClass.setSourceSection(sourceSection); + if (wasSingleChar) { + characterClass.setWasSingleChar(); + } return characterClass; } @@ -632,7 +640,8 @@ private Group parse(boolean rootCapture) throws RegexSyntaxException { curGroup.removeLastSequence(); ast.getNodeCount().dec(); } - tryMergeCommonPrefixes(); + sortAlternatives(); + tryMergeCommonPrefixes(curGroup); popGroup(token); break; case charClass: @@ -683,10 +692,10 @@ private void parseQuantifier(Token.Quantifier quantifier) throws RegexSyntaxExce return; } setQuantifier(curTerm, quantifier); - // merge equal successive quantified character classes - if (curSequence.size() > 1 && curTerm instanceof CharacterClass && curSequence.getTerms().get(curSequence.size() - 2) instanceof CharacterClass) { - CharacterClass prev = (CharacterClass) curSequence.getTerms().get(curSequence.size() - 2); - if (prev.hasQuantifier() && ((CharacterClass) curTerm).getCharSet().equals(prev.getCharSet())) { + // merge equal successive quantified terms + if (curSequence.size() > 1) { + Term prev = curSequence.getTerms().get(curSequence.size() - 2); + if (prev.hasQuantifier() && curTerm.equalsSemantic(prev, true)) { setQuantifier(prev, new Token.Quantifier( prev.getQuantifier().getMin() + quantifier.getMin(), prev.getQuantifier().isInfiniteLoop() || quantifier.isInfiniteLoop() ? -1 : prev.getQuantifier().getMax() + quantifier.getMax(), @@ -727,6 +736,7 @@ private boolean tryMergeSingleCharClassAlternations() { CharacterClass prevCC = (CharacterClass) prevSequence.getFirstTerm(); CharacterClass curCC = (CharacterClass) curSequence.getFirstTerm(); prevCC.setCharSet(prevCC.getCharSet().union(curCC.getCharSet())); + prevCC.setWasSingleChar(false); curSequence.removeLastTerm(); ast.getNodeCount().dec(); if (options.isDumpAutomata()) { @@ -742,56 +752,187 @@ private boolean tryMergeSingleCharClassAlternations() { } /** - * Simplify redundant alternation prefixes, e.g. {@code /ab|ac/ -> /a(?:b|c)/}. This method - * should be called when {@code curGroup} is about to be closed. + * Stable-sort consecutive alternations that start with single characters, to enable more + * simplifications with {@link #tryMergeCommonPrefixes(Group)}. This also works in ignore-case + * mode, since we track character classes that were generated from single characters via + * {@link CharacterClass#wasSingleChar()}. */ - private void tryMergeCommonPrefixes() { + private void sortAlternatives() { if (curGroup.size() < 2) { return; } - int prefixSize = 0; - while (groupHasEqualCharClassesAt(prefixSize)) { - prefixSize++; - } - if (prefixSize > 0) { - Sequence prefixSeq = ast.createSequence(); - for (int i = 0; i < prefixSize; i++) { - prefixSeq.add(curGroup.getAlternatives().get(0).getTerms().get(i)); + int begin = 0; + while (begin + 1 < curGroup.size()) { + int end = findSingleCharAlternatives(curGroup, begin); + if (end > begin + 1) { + curGroup.getAlternatives().subList(begin, end).sort((Sequence a, Sequence b) -> { + return ((CharacterClass) a.getFirstTerm()).getCharSet().getLo(0) - ((CharacterClass) b.getFirstTerm()).getCharSet().getLo(0); + }); + begin = end; + } else { + begin++; } - Group innerGroup = ast.createGroup(); - innerGroup.setEnclosedCaptureGroupsLow(curGroup.getEnclosedCaptureGroupsLow()); - innerGroup.setEnclosedCaptureGroupsHigh(curGroup.getEnclosedCaptureGroupsHigh()); - prefixSeq.add(innerGroup); - for (Sequence s : curGroup.getAlternatives()) { - assert s.size() >= prefixSize; - Sequence copy = innerGroup.addSequence(ast); - for (int i = prefixSize; i < s.size(); i++) { - copy.add(s.getTerms().get(i)); + } + } + + /** + * Simplify redundant alternation prefixes, e.g. {@code /ab|ac/ -> /a(?:b|c)/}. This method + * should be called when {@code curGroup} is about to be closed. + */ + private boolean tryMergeCommonPrefixes(Group group) { + if (group.size() < 2) { + return false; + } + ArrayList newAlternatives = null; + int lastEnd = 0; + int begin = 0; + while (begin + 1 < group.size()) { + int end = findMatchingAlternatives(group, begin); + if (end < 0) { + begin++; + } else { + if (newAlternatives == null) { + newAlternatives = new ArrayList<>(); + } + for (int i = lastEnd; i < begin; i++) { + newAlternatives.add(group.getAlternatives().get(i)); } + lastEnd = end; + int prefixSize = 1; + while (alternativesAreEqualAt(group, begin, end, prefixSize)) { + prefixSize++; + } + Sequence prefixSeq = ast.createSequence(); + Group innerGroup = ast.createGroup(); + int enclosedCGLo = Integer.MAX_VALUE; + int enclosedCGHi = Integer.MIN_VALUE; + boolean emptyAlt = false; + for (int i = begin; i < end; i++) { + Sequence s = group.getAlternatives().get(i); + assert s.size() >= prefixSize; + for (int j = 0; j < prefixSize; j++) { + Term t = s.getTerms().get(j); + if (i == begin) { + prefixSeq.add(t); + } else { + deleteVisitor.run(t); + } + } + // merge successive single-character-class alternatives + if (i > begin && s.size() - prefixSize == 1 && + s.getLastTerm() instanceof CharacterClass && !s.getLastTerm().hasQuantifier() && + innerGroup.getLastAlternative().isSingleCharClass()) { + CharacterClass prevCC = (CharacterClass) innerGroup.getLastAlternative().getFirstTerm(); + CharacterClass curCC = (CharacterClass) s.getLastTerm(); + prevCC.setCharSet(prevCC.getCharSet().union(curCC.getCharSet())); + } else { + // avoid creation of multiple empty alternatives in one group + if (prefixSize == s.size()) { + if (!emptyAlt) { + innerGroup.addSequence(ast); + } + emptyAlt = true; + } else { + Sequence copy = innerGroup.addSequence(ast); + for (int j = prefixSize; j < s.size(); j++) { + Term t = s.getTerms().get(j); + copy.add(t); + if (t instanceof Group) { + Group g = (Group) t; + if (g.getEnclosedCaptureGroupsLow() != g.getEnclosedCaptureGroupsHigh()) { + enclosedCGLo = Math.min(enclosedCGLo, g.getEnclosedCaptureGroupsLow()); + enclosedCGHi = Math.max(enclosedCGHi, g.getEnclosedCaptureGroupsHigh()); + } + if (g.isCapturing()) { + enclosedCGLo = Math.min(enclosedCGLo, g.getGroupNumber()); + enclosedCGHi = Math.max(enclosedCGHi, g.getGroupNumber() + 1); + } + } + } + } + } + } + if (enclosedCGLo != Integer.MAX_VALUE) { + innerGroup.setEnclosedCaptureGroupsLow(enclosedCGLo); + innerGroup.setEnclosedCaptureGroupsHigh(enclosedCGHi); + } + if (!innerGroup.isEmpty() && !(innerGroup.size() == 1 && innerGroup.getAlternatives().get(0).isEmpty())) { + tryMergeCommonPrefixes(innerGroup); + prefixSeq.add(innerGroup); + } + newAlternatives.add(prefixSeq); + begin = end; } - curGroup.getAlternatives().clear(); - curGroup.add(prefixSeq); } + if (newAlternatives != null) { + for (int i = lastEnd; i < group.size(); i++) { + newAlternatives.add(group.getAlternatives().get(i)); + } + group.setAlternatives(newAlternatives); + } + return newAlternatives != null; } - private boolean groupHasEqualCharClassesAt(int i) { - CharacterClass cmp = null; - for (Sequence s : curGroup.getAlternatives()) { - if (s.size() <= i || s.getTerms().get(i).hasQuantifier() || !(s.getTerms().get(i) instanceof CharacterClass)) { + /** + * Returns {@code true} iff the term at index {@code iTerm} of all alternatives in {@code group} + * from index {@code altBegin} (inclusive) to {@code altEnd} (exclusive) are semantically equal. + */ + private static boolean alternativesAreEqualAt(Group group, int altBegin, int altEnd, int iTerm) { + if (group.getAlternatives().get(altBegin).size() <= iTerm) { + return false; + } + Term cmp = group.getAlternatives().get(altBegin).getTerms().get(iTerm); + for (int i = altBegin + 1; i < altEnd; i++) { + Sequence s = group.getAlternatives().get(i); + if (s.size() <= iTerm) { return false; } - CharacterClass cc = (CharacterClass) s.getTerms().get(i); - if (cmp == null) { - cmp = cc; - } else { - if (!cc.getCharSet().equals(cmp.getCharSet())) { - return false; - } + if (!s.getTerms().get(iTerm).equalsSemantic(cmp)) { + return false; } } return true; } + /** + * Returns an index {@code end} where the following condition holds: The first term of all + * alternatives in {@code group} from alternative index {@code begin} (inclusive) to {@code end} + * (exclusive) is semantically equivalent. If no such index exists, returns {@code -1}. + */ + private static int findMatchingAlternatives(Group group, int begin) { + if (group.getAlternatives().get(begin).isEmpty()) { + return -1; + } + Term cmp = group.getAlternatives().get(begin).getFirstTerm(); + int ret = -1; + for (int i = begin + 1; i < group.size(); i++) { + Sequence s = group.getAlternatives().get(i); + if (!s.isEmpty() && cmp.equalsSemantic(s.getFirstTerm())) { + ret = i + 1; + } else { + return ret; + } + } + return ret; + } + + /** + * Returns an index {@code end} where the following condition holds: The first term of all + * alternatives in {@code group} from alternative index {@code begin} (inclusive) to {@code end} + * (exclusive) is a character class generated from a single character. + */ + private static int findSingleCharAlternatives(Group group, int begin) { + int ret = -1; + for (int i = begin; i < group.size(); i++) { + Sequence s = group.getAlternatives().get(i); + if (s.isEmpty() || !(s.getFirstTerm() instanceof CharacterClass) || !((CharacterClass) s.getFirstTerm()).wasSingleChar()) { + return ret; + } + ret = i + 1; + } + return ret; + } + private RegexSyntaxException syntaxError(String msg) { return new RegexSyntaxException(source, msg); } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/Token.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/Token.java index 6d3f5eebc528..9bc0ad11155e 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/Token.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/Token.java @@ -111,7 +111,11 @@ public static Token createQuantifier(int min, int max, boolean greedy) { } public static Token createCharClass(CodePointSet codePointSet) { - return new CharacterClass(codePointSet); + return new CharacterClass(codePointSet, false); + } + + public static Token createCharClass(CodePointSet codePointSet, boolean wasSingleChar) { + return new CharacterClass(codePointSet, wasSingleChar); } public static Token createLookAheadAssertionBegin(boolean negated) { @@ -223,10 +227,12 @@ public JsonObject toJson() { public static final class CharacterClass extends Token { private final CodePointSet codePointSet; + private final boolean wasSingleChar; - public CharacterClass(CodePointSet codePointSet) { + public CharacterClass(CodePointSet codePointSet, boolean wasSingleChar) { super(Kind.charClass); this.codePointSet = codePointSet; + this.wasSingleChar = wasSingleChar; } @TruffleBoundary @@ -238,6 +244,10 @@ public JsonObject toJson() { public CodePointSet getCodePointSet() { return codePointSet; } + + public boolean wasSingleChar() { + return wasSingleChar; + } } public static final class BackReference extends Token { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/BackReference.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/BackReference.java index 8d0363b4c8d2..76c546b9a5e8 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/BackReference.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/BackReference.java @@ -58,6 +58,11 @@ public int getGroupNr() { return groupNr; } + @Override + public boolean equalsSemantic(RegexASTNode obj, boolean ignoreQuantifier) { + return obj instanceof BackReference && ((BackReference) obj).groupNr == groupNr && (ignoreQuantifier || quantifierEquals((BackReference) obj)); + } + @TruffleBoundary @Override public String toString() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/CharacterClass.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/CharacterClass.java index bcebcd3e7b64..cdb0db206876 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/CharacterClass.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/CharacterClass.java @@ -96,6 +96,18 @@ public void setCharSet(CharSet charSet) { this.charSet = charSet; } + public boolean wasSingleChar() { + return isFlagSet(FLAG_CHARACTER_CLASS_WAS_SINGLE_CHAR); + } + + public void setWasSingleChar() { + setWasSingleChar(true); + } + + public void setWasSingleChar(boolean value) { + setFlag(FLAG_CHARACTER_CLASS_WAS_SINGLE_CHAR, value); + } + public void addLookBehindEntry(RegexAST ast, Group lookBehindEntry) { if (lookBehindEntries == null) { lookBehindEntries = new ASTNodeSet<>(ast); @@ -147,6 +159,11 @@ public void extractSingleChar(char[] literal, char[] mask, int i) { } } + @Override + public boolean equalsSemantic(RegexASTNode obj, boolean ignoreQuantifier) { + return obj instanceof CharacterClass && ((CharacterClass) obj).getCharSet().equals(charSet) && (ignoreQuantifier || quantifierEquals((CharacterClass) obj)); + } + @TruffleBoundary @Override public String toString() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Group.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Group.java index 9127ac955580..6f951950b0e5 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Group.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Group.java @@ -56,7 +56,7 @@ */ public final class Group extends Term implements RegexASTVisitorIterable { - private final ArrayList alternatives = new ArrayList<>(); + private ArrayList alternatives = new ArrayList<>(); private short visitorIterationIndex = 0; private byte groupNumber = -1; private byte enclosedCaptureGroupsLow; @@ -253,6 +253,13 @@ public ArrayList getAlternatives() { return alternatives; } + public void setAlternatives(ArrayList alternatives) { + for (Sequence s : alternatives) { + s.setParent(this); + } + this.alternatives = alternatives; + } + @Override public SourceSection getSourceSection() { if (super.getSourceSection() == null && sourceSectionBegin != null && sourceSectionEnd != null) { @@ -304,7 +311,6 @@ public boolean isEmpty() { */ public void add(Sequence sequence) { sequence.setParent(this); - sequence.setGroupIndex(alternatives.size()); alternatives.add(sequence); } @@ -318,9 +324,6 @@ public void add(Sequence sequence) { public void insertFirst(Sequence sequence) { sequence.setParent(this); alternatives.add(0, sequence); - for (int i = 0; i < alternatives.size(); i++) { - alternatives.get(i).setGroupIndex(i); - } } /** @@ -335,6 +338,10 @@ public Sequence addSequence(RegexAST ast) { return sequence; } + public Sequence getLastAlternative() { + return alternatives.get(size() - 1); + } + public void removeLastSequence() { alternatives.remove(alternatives.size() - 1); } @@ -367,6 +374,26 @@ public String loopToString() { return isLoop() ? "*" : quantifierToString(); } + @Override + public boolean equalsSemantic(RegexASTNode obj, boolean ignoreQuantifier) { + if (obj == this) { + return true; + } + if (!(obj instanceof Group)) { + return false; + } + Group o = (Group) obj; + if (size() != o.size() || groupNumber != o.groupNumber || isLoop() != o.isLoop() || (!ignoreQuantifier && !quantifierEquals(o))) { + return false; + } + for (int i = 0; i < size(); i++) { + if (!alternatives.get(i).equalsSemantic(o.alternatives.get(i))) { + return false; + } + } + return true; + } + @TruffleBoundary @Override public String toString() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookAheadAssertion.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookAheadAssertion.java index 03d76b143acb..56a121cbd167 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookAheadAssertion.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookAheadAssertion.java @@ -40,10 +40,10 @@ public class LookAheadAssertion extends LookAroundAssertion { /** * Creates a new lookahead assertion AST node. - * + * * Note that for this node to be complete, {@link RegexASTSubtreeRootNode#setGroup(Group)} has * to be called with the {@link Group} that represents the contents of this lookahead assertion. - * + * * @param negated whether this lookahead assertion is negative or not */ LookAheadAssertion(boolean negated) { @@ -64,6 +64,12 @@ public String getPrefix() { return isNegated() ? "?!" : "?="; } + @Override + public boolean equalsSemantic(RegexASTNode obj, boolean ignoreQuantifier) { + assert !hasQuantifier(); + return this == obj || (obj instanceof LookAheadAssertion && groupEqualsSemantic((LookAheadAssertion) obj)); + } + @TruffleBoundary @Override public JsonValue toJson() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookAroundAssertion.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookAroundAssertion.java index 3bbe98a6ebdb..2ea8e3e5c1d1 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookAroundAssertion.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookAroundAssertion.java @@ -51,4 +51,9 @@ public abstract class LookAroundAssertion extends RegexASTSubtreeRootNode { public boolean isNegated() { return isFlagSet(FLAG_LOOK_AROUND_NEGATED); } + + boolean groupEqualsSemantic(LookAroundAssertion o) { + assert !hasQuantifier(); + return isNegated() == o.isNegated() && getGroup().equalsSemantic(o.getGroup()); + } } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookBehindAssertion.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookBehindAssertion.java index 633e71727743..cca64fb2bb2e 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookBehindAssertion.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/LookBehindAssertion.java @@ -101,6 +101,12 @@ public String getPrefix() { return isNegated() ? "?= 0; } diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexASTRootNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexASTRootNode.java index a389b7f5e352..982cf532a58e 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexASTRootNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexASTRootNode.java @@ -52,6 +52,13 @@ public String getPrefix() { return "ROOT"; } + @Override + public boolean equalsSemantic(RegexASTNode obj, boolean ignoreQuantifier) { + assert !hasQuantifier(); + return this == obj || (obj instanceof RegexASTRootNode && ((RegexASTRootNode) obj).getGroup().equalsSemantic(getGroup())); + } + + @TruffleBoundary @Override public String toString() { return getGroup().toString(); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexASTSubtreeRootNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexASTSubtreeRootNode.java index e7940e8f6d01..e3e2789c8d06 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexASTSubtreeRootNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/RegexASTSubtreeRootNode.java @@ -116,6 +116,7 @@ public String toString() { return "(" + getPrefix() + group.alternativesToString() + ")"; } + @TruffleBoundary @Override protected JsonObject toJson(String typeName) { return super.toJson(typeName).append(Json.prop("group", astNodeId(group))); diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Sequence.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Sequence.java index 737acf8afb10..da5526b4a185 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Sequence.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Sequence.java @@ -46,7 +46,6 @@ public final class Sequence extends RegexASTNode implements RegexASTVisitorIterable { private final ArrayList terms = new ArrayList<>(); - private short groupIndex; private short visitorIterationIndex = 0; Sequence() { @@ -77,15 +76,6 @@ public void setParent(RegexASTNode parent) { super.setParent(parent); } - public short getGroupIndex() { - assert getParent().getAlternatives().get(groupIndex) == this; - return groupIndex; - } - - public void setGroupIndex(int groupIndex) { - this.groupIndex = (short) groupIndex; - } - /** * Returns the list of terms that constitute this {@link Sequence}. *

    @@ -238,6 +228,26 @@ public SourceSection getSourceSection() { return super.getSourceSection(); } + @Override + public boolean equalsSemantic(RegexASTNode obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof Sequence)) { + return false; + } + Sequence o = (Sequence) obj; + if (size() != o.size()) { + return false; + } + for (int i = 0; i < size(); i++) { + if (!terms.get(i).equalsSemantic(o.terms.get(i))) { + return false; + } + } + return true; + } + @TruffleBoundary @Override public String toString() { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Term.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Term.java index fe7d5ba218d1..cbdbb7dddd68 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Term.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Term.java @@ -24,6 +24,8 @@ */ package com.oracle.truffle.regex.tregex.parser.ast; +import java.util.Objects; + import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.regex.tregex.parser.Token; @@ -71,6 +73,17 @@ public void setQuantifier(Token.Quantifier quantifier) { this.quantifier = quantifier; } + boolean quantifierEquals(Term o) { + return Objects.equals(quantifier, o.quantifier); + } + + @Override + public boolean equalsSemantic(RegexASTNode obj) { + return equalsSemantic(obj, false); + } + + public abstract boolean equalsSemantic(RegexASTNode obj, boolean ignoreQuantifier); + @TruffleBoundary protected String quantifierToString() { return hasQuantifier() ? quantifier.toString() : ""; From 11c3cc999345414fd81fc78057f30b9f72a191c9 Mon Sep 17 00:00:00 2001 From: Josef Haider Date: Wed, 25 Sep 2019 09:41:02 +0200 Subject: [PATCH 008/140] TRegex: fix deduplication in CharSet --- .../oracle/truffle/regex/charset/CharSet.java | 53 ++++++++++++------- .../regex/charset/SortedListOfRanges.java | 3 -- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java index 3d37ee82cbcc..cf2ba5fe8d2e 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/charset/CharSet.java @@ -52,8 +52,8 @@ public final class CharSet implements ImmutableSortedListOfRanges, Comparable, JsonConvertible { private static final CharSet BYTE_RANGE = new CharSet(new char[]{0x00, 0xff}); - private static final CharSet CONSTANT_EMPTY = new CharSet(new char[0]); - private static final CharSet CONSTANT_FULL = new CharSet(new char[]{Character.MIN_VALUE, Character.MAX_VALUE}); + private static final CharSet CONSTANT_EMPTY = new CharSet(new char[0], true); + private static final CharSet CONSTANT_FULL = new CharSet(new char[]{Character.MIN_VALUE, Character.MAX_VALUE}, true); private static final CharSet[] CONSTANT_ASCII = new CharSet[128]; private static final CharSet[] CONSTANT_INVERSE_ASCII = new CharSet[128]; @@ -75,16 +75,22 @@ public final class CharSet implements ImmutableSortedListOfRanges, Comparable Date: Thu, 26 Sep 2019 08:55:52 +0000 Subject: [PATCH 009/140] Enable Math.fma intrinsics for AArch64 Math.fma returns the exact product of the first two arguments summed with the third argument and then rounded once. This behaviour has no difference with that of the AArch64 FMADD instruction. So this patch enables Math.fma intrinsics if VM option "UseFMA" is set and the JDK version is greater than 8. Change-Id: Iab08fc35b94f4f2dd19277a040c5e92fc01be5a5 --- .../asm/aarch64/AArch64MacroAssembler.java | 14 ++++++ .../AArch64ArithmeticLIRGenerator.java | 14 ++++-- .../aarch64/AArch64HotSpotBackendFactory.java | 2 +- .../hotspot/test/CheckGraalIntrinsics.java | 3 +- .../lir/aarch64/AArch64ArithmeticOp.java | 5 ++- .../aarch64/AArch64GraphBuilderPlugins.java | 44 +++++++++++++++---- 6 files changed, 67 insertions(+), 15 deletions(-) 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 62fa9930ba93..fb547897a129 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 @@ -1308,6 +1308,20 @@ public void frem(int size, Register dst, Register n, Register d) { super.fmsub(size, dst, dst, d, n); } + /** + * dst = src1 * src2 + src3. + * + * @param size register size. + * @param dst floating point register. May not be null. + * @param src1 floating point register. May not be null. + * @param src2 floating point register. May not be null. + * @param src3 floating point register. May not be null. + */ + @Override + public void fmadd(int size, Register dst, Register src1, Register src2, Register src3) { + super.fmadd(size, dst, src1, src2, src3); + } + /* Branches */ /** 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 fb11ce63bcfb..34837148da55 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 @@ -229,9 +229,12 @@ public Value emitMSub(Value a, Value b, Value c) { } private Value emitMultiplyAddSub(AArch64ArithmeticOp op, Value a, Value b, Value c) { - assert isNumericInteger(a.getPlatformKind()); - assert isNumericInteger(b.getPlatformKind()); - assert isNumericInteger(c.getPlatformKind()); + assert a.getPlatformKind() == b.getPlatformKind() && b.getPlatformKind() == c.getPlatformKind(); + if (op == AArch64ArithmeticOp.ADD || op == AArch64ArithmeticOp.SUB) { + assert isNumericInteger(a.getPlatformKind()); + } else if (op == AArch64ArithmeticOp.FADD) { + assert a.getPlatformKind() == AArch64Kind.SINGLE || a.getPlatformKind() == AArch64Kind.DOUBLE; + } Variable result = getLIRGen().newVariable(LIRKind.combine(a, b, c)); AllocatableValue x = moveSp(asAllocatable(a)); @@ -446,6 +449,11 @@ public Value emitBitScanReverse(Value value) { return result; } + @Override + public Value emitFusedMultiplyAdd(Value a, Value b, Value c) { + return emitMultiplyAddSub(AArch64ArithmeticOp.FADD, a, b, c); + } + @Override public Value emitCountLeadingZeros(Value value) { Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java index b5378a4a1741..c40b4390dd47 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java @@ -192,7 +192,7 @@ protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRun replacements, options); AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false, - /* registerMathPlugins */true); + /* registerMathPlugins */true, /* emitJDK9StringSubstitutions */true, config.useFMAIntrinsics); return plugins; } diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java index eaabadbc4d42..a84ffd134028 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java @@ -64,6 +64,7 @@ import jdk.vm.ci.meta.MetaUtil; import jdk.vm.ci.meta.MethodHandleAccessProvider.IntrinsicMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.sparc.SPARC; /** * Checks the intrinsics implemented by Graal against the set of intrinsics declared by HotSpot. The @@ -375,7 +376,7 @@ public CheckGraalIntrinsics() { add(ignore, "java/lang/Math.fma(DDD)D", "java/lang/Math.fma(FFF)F"); - } else if (!(arch instanceof AMD64)) { + } else if (arch instanceof SPARC) { add(toBeInvestigated, "java/lang/Math.fma(DDD)D", "java/lang/Math.fma(FFF)F"); 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 8d37b4ae1c9a..26fff457b6c3 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 @@ -481,7 +481,7 @@ public static class MultiplyAddSubOp extends AArch64LIRInstruction { */ public MultiplyAddSubOp(AArch64ArithmeticOp op, AllocatableValue result, AllocatableValue src1, AllocatableValue src2, AllocatableValue src3) { super(TYPE); - assert op == ADD || op == SUB; + assert op == ADD || op == SUB || op == FADD; this.op = op; this.result = result; this.src1 = src1; @@ -499,6 +499,9 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { case SUB: masm.msub(size, asRegister(result), asRegister(src1), asRegister(src2), asRegister(src3)); break; + case FADD: + masm.fmadd(size, asRegister(result), asRegister(src1), asRegister(src2), asRegister(src3)); + break; default: throw GraalError.shouldNotReachHere(); } diff --git a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java index cab247c0c7a5..40d9194865cc 100644 --- a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java @@ -47,6 +47,7 @@ import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.replacements.TargetGraphBuilderPlugins; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; +import org.graalvm.compiler.replacements.nodes.FusedMultiplyAddNode; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; @@ -61,16 +62,11 @@ public class AArch64GraphBuilderPlugins implements TargetGraphBuilderPlugins { @Override public void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, Architecture arch, boolean explicitUnsafeNullChecks, boolean registerMathPlugins, boolean emitJDK9StringSubstitutions, boolean useFMAIntrinsics) { - register(plugins, replacementsBytecodeProvider, explicitUnsafeNullChecks, registerMathPlugins, emitJDK9StringSubstitutions); + register(plugins, replacementsBytecodeProvider, explicitUnsafeNullChecks, registerMathPlugins, emitJDK9StringSubstitutions, useFMAIntrinsics); } public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks, - boolean registerMathPlugins) { - register(plugins, bytecodeProvider, explicitUnsafeNullChecks, registerMathPlugins, true); - } - - public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks, - boolean registerMathPlugins, boolean emitJDK9StringSubstitutions) { + boolean registerMathPlugins, boolean emitJDK9StringSubstitutions, boolean useFMAIntrinsics) { InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); invocationPlugins.defer(new Runnable() { @Override @@ -78,7 +74,7 @@ public void run() { registerIntegerLongPlugins(invocationPlugins, JavaKind.Int, bytecodeProvider); registerIntegerLongPlugins(invocationPlugins, JavaKind.Long, bytecodeProvider); if (registerMathPlugins) { - registerMathPlugins(invocationPlugins); + registerMathPlugins(invocationPlugins, useFMAIntrinsics); } if (emitJDK9StringSubstitutions) { registerStringLatin1Plugins(invocationPlugins, bytecodeProvider); @@ -130,7 +126,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec }); } - private static void registerMathPlugins(InvocationPlugins plugins) { + private static void registerMathPlugins(InvocationPlugins plugins, boolean useFMAIntrinsics) { Registration r = new Registration(plugins, Math.class); registerUnaryMath(r, "sin", SIN); registerUnaryMath(r, "cos", COS); @@ -148,6 +144,36 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec registerRound(r, "rint", RoundingMode.NEAREST); registerRound(r, "ceil", RoundingMode.UP); registerRound(r, "floor", RoundingMode.DOWN); + if (useFMAIntrinsics && JavaVersionUtil.JAVA_SPEC > 8) { + registerFMA(r); + } + } + + private static void registerFMA(Registration r) { + r.register3("fma", Double.TYPE, Double.TYPE, Double.TYPE, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, + ResolvedJavaMethod targetMethod, + Receiver receiver, + ValueNode na, + ValueNode nb, + ValueNode nc) { + b.push(JavaKind.Double, b.append(new FusedMultiplyAddNode(na, nb, nc))); + return true; + } + }); + r.register3("fma", Float.TYPE, Float.TYPE, Float.TYPE, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, + ResolvedJavaMethod targetMethod, + Receiver receiver, + ValueNode na, + ValueNode nb, + ValueNode nc) { + b.push(JavaKind.Float, b.append(new FusedMultiplyAddNode(na, nb, nc))); + return true; + } + }); } private static void registerUnaryMath(Registration r, String name, UnaryOperation operation) { From f4ffe05ec4545f1140082ca7cf055f5cbb71e97d Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 30 Sep 2019 18:30:26 +0200 Subject: [PATCH 010/140] Implement context specific resource limits for time and statement context. --- .../truffle/test/PartialEvaluationTest.java | 10 + .../test/ResourceLimitsCompilationTest.java | 268 +++++++ sdk/CHANGELOG.md | 2 + .../src/org/graalvm/polyglot/Context.java | 35 +- .../src/org/graalvm/polyglot/Engine.java | 47 +- .../graalvm/polyglot/PolyglotException.java | 6 +- .../graalvm/polyglot/ResourceLimitEvent.java | 79 ++ .../org/graalvm/polyglot/ResourceLimits.java | 256 +++++++ .../polyglot/impl/AbstractPolyglotImpl.java | 59 +- .../polyglot/management/ExecutionEvent.java | 18 +- .../management/ExecutionListener.java | 29 +- .../polyglot/management/Management.java | 80 +++ .../test/InstrumentationTestLanguage.java | 8 +- .../test/ResourceLimitsTest.java | 679 ++++++++++++++++++ .../test/polyglot/AbstractPolyglotTest.java | 19 +- .../api/test/polyglot/ContextAPITest.java | 41 +- .../polyglot/ContextParallelCloseTest.java | 2 +- .../api/test/polyglot/EngineAPITest.java | 2 +- .../truffle/polyglot/ContextThreadLocal.java | 63 +- .../truffle/polyglot/EngineAccessor.java | 22 +- .../truffle/polyglot/HostToGuestRootNode.java | 10 +- .../truffle/polyglot/PolyglotBindings.java | 23 +- .../polyglot/PolyglotBindingsValue.java | 2 +- .../polyglot/PolyglotContextConfig.java | 5 +- .../truffle/polyglot/PolyglotContextImpl.java | 319 ++++---- .../truffle/polyglot/PolyglotEngineImpl.java | 120 +++- .../oracle/truffle/polyglot/PolyglotImpl.java | 23 +- .../polyglot/PolyglotLanguageContext.java | 29 +- .../truffle/polyglot/PolyglotLimits.java | 447 ++++++++++++ .../truffle/polyglot/PolyglotLogHandler.java | 4 +- ...nListener.java => PolyglotManagement.java} | 44 +- .../truffle/polyglot/PolyglotReferences.java | 4 +- .../truffle/polyglot/PolyglotThreadInfo.java | 54 +- .../truffle/polyglot/PolyglotValue.java | 4 +- .../sl/builtins/SLStackTraceBuiltin.java | 2 +- .../truffle/sl/nodes/SLEvalRootNode.java | 7 +- 36 files changed, 2470 insertions(+), 352 deletions(-) create mode 100644 compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ResourceLimitsCompilationTest.java create mode 100644 sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimitEvent.java create mode 100644 sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java create mode 100644 sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/Management.java create mode 100644 truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java create mode 100644 truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java rename truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/{PolyglotExecutionListener.java => PolyglotManagement.java} (94%) 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 8cab8d230685..18b1a8a73760 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 @@ -133,6 +133,16 @@ protected void assertPartialEvalNoInvokes(CallTarget callTarget, Object[] argume } } + protected StructuredGraph partialEval(OptimizedCallTarget compilable, Object[] arguments) { + return partialEval(compilable, arguments, AllowAssumptions.YES, INVALID_COMPILATION_ID); + } + + protected void compile(OptimizedCallTarget compilable, StructuredGraph graph) { + String methodName = "test"; + CompilationIdentifier compilationId = getCompilationId(compilable); + truffleCompiler.compilePEGraph(graph, methodName, suite, compilable, asCompilationRequest(compilationId), null, new CancellableCompileTask(true)); + } + @SuppressWarnings("try") protected StructuredGraph partialEval(OptimizedCallTarget compilable, Object[] arguments, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { // Executed AST so that all classes are loaded and initialized. diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ResourceLimitsCompilationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ResourceLimitsCompilationTest.java new file mode 100644 index 000000000000..6470a5049018 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/ResourceLimitsCompilationTest.java @@ -0,0 +1,268 @@ +/* + * Copyright (c) 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.truffle.test; + +import static org.junit.Assume.assumeFalse; + +import java.util.concurrent.Semaphore; +import java.util.function.Predicate; + +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodes.InvokeWithExceptionNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.calc.AddNode; +import org.graalvm.compiler.nodes.java.AtomicReadAndAddNode; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.nodes.memory.ReadNode; +import org.graalvm.compiler.nodes.memory.WriteNode; +import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.ResourceLimits; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.oracle.truffle.api.instrumentation.test.InstrumentationTestLanguage; +import com.oracle.truffle.api.test.polyglot.EngineAPITest; + +import jdk.vm.ci.sparc.SPARC; + +public class ResourceLimitsCompilationTest extends PartialEvaluationTest { + + @Before + public void setup() { + EngineAPITest.resetSingleContextState(true); + } + + @Test + @SuppressWarnings("try") + public void testStatementLimitSingleContext() { + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(5000, null).// + build(); + + try (Context context = Context.newBuilder().resourceLimits(limits).build();) { + OptimizedCallTarget target = evalTestScript(context); + StructuredGraph graph = partialEval(target, new Object[0]); + Assert.assertEquals(0, countNodes(graph, MethodCallTargetNode.TYPE)); + Assert.assertEquals(6, countNodes(graph, AddNode.TYPE)); + compile(target, graph); + /* + * Verify that the statements fold to a single read/write. + */ + Assert.assertEquals(1, countNodes(graph, ReadNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementCounter"))); + Assert.assertEquals(1, countNodes(graph, WriteNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementCounter"))); + } + } + + @Test + @SuppressWarnings("try") + public void testStatementLimitMultiContext() { + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(5000, null).// + build(); + try (Engine engine = Engine.create();) { + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + assertLimitCheckFastPath(context); + } + } + } + + @Test + @SuppressWarnings("try") + public void testStatementLimitMultiContextTwoEqualConfigs() { + ResourceLimits limits0 = ResourceLimits.newBuilder().// + statementLimit(5000, null).// + build(); + ResourceLimits limits1 = ResourceLimits.newBuilder().// + statementLimit(5000, null).// + build(); + try (Engine engine = Engine.create();) { + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits0).build()) { + assertLimitCheckFastPath(context); + } + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits1).build()) { + assertLimitCheckFastPath(context); + } + } + } + + @Test + @SuppressWarnings("try") + public void testStatementLimitMultiContextTwoDifferentConfigs() { + ResourceLimits limits0 = ResourceLimits.newBuilder().// + statementLimit(5000, null).// + build(); + ResourceLimits limits1 = ResourceLimits.newBuilder().// + statementLimit(5000 - 1, null).// + build(); + try (Engine engine = Engine.create();) { + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits0).build()) { + assertLimitCheckFastPath(context); + } + // the code deoptimizes and also reads the limit + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits1).build()) { + OptimizedCallTarget target = evalTestScript(context); + StructuredGraph graph = partialEval(target, new Object[0]); + Assert.assertEquals(0, countNodes(graph, MethodCallTargetNode.TYPE)); + Assert.assertEquals(6, countNodes(graph, AddNode.TYPE)); + compile(target, graph); + /* + * Verify that the statements fold to a single read for the context and a single + * read/write for the statement counts. + */ + Assert.assertEquals(1, countNodes(graph, ReadNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("ContextThreadLocal.activeSingleContextNonVolatile"))); + Assert.assertEquals(1, countNodes(graph, ReadNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementCounter"))); + Assert.assertEquals(0, countNodes(graph, ReadNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementLimit"))); + Assert.assertEquals(1, countNodes(graph, WriteNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementCounter"))); + } + } + } + + private void assertLimitCheckFastPath(Context context) { + OptimizedCallTarget target = evalTestScript(context); + StructuredGraph graph = partialEval(target, new Object[0]); + Assert.assertEquals(0, countNodes(graph, MethodCallTargetNode.TYPE)); + Assert.assertEquals(6, countNodes(graph, AddNode.TYPE)); + compile(target, graph); + /* + * Verify that the statements fold to a single read for the context and a single read/write + * for the statement counts. + */ + Assert.assertEquals(1, countNodes(graph, ReadNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("ContextThreadLocal.activeSingleContextNonVolatile"))); + Assert.assertEquals(1, countNodes(graph, ReadNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementCounter"))); + Assert.assertEquals(1, countNodes(graph, WriteNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementCounter"))); + Assert.assertEquals(0, countNodes(graph, ReadNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementLimit"))); + } + + @Test + @SuppressWarnings("try") + public void testStatementLimitEngineMultiThread() throws InterruptedException { + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(5000, null).// + build(); + try (Engine engine = Engine.create();) { + + try (Context context0 = Context.newBuilder().engine(engine).resourceLimits(limits).build(); + Context context1 = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + forceEngineMultiThreading(context0, context1); + + OptimizedCallTarget target = evalTestScript(context0); + StructuredGraph graph = partialEval(target, new Object[0]); + Assert.assertEquals(1, countNodes(graph, MethodCallTargetNode.TYPE)); + Assert.assertEquals(6, countNodes(graph, AddNode.TYPE)); + compile(target, graph); + /* + * Verify that the statements fold to a single read for the context and a single + * read/write for the statement counts. + */ + Assert.assertEquals(1, countNodes(graph, ReadNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementCounter"))); + Assert.assertEquals(1, countNodes(graph, WriteNode.TYPE, (n) -> n.getLocationIdentity().toString().equals("PolyglotContextImpl.statementCounter"))); + Assert.assertEquals(1, countNodes(graph, InvokeWithExceptionNode.TYPE)); + } + } + } + + @Test + @SuppressWarnings("try") + public void testStatementLimitContextMultiThread() throws InterruptedException { + assumeFalse("skipping SPARC unsupported test", getBackend().getTarget().arch instanceof SPARC); + + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(5000, null).// + build(); + + try (Engine engine = Engine.create();) { + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + forceContextMultiThreading(context); + + OptimizedCallTarget target = evalTestScript(context); + StructuredGraph graph = partialEval(target, new Object[0]); + Assert.assertEquals(1, countNodes(graph, MethodCallTargetNode.TYPE)); + Assert.assertEquals(6, countNodes(graph, AtomicReadAndAddNode.TYPE)); + compile(target, graph); + Assert.assertEquals(6, countNodes(graph, AtomicReadAndAddNode.TYPE)); + Assert.assertEquals(1, countNodes(graph, InvokeWithExceptionNode.TYPE)); + } + } + } + + /** + * Make sure using two contexts of the same engine that the engine is accessed from two threads + * at the same time. The context does not need to support multi-threading for this. + */ + private static void forceEngineMultiThreading(Context context0, Context context1) throws InterruptedException { + Assert.assertSame(context0.getEngine(), context1.getEngine()); + Semaphore entered = new Semaphore(0); + Semaphore leaving = new Semaphore(0); + Thread t = new Thread(() -> { + context1.enter(); + entered.release(); + leaving.acquireUninterruptibly(); + context1.leave(); + }); + t.start(); + entered.acquire(); + context0.enter(); + leaving.release(); + context0.leave(); + t.join(); + } + + private static void forceContextMultiThreading(Context context) throws InterruptedException { + context.enter(); + Thread t = new Thread(() -> { + context.enter(); + context.leave(); + }); + t.start(); + t.join(); + context.leave(); + } + + private static OptimizedCallTarget evalTestScript(Context context) { + context.eval(InstrumentationTestLanguage.ID, "ROOT(STATEMENT, STATEMENT, STATEMENT, STATEMENT, STATEMENT, STATEMENT)"); + context.enter(); + return (OptimizedCallTarget) InstrumentationTestLanguage.getLastParsedCalltarget(); + } + + private static int countNodes(StructuredGraph graph, NodeClass nodeClass) { + return countNodes(graph, nodeClass, (n) -> true); + } + + @SuppressWarnings("unchecked") + private static int countNodes(StructuredGraph graph, NodeClass nodeClass, Predicate filter) { + int count = 0; + for (Node node : graph.getNodes()) { + if (nodeClass.getClazz().isInstance(node) && filter.test((T) node)) { + count++; + } + } + return count; + } + +} diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index 8d05d98e0724..c4e249e40d83 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -4,6 +4,8 @@ This changelog summarizes major changes between GraalVM SDK versions. The main f ## Version 19.3.0 * The default temporary directory can be configured by [FileSystem](http://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/io/FileSystem.html#getTempDirectory--). +* Added `org.graalvm.polyglot.ResourceLimits` that allows to specify context specific time and statement count execution limits. +* Context can now be closed if they are still explicitly entered using `Context.enter` on the current thread. This allows for simpler error recovery code. ## Version 19.2.0 * Added support for date, time, timezone and duration values in polyglot 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 69b1de70da0e..a2ca0156f81e 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 @@ -423,6 +423,15 @@ public boolean initialize(String languageId) { return impl.initializeLanguage(languageId); } + /** + * Resets all accumulators of resource limits for the associated context to zero. + * + * @since 19.3 + */ + public void resetLimits() { + impl.resetLimits(); + } + /** * Converts a host value to a polyglot {@link Value value} representation. This conversion is * applied implicitly whenever {@link Value#execute(Object...) execution} or @@ -766,6 +775,7 @@ public final class Builder { private Boolean allowCreateProcess; private ProcessHandler processHandler; private EnvironmentAccess environmentAccess; + private ResourceLimits resourceLimits; private Map environment; private ZoneId zone; @@ -1277,6 +1287,20 @@ public Builder processHandler(ProcessHandler handler) { return this; } + /** + * Assigns resource limit configuration to a context. By default no resource limits are + * assigned. The limits will be enabled for all contexts created using this builder. + * Assigning a limit may have performance impact of all contexts that run with the same + * engine. + * + * @see ResourceLimits for usage examples + * @since 19.3.0 + */ + public Builder resourceLimits(ResourceLimits limits) { + this.resourceLimits = limits; + return this; + } + /** * Allow environment access using the provided policy. If {@link #allowAllAccess(boolean) * all access} is {@code true} then the default environment access policy is @@ -1378,6 +1402,13 @@ public Context build() { if (environmentAccess == null) { environmentAccess = this.allowAllAccess ? EnvironmentAccess.INHERIT : EnvironmentAccess.NONE; } + Object limits; + if (resourceLimits != null) { + limits = resourceLimits.impl; + } else { + limits = null; + } + if (!io && customFileSystem != null) { throw new IllegalStateException("Cannot install custom FileSystem when IO is disabled."); } @@ -1407,7 +1438,7 @@ public Context build() { return engine.impl.createContext(null, null, null, hostClassLookupEnabled, hostAccess, polyglotAccess, nativeAccess, createThread, io, hostClassLoading, experimentalOptions, localHostLookupFilter, Collections.emptyMap(), arguments == null ? Collections.emptyMap() : arguments, - onlyLanguages, customFileSystem, customLogHandler, createProcess, processHandler, environmentAccess, environment, zone); + onlyLanguages, customFileSystem, customLogHandler, createProcess, processHandler, environmentAccess, environment, zone, limits); } else { if (messageTransport != null) { throw new IllegalStateException("Cannot use MessageTransport in a context that shares an Engine."); @@ -1415,7 +1446,7 @@ public Context build() { return engine.impl.createContext(out, err, in, hostClassLookupEnabled, hostAccess, polyglotAccess, nativeAccess, createThread, io, hostClassLoading, experimentalOptions, localHostLookupFilter, options == null ? Collections.emptyMap() : options, arguments == null ? Collections.emptyMap() : arguments, - onlyLanguages, customFileSystem, customLogHandler, createProcess, processHandler, environmentAccess, environment, zone); + onlyLanguages, customFileSystem, customLogHandler, createProcess, processHandler, environmentAccess, environment, zone, limits); } } 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 acde837f6f12..8869df0a9984 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 @@ -53,6 +53,7 @@ import java.nio.file.Path; import java.security.AccessController; import java.security.PrivilegedAction; +import java.time.Duration; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -522,6 +523,11 @@ public boolean useContextClassLoader() { return useContextClassLoader; } + @Override + public AbstractContextImpl getImpl(Context context) { + return context.impl; + } + @Override public Engine newEngine(AbstractEngineImpl impl) { return new Engine(impl); @@ -582,11 +588,21 @@ public AbstractInstrumentImpl getImpl(Instrument value) { return value.impl; } + @Override + public ResourceLimitEvent newResourceLimitsEvent(Object impl) { + return new ResourceLimitEvent(impl); + } + @Override public AbstractLanguageImpl getImpl(Language value) { return value.impl; } + @Override + public Object getImpl(ResourceLimits value) { + return value.impl; + } + @Override public AbstractStackFrameImpl getImpl(StackFrame value) { return value.impl; @@ -748,46 +764,56 @@ public Engine buildEngine(OutputStream out, OutputStream err, InputStream in, Ma } @Override - public AbstractExecutionListenerImpl getExecutionListenerImpl() { - return new AbstractExecutionListenerImpl(this) { + public Object buildLimits(long statementLimit, Predicate statementLimitSourceFilter, Duration timeLimit, Duration timeLimitAccuracy, Consumer onLimit) { + throw noPolyglotImplementationFound(); + } + + @Override + public Context getLimitEventContext(Object impl) { + throw noPolyglotImplementationFound(); + } + + @Override + public AbstractManagementImpl getManagementImpl() { + return new AbstractManagementImpl(this) { @Override - public boolean isStatement(Object impl) { + public boolean isExecutionEventStatement(Object impl) { return false; } @Override - public boolean isRoot(Object impl) { + public boolean isExecutionEventRoot(Object impl) { return false; } @Override - public boolean isExpression(Object impl) { + public boolean isExecutionEventExpression(Object impl) { return false; } @Override - public String getRootName(Object impl) { + public String getExecutionEventRootName(Object impl) { throw noPolyglotImplementationFound(); } @Override - public PolyglotException getException(Object impl) { + public PolyglotException getExecutionEventException(Object impl) { throw noPolyglotImplementationFound(); } @Override - public Value getReturnValue(Object impl) { + public Value getExecutionEventReturnValue(Object impl) { throw noPolyglotImplementationFound(); } @Override - public SourceSection getLocation(Object impl) { + public SourceSection getExecutionEventLocation(Object impl) { throw noPolyglotImplementationFound(); } @Override - public List getInputValues(Object impl) { + public List getExecutionEventInputValues(Object impl) { throw noPolyglotImplementationFound(); } @@ -802,6 +828,7 @@ public Object attachExecutionListener(Engine engine, Consumer on Predicate sourceFilter, Predicate rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectErrors) { throw noPolyglotImplementationFound(); } + }; } 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 ea4370731a72..31d8992b17ab 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 @@ -275,9 +275,9 @@ public boolean isInternalError() { /** * Returns true if the execution was cancelled. The execution can be cancelled by - * {@link Context#close(boolean) closing} a context or if an instrument such as a debugger - * decides to cancel the current execution. The context that caused a cancel event becomes - * unusable, i.e. closed. + * {@link Context#close(boolean) closing} a context, if an instrument such as a debugger decides + * to cancel the current execution or if a {@link ResourceLimits resource limit} was exceeded. + * The context that caused a cancel event becomes unusable, i.e. closed. * * @since 19.0 */ diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimitEvent.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimitEvent.java new file mode 100644 index 000000000000..993ad07c0b80 --- /dev/null +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimitEvent.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2019, 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.polyglot; + +/** + * Event triggered by a resource limit for a context. Event objects are short-lived and should not + * be stored. Their use should be limited to the duration of the event. + * + * @see ResourceLimits + * @since 19.3 + */ +public final class ResourceLimitEvent { + + private final Object impl; + + ResourceLimitEvent(Object impl) { + this.impl = impl; + } + + /** + * The context for which the limit was exceeded. Never null. + * + * @since 19.3 + */ + public Context getContext() { + return Engine.getImpl().getLimitEventContext(impl); + } + + /** + * {@inheritDoc} + * + * @since 19.3 + */ + @Override + public String toString() { + StringBuilder b = new StringBuilder("ResourceLimitEvent["); + b.append(getContext().toString()); + b.append("]"); + return b.toString(); + } +} diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java new file mode 100644 index 000000000000..a7ad6089c560 --- /dev/null +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2019, 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.polyglot; + +import java.lang.management.ThreadMXBean; +import java.time.Duration; +import java.util.function.Consumer; +import java.util.function.Predicate; + +/** + * Represents resource limits configuration that is used to configure contexts. Resource limit + * instances are created using the {@link #newBuilder() builder} and activated by + * {@link Context.Builder#resourceLimits(ResourceLimits) enabling} them for a {@link Context + * context}. All configured limits are applied per context instance. Resource limits may be + * {@link Context#resetLimits() reset}. If a resource limit is triggered the context that triggered + * the limit will automatically be {@link Context#close(boolean) closed} and can no longer be used + * to evaluate code. + *

    + * The following resource limits are supported: + *

      + *
    • {@link Builder#cpuTimeLimit(Duration, Duration) Time} limit per context. Allows to limit the + * amount of time spent per context. + *
    • {@link Builder#statementLimit(long, Predicate) Statement count} limit per context. Allows to + * limit the amount of statements executed per context. + *
    + *

    + *

    Statement Limit Example

    + *
    + * ResourceLimits limits = ResourceLimits.newBuilder()
    + *                       .statementLimit(500, null)
    + *                   .build();
    + * try (Context context = Context.newBuilder("js")
    + *                            .resourceLimits(limits)
    + *                        .build();) {
    + *     try {
    + *         context.eval("js", "while(true);");
    + *         assert false;
    + *     } catch (PolyglotException e) {
    + *         // triggered after 500 iterations of while(true);
    + *         // context is closed and can no longer be used
    + *         assert e.isCancelled();
    + *     }
    + * }
    + * 
    + *
    + * + *

    Time Limit Example

    + * + * + *
    + * ResourceLimits limits = ResourceLimits.newBuilder()
    + *                   .timeLimit(Duration.ofMillis(500),
    + *                              Duration.ofMillis(5))
    + *                   .build();
    + * try (Context context = Context.newBuilder("js")
    + *                            .resourceLimits(limits)
    + *                        .build();) {
    + *     try {
    + *         context.eval("js", "while(true);");
    + *         assert false;
    + *     } catch (PolyglotException e) {
    + *         // triggered after 500ms;
    + *         // context is closed and can no longer be used
    + *         assert e.isCancelled();
    + *     }
    + * }
    + * 
    + *
    + * + * @see #newBuilder() + * @since 19.3 + */ +public final class ResourceLimits { + + private static final ResourceLimits EMPTY = new ResourceLimits(null); + + final Object impl; + + ResourceLimits(Object impl) { + this.impl = impl; + } + + /** + * Creates a new builder to construct {@link ResourceLimits} instances. + * + * @since 19.3 + */ + public static Builder newBuilder() { + return EMPTY.new Builder(); + } + + /** + * A builder used to construct resource limits. Builder instances are not thread-safe and may + * not be used from multiple threads at the same time. + * + * @since 19.3 + */ + public final class Builder { + + long statementLimit; + Predicate statementLimitSourceFilter; + Duration timeLimit; + Duration timeLimitAccuracy; + Consumer onLimit; + + Builder() { + } + + /** + * Specifies the maximum number of statements a context may execute until the onLimit event + * is notified and the context will be {@link Context#close() closed}. After the statement + * limit was triggered for a context, it is no longer usable and every use of the context + * will throw a {@link PolyglotException} that returns true for + * {@link PolyglotException#isCancelled()}. The statement limit is independent of the number + * of threads executing and is applied per context. Invoking this method multiple times + * overwrites previous statement limit configurations. If the statement limit is exceeded + * then the {@link #onLimit(Consumer) onLimit} listener is notified. + *

    + * By default there is no statement limit applied. The limit may be set to 0 to disable the + * statement limit. In addition to the limit a source filter may be set to indicate for + * which sources the limit should be applied. If the source filter is null then + * it will be applied to all {@link Source#isInternal() internal} and public sources. The + * provided limit must not be negative otherwise an {@link IllegalArgumentException} is + * thrown. If a {@link Context.Builder#engine(Engine) shared engine} is used then the same + * source filter instance must be used for all contexts of an engine. Otherwise an + * {@link IllegalArgumentException} is thrown when the context is + * {@link Context.Builder#build() built}. The limit itself may vary between contexts. + *

    + * The statement limit is applied to the context and all inner contexts it spawns. + * Therefore, new inner contexts cannot be used to exceed the statement limit. + *

    + * Note that attaching a statement limit to a context reduces the throughput of all guest + * applications with that use the same engine. The statement counter needs to be updated for + * every statement that is executed. It is recommended to benchmark the use of the statement + * limit before it is used in production. + * + * @see ResourceLimits Example Usage + * @since 19.3 + */ + @SuppressWarnings("hiding") + public Builder statementLimit(long limit, Predicate sourceFilter) { + if (limit < 0) { + throw new IllegalArgumentException("The statement limit must not be negative."); + } + this.statementLimit = limit; + this.statementLimitSourceFilter = sourceFilter; + return this; + } + + /** + * Specifies the maximum {@link ThreadMXBean#getThreadCpuTime(long) CPU time} a context may + * be active until the onLimit event is notified and the context will be + * {@link Context#close() closed}. The lime limit {@link Duration duration} may be specified + * alongside an {@link Duration accuracy} with which the time limit is enforced. Both time + * limit and accuracy must be positive. Both parameters may be set to null to + * disable the time limit for a builder. By default no time limit is configured. Invoking + * this method multiple times overwrites previous time limit configurations. If the time + * limit is exceeded then the {@link #onLimit(Consumer) onLimit} listener is notified. The + * minimal accuracy is one millisecond, values below that will be rounded up. + *

    + * The activation CPU time of a context typically does not include time spent waiting for + * synchronization or IO. If the guest application is executed on multiple threads at the + * same time, or if the guest application creates new threads then the CPU time of those + * threads will be accumulated individually in the activation time. E.g. if two threads + * execute the same context then the time limit will be exceeded twice as fast. + *

    + * The time limit is enforced by a separate high-priority thread that will be woken + * regularly. There is no guarantee that the context will be cancelled within the accuracy + * specified. The accuracy may be significantly missed, e.g. if the host VM causes a full + * garbage collection. If the time limit is never exceeded then the throughput of the guest + * context is not affected. If the time limit is exceeded for one context then it may slow + * down the throughput for other contexts of an engine temporarily. + *

    + * The time limit is applied to the context and all inner contexts it spawns. Therefore, new + * inner contexts cannot be used to exceed the time limit. + * + * @see ThreadMXBean#getThreadCpuTime(long) + * @see ResourceLimits Example Usage + * @since 19.3 + */ + @SuppressWarnings("hiding") + public Builder cpuTimeLimit(Duration timeLimit, Duration accuracy) { + if (timeLimit == null && accuracy == null) { + // fall through to allow reset + } else if (timeLimit == null || accuracy == null) { + throw new IllegalArgumentException("If a timeLimit is specified accuracy must be specified as well."); + } else if (timeLimit.isNegative() || timeLimit.isZero()) { + throw new IllegalArgumentException("Time limit must not be negative or zero."); + } else if (accuracy.isNegative() || accuracy.isZero()) { + throw new IllegalArgumentException("Accuracy must not be negative or zero."); + } + this.timeLimit = timeLimit; + this.timeLimitAccuracy = accuracy; + return this; + } + + /** + * Notified when a resource limit is reached. Default is null. May be set to + * null to disable events. + * + * @since 19.3 + */ + public Builder onLimit(@SuppressWarnings("hiding") Consumer onLimit) { + this.onLimit = onLimit; + return this; + } + + /** + * Builds the limit configuration object. + * + * @see ResourceLimits Example Usage + * @since 19.3 + */ + public ResourceLimits build() { + return new ResourceLimits(Engine.getImpl().buildLimits(statementLimit, statementLimitSourceFilter, timeLimit, timeLimitAccuracy, onLimit)); + } + } +} 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 976b705a8797..8d69ae304aa1 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 @@ -78,6 +78,8 @@ import org.graalvm.polyglot.Language; import org.graalvm.polyglot.PolyglotAccess; import org.graalvm.polyglot.PolyglotException; +import org.graalvm.polyglot.ResourceLimitEvent; +import org.graalvm.polyglot.ResourceLimits; import org.graalvm.polyglot.PolyglotException.StackFrame; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.SourceSection; @@ -98,14 +100,15 @@ protected AbstractPolyglotImpl() { } } - public abstract static class MonitoringAccess { - protected MonitoringAccess() { - if (!getClass().getCanonicalName().equals("org.graalvm.polyglot.management.ExecutionListener.MonitoringAccessImpl")) { - throw new AssertionError("Only one implementation of MonitoringAccessImpl allowed. " + getClass().getCanonicalName()); + public abstract static class ManagementAccess { + protected ManagementAccess() { + if (!getClass().getCanonicalName().equals("org.graalvm.polyglot.management.Management.ManagementAccessImpl")) { + throw new AssertionError("Only one implementation of ManagementAccessImpl allowed. " + getClass().getCanonicalName()); } } public abstract ExecutionEvent newExecutionEvent(Object event); + } public abstract static class IOAccess { @@ -151,7 +154,9 @@ protected APIAccess() { public abstract Object getReceiver(Value value); - public abstract AbstractValueImpl getImpl(Value engine); + public abstract AbstractValueImpl getImpl(Value value); + + public abstract AbstractContextImpl getImpl(Context context); public abstract AbstractEngineImpl getImpl(Engine engine); @@ -163,6 +168,8 @@ protected APIAccess() { public abstract AbstractInstrumentImpl getImpl(Instrument value); + public abstract ResourceLimitEvent newResourceLimitsEvent(Object impl); + public abstract StackFrame newPolyglotStackTraceElement(PolyglotException e, AbstractStackFrameImpl impl); public abstract List getTargetMappings(HostAccess access); @@ -185,16 +192,18 @@ protected APIAccess() { public abstract void validatePolyglotAccess(PolyglotAccess access, UnmodifiableEconomicSet language); + public abstract Object getImpl(ResourceLimits value); + } // shared SPI APIAccess api; - MonitoringAccess monitoring; + ManagementAccess management; IOAccess io; - public final void setMonitoring(MonitoringAccess monitoring) { - this.monitoring = monitoring; + public final void setMonitoring(ManagementAccess monitoring) { + this.management = monitoring; } public final void setConstructors(APIAccess constructors) { @@ -211,8 +220,8 @@ public APIAccess getAPIAccess() { return api; } - public MonitoringAccess getMonitoring() { - return monitoring; + public ManagementAccess getManagement() { + return management; } public final IOAccess getIO() { @@ -242,29 +251,29 @@ public abstract Engine buildEngine(OutputStream out, OutputStream err, InputStre public abstract AbstractSourceSectionImpl getSourceSectionImpl(); - public abstract AbstractExecutionListenerImpl getExecutionListenerImpl(); + public abstract AbstractManagementImpl getManagementImpl(); public abstract Path findHome(); - public abstract static class AbstractExecutionListenerImpl { + public abstract static class AbstractManagementImpl { - protected AbstractExecutionListenerImpl(AbstractPolyglotImpl engineImpl) { + protected AbstractManagementImpl(AbstractPolyglotImpl engineImpl) { Objects.requireNonNull(engineImpl); } - public abstract List getInputValues(Object impl); + public abstract List getExecutionEventInputValues(Object impl); - public abstract SourceSection getLocation(Object impl); + public abstract SourceSection getExecutionEventLocation(Object impl); - public abstract String getRootName(Object impl); + public abstract String getExecutionEventRootName(Object impl); - public abstract Value getReturnValue(Object impl); + public abstract Value getExecutionEventReturnValue(Object impl); - public abstract boolean isExpression(Object impl); + public abstract boolean isExecutionEventExpression(Object impl); - public abstract boolean isStatement(Object impl); + public abstract boolean isExecutionEventStatement(Object impl); - public abstract boolean isRoot(Object impl); + public abstract boolean isExecutionEventRoot(Object impl); public abstract void closeExecutionListener(Object impl); @@ -275,7 +284,7 @@ public abstract Object attachExecutionListener(Engine engine, Consumer sourceFilter, Predicate rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectExceptions); - public abstract PolyglotException getException(Object impl); + public abstract PolyglotException getExecutionEventException(Object impl); } @@ -412,6 +421,8 @@ protected AbstractContextImpl(AbstractPolyglotImpl impl) { public abstract Value getBindings(String language); public abstract Value getPolyglotBindings(); + + public abstract void resetLimits(); } public abstract static class AbstractEngineImpl { @@ -442,7 +453,7 @@ public abstract Context createContext(OutputStream out, OutputStream err, InputS 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); + EnvironmentAccess environmentAccess, Map environment, ZoneId zone, Object limitsImpl); public abstract String getImplementationName(); @@ -734,4 +745,8 @@ public Context getCurrentContext() { public abstract Object newTargetTypeMapping(Class sourceType, Class targetType, Predicate acceptsValue, Function convertValue); + public abstract Object buildLimits(long statementLimit, Predicate statementLimitSourceFilter, Duration timeLimit, Duration timeLimitAccuracy, Consumer onLimit); + + public abstract Context getLimitEventContext(Object impl); + } 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 f8479eb77020..cc97f88a4682 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 @@ -45,7 +45,7 @@ import org.graalvm.polyglot.PolyglotException; import org.graalvm.polyglot.SourceSection; import org.graalvm.polyglot.Value; -import static org.graalvm.polyglot.management.ExecutionListener.IMPL; +import static org.graalvm.polyglot.management.Management.IMPL; /** * An execution event object passed to an execution listener consumer. Execution event instances @@ -70,7 +70,7 @@ public final class ExecutionEvent { * @since 19.0 */ public SourceSection getLocation() { - return IMPL.getLocation(impl); + return IMPL.getExecutionEventLocation(impl); } /** @@ -81,7 +81,7 @@ public SourceSection getLocation() { * @since 19.0 */ public String getRootName() { - return IMPL.getRootName(impl); + return IMPL.getExecutionEventRootName(impl); } /** @@ -97,7 +97,7 @@ public String getRootName() { * @since 19.0 */ public List getInputValues() { - return IMPL.getInputValues(impl); + return IMPL.getExecutionEventInputValues(impl); } /** @@ -111,7 +111,7 @@ public List getInputValues() { * @since 19.0 */ public Value getReturnValue() { - return IMPL.getReturnValue(impl); + return IMPL.getExecutionEventReturnValue(impl); } /** @@ -125,7 +125,7 @@ public Value getReturnValue() { * @since 19.0 */ public PolyglotException getException() { - return IMPL.getException(impl); + return IMPL.getExecutionEventException(impl); } /** @@ -136,7 +136,7 @@ public PolyglotException getException() { * @since 19.0 */ public boolean isExpression() { - return IMPL.isExpression(impl); + return IMPL.isExecutionEventExpression(impl); } /** @@ -147,7 +147,7 @@ public boolean isExpression() { * @since 19.0 */ public boolean isStatement() { - return IMPL.isStatement(impl); + return IMPL.isExecutionEventStatement(impl); } /** @@ -158,7 +158,7 @@ public boolean isStatement() { * @since 19.0 */ public boolean isRoot() { - return IMPL.isRoot(impl); + return IMPL.isExecutionEventRoot(impl); } /** 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 bf7c9de20c8b..bddfeef31435 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 @@ -40,7 +40,6 @@ */ package org.graalvm.polyglot.management; -import java.lang.reflect.Method; import java.util.function.Consumer; import java.util.function.Predicate; @@ -48,9 +47,6 @@ import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.PolyglotException; import org.graalvm.polyglot.Source; -import org.graalvm.polyglot.impl.AbstractPolyglotImpl; -import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractExecutionListenerImpl; -import org.graalvm.polyglot.impl.AbstractPolyglotImpl.MonitoringAccess; /** * Execution listeners allow to instrument the execution of guest languages. For example, it is @@ -215,7 +211,7 @@ private ExecutionListener(Object impl) { * @since 19.0 */ public void close() { - IMPL.closeExecutionListener(impl); + Management.IMPL.closeExecutionListener(impl); } /** @@ -427,30 +423,9 @@ public Builder collectExceptions(boolean enabled) { */ public ExecutionListener attach(Engine engine) { return new ExecutionListener( - IMPL.attachExecutionListener(engine, onEnter, onReturn, expressions, statements, roots, + Management.IMPL.attachExecutionListener(engine, onEnter, onReturn, expressions, statements, roots, sourceFilter, rootNameFilter, collectInputValues, collectReturnValues, collectExceptions)); } } - static final AbstractExecutionListenerImpl IMPL = initImpl(); - - private static AbstractExecutionListenerImpl initImpl() { - try { - Method method = Engine.class.getDeclaredMethod("getImpl"); - method.setAccessible(true); - AbstractPolyglotImpl impl = (AbstractPolyglotImpl) method.invoke(null); - impl.setMonitoring(new MonitoringAccessImpl()); - return impl.getExecutionListenerImpl(); - } catch (Exception e) { - throw new IllegalStateException("Failed to initialize execution listener class.", e); - } - } - - private static class MonitoringAccessImpl extends MonitoringAccess { - @Override - public ExecutionEvent newExecutionEvent(Object event) { - return new ExecutionEvent(event); - } - } - } 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 new file mode 100644 index 000000000000..f161f2c6bf5c --- /dev/null +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/management/Management.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019, 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.polyglot.management; + +import java.lang.reflect.Method; + +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractManagementImpl; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.ManagementAccess; + +/* + * Class to manage package access. + */ +final class Management { + + private Management() { + } + + static final AbstractManagementImpl IMPL = initImpl(); + + private static AbstractManagementImpl initImpl() { + try { + Method method = Engine.class.getDeclaredMethod("getImpl"); + method.setAccessible(true); + AbstractPolyglotImpl impl = (AbstractPolyglotImpl) method.invoke(null); + impl.setMonitoring(new ManagementAccessImpl()); + return impl.getManagementImpl(); + } catch (Exception e) { + throw new IllegalStateException("Failed to initialize execution listener class.", e); + } + } + + private static class ManagementAccessImpl extends ManagementAccess { + @Override + public ExecutionEvent newExecutionEvent(Object event) { + return new ExecutionEvent(event); + } + + } + +} 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 fdb979bfd539..30b652756d50 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 @@ -229,6 +229,12 @@ protected InstrumentContext createContext(TruffleLanguage.Env env) { return new InstrumentContext(env, initSource, runInitAfterExec); } + private CallTarget lastParsed; + + public static CallTarget getLastParsedCalltarget() { + return getCurrentLanguage(InstrumentationTestLanguage.class).lastParsed; + } + @Override protected void initializeContext(InstrumentContext context) throws Exception { super.initializeContext(context); @@ -260,7 +266,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { throw new IOException(e); } RootCallTarget afterTarget = getContextReference().get().afterTarget; - return Truffle.getRuntime().createCallTarget(new InstrumentationTestRootNode(this, "", outer, afterTarget, node)); + return lastParsed = Truffle.getRuntime().createCallTarget(new InstrumentationTestRootNode(this, "", outer, afterTarget, node)); } public static RootNode parse(String code) { diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java new file mode 100644 index 000000000000..73a8f5ff00d4 --- /dev/null +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2019, 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 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 static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.PolyglotException; +import org.graalvm.polyglot.ResourceLimitEvent; +import org.graalvm.polyglot.ResourceLimits; +import org.graalvm.polyglot.Source; +import org.junit.Test; + +public class ResourceLimitsTest { + + @Test + public void testBoundContextTimeLimit() { + ResourceLimits limits = ResourceLimits.newBuilder().// + cpuTimeLimit(Duration.ofMillis(10), Duration.ofMillis(1)).// + build(); + + try (Context context = Context.newBuilder().resourceLimits(limits).build()) { + context.initialize(InstrumentationTestLanguage.ID); + try { + // we wait, because we want to test that the time limit + // has effect only for entered contexts + Thread.sleep(20); + } catch (InterruptedException e) { + } + try { + evalStatements(context); + fail(); + } catch (PolyglotException e) { + assertTimeout(context, e); + } + } + } + + @Test + public void testSharedContextTimeLimitSynchronous() { + ResourceLimits limits = ResourceLimits.newBuilder().// + cpuTimeLimit(Duration.ofMillis(3), Duration.ofMillis(1)).// + build(); + + Engine engine = Engine.create(); + + for (int i = 0; i < 10; i++) { + try (Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + try { + evalStatements(c); + fail(); + } catch (PolyglotException e) { + assertTimeout(c, e); + } + } + } + } + + @Test + public void testSharedContextTimeLimitParallel() throws InterruptedException, ExecutionException { + ResourceLimits limits = ResourceLimits.newBuilder().// + cpuTimeLimit(Duration.ofMillis(5), Duration.ofMillis(1)).// + build(); + + Engine engine = Engine.create(); + ExecutorService executorService = Executors.newFixedThreadPool(10); + List> futures = new ArrayList<>(); + for (int i = 0; i < 100; i++) { + futures.add(executorService.submit(() -> { + try (Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + try { + evalStatements(c); + fail(); + } catch (PolyglotException e) { + assertTimeout(c, e); + } + } + })); + } + for (Future future : futures) { + future.get(); + } + executorService.shutdown(); + } + + @Test + public void testSharedContextTimeLimitResetParallel() throws InterruptedException, ExecutionException { + ResourceLimits limits = ResourceLimits.newBuilder().// + cpuTimeLimit(Duration.ofMillis(250), Duration.ofMillis(1)).// + build(); + + System.gc(); // force gc before running this test + System.gc(); + Engine engine = Engine.create(); + ExecutorService executorService = Executors.newFixedThreadPool(10); + List> futures = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + futures.add(executorService.submit(() -> { + try (Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + for (int j = 0; j < 10; j++) { + c.enter(); + Thread.sleep(50); + c.leave(); + c.resetLimits(); + } + try { + evalStatements(c); + fail(); + } catch (PolyglotException e) { + assertTimeout(c, e); + } + } catch (InterruptedException e) { + throw new AssertionError(e); + } + })); + } + for (Future future : futures) { + future.get(); + } + executorService.shutdown(); + } + + private static void evalStatements(Context c) { + /* + * We do multiple smaller eval statements in order to test the behavior when the resource + * consumption limit was reached between statements. + */ + c.eval(statements(10)); + c.eval(statements(500)); + c.eval(statements(1000)); + c.eval(statements(Integer.MAX_VALUE)); + } + + private static void assertTimeout(Context c, PolyglotException e) { + assertTrue(e.isCancelled()); + assertTrue(e.getMessage(), e.getMessage().startsWith("Time resource limit")); + try { + c.eval(InstrumentationTestLanguage.ID, "EXPRESSION"); + fail(); + } catch (PolyglotException ex) { + assertTrue(e.isCancelled()); + assertTrue(e.getMessage(), e.getMessage().startsWith("Time resource limit")); + } + } + + @Test + public void testStatementLimit() { + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(50, null).// + build(); + + try (Context context = Context.newBuilder().resourceLimits(limits).build()) { + context.eval(statements(50)); + try { + context.eval(statements(1)); + fail(); + } catch (PolyglotException e) { + assertStatementCountLimit(context, e, 50); + } + } + } + + @Test + public void testStatementLimitFilter() { + Source internalSource = statements(10, "internalSource"); + Source publicSource = statements(10, "publicSource"); + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(50, (s) -> internalSource.equals(s)).// + build(); + + try (Context context = Context.newBuilder().resourceLimits(limits).build()) { + for (int i = 0; i < 5; i++) { + context.eval(publicSource); + context.eval(internalSource); + } + try { + for (int i = 0; i < 100; i++) { + context.eval(internalSource); + } + context.eval(InstrumentationTestLanguage.ID, "LOOP(1, STATEMENT)"); + fail(); + } catch (PolyglotException e) { + assertStatementCountLimit(context, e, 50); + } + } + } + + @Test + public void testStatementInvalidLimitFilter() { + ResourceLimits limits0 = ResourceLimits.newBuilder().// + statementLimit(50, (s) -> true).// + build(); + ResourceLimits limits1 = ResourceLimits.newBuilder().// + statementLimit(50, (s) -> true).// + build(); + Context.newBuilder().resourceLimits(limits0).build().close(); + Context.newBuilder().resourceLimits(limits1).build().close(); + + Engine engine = Engine.create(); + Context.newBuilder().engine(engine).resourceLimits(limits0).build().close(); + Context.Builder builder = Context.newBuilder().engine(engine).resourceLimits(limits1); + try { + builder.build(); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Using multiple source predicates per engine is not supported. " + + "The same statement limit source predicate must be used for all polyglot contexts that are assigned to the same engine. " + + "Resolve this by using the same predicate instance when constructing the limits object with ResourceLimits.Builder.statementLimit(long, Predicate).", + e.getMessage()); + } + } + + @Test + public void testStatementLimitFilterError() { + RuntimeException expectedException = new RuntimeException("error"); + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(50, (s) -> { + throw expectedException; + }).// + build(); + try (Context context = Context.newBuilder().resourceLimits(limits).build()) { + Source source = statements(1); + try { + context.eval(source); + fail(); + } catch (PolyglotException ex) { + assertTrue(ex.isHostException()); + assertSame(expectedException, ex.asHostException()); + } + } + } + + @Test + public void testStatementLimitOnEvent() { + List events = new ArrayList<>(); + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(1, null).// + onLimit((e) -> events.add(e)).// + build(); + try (Context context = Context.newBuilder().resourceLimits(limits).build()) { + Source source = statements(1); + + context.eval(source); + try { + context.eval(source); + fail(); + } catch (PolyglotException ex) { + assertStatementCountLimit(context, ex, 1); + assertEquals(1, events.size()); + assertSame(context, events.iterator().next().getContext()); + } + } + } + + @Test + public void testStatementLimitDifferentPerContext() { + ResourceLimits limits1 = ResourceLimits.newBuilder().// + statementLimit(1, null).// + build(); + ResourceLimits limits2 = ResourceLimits.newBuilder().// + statementLimit(2, null).// + build(); + Source source = statements(1); + Engine engine = Engine.create(); + + for (int i = 0; i < 10; i++) { + // test no limit + try (Context context = Context.newBuilder().engine(engine).build()) { + context.eval(source); + context.eval(source); + context.eval(source); + } + + // test with limit + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits1).build()) { + context.eval(source); + try { + context.eval(source); + fail(); + } catch (PolyglotException ex) { + assertStatementCountLimit(context, ex, 1); + } + } + + // test with different limit + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits2).build()) { + context.eval(source); + context.eval(source); + try { + context.eval(source); + fail(); + } catch (PolyglotException ex) { + assertStatementCountLimit(context, ex, 2); + } + } + } + } + + @Test + public void testStatementLimitDifferentPerContextParallel() { + ResourceLimits limits1 = ResourceLimits.newBuilder().// + statementLimit(1, null).// + build(); + ResourceLimits limits2 = ResourceLimits.newBuilder().// + statementLimit(2, null).// + build(); + Source source = statements(1); + Engine engine = Engine.create(); + + ExecutorService executorService = Executors.newFixedThreadPool(20); + List> futures = new ArrayList<>(); + + for (int i = 0; i < 10; i++) { + futures.add(executorService.submit(() -> { + + // test no limit + try (Context context = Context.newBuilder().engine(engine).build()) { + context.eval(source); + context.eval(source); + context.eval(source); + } + + // test with limit + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits1).build()) { + context.eval(source); + try { + context.eval(source); + fail(); + } catch (PolyglotException ex) { + assertStatementCountLimit(context, ex, 1); + } + } + + // test with different limit + try (Context context = Context.newBuilder().engine(engine).resourceLimits(limits2).build()) { + context.eval(source); + context.eval(source); + try { + context.eval(source); + fail(); + } catch (PolyglotException ex) { + assertStatementCountLimit(context, ex, 2); + } + } + })); + } + } + + private static Source statements(int count) { + return statements(count, ResourceLimitsTest.class.getSimpleName()); + } + + private static Source statements(int count, String name) { + return Source.newBuilder(InstrumentationTestLanguage.ID, "LOOP(" + (count == Integer.MAX_VALUE ? "infinity" : count) + ", STATEMENT)", name).buildLiteral(); + } + + @Test + public void testSharedContextStatementLimitSynchronous() { + List events = new ArrayList<>(); + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(50, null).// + onLimit((e) -> events.add(e)).// + build(); + Engine engine = Engine.create(); + + for (int i = 0; i < 10; i++) { + try (Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + c.eval(statements(50)); + try { + c.eval(statements(1)); + fail(); + } catch (PolyglotException e) { + assertStatementCountLimit(c, e, 50); + assertEquals(1, events.size()); + assertSame(c, events.iterator().next().getContext()); + assertNotNull(events.iterator().next().toString()); + } + } + events.clear(); + } + } + + @Test + public void testSharedContextStatementLimitParallel() throws InterruptedException, ExecutionException { + Engine engine = Engine.create(); + Map events = new HashMap<>(); + final int limit = 50; + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(limit, null).// + onLimit((e) -> { + synchronized (events) { + events.put(e.getContext(), e); + } + }).// + build(); + ExecutorService executorService = Executors.newFixedThreadPool(20); + List> futures = new ArrayList<>(); + final int tasks = 1000; + for (int i = 0; i < tasks; i++) { + futures.add(executorService.submit(() -> { + try (Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + c.eval(statements(limit)); + try { + c.eval(statements(1)); + fail(); + } catch (PolyglotException e) { + assertStatementCountLimit(c, e, limit); + synchronized (events) { + assertNotNull(events.get(c)); + assertSame(c, events.get(c).getContext()); + assertNotNull(events.get(c).toString()); + } + } + } + })); + } + for (Future future : futures) { + future.get(); + } + executorService.shutdown(); + synchronized (events) { + assertEquals(tasks, events.size()); + } + } + + @Test + public void testParallelContextStatementLimit() throws InterruptedException, ExecutionException { + Engine engine = Engine.create(); + Map events = new HashMap<>(); + final int limit = 10000; + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(limit, null).// + onLimit((e) -> { + synchronized (events) { + assertTrue(events.isEmpty()); + events.put(e.getContext(), e); + } + }).// + build(); + ExecutorService executorService = Executors.newFixedThreadPool(20); + List> futures = new ArrayList<>(); + try (Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + for (int i = 0; i < limit; i++) { + futures.add(executorService.submit(() -> { + c.eval(statements(1)); + })); + } + for (Future future : futures) { + future.get(); + } + try { + c.eval(statements(1)); + fail(); + } catch (PolyglotException e) { + assertStatementCountLimit(c, e, limit); + synchronized (events) { + assertNotNull(events.get(c)); + assertSame(c, events.get(c).getContext()); + assertNotNull(events.get(c).toString()); + } + } + } + executorService.shutdown(); + } + + @Test + public void testParallelMultiContextStatementLimit() throws InterruptedException, ExecutionException { + Engine engine = Engine.create(); + Map events = new ConcurrentHashMap<>(); + final int executions = 100; + final int contexts = 100; + final int threads = 20; + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(executions, null).// + onLimit((e) -> { + events.put(e.getContext(), e); + }).// + build(); + ExecutorService executorService = Executors.newFixedThreadPool(threads); + List> testFutures = new ArrayList<>(); + for (int contextIndex = 0; contextIndex < contexts; contextIndex++) { + Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build(); + List> futures = new ArrayList<>(); + for (int i = 0; i < executions; i++) { + futures.add(executorService.submit(() -> { + c.eval(statements(1)); + })); + } + testFutures.add(executorService.submit(() -> { + for (Future future : futures) { + try { + future.get(); + } catch (InterruptedException | ExecutionException e1) { + if (e1 instanceof ExecutionException) { + if (e1.getCause() instanceof PolyglotException) { + PolyglotException e = (PolyglotException) e1.getCause(); + if (e.isCancelled()) { + throw new AssertionError("Context was cancelled too early.", e); + } + } + } + throw new RuntimeException(e1); + } + } + try { + c.eval(statements(1)); + fail(); + } catch (PolyglotException e) { + assertStatementCountLimit(c, e, executions); + assertNotNull(events.get(c)); + assertSame(c, events.get(c).getContext()); + assertNotNull(events.get(c).toString()); + } + c.close(); + })); + } + for (Future future : testFutures) { + future.get(); + } + + assertEquals(contexts, events.size()); + executorService.shutdown(); + } + + @Test + public void testParallelMultiContextStatementResetLimit() throws InterruptedException, ExecutionException { + Engine engine = Engine.create(); + Map events = new ConcurrentHashMap<>(); + final int executions = 100; + final int contexts = 100; + final int threads = 20; + ResourceLimits limits = ResourceLimits.newBuilder().// + statementLimit(executions, null).// + onLimit((e) -> { + events.put(e.getContext(), e); + }).// + build(); + ExecutorService executorService = Executors.newFixedThreadPool(threads); + List> testFutures = new ArrayList<>(); + for (int contextIndex = 0; contextIndex < contexts; contextIndex++) { + Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build(); + List> futures = new ArrayList<>(); + for (int i = 0; i < executions; i++) { + futures.add(executorService.submit(() -> { + c.eval(statements(1)); + })); + } + Future prev = executorService.submit(() -> { + for (Future future : futures) { + try { + future.get(); + } catch (InterruptedException | ExecutionException e1) { + throw new RuntimeException(e1); + } + } + c.resetLimits(); + }); + + testFutures.add(executorService.submit(() -> { + try { + prev.get(); + } catch (InterruptedException | ExecutionException e1) { + throw new RuntimeException(e1); + } + c.eval(statements(executions)); + try { + c.eval(statements(1)); + fail(); + } catch (PolyglotException e) { + assertStatementCountLimit(c, e, executions); + assertNotNull(events.get(c)); + assertSame(c, events.get(c).getContext()); + assertNotNull(events.get(c).toString()); + } + c.close(); + })); + } + for ( + + Future future : testFutures) { + future.get(); + } + + assertEquals(contexts, events.size()); + executorService.shutdown(); + } + + @Test + public void testTimeLimitErrors() { + ResourceLimits.Builder builder = ResourceLimits.newBuilder(); + assertFails(() -> builder.cpuTimeLimit(Duration.ofMillis(-1), Duration.ofMillis(1)), IllegalArgumentException.class); + assertFails(() -> builder.cpuTimeLimit(Duration.ofMillis(0), Duration.ofMillis(1)), IllegalArgumentException.class); + assertFails(() -> builder.cpuTimeLimit(Duration.ofMillis(1), Duration.ofMillis(-1)), IllegalArgumentException.class); + assertFails(() -> builder.cpuTimeLimit(Duration.ofMillis(1), Duration.ofMillis(0)), IllegalArgumentException.class); + assertFails(() -> builder.cpuTimeLimit(null, Duration.ofMillis(0)), IllegalArgumentException.class); + assertFails(() -> builder.cpuTimeLimit(Duration.ofMillis(0), null), IllegalArgumentException.class); + builder.cpuTimeLimit(null, null); // allowed to reset + } + + @Test + public void testStatementLimitErrors() { + assertFails(() -> ResourceLimits.newBuilder().statementLimit(-1, null), IllegalArgumentException.class); + Context context = Context.create(); + // no op without limits + context.resetLimits(); + + Context.newBuilder().resourceLimits(null); // allowed + } + + private static void assertStatementCountLimit(Context c, PolyglotException e, int limit) { + assertTrue(e.isCancelled()); + String expectedMessage = "Statement count limit of " + limit + " exceeded. Statements executed " + (limit + 1) + "."; + assertEquals(expectedMessage, e.getMessage()); + assertEquals("STATEMENT", e.getSourceLocation().getCharacters()); + try { + c.eval(InstrumentationTestLanguage.ID, "EXPRESSION"); + fail(); + } catch (PolyglotException ex) { + assertTrue(e.isCancelled()); + assertEquals(expectedMessage, e.getMessage()); + } + } + +} 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 564c13a6be08..adabc666cd0e 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 @@ -73,6 +73,7 @@ public abstract class AbstractPolyglotTest { protected TruffleLanguage language; protected TruffleInstrument.Env instrumentEnv; protected boolean cleanupOnSetup = true; + protected boolean enterContext = true; protected final void setupEnv(Context newContext, ProxyInstrument instrument) { setupEnv(newContext, null, instrument); @@ -129,7 +130,9 @@ protected final void setupEnv(Context newContext, ProxyLanguage language, ProxyI newContext.initialize(languageId); // enter current context - newContext.enter(); + if (enterContext) { + newContext.enter(); + } assertNotNull(this.languageEnv); assertNotNull(this.language); @@ -167,13 +170,23 @@ protected final Supplier adoptNode(TruffleLanguage lang, @After public final void cleanup() { if (context != null) { - context.leave(); + if (enterContext) { + context.leave(); + } + context.close(); context = null; } } - protected static void assertFails(Callable callable, Class exceptionType) { + public static void assertFails(Runnable callable, Class exceptionType) { + assertFails((Callable) () -> { + callable.run(); + return null; + }, exceptionType); + } + + public static void assertFails(Callable callable, Class exceptionType) { try { callable.call(); } catch (Throwable t) { 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 8ba09dc83e7e..27caa3e0d956 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 @@ -117,6 +117,28 @@ public void testEqualsAndHashcode() { context.close(); } + @Test + public void testCloseBeforeLeave() { + for (int i = 0; i < 10; i++) { + Context context = Context.create(); + for (int j = 0; j < i; j++) { + context.enter(); + } + context.close(); + // we have already left the context + try { + Context.getCurrent(); + fail(); + } catch (IllegalStateException e) { + } + for (int j = 0; j < i; j++) { + // additional leave calls are allowed + // this allows to simplify some error recovery code + context.leave(); + } + } + } + @Test public void testContextCreateSingleLanguage() { Context context = Context.create(ContextAPITestLanguage.ID); @@ -287,21 +309,9 @@ private static void testEnterLeave(Context context, int depth) { context.getPolyglotBindings().getMember(""); context.enter(); - try { - context.close(); - fail(); - } catch (IllegalStateException e) { - } - context.getPolyglotBindings().getMember(""); context.enter(); - try { - context.close(); - fail(); - } catch (IllegalStateException e) { - } - if (depth < 3) { Context innerContext = Context.create(); testEnterLeave(innerContext, depth + 1); @@ -310,12 +320,6 @@ private static void testEnterLeave(Context context, int depth) { context.leave(); - try { - context.close(); - fail(); - } catch (IllegalStateException e) { - } - context.leave(); try { @@ -323,7 +327,6 @@ private static void testEnterLeave(Context context, int depth) { fail(); } catch (IllegalStateException e) { } - } @Test diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextParallelCloseTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextParallelCloseTest.java index 490c9e43d9eb..c645af295f31 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextParallelCloseTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextParallelCloseTest.java @@ -101,7 +101,7 @@ public void testCloseDeadlock() throws InterruptedException, ExecutionException context.eval(ReuseLanguage.ID, ""); fail(); } catch (IllegalStateException e) { - assertEquals("Engine is already closed.", e.getMessage()); + assertEquals("The Context is already closed.", e.getMessage()); } } } finally { 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 41ffa6013a51..5949d6cf914d 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 @@ -356,7 +356,7 @@ public void testPrepareContextAndUseItAfterReset() throws Exception { } } - private static Object resetSingleContextState(boolean reuse) { + public static Object resetSingleContextState(boolean reuse) { try { Class c = Class.forName("com.oracle.truffle.polyglot.PolyglotContextImpl"); Method m = c.getDeclaredMethod("resetSingleContextState", boolean.class); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/ContextThreadLocal.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/ContextThreadLocal.java index bcf4cf323f9e..fd977c439033 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/ContextThreadLocal.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/ContextThreadLocal.java @@ -48,17 +48,19 @@ final class ContextThreadLocal extends ThreadLocal { - private final Assumption singleThread = Truffle.getRuntime().createAssumption("constant context store"); - private PolyglotContextImpl firstContext; - @CompilationFinal private volatile Thread firstThread; + private final Assumption singleThread = Truffle.getRuntime().createAssumption("single thread"); + private volatile PolyglotContextImpl activeSingleContext; + private PolyglotContextImpl activeSingleContextNonVolatile; + @CompilationFinal private volatile Thread activeSingleThread; @Override protected Object initialValue() { - if (Thread.currentThread() == firstThread) { + if (Thread.currentThread() == activeSingleThread) { // must only happen once - Object context = firstContext; - firstContext = null; - firstThread = null; + Object context = activeSingleContext; + activeSingleContext = null; + activeSingleThread = null; + activeSingleContextNonVolatile = null; return context; } return null; @@ -66,16 +68,21 @@ protected Object initialValue() { public boolean isSet() { if (singleThread.isValid()) { - boolean set = firstContext != null; - return Thread.currentThread() == firstThread && set; + boolean set = activeSingleContext != null; + return Thread.currentThread() == activeSingleThread && set; } else { return getTL() != null; } } - public Object getNoThreadCheck() { + /** + * If we are entered and there is a single thread we can globally ignore the thread check. We + * can also read from a non volatile field in order to allow moving of context reads. + */ + public Object getEntered() { if (singleThread.isValid()) { - return firstContext; + assert Thread.currentThread() == activeSingleThread; + return activeSingleContextNonVolatile; } else { return getTL(); } @@ -85,8 +92,8 @@ public Object getNoThreadCheck() { public Object get() { Object context; if (singleThread.isValid()) { - if (Thread.currentThread() == firstThread) { - context = firstContext; + if (Thread.currentThread() == activeSingleThread) { + context = activeSingleContext; } else { CompilerDirectives.transferToInterpreter(); context = getImplSlowPath(); @@ -105,9 +112,10 @@ public void set(Object value) { Object setReturnParent(Object value) { if (singleThread.isValid()) { Object prev; - if (Thread.currentThread() == firstThread) { - prev = this.firstContext; - this.firstContext = (PolyglotContextImpl) value; + if (Thread.currentThread() == activeSingleThread) { + prev = this.activeSingleContext; + this.activeSingleContext = (PolyglotContextImpl) value; + this.activeSingleContextNonVolatile = (PolyglotContextImpl) value; } else { CompilerDirectives.transferToInterpreter(); prev = setReturnParentSlowPath(value); @@ -131,10 +139,11 @@ private Object getTL() { if (current instanceof PolyglotThread) { PolyglotThread polyglotThread = ((PolyglotThread) current); Object context = polyglotThread.context; - if (context == null && firstThread == current) { - context = polyglotThread.context = firstContext; - firstContext = null; - firstThread = null; + if (context == null && activeSingleThread == current) { + context = polyglotThread.context = activeSingleContext; + activeSingleContext = null; + activeSingleContextNonVolatile = null; + activeSingleThread = null; } return context; } else { @@ -162,16 +171,18 @@ private synchronized Object setReturnParentSlowPath(Object context) { return setTLReturnParent(context); } Thread currentThread = Thread.currentThread(); - Thread storeThread = firstThread; - Object prev = this.firstContext; + Thread storeThread = activeSingleThread; + Object prev = this.activeSingleContext; if (currentThread == storeThread) { - this.firstContext = (PolyglotContextImpl) context; + this.activeSingleContext = (PolyglotContextImpl) context; + this.activeSingleContextNonVolatile = (PolyglotContextImpl) context; } else { if (storeThread == null) { - this.firstThread = currentThread; - this.firstContext = (PolyglotContextImpl) context; + this.activeSingleThread = currentThread; + this.activeSingleContext = (PolyglotContextImpl) context; + this.activeSingleContextNonVolatile = (PolyglotContextImpl) context; } else { - singleThread.invalidate(); + this.singleThread.invalidate(); return setTLReturnParent(context); } } 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 8da2683b56e7..57a009cf1847 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 @@ -343,7 +343,7 @@ public LanguageInfo getObjectLanguage(Object obj, Object vmObject) { @Override public Object getCurrentVM() { - PolyglotContextImpl context = PolyglotContextImpl.current(); + PolyglotContextImpl context = PolyglotContextImpl.currentNotEntered(); if (context == null) { return null; } @@ -352,7 +352,7 @@ public Object getCurrentVM() { @Override public boolean isMultiThreaded(Object o) { - PolyglotContextImpl context = PolyglotContextImpl.current(); + PolyglotContextImpl context = PolyglotContextImpl.currentNotEntered(); if (context == null) { return true; } @@ -451,17 +451,17 @@ public void exportSymbol(Object vmObject, String symbolName, Object value) { } if (value == null) { - context.context.polyglotBindings.remove(symbolName); + context.context.getPolyglotGuestBindings().remove(symbolName); } else { - context.context.polyglotBindings.put(symbolName, context.asValue(value)); + context.context.getPolyglotGuestBindings().put(symbolName, context.asValue(value)); } } @SuppressWarnings("unchecked") @Override public Map getExportedSymbols(Object vmObject) { - PolyglotContextImpl currentContext = PolyglotContextImpl.current(); - return currentContext.polyglotHostBindings.as(Map.class); + PolyglotContextImpl currentContext = PolyglotContextImpl.currentNotEntered(); + return currentContext.getPolyglotBindings().as(Map.class); } @Override @@ -519,12 +519,14 @@ public TruffleContext getParentContext(Object impl) { @Override public Object enterInternalContext(Object impl) { - return ((PolyglotContextImpl) impl).enter(); + PolyglotContextImpl context = ((PolyglotContextImpl) impl); + return context.engine.enter(context); } @Override public void leaveInternalContext(Object impl, Object prev) { - ((PolyglotContextImpl) impl).leave(prev); + PolyglotContextImpl context = ((PolyglotContextImpl) impl); + context.engine.leave(prev, context); } @Override @@ -598,7 +600,7 @@ public Throwable asHostException(Throwable exception) { @Override public Object getCurrentHostContext() { - PolyglotContextImpl polyglotContext = PolyglotContextImpl.current(); + PolyglotContextImpl polyglotContext = PolyglotContextImpl.currentNotEntered(); return polyglotContext == null ? null : polyglotContext.getHostContext(); } @@ -640,7 +642,7 @@ public Object findMetaObjectForLanguage(Object languageVMObject, Object value) { @SuppressWarnings("cast") @Override public PolyglotException wrapGuestException(String languageId, Throwable e) { - PolyglotContextImpl pc = PolyglotContextImpl.current(); + PolyglotContextImpl pc = PolyglotContextImpl.currentNotEntered(); if (pc == null) { return null; } 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 cb64355d59e2..ab97353d6e05 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 @@ -60,8 +60,12 @@ abstract class HostToGuestRootNode extends RootNode { @CompilationFinal private volatile ContextProfile profile; + private final PolyglotEngineImpl engine; + HostToGuestRootNode() { super(null); + this.engine = (PolyglotEngineImpl) EngineAccessor.NODES.getSourceVM(this); + assert this.engine != null : "all host to guest root nodes need to be initialized when entered"; } protected abstract Class getReceiverType(); @@ -72,14 +76,14 @@ public final Object execute(VirtualFrame frame) { PolyglotLanguageContext languageContext = profileContext(args[0]); assert languageContext != null; PolyglotContextImpl context = languageContext.context; - boolean needsEnter = languageContext != null && context.needsEnter(); + boolean needsEnter = languageContext != null && engine.needsEnter(context); Object prev; if (needsEnter) { if (!seenEnter) { CompilerDirectives.transferToInterpreterAndInvalidate(); seenEnter = true; } - prev = context.enter(); + prev = engine.enter(context); } else { if (!seenNonEnter) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -99,7 +103,7 @@ public final Object execute(VirtualFrame frame) { throw PolyglotImpl.wrapGuestException((languageContext), e); } finally { if (needsEnter) { - context.leave(prev); + engine.leave(prev, context); } } } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotBindings.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotBindings.java index 402622edfae0..1f08a51913a9 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotBindings.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotBindings.java @@ -57,11 +57,18 @@ final class PolyglotBindings implements TruffleObject { // a bindings object for each language. private final PolyglotLanguageContext languageContext; // the bindings map that shared across a bindings object for each language context - private final Map bindings; + private volatile Map bindings; - PolyglotBindings(PolyglotLanguageContext languageContext, Map bindings) { + PolyglotBindings(PolyglotLanguageContext languageContext) { this.languageContext = languageContext; - this.bindings = bindings; + } + + public Map getBindings() { + Map localBindings = this.bindings; + if (localBindings == null) { + this.bindings = localBindings = languageContext.context.getPolyglotGuestBindings(); + } + return localBindings; } @SuppressWarnings("static-method") @@ -73,7 +80,7 @@ boolean hasMembers() { @ExportMessage @TruffleBoundary Object readMember(String member) throws UnknownIdentifierException { - Value value = bindings.get(member); + Value value = getBindings().get(member); if (value == null) { // legacy support Value legacyValue = languageContext.context.findLegacyExportedSymbol(member); @@ -88,13 +95,13 @@ Object readMember(String member) throws UnknownIdentifierException { @ExportMessage @TruffleBoundary void writeMember(String member, Object value) { - bindings.put(member, languageContext.asValue(value)); + getBindings().put(member, languageContext.asValue(value)); } @ExportMessage @TruffleBoundary void removeMember(String member) throws UnknownIdentifierException { - Value ret = bindings.remove(member); + Value ret = getBindings().remove(member); if (ret == null) { throw UnknownIdentifierException.create(member); } @@ -103,7 +110,7 @@ void removeMember(String member) throws UnknownIdentifierException { @ExportMessage @TruffleBoundary Object getMembers(@SuppressWarnings("unused") boolean includeInternal) { - return new DefaultScope.VariableNamesObject(bindings.keySet()); + return new DefaultScope.VariableNamesObject(getBindings().keySet()); } @ExportMessage(name = "isMemberReadable") @@ -111,7 +118,7 @@ Object getMembers(@SuppressWarnings("unused") boolean includeInternal) { @ExportMessage(name = "isMemberRemovable") @TruffleBoundary boolean isMemberExisting(String member) { - boolean existing = bindings.containsKey(member); + boolean existing = getBindings().containsKey(member); if (!existing) { return languageContext.context.findLegacyExportedSymbol(member) != null; } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotBindingsValue.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotBindingsValue.java index 04e281fab673..41a965ef6847 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotBindingsValue.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotBindingsValue.java @@ -58,7 +58,7 @@ final class PolyglotBindingsValue extends PolyglotValue { PolyglotBindingsValue(PolyglotLanguageContext context) { super(context); this.values = context.context.polyglotBindings; - this.delegateBindings = context.asValue(new PolyglotBindings(context, values)); + this.delegateBindings = context.asValue(new PolyglotBindings(context)); } @Override 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 fd511e0d0c72..bec577291778 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 @@ -84,13 +84,15 @@ final class PolyglotContextConfig { private final Map environment; private volatile Map configuredEnvironement; private volatile ZoneId timeZone; + final PolyglotLimits limits; PolyglotContextConfig(PolyglotEngineImpl engine, OutputStream out, OutputStream err, InputStream in, boolean hostLookupAllowed, PolyglotAccess polyglotAccess, boolean nativeAccessAllowed, boolean createThreadAllowed, boolean hostClassLoadingAllowed, boolean allowExperimentalOptions, Predicate classFilter, Map applicationArguments, EconomicSet allowedPublicLanguages, Map options, FileSystem fileSystem, FileSystem internalFileSystem, Handler logHandler, - boolean createProcessAllowed, ProcessHandler processHandler, EnvironmentAccess environmentAccess, Map environment, ZoneId timeZone) { + boolean createProcessAllowed, ProcessHandler processHandler, EnvironmentAccess environmentAccess, Map environment, + ZoneId timeZone, PolyglotLimits limits) { assert out != null; assert err != null; assert in != null; @@ -112,6 +114,7 @@ final class PolyglotContextConfig { this.optionsByLanguage = new HashMap<>(); this.logHandler = logHandler; this.timeZone = timeZone; + this.limits = limits; this.logLevels = new HashMap<>(engine.logLevels); for (String optionKey : options.keySet()) { final String group = PolyglotEngineImpl.parseOptionGroup(optionKey); 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 f6d3a653f165..6c0795dc4f4b 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 @@ -56,7 +56,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.concurrent.locks.ReentrantLock; import org.graalvm.collections.EconomicSet; @@ -78,7 +80,7 @@ import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.impl.Accessor.CastUnsafe; import com.oracle.truffle.polyglot.HostLanguage.HostContext; -import java.util.WeakHashMap; +import com.oracle.truffle.polyglot.PolyglotEngineImpl.CancelExecution; final class PolyglotContextImpl extends AbstractContextImpl implements com.oracle.truffle.polyglot.PolyglotImpl.VMObject { @@ -87,8 +89,8 @@ final class PolyglotContextImpl extends AbstractContextImpl implements com.oracl * simplifies resetting state in AOT mode during native image generation. */ static final class SingleContextState { - private final ContextThreadLocal contextThreadLocal = new ContextThreadLocal(); - private final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("Single Context"); + final ContextThreadLocal contextThreadLocal = new ContextThreadLocal(); + final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("Single Context"); @CompilationFinal private volatile PolyglotContextImpl singleContext; /** Copy constructor that keeps the previous state. */ @@ -102,7 +104,7 @@ static final class SingleContextState { } } - @CompilationFinal private static SingleContextState singleContextState = new SingleContextState(null); + @CompilationFinal static SingleContextState singleContextState = new SingleContextState(null); /* * Used from testing using reflection. Its invalid to call it anywhere else than testing. Used @@ -130,10 +132,7 @@ static boolean isSingleContextAssumptionValid() { return singleContextState.singleContextAssumption.isValid(); } - private static final Object NO_ENTER = new Object(); - final Assumption singleThreaded = Truffle.getRuntime().createAssumption("Single threaded"); - private final Assumption singleThreadedConstant = Truffle.getRuntime().createAssumption("Single threaded constant thread"); private final Map threads = new WeakHashMap<>(); private volatile PolyglotThreadInfo currentThreadInfo = PolyglotThreadInfo.NULL; @@ -144,12 +143,14 @@ static boolean isSingleContextAssumptionValid() { * closed state. */ volatile boolean cancelling; + volatile String invalidMessage; volatile Thread closingThread; private final ReentrantLock closingLock = new ReentrantLock(); /* * If the context is closed all operations should fail with IllegalStateException. */ volatile boolean closed; + volatile boolean invalid; volatile boolean disposing; final PolyglotEngineImpl engine; @CompilationFinal(dimensions = 1) final PolyglotLanguageContext[] contexts; @@ -161,8 +162,8 @@ static boolean isSingleContextAssumptionValid() { final TruffleContext truffleContext; final PolyglotContextImpl parent; - final Map polyglotBindings; // for direct legacy access - final Value polyglotHostBindings; // for accesses from the polyglot api + volatile Map polyglotBindings; // for direct legacy access + volatile Value polyglotHostBindings; // for accesses from the polyglot api final PolyglotLanguage creator; // creator for internal contexts final Map creatorArguments; // special arguments for internal contexts final ContextWeakReference weakReference; @@ -176,6 +177,13 @@ static boolean isSingleContextAssumptionValid() { private final List childContexts = new ArrayList<>(); boolean inContextPreInitialization; // effectively final + volatile long volatileStatementCounter; + long statementCounter; + long elapsedTime; + final long statementLimit; + + static final AtomicLongFieldUpdater STATEMENT_COUNTER_UPDATER = AtomicLongFieldUpdater.newUpdater(PolyglotContextImpl.class, "volatileStatementCounter"); + /* Constructor for testing. */ private PolyglotContextImpl() { super(null); @@ -189,6 +197,7 @@ private PolyglotContextImpl() { this.creator = null; this.creatorArguments = null; this.weakReference = null; + this.statementLimit = 0; this.subProcesses = new HashSet<>(); } @@ -203,16 +212,16 @@ private PolyglotContextImpl() { this.creator = null; this.creatorArguments = Collections.emptyMap(); this.truffleContext = EngineAccessor.LANGUAGE.createTruffleContext(this); - this.polyglotBindings = new ConcurrentHashMap<>(); this.weakReference = new ContextWeakReference(this); this.contextImpls = new Object[engine.contextLength]; this.contexts = createContextArray(); if (!config.logLevels.isEmpty()) { EngineAccessor.LANGUAGE.configureLoggers(this, config.logLevels, getAllLoggers(engine)); } - PolyglotLanguageContext hostContext = getContextInitialized(engine.hostLanguage, null); - this.polyglotHostBindings = getAPIAccess().newValue(polyglotBindings, new PolyglotBindingsValue(hostContext)); this.subProcesses = new HashSet<>(); + this.statementLimit = config.limits != null ? config.limits.statementLimit : Long.MAX_VALUE - 1; + this.statementCounter = statementLimit; + this.volatileStatementCounter = statementLimit; notifyContextCreated(); PolyglotContextImpl.initializeStaticContext(this); } @@ -229,23 +238,27 @@ private PolyglotContextImpl() { this.engine = parent.engine; this.creator = creator.language; this.creatorArguments = langConfig; + this.statementLimit = 0; // inner context limit must not be used anyway this.weakReference = new ContextWeakReference(this); this.parent.addChildContext(this); this.truffleContext = spiContext; - this.polyglotBindings = new ConcurrentHashMap<>(); if (!parent.config.logLevels.isEmpty()) { EngineAccessor.LANGUAGE.configureLoggers(this, parent.config.logLevels, getAllLoggers(engine)); } this.contextImpls = new Object[engine.contextLength]; this.contexts = createContextArray(); - this.polyglotHostBindings = getAPIAccess().newValue(polyglotBindings, new PolyglotBindingsValue(getHostContext())); this.subProcesses = new HashSet<>(); // notifyContextCreated() is called after spiContext.impl is set to this. this.engine.noInnerContexts.invalidate(); initializeStaticContext(this); } + @Override + public void resetLimits() { + PolyglotLimits.reset(this); + } + private PolyglotLanguageContext[] createContextArray() { Collection languages = engine.idToLanguage.values(); PolyglotLanguageContext[] newContexts = new PolyglotLanguageContext[engine.contextLength]; @@ -348,11 +361,7 @@ private synchronized void addChildContext(PolyglotContextImpl child) { childContexts.add(child); } - static PolyglotContextImpl current() { - return currentEntered(null); - } - - private static PolyglotContextImpl currentEntered(PolyglotEngineImpl engine) { + static PolyglotContextImpl currentNotEntered() { SingleContextState singleContext = singleContextState; if (singleContext.singleContextAssumption.isValid()) { if (singleContext.contextThreadLocal.isSet()) { @@ -362,30 +371,33 @@ private static PolyglotContextImpl currentEntered(PolyglotEngineImpl engine) { return null; } } else { - ContextThreadLocal local = singleContext.contextThreadLocal; - if (engine != null && engine.singleThread.isValid()) { - return (PolyglotContextImpl) local.getNoThreadCheck(); - } else { - return (PolyglotContextImpl) local.get(); - } + return (PolyglotContextImpl) singleContext.contextThreadLocal.get(); } } - /** - * Must only be used to lookup the context if entered in an engine. - */ - static PolyglotContextImpl requireContextEntered(PolyglotEngineImpl engine) { - CompilerAsserts.partialEvaluationConstant(engine); - PolyglotContextImpl context = currentEntered(engine); - assert context != null : "No current context available."; - return context; + static PolyglotContextImpl currentEntered(PolyglotEngineImpl enteredInEngine) { + assert enteredInEngine != null; + CompilerAsserts.partialEvaluationConstant(enteredInEngine); + SingleContextState singleContext = singleContextState; + Object context; + if (singleContext.singleContextAssumption.isValid()) { + context = singleContext.singleContext; + } else { + ContextThreadLocal local = singleContext.contextThreadLocal; + context = local.getEntered(); + } + assert context != null; + if (CompilerDirectives.inCompiledCode()) { + context = enteredInEngine.castUnsafe.unsafeCast(context, PolyglotContextImpl.class, true, true, true); + } + return (PolyglotContextImpl) context; } /** * May be used anywhere to lookup the context. */ static PolyglotContextImpl requireContext() { - PolyglotContextImpl context = currentEntered(null); + PolyglotContextImpl context = currentNotEntered(); assert context != null : "No current context available."; return context; } @@ -393,7 +405,7 @@ static PolyglotContextImpl requireContext() { @Override public synchronized void explicitEnter(Context sourceContext) { checkCreatorAccess(sourceContext, "entered"); - Object prev = enter(); + Object prev = engine.enter(this); PolyglotThreadInfo current = getCurrentThreadInfo(); assert current.getThread() == Thread.currentThread(); current.explicitContextStack.addLast(prev); @@ -401,13 +413,18 @@ public synchronized void explicitEnter(Context sourceContext) { @Override public synchronized void explicitLeave(Context sourceContext) { + if (closed || closingThread == Thread.currentThread()) { + // explicit leaves if already closed are allowed. + // as close may automatically leave the context on threads. + return; + } checkCreatorAccess(sourceContext, "left"); PolyglotThreadInfo current = getCurrentThreadInfo(); LinkedList stack = current.explicitContextStack; if (stack.isEmpty() || current.getThread() == null) { throw new IllegalStateException("The context is not entered explicity. A context can only be left if it was previously entered."); } - leave(stack.removeLast()); + engine.leave(stack.removeLast(), this); } private void checkCreatorAccess(Context context, String operation) { @@ -416,73 +433,15 @@ private void checkCreatorAccess(Context context, String operation) { } } - boolean needsEnter() { - if (singleContextState.singleContextAssumption.isValid()) { - // if its a single context we know which one to enter - return !singleContextState.contextThreadLocal.isSet(); - } else { - return current() != this; - } - } - - PolyglotThreadInfo getCachedThreadInfo() { - return singleThreadedConstant.isValid() ? constantCurrentThreadInfo : currentThreadInfo; - } - - Object enterIfNeeded() { - if (needsEnter()) { - return enter(); - } - return NO_ENTER; - } - - void leaveIfNeeded(Object prev) { - if (prev != NO_ENTER) { - leave(prev); - } - } - - Object enter() { - Object context; - PolyglotThreadInfo info = getCachedThreadInfo(); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, info.getThread() == Thread.currentThread())) { - // fast-path -> same thread - context = singleContextState.contextThreadLocal.setReturnParent(this); - info.enter(); - } else { - // slow path -> changed thread - if (singleThreaded.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - context = enterThreadChanged(); - } - assert this == current(); - return context; - } - - void leave(Object prev) { - assert current() == this : "Cannot leave context that is currently not entered. Forgot to enter or leave a context?"; - PolyglotThreadInfo info = getCachedThreadInfo(); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, info.getThread() == Thread.currentThread())) { - info.leave(); - } else { - if (singleThreaded.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - leaveThreadChanged(); - } - singleContextState.contextThreadLocal.set(prev); - } - @TruffleBoundary PolyglotContextImpl enterThreadChanged() { Thread current = Thread.currentThread(); PolyglotContextImpl prev; boolean needsInitialization = false; synchronized (this) { - engine.checkState(); - checkClosed(); PolyglotThreadInfo threadInfo = getCurrentThreadInfo(); + checkClosed(); + engine.checkState(); assert threadInfo != null; threadInfo = threads.get(current); @@ -506,7 +465,7 @@ PolyglotContextImpl enterThreadChanged() { // enter the thread info already prev = (PolyglotContextImpl) singleContextState.contextThreadLocal.setReturnParent(this); - threadInfo.enter(); + threadInfo.enter(engine); if (transitionToMultiThreading) { // we need to verify that all languages give access @@ -519,7 +478,7 @@ PolyglotContextImpl enterThreadChanged() { } // never cache last thread on close or when closingThread - if (!closed && closing == null) { + if (!closed && closing == null && !invalid) { setCachedThreadInfo(threadInfo); } @@ -530,20 +489,12 @@ PolyglotContextImpl enterThreadChanged() { return prev; } - private void setCachedThreadInfo(PolyglotThreadInfo info) { + void setCachedThreadInfo(PolyglotThreadInfo info) { assert Thread.holdsLock(this); - // persist enteredCount from the current cached thread - if (constantCurrentThreadInfo != info) { - if (constantCurrentThreadInfo.getThread() == null) { - constantCurrentThreadInfo = info; - } else { - constantCurrentThreadInfo = PolyglotThreadInfo.NULL; - if (info != PolyglotThreadInfo.NULL) { - singleThreadedConstant.invalidate(); - } - } - } currentThreadInfo = info; + if (engine.singleThreadPerContext.isValid() && engine.singleContext.isValid()) { + constantCurrentThreadInfo = info; + } } private void checkAllThreadAccesses() { @@ -579,19 +530,22 @@ private void checkAllThreadAccesses() { } @TruffleBoundary - synchronized PolyglotThreadInfo leaveThreadChanged() { - Thread current = Thread.currentThread(); - setCachedThreadInfo(PolyglotThreadInfo.NULL); + PolyglotThreadInfo leaveThreadChanged() { + PolyglotThreadInfo info; + synchronized (this) { + Thread current = Thread.currentThread(); + setCachedThreadInfo(PolyglotThreadInfo.NULL); - PolyglotThreadInfo threadInfo = threads.get(current); - assert threadInfo != null; - PolyglotThreadInfo info = threadInfo; - if (cancelling && info.isLastActive()) { - notifyThreadClosed(); - } - info.leave(); - if (!closed && !cancelling) { - setCachedThreadInfo(threadInfo); + PolyglotThreadInfo threadInfo = threads.get(current); + assert threadInfo != null; + info = threadInfo; + if (cancelling && info.isLastActive()) { + notifyThreadClosed(); + } + info.leave(engine); + if (!closed && !cancelling && !invalid) { + setCachedThreadInfo(threadInfo); + } } return info; } @@ -604,6 +558,16 @@ private void initializeNewThread(Thread thread) { } } + long getStatementsExecuted() { + long count; + if (engine.singleThreadPerContext.isValid()) { + count = this.statementCounter; + } else { + count = this.volatileStatementCounter; + } + return statementLimit - count; + } + private void transitionToMultiThreaded() { assert singleThreaded.isValid(); assert Thread.holdsLock(this); @@ -613,9 +577,11 @@ private void transitionToMultiThreaded() { LANGUAGE.initializeMultiThreading(context.env); } } - engine.singleThread.invalidate(); + + long statementsExecuted = statementLimit - statementCounter; + STATEMENT_COUNTER_UPDATER.getAndAdd(this, -statementsExecuted); + engine.singleThreadPerContext.invalidate(); singleThreaded.invalidate(); - singleThreadedConstant.invalidate(); } private PolyglotThreadInfo createThreadInfo(Thread current) { @@ -684,13 +650,13 @@ public Value getBindings(String languageId) { PolyglotLanguage language = requirePublicLanguage(languageId); PolyglotLanguageContext languageContext = getContext(language); if (!languageContext.isInitialized()) { - Object prev = enterIfNeeded(); + Object prev = engine.enterIfNeeded(this); try { languageContext.ensureInitialized(null); } catch (Throwable e) { throw PolyglotImpl.wrapGuestException(languageContext, e); } finally { - leaveIfNeeded(prev); + engine.leaveIfNeeded(prev, this); } } return languageContext.getHostBindings(); @@ -699,10 +665,37 @@ public Value getBindings(String languageId) { @Override public Value getPolyglotBindings() { checkClosed(); - return this.polyglotHostBindings; + Value bindings = this.polyglotHostBindings; + if (bindings == null) { + initPolyglotBindings(); + bindings = this.polyglotHostBindings; + } + return bindings; + } + + public Map getPolyglotGuestBindings() { + Map bindings = this.polyglotBindings; + if (bindings == null) { + initPolyglotBindings(); + bindings = this.polyglotBindings; + } + return bindings; + } + + private void initPolyglotBindings() { + synchronized (this) { + if (this.polyglotBindings == null) { + this.polyglotBindings = new ConcurrentHashMap<>(); + this.polyglotHostBindings = getAPIAccess().newValue(polyglotBindings, new PolyglotBindingsValue(getHostContext())); + } + } } private void checkClosed() { + if (invalid && closingThread != Thread.currentThread()) { + // try closing if this is the last thread + throw PolyglotImpl.wrapGuestException(engine, new CancelExecution(null, invalidMessage)); + } if (closed) { throw new PolyglotIllegalStateException("The Context is already closed."); } @@ -790,13 +783,13 @@ public boolean initializeLanguage(String languageId) { PolyglotLanguageContext languageContext = getContext(language); languageContext.checkAccess(null); if (!languageContext.isInitialized()) { - Object prev = enterIfNeeded(); + Object prev = engine.enterIfNeeded(this); try { return languageContext.ensureInitialized(null); } catch (Throwable t) { throw PolyglotImpl.wrapGuestException(languageContext, t); } finally { - leaveIfNeeded(prev); + engine.leaveIfNeeded(prev, this); } } return false; @@ -805,7 +798,7 @@ public boolean initializeLanguage(String languageId) { @Override public Value eval(String languageId, Object sourceImpl) { PolyglotLanguage language = requirePublicLanguage(languageId); - Object prev = enterIfNeeded(); + Object prev = engine.enterIfNeeded(this); PolyglotLanguageContext languageContext = getContext(language); try { languageContext.checkAccess(null); @@ -826,7 +819,7 @@ public Value eval(String languageId, Object sourceImpl) { } catch (Throwable e) { throw PolyglotImpl.wrapGuestException(languageContext, e); } finally { - leaveIfNeeded(prev); + engine.leaveIfNeeded(prev, this); } } @@ -865,7 +858,7 @@ public void close(Context sourceContext, boolean cancelIfExecuting) { checkCreatorAccess(sourceContext, "closed"); boolean closeCompleted = closeImpl(cancelIfExecuting, cancelIfExecuting); if (cancelIfExecuting) { - engine.getCancelHandler().waitForClosing(Arrays.asList(this)); + engine.getCancelHandler().cancel(Arrays.asList(this)); } else if (!closeCompleted) { throw new PolyglotIllegalStateException(String.format("The context is currently executing on another thread. " + "Set cancelIfExecuting to true to stop the execution on this thread.")); @@ -1010,10 +1003,6 @@ boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { // triggers a thread changed event which requires slow path enter setCachedThreadInfo(PolyglotThreadInfo.NULL); - if (!threadInfo.explicitContextStack.isEmpty()) { - throw new IllegalStateException("The context is explicitely entered on the current thread. Call leave() before closing the context to resolve this."); - } - if (cancelIfExecuting) { cancelling = true; if (threadInfo != PolyglotThreadInfo.NULL) { @@ -1031,7 +1020,17 @@ boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { return false; } closingThread = Thread.currentThread(); + if (!threadInfo.explicitContextStack.isEmpty()) { + PolyglotContextImpl c = this; + while (!threadInfo.explicitContextStack.isEmpty()) { + Object prev = threadInfo.explicitContextStack.removeLast(); + engine.leave(prev, c); + c = (PolyglotContextImpl) prev; + } + threadInfo.explicitContextStack.clear(); + } closingLock.lock(); + break; } } @@ -1048,7 +1047,7 @@ boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { assert closingThread == Thread.currentThread(); assert closingLock.isHeldByCurrentThread() : "lock is acquired"; assert !closed; - Object prev = enter(); + Object prev = engine.enter(this); try { closeChildContexts(cancelIfExecuting, waitForPolyglotThreads); @@ -1062,7 +1061,7 @@ boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { success = true; } finally { synchronized (this) { - leave(prev); + engine.leave(prev, this); if (success) { remainingThreads = threads.keySet().toArray(new Thread[0]); } @@ -1211,7 +1210,7 @@ boolean patch(PolyglotContextConfig newConfig) { if (!newConfig.logLevels.isEmpty()) { EngineAccessor.LANGUAGE.configureLoggers(this, newConfig.logLevels, getAllLoggers(engine)); } - final Object prev = enter(); + final Object prev = engine.enter(this); try { for (int i = 1; i < this.contexts.length; i++) { final PolyglotLanguageContext context = this.contexts[i]; @@ -1220,7 +1219,7 @@ boolean patch(PolyglotContextConfig newConfig) { } } } finally { - leave(prev); + engine.leave(prev, this); } return true; } @@ -1255,7 +1254,7 @@ static PolyglotContextImpl preInitialize(final PolyglotEngineImpl engine) { allowedLanguages, Collections.emptyMap(), fs, internalFs, engine.logHandler, false, null, - EnvironmentAccess.INHERIT, null, null); + EnvironmentAccess.INHERIT, null, null, null); final PolyglotContextImpl context = new PolyglotContextImpl(engine, config); try { final String oldOption = engine.engineOptionValues.get(PolyglotEngineOptions.PreinitializeContexts); @@ -1272,7 +1271,7 @@ static PolyglotContextImpl preInitialize(final PolyglotEngineImpl engine) { Collections.addAll(languagesToPreinitialize, optionValue.split(",")); context.inContextPreInitialization = true; try { - Object prev = context.enter(); + Object prev = context.engine.enter(context); try { for (String languageId : engine.getLanguages().keySet()) { if (languagesToPreinitialize.contains(languageId)) { @@ -1287,7 +1286,7 @@ static PolyglotContextImpl preInitialize(final PolyglotEngineImpl engine) { language.clearOptionValues(); } } finally { - context.leave(prev); + context.engine.leave(prev, context); } } finally { context.inContextPreInitialization = false; @@ -1308,6 +1307,26 @@ static PolyglotContextImpl preInitialize(final PolyglotEngineImpl engine) { } } + synchronized long getTimeActive() { + long timeExecuted = 0; + Collection polyglotThreads = getSeenThreads().values(); + for (PolyglotThreadInfo threadInfo : polyglotThreads) { + timeExecuted += threadInfo.getTimeExecuted(); + } + return timeExecuted; + } + + synchronized void resetTiming() { + Collection polyglotThreads = getSeenThreads().values(); + for (PolyglotThreadInfo threadInfo : polyglotThreads) { + threadInfo.resetTiming(); + } + } + + PolyglotThreadInfo getCachedThreadInfo(boolean isConstant) { + return isConstant ? constantCurrentThreadInfo : currentThreadInfo; + } + private static Object[] getAllLoggers(PolyglotEngineImpl engine) { Object defaultLoggers = EngineAccessor.LANGUAGE.getDefaultLoggers(); Object engineLoggers = engine.getEngineLoggers(); @@ -1325,4 +1344,18 @@ static class ContextWeakReference extends WeakReference { } + synchronized boolean invalidate(String message) { + if (!invalid) { + setCachedThreadInfo(PolyglotThreadInfo.NULL); + /* + * Setting the invalid message and invalid flag will cause a special invalid message + * when the context was disabled. + */ + invalidMessage = message; + invalid = true; + return true; + } + return false; + } + } 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 88e7af5a3f4f..6a9589c033c8 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 @@ -105,6 +105,7 @@ import com.oracle.truffle.api.nodes.LanguageInfo; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.polyglot.PolyglotContextImpl.ContextWeakReference; +import com.oracle.truffle.polyglot.PolyglotLimits.EngineLimits; final class PolyglotEngineImpl extends AbstractPolyglotImpl.AbstractEngineImpl implements com.oracle.truffle.polyglot.PolyglotImpl.VMObject { @@ -157,8 +158,9 @@ final class PolyglotEngineImpl extends AbstractPolyglotImpl.AbstractEngineImpl i PolyglotLanguage hostLanguage; final Assumption singleContext = Truffle.getRuntime().createAssumption("Single context per engine."); - final Assumption singleThread = Truffle.getRuntime().createAssumption("Single thread per engine."); + final Assumption singleThreadPerContext = Truffle.getRuntime().createAssumption("Single thread per context of an engine."); final Assumption noInnerContexts = Truffle.getRuntime().createAssumption("No inner contexts."); + final Assumption noThreadTimingNeeded = Truffle.getRuntime().createAssumption("No enter timing needed."); volatile OptionDescriptors allOptions; volatile boolean closed; @@ -173,6 +175,7 @@ final class PolyglotEngineImpl extends AbstractPolyglotImpl.AbstractEngineImpl i final CastUnsafe castUnsafe; final int contextLength; + private volatile EngineLimits limits; PolyglotEngineImpl(PolyglotImpl impl, DispatchOutputStream out, DispatchOutputStream err, InputStream in, Map options, boolean allowExperimentalOptions, boolean useSystemProperties, ClassLoader contextClassLoader, boolean boundEngine, @@ -848,7 +851,7 @@ synchronized void ensureClosed(boolean cancelIfExecuting, boolean ignoreCloseFai } } if (cancelIfExecuting) { - getCancelHandler().waitForClosing(localContexts); + getCancelHandler().cancel(localContexts); } if (!boundEngine && !stillRunning) { @@ -898,7 +901,7 @@ synchronized void ensureClosed(boolean cancelIfExecuting, boolean ignoreCloseFai } } - private List collectAliveContexts() { + List collectAliveContexts() { Thread.holdsLock(this); List localContexts = new ArrayList<>(contexts.size()); for (ContextWeakReference ref : contexts) { @@ -1059,7 +1062,7 @@ final class CancelHandler { this.instrumenter = (Instrumenter) INSTRUMENT.getEngineInstrumenter(instrumentationHandler); } - void waitForClosing(List localContexts) { + void cancel(List localContexts) { boolean cancelling = false; for (PolyglotContextImpl context : localContexts) { if (context.cancelling) { @@ -1067,10 +1070,8 @@ void waitForClosing(List localContexts) { break; } } - if (cancelling) { enableCancel(); - try { for (PolyglotContextImpl context : localContexts) { context.sendInterrupt(); @@ -1084,7 +1085,7 @@ void waitForClosing(List localContexts) { } } - private synchronized void enableCancel() { + synchronized void enableCancel() { if (cancellationBinding == null) { cancellationBinding = instrumenter.attachExecutionEventListener(SourceSectionFilter.ANY, new ExecutionEventListener() { public void onReturnValue(EventContext context, VirtualFrame frame, Object result) { @@ -1092,7 +1093,9 @@ public void onReturnValue(EventContext context, VirtualFrame frame, Object resul } public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) { - cancelExecution(context); + if (!(exception instanceof CancelExecution)) { + cancelExecution(context); + } } public void onEnter(EventContext context, VirtualFrame frame) { @@ -1102,8 +1105,8 @@ public void onEnter(EventContext context, VirtualFrame frame) { @TruffleBoundary private void cancelExecution(EventContext eventContext) { PolyglotContextImpl context = PolyglotContextImpl.requireContext(); - if (context.cancelling) { - throw new CancelExecution(eventContext); + if (context.invalid || context.cancelling) { + throw new CancelExecution(eventContext, context.invalidMessage); } } }); @@ -1124,12 +1127,14 @@ private synchronized void disableCancel() { } @SuppressWarnings("serial") - private static final class CancelExecution extends ThreadDeath implements TruffleException { + static final class CancelExecution extends ThreadDeath implements TruffleException { private final Node node; + private final String cancelMessage; - CancelExecution(EventContext context) { - this.node = context.getInstrumentedNode(); + CancelExecution(EventContext context, String cancelMessage) { + this.node = context != null ? context.getInstrumentedNode() : null; + this.cancelMessage = cancelMessage; } public Node getLocation() { @@ -1138,7 +1143,11 @@ public Node getLocation() { @Override public String getMessage() { - return "Execution got cancelled."; + if (cancelMessage == null) { + return "Execution got cancelled."; + } else { + return cancelMessage; + } } public boolean isCancelled() { @@ -1192,7 +1201,7 @@ public synchronized Context createContext(OutputStream configOut, OutputStream c PolyglotAccess polyglotAccess, 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) { + EnvironmentAccess environmentAccess, Map environment, ZoneId zone, Object limitsImpl) { checkState(); if (boundEngine && preInitializedContext == null && !contexts.isEmpty()) { throw new IllegalArgumentException("Automatically created engines cannot be used to create more than one context. " + @@ -1258,11 +1267,15 @@ public synchronized Context createContext(OutputStream configOut, OutputStream c if (!ALLOW_ENVIRONMENT_ACCESS && environmentAccess != EnvironmentAccess.NONE) { throw new IllegalArgumentException("Cannot allow EnvironmentAccess because the privilege is removed at image build time"); } + PolyglotLimits polyglotLimits = (PolyglotLimits) limitsImpl; + if (limits != null) { + limits.validate(polyglotLimits); + } 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); + environmentAccess, environment, zone, polyglotLimits); PolyglotContextImpl context = loadPreinitializedContext(config); if (context == null) { @@ -1274,6 +1287,14 @@ public synchronized Context createContext(OutputStream configOut, OutputStream c assert contexts.contains(context.weakReference); } + if (polyglotLimits != null) { + EngineLimits l = this.limits; + if (l == null) { + this.limits = l = new EngineLimits(this); + } + l.initialize(polyglotLimits, context); + } + Context api = impl.getAPIAccess().newContext(context); context.creatorApi = api; context.currentApi = impl.getAPIAccess().newContext(context); @@ -1351,4 +1372,71 @@ Supplier>> getFil } return res; } + + private static final Object NO_ENTER = new Object(); + + @SuppressWarnings("static-method") + boolean needsEnter(PolyglotContextImpl context) { + if (PolyglotContextImpl.singleContextState.singleContextAssumption.isValid()) { + // if its a single context we know which one to enter + return !PolyglotContextImpl.singleContextState.contextThreadLocal.isSet(); + } else { + return PolyglotContextImpl.currentNotEntered() != context; + } + } + + Object enterIfNeeded(PolyglotContextImpl context) { + if (needsEnter(context)) { + return enter(context); + } + assert PolyglotContextImpl.requireContext() != null; + return NO_ENTER; + } + + void leaveIfNeeded(Object prev, PolyglotContextImpl context) { + if (prev != NO_ENTER) { + leave(prev, context); + } + } + + Object enter(PolyglotContextImpl context) { + Object prev; + PolyglotThreadInfo info = getCachedThreadInfo(context); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, info.getThread() == Thread.currentThread())) { + // fast-path -> same thread + prev = PolyglotContextImpl.singleContextState.contextThreadLocal.setReturnParent(context); + info.enter(this); + } else { + // slow path -> changed thread + if (singleThreadPerContext.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + prev = context.enterThreadChanged(); + } + assert context == PolyglotContextImpl.currentNotEntered(); + return prev; + } + + void leave(Object prev, PolyglotContextImpl polyglotContext) { + assert polyglotContext.closed || polyglotContext.closingThread == Thread.currentThread() || + PolyglotContextImpl.currentNotEntered() == polyglotContext : "Cannot leave context that is currently not entered. Forgot to enter or leave a context?"; + PolyglotThreadInfo info = getCachedThreadInfo(polyglotContext); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, info.getThread() == Thread.currentThread())) { + info.leave(this); + } else { + if (singleThreadPerContext.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + polyglotContext.leaveThreadChanged(); + } + PolyglotContextImpl.singleContextState.contextThreadLocal.set(prev); + } + + PolyglotThreadInfo getCachedThreadInfo(PolyglotContextImpl context) { + if (singleThreadPerContext.isValid() && singleContext.isValid()) { + return context.getCachedThreadInfo(true); + } else { + return context.getCachedThreadInfo(false); + } + } } 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 3f80c193067e..a07fc3bc8186 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 @@ -45,11 +45,13 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Path; +import java.time.Duration; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.logging.Handler; @@ -58,6 +60,7 @@ import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.HostAccess; import org.graalvm.polyglot.PolyglotException; +import org.graalvm.polyglot.ResourceLimitEvent; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.impl.AbstractPolyglotImpl; import org.graalvm.polyglot.io.MessageTransport; @@ -93,7 +96,7 @@ public Throwable fillInStackTrace() { private final PolyglotSource sourceImpl = new PolyglotSource(this); private final PolyglotSourceSection sourceSectionImpl = new PolyglotSourceSection(this); - private final PolyglotExecutionListener executionListenerImpl = new PolyglotExecutionListener(this); + private final PolyglotManagement executionListenerImpl = new PolyglotManagement(this); private final AtomicReference preInitializedEngineRef = new AtomicReference<>(); final Map, PolyglotValue> primitiveValues = new HashMap<>(); @@ -113,6 +116,18 @@ protected void initialize() { disconnectedHostValue = new PolyglotValue.HostValue(this); } + @Override + public Context getLimitEventContext(Object impl) { + return (Context) impl; + } + + @Override + public Object buildLimits(long statementLimit, Predicate statementLimitSourceFilter, + Duration timeLimit, Duration timeLimitAccuracy, + Consumer onLimit) { + return new PolyglotLimits(statementLimit, statementLimitSourceFilter, timeLimit, timeLimitAccuracy, onLimit); + } + /** * Internal method do not use. */ @@ -133,7 +148,7 @@ public AbstractSourceSectionImpl getSourceSectionImpl() { * Internal method do not use. */ @Override - public AbstractExecutionListenerImpl getExecutionListenerImpl() { + public AbstractManagementImpl getManagementImpl() { return executionListenerImpl; } @@ -142,7 +157,7 @@ public AbstractExecutionListenerImpl getExecutionListenerImpl() { */ @Override public Context getCurrentContext() { - PolyglotContextImpl context = PolyglotContextImpl.current(); + PolyglotContextImpl context = PolyglotContextImpl.currentNotEntered(); if (context == null) { return super.getCurrentContext(); } @@ -248,7 +263,7 @@ public Object newTargetTypeMapping(Class sourceType, Class targetTy @Override @TruffleBoundary public Value asValue(Object hostValue) { - PolyglotContextImpl currentContext = PolyglotContextImpl.current(); + PolyglotContextImpl currentContext = PolyglotContextImpl.currentNotEntered(); if (currentContext != null) { // if we are currently entered in a context just use it and bind the value to it. return currentContext.asValue(hostValue); 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 8fa35dcfd451..33fb3d3fa0c4 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 @@ -104,7 +104,7 @@ final class Lazy { this.languageInstance = languageInstance; this.sourceCache = languageInstance.getSourceCache(); this.activePolyglotThreads = new HashSet<>(); - this.polyglotGuestBindings = new PolyglotBindings(PolyglotLanguageContext.this, context.polyglotBindings); + this.polyglotGuestBindings = new PolyglotBindings(PolyglotLanguageContext.this); this.uncaughtExceptionHandler = new PolyglotUncaughtExceptionHandler(); this.valueCache = new ConcurrentHashMap<>(); this.accessibleInternalLanguages = computeAccessibleLanguages(config, true); @@ -290,14 +290,14 @@ Value getHostBindings() { if (this.hostBindings == null) { synchronized (this) { if (this.hostBindings == null) { - Object prev = context.enterIfNeeded(); + Object prev = context.engine.enterIfNeeded(context); try { Iterable scopes = LANGUAGE.findTopScopes(env); this.hostBindings = this.asValue(PolyglotLanguageBindings.create(scopes)); } catch (Throwable t) { throw PolyglotImpl.wrapGuestException(this, t); } finally { - context.leaveIfNeeded(prev); + context.engine.leaveIfNeeded(prev, context); } } } @@ -348,7 +348,7 @@ boolean dispose() { Env localEnv = this.env; if (localEnv != null) { if (!lazy.activePolyglotThreads.isEmpty()) { - throw new AssertionError("The language did not complete all polyglot threads but should have: " + lazy.activePolyglotThreads); + throw new IllegalStateException("The language did not complete all polyglot threads but should have: " + lazy.activePolyglotThreads); } for (PolyglotThreadInfo threadInfo : context.getSeenThreads().values()) { assert threadInfo != PolyglotThreadInfo.NULL; @@ -377,7 +377,7 @@ Object enterThread(PolyglotThread thread) { assert Thread.currentThread() == thread; synchronized (context) { lazy.activePolyglotThreads.add(thread); - return context.enter(); + return context.engine.enter(context); } } @@ -397,7 +397,7 @@ void leaveThread(Object prev, PolyglotThread thread) { } } lazy.activePolyglotThreads.remove(thread); - context.leave(prev); + context.engine.leave(prev, context); seenThreads.remove(thread); } EngineAccessor.INSTRUMENT.notifyThreadFinished(context.engine, context.truffleContext, thread); @@ -767,12 +767,17 @@ Value asValue(Object guestValue) { synchronized PolyglotValue lookupValueCache(Object guestValue) { assert toGuestValue(guestValue) == guestValue : "Not a valid guest value: " + guestValue + ". Only interop values are allowed to be exported."; - PolyglotValue cache = lazy.valueCache.computeIfAbsent(guestValue.getClass(), new Function, PolyglotValue>() { - public PolyglotValue apply(Class t) { - return PolyglotValue.createInteropValue(PolyglotLanguageContext.this, (TruffleObject) guestValue, guestValue.getClass()); - } - }); - return cache; + Object prev = context.engine.enterIfNeeded(context); + try { + PolyglotValue cache = lazy.valueCache.computeIfAbsent(guestValue.getClass(), new Function, PolyglotValue>() { + public PolyglotValue apply(Class t) { + return PolyglotValue.createInteropValue(PolyglotLanguageContext.this, (TruffleObject) guestValue, guestValue.getClass()); + } + }); + return cache; + } finally { + context.engine.leaveIfNeeded(prev, context); + } } static final class ToHostValueNode { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java new file mode 100644 index 000000000000..cc0457cda4b1 --- /dev/null +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2019, 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 java.lang.management.ManagementFactory; +import java.lang.ref.WeakReference; +import java.time.Duration; +import java.util.TimerTask; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import org.graalvm.polyglot.ResourceLimitEvent; +import org.graalvm.polyglot.ResourceLimits; +import org.graalvm.polyglot.Source; + +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.TruffleOptions; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.FrameSlot; +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.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.StatementTag; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.polyglot.PolyglotEngineImpl.CancelExecution; + +/** + * Limits objects that backs the {@link ResourceLimits} API object. + */ +final class PolyglotLimits { + + final long statementLimit; + final Predicate statementLimitSourcePredicate; + final Duration timeLimit; + final Duration timeAccuracy; + final Consumer onEvent; + + PolyglotLimits(long statementLimit, Predicate statementLimitSourcePredicate, Duration timeLimit, Duration timeAccuracy, Consumer onEvent) { + this.statementLimit = statementLimit; + this.statementLimitSourcePredicate = statementLimitSourcePredicate; + this.timeLimit = timeLimit; + this.timeAccuracy = timeAccuracy; + this.onEvent = onEvent; + } + + static void reset(PolyglotContextImpl context) { + synchronized (context) { + PolyglotLimits limits = context.config.limits; + if (limits != null && limits.timeLimit != null) { + context.resetTiming(); + } + context.statementCounter = context.statementLimit; + context.volatileStatementCounter = context.statementLimit; + } + } + + static final Object CACHED_CONTEXT = new Object() { + @Override + public String toString() { + return "$$$cached_context$$$"; + } + }; + + static final class StatementIncrementNode extends ExecutionEventNode { + + final EngineLimits limits; + final EventContext eventContext; + final PolyglotEngineImpl engine; + final FrameSlot readContext; + final ConditionProfile needsLookup = ConditionProfile.createBinaryProfile(); + final FrameDescriptor descriptor; + @CompilationFinal private boolean seenInnerContext; + + StatementIncrementNode(EventContext context, EngineLimits limits) { + this.limits = limits; + this.eventContext = context; + this.engine = limits.engine; + if (!engine.singleThreadPerContext.isValid() || !engine.singleContext.isValid()) { + descriptor = context.getInstrumentedNode().getRootNode().getFrameDescriptor(); + readContext = descriptor.findOrAddFrameSlot(CACHED_CONTEXT, FrameSlotKind.Object); + } else { + readContext = null; + descriptor = null; + } + } + + @Override + protected void onEnter(VirtualFrame frame) { + PolyglotContextImpl currentContext; + if (readContext == null || frame.getFrameDescriptor() != descriptor) { + currentContext = getLimitContext(); + } else { + try { + Object readValue = frame.getObject(readContext); + if (needsLookup.profile(readValue == descriptor.getDefaultValue())) { + currentContext = getLimitContext(); + frame.setObject(readContext, currentContext); + } else { + currentContext = (PolyglotContextImpl) readValue; + } + } catch (FrameSlotTypeException e) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + currentContext = getLimitContext(); + frame.setObject(readContext, currentContext); + } + } + + long count; + if (engine.singleThreadPerContext.isValid()) { + count = --currentContext.statementCounter; + } else { + count = PolyglotContextImpl.STATEMENT_COUNTER_UPDATER.decrementAndGet(currentContext); + } + if (count < 0) { // overflowed + CompilerDirectives.transferToInterpreterAndInvalidate(); + notifyStatementLimitReached(currentContext, currentContext.statementLimit - count, currentContext.statementLimit); + } + } + + private PolyglotContextImpl getLimitContext() { + PolyglotContextImpl context = PolyglotContextImpl.currentEntered(engine); + if (engine.noInnerContexts.isValid() || context.parent == null) { + // fast path for no inner contexts + return context; + } + if (!seenInnerContext) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + seenInnerContext = true; + } + while (context.parent != null) { + context = context.parent; + } + return context; + } + + private void notifyStatementLimitReached(PolyglotContextImpl context, long actualCount, long limit) { + boolean limitReached = false; + synchronized (context) { + // reset statement counter + if (limits.engine.singleThreadPerContext.isValid()) { + if (context.statementCounter < 0) { + context.statementCounter = limit; + limitReached = true; + } + } else { + if (context.volatileStatementCounter < 0) { + context.volatileStatementCounter = limit; + limitReached = true; + } + } + } + if (limitReached) { + String message = String.format("Statement count limit of %s exceeded. Statements executed %s.", + limit, actualCount); + boolean invalidated = context.invalidate(message); + if (invalidated) { + context.close(context.creatorApi, true); + RuntimeException e = limits.notifyEvent(context); + if (e != null) { + throw e; + } + throw new CancelExecution(eventContext, message); + } + } + + } + + } + + static final class TimeLimitChecker extends TimerTask { + + private final WeakReference contextRef; + private final long timeLimitNS; + + TimeLimitChecker(PolyglotContextImpl context) { + this.contextRef = new WeakReference<>(context); + this.timeLimitNS = context.config.limits.timeLimit.toNanos(); + } + + @Override + public void run() { + PolyglotContextImpl context = contextRef.get(); + if (context == null || context.closed) { + cancel(); + return; + } + long timeActiveNS = context.getTimeActive(); + if (timeActiveNS > timeLimitNS) { + if (!context.invalid) { + String message = String.format("Time resource limit of %sms exceeded. Time executed %sms.", + context.config.limits.timeLimit.toMillis(), + Duration.ofNanos(timeActiveNS).toMillis()); + boolean invalidated = context.invalidate(message); + /* + * We immediately set the context invalid so it can no longer be entered. The + * cancel executor closes the context on a parallel thread and closes the + * context properly. If necessary the cancel instrumentation needs to be + * restored after the context was successfully cancelled so we need a thread + * that waits for the cancel to be complete. + */ + if (invalidated) { + EngineLimits.getCancelExecutor().submit(new Runnable() { + public void run() { + context.close(context.creatorApi, true); + } + }); + } + } + } + } + } + + /** + * Resource limit related data for each engine. Lazily constructed. + */ + static final class EngineLimits { + + private static volatile ScheduledThreadPoolExecutor limitExecutor; + private static volatile ThreadPoolExecutor cancelExecutor; + + private static final Predicate NO_PREDICATE = new Predicate() { + public boolean test(Source t) { + return true; + } + }; + + final PolyglotEngineImpl engine; + @CompilationFinal boolean timeLimitEnabled; + @CompilationFinal long statementLimit = -1; + @CompilationFinal Assumption sameStatementLimit; + @CompilationFinal Predicate statementLimitSourcePredicate; + EventBinding statementLimitBinding; + + EngineLimits(PolyglotEngineImpl engine) { + this.engine = engine; + } + + void validate(PolyglotLimits limits) { + Predicate newPredicate = limits != null ? limits.statementLimitSourcePredicate : null; + if (newPredicate == null) { + newPredicate = NO_PREDICATE; + } + if (this.statementLimitSourcePredicate != null && newPredicate != statementLimitSourcePredicate) { + throw new IllegalArgumentException("Using multiple source predicates per engine is not supported. " + + "The same statement limit source predicate must be used for all polyglot contexts that are assigned to the same engine. " + + "Resolve this by using the same predicate instance when constructing the limits object with ResourceLimits.Builder.statementLimit(long, Predicate)."); + } + + if (limits != null && limits.timeLimit != null) { + long time = -1; + RuntimeException cause = null; + if (!TruffleOptions.AOT) { + // SVM support GR-10551 + try { + ManagementFactory.getThreadMXBean().setThreadCpuTimeEnabled(true); + time = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime(); + } catch (UnsupportedOperationException e) { + // fallthrough not supported + cause = e; + } + } + if (time == -1) { + throw new UnsupportedOperationException("ThreadMXBean.getCurrentThreadCpuTime() is not supported or enabled by the host VM but required for time limits.", cause); + } + } + } + + void initialize(PolyglotLimits limits, PolyglotContextImpl context) { + assert Thread.holdsLock(engine); + Predicate newPredicate = limits.statementLimitSourcePredicate; + if (newPredicate == null) { + newPredicate = NO_PREDICATE; + } + if (this.statementLimitSourcePredicate == null) { + this.statementLimitSourcePredicate = newPredicate; + } + // ensured by validate + assert this.statementLimitSourcePredicate == newPredicate; + + if (limits.statementLimit != 0) { + Assumption sameLimit = this.sameStatementLimit; + if (sameLimit != null && sameLimit.isValid() && limits.statementLimit != statementLimit) { + sameLimit.invalidate(); + } else if (sameLimit == null) { + this.sameStatementLimit = Truffle.getRuntime().createAssumption("Same statement limit."); + this.statementLimit = limits.statementLimit; + } + + if (statementLimitBinding == null) { + Instrumenter instrumenter = (Instrumenter) EngineAccessor.INSTRUMENT.getEngineInstrumenter(engine.instrumentationHandler); + SourceSectionFilter.Builder filter = SourceSectionFilter.newBuilder().tagIs(StatementTag.class); + if (statementLimitSourcePredicate != null) { + filter.sourceIs(new SourcePredicate() { + @Override + public boolean test(com.oracle.truffle.api.source.Source s) { + try { + return statementLimitSourcePredicate.test(engine.getImpl().getPolyglotSource(s)); + } catch (Throwable e) { + throw new HostException(e); + } + } + }); + } + statementLimitBinding = instrumenter.attachExecutionEventFactory(filter.build(), new ExecutionEventNodeFactory() { + public ExecutionEventNode create(EventContext eventContext) { + return new StatementIncrementNode(eventContext, EngineLimits.this); + } + }); + } + } + if (limits.timeLimit != null) { + engine.noThreadTimingNeeded.invalidate(); + long timeLimitMillis = limits.timeLimit.toMillis(); + assert timeLimitMillis > 0; // needs to verified before + TimeLimitChecker task = new TimeLimitChecker(context); + long accuracy = Math.max(1, limits.timeAccuracy.toMillis()); + getLimitTimer().scheduleAtFixedRate(task, accuracy, accuracy, TimeUnit.MILLISECONDS); + } + + reset(context); + } + + long getStatementLimit() { + return statementLimit; + } + + RuntimeException notifyEvent(PolyglotContextImpl context) { + PolyglotLimits limits = context.config.limits; + if (limits == null) { + return null; + } + Consumer onEvent = limits.onEvent; + if (onEvent == null) { + return null; + } + try { + onEvent.accept(engine.getImpl().getAPIAccess().newResourceLimitsEvent(context.creatorApi)); + } catch (Throwable t) { + return PolyglotImpl.wrapHostException(context, t); + } + return null; + } + + static ExecutorService getCancelExecutor() { + ThreadPoolExecutor executor = cancelExecutor; + if (executor == null) { + synchronized (EngineLimits.class) { + executor = cancelExecutor; + if (executor == null) { + cancelExecutor = executor = (ThreadPoolExecutor) Executors.newCachedThreadPool( + new HighPriorityThreadFactory("Polyglot Cancel Thread")); + } + } + } + return executor; + } + + static ScheduledExecutorService getLimitTimer() { + ScheduledThreadPoolExecutor executor = limitExecutor; + if (executor == null) { + synchronized (EngineLimits.class) { + executor = limitExecutor; + if (executor == null) { + executor = new ScheduledThreadPoolExecutor(0, new HighPriorityThreadFactory("Polyglot Limit Timer")); + executor.setKeepAliveTime(1, TimeUnit.SECONDS); + limitExecutor = executor; + } + } + } + return executor; + } + + static final class HighPriorityThreadFactory implements ThreadFactory { + private final AtomicLong threadCounter = new AtomicLong(); + private final String baseName; + + HighPriorityThreadFactory(String baseName) { + this.baseName = baseName; + } + + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setName(baseName + "-" + threadCounter.incrementAndGet()); + t.setPriority(Thread.MAX_PRIORITY); + return t; + } + + } + } + +} diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLogHandler.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLogHandler.java index 648ecb6c7869..eb2945878f5d 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLogHandler.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLogHandler.java @@ -99,7 +99,7 @@ private static Handler findDelegate() { } static PolyglotContextImpl getCurrentOuterContext() { - PolyglotContextImpl currentContext = PolyglotContextImpl.current(); + PolyglotContextImpl currentContext = PolyglotContextImpl.currentNotEntered(); if (currentContext != null) { while (currentContext.parent != null) { currentContext = currentContext.parent; @@ -179,7 +179,7 @@ private ImmutableLogRecord(final Level level, final String loggerName, final Str Object[] copy = parameters; if (parameters != null && parameters.length > 0) { copy = new Object[parameters.length]; - final PolyglotContextImpl context = PolyglotContextImpl.current(); + final PolyglotContextImpl context = PolyglotContextImpl.currentNotEntered(); for (int i = 0; i < parameters.length; i++) { copy[i] = safeValue(parameters[i], context); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExecutionListener.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotManagement.java similarity index 94% rename from truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExecutionListener.java rename to truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotManagement.java index 3efcf61873e9..c3f50f297a8b 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotExecutionListener.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotManagement.java @@ -51,8 +51,8 @@ import org.graalvm.polyglot.Source; import org.graalvm.polyglot.SourceSection; import org.graalvm.polyglot.Value; -import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractExecutionListenerImpl; -import org.graalvm.polyglot.impl.AbstractPolyglotImpl.MonitoringAccess; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractManagementImpl; +import org.graalvm.polyglot.impl.AbstractPolyglotImpl.ManagementAccess; import org.graalvm.polyglot.management.ExecutionEvent; import com.oracle.truffle.api.CompilerDirectives; @@ -70,21 +70,23 @@ import com.oracle.truffle.api.instrumentation.Tag; import com.oracle.truffle.api.nodes.RootNode; -final class PolyglotExecutionListener extends AbstractExecutionListenerImpl { +final class PolyglotManagement extends AbstractManagementImpl { static final Object[] EMPTY_ARRAY = new Object[0]; private final PolyglotImpl engineImpl; - PolyglotExecutionListener(PolyglotImpl engineImpl) { + PolyglotManagement(PolyglotImpl engineImpl) { super(engineImpl); this.engineImpl = engineImpl; } + // implementation for org.graalvm.polyglot.management.ExecutionListener + @Override public Object attachExecutionListener(Engine engineAPI, Consumer onEnter, Consumer onReturn, boolean expressions, boolean statements, boolean roots, Predicate sourceFilter, Predicate rootFilter, boolean collectInputValues, boolean collectReturnValues, boolean collectExceptions) { - PolyglotEngineImpl engine = (PolyglotEngineImpl) engineImpl.getAPIAccess().getImpl(engineAPI); + PolyglotEngineImpl engine = getEngine(engineAPI); Instrumenter instrumenter = (Instrumenter) EngineAccessor.INSTRUMENT.getEngineInstrumenter(engine.instrumentationHandler); List> tags = new ArrayList<>(); @@ -188,7 +190,7 @@ public void closeExecutionListener(Object impl) { } @Override - public List getInputValues(Object impl) { + public List getExecutionEventInputValues(Object impl) { try { return ((Event) impl).getInputValues(); } catch (Throwable t) { @@ -197,7 +199,7 @@ public List getInputValues(Object impl) { } @Override - public String getRootName(Object impl) { + public String getExecutionEventRootName(Object impl) { try { return ((Event) impl).getRootName(); } catch (Throwable t) { @@ -206,7 +208,7 @@ public String getRootName(Object impl) { } @Override - public Value getReturnValue(Object impl) { + public Value getExecutionEventReturnValue(Object impl) { try { return ((Event) impl).getReturnValue(); } catch (Throwable t) { @@ -215,27 +217,27 @@ public Value getReturnValue(Object impl) { } @Override - public SourceSection getLocation(Object impl) { + public SourceSection getExecutionEventLocation(Object impl) { return ((Event) impl).getLocation(); } @Override - public PolyglotException getException(Object impl) { + public PolyglotException getExecutionEventException(Object impl) { return ((Event) impl).getException(); } @Override - public boolean isExpression(Object impl) { + public boolean isExecutionEventExpression(Object impl) { return hasTag(impl, StandardTags.ExpressionTag.class); } @Override - public boolean isStatement(Object impl) { + public boolean isExecutionEventStatement(Object impl) { return hasTag(impl, StandardTags.StatementTag.class); } @Override - public boolean isRoot(Object impl) { + public boolean isExecutionEventRoot(Object impl) { return hasTag(impl, StandardTags.RootTag.class); } @@ -260,7 +262,7 @@ static class ListenerImpl { final PolyglotEngineImpl engine; final Consumer onEnter; final Consumer onReturn; - final MonitoringAccess monitoring; + final ManagementAccess management; final boolean collectInputValues; final boolean collectReturnValues; final boolean collectExceptions; @@ -277,7 +279,7 @@ static class ListenerImpl { this.onEnter = onEnter; this.onReturn = onReturn; // monitoring is not final so we need to pull it out into a final field - this.monitoring = engine.impl.getMonitoring(); + this.management = engine.impl.getManagement(); this.collectInputValues = collectInputValues; this.collectReturnValues = collectReturnValues; this.collectExceptions = collectExceptions; @@ -478,7 +480,7 @@ private void invokeReturnAllocate(Object[] inputValues, Object result) { @TruffleBoundary(allowInlining = true) protected final void invokeExceptionAllocate(List inputValues, Throwable e) { PolyglotException ex = e != null ? PolyglotImpl.wrapGuestException(language.getCurrentLanguageContext(), e) : null; - config.onReturn.accept(config.monitoring.newExecutionEvent(new DynamicEvent(this, inputValues, null, ex))); + config.onReturn.accept(config.management.newExecutionEvent(new DynamicEvent(this, inputValues, null, ex))); } } @@ -524,7 +526,7 @@ abstract static class AbstractNode extends ExecutionEventNode implements Event { this.config = config; this.context = context; this.location = config.engine.impl.getPolyglotSourceSection(context.getInstrumentedSourceSection()); - this.cachedEvent = config.engine.impl.getMonitoring().newExecutionEvent(this); + this.cachedEvent = config.engine.impl.getManagement().newExecutionEvent(this); } public String getRootName() { @@ -573,7 +575,7 @@ protected final void invokeException() { @TruffleBoundary(allowInlining = true) protected final void invokeReturnAllocate(List inputValues, Value returnValue) { - config.onReturn.accept(config.monitoring.newExecutionEvent(new DynamicEvent(this, inputValues, returnValue, null))); + config.onReturn.accept(config.management.newExecutionEvent(new DynamicEvent(this, inputValues, returnValue, null))); } public final SourceSection getLocation() { @@ -623,4 +625,10 @@ public int size() { } + // implementation for org.graalvm.polyglot.management.Limits + + private PolyglotEngineImpl getEngine(Engine engineAPI) { + return (PolyglotEngineImpl) engineImpl.getAPIAccess().getImpl(engineAPI); + } + } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java index 43e5494ae751..5e0a07c34af0 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java @@ -307,7 +307,7 @@ private static final class MultiLanguageSupplier extends LanguageReference get() { assert language.assertCorrectEngine(); - return PolyglotContextImpl.requireContextEntered(language.engine).getContext(language).getLanguageInstance().spi; + return PolyglotContextImpl.currentEntered(language.engine).getContext(language).getLanguageInstance().spi; } } @@ -322,7 +322,7 @@ private static final class MultiContextSupplier extends ContextReference @Override public Object get() { assert language.assertCorrectEngine(); - return PolyglotContextImpl.requireContextEntered(language.engine).getContextImpl(language); + return PolyglotContextImpl.currentEntered(language.engine).getContextImpl(language); } } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotThreadInfo.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotThreadInfo.java index 26d62d6f15ab..966557db540b 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotThreadInfo.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotThreadInfo.java @@ -40,9 +40,14 @@ */ package com.oracle.truffle.polyglot; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadMXBean; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.LinkedList; +import java.util.concurrent.TimeUnit; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; final class PolyglotThreadInfo { @@ -53,6 +58,10 @@ final class PolyglotThreadInfo { private int enteredCount; final LinkedList explicitContextStack = new LinkedList<>(); volatile boolean cancelled; + private volatile long lastEntered; + private volatile long timeExecuted; + + private static final ThreadMXBean THREAD_BEAN = ManagementFactory.getThreadMXBean(); PolyglotThreadInfo(Thread thread) { this.thread = new WeakReference<>(thread); @@ -66,9 +75,41 @@ boolean isCurrent() { return getThread() == Thread.currentThread(); } - void enter() { + void enter(PolyglotEngineImpl engine) { assert Thread.currentThread() == getThread(); - enteredCount++; + int count = ++enteredCount; + if (!engine.noThreadTimingNeeded.isValid() && count == 1) { + lastEntered = getTime(); + } + } + + void resetTiming() { + if (enteredCount > 0) { + lastEntered = getTime(); + } + this.timeExecuted = 0; + } + + long getTimeExecuted() { + long totalTime = timeExecuted; + long last = this.lastEntered; + if (last > 0) { + totalTime += getTime() - last; + } + return totalTime; + } + + @TruffleBoundary + private long getTime() { + Thread t = getThread(); + if (t == null) { + return timeExecuted; + } + long time = THREAD_BEAN.getThreadCpuTime(t.getId()); + if (time == -1) { + return TimeUnit.MILLISECONDS.convert(System.currentTimeMillis(), TimeUnit.NANOSECONDS); + } + return time; } boolean isPolyglotThread(PolyglotContextImpl c) { @@ -78,9 +119,14 @@ boolean isPolyglotThread(PolyglotContextImpl c) { return false; } - void leave() { + void leave(PolyglotEngineImpl engine) { assert Thread.currentThread() == getThread(); - --enteredCount; + int count = --enteredCount; + if (!engine.noThreadTimingNeeded.isValid() && count == 0) { + long last = this.lastEntered; + this.lastEntered = 0; + this.timeExecuted += getTime() - last; + } } boolean isLastActive() { diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValue.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValue.java index 06ff07782d3f..d916d4f2b84d 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValue.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotValue.java @@ -424,12 +424,12 @@ private Object findMetaObject(Object target) { } private static Object enter(PolyglotLanguageContext languageContext) { - return languageContext != null ? languageContext.context.enterIfNeeded() : null; + return languageContext != null ? languageContext.context.engine.enterIfNeeded(languageContext.context) : null; } private static void leave(PolyglotLanguageContext languageContext, Object prev) { if (languageContext != null) { - languageContext.context.leaveIfNeeded(prev); + languageContext.context.engine.leaveIfNeeded(prev, languageContext.context); } } diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java index 902cb20ba4f6..f5fe1fde7a71 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java @@ -83,7 +83,7 @@ public Integer visitFrame(FrameInstance frameInstance) { Frame frame = frameInstance.getFrame(FrameAccess.READ_ONLY); RootNode rn = ((RootCallTarget) callTarget).getRootNode(); // ignore internal or interop stack frames - if (rn.getLanguageInfo() == null) { + if (rn.isInternal() || rn.getLanguageInfo() == null) { return 1; } if (str.length() > 0) { diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java index ba452f52ec04..ab2ecb4b392d 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java @@ -74,12 +74,17 @@ public final class SLEvalRootNode extends RootNode { @Child private DirectCallNode mainCallNode; public SLEvalRootNode(SLLanguage language, RootCallTarget rootFunction, Map functions) { - super(null); // internal frame + super(language); this.functions = functions; this.mainCallNode = rootFunction != null ? DirectCallNode.create(rootFunction) : null; this.reference = language.getContextReference(); } + @Override + public boolean isInternal() { + return true; + } + @Override protected boolean isInstrumentable() { return false; From 46b010d149f68bff1a719c2d25118f6e965a9314 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 23 Sep 2019 18:57:39 +0200 Subject: [PATCH 011/140] Fix renamed field in TruffleFeature. --- .../src/com/oracle/svm/truffle/TruffleFeature.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java index ce881d9ec3b8..4b060cd3808f 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java @@ -807,7 +807,7 @@ final class Target_com_oracle_truffle_polyglot_ContextThreadLocal { * Don't store any threads in the image. */ @Alias @RecomputeFieldValue(kind = Kind.Reset) // - Thread firstThread; + Thread activeSingleThread; } @TargetClass(className = "com.oracle.truffle.polyglot.PolyglotContextImpl$SingleContextState", onlyWith = TruffleFeature.IsEnabled.class) From 4425ffbe3e7fe2ae144f031a90311e833099a810 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 23 Sep 2019 19:37:22 +0200 Subject: [PATCH 012/140] Intrinsify access check of atomic long field updater to never do the access check on the fast-path. --- .../substitutions/TruffleGraphBuilderPlugins.java | 14 ++++++++++++++ .../truffle/runtime/GraalTruffleRuntime.java | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/substitutions/TruffleGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/substitutions/TruffleGraphBuilderPlugins.java index 0334c7c6cb48..51b428cd4b56 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/substitutions/TruffleGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/substitutions/TruffleGraphBuilderPlugins.java @@ -33,6 +33,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.Stamp; @@ -121,6 +122,19 @@ public static void registerInvocationPlugins(InvocationPlugins plugins, boolean registerCompilerAssertsPlugins(plugins, metaAccess, canDelayIntrinsification); registerOptimizedCallTargetPlugins(plugins, metaAccess, canDelayIntrinsification, types); registerFrameWithoutBoxingPlugins(plugins, metaAccess, canDelayIntrinsification, providers.getConstantReflection(), types); + registerAtomicFieldUpdater(plugins, metaAccess); + } + + private static void registerAtomicFieldUpdater(InvocationPlugins plugins, MetaAccessProvider metaAccess) { + TruffleCompilerRuntime rt = TruffleCompilerRuntime.getRuntime(); + ResolvedJavaType casUpdater = rt.resolveType(metaAccess, AtomicLongFieldUpdater.class.getName() + "$CASUpdater"); + Registration r = new Registration(plugins, new ResolvedJavaSymbol(casUpdater)); + r.register2("accessCheck", Receiver.class, Object.class, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { + return true; + } + }); } public static void registerOptimizedAssumptionPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, KnownTruffleTypes types) { 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 169b3e0ba412..28b778ceca81 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 @@ -44,6 +44,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.function.Consumer; import org.graalvm.collections.EconomicMap; @@ -339,6 +340,14 @@ public LoopExplosionKind getLoopExplosionKind(ResolvedJavaMethod method) { } } + /* + * Dummy field for initializing atomic long field updater. + */ + @SuppressWarnings("unused") + private static class Dummy { + private volatile long dummy; + } + private static UnmodifiableEconomicMap> initLookupTypes(Iterable> extraTypes) { EconomicMap> m = EconomicMap.create(); for (Class c : new Class[]{ @@ -362,6 +371,7 @@ private static UnmodifiableEconomicMap> initLookupTypes(Iterabl AbstractAssumption.class, MaterializedFrame.class, FrameWithoutBoxing.class, + AtomicLongFieldUpdater.newUpdater(Dummy.class, "dummy").getClass(), }) { m.put(c.getName(), c); } From 5e901c3521fa5c75fc9fd43eaeb878c754dffbe8 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Tue, 24 Sep 2019 12:21:45 +0200 Subject: [PATCH 013/140] Fix dummy field must be public in order to work on JDK11. --- .../graalvm/compiler/truffle/runtime/GraalTruffleRuntime.java | 4 ++-- 1 file 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 28b778ceca81..0b4429676d54 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 @@ -344,8 +344,8 @@ public LoopExplosionKind getLoopExplosionKind(ResolvedJavaMethod method) { * Dummy field for initializing atomic long field updater. */ @SuppressWarnings("unused") - private static class Dummy { - private volatile long dummy; + public static class Dummy { + public volatile long dummy; } private static UnmodifiableEconomicMap> initLookupTypes(Iterable> extraTypes) { From a0bae6e81f63cfc03be0948064bd2e3f5ebb20fe Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Tue, 24 Sep 2019 13:42:21 +0200 Subject: [PATCH 014/140] Add requires java.management for Truffle. --- truffle/mx.truffle/suite.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 526341d1c9c2..b24892cd0e18 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -751,7 +751,8 @@ "requires" : [ "static java.desktop", "jdk.unsupported", # sun.misc.Unsafe - "java.logging" + "java.logging", + "java.management" ], "exports" : [ # Qualified exports From 308a3a63e1ea69042093665e9da6f01bac25c4b3 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Tue, 24 Sep 2019 15:23:46 +0200 Subject: [PATCH 015/140] Make tests more stable. Increase minimum time resolution to 10ms. --- .../org/graalvm/polyglot/ResourceLimits.java | 2 +- .../test/ResourceLimitsTest.java | 37 +++++++++------- .../truffle/polyglot/PolyglotLimits.java | 43 +++++++++++++------ 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java index a7ad6089c560..079dbb491aa7 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java @@ -194,7 +194,7 @@ public Builder statementLimit(long limit, Predicate sourceFilter) { * disable the time limit for a builder. By default no time limit is configured. Invoking * this method multiple times overwrites previous time limit configurations. If the time * limit is exceeded then the {@link #onLimit(Consumer) onLimit} listener is notified. The - * minimal accuracy is one millisecond, values below that will be rounded up. + * minimal accuracy is 10 milliseconds, values below that will be rounded up. *

    * The activation CPU time of a context typically does not include time spent waiting for * synchronization or IO. If the guest application is executed on multiple threads at the diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java index 73a8f5ff00d4..a48210fdb93e 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java @@ -57,6 +57,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Engine; @@ -76,12 +77,6 @@ public void testBoundContextTimeLimit() { try (Context context = Context.newBuilder().resourceLimits(limits).build()) { context.initialize(InstrumentationTestLanguage.ID); - try { - // we wait, because we want to test that the time limit - // has effect only for entered contexts - Thread.sleep(20); - } catch (InterruptedException e) { - } try { evalStatements(context); fail(); @@ -115,10 +110,12 @@ public void testSharedContextTimeLimitSynchronous() { public void testSharedContextTimeLimitParallel() throws InterruptedException, ExecutionException { ResourceLimits limits = ResourceLimits.newBuilder().// cpuTimeLimit(Duration.ofMillis(5), Duration.ofMillis(1)).// - build(); + onLimit((e) -> { + + }).build(); Engine engine = Engine.create(); - ExecutorService executorService = Executors.newFixedThreadPool(10); + ExecutorService executorService = Executors.newFixedThreadPool(5); List> futures = new ArrayList<>(); for (int i = 0; i < 100; i++) { futures.add(executorService.submit(() -> { @@ -135,13 +132,14 @@ public void testSharedContextTimeLimitParallel() throws InterruptedException, Ex for (Future future : futures) { future.get(); } - executorService.shutdown(); + executorService.shutdownNow(); + executorService.awaitTermination(100, TimeUnit.SECONDS); } @Test public void testSharedContextTimeLimitResetParallel() throws InterruptedException, ExecutionException { ResourceLimits limits = ResourceLimits.newBuilder().// - cpuTimeLimit(Duration.ofMillis(250), Duration.ofMillis(1)).// + cpuTimeLimit(Duration.ofMillis(30), Duration.ofMillis(10)).// build(); System.gc(); // force gc before running this test @@ -152,9 +150,9 @@ public void testSharedContextTimeLimitResetParallel() throws InterruptedExceptio for (int i = 0; i < 10; i++) { futures.add(executorService.submit(() -> { try (Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { - for (int j = 0; j < 10; j++) { + for (int j = 0; j < 2; j++) { c.enter(); - Thread.sleep(50); + Thread.sleep(5); c.leave(); c.resetLimits(); } @@ -173,6 +171,7 @@ public void testSharedContextTimeLimitResetParallel() throws InterruptedExceptio future.get(); } executorService.shutdown(); + executorService.awaitTermination(100, TimeUnit.SECONDS); } private static void evalStatements(Context c) { @@ -182,8 +181,9 @@ private static void evalStatements(Context c) { */ c.eval(statements(10)); c.eval(statements(500)); - c.eval(statements(1000)); - c.eval(statements(Integer.MAX_VALUE)); + while (true) { + c.eval(statements(1000)); + } } private static void assertTimeout(Context c, PolyglotException e) { @@ -352,7 +352,7 @@ public void testStatementLimitDifferentPerContext() { } @Test - public void testStatementLimitDifferentPerContextParallel() { + public void testStatementLimitDifferentPerContextParallel() throws InterruptedException { ResourceLimits limits1 = ResourceLimits.newBuilder().// statementLimit(1, null).// build(); @@ -399,6 +399,9 @@ public void testStatementLimitDifferentPerContextParallel() { } })); } + + executorService.shutdown(); + executorService.awaitTermination(100, TimeUnit.SECONDS); } private static Source statements(int count) { @@ -473,6 +476,7 @@ public void testSharedContextStatementLimitParallel() throws InterruptedExceptio future.get(); } executorService.shutdown(); + executorService.awaitTermination(100, TimeUnit.SECONDS); synchronized (events) { assertEquals(tasks, events.size()); } @@ -516,6 +520,7 @@ public void testParallelContextStatementLimit() throws InterruptedException, Exe } } executorService.shutdown(); + executorService.awaitTermination(100, TimeUnit.SECONDS); } @Test @@ -575,6 +580,7 @@ public void testParallelMultiContextStatementLimit() throws InterruptedException assertEquals(contexts, events.size()); executorService.shutdown(); + executorService.awaitTermination(100, TimeUnit.SECONDS); } @Test @@ -638,6 +644,7 @@ public void testParallelMultiContextStatementResetLimit() throws InterruptedExce assertEquals(contexts, events.size()); executorService.shutdown(); + executorService.awaitTermination(100, TimeUnit.SECONDS); } @Test diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java index cc0457cda4b1..cf634453dbdf 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java @@ -46,6 +46,7 @@ import java.util.TimerTask; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; @@ -225,28 +226,40 @@ private void notifyStatementLimitReached(PolyglotContextImpl context, long actua static final class TimeLimitChecker extends TimerTask { - private final WeakReference contextRef; + private final WeakReference context; private final long timeLimitNS; + private final EngineLimits limits; + private FutureTask cancelResult; - TimeLimitChecker(PolyglotContextImpl context) { - this.contextRef = new WeakReference<>(context); + TimeLimitChecker(PolyglotContextImpl context, EngineLimits limits) { + this.context = new WeakReference<>(context); this.timeLimitNS = context.config.limits.timeLimit.toNanos(); + this.limits = limits; } @Override public void run() { - PolyglotContextImpl context = contextRef.get(); - if (context == null || context.closed) { + PolyglotContextImpl c = this.context.get(); + if (cancelResult != null) { + if (cancelResult.isDone()) { + cancel(); + try { + cancelResult.get(); + } catch (Exception e) { + } + } + return; + } else if (c == null || c.closed) { cancel(); return; } - long timeActiveNS = context.getTimeActive(); + long timeActiveNS = c.getTimeActive(); if (timeActiveNS > timeLimitNS) { - if (!context.invalid) { + if (!c.invalid) { String message = String.format("Time resource limit of %sms exceeded. Time executed %sms.", - context.config.limits.timeLimit.toMillis(), + c.config.limits.timeLimit.toMillis(), Duration.ofNanos(timeActiveNS).toMillis()); - boolean invalidated = context.invalidate(message); + boolean invalidated = c.invalidate(message); /* * We immediately set the context invalid so it can no longer be entered. The * cancel executor closes the context on a parallel thread and closes the @@ -255,9 +268,12 @@ public void run() { * that waits for the cancel to be complete. */ if (invalidated) { - EngineLimits.getCancelExecutor().submit(new Runnable() { + limits.notifyEvent(c); + cancelResult = (FutureTask) EngineLimits.getCancelExecutor().submit(new Runnable() { public void run() { - context.close(context.creatorApi, true); + if (!c.closed) { + c.close(c.creatorApi, true); + } } }); } @@ -368,8 +384,8 @@ public ExecutionEventNode create(EventContext eventContext) { engine.noThreadTimingNeeded.invalidate(); long timeLimitMillis = limits.timeLimit.toMillis(); assert timeLimitMillis > 0; // needs to verified before - TimeLimitChecker task = new TimeLimitChecker(context); - long accuracy = Math.max(1, limits.timeAccuracy.toMillis()); + TimeLimitChecker task = new TimeLimitChecker(context, this); + long accuracy = Math.max(10, limits.timeAccuracy.toMillis()); getLimitTimer().scheduleAtFixedRate(task, accuracy, accuracy, TimeUnit.MILLISECONDS); } @@ -405,6 +421,7 @@ static ExecutorService getCancelExecutor() { if (executor == null) { cancelExecutor = executor = (ThreadPoolExecutor) Executors.newCachedThreadPool( new HighPriorityThreadFactory("Polyglot Cancel Thread")); + executor.setKeepAliveTime(1, TimeUnit.SECONDS); } } } From d7e082711cd9c99b280cd1fd7134a664624dc2f0 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Tue, 24 Sep 2019 16:08:55 +0200 Subject: [PATCH 016/140] Also check context state in language context access check. --- .../src/com/oracle/truffle/polyglot/PolyglotContextImpl.java | 2 +- .../com/oracle/truffle/polyglot/PolyglotLanguageContext.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) 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 6c0795dc4f4b..fb7342a114f9 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 @@ -691,7 +691,7 @@ private void initPolyglotBindings() { } } - private void checkClosed() { + void checkClosed() { if (invalid && closingThread != Thread.currentThread()) { // try closing if this is the last thread throw PolyglotImpl.wrapGuestException(engine, new CancelExecution(null, invalidMessage)); 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 33fb3d3fa0c4..a0647209ef77 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 @@ -570,7 +570,8 @@ boolean ensureInitialized(PolyglotLanguage accessingLanguage) { void checkAccess(PolyglotLanguage accessingLanguage) { context.engine.checkState(); - if (context.closed || context.disposing) { + context.checkClosed(); + if (context.disposing) { throw new PolyglotIllegalStateException("The Context is already closed."); } if (!context.config.isAccessPermitted(accessingLanguage, language)) { From 5fe1621a9b77171ecc3e608e85bccbf094357552 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Tue, 24 Sep 2019 17:35:37 +0200 Subject: [PATCH 017/140] Fix invalidation order. --- .../truffle/api/instrumentation/test/ResourceLimitsTest.java | 3 +-- .../src/com/oracle/truffle/polyglot/PolyglotContextImpl.java | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java index a48210fdb93e..929659c0c351 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java @@ -484,7 +484,6 @@ public void testSharedContextStatementLimitParallel() throws InterruptedExceptio @Test public void testParallelContextStatementLimit() throws InterruptedException, ExecutionException { - Engine engine = Engine.create(); Map events = new HashMap<>(); final int limit = 10000; ResourceLimits limits = ResourceLimits.newBuilder().// @@ -498,7 +497,7 @@ public void testParallelContextStatementLimit() throws InterruptedException, Exe build(); ExecutorService executorService = Executors.newFixedThreadPool(20); List> futures = new ArrayList<>(); - try (Context c = Context.newBuilder().engine(engine).resourceLimits(limits).build()) { + try (Context c = Context.newBuilder().resourceLimits(limits).build()) { for (int i = 0; i < limit; i++) { futures.add(executorService.submit(() -> { c.eval(statements(1)); 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 fb7342a114f9..435701d75377 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 @@ -577,11 +577,11 @@ private void transitionToMultiThreaded() { LANGUAGE.initializeMultiThreading(context.env); } } + engine.singleThreadPerContext.invalidate(); + singleThreaded.invalidate(); long statementsExecuted = statementLimit - statementCounter; STATEMENT_COUNTER_UPDATER.getAndAdd(this, -statementsExecuted); - engine.singleThreadPerContext.invalidate(); - singleThreaded.invalidate(); } private PolyglotThreadInfo createThreadInfo(Thread current) { From afc34c7250a026b26f6e18ab44700dc899594938 Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Mon, 30 Sep 2019 13:16:56 -0700 Subject: [PATCH 018/140] Report missing URL protocols using the exception specified by the JDK --- .../svm/core/jdk/JavaNetSubstitutions.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaNetSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaNetSubstitutions.java index 1cb297ec0d5a..46e157132c9e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaNetSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaNetSubstitutions.java @@ -29,6 +29,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; @@ -58,7 +59,14 @@ final class Target_java_net_URL { @Delete private static Hashtable handlers; @Substitute - private static URLStreamHandler getURLStreamHandler(String protocol) { + private static URLStreamHandler getURLStreamHandler(String protocol) throws MalformedURLException { + /* + * The original version of this method does not throw MalformedURLException directly, but + * instead returns null if no handler is found. The callers then check the result and throw + * the exception when the return value is null. Implementing our substitution the same way + * would mean that we cannot provide a helpful exception message why a protocol is not + * available, and how to add a protocol at image build time. + */ return JavaNetSubstitutions.getURLStreamHandler(protocol); } } @@ -150,7 +158,7 @@ static boolean addURLStreamHandler(String protocol) { } } - static URLStreamHandler getURLStreamHandler(String protocol) { + static URLStreamHandler getURLStreamHandler(String protocol) throws MalformedURLException { URLStreamHandler result = URLProtocolsSupport.get(protocol); if (result == null) { if (onDemandProtocols.contains(protocol)) { @@ -192,8 +200,12 @@ public InputStream getInputStream() throws IOException { }; } - private static void unsupported(String message) { - throw VMError.unsupportedFeature(message); + private static void unsupported(String message) throws MalformedURLException { + /* + * We throw a MalformedURLException and not our own unsupported feature error to be + * consistent with the specification of URL. + */ + throw new MalformedURLException(message); } static String supportedProtocols() { From efbcfe71fc1f0ac3605b106f0c57d9c790383f66 Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Tue, 1 Oct 2019 14:56:04 +0200 Subject: [PATCH 019/140] [GR-18565] Mark r27 as not allocatable. --- .../aarch64/AArch64HotSpotRegisterAllocationConfig.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java index af351fe408a9..1ad98cdd22c3 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java @@ -44,7 +44,6 @@ import static jdk.vm.ci.aarch64.AArch64.r24; import static jdk.vm.ci.aarch64.AArch64.r25; import static jdk.vm.ci.aarch64.AArch64.r26; -import static jdk.vm.ci.aarch64.AArch64.r27; import static jdk.vm.ci.aarch64.AArch64.r28; import static jdk.vm.ci.aarch64.AArch64.r29; import static jdk.vm.ci.aarch64.AArch64.r3; @@ -100,12 +99,16 @@ public class AArch64HotSpotRegisterAllocationConfig extends RegisterAllocationConfig { + /** + * Excluding r27 is a temporary solution until we exclude r27 unconditionally at + * {@link jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig}. + */ // @formatter:off static final Register[] registerAllocationOrder = { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, - r24, r25, r26, r27, r28, r29, r30, r31, + r24, r25, r26, /* r27, */ r28, r29, r30, r31, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, From c2519476afddb18f4b17d1e15f4da8bbded3606a Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Wed, 2 Oct 2019 10:44:03 +0200 Subject: [PATCH 020/140] add explanation. --- .../aarch64/AArch64HotSpotRegisterAllocationConfig.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java index 1ad98cdd22c3..299d7049dcec 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java @@ -102,6 +102,12 @@ public class AArch64HotSpotRegisterAllocationConfig extends RegisterAllocationCo /** * Excluding r27 is a temporary solution until we exclude r27 unconditionally at * {@link jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig}. + * + * The underlying reason is that HotSpot does not intend to support r27 as an allocatable + * register. This register is excluded from callee-saved register at + * cpu/aarch64/sharedRuntime_aarch64.cpp:RegisterSaver::save_live_registers, and may lead to + * dereferencing unknown value from the stack at + * share/runtime/stackValue.cpp:StackValue::create_stack_value during deoptimization. */ // @formatter:off static final Register[] registerAllocationOrder = { From 40cb97ac0cf021836a6268a9939d23e04f6683e2 Mon Sep 17 00:00:00 2001 From: Danilo Ansaloni Date: Wed, 2 Oct 2019 11:32:02 +0200 Subject: [PATCH 021/140] [GR-18596] Default host-vms have higher priority than `-java8` and `-java11`. --- vm/mx.vm/mx_vm_benchmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/mx.vm/mx_vm_benchmark.py b/vm/mx.vm/mx_vm_benchmark.py index 256e0d75dc1f..2f62a5b77b04 100644 --- a/vm/mx.vm/mx_vm_benchmark.py +++ b/vm/mx.vm/mx_vm_benchmark.py @@ -354,7 +354,7 @@ def __call__(self, *args, **kwargs): def register_graalvm_vms(): default_host_vm_name = mx_vm.graalvm_dist_name().lower().replace('_', '-') - host_vm_names = [default_host_vm_name] + ([default_host_vm_name.replace('-java8', '')] if '-java8' in default_host_vm_name else []) + host_vm_names = ([default_host_vm_name.replace('-java8', '')] if '-java8' in default_host_vm_name else []) + [default_host_vm_name] for host_vm_name in host_vm_names: for config_name, java_args, launcher_args, priority in mx_sdk.graalvm_hostvm_configs: mx_benchmark.java_vm_registry.add_vm(GraalVm(host_vm_name, config_name, java_args, launcher_args), _suite, priority) From 48793b6d2ad2feab61561e42b30f526bd1d26885 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Wed, 2 Oct 2019 21:06:06 +0200 Subject: [PATCH 022/140] Fix context thread local may be null on SVM. --- .../truffle/polyglot/PolyglotContextImpl.java | 17 +++++++++++++++-- .../truffle/polyglot/PolyglotEngineImpl.java | 10 ++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) 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 435701d75377..282214a057a4 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 @@ -89,8 +89,8 @@ final class PolyglotContextImpl extends AbstractContextImpl implements com.oracl * simplifies resetting state in AOT mode during native image generation. */ static final class SingleContextState { - final ContextThreadLocal contextThreadLocal = new ContextThreadLocal(); - final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("Single Context"); + private final ContextThreadLocal contextThreadLocal = new ContextThreadLocal(); + private final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("Single Context"); @CompilationFinal private volatile PolyglotContextImpl singleContext; /** Copy constructor that keeps the previous state. */ @@ -102,6 +102,15 @@ static final class SingleContextState { SingleContextState(PolyglotContextImpl context) { this.singleContext = context; } + + ContextThreadLocal getContextThreadLocal() { + return contextThreadLocal; + } + + Assumption getSingleContextAssumption() { + return singleContextAssumption; + } + } @CompilationFinal static SingleContextState singleContextState = new SingleContextState(null); @@ -116,6 +125,10 @@ static Object resetSingleContextState(boolean reuse) { return prev; } + static SingleContextState getSingleContextState() { + return singleContextState; + } + /* * Used from testing using reflection. Its invalid to call it anywhere else than testing. Used * in EngineAPITest. 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 6a9589c033c8..4bf3d00e0c36 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 @@ -818,6 +818,7 @@ synchronized void ensureClosed(boolean cancelIfExecuting, boolean ignoreCloseFai boolean stillRunning = false; if (!cancelIfExecuting) { for (PolyglotContextImpl context : localContexts) { + assert !Thread.holdsLock(context); synchronized (context) { if (context.hasActiveOtherThread(false) && context.closingThread == null) { if (!ignoreCloseFailure) { @@ -831,6 +832,7 @@ synchronized void ensureClosed(boolean cancelIfExecuting, boolean ignoreCloseFai } } for (PolyglotContextImpl context : localContexts) { + assert !Thread.holdsLock(context); try { boolean closeCompleted = context.closeImpl(cancelIfExecuting, cancelIfExecuting); if (!closeCompleted && !cancelIfExecuting) { @@ -1377,9 +1379,9 @@ Supplier>> getFil @SuppressWarnings("static-method") boolean needsEnter(PolyglotContextImpl context) { - if (PolyglotContextImpl.singleContextState.singleContextAssumption.isValid()) { + if (PolyglotContextImpl.getSingleContextState().getSingleContextAssumption().isValid()) { // if its a single context we know which one to enter - return !PolyglotContextImpl.singleContextState.contextThreadLocal.isSet(); + return !PolyglotContextImpl.singleContextState.getContextThreadLocal().isSet(); } else { return PolyglotContextImpl.currentNotEntered() != context; } @@ -1404,7 +1406,7 @@ Object enter(PolyglotContextImpl context) { PolyglotThreadInfo info = getCachedThreadInfo(context); if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, info.getThread() == Thread.currentThread())) { // fast-path -> same thread - prev = PolyglotContextImpl.singleContextState.contextThreadLocal.setReturnParent(context); + prev = PolyglotContextImpl.getSingleContextState().getContextThreadLocal().setReturnParent(context); info.enter(this); } else { // slow path -> changed thread @@ -1429,7 +1431,7 @@ void leave(Object prev, PolyglotContextImpl polyglotContext) { } polyglotContext.leaveThreadChanged(); } - PolyglotContextImpl.singleContextState.contextThreadLocal.set(prev); + PolyglotContextImpl.getSingleContextState().getContextThreadLocal().set(prev); } PolyglotThreadInfo getCachedThreadInfo(PolyglotContextImpl context) { From ab0b13c3264c4d946f2f81971dac4d0f1b04e894 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 3 Oct 2019 13:43:18 +0200 Subject: [PATCH 023/140] Lookup ThreadMXBean lazily. --- .../oracle/truffle/polyglot/PolyglotThreadInfo.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotThreadInfo.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotThreadInfo.java index 966557db540b..83edc833673c 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotThreadInfo.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotThreadInfo.java @@ -61,7 +61,7 @@ final class PolyglotThreadInfo { private volatile long lastEntered; private volatile long timeExecuted; - private static final ThreadMXBean THREAD_BEAN = ManagementFactory.getThreadMXBean(); + private static volatile ThreadMXBean threadBean; PolyglotThreadInfo(Thread thread) { this.thread = new WeakReference<>(thread); @@ -105,7 +105,15 @@ private long getTime() { if (t == null) { return timeExecuted; } - long time = THREAD_BEAN.getThreadCpuTime(t.getId()); + ThreadMXBean bean = threadBean; + if (bean == null) { + /* + * getThreadMXBean is synchronized so better cache in a local volatile field to avoid + * contention. + */ + threadBean = bean = ManagementFactory.getThreadMXBean(); + } + long time = bean.getThreadCpuTime(t.getId()); if (time == -1) { return TimeUnit.MILLISECONDS.convert(System.currentTimeMillis(), TimeUnit.NANOSECONDS); } From 2f1b7b49731db0fe04891b4126187e3688812e5a Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 3 Oct 2019 15:09:07 +0200 Subject: [PATCH 024/140] Remove usage of AtomicLongFieldUpdate and replace it with AtomicLong. --- .../TruffleGraphBuilderPlugins.java | 16 +--------------- .../truffle/runtime/GraalTruffleRuntime.java | 10 ---------- .../truffle/polyglot/PolyglotContextImpl.java | 12 +++++------- .../oracle/truffle/polyglot/PolyglotImpl.java | 2 +- .../oracle/truffle/polyglot/PolyglotLimits.java | 8 ++++---- 5 files changed, 11 insertions(+), 37 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/substitutions/TruffleGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/substitutions/TruffleGraphBuilderPlugins.java index 51b428cd4b56..06db171aa787 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/substitutions/TruffleGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/substitutions/TruffleGraphBuilderPlugins.java @@ -33,7 +33,6 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.Callable; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.Stamp; @@ -52,7 +51,6 @@ import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.truffle.compiler.nodes.IsInlinedNode; import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NodeView; @@ -87,6 +85,7 @@ import org.graalvm.compiler.truffle.compiler.PartialEvaluator; import org.graalvm.compiler.truffle.compiler.TruffleCompilerOptions; import org.graalvm.compiler.truffle.compiler.nodes.IsCompilationConstantNode; +import org.graalvm.compiler.truffle.compiler.nodes.IsInlinedNode; import org.graalvm.compiler.truffle.compiler.nodes.ObjectLocationIdentity; import org.graalvm.compiler.truffle.compiler.nodes.TruffleAssumption; import org.graalvm.compiler.truffle.compiler.nodes.asserts.NeverPartOfCompilationNode; @@ -122,19 +121,6 @@ public static void registerInvocationPlugins(InvocationPlugins plugins, boolean registerCompilerAssertsPlugins(plugins, metaAccess, canDelayIntrinsification); registerOptimizedCallTargetPlugins(plugins, metaAccess, canDelayIntrinsification, types); registerFrameWithoutBoxingPlugins(plugins, metaAccess, canDelayIntrinsification, providers.getConstantReflection(), types); - registerAtomicFieldUpdater(plugins, metaAccess); - } - - private static void registerAtomicFieldUpdater(InvocationPlugins plugins, MetaAccessProvider metaAccess) { - TruffleCompilerRuntime rt = TruffleCompilerRuntime.getRuntime(); - ResolvedJavaType casUpdater = rt.resolveType(metaAccess, AtomicLongFieldUpdater.class.getName() + "$CASUpdater"); - Registration r = new Registration(plugins, new ResolvedJavaSymbol(casUpdater)); - r.register2("accessCheck", Receiver.class, Object.class, new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { - return true; - } - }); } public static void registerOptimizedAssumptionPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, KnownTruffleTypes types) { 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 0b4429676d54..169b3e0ba412 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 @@ -44,7 +44,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.function.Consumer; import org.graalvm.collections.EconomicMap; @@ -340,14 +339,6 @@ public LoopExplosionKind getLoopExplosionKind(ResolvedJavaMethod method) { } } - /* - * Dummy field for initializing atomic long field updater. - */ - @SuppressWarnings("unused") - public static class Dummy { - public volatile long dummy; - } - private static UnmodifiableEconomicMap> initLookupTypes(Iterable> extraTypes) { EconomicMap> m = EconomicMap.create(); for (Class c : new Class[]{ @@ -371,7 +362,6 @@ private static UnmodifiableEconomicMap> initLookupTypes(Iterabl AbstractAssumption.class, MaterializedFrame.class, FrameWithoutBoxing.class, - AtomicLongFieldUpdater.newUpdater(Dummy.class, "dummy").getClass(), }) { m.put(c.getName(), c); } 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 282214a057a4..a50e1109ca69 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 @@ -58,7 +58,7 @@ import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; import org.graalvm.collections.EconomicSet; @@ -190,13 +190,11 @@ static boolean isSingleContextAssumptionValid() { private final List childContexts = new ArrayList<>(); boolean inContextPreInitialization; // effectively final - volatile long volatileStatementCounter; + final AtomicLong volatileStatementCounter = new AtomicLong(); long statementCounter; long elapsedTime; final long statementLimit; - static final AtomicLongFieldUpdater STATEMENT_COUNTER_UPDATER = AtomicLongFieldUpdater.newUpdater(PolyglotContextImpl.class, "volatileStatementCounter"); - /* Constructor for testing. */ private PolyglotContextImpl() { super(null); @@ -234,7 +232,7 @@ private PolyglotContextImpl() { this.subProcesses = new HashSet<>(); this.statementLimit = config.limits != null ? config.limits.statementLimit : Long.MAX_VALUE - 1; this.statementCounter = statementLimit; - this.volatileStatementCounter = statementLimit; + this.volatileStatementCounter.set(statementLimit); notifyContextCreated(); PolyglotContextImpl.initializeStaticContext(this); } @@ -576,7 +574,7 @@ long getStatementsExecuted() { if (engine.singleThreadPerContext.isValid()) { count = this.statementCounter; } else { - count = this.volatileStatementCounter; + count = this.volatileStatementCounter.get(); } return statementLimit - count; } @@ -594,7 +592,7 @@ private void transitionToMultiThreaded() { singleThreaded.invalidate(); long statementsExecuted = statementLimit - statementCounter; - STATEMENT_COUNTER_UPDATER.getAndAdd(this, -statementsExecuted); + volatileStatementCounter.getAndAdd(-statementsExecuted); } private PolyglotThreadInfo createThreadInfo(Thread current) { 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 a07fc3bc8186..9da9292f21bd 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 @@ -56,6 +56,7 @@ import java.util.function.Predicate; import java.util.logging.Handler; +import org.graalvm.home.HomeFinder; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.HostAccess; @@ -69,7 +70,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleOptions; import com.oracle.truffle.api.impl.DispatchOutputStream; -import org.graalvm.home.HomeFinder; import com.oracle.truffle.api.impl.TruffleLocator; import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.interop.TruffleObject; diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java index cf634453dbdf..b002493e336c 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLimits.java @@ -107,7 +107,7 @@ static void reset(PolyglotContextImpl context) { context.resetTiming(); } context.statementCounter = context.statementLimit; - context.volatileStatementCounter = context.statementLimit; + context.volatileStatementCounter.set(context.statementLimit); } } @@ -166,7 +166,7 @@ protected void onEnter(VirtualFrame frame) { if (engine.singleThreadPerContext.isValid()) { count = --currentContext.statementCounter; } else { - count = PolyglotContextImpl.STATEMENT_COUNTER_UPDATER.decrementAndGet(currentContext); + count = currentContext.volatileStatementCounter.decrementAndGet(); } if (count < 0) { // overflowed CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -200,8 +200,8 @@ private void notifyStatementLimitReached(PolyglotContextImpl context, long actua limitReached = true; } } else { - if (context.volatileStatementCounter < 0) { - context.volatileStatementCounter = limit; + if (context.volatileStatementCounter.get() < 0) { + context.volatileStatementCounter.set(limit); limitReached = true; } } From 346f4ef173db258d507ee4020e65bb0bdf15e457 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 3 Oct 2019 15:12:35 +0200 Subject: [PATCH 025/140] Remove useless System.gc calls. --- .../truffle/api/instrumentation/test/ResourceLimitsTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java index 929659c0c351..400a9e19c8ce 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/ResourceLimitsTest.java @@ -142,8 +142,6 @@ public void testSharedContextTimeLimitResetParallel() throws InterruptedExceptio cpuTimeLimit(Duration.ofMillis(30), Duration.ofMillis(10)).// build(); - System.gc(); // force gc before running this test - System.gc(); Engine engine = Engine.create(); ExecutorService executorService = Executors.newFixedThreadPool(10); List> futures = new ArrayList<>(); From 144689cc45498a971f31b5115015c45c73ab0cb8 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 3 Oct 2019 15:36:57 +0200 Subject: [PATCH 026/140] Javadoc fixes. --- .../org/graalvm/polyglot/ResourceLimits.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java index 079dbb491aa7..0f189136922c 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/ResourceLimits.java @@ -168,9 +168,9 @@ public final class Builder { * Therefore, new inner contexts cannot be used to exceed the statement limit. *

    * Note that attaching a statement limit to a context reduces the throughput of all guest - * applications with that use the same engine. The statement counter needs to be updated for - * every statement that is executed. It is recommended to benchmark the use of the statement - * limit before it is used in production. + * applications with that use the same engine. The statement counter needs to be updated + * with every statement that is executed. It is recommended to benchmark the use of the + * statement limit before it is used in production. * * @see ResourceLimits Example Usage * @since 19.3 @@ -188,7 +188,7 @@ public Builder statementLimit(long limit, Predicate sourceFilter) { /** * Specifies the maximum {@link ThreadMXBean#getThreadCpuTime(long) CPU time} a context may * be active until the onLimit event is notified and the context will be - * {@link Context#close() closed}. The lime limit {@link Duration duration} may be specified + * {@link Context#close() closed}. The {@link Duration time limit} may be specified * alongside an {@link Duration accuracy} with which the time limit is enforced. Both time * limit and accuracy must be positive. Both parameters may be set to null to * disable the time limit for a builder. By default no time limit is configured. Invoking @@ -196,11 +196,10 @@ public Builder statementLimit(long limit, Predicate sourceFilter) { * limit is exceeded then the {@link #onLimit(Consumer) onLimit} listener is notified. The * minimal accuracy is 10 milliseconds, values below that will be rounded up. *

    - * The activation CPU time of a context typically does not include time spent waiting for - * synchronization or IO. If the guest application is executed on multiple threads at the - * same time, or if the guest application creates new threads then the CPU time of those - * threads will be accumulated individually in the activation time. E.g. if two threads - * execute the same context then the time limit will be exceeded twice as fast. + * The used CPU time of a context typically does not include time spent waiting for + * synchronization or IO. The CPU time of all threads will be added and checked against the + * CPU time limit. This can mean that if two threads execute the same context then the time + * limit will be exceeded twice as fast. *

    * The time limit is enforced by a separate high-priority thread that will be woken * regularly. There is no guarantee that the context will be cancelled within the accuracy From 0759d9a0f94da5f4ba613af92915b09e6dd8f6cc Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Thu, 3 Oct 2019 15:41:01 +0200 Subject: [PATCH 027/140] Fix changelog. --- sdk/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index c4e249e40d83..8b1b53e11b53 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -5,7 +5,7 @@ This changelog summarizes major changes between GraalVM SDK versions. The main f ## Version 19.3.0 * The default temporary directory can be configured by [FileSystem](http://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/io/FileSystem.html#getTempDirectory--). * Added `org.graalvm.polyglot.ResourceLimits` that allows to specify context specific time and statement count execution limits. -* Context can now be closed if they are still explicitly entered using `Context.enter` on the current thread. This allows for simpler error recovery code. +* Contexts can now be closed if they are still explicitly entered using `Context.enter` on the current thread. This allows for simpler error recovery code. ## Version 19.2.0 * Added support for date, time, timezone and duration values in polyglot From 2a986cfd29eb42ce1dbf7d23424d94bd341d9d02 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 27 Sep 2019 16:34:53 +0200 Subject: [PATCH 028/140] Initialize JNI "net" only once. --- .../graal/snippets/CEntryPointSnippets.java | 11 +++---- .../core/posix/PosixNativeLibraryFeature.java | 19 +++++------- .../windows/WindowsNativeLibraryFeature.java | 15 ++++------ .../svm/core/jdk/NativeLibrarySupport.java | 30 ++++++++++++------- .../jdk/PlatformNativeLibrarySupport.java | 22 +++++++++----- 5 files changed, 53 insertions(+), 44 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index a8aade206088..4c2d3fce83d0 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -232,7 +232,9 @@ private static int initializeIsolate() { int state = unsafe.getInt(initStateAddr); if (state != FirstIsolateInitStates.SUCCESSFUL) { firstIsolate = unsafe.compareAndSwapInt(null, initStateAddr, FirstIsolateInitStates.UNINITIALIZED, FirstIsolateInitStates.IN_PROGRESS); - if (!firstIsolate) { + if (firstIsolate) { + PlatformNativeLibrarySupport.singleton().setIsFirstIsolate(); + } else { while (state == FirstIsolateInitStates.IN_PROGRESS) { // spin-wait for first isolate state = unsafe.getIntVolatile(null, initStateAddr); } @@ -242,13 +244,12 @@ private static int initializeIsolate() { } } - boolean success = true; - if (firstIsolate) { - success = PlatformNativeLibrarySupport.singleton().initializeSharedBuiltinLibrariesOnce(); + boolean success = PlatformNativeLibrarySupport.singleton().initializeBuiltinLibraries(); + + if (firstIsolate) { // let other isolates (if any) initialize now state = success ? FirstIsolateInitStates.SUCCESSFUL : FirstIsolateInitStates.FAILED; unsafe.putIntVolatile(null, initStateAddr, state); } - success = success && PlatformNativeLibrarySupport.singleton().initializeBuiltinLibraries(); if (!success) { return CEntryPointErrors.ISOLATE_INITIALIZATION_FAILED; } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java index 7425834bc880..ed0706bce9da 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java @@ -25,6 +25,7 @@ package com.oracle.svm.core.posix; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; +import com.oracle.svm.core.jdk.NativeLibrarySupport; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -72,6 +73,7 @@ public boolean initializeBuiltinLibraries() { try { loadJavaLibrary(); loadZipLibrary(); + loadNetLibrary(); /* * The JDK uses posix_spawn on the Mac to launch executables. This requires a @@ -94,24 +96,17 @@ protected void loadJavaLibrary() { Target_java_io_UnixFileSystem_JNI.initIDs(); } - @Override - public boolean initializeSharedBuiltinLibrariesOnce() { - if (!super.initializeSharedBuiltinLibrariesOnce()) { - return false; - } - if (Platform.includedIn(InternalPlatform.PLATFORM_JNI.class)) { + protected void loadNetLibrary() { + if (isFirstIsolate()) { /* * NOTE: because the native OnLoad code probes java.net.preferIPv4Stack and stores its * value in process-wide shared native state, the property's value in the first launched * isolate applies to all subsequently launched isolates. */ - try { - System.loadLibrary("net"); - } catch (UnsatisfiedLinkError e) { - return false; - } + System.loadLibrary("net"); + } else { + NativeLibrarySupport.singleton().registerInitializedBuiltinLibrary("net"); } - return true; } @Override diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsNativeLibraryFeature.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsNativeLibraryFeature.java index 1c6110e705dd..9bf5a390de2b 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsNativeLibraryFeature.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsNativeLibraryFeature.java @@ -26,6 +26,7 @@ import java.io.FileDescriptor; +import com.oracle.svm.core.jdk.NativeLibrarySupport; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -68,6 +69,7 @@ public boolean initializeBuiltinLibraries() { try { loadJavaLibrary(); loadZipLibrary(); + loadNetLibrary(); } catch (UnsatisfiedLinkError e) { Log.log().string("System.loadLibrary failed, " + e).newline(); return false; @@ -86,12 +88,8 @@ protected void loadJavaLibrary() { WindowsUtils.setHandle(FileDescriptor.err, FileAPI.GetStdHandle(FileAPI.STD_ERROR_HANDLE())); } - @Override - public boolean initializeSharedBuiltinLibrariesOnce() { - if (!super.initializeSharedBuiltinLibrariesOnce()) { - return false; - } - try { + protected void loadNetLibrary() { + if (isFirstIsolate()) { WinSock.init(); System.loadLibrary("net"); /* @@ -99,10 +97,9 @@ public boolean initializeSharedBuiltinLibrariesOnce() { * value in process-wide shared native state, the property's value in the first launched * isolate applies to all subsequently launched isolates. */ - } catch (UnsatisfiedLinkError e) { - return false; + } else { + NativeLibrarySupport.singleton().registerInitializedBuiltinLibrary("net"); } - return true; } @Override diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java index 4dbb763e26a3..2265d9be27f2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java @@ -125,14 +125,16 @@ private boolean loadLibrary0(File file, boolean asBuiltin) { if (asBuiltin && (libraryInitializer == null || !libraryInitializer.isBuiltinLibrary(file.getName()))) { return false; } - String canonical; try { canonical = asBuiltin ? file.getName() : file.getCanonicalPath(); } catch (IOException e) { return false; } + return addLibrary(asBuiltin, canonical, true); + } + private boolean addLibrary(boolean asBuiltin, String canonical, boolean loadAndInitialize) { lock.lock(); try { for (NativeLibrary loaded : loadedLibraries) { @@ -147,17 +149,19 @@ private boolean loadLibrary0(File file, boolean asBuiltin) { } } NativeLibrary lib = PlatformNativeLibrarySupport.singleton().createLibrary(canonical, asBuiltin); - currentLoadContext.push(lib); - try { - if (!lib.load()) { - return false; - } - if (libraryInitializer != null) { - libraryInitializer.initialize(lib); + if (loadAndInitialize) { + currentLoadContext.push(lib); + try { + if (!lib.load()) { + return false; + } + if (libraryInitializer != null) { + libraryInitializer.initialize(lib); + } + } finally { + NativeLibrary top = currentLoadContext.pop(); + assert top == lib; } - } finally { - NativeLibrary top = currentLoadContext.pop(); - assert top == lib; } loadedLibraries.add(lib); return true; @@ -180,4 +184,8 @@ public PointerBase findSymbol(String name) { lock.unlock(); } } + + public void registerInitializedBuiltinLibrary(String name) { + addLibrary(true, name, false); + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/PlatformNativeLibrarySupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/PlatformNativeLibrarySupport.java index 20fcb83b4b74..c7dc2c3c4636 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/PlatformNativeLibrarySupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/PlatformNativeLibrarySupport.java @@ -142,16 +142,24 @@ public interface NativeLibrary { public abstract PointerBase findBuiltinSymbol(String name); + private boolean firstIsolate = false; + + /** @see #isFirstIsolate() */ + public void setIsFirstIsolate() { + firstIsolate = true; + } + /** - * Initializes built-in libraries that are explicitly or implicitly shared between the isolates - * of a process (for example, because they have a single native state that does not distinguish - * between isolate). This method is called exactly once per process, during the creation of the - * first isolate in the process, followed by a call to {@link #initializeBuiltinLibraries()}. + * Indicates if the current isolate is the first isolate in this process and whether it is + * therefore responsible for initializing any built-in libraries that are explicitly or + * implicitly shared between the isolates of the process (for example, because they have a + * single native state that does not distinguish between isolates). This method is called before + * {@link #initializeBuiltinLibraries()}, which can then use {@link #isFirstIsolate()}. */ - public boolean initializeSharedBuiltinLibrariesOnce() { - return true; + protected boolean isFirstIsolate() { + return firstIsolate; } - /** Initializes built-in libraries for the current isolate, during its creation. */ + /** Initializes built-in libraries during isolate creation. */ public abstract boolean initializeBuiltinLibraries(); } From 942be176faaec850e04d17c503073a0aaeddc030 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 27 Sep 2019 19:28:46 +0200 Subject: [PATCH 029/140] Prepare built-in native libraries during image build. --- .../core/posix/PosixNativeLibraryFeature.java | 28 +++++++---- .../windows/WindowsNativeLibraryFeature.java | 28 +++++++---- .../svm/core/jdk/NativeLibrarySupport.java | 44 +++++++++++++---- .../jdk/PlatformNativeLibrarySupport.java | 47 ++++++++++++++----- .../svm/hosted/SecurityServicesFeature.java | 7 ++- .../svm/hosted/jdk/JNIRegistrationJava.java | 4 +- 6 files changed, 114 insertions(+), 44 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java index ed0706bce9da..9ad31cf2fad7 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java @@ -59,7 +59,7 @@ class PosixNativeLibrarySupport extends JNIPlatformNativeLibrarySupport { @Platforms(Platform.HOSTED_ONLY.class) PosixNativeLibrarySupport() { if (JavaVersionUtil.JAVA_SPEC >= 11) { - addBuiltInLibrary("extnet"); + NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("extnet"); } } @@ -126,15 +126,9 @@ class PosixNativeLibrary implements NativeLibrary { private final String canonicalIdentifier; private final boolean builtin; private PointerBase dlhandle = WordFactory.nullPointer(); + private boolean loaded = false; PosixNativeLibrary(String canonicalIdentifier, boolean builtin) { - // Make sure the jvm.lib is available for linking - // Need a better place to put this. - if (Platform.includedIn(InternalPlatform.LINUX_JNI.class) || - Platform.includedIn(InternalPlatform.DARWIN_JNI.class)) { - Jvm.initialize(); - } - this.canonicalIdentifier = canonicalIdentifier; this.builtin = builtin; } @@ -151,6 +145,19 @@ public boolean isBuiltin() { @Override public boolean load() { + assert !loaded; + loaded = doLoad(); + return loaded; + } + + private boolean doLoad() { + // Make sure the jvm.lib is available for linking + // Need a better place to put this. + if (Platform.includedIn(InternalPlatform.LINUX_JNI.class) || + Platform.includedIn(InternalPlatform.DARWIN_JNI.class)) { + Jvm.initialize(); + } + if (builtin) { return true; } @@ -159,6 +166,11 @@ public boolean load() { return dlhandle.isNonNull(); } + @Override + public boolean isLoaded() { + return loaded; + } + @Override public PointerBase findSymbol(String name) { if (builtin) { diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsNativeLibraryFeature.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsNativeLibraryFeature.java index 9bf5a390de2b..0e13f9fc1d6a 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsNativeLibraryFeature.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsNativeLibraryFeature.java @@ -119,13 +119,10 @@ class WindowsNativeLibrary implements NativeLibrary { private final String canonicalIdentifier; private final boolean builtin; - private HMODULE dlhandle = WordFactory.nullPointer(); + private HMODULE dlhandle; + private boolean loaded = false; WindowsNativeLibrary(String canonicalIdentifier, boolean builtin) { - // Make sure the jvm.lib is available for linking - // Need a better place to put this. - Jvm.initialize(); - this.canonicalIdentifier = canonicalIdentifier; this.builtin = builtin; } @@ -142,6 +139,16 @@ public boolean isBuiltin() { @Override public boolean load() { + assert !loaded; + loaded = doLoad(); + return loaded; + } + + private boolean doLoad() { + // Make sure the jvm.lib is available for linking + // Need a better place to put this. + Jvm.initialize(); + if (builtin) { return true; } @@ -157,16 +164,19 @@ public boolean load() { return dlhandle.isNonNull(); } + @Override + public boolean isLoaded() { + return loaded; + } + @Override public PointerBase findSymbol(String name) { if (builtin) { - PointerBase addr = findBuiltinSymbol(name); - return (addr); + return findBuiltinSymbol(name); } assert dlhandle.isNonNull(); try (CCharPointerHolder symbol = CTypeConversion.toCString(name)) { - PointerBase addr = WinBase.GetProcAddress(dlhandle, symbol.get()); - return (addr); + return WinBase.GetProcAddress(dlhandle, symbol.get()); } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java index 2265d9be27f2..17831f99dc53 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java @@ -70,7 +70,7 @@ public static NativeLibrarySupport singleton() { private final ReentrantLock lock = new ReentrantLock(); - private final List loadedLibraries = new ArrayList<>(); + private final List knownLibraries = new ArrayList<>(); private final Deque currentLoadContext = new ArrayDeque<>(); @@ -87,6 +87,16 @@ public void registerLibraryInitializer(LibraryInitializer initializer) { this.libraryInitializer = initializer; } + @Platforms(HOSTED_ONLY.class) + public void preregisterUninitializedBuiltinLibrary(String name) { + knownLibraries.add(PlatformNativeLibrarySupport.singleton().createLibrary(name, true)); + } + + @Platforms(HOSTED_ONLY.class) + public boolean isPreregisteredBuiltinLibrary(String name) { + return knownLibraries.stream().anyMatch(l -> l.isBuiltin() && l.getCanonicalIdentifier().equals(name)); + } + public void loadLibrary(String name, boolean isAbsolute) { if (isAbsolute) { if (loadLibrary0(new File(name), false)) { @@ -122,9 +132,6 @@ public void loadLibrary(String name, boolean isAbsolute) { } private boolean loadLibrary0(File file, boolean asBuiltin) { - if (asBuiltin && (libraryInitializer == null || !libraryInitializer.isBuiltinLibrary(file.getName()))) { - return false; - } String canonical; try { canonical = asBuiltin ? file.getName() : file.getCanonicalPath(); @@ -137,18 +144,33 @@ private boolean loadLibrary0(File file, boolean asBuiltin) { private boolean addLibrary(boolean asBuiltin, String canonical, boolean loadAndInitialize) { lock.lock(); try { - for (NativeLibrary loaded : loadedLibraries) { - if (canonical.equals(loaded.getCanonicalIdentifier())) { - return true; + NativeLibrary lib = null; + for (NativeLibrary known : knownLibraries) { + if (canonical.equals(known.getCanonicalIdentifier())) { + if (known.isLoaded()) { + return true; + } else { + assert known.isBuiltin() : "non-built-in libraries must always have been loaded"; + assert asBuiltin : "must have tried loading as built-in first"; + lib = known; // load and initialize below + break; + } } } + if (asBuiltin && lib == null && (libraryInitializer == null || !libraryInitializer.isBuiltinLibrary(canonical))) { + return false; + } // Libraries can load libraries during initialization, avoid recursion with a stack for (NativeLibrary loading : currentLoadContext) { if (canonical.equals(loading.getCanonicalIdentifier())) { return true; } } - NativeLibrary lib = PlatformNativeLibrarySupport.singleton().createLibrary(canonical, asBuiltin); + boolean created = false; + if (lib == null) { + lib = PlatformNativeLibrarySupport.singleton().createLibrary(canonical, asBuiltin); + created = true; + } if (loadAndInitialize) { currentLoadContext.push(lib); try { @@ -163,7 +185,9 @@ private boolean addLibrary(boolean asBuiltin, String canonical, boolean loadAndI assert top == lib; } } - loadedLibraries.add(lib); + if (created) { + knownLibraries.add(lib); + } return true; } finally { lock.unlock(); @@ -173,7 +197,7 @@ private boolean addLibrary(boolean asBuiltin, String canonical, boolean loadAndI public PointerBase findSymbol(String name) { lock.lock(); try { - for (NativeLibrary lib : loadedLibraries) { + for (NativeLibrary lib : knownLibraries) { PointerBase entry = lib.findSymbol(name); if (entry.isNonNull()) { return entry; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/PlatformNativeLibrarySupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/PlatformNativeLibrarySupport.java index c7dc2c3c4636..ba2f2881e646 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/PlatformNativeLibrarySupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/PlatformNativeLibrarySupport.java @@ -28,8 +28,10 @@ import java.util.Arrays; import java.util.List; +import com.oracle.svm.core.annotate.AutomaticFeature; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.PointerBase; @@ -92,14 +94,13 @@ protected PlatformNativeLibrarySupport() { } } - private List builtInLibraries = new ArrayList<>(Arrays.asList(defaultBuiltInLibraries)); - - public void addBuiltInLibrary(String libName) { - builtInLibraries.add(libName); - } - - public boolean isBuiltinLibrary(String name) { - return builtInLibraries.contains(name); + /** + * Determines if a library which has not been + * {@linkplain NativeLibrarySupport#preregisterUninitializedBuiltinLibrary pre-registered} + * during image generation is a built-in library. + */ + public boolean isBuiltinLibrary(@SuppressWarnings("unused") String name) { + return false; } private List builtInPkgNatives; @@ -134,8 +135,9 @@ public interface NativeLibrary { boolean load(); - PointerBase findSymbol(String name); + boolean isLoaded(); + PointerBase findSymbol(String name); } public abstract NativeLibrary createLibrary(String canonical, boolean builtIn); @@ -144,7 +146,10 @@ public interface NativeLibrary { private boolean firstIsolate = false; - /** @see #isFirstIsolate() */ + /** + * This method is called before {@link #initializeBuiltinLibraries()}, which can then use + * {@link #isFirstIsolate()}. + */ public void setIsFirstIsolate() { firstIsolate = true; } @@ -153,13 +158,29 @@ public void setIsFirstIsolate() { * Indicates if the current isolate is the first isolate in this process and whether it is * therefore responsible for initializing any built-in libraries that are explicitly or * implicitly shared between the isolates of the process (for example, because they have a - * single native state that does not distinguish between isolates). This method is called before - * {@link #initializeBuiltinLibraries()}, which can then use {@link #isFirstIsolate()}. + * single native state that does not distinguish between isolates). */ protected boolean isFirstIsolate() { return firstIsolate; } - /** Initializes built-in libraries during isolate creation. */ + /** + * Initializes built-in libraries during isolate creation. + * + * @see #isFirstIsolate() + */ public abstract boolean initializeBuiltinLibraries(); } + +@AutomaticFeature +class PlatformNativeLibrarySupportFeature implements Feature { + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + if (Platform.includedIn(InternalPlatform.PLATFORM_JNI.class)) { + for (String libName : PlatformNativeLibrarySupport.defaultBuiltInLibraries) { + PlatformNativeLibrarySupport.singleton(); + NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary(libName); + } + } + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java index e21a96835625..12ed190893b4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java @@ -37,6 +37,7 @@ import java.util.Map; import java.util.function.Function; +import com.oracle.svm.core.jdk.NativeLibrarySupport; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.nativeimage.ImageSingletons; @@ -223,7 +224,8 @@ private static void linkSunEC(DuringAnalysisAccess duringAnalysisAccess) { NativeLibraries nativeLibraries = a.getNativeLibraries(); if (nativeLibraries.getStaticLibraryPath("sunec") != null) { /* We statically link sunec thus we classify it as builtIn library */ - PlatformNativeLibrarySupport.singleton().addBuiltInLibrary("sunec"); + PlatformNativeLibrarySupport.singleton(); + NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("sunec"); /* and ensure native calls to sun_security_ec* will be resolved as builtIn. */ PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("sun_security_ec"); @@ -239,7 +241,8 @@ private static void linkJaas(DuringAnalysisAccess duringAnalysisAccess) { NativeLibraries nativeLibraries = ((FeatureImpl.DuringAnalysisAccessImpl) duringAnalysisAccess).getNativeLibraries(); if (nativeLibraries.getStaticLibraryPath("jaas") != null) { /* We can statically link jaas, thus we classify it as builtIn library */ - PlatformNativeLibrarySupport.singleton().addBuiltInLibrary("jaas_unix"); + PlatformNativeLibrarySupport.singleton(); + NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("jaas_unix"); /* Resolve calls to com_sun_security_auth_module_UnixSystem* as builtIn. */ PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("com_sun_security_auth_module_UnixSystem"); nativeLibraries.addLibrary("jaas", true); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJava.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJava.java index 89291a609c68..bc90a65af34f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJava.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJava.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.hosted.jdk; +import com.oracle.svm.core.jdk.NativeLibrarySupport; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -36,7 +37,6 @@ import com.oracle.svm.core.annotate.AutomaticFeature; import com.oracle.svm.core.graal.GraalFeature; -import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport; import com.oracle.svm.core.jni.JNIRuntimeAccess; import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; @@ -61,7 +61,7 @@ public void registerGraphBuilderPlugins(Providers providers, Plugins plugins, bo public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode libnameNode) { if (libnameNode.isConstant()) { String libname = (String) SubstrateObjectConstant.asObject(libnameNode.asConstant()); - if (libname != null && PlatformNativeLibrarySupport.singleton().isBuiltinLibrary(libname)) { + if (libname != null && NativeLibrarySupport.singleton().isPreregisteredBuiltinLibrary(libname)) { /* * Support for automatic static linking of standard libraries. This works * because all of the JDK uses System.loadLibrary with literal String From 2cf6310e9dcb32ae3198489094c7ada655a77488 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Sat, 28 Sep 2019 11:58:15 +0200 Subject: [PATCH 030/140] Increase process open file limit to hard maximum on startup. --- .../core/posix/PosixJavaNIOSubstitutions.java | 4 +- .../core/posix/PosixNativeLibraryFeature.java | 26 ++++++++++- .../core/posix/headers/PosixDirectives.java | 3 +- .../svm/core/posix/headers/Resource.java | 9 ++-- .../posix/headers/darwin/DarwinSyslimits.java | 44 +++++++++++++++++++ .../posix/headers/linux/Linux64Suffix.java | 10 ++++- 6 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSyslimits.java diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNIOSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNIOSubstitutions.java index 04c99714f449..0d80a55249cb 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNIOSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNIOSubstitutions.java @@ -508,10 +508,10 @@ private static int fdLimit() throws IOException { if (getrlimit(RLIMIT_NOFILE(), rlp) < 0) { throw PosixUtils.newIOExceptionWithLastError("getrlimit failed"); } - if (rlp.rlim_max() < 0 || rlp.rlim_max() > Integer.MAX_VALUE) { + if (rlp.rlim_max().belowThan(0) || rlp.rlim_max().aboveThan(Integer.MAX_VALUE)) { return Integer.MAX_VALUE; } else { - return (int) rlp.rlim_max(); + return (int) rlp.rlim_max().rawValue(); } } } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java index 9ad31cf2fad7..7dc15dcf16bc 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java @@ -25,25 +25,30 @@ package com.oracle.svm.core.posix; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; -import com.oracle.svm.core.jdk.NativeLibrarySupport; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.type.CTypeConversion; import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.PointerBase; +import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; import com.oracle.svm.core.annotate.Alias; import com.oracle.svm.core.annotate.AutomaticFeature; import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.headers.Errno; import com.oracle.svm.core.jdk.JNIPlatformNativeLibrarySupport; import com.oracle.svm.core.jdk.Jvm; +import com.oracle.svm.core.jdk.NativeLibrarySupport; import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.posix.headers.Dlfcn; +import com.oracle.svm.core.posix.headers.Resource; +import com.oracle.svm.core.posix.headers.darwin.DarwinSyslimits; @AutomaticFeature @Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) @@ -69,12 +74,29 @@ static void initialize() { @Override public boolean initializeBuiltinLibraries() { + if (isFirstIsolate()) { // raise process file descriptor limit to hard max if possible + Resource.rlimit rlp = StackValue.get(Resource.rlimit.class); + if (Resource.getrlimit(Resource.RLIMIT_NOFILE(), rlp) == 0) { + UnsignedWord newValue = rlp.rlim_max(); + if (Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class)) { + // On Darwin, getrlimit may return RLIM_INFINITY for rlim_max, but then OPEN_MAX + // must be used for setrlimit or it will fail with errno EINVAL. + newValue = WordFactory.unsigned(DarwinSyslimits.OPEN_MAX()); + } + rlp.set_rlim_cur(newValue); + if (Resource.setrlimit(Resource.RLIMIT_NOFILE(), rlp) != 0) { + Log.log().string("setrlimit to increase file descriptor limit failed, errno ").signed(Errno.errno()).newline(); + } + } else { + Log.log().string("getrlimit failed, errno ").signed(Errno.errno()).newline(); + } + } + if (Platform.includedIn(InternalPlatform.PLATFORM_JNI.class)) { try { loadJavaLibrary(); loadZipLibrary(); loadNetLibrary(); - /* * The JDK uses posix_spawn on the Mac to launch executables. This requires a * separate process "jspawnhelper" which we don't want to have to rely on. Force the diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/PosixDirectives.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/PosixDirectives.java index 9ee7b3608630..e3cfd591600c 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/PosixDirectives.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/PosixDirectives.java @@ -90,7 +90,8 @@ public class PosixDirectives implements CContext.Directives { "", "", "", - "" + "", + "", }; private static final String[] linuxLibs = new String[]{ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Resource.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Resource.java index de013704bf55..a11b5de83e0a 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Resource.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Resource.java @@ -30,6 +30,7 @@ import org.graalvm.nativeimage.c.struct.CField; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.word.PointerBase; +import org.graalvm.word.UnsignedWord; // Checkstyle: stop @@ -46,17 +47,17 @@ public class Resource { public interface rlimit extends PointerBase { /** The current (soft) limit. */ @CField - long rlim_cur(); + UnsignedWord rlim_cur(); @CField - void set_rlim_cur(long value); + void set_rlim_cur(UnsignedWord value); /** The hard limit. */ @CField - long rlim_max(); + UnsignedWord rlim_max(); @CField - void set_rlim_max(long value); + void set_rlim_max(UnsignedWord value); } @CFunction diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSyslimits.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSyslimits.java new file mode 100644 index 000000000000..97351a186ef5 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSyslimits.java @@ -0,0 +1,44 @@ +/* + * 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 com.oracle.svm.core.posix.headers.darwin; + +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.c.CContext; +import org.graalvm.nativeimage.c.constant.CConstant; +import org.graalvm.nativeimage.impl.InternalPlatform; + +import com.oracle.svm.core.posix.headers.PosixDirectives; + +/** Declarations of method from . */ +@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@CContext(PosixDirectives.class) +public class DarwinSyslimits { + // { Allow names with underscores: Checkstyle: stop + + @CConstant + public static native int OPEN_MAX(); + + // } Allow names with underscores: Checkstyle: resume +} diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Linux64Suffix.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Linux64Suffix.java index 9f241cb90f58..5df15dc06c77 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Linux64Suffix.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Linux64Suffix.java @@ -138,10 +138,16 @@ static final class Target_com_oracle_svm_core_posix_headers_Mman { @CContext(PosixDirectives.class) interface rlimit64 extends PointerBase { @KeepOriginal - long rlim_cur(); + UnsignedWord rlim_cur(); @KeepOriginal - long rlim_max(); + void set_rlim_cur(UnsignedWord value); + + @KeepOriginal + UnsignedWord rlim_max(); + + @KeepOriginal + void set_rlim_max(UnsignedWord value); } @TargetClass(com.oracle.svm.core.posix.headers.Resource.class) From c6e4d9c3c37529110702fe3531d7f8abe968fe7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Wed, 2 Oct 2019 16:32:44 +0200 Subject: [PATCH 031/140] Fix cyclic ImageSingletons init for Java 11+ --- .../svm/core/posix/PosixNativeLibraryFeature.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java index 7dc15dcf16bc..2bf7ae91f50a 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java @@ -57,16 +57,20 @@ class PosixNativeLibraryFeature implements Feature { public void afterRegistration(AfterRegistrationAccess access) { PosixNativeLibrarySupport.initialize(); } -} - -class PosixNativeLibrarySupport extends JNIPlatformNativeLibrarySupport { - @Platforms(Platform.HOSTED_ONLY.class) - PosixNativeLibrarySupport() { + @Override + public void duringSetup(DuringSetupAccess access) { if (JavaVersionUtil.JAVA_SPEC >= 11) { NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("extnet"); } } +} + +final class PosixNativeLibrarySupport extends JNIPlatformNativeLibrarySupport { + + @Platforms(Platform.HOSTED_ONLY.class) + private PosixNativeLibrarySupport() { + } static void initialize() { ImageSingletons.add(PlatformNativeLibrarySupport.class, new PosixNativeLibrarySupport()); From 41380e37bea0158ab1e2df64b34136c042a1abb4 Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Wed, 2 Oct 2019 15:41:05 +0200 Subject: [PATCH 032/140] Allow empty symbol names for unpublished entry points --- .../oracle/svm/core/graal/llvm/SubstrateLLVMGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMGenerator.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMGenerator.java index 0640d982300c..e0a6c2962233 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMGenerator.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMGenerator.java @@ -95,9 +95,9 @@ public class SubstrateLLVMGenerator extends LLVMGenerator implements SubstrateLI Object entryPointData = ((HostedMethod) method).getWrapped().getEntryPointData(); if (entryPointData instanceof CEntryPointData) { CEntryPointData cEntryPointData = (CEntryPointData) entryPointData; - String entryPointSymbolName = cEntryPointData.getSymbolName(); - assert !entryPointSymbolName.isEmpty(); if (cEntryPointData.getPublishAs() != CEntryPointOptions.Publish.NotPublished) { + String entryPointSymbolName = cEntryPointData.getSymbolName(); + assert !entryPointSymbolName.isEmpty(); aliases.add(entryPointSymbolName); } } From ccd7e1dadcc949355db76ab38a61268298c85e6c Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 3 Oct 2019 12:18:46 +0200 Subject: [PATCH 033/140] sulong: make SULONG_LLVM_ORG platform dependent --- sulong/ci.hocon | 4 ++-- sulong/mx.sulong/suite.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sulong/ci.hocon b/sulong/ci.hocon index 47f1c494b395..2b1a0ee06d87 100644 --- a/sulong/ci.hocon +++ b/sulong/ci.hocon @@ -81,7 +81,7 @@ sulong-gateTest80-linux: ${sulong-gateTest-linux} ${sulong-gateTest-default-tool sulong-gateTestLLVMorg-linux: ${sulong-gateTest-linux} { # nothing to do environment: { - LD_LIBRARY_PATH: "$BUILD_DIR/main/sulong/mxbuild/SULONG_LLVM_ORG/lib:$LD_LIBRARY_PATH" + LD_LIBRARY_PATH: "$BUILD_DIR/main/sulong/mxbuild/linux-amd64/SULONG_LLVM_ORG/lib:$LD_LIBRARY_PATH" } } @@ -100,7 +100,7 @@ sulong-gateTest40-darwin: ${sulong-gateCommon} ${darwin-amd64} ${sulong-gateTest sulong-gateTestLLVMorg-darwin: ${sulong-gateCommon} ${darwin-amd64} { # nothing to do environment: { - LD_LIBRARY_PATH: "$BUILD_DIR/main/sulong/mxbuild/SULONG_LLVM_ORG/lib:$LD_LIBRARY_PATH" + LD_LIBRARY_PATH: "$BUILD_DIR/main/sulong/mxbuild/darwin-amd64/SULONG_LLVM_ORG/lib:$LD_LIBRARY_PATH" } } diff --git a/sulong/mx.sulong/suite.py b/sulong/mx.sulong/suite.py index 3467f72faab6..85fb2fc0d618 100644 --- a/sulong/mx.sulong/suite.py +++ b/sulong/mx.sulong/suite.py @@ -1128,6 +1128,7 @@ "file:patches/*" ], }, + "platformDependent" : True, "maven": False, "license" : "NCSA", }, From 5b68b65cdb691cbb35e3d488cfcd4b61cb7e5c60 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 3 Oct 2019 14:00:43 +0200 Subject: [PATCH 034/140] sulong: bootstrap launchers should use absolute suite path --- sulong/mx.sulong/suite.py | 6 ++++-- .../bootstrap-toolchain-launchers/Makefile | 4 +++- .../mx_launcher_template.sh | 16 +--------------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/sulong/mx.sulong/suite.py b/sulong/mx.sulong/suite.py index 85fb2fc0d618..d7ce2f7ded34 100644 --- a/sulong/mx.sulong/suite.py +++ b/sulong/mx.sulong/suite.py @@ -323,9 +323,11 @@ "class" : "ToolchainLauncherProject", "native": True, "vpath": True, - "platformDependent": False, + "platformDependent": True, "buildEnv" : { "MX_EXE" : "", + "SUITE_DIR" : "/../..", + "PLATFORM" : "native", }, "buildDependencies" : [ "SULONG_LLVM_ORG", @@ -337,7 +339,7 @@ "subDir": "tests", "native": True, "vpath": True, - "platformDependent": False, + "platformDependent": True, "max_jobs": "1", "buildEnv" : { "SULONG_EXE" : " lli", diff --git a/sulong/projects/bootstrap-toolchain-launchers/Makefile b/sulong/projects/bootstrap-toolchain-launchers/Makefile index 28713b325f36..efbb0016e9b3 100644 --- a/sulong/projects/bootstrap-toolchain-launchers/Makefile +++ b/sulong/projects/bootstrap-toolchain-launchers/Makefile @@ -35,8 +35,10 @@ default: ${RESULTS} QUIETLY$(MX_VERBOSE) = @ MX_EXE?=mx +SUITE_DIR?=suite/dir/not/found +PLATFORM?=no-platform-specified bin/%: mx_launcher_template.sh @mkdir -p $(dir $@) - $(QUIETLY) cat $< | sed "s##native-toolchain $(notdir $@)#" | sed "s##${MX_EXE}#" > $@ + $(QUIETLY) cat $< | sed "s##${PLATFORM}-toolchain $(notdir $@)#" | sed "s##${MX_EXE}#" | sed "s##${SUITE_DIR}#" > $@ @chmod +x $@ diff --git a/sulong/projects/bootstrap-toolchain-launchers/mx_launcher_template.sh b/sulong/projects/bootstrap-toolchain-launchers/mx_launcher_template.sh index c16c52b58657..82e23e8ea3c6 100755 --- a/sulong/projects/bootstrap-toolchain-launchers/mx_launcher_template.sh +++ b/sulong/projects/bootstrap-toolchain-launchers/mx_launcher_template.sh @@ -31,20 +31,6 @@ set -e -# Resolve the location of this script -source="${BASH_SOURCE[0]}" -while [ -h "$source" ] ; do - prev_source="$source" - source="$(readlink "$source")"; - if [[ "$source" != /* ]]; then - # if the link was relative, it was relative to where it came from - dir="$( cd -P "$( dirname "$prev_source" )" && pwd )" - source="$dir/$source" - fi -done -location="$( cd -P "$( dirname "$source" )" && pwd )" -suite_dir="$( dirname "$( dirname "$( dirname ${location} )" )" )" - unset DYNAMIC_IMPORTS unset DEFAULT_DYNAMIC_IMPORTS @@ -52,4 +38,4 @@ if [[ "$JACOCO" != "" ]]; then EXTRA_MX_ARGS="--jacoco=$JACOCO --jacoco-exec-file=$suite_dir/jacoco.exec" fi - $EXTRA_MX_ARGS -p "${suite_dir}" "$@" + $EXTRA_MX_ARGS -p "" "$@" From 929edd1965660a7df3b090a6e018bef390c58b1f Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 3 Oct 2019 20:53:03 +0200 Subject: [PATCH 035/140] sulong: add extra flags for native libraries --- .../projects/com.oracle.truffle.llvm.libraries.native/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.libraries.native/Makefile b/sulong/projects/com.oracle.truffle.llvm.libraries.native/Makefile index df3e4710e930..00509b204985 100644 --- a/sulong/projects/com.oracle.truffle.llvm.libraries.native/Makefile +++ b/sulong/projects/com.oracle.truffle.llvm.libraries.native/Makefile @@ -42,7 +42,8 @@ else LDFLAGS=-shared -g endif -CFLAGS=-g -fPIC -DPIC -O3 +LDFLAGS+= ${EXTRA_LDFLAGS} +CFLAGS=-g -fPIC -DPIC -O3 ${EXTRA_CFLAGS} bin/polyglot-mock.o: CFLAGS+=-Wno-return-type From 7f4d3adbbd2d26aab558c28e02a1beb4b6ba9d28 Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Thu, 3 Oct 2019 20:52:11 -0700 Subject: [PATCH 036/140] Pre-allocate JNI C structs in the image heap --- .../svm/jni/functions/JNIFunctionTables.java | 102 +++++++++++------- .../functions/JNIFunctionTablesFeature.java | 83 +++++++------- .../JNIStructFunctionsInitializer.java | 74 ------------- 3 files changed, 104 insertions(+), 155 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIStructFunctionsInitializer.java diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctionTables.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctionTables.java index e924d7fb76c8..303d24a9c4b0 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctionTables.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIFunctionTables.java @@ -24,15 +24,21 @@ */ package com.oracle.svm.jni.functions; +import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.UnmanagedMemory; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.c.function.CFunctionPointer; import org.graalvm.nativeimage.c.struct.SizeOf; -import org.graalvm.word.WordFactory; +import org.graalvm.word.Pointer; +import org.graalvm.word.UnsignedWord; +import org.graalvm.word.WordBase; -import com.oracle.svm.core.annotate.UnknownObjectField; -import com.oracle.svm.core.jdk.RuntimeSupport; -import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicPointer; +import com.oracle.svm.core.FrameAccess; +import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.LayoutEncoding; +import com.oracle.svm.core.util.VMError; import com.oracle.svm.jni.nativeapi.JNIInvokeInterface; import com.oracle.svm.jni.nativeapi.JNIJavaVM; import com.oracle.svm.jni.nativeapi.JNINativeInterface; @@ -50,54 +56,78 @@ public static JNIFunctionTables singleton() { return ImageSingletons.lookup(JNIFunctionTables.class); } + /* + * Space for C data structures that are passed out to C code at run time. Because these arrays + * are in the image heap, they are never moved by the GC at run time. + */ + private final WordBase[] javaVMData; + private final WordBase[] invokeInterfaceDataMutable; + final CFunctionPointer[] invokeInterfaceDataPrototype; + final CFunctionPointer[] functionTableData; + + @Platforms(Platform.HOSTED_ONLY.class) private JNIFunctionTables() { + javaVMData = new WordBase[wordArrayLength(SizeOf.get(JNIJavaVM.class))]; + invokeInterfaceDataMutable = new WordBase[wordArrayLength(SizeOf.get(JNIInvokeInterface.class))]; + invokeInterfaceDataPrototype = new CFunctionPointer[wordArrayLength(SizeOf.get(JNIInvokeInterface.class))]; + functionTableData = new CFunctionPointer[wordArrayLength(SizeOf.get(JNINativeInterface.class))]; } - void initialize(JNIStructFunctionsInitializer invokes, JNIStructFunctionsInitializer functionTable) { - assert this.invokesInitializer == null && this.functionTableInitializer == null; - this.invokesInitializer = invokes; - this.functionTableInitializer = functionTable; + @Platforms(Platform.HOSTED_ONLY.class) + private static int wordArrayLength(int sizeInBytes) { + int wordSize = FrameAccess.wordSize(); + VMError.guarantee(sizeInBytes % wordSize == 0); + return sizeInBytes / wordSize; } - @UnknownObjectField(types = JNIStructFunctionsInitializer.class) // - private JNIStructFunctionsInitializer invokesInitializer; - private JNIJavaVM globalJavaVM; public JNIJavaVM getGlobalJavaVM() { - if (globalJavaVM.isNull()) { - JNIInvokeInterface invokes = UnmanagedMemory.calloc(SizeOf.get(JNIInvokeInterface.class)); - invokesInitializer.initialize(invokes); + JNIJavaVM javaVM = globalJavaVM; + if (javaVM.isNull()) { + /* + * The function pointer table filled during image generation must be in the read-only + * part of the image heap, because code relocations are needed for it. To work around + * this limitation, we copy the read-only table filled during image generation to a + * writable table of the same size. + */ + for (int i = 0; i < invokeInterfaceDataPrototype.length; i++) { + invokeInterfaceDataMutable[i] = invokeInterfaceDataPrototype[i]; + } + + javaVM = (JNIJavaVM) dataAddress(javaVMData); + JNIInvokeInterface invokes = (JNIInvokeInterface) dataAddress(invokeInterfaceDataMutable); invokes.setIsolate(CurrentIsolate.getIsolate()); - globalJavaVM = UnmanagedMemory.calloc(SizeOf.get(JNIJavaVM.class)); - globalJavaVM.setFunctions(invokes); - RuntimeSupport.getRuntimeSupport().addTearDownHook(() -> { - UnmanagedMemory.free(globalJavaVM.getFunctions()); - UnmanagedMemory.free(globalJavaVM); - globalJavaVM = WordFactory.nullPointer(); - }); + javaVM.setFunctions(invokes); + + globalJavaVM = javaVM; } - return globalJavaVM; + return javaVM; } - @UnknownObjectField(types = JNIStructFunctionsInitializer.class) // - private JNIStructFunctionsInitializer functionTableInitializer; - - private final AtomicPointer globalFunctionTable = new AtomicPointer<>(); + private JNINativeInterface globalFunctionTable; public JNINativeInterface getGlobalFunctionTable() { - JNINativeInterface functionTable = globalFunctionTable.get(); + JNINativeInterface functionTable = globalFunctionTable; if (functionTable.isNull()) { - functionTable = UnmanagedMemory.malloc(SizeOf.get(JNINativeInterface.class)); - functionTableInitializer.initialize(functionTable); - if (globalFunctionTable.compareAndSet(WordFactory.nullPointer(), functionTable)) { - RuntimeSupport.getRuntimeSupport().addTearDownHook(() -> UnmanagedMemory.free(globalFunctionTable.get())); - } else { // lost the race - UnmanagedMemory.free(functionTable); - functionTable = globalFunctionTable.get(); - } + /* + * The JNI function table is filled during image generation and is ready to use, so we + * do not need to copy it to a modifiable part of the image heap. + */ + functionTable = (JNINativeInterface) dataAddress(functionTableData); + + globalFunctionTable = functionTable; } return functionTable; } + /** + * Returns the absolute address of the first array element of the provided array. The array must + * be in the image heap, i.e., never moved by the GC. + */ + private static Pointer dataAddress(WordBase[] dataArray) { + final DynamicHub hub = DynamicHub.fromClass(dataArray.getClass()); + final UnsignedWord offsetOfFirstArrayElement = LayoutEncoding.getArrayElementOffset(hub.getLayoutEncoding(), 0); + return Word.objectToUntrackedPointer(dataArray).add(offsetOfFirstArrayElement); + } } 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 f35b22b37027..5884e5e3b9c3 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 @@ -39,6 +39,7 @@ import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.svm.core.FrameAccess; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; import com.oracle.svm.hosted.FeatureImpl.BeforeCompilationAccessImpl; @@ -156,12 +157,10 @@ public void beforeCompilation(BeforeCompilationAccess a) { HostedMetaAccess metaAccess = access.getMetaAccess(); CFunctionPointer unimplementedWithJavaVMArgument = getStubFunctionPointer(access, (HostedMethod) getSingleMethod(metaAccess, UnimplementedWithJavaVMArgument.class)); - JNIStructFunctionsInitializer invokesInitializer = buildInvokesInitializer(access, unimplementedWithJavaVMArgument); + fillJNIInvocationInterfaceTable(access, JNIFunctionTables.singleton().invokeInterfaceDataPrototype, unimplementedWithJavaVMArgument); CFunctionPointer unimplementedWithJNIEnvArgument = getStubFunctionPointer(access, (HostedMethod) getSingleMethod(metaAccess, UnimplementedWithJNIEnvArgument.class)); - JNIStructFunctionsInitializer functionsInitializer = buildFunctionsInitializer(access, unimplementedWithJNIEnvArgument); - - JNIFunctionTables.singleton().initialize(invokesInitializer, functionsInitializer); + fillJNIFunctionsTable(access, JNIFunctionTables.singleton().functionTableData, unimplementedWithJNIEnvArgument); } private static CFunctionPointer prepareCallTrampoline(CompilationAccessImpl access, CallVariant variant, boolean nonVirtual) { @@ -184,42 +183,28 @@ private static CFunctionPointer getStubFunctionPointer(CompilationAccessImpl acc return MethodPointer.factory(access.getUniverse().lookup(stub)); } - private JNIStructFunctionsInitializer buildInvokesInitializer(CompilationAccessImpl access, CFunctionPointer unimplemented) { + private void fillJNIInvocationInterfaceTable(CompilationAccessImpl access, CFunctionPointer[] table, CFunctionPointer defaultValue) { + initializeFunctionPointerTable(access, table, defaultValue); + HostedType invokes = access.getMetaAccess().lookupJavaType(JNIInvocationInterface.class); HostedMethod[] methods = invokes.getDeclaredMethods(); - int index = 0; - int[] offsets = new int[methods.length]; - CFunctionPointer[] pointers = new CFunctionPointer[offsets.length]; for (HostedMethod method : methods) { StructFieldInfo field = findFieldFor(invokeInterfaceMetadata, method.getName()); - offsets[index] = field.getOffsetInfo().getProperty(); - pointers[index] = getStubFunctionPointer(access, method); - index++; + int offset = field.getOffsetInfo().getProperty(); + setFunctionPointerTable(table, offset, getStubFunctionPointer(access, method)); } - VMError.guarantee(index == offsets.length && index == pointers.length); - JNIStructFunctionsInitializer initializer = new JNIStructFunctionsInitializer<>(JNIInvokeInterface.class, offsets, pointers, unimplemented); - access.registerAsImmutable(pointers); - access.registerAsImmutable(initializer); - return initializer; } - private JNIStructFunctionsInitializer buildFunctionsInitializer(CompilationAccessImpl access, CFunctionPointer unimplemented) { + private void fillJNIFunctionsTable(CompilationAccessImpl access, CFunctionPointer[] table, CFunctionPointer defaultValue) { + initializeFunctionPointerTable(access, table, defaultValue); + Class clazz = JNIFunctions.class; HostedType functions = access.getMetaAccess().lookupJavaType(clazz); HostedMethod[] methods = functions.getDeclaredMethods(); - int index = 0; - int count = methods.length + generatedMethods.length; - // Call, CallStatic, CallNonvirtual: for each return value kind: array, va_list, varargs - // NewObject: array, va_list, varargs - count += (jniKinds.size() * 3 + 1) * 3; - int[] offsets = new int[count]; - CFunctionPointer[] pointers = new CFunctionPointer[offsets.length]; - access.registerAsImmutable(pointers); for (HostedMethod method : methods) { StructFieldInfo field = findFieldFor(functionTableMetadata, method.getName()); - offsets[index] = field.getOffsetInfo().getProperty(); - pointers[index] = getStubFunctionPointer(access, method); - index++; + int offset = field.getOffsetInfo().getProperty(); + setFunctionPointerTable(table, offset, getStubFunctionPointer(access, method)); } for (ResolvedJavaMethod accessor : generatedMethods) { StructFieldInfo field = findFieldFor(functionTableMetadata, accessor.getName()); @@ -228,9 +213,8 @@ private JNIStructFunctionsInitializer buildFunctionsInitiali AnalysisMethod analysisMethod = analysisUniverse.lookup(accessor); HostedMethod hostedMethod = access.getUniverse().lookup(analysisMethod); - offsets[index] = field.getOffsetInfo().getProperty(); - pointers[index] = MethodPointer.factory(hostedMethod); - index++; + int offset = field.getOffsetInfo().getProperty(); + setFunctionPointerTable(table, offset, MethodPointer.factory(hostedMethod)); } for (CallVariant variant : CallVariant.values()) { CFunctionPointer trampoline = prepareCallTrampoline(access, variant, false); @@ -240,25 +224,17 @@ private JNIStructFunctionsInitializer buildFunctionsInitiali String[] prefixes = {"Call", "CallStatic"}; for (String prefix : prefixes) { StructFieldInfo field = findFieldFor(functionTableMetadata, prefix + kind.name() + "Method" + suffix); - offsets[index] = field.getOffsetInfo().getProperty(); - pointers[index] = trampoline; - index++; + int offset = field.getOffsetInfo().getProperty(); + setFunctionPointerTable(table, offset, trampoline); } StructFieldInfo field = findFieldFor(functionTableMetadata, "CallNonvirtual" + kind.name() + "Method" + suffix); - offsets[index] = field.getOffsetInfo().getProperty(); - pointers[index] = nonvirtualTrampoline; - index++; + int offset = field.getOffsetInfo().getProperty(); + setFunctionPointerTable(table, offset, nonvirtualTrampoline); } StructFieldInfo field = findFieldFor(functionTableMetadata, "NewObject" + suffix); - offsets[index] = field.getOffsetInfo().getProperty(); - pointers[index] = trampoline; - index++; + int offset = field.getOffsetInfo().getProperty(); + setFunctionPointerTable(table, offset, trampoline); } - VMError.guarantee(index == offsets.length && index == pointers.length); - JNIStructFunctionsInitializer initializer = new JNIStructFunctionsInitializer<>(JNINativeInterface.class, offsets, pointers, unimplemented); - access.registerAsImmutable(pointers); - access.registerAsImmutable(initializer); - return initializer; } private static StructFieldInfo findFieldFor(StructInfo info, String name) { @@ -272,4 +248,21 @@ private static StructFieldInfo findFieldFor(StructInfo info, String name) { } throw VMError.shouldNotReachHere("Cannot find JNI function table field for: " + name); } + + private static void initializeFunctionPointerTable(CompilationAccessImpl access, CFunctionPointer[] table, CFunctionPointer defaultValue) { + for (int i = 0; i < table.length; i++) { + table[i] = defaultValue; + } + /* + * All objects in the image heap that have function pointers, i.e., relocations, must be + * immutable at run time. + */ + access.registerAsImmutable(table); + } + + private static void setFunctionPointerTable(CFunctionPointer[] table, int offsetInBytes, CFunctionPointer value) { + int wordSize = FrameAccess.wordSize(); + VMError.guarantee(offsetInBytes % wordSize == 0); + table[offsetInBytes / wordSize] = value; + } } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIStructFunctionsInitializer.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIStructFunctionsInitializer.java deleted file mode 100644 index 873283157775..000000000000 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/functions/JNIStructFunctionsInitializer.java +++ /dev/null @@ -1,74 +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.jni.functions; - -import java.util.stream.IntStream; - -import org.graalvm.nativeimage.c.function.CFunctionPointer; -import org.graalvm.nativeimage.c.struct.SizeOf; -import org.graalvm.word.Pointer; -import org.graalvm.word.PointerBase; -import org.graalvm.word.WordBase; - -import com.oracle.svm.core.FrameAccess; -import com.oracle.svm.core.annotate.UnknownObjectField; -import com.oracle.svm.core.util.VMError; - -/** - * Initializes a function table struct at runtime by writing values to specific offsets. - */ -class JNIStructFunctionsInitializer { - private final int structSize; - - private WordBase defaultValue; - - @UnknownObjectField(types = int[].class) // - private int[] offsets; - - @UnknownObjectField(types = CFunctionPointer[].class) // - private CFunctionPointer[] functions; - - JNIStructFunctionsInitializer(Class structClass, int[] offsets, CFunctionPointer[] functions, WordBase defaultValue) { - this.structSize = SizeOf.get(structClass); - this.offsets = offsets; - this.functions = functions; - this.defaultValue = defaultValue; - - int wordSize = FrameAccess.wordSize(); - VMError.guarantee(structSize % wordSize == 0 && IntStream.of(offsets).allMatch(offset -> (offset % wordSize == 0)), - "Unaligned struct breaks default value initialization"); - } - - public void initialize(T structure) { - Pointer p = (Pointer) structure; - int wordSize = FrameAccess.wordSize(); - for (int k = 0; k + wordSize <= structSize; k += wordSize) { - p.writeWord(k, defaultValue); - } - for (int i = 0; i < offsets.length; i++) { - p.writeWord(offsets[i], functions[i]); - } - } -} From df33c8c57114486158d99f4e41ae55db9f3fc6ed Mon Sep 17 00:00:00 2001 From: Martin Entlicher Date: Thu, 3 Oct 2019 14:01:00 +0200 Subject: [PATCH 037/140] [GR-11634] Function breakpoints. --- .../test/SLInspectDebugTest.java | 181 ++++++++++++++++++ .../chromeinspector/BreakpointsHandler.java | 41 +++- .../chromeinspector/ConsoleUtilitiesAPI.java | 90 +++++++++ .../chromeinspector/InspectorDebugger.java | 66 ++++++- .../domains/DebuggerDomain.java | 2 + .../server/InspectServerSession.java | 6 + truffle/CHANGELOG.md | 2 + .../api/debug/test/BreakpointTest.java | 135 +++++++++++++ .../oracle/truffle/api/debug/Breakpoint.java | 82 ++++++-- .../truffle/api/debug/BreakpointLocation.java | 25 ++- .../oracle/truffle/api/debug/DebugScope.java | 23 +++ .../oracle/truffle/api/debug/DebugValue.java | 28 +++ .../truffle/api/debug/DebuggerSession.java | 27 ++- .../test/InstrumentationTestLanguage.java | 48 ++--- .../truffle/api/interop/InteropAccessor.java | 5 + .../src/com/oracle/truffle/api/Scope.java | 43 ++++- .../com/oracle/truffle/api/impl/Accessor.java | 2 + .../oracle/truffle/sl/test/SLDebugTest.java | 105 ++++++++++ .../src/com/oracle/truffle/sl/SLLanguage.java | 9 +- .../truffle/sl/nodes/SLStatementNode.java | 6 +- .../sl/nodes/local/SLLexicalScope.java | 4 +- 21 files changed, 865 insertions(+), 65 deletions(-) create mode 100644 tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/ConsoleUtilitiesAPI.java diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/SLInspectDebugTest.java b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/SLInspectDebugTest.java index f093515e5aed..fa88fc76eb85 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/SLInspectDebugTest.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/SLInspectDebugTest.java @@ -144,6 +144,26 @@ public class SLInspectDebugTest { "function fn() {\n" + " return 2;\n" + "}\n"; + private static final String GUEST_FUNCTIONS = "function main() {\n" + + " foo0();\n" + + " foo1();\n" + + " foo0();\n" + + " foo1();\n" + + "}\n" + + "function foo0() {\n" + + " n = 0;" + + "}\n" + + "function foo1() {\n" + + " n = 1;" + + "}\n"; + private static final String BUILTIN_FUNCTIONS = "function main() {\n" + + " isExecutable(a);\n" + + " nanoTime();\n" + + " isNull(a);\n" + + " isExecutable(a);\n" + + " isNull(b);\n" + + " nanoTime();\n" + + "}\n"; private static final String SL_BUILTIN_URI = "SL builtin"; private InspectorTester tester; @@ -514,6 +534,167 @@ public void testBreakpointDeactivation() throws Exception { tester.finish(); } + @Test + public void testGuestFunctionBreakpoints() throws Exception { + testGuestFunctionBreakpoints(false); + } + + private void testGuestFunctionBreakpoints(boolean useConsoleUtilities) throws Exception { + tester = InspectorTester.start(true); + Source source = Source.newBuilder("sl", GUEST_FUNCTIONS, "SLTest.sl").build(); + String slTestURI = InspectorTester.getStringURI(source.getURI()); + tester.sendMessage("{\"id\":1,\"method\":\"Runtime.enable\"}"); + tester.sendMessage("{\"id\":2,\"method\":\"Debugger.enable\"}"); + tester.sendMessage("{\"id\":3,\"method\":\"Runtime.runIfWaitingForDebugger\"}"); + assertTrue(tester.compareReceivedMessages("{\"result\":{},\"id\":1}\n" + + "{\"result\":{},\"id\":2}\n" + + "{\"result\":{},\"id\":3}\n" + + "{\"method\":\"Runtime.executionContextCreated\",\"params\":{\"context\":{\"origin\":\"\",\"name\":\"test\",\"id\":1}}}\n")); + tester.eval(source); + long id = tester.getContextId(); + + // Suspend at the beginning of the script: + assertTrue(tester.compareReceivedMessages( + "{\"method\":\"Debugger.scriptParsed\",\"params\":{\"endLine\":0,\"scriptId\":\"0\",\"endColumn\":0,\"startColumn\":0,\"startLine\":0,\"length\":0,\"executionContextId\":" + id + ",\"url\":\"" + SL_BUILTIN_URI + "\",\"hash\":\"ffffffffffffffffffffffffffffffffffffffff\"}}\n" + + "{\"method\":\"Debugger.scriptParsed\",\"params\":{\"endLine\":9,\"scriptId\":\"1\",\"endColumn\":9,\"startColumn\":0,\"startLine\":0,\"length\":116,\"executionContextId\":" + id + ",\"url\":\"" + slTestURI + "\",\"hash\":\"e5d2cd9aefc7cdf3fc01da4bfe94b4d3ff485978\"}}\n" + + "{\"method\":\"Debugger.paused\",\"params\":{\"reason\":\"other\",\"hitBreakpoints\":[]," + + "\"callFrames\":[{\"callFrameId\":\"0\",\"functionName\":\"main\"," + + "\"scopeChain\":[{\"name\":\"main\",\"type\":\"local\",\"object\":{\"description\":\"main\",\"type\":\"object\",\"objectId\":\"1\"}}," + + "{\"name\":\"global\",\"type\":\"global\",\"object\":{\"description\":\"global\",\"type\":\"object\",\"objectId\":\"2\"}}]," + + "\"this\":{\"subtype\":\"null\",\"description\":\"NULL\",\"type\":\"object\",\"objectId\":\"3\"}," + + "\"functionLocation\":{\"scriptId\":\"1\",\"columnNumber\":9,\"lineNumber\":0}," + + "\"location\":{\"scriptId\":\"1\",\"columnNumber\":2,\"lineNumber\":1}," + + "\"url\":\"" + slTestURI + "\"}]}}\n")); + int objectId = 4; + if (useConsoleUtilities) { + tester.sendMessage("{\"id\":6,\"method\":\"Debugger.evaluateOnCallFrame\",\"params\":{\"callFrameId\":\"0\",\"expression\":\"debug(foo0)\",\"objectGroup\":\"console\",\"includeCommandLineAPI\":true,\"silent\":false,\"returnByValue\":false,\"generatePreview\":true}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":6}\n")); + } else { + tester.sendMessage("{\"id\":5,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"foo0\"}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{\"result\":{\"description\":\"Function foo0\",\"className\":\"Function\",\"type\":\"function\",\"objectId\":\"4\"}},\"id\":5}\n")); + tester.sendMessage("{\"id\":6,\"method\":\"Debugger.setBreakpointOnFunctionCall\",\"params\":{\"objectId\":\"" + (objectId++) + "\"}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{\"breakpointId\":\"1\"},\"id\":6}\n")); + } + tester.sendMessage("{\"id\":7,\"method\":\"Debugger.resume\"}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":7}\n" + + "{\"method\":\"Debugger.resumed\"}\n")); + assertTrue(tester.compareReceivedMessages( + "{\"method\":\"Debugger.paused\",\"params\":{\"reason\":\"other\",\"hitBreakpoints\":[\"1\"]," + + "\"callFrames\":[{\"callFrameId\":\"0\",\"functionName\":\"foo0\"," + + "\"scopeChain\":[{\"name\":\"foo0\",\"type\":\"local\",\"object\":{\"description\":\"foo0\",\"type\":\"object\",\"objectId\":\"" + (objectId++) + "\"}}," + + "{\"name\":\"global\",\"type\":\"global\",\"object\":{\"description\":\"global\",\"type\":\"object\",\"objectId\":\"" + (objectId++) + "\"}}]," + + "\"this\":{\"subtype\":\"null\",\"description\":\"NULL\",\"type\":\"object\",\"objectId\":\"" + (objectId++) + "\"}," + + "\"functionLocation\":{\"scriptId\":\"1\",\"columnNumber\":9,\"lineNumber\":6}," + + "\"location\":{\"scriptId\":\"1\",\"columnNumber\":9,\"lineNumber\":6}," + + "\"url\":\"" + slTestURI + "\"}," + + "{\"callFrameId\":\"1\",\"functionName\":\"main\"," + + "\"scopeChain\":[{\"name\":\"main\",\"type\":\"local\",\"object\":{\"description\":\"main\",\"type\":\"object\",\"objectId\":\"" + (objectId++) + "\"}}," + + "{\"name\":\"global\",\"type\":\"global\",\"object\":{\"description\":\"global\",\"type\":\"object\",\"objectId\":\"" + (objectId++) + "\"}}]," + + "\"this\":{\"subtype\":\"null\",\"description\":\"NULL\",\"type\":\"object\",\"objectId\":\"" + (objectId++) + "\"}," + + "\"functionLocation\":{\"scriptId\":\"1\",\"columnNumber\":9,\"lineNumber\":0}," + + "\"location\":{\"scriptId\":\"1\",\"columnNumber\":2,\"lineNumber\":1}," + + "\"url\":\"" + slTestURI + "\"}]}}\n")); + if (useConsoleUtilities) { + tester.sendMessage("{\"id\":8,\"method\":\"Debugger.evaluateOnCallFrame\",\"params\":{\"callFrameId\":\"0\",\"expression\":\"undebug(foo0)\",\"objectGroup\":\"console\",\"includeCommandLineAPI\":true,\"silent\":false,\"returnByValue\":false,\"generatePreview\":true}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":8}\n")); + } else { + tester.sendMessage("{\"id\":8,\"method\":\"Debugger.removeBreakpoint\",\"params\":{\"breakpointId\":\"1\"}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":8}\n")); + } + // Resume to finish: + tester.sendMessage("{\"id\":10,\"method\":\"Debugger.resume\"}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":10}\n" + + "{\"method\":\"Debugger.resumed\"}\n")); + tester.finish(); + } + + @Test + public void testBuiltInFunctionBreakpoints() throws Exception { + testBuiltInFunctionBreakpoints(false); + } + + private void testBuiltInFunctionBreakpoints(boolean useConsoleUtilities) throws Exception { + tester = InspectorTester.start(true); + Source source = Source.newBuilder("sl", BUILTIN_FUNCTIONS, "SLTest.sl").build(); + String slTestURI = InspectorTester.getStringURI(source.getURI()); + tester.sendMessage("{\"id\":1,\"method\":\"Runtime.enable\"}"); + tester.sendMessage("{\"id\":2,\"method\":\"Debugger.enable\"}"); + tester.sendMessage("{\"id\":3,\"method\":\"Runtime.runIfWaitingForDebugger\"}"); + assertTrue(tester.compareReceivedMessages("{\"result\":{},\"id\":1}\n" + + "{\"result\":{},\"id\":2}\n" + + "{\"result\":{},\"id\":3}\n" + + "{\"method\":\"Runtime.executionContextCreated\",\"params\":{\"context\":{\"origin\":\"\",\"name\":\"test\",\"id\":1}}}\n")); + tester.eval(source); + long id = tester.getContextId(); + + // Suspend at the beginning of the script: + assertTrue(tester.compareReceivedMessages( + "{\"method\":\"Debugger.scriptParsed\",\"params\":{\"endLine\":0,\"scriptId\":\"0\",\"endColumn\":0,\"startColumn\":0,\"startLine\":0,\"length\":0,\"executionContextId\":" + id + ",\"url\":\"" + SL_BUILTIN_URI + "\",\"hash\":\"ffffffffffffffffffffffffffffffffffffffff\"}}\n" + + "{\"method\":\"Debugger.scriptParsed\",\"params\":{\"endLine\":7,\"scriptId\":\"1\",\"endColumn\":1,\"startColumn\":0,\"startLine\":0,\"length\":112,\"executionContextId\":" + id + ",\"url\":\"" + slTestURI + "\",\"hash\":\"da38785ae156af96f047f02ffe94b4d3ff485978\"}}\n" + + "{\"method\":\"Debugger.paused\",\"params\":{\"reason\":\"other\",\"hitBreakpoints\":[]," + + "\"callFrames\":[{\"callFrameId\":\"0\",\"functionName\":\"main\"," + + "\"scopeChain\":[{\"name\":\"main\",\"type\":\"local\",\"object\":{\"description\":\"main\",\"type\":\"object\",\"objectId\":\"1\"}}," + + "{\"name\":\"global\",\"type\":\"global\",\"object\":{\"description\":\"global\",\"type\":\"object\",\"objectId\":\"2\"}}]," + + "\"this\":{\"subtype\":\"null\",\"description\":\"NULL\",\"type\":\"object\",\"objectId\":\"3\"}," + + "\"functionLocation\":{\"scriptId\":\"1\",\"columnNumber\":9,\"lineNumber\":0}," + + "\"location\":{\"scriptId\":\"1\",\"columnNumber\":2,\"lineNumber\":1}," + + "\"url\":\"" + slTestURI + "\"}]}}\n")); + int objectId = 4; + if (useConsoleUtilities) { + tester.sendMessage("{\"id\":6,\"method\":\"Debugger.evaluateOnCallFrame\",\"params\":{\"callFrameId\":\"0\",\"expression\":\"debug(isNull)\",\"objectGroup\":\"console\",\"includeCommandLineAPI\":true,\"silent\":false,\"returnByValue\":false,\"generatePreview\":true}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":6}\n")); + } else { + tester.sendMessage("{\"id\":5,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"isNull\"}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{\"result\":{\"description\":\"Function isNull\",\"className\":\"Function\",\"type\":\"function\",\"objectId\":\"" + objectId + "\"}},\"id\":5}\n")); + tester.sendMessage("{\"id\":6,\"method\":\"Debugger.setBreakpointOnFunctionCall\",\"params\":{\"objectId\":\"" + (objectId++) + "\"}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{\"breakpointId\":\"1\"},\"id\":6}\n")); + } + tester.sendMessage("{\"id\":7,\"method\":\"Debugger.resume\"}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":7}\n" + + "{\"method\":\"Debugger.resumed\"}\n")); + assertTrue(tester.compareReceivedMessages( + "{\"method\":\"Debugger.paused\",\"params\":{\"reason\":\"other\",\"hitBreakpoints\":[\"1\"]," + + "\"callFrames\":[{\"callFrameId\":\"0\",\"functionName\":\"main\"," + + "\"scopeChain\":[{\"name\":\"main\",\"type\":\"local\",\"object\":{\"description\":\"main\",\"type\":\"object\",\"objectId\":\"" + (objectId++) + "\"}}," + + "{\"name\":\"global\",\"type\":\"global\",\"object\":{\"description\":\"global\",\"type\":\"object\",\"objectId\":\"" + (objectId++) + "\"}}]," + + "\"this\":{\"subtype\":\"null\",\"description\":\"NULL\",\"type\":\"object\",\"objectId\":\"" + (objectId++) + "\"}," + + "\"functionLocation\":{\"scriptId\":\"1\",\"columnNumber\":9,\"lineNumber\":0}," + + "\"location\":{\"scriptId\":\"1\",\"columnNumber\":2,\"lineNumber\":3}," + + "\"url\":\"" + slTestURI + "\"}]}}\n")); + if (useConsoleUtilities) { + tester.sendMessage("{\"id\":8,\"method\":\"Debugger.evaluateOnCallFrame\",\"params\":{\"callFrameId\":\"0\",\"expression\":\"undebug(isNull)\",\"objectGroup\":\"console\",\"includeCommandLineAPI\":true,\"silent\":false,\"returnByValue\":false,\"generatePreview\":true}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":8}\n")); + } else { + tester.sendMessage("{\"id\":8,\"method\":\"Debugger.removeBreakpoint\",\"params\":{\"breakpointId\":\"1\"}}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":8}\n")); + } + // Resume to finish: + tester.sendMessage("{\"id\":10,\"method\":\"Debugger.resume\"}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":10}\n" + + "{\"method\":\"Debugger.resumed\"}\n")); + tester.finish(); + } + + @Test + public void testConsoleUtilitiesDebugUndebug() throws Exception { + testGuestFunctionBreakpoints(true); + testBuiltInFunctionBreakpoints(true); + } + @Test public void testScopes() throws Exception { tester = InspectorTester.start(true); diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/BreakpointsHandler.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/BreakpointsHandler.java index df874de78d07..e2c22c01c891 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/BreakpointsHandler.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/BreakpointsHandler.java @@ -24,9 +24,12 @@ */ package com.oracle.truffle.tools.chromeinspector; +import java.net.URI; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import java.util.regex.Pattern; @@ -34,7 +37,9 @@ import com.oracle.truffle.tools.utils.json.JSONObject; import com.oracle.truffle.api.debug.Breakpoint; +import com.oracle.truffle.api.debug.DebugValue; import com.oracle.truffle.api.debug.DebuggerSession; +import com.oracle.truffle.api.debug.SourceElement; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; @@ -45,7 +50,6 @@ import com.oracle.truffle.tools.chromeinspector.server.CommandProcessException; import com.oracle.truffle.tools.chromeinspector.types.Location; import com.oracle.truffle.tools.chromeinspector.types.Script; -import java.util.concurrent.atomic.AtomicReference; final class BreakpointsHandler { @@ -191,6 +195,41 @@ private static Breakpoint.Builder createBuilder(Source source, int line, int col return builder; } + Params createFunctionBreakpoint(DebugValue functionValue, String condition) { + SourceSection functionLocation = functionValue.getSourceLocation(); + Breakpoint.Builder builder; + if (functionLocation != null) { + builder = Breakpoint.newBuilder(functionLocation); + } else { + builder = Breakpoint.newBuilder((URI) null); + } + builder.rootInstance(functionValue); + builder.sourceElements(SourceElement.ROOT); + Breakpoint bp = builder.build(); + if (condition != null && !condition.isEmpty()) { + bp.setCondition(condition); + } + ds.install(bp); + long id; + synchronized (bpIDs) { + id = ++lastID; + bpIDs.put(bp, id); + } + JSONObject json = new JSONObject(); + json.put("breakpointId", Long.toString(id)); + return new Params(json); + } + + void removeFunctionBreakpoint(DebugValue functionValue) { + List breakpoints = functionValue.getRootInstanceBreakpoints(); + for (Breakpoint breakpoint : breakpoints) { + String id = getId(breakpoint); + if (id != null) { + removeBreakpoint(id); + } + } + } + private final class ResolvedHandler implements Breakpoint.ResolveListener { private final Supplier eventHandler; diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/ConsoleUtilitiesAPI.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/ConsoleUtilitiesAPI.java new file mode 100644 index 000000000000..5039126cd2ee --- /dev/null +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/ConsoleUtilitiesAPI.java @@ -0,0 +1,90 @@ +/* + * 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.truffle.tools.chromeinspector; + +import com.oracle.truffle.api.debug.DebugValue; + +/** + * Console Utilities API. The API is described at + * https:// + * developers.google.com/web/tools/chrome-devtools/console/utilities. + */ +public final class ConsoleUtilitiesAPI { + + enum Method { + DEBUG("debug"), + UNDEBUG("undebug"); + + private final String method; + + Method(String method) { + this.method = method; + } + + String getMethod() { + return method; + } + } + + private final Method method; + private final String expression; + + private ConsoleUtilitiesAPI(Method method, String expression) { + this.method = method; + this.expression = expression; + } + + public static ConsoleUtilitiesAPI parse(String expression) { + for (Method method : Method.values()) { + if (expression.startsWith(method.getMethod())) { + int i = method.getMethod().length(); + while (i < expression.length() && Character.isWhitespace(expression.charAt(i))) { + i++; + } + if (i < expression.length() && expression.charAt(i) == '(' && expression.endsWith(")")) { + return new ConsoleUtilitiesAPI(method, expression.substring(i + 1, expression.length() - 1).trim()); + } + } + } + return null; + } + + public String getExpression() { + return expression; + } + + public DebugValue process(DebugValue value, BreakpointsHandler breakpointsHandler) { + switch (method) { + case DEBUG: + breakpointsHandler.createFunctionBreakpoint(value, null); + return null; + case UNDEBUG: + breakpointsHandler.removeFunctionBreakpoint(value); + return null; + default: + throw new IllegalStateException("Unknown API method " + method.name()); + } + } +} 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 9f279d6846e0..53c9dc096615 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 @@ -368,7 +368,7 @@ private CallFrame[] createCallFrames(Iterable frames, SuspendAn for (DebugStackFrame frame : frames) { depthAll++; SourceSection sourceSection = frame.getSourceSection(); - if (sourceSection == null) { + if (sourceSection == null || !sourceSection.isAvailable()) { continue; } if (!context.isInspectInternal() && frame.isInternal()) { @@ -532,6 +532,34 @@ public Params setBreakpoint(Location location, String condition) throws CommandP return breakpointsHandler.createBreakpoint(location, condition); } + @Override + public Params setBreakpointOnFunctionCall(String functionObjectId, String condition) throws CommandProcessException { + if (functionObjectId == null) { + throw new CommandProcessException("Must specify function object ID."); + } + RemoteObject functionObject = context.getRemoteObjectsHandler().getRemote(functionObjectId); + if (functionObject != null) { + DebugValue functionValue = functionObject.getDebugValue(); + try { + return context.executeInSuspendThread(new SuspendThreadExecutable() { + @Override + public Params executeCommand() throws CommandProcessException { + return breakpointsHandler.createFunctionBreakpoint(functionValue, condition); + } + + @Override + public Params processException(DebugException dex) { + return new Params(new JSONObject()); + } + }); + } catch (NoSuspendedThreadException e) { + return new Params(new JSONObject()); + } + } else { + throw new CommandProcessException("Function with object ID " + functionObjectId + " does not exist."); + } + } + @Override public void removeBreakpoint(String id) throws CommandProcessException { if (!breakpointsHandler.removeBreakpoint(id)) { @@ -553,13 +581,13 @@ static String getEvalNonInteractiveMessage() { } @Override - public Params evaluateOnCallFrame(String callFrameId, String expression, String objectGroup, + public Params evaluateOnCallFrame(String callFrameId, String expressionOrig, String objectGroup, boolean includeCommandLineAPI, boolean silent, boolean returnByValue, boolean generatePreview, boolean throwOnSideEffect) throws CommandProcessException { if (callFrameId == null) { throw new CommandProcessException("A callFrameId required."); } - if (expression == null) { + if (expressionOrig == null) { throw new CommandProcessException("An expression required."); } int frameId; @@ -568,6 +596,18 @@ public Params evaluateOnCallFrame(String callFrameId, String expression, String } catch (NumberFormatException ex) { throw new CommandProcessException(ex.getLocalizedMessage()); } + ConsoleUtilitiesAPI cuAPI; + if (includeCommandLineAPI) { + cuAPI = ConsoleUtilitiesAPI.parse(expressionOrig); + } else { + cuAPI = null; + } + final String expression; + if (cuAPI != null) { + expression = cuAPI.getExpression(); + } else { + expression = expressionOrig; + } JSONObject jsonResult; try { jsonResult = context.executeInSuspendThread(new SuspendThreadExecutable() { @@ -578,11 +618,13 @@ public JSONObject executeCommand() throws CommandProcessException { } CallFrame cf = suspendedInfo.getCallFrames()[frameId]; JSONObject json = new JSONObject(); - DebugValue value; - try { - value = cf.getFrame().eval(expression); - } catch (IllegalStateException ex) { - value = getVarValue(expression, cf); + DebugValue value = getVarValue(expression, cf); + if (value == null) { + try { + value = cf.getFrame().eval(expression); + } catch (IllegalStateException ex) { + // Not an interactive language + } } if (value == null) { LanguageInfo languageInfo = cf.getFrame().getLanguage(); @@ -597,6 +639,12 @@ public JSONObject executeCommand() throws CommandProcessException { } } if (value != null) { + if (cuAPI != null) { + value = cuAPI.process(value, breakpointsHandler); + if (value == null) { + return json; + } + } RemoteObject ro = new RemoteObject(value, generatePreview, context); context.getRemoteObjectsHandler().register(ro); json.put("result", ro.toJSON()); @@ -899,7 +947,7 @@ public void onSuspend(SuspendedEvent se) { // Debugger has been disabled while waiting on locks return; } - if (se.hasSourceElement(SourceElement.ROOT) && !se.hasSourceElement(SourceElement.STATEMENT) && se.getSuspendAnchor() == SuspendAnchor.BEFORE) { + if (se.hasSourceElement(SourceElement.ROOT) && !se.hasSourceElement(SourceElement.STATEMENT) && se.getSuspendAnchor() == SuspendAnchor.BEFORE && se.getBreakpoints().isEmpty()) { // Suspend requested and we're at the begining of a ROOT. debuggerSession.suspendNextExecution(); return; diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/domains/DebuggerDomain.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/domains/DebuggerDomain.java index 98f0b8dc3bd2..daa77b924522 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/domains/DebuggerDomain.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/domains/DebuggerDomain.java @@ -68,6 +68,8 @@ protected DebuggerDomain() { public abstract Params setBreakpoint(Location location, String condition) throws CommandProcessException; + public abstract Params setBreakpointOnFunctionCall(String functionObjectId, String condition) throws CommandProcessException; + public abstract void removeBreakpoint(String id) throws CommandProcessException; public abstract void continueToLocation(Location location, CommandPostProcessor postProcessor) throws CommandProcessException; diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/server/InspectServerSession.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/server/InspectServerSession.java index 54a54d71cfdc..333fe32ad969 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/server/InspectServerSession.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/server/InspectServerSession.java @@ -408,6 +408,12 @@ private Params doProcessCommand(Command cmd, CommandPostProcessor postProcessor) Location.create(json.getJSONObject("location")), json.optString("condition")); break; + case "Debugger.setBreakpointOnFunctionCall": + json = cmd.getParams().getJSONObject(); + resultParams = debugger.setBreakpointOnFunctionCall( + json.optString("objectId"), + json.optString("condition")); + break; case "Debugger.removeBreakpoint": debugger.removeBreakpoint(cmd.getParams().getBreakpointId()); break; diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 5d646f2abe2e..9d599b2f38cf 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -14,6 +14,8 @@ This changelog summarizes major changes between Truffle versions relevant to lan * Added new experimental inlining heuristic in which inlining budgets are based on Graal IR node counts and not Truffle Node counts. Enable with `-Dgraal.TruffleLanguageAgnosticInlining=true`. * Deprecated `DynamicObject#isEmpty()`, `DynamicObject#size()`; use `Shape#getPropertyCount()` instead. * Deprecated `Shape#getPropertyList(Pred)`, `Shape#getKeyList(Pred)`, `Shape#hasTransitionWithKey(Object)`, `Shape.Allocator#locationForValue(Object, EnumSet)` without replacement. +* Added [Scope.Builder#rootInstance(Object)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.Builder.html#rootInstance-java.lang.Object-), [Scope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.html#getRootInstance--) and [DebugScope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugScope.html#getRootInstance--) to provide an instance of guest language representation of the root node (e.g. a guest language function). +* Debugger breakpoints can be restricted to a particular root instance via [Breakpoint.Builder#rootInstance(DebugValue)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/Breakpoint.Builder.html#rootInstance-com.oracle.truffle.api.debug.DebugValue-) and found later on via [DebugValue#getRootInstanceBreakpoints()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugValue.html#getRootInstanceBreakpoints--). ## Version 19.2.0 * Added sub-process output (error output) [redirection into OutputStream](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/ProcessHandler.Redirect.html#stream-java.io.OutputStream-). diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java index 4dc08535c58a..e1b37e04108f 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java @@ -56,6 +56,8 @@ import org.junit.Test; import com.oracle.truffle.api.debug.Breakpoint; +import com.oracle.truffle.api.debug.DebugScope; +import com.oracle.truffle.api.debug.DebugValue; import com.oracle.truffle.api.debug.Debugger; import com.oracle.truffle.api.debug.DebuggerSession; import com.oracle.truffle.api.debug.SourceElement; @@ -1101,6 +1103,139 @@ private void assertColumnPositionsTest(String source) throws Exception { tester.assertColumnBreakpointsResolution(source, "B", "R", InstrumentablePositionsTestLanguage.ID); } + @Test + public void testFunctionSensitiveBreakpoints1() throws Exception { + // Test ROOT breakpoint on foo0 + Source source = testSource("ROOT(\n" + + " DEFINE(foo0, ROOT()),\n" + + " DEFINE(foo1, ROOT()),\n" + + " STATEMENT,\n" + + " CALL(foo0),\n" + + " CALL(foo1)\n" + + ")\n"); + try (DebuggerSession session = startSession()) { + session.suspendNextExecution(); + startEval(source); + expectSuspended((SuspendedEvent event) -> { + checkState(event, 4, true, "STATEMENT"); + // Retrieve the function instance + DebugScope functionScope = session.getTopScope(source.getLanguage()); + DebugValue foo0 = functionScope.getDeclaredValue("foo0"); + Breakpoint breakpoint = Breakpoint.newBuilder(getSourceImpl(source)).rootInstance(foo0).sourceElements(SourceElement.ROOT).build(); + session.install(breakpoint); + }); + expectSuspended((SuspendedEvent event) -> { + // Suspend in foo0 only, not in foo1: + checkState(event, 2, true, " ROOT()"); + assertEquals(1, event.getBreakpoints().size()); + }); + expectDone(); + } + } + + @Test + public void testFunctionSensitiveBreakpoints2() throws Exception { + // Test all elements breakpoints on both foo0 and foo1. + // Both breakpoints are hit just once in every function. + Source source = testSource("ROOT(\n" + + " DEFINE(\n" + + " foo0, ROOT(\n" + + " STATEMENT,\n" + + " EXPRESSION)\n" + + " ),\n" + + " DEFINE(\n" + + " foo1, ROOT(\n" + + " STATEMENT,\n" + + " EXPRESSION)\n" + + " ),\n" + + " STATEMENT,\n" + + " CALL(foo0),\n" + + " CALL(foo1)\n" + + ")\n"); + try (DebuggerSession session = startSession()) { + session.suspendNextExecution(); + startEval(source); + String[] functions = new String[]{"foo0", "foo1"}; + final Breakpoint[] breakpoints = new Breakpoint[2]; + expectSuspended((SuspendedEvent event) -> { + checkState(event, 12, true, "STATEMENT"); + // Retrieve the function instances + DebugScope functionScope = session.getTopScope(source.getLanguage()); + for (int f = 0; f < functions.length; f++) { + DebugValue foo = functionScope.getDeclaredValue(functions[f]); + // Create breakpoints for all source elements: + breakpoints[f] = Breakpoint.newBuilder(getSourceImpl(source)).rootInstance(foo).sourceElements(SourceElement.values()).build(); + session.install(breakpoints[f]); + } + }); + for (int f = 0; f < functions.length; f++) { + int ff = f; + for (int iElem = 0; iElem < SourceElement.values().length; iElem++) { + int expectedLine = 5 * f + 3 + iElem; + expectSuspended((SuspendedEvent event) -> { + assertEquals(expectedLine, event.getSourceSection().getStartLine()); + List bpHit = event.getBreakpoints(); + assertEquals(1, bpHit.size()); + assertSame(breakpoints[ff], bpHit.get(0)); + }); + } + } + expectDone(); + } + } + + @Test + public void testFunctionSensitiveBreakpoints3() throws Exception { + // Test line breakpoints in foo0 and foo1. + // Only 2 out of 4 breakpoints are hit. + Source source = testSource("ROOT(\n" + + " DEFINE(foo0,\n" + + " ROOT(\n" + + " STATEMENT,\n" + + " EXPRESSION)\n" + + " ),\n" + + " DEFINE(foo1,\n" + + " ROOT(\n" + + " STATEMENT,\n" + + " EXPRESSION)\n" + + " ),\n" + + " STATEMENT,\n" + + " CALL(foo0),\n" + + " CALL(foo1)\n" + + ")\n"); + try (DebuggerSession session = startSession()) { + session.suspendNextExecution(); + startEval(source); + String[] functions = new String[]{"foo0", "foo1"}; + final Breakpoint[][] breakpoints = new Breakpoint[2][2]; + expectSuspended((SuspendedEvent event) -> { + checkState(event, 12, true, "STATEMENT"); + // Retrieve the function instances + DebugScope functionScope = session.getTopScope(source.getLanguage()); + for (int f = 0; f < functions.length; f++) { + DebugValue foo = functionScope.getDeclaredValue(functions[f]); + // Create breakpoints for two lines in the two functions: + breakpoints[f][0] = Breakpoint.newBuilder(getSourceImpl(source)).rootInstance(foo).lineIs(4).build(); + breakpoints[f][1] = Breakpoint.newBuilder(getSourceImpl(source)).rootInstance(foo).lineIs(9).build(); + for (Breakpoint b : breakpoints[f]) { + session.install(b); + } + } + }); + for (int f = 0; f < functions.length; f++) { + int ff = f; + int expectedLine = 5 * f + 4; + expectSuspended((SuspendedEvent event) -> { + assertEquals(expectedLine, event.getSourceSection().getStartLine()); + List bpHit = event.getBreakpoints(); + assertEquals(1, bpHit.size()); + assertSame(breakpoints[ff][ff], bpHit.get(0)); + }); + } + expectDone(); + } + } + @Test public void testStepOverBreakpoint() { final Source source = testSource("ROOT(\n" + 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 69cb393ace97..216858a9dd27 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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,7 +40,10 @@ */ package com.oracle.truffle.api.debug; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; import java.net.URI; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Objects; @@ -55,6 +58,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.Scope; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; @@ -168,6 +172,7 @@ public enum Kind { private final BreakpointLocation locationKey; private final boolean oneShot; private final BreakpointExceptionFilter exceptionFilter; + private final Reference rootInstanceRef; private final ResolveListener resolveListener; private volatile Debugger debugger; @@ -192,14 +197,17 @@ public enum Kind { private final AtomicReference> sourceBinding = new AtomicReference<>(); Breakpoint(BreakpointLocation key, SuspendAnchor suspendAnchor) { - this(key, suspendAnchor, false, null, null); + this(key, suspendAnchor, false, null, null, null); } - private Breakpoint(BreakpointLocation key, SuspendAnchor suspendAnchor, boolean oneShot, BreakpointExceptionFilter exceptionFilter, ResolveListener resolveListener) { + private Breakpoint(BreakpointLocation key, SuspendAnchor suspendAnchor, boolean oneShot, + BreakpointExceptionFilter exceptionFilter, Object rootInstance, + ResolveListener resolveListener) { this.locationKey = key; this.suspendAnchor = suspendAnchor; this.oneShot = oneShot; this.exceptionFilter = exceptionFilter; + this.rootInstanceRef = rootInstance != null ? new WeakReference<>(rootInstance) : null; this.resolveListener = resolveListener; this.enabled = true; } @@ -209,6 +217,7 @@ private Breakpoint() { this.suspendAnchor = SuspendAnchor.BEFORE; this.oneShot = false; this.exceptionFilter = null; + this.rootInstanceRef = null; this.resolveListener = null; } @@ -666,7 +675,7 @@ private void uninstall() { * * @throws BreakpointConditionFailure */ - boolean notifyIndirectHit(DebuggerNode source, DebuggerNode node, MaterializedFrame frame, DebugException exception) throws BreakpointConditionFailure { + boolean notifyIndirectHit(EventContext context, DebuggerNode source, DebuggerNode node, MaterializedFrame frame, DebugException exception) throws BreakpointConditionFailure { if (!isEnabled()) { return false; } @@ -674,6 +683,12 @@ boolean notifyIndirectHit(DebuggerNode source, DebuggerNode node, MaterializedFr if (source != node) { // We're testing a different breakpoint at the same location + if (rootInstanceRef != null) { + Object rootInstance = rootInstanceRef.get(); + if (rootInstance != null && rootInstance != getCurrentRootInstance(context, this, frame.materialize())) { + return false; + } + } AbstractBreakpointNode breakpointNode = ((AbstractBreakpointNode) node); if (!breakpointNode.testCondition(frame)) { return false; @@ -699,13 +714,13 @@ boolean notifyIndirectHit(DebuggerNode source, DebuggerNode node, MaterializedFr } @TruffleBoundary - private Object doBreak(DebuggerNode source, SessionList breakInSessions, MaterializedFrame frame, boolean onEnter, Object result, Throwable exception, + private Object doBreak(EventContext context, DebuggerNode source, SessionList breakInSessions, MaterializedFrame frame, boolean onEnter, Object result, Throwable exception, BreakpointConditionFailure failure) { - return doBreak(source, breakInSessions, frame, onEnter, result, exception, source, false, null, failure); + return doBreak(context, source, breakInSessions, frame, onEnter, result, exception, source, false, null, failure); } @TruffleBoundary - private Object doBreak(DebuggerNode source, SessionList breakInSessions, MaterializedFrame frame, boolean onEnter, Object result, Throwable exception, + private Object doBreak(EventContext context, DebuggerNode source, SessionList breakInSessions, MaterializedFrame frame, boolean onEnter, Object result, Throwable exception, Node throwLocation, boolean isCatchNodeComputed, DebugException.CatchLocation catchLocation, BreakpointConditionFailure failure) { if (!isEnabled()) { // make sure we do not cause break events if we got disabled already @@ -729,7 +744,7 @@ private Object doBreak(DebuggerNode source, SessionList breakInSessions, Materia } else { de = null; } - newResult = session.notifyCallback(source, frame, anchor, null, newResult, de, failure); + newResult = session.notifyCallback(context, source, frame, anchor, null, newResult, de, failure); } current = current.next; } @@ -750,6 +765,10 @@ Breakpoint getROWrapper() { return wrapper; } + Object getRootInstance() { + return rootInstanceRef != null ? rootInstanceRef.get() : null; + } + /** * Creates a new breakpoint builder based on a URI location. * @@ -821,12 +840,16 @@ public final class Builder { private ResolveListener resolveListener; private int ignoreCount; private boolean oneShot; + private DebugValue rootInstance; private SourceSection sourceSection; private SourceElement[] sourceElements; private Builder(Object key) { - Objects.requireNonNull(key); - this.key = key; + if (key == null) { + this.key = BreakpointLocation.ANY_SOURCE; + } else { + this.key = key; + } } private Builder(SourceSection key) { @@ -961,6 +984,18 @@ public Builder sourceElements(@SuppressWarnings("hiding") SourceElement... sourc return this; } + /** + * Specifies the breakpoint's root instance. The breakpoint will be hit only when the + * {@link DebugScope#getRootInstance()} matches to the provided one. + * + * @param rootInstance value of the root instance in which the breakpoint is to be hit. + * @since 19.3.0 + */ + public Builder rootInstance(@SuppressWarnings("hiding") DebugValue rootInstance) { + this.rootInstance = rootInstance; + return this; + } + /** * @return a new breakpoint instance of {@link Kind#SOURCE_LOCATION SOURCE_LOCATION} kind. * @@ -976,7 +1011,10 @@ public Breakpoint build() { } else { location = BreakpointLocation.create(key, sourceElements, line, column); } - Breakpoint breakpoint = new Breakpoint(location, anchor, oneShot, null, resolveListener); + Breakpoint breakpoint = new Breakpoint( + location, anchor, oneShot, null, + rootInstance != null ? rootInstance.get() : null, + resolveListener); breakpoint.setIgnoreCount(ignoreCount); return breakpoint; } @@ -1043,7 +1081,7 @@ public Breakpoint build() { } BreakpointLocation location = BreakpointLocation.create(sourceElements, suspensionFilter); BreakpointExceptionFilter efilter = new BreakpointExceptionFilter(caught, uncaught); - return new Breakpoint(location, SuspendAnchor.AFTER, false, efilter, null); + return new Breakpoint(location, SuspendAnchor.AFTER, false, efilter, null, null); } } @@ -1196,8 +1234,18 @@ protected void onReturnExceptional(VirtualFrame frame, Throwable exception) { @TruffleBoundary void doBreak(MaterializedFrame frame, SessionList debuggerSessions, BreakpointConditionFailure conditionError, Throwable exception, BreakpointExceptionFilter.Match matched) { Node throwLocation = getContext().getInstrumentedNode(); - getBreakpoint().doBreak(this, debuggerSessions, frame, false, null, exception, throwLocation, matched.isCatchNodeComputed, matched.catchLocation, conditionError); + getBreakpoint().doBreak(getContext(), this, debuggerSessions, frame, false, null, exception, throwLocation, matched.isCatchNodeComputed, matched.catchLocation, conditionError); + } + } + + @TruffleBoundary + private static Object getCurrentRootInstance(EventContext context, Breakpoint breakpoint, MaterializedFrame frame) { + Iterable localScopes = breakpoint.debugger.getEnv().findLocalScopes(context.getInstrumentedNode(), frame); + Iterator localScopesIterator = localScopes.iterator(); + if (localScopesIterator.hasNext()) { + return localScopesIterator.next().getRootInstance(); } + return null; } private abstract static class AbstractBreakpointNode extends DebuggerNode { @@ -1269,6 +1317,12 @@ protected final Object onNode(VirtualFrame frame, boolean onEnter, Object result if (sessions == null) { return result; } + if (breakpoint.rootInstanceRef != null) { + Object rootInstance = breakpoint.rootInstanceRef.get(); + if (rootInstance != null && rootInstance != getCurrentRootInstance(context, breakpoint, frame.materialize())) { + return result; + } + } if (!conditionExistsUnchanged.isValid()) { CompilerDirectives.transferToInterpreterAndInvalidate(); if (breakpoint.condition != null) { @@ -1288,7 +1342,7 @@ protected final Object onNode(VirtualFrame frame, boolean onEnter, Object result conditionError = e; } breakBranch.enter(); - return breakpoint.doBreak(this, sessions, frame.materialize(), onEnter, result, exception, conditionError); + return breakpoint.doBreak(context, this, sessions, frame.materialize(), onEnter, result, exception, conditionError); } @ExplodeLoop diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java index be15565e2e74..883d8d30c698 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java @@ -67,6 +67,8 @@ abstract class BreakpointLocation { */ static final BreakpointLocation ANY = new BreakpointSourceLocation(); + static final URI ANY_SOURCE = URI.create(""); + static BreakpointLocation create(Object key, SourceElement[] sourceElements, SourceSection sourceSection) { return new BreakpointSourceLocation(key, sourceElements, sourceSection); } @@ -125,7 +127,7 @@ private static final class BreakpointSourceLocation extends BreakpointLocation { */ BreakpointSourceLocation(Object key, SourceElement[] sourceElements, int line, int column) { assert key instanceof Source || key instanceof URI; - assert line > 0; + assert line > 0 || line == -1; assert column > 0 || column == -1; this.key = key; this.sourceElements = sourceElements; @@ -164,6 +166,14 @@ Predicate createSourcePredicate() { return null; } if (key instanceof URI) { + if (key == ANY_SOURCE) { + return new Predicate() { + @Override + public boolean test(Source s) { + return true; + } + }; + } final URI sourceUri = (URI) key; final String sourceRawPath = sourceUri.getRawPath() != null ? sourceUri.getRawPath() : sourceUri.getRawSchemeSpecificPart(); return new Predicate() { @@ -207,6 +217,9 @@ SourceSection adjustLocation(Source source, TruffleInstrument.Env env, SuspendAn if (key == null) { return null; } + if (line == -1) { + return source.createUnavailableSection(); + } boolean hasColumn = column > 0; SourceSection location = SuspendableLocationFinder.findNearest(source, sourceElements, line, column, suspendAnchor, env); if (location != null) { @@ -236,10 +249,12 @@ SourceSectionFilter createLocationFilter(Source source, SuspendAnchor suspendAnc if (key == null) { return f.tagIs(DebuggerTags.AlwaysHalt.class).build(); } - if (source != null) { - f.sourceIs(source); - } else { - f.sourceFilter(createSourceFilter()); + if (key != ANY_SOURCE) { + if (source != null) { + f.sourceIs(source); + } else { + f.sourceFilter(createSourceFilter()); + } } if (line != -1) { switch (suspendAnchor) { diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebugScope.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebugScope.java index 853864694a31..e12b71416528 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebugScope.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebugScope.java @@ -218,6 +218,29 @@ public DebugValue getReceiver() { return receiverValue; } + /** + * Get value that represents root instance of this scope. The value is an instance of guest + * language representation of the root node of this scope, e.g. a guest language function. + * + * @return the root instance value, or null when no such value exists. + * @since 19.3.0 + */ + public DebugValue getRootInstance() { + verifyValidState(); + DebugValue functionValue = null; + try { + Object function = scope.getRootInstance(); + if (function != null) { + functionValue = new DebugValue.HeapValue(session, getLanguage(), root.getName(), function); + } + } catch (ThreadDeath td) { + throw td; + } catch (Throwable ex) { + throw new DebugException(session, ex, language, null, true, null); + } + return functionValue; + } + /** * Get local variables declared in this scope, valid at the current suspension point. Call this * method on {@link #getParent() parent}, to get values of variables declared in parent scope, diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebugValue.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebugValue.java index 283502bdffd8..77fa6c265b01 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebugValue.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebugValue.java @@ -41,7 +41,10 @@ package com.oracle.truffle.api.debug; import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; import java.util.List; +import java.util.function.Consumer; import com.oracle.truffle.api.instrumentation.TruffleInstrument; import com.oracle.truffle.api.interop.InteropLibrary; @@ -208,6 +211,31 @@ public final boolean isNull() { return INTEROP.isNull(value); } + /** + * Get a list of breakpoints installed to the value's session and whose + * {@link Breakpoint.Builder#rootInstance(DebugValue) root instance} is this value. + * + * @return a list of breakpoints with this value as root instance + * @since 19.3.0 + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public final List getRootInstanceBreakpoints() { + Object value = get(); + List[] breakpoints = new List[]{null}; + getSession().visitBreakpoints(new Consumer() { + @Override + public void accept(Breakpoint b) { + if (b.getRootInstance() == value) { + if (breakpoints[0] == null) { + breakpoints[0] = new LinkedList<>(); + } + breakpoints[0].add(b); + } + } + }); + return breakpoints[0] != null ? breakpoints[0] : Collections.emptyList(); + } + /** * Provides properties representing an internal structure of this value. The returned collection * is not thread-safe. If the value is not {@link #isReadable() readable} then null diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java index 7da49830d8db..43ec959b6bc5 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java @@ -56,6 +56,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.Supplier; @@ -639,6 +640,14 @@ public List getBreakpoints() { return Collections.unmodifiableList(b); } + void visitBreakpoints(Consumer consumer) { + synchronized (this.breakpoints) { + for (Breakpoint b : this.breakpoints) { + consumer.accept(b); + } + } + } + /** * Set whether breakpoints are active in this session. This has no effect on breakpoints * enabled/disabled state. Breakpoints need to be active to actually break the execution. The @@ -860,7 +869,7 @@ SourceSection resolveSection(SourceSection section) { } @TruffleBoundary - Object notifyCallback(DebuggerNode source, MaterializedFrame frame, SuspendAnchor suspendAnchor, + Object notifyCallback(EventContext context, DebuggerNode source, MaterializedFrame frame, SuspendAnchor suspendAnchor, InputValuesProvider inputValuesProvider, Object returnValue, DebugException exception, BreakpointConditionFailure conditionFailure) { ThreadSuspension suspensionDisabled = threadSuspensions.get(); @@ -929,7 +938,7 @@ Object notifyCallback(DebuggerNode source, MaterializedFrame frame, SuspendAncho breakpointFailures.put(fb, conditionFailure.getConditionFailure()); } - Object newReturnValue = processBreakpointsAndStep(nodes, s, source, frame, suspendAnchor, + Object newReturnValue = processBreakpointsAndStep(context, nodes, s, source, frame, suspendAnchor, inputValuesProvider, returnValue, exception, breakpointFailures, new Supplier() { @Override @@ -1000,7 +1009,7 @@ public Caller visitFrame(FrameInstance frameInstance) { doSuspend(context, SuspendAnchor.AFTER, caller.frame, insertableNode, null, null, null, Collections.emptyList(), Collections.emptyMap()); } - private Object notifyCallerReturn(SteppingStrategy s, DebuggerNode source, SuspendAnchor suspendAnchor, Object returnValue) { + private Object notifyCallerReturn(EventContext context, SteppingStrategy s, DebuggerNode source, SuspendAnchor suspendAnchor, Object returnValue) { // SuspensionFilter: if (source.isStepNode()) { if (ignoreLanguageContextInitialization.get() && !source.getContext().isLanguageContextInitialized()) { @@ -1057,7 +1066,7 @@ public Caller visitFrame(FrameInstance frameInstance) { for (DebuggerNode node : nodes) { node.markAsDuplicate(this); } - Object newReturnValue = processBreakpointsAndStep(nodes, s, source, caller.frame, suspendAnchor, null, returnValue, null, null, new Supplier() { + Object newReturnValue = processBreakpointsAndStep(context, nodes, s, source, caller.frame, suspendAnchor, null, returnValue, null, null, new Supplier() { @Override public SuspendedContext get() { return SuspendedContext.create(caller.node, null); @@ -1067,7 +1076,7 @@ public SuspendedContext get() { } @SuppressWarnings("all") // The parameter breakpointFailures should not be assigned - private Object processBreakpointsAndStep(List nodes, SteppingStrategy s, DebuggerNode source, MaterializedFrame frame, + private Object processBreakpointsAndStep(EventContext context, List nodes, SteppingStrategy s, DebuggerNode source, MaterializedFrame frame, SuspendAnchor suspendAnchor, InputValuesProvider inputValuesProvider, Object returnValue, DebugException exception, Map breakpointFailures, Supplier contextSupplier) { List breaks = null; @@ -1079,7 +1088,7 @@ private Object processBreakpointsAndStep(List nodes, SteppingStrat boolean hit = true; BreakpointConditionFailure failure = null; try { - hit = breakpoint.notifyIndirectHit(source, node, frame, exception); + hit = breakpoint.notifyIndirectHit(context, source, node, frame, exception); } catch (BreakpointConditionFailure e) { failure = e; } @@ -1368,7 +1377,7 @@ private void doStepBefore(MaterializedFrame frame) { SuspendAnchor anchor = SuspendAnchor.BEFORE; SteppingStrategy steppingStrategy; if (suspendNext || suspendAll || (steppingStrategy = getSteppingStrategy(Thread.currentThread())) != null && steppingStrategy.isActiveOnStepTo(context, anchor)) { - notifyCallback(this, frame, anchor, null, null, null, null); + notifyCallback(context, this, frame, anchor, null, null, null, null); } } @@ -1377,7 +1386,7 @@ protected final Object doStepAfter(MaterializedFrame frame, Object result) { SuspendAnchor anchor = SuspendAnchor.AFTER; SteppingStrategy steppingStrategy = getSteppingStrategy(Thread.currentThread()); if (steppingStrategy != null && steppingStrategy.isActiveOnStepTo(context, anchor)) { - return notifyCallback(this, frame, anchor, this, result, null, null); + return notifyCallback(context, this, frame, anchor, this, result, null, null); } return result; } @@ -1483,7 +1492,7 @@ private void doReturn(MaterializedFrame frame, Object result) { } } if (steppingStrategy != null && steppingStrategy.isStopAfterCall()) { - Object newResult = notifyCallerReturn(steppingStrategy, this, SuspendAnchor.AFTER, result); + Object newResult = notifyCallerReturn(context, steppingStrategy, this, SuspendAnchor.AFTER, result); if (newResult != result) { throw getContext().createUnwind(new ChangedReturnInfo(newResult)); } 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 fdb979bfd539..56de1035bb02 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 @@ -1824,31 +1824,35 @@ protected Object findMetaObject(InstrumentContext context, Object obj) { @Override protected Iterable findLocalScopes(InstrumentContext context, Node node, Frame frame) { Iterable scopes = super.findLocalScopes(context, node, frame); + // arguments[0] contains 'this'. Add it to the default scope: Object[] arguments; - if (frame == null || (arguments = frame.getArguments()) == null || arguments.length == 0 || !(arguments[0] instanceof ThisArg)) { - return scopes; + Object thisObject; + if (frame != null && (arguments = frame.getArguments()) != null && arguments.length > 0 && arguments[0] instanceof ThisArg) { + thisObject = ((ThisArg) arguments[0]).thisElement; } else { - // arguments[0] contains 'this'. Add it to the default scope: - Object thisObject = ((ThisArg) arguments[0]).thisElement; - return new Iterable() { - @Override - public Iterator iterator() { - Iterator iterator = scopes.iterator(); - return new Iterator() { - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public Scope next() { - Scope scope = iterator.next(); - return Scope.newBuilder(scope.getName(), scope.getVariables()).node(scope.getNode()).receiver("THIS", thisObject).build(); - } - }; - } - }; + thisObject = null; } + // Find the current root instance - function. + Object function = context.callFunctions.findFunction(node.getRootNode().getName()); + return new Iterable() { + @Override + public Iterator iterator() { + Iterator iterator = scopes.iterator(); + return new Iterator() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Scope next() { + Scope scope = iterator.next(); + return Scope.newBuilder(scope.getName(), scope.getVariables()).node(scope.getNode()).arguments(scope.getArguments()).receiver("THIS", thisObject).rootInstance( + function).build(); + } + }; + } + }; } @Override diff --git a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropAccessor.java b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropAccessor.java index 7ac264ac3935..48334280ebc5 100644 --- a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropAccessor.java +++ b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/InteropAccessor.java @@ -66,6 +66,11 @@ public void checkInteropType(Object result) { InteropAccessNode.checkInteropType(result); } + @Override + public boolean isExecutableObject(Object value) { + return InteropLibrary.getFactory().getUncached().isExecutable(value); + } + @Override public Object createDefaultNodeObject(Node node) { return EmptyTruffleObject.INSTANCE; diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/Scope.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/Scope.java index e2ad0a893ce2..7dd2a9930e78 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/Scope.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/Scope.java @@ -62,6 +62,7 @@ public final class Scope { private final Object variables; private final Object receiver; private final String receiverName; + private final Object rootInstance; private Scope() { name = null; @@ -70,9 +71,10 @@ private Scope() { variables = null; receiver = null; receiverName = null; + rootInstance = null; } - Scope(String name, Node node, Object arguments, Object variables, Object receiver, String receiverName) { + Scope(String name, Node node, Object arguments, Object variables, Object receiver, String receiverName, Object rootInstance) { this.name = name; this.node = node; assertNullOrTruffleObject(arguments); @@ -82,6 +84,8 @@ private Scope() { assertNullOrInteropType(receiver); this.receiver = receiver; this.receiverName = receiverName; + assertNullOrInteropType(rootInstance); + this.rootInstance = rootInstance; } private static boolean assertTruffleObject(Object obj) { @@ -99,6 +103,12 @@ private static void assertNullOrInteropType(Object obj) { } } + private static void assertNullOrExecutable(Object obj) { + if (obj != null) { + assert LanguageAccessor.interopAccess().isExecutableObject(obj) : Objects.toString(obj); + } + } + /** * Create a new Scope builder. *

    @@ -186,6 +196,17 @@ public Object getReceiver() { return receiver; } + /** + * Get the root instance object of this scope. The object is an instance of guest language + * representation of the root node of this scope, e.g. a guest language function. + * + * @return the root instance object, or null when no such instance exists. + * @since 19.3.0 + */ + public Object getRootInstance() { + return rootInstance; + } + /** * Get code name of the receiver object, if there is any. * @@ -210,6 +231,7 @@ public final class Builder { private final Object variables; private Object receiver; private String receiverName; + private Object rootInstance; Builder(String name, Object variables) { assert name != null; @@ -266,13 +288,30 @@ public Builder receiver(String name, Object receiver) { return this; } + /** + * Set the root instance object of this scope. The object is an instance of guest language + * representation of the root node of this scope, e.g. a guest language function. It's + * supposed to be executable. + * + * @param rootInstance the root instance object, or null when no such instance + * exists. + * @since 19.3.0 + */ + @SuppressWarnings("hiding") + public Builder rootInstance(Object rootInstance) { + assertNullOrInteropType(rootInstance); + assertNullOrExecutable(rootInstance); + this.rootInstance = rootInstance; + return this; + } + /** * Uses configuration of this builder to create new {@link Scope} object. * * @since 0.30 */ public Scope build() { - return new Scope(name, node, arguments, variables, receiver, receiverName); + return new Scope(name, node, arguments, variables, receiver, receiverName, rootInstance); } } } 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 93677d944ebf..ab156963f515 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 @@ -193,6 +193,8 @@ public abstract static class InteropSupport { public abstract void checkInteropType(Object result); + public abstract boolean isExecutableObject(Object value); + public abstract Object createDefaultNodeObject(Node node); public abstract boolean isValidNodeObject(Object obj); diff --git a/truffle/src/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLDebugTest.java b/truffle/src/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLDebugTest.java index 48212df681f7..4f5fc4a24f5a 100644 --- a/truffle/src/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLDebugTest.java +++ b/truffle/src/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLDebugTest.java @@ -48,6 +48,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.net.URI; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -256,6 +257,110 @@ public void testBreakpoint() throws Throwable { } } + @Test + public void testGuestFunctionBreakpoints() throws Throwable { + final Source functions = slCode("function main() {\n" + + " a = fac;\n" + + " return fac(5);\n" + + "}\n" + + "function fac(n) {\n" + + " if (n <= 1) {\n" + + " return 1;\n" + // break + " }\n" + + " return n * facMin1(n);\n" + + "}\n" + + "function facMin1(n) {\n" + + " m = n - 1;\n" + + " return fac(m);\n" + + "}\n"); + try (DebuggerSession session = startSession()) { + session.suspendNextExecution(); + startEval(functions); + Breakpoint[] functionBreakpoint = new Breakpoint[]{null}; + + expectSuspended((SuspendedEvent event) -> { + event.prepareStepOver(1); + }); + expectSuspended((SuspendedEvent event) -> { + DebugValue fac = event.getTopStackFrame().getScope().getDeclaredValue("a"); + // Breakpoint in "fac" will not suspend in "facMin1". + Breakpoint breakpoint = Breakpoint.newBuilder(fac.getSourceLocation()).sourceElements(SourceElement.ROOT).rootInstance(fac).build(); + session.install(breakpoint); + functionBreakpoint[0] = breakpoint; + event.prepareContinue(); + }); + expectSuspended((SuspendedEvent event) -> { + Assert.assertEquals(5, event.getSourceSection().getStartLine()); + Assert.assertEquals(5, event.getTopStackFrame().getScope().getDeclaredValue("n").as(Number.class).intValue()); + event.prepareContinue(); + }); + expectSuspended((SuspendedEvent event) -> { + Assert.assertEquals(5, event.getSourceSection().getStartLine()); + Assert.assertEquals(4, event.getTopStackFrame().getScope().getDeclaredValue("n").as(Number.class).intValue()); + functionBreakpoint[0].dispose(); + event.prepareContinue(); + }); + expectDone(); + } + } + + @Test + public void testBuiltInFunctionBreakpoints() throws Throwable { + final Source functions = slCode("function main() {\n" + + " a = isNull;\n" + + " b = nanoTime;\n" + + " isNull(a);\n" + + " isExecutable(a);\n" + + " isNull(b);\n" + + " nanoTime();\n" + + " isNull(a);\n" + + " nanoTime();\n" + + "}\n"); + try (DebuggerSession session = startSession()) { + session.suspendNextExecution(); + startEval(functions); + Breakpoint[] functionBreakpoint = new Breakpoint[]{null}; + + expectSuspended((SuspendedEvent event) -> { + event.prepareStepOver(2); + }); + expectSuspended((SuspendedEvent event) -> { + DebugValue isNull = event.getTopStackFrame().getScope().getDeclaredValue("a"); + Breakpoint breakpoint = Breakpoint.newBuilder((URI) null).sourceElements(SourceElement.ROOT).rootInstance(isNull).build(); + session.install(breakpoint); + functionBreakpoint[0] = breakpoint; + event.prepareContinue(); + }); + expectSuspended((SuspendedEvent event) -> { + Assert.assertFalse(event.getSourceSection().isAvailable()); + Assert.assertEquals("isNull", event.getTopStackFrame().getName()); + Iterator frames = event.getStackFrames().iterator(); + frames.next(); // Skip the top one + DebugStackFrame mainFrame = frames.next(); + Assert.assertEquals(4, mainFrame.getSourceSection().getStartLine()); + // Dispose the breakpoint on isNull() and create one on nanoTime() instead: + functionBreakpoint[0].dispose(); + DebugValue nanoTime = mainFrame.getScope().getDeclaredValue("b"); + // Breakpoint in "fac" will not suspend in "facMin1". + Breakpoint breakpoint = Breakpoint.newBuilder(nanoTime.getSourceLocation()).sourceElements(SourceElement.ROOT).rootInstance(nanoTime).build(); + session.install(breakpoint); + functionBreakpoint[0] = breakpoint; + event.prepareContinue(); + }); + expectSuspended((SuspendedEvent event) -> { + Assert.assertFalse(event.getSourceSection().isAvailable()); + Assert.assertEquals("nanoTime", event.getTopStackFrame().getName()); + Iterator frames = event.getStackFrames().iterator(); + frames.next(); // Skip the top one + DebugStackFrame mainFrame = frames.next(); + Assert.assertEquals(7, mainFrame.getSourceSection().getStartLine()); + functionBreakpoint[0].dispose(); + event.prepareContinue(); + }); + expectDone(); + } + } + @Test public void testStepInOver() throws Throwable { /* 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 36506f92eaa6..943f61312474 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 @@ -380,11 +380,18 @@ public Scope next() { if (!hasNext()) { throw new NoSuchElementException(); } - Scope vscope = Scope.newBuilder(nextScope.getName(), nextScope.getVariables(frame)).node(nextScope.getNode()).arguments(nextScope.getArguments(frame)).build(); + Object functionObject = findFunctionObject(); + Scope vscope = Scope.newBuilder(nextScope.getName(), nextScope.getVariables(frame)).node(nextScope.getNode()).arguments(nextScope.getArguments(frame)).rootInstance( + functionObject).build(); previousScope = nextScope; nextScope = null; return vscope; } + + private Object findFunctionObject() { + String name = node.getRootNode().getName(); + return context.getFunctionRegistry().getFunction(name); + } }; } }; diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java index 6ef727829324..66339fc4d5e2 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java @@ -101,7 +101,11 @@ public final SourceSection getSourceSection() { } Source source = rootSourceSection.getSource(); if (sourceCharIndex == UNAVAILABLE_SOURCE) { - return source.createUnavailableSection(); + if (hasRootTag && !rootSourceSection.isAvailable()) { + return rootSourceSection; + } else { + return source.createUnavailableSection(); + } } else { return source.createSection(sourceCharIndex, sourceLength); } diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLLexicalScope.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLLexicalScope.java index 0f5b489a7242..7bcc026818d6 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLLexicalScope.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLLexicalScope.java @@ -60,6 +60,7 @@ import com.oracle.truffle.api.nodes.NodeVisitor; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.sl.nodes.SLEvalRootNode; +import com.oracle.truffle.sl.nodes.SLRootNode; import com.oracle.truffle.sl.nodes.SLStatementNode; import com.oracle.truffle.sl.nodes.controlflow.SLBlockNode; import com.oracle.truffle.sl.runtime.SLNull; @@ -112,7 +113,8 @@ public static SLLexicalScope createScope(Node node) { block = findChildrenBlock(node); if (block == null) { // Corrupted SL AST, no block was found - assert node.getRootNode() instanceof SLEvalRootNode : "Corrupted SL AST under " + node; + RootNode root = node.getRootNode(); + assert root instanceof SLEvalRootNode || root instanceof SLRootNode : "Corrupted SL AST under " + node; return new SLLexicalScope(null, null, (SLBlockNode) null); } node = null; // node is above the block From 546bbe745a67467885bc77bcacc3a4ee7d46ff4d Mon Sep 17 00:00:00 2001 From: Martin Entlicher Date: Thu, 3 Oct 2019 22:22:43 +0200 Subject: [PATCH 038/140] Function breakpoint on an internal function suspends on a non-internal caller. --- .../api/debug/test/BreakpointTest.java | 88 +++++++++++ .../oracle/truffle/api/debug/Breakpoint.java | 56 +++++-- .../truffle/api/debug/BreakpointLocation.java | 28 +++- .../truffle/api/debug/DebuggerSession.java | 140 ++++++++++-------- .../test/InstrumentationTestLanguage.java | 3 + 5 files changed, 237 insertions(+), 78 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java index e1b37e04108f..0e7eab481429 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java @@ -63,6 +63,7 @@ import com.oracle.truffle.api.debug.SourceElement; import com.oracle.truffle.api.debug.SuspendAnchor; import com.oracle.truffle.api.debug.SuspendedEvent; +import com.oracle.truffle.api.debug.SuspensionFilter; import com.oracle.truffle.api.instrumentation.test.InstrumentationTestLanguage; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.test.ReflectionUtils; @@ -1236,6 +1237,93 @@ public void testFunctionSensitiveBreakpoints3() throws Exception { } } + @Test + public void testFunctionSensitiveBreakpointsInternal() throws Exception { + // Test breakpoints hit on functions in internal source + Source source = testSource("ROOT(\n" + + " STATEMENT,\n" + + " CALL(foo0),\n" + + " CALL(foo1),\n" + + " CALL(foo2)\n" + + ")\n"); + Source internalSource = Source.newBuilder(InstrumentationTestLanguage.ID, "ROOT(\n" + + " DEFINE(foo0,\n" + + " ROOT(\n" + + " STATEMENT,\n" + + " EXPRESSION)\n" + + " ),\n" + + " DEFINE(foo1,\n" + + " ROOT(\n" + + " STATEMENT,\n" + + " EXPRESSION)\n" + + " ),\n" + + " DEFINE(foo2,\n" + + " ROOT(\n" + + " CALL(foo0),\n" + + " CALL(foo1))\n" + + " )\n" + + ")\n", "SLInternal.sl").internal(true).buildLiteral(); + boolean internalSession = false; + do { + try (DebuggerSession session = startSession()) { + session.setSteppingFilter(SuspensionFilter.newBuilder().includeInternal(internalSession).build()); + startEval(internalSource); + expectDone(); + session.suspendNextExecution(); + startEval(source); + String[] functions = new String[]{"foo0", "foo1"}; + final Breakpoint[] breakpoints = new Breakpoint[2]; + expectSuspended((SuspendedEvent event) -> { + checkState(event, 2, true, "STATEMENT"); + // Retrieve the function instances + DebugScope functionScope = session.getTopScope(source.getLanguage()); + for (int f = 0; f < functions.length; f++) { + DebugValue foo = functionScope.getDeclaredValue(functions[f]); + assertTrue(foo.getSourceLocation().getSource().isInternal()); + // Create breakpoint for the function, use the source section, or nothing: + Breakpoint.Builder builder; + if (f == 0) { + builder = Breakpoint.newBuilder(foo.getSourceLocation()); + } else { + builder = Breakpoint.newBuilder((URI) null); + } + breakpoints[f] = builder.rootInstance(foo).sourceElements(SourceElement.ROOT).build(); + session.install(breakpoints[f]); + } + }); + if (!internalSession) { + // Breakpoints hit in the non-internal source only + for (int f = 0; f < functions.length; f++) { + int ff = f; + int expectedLine = 3 + f; + expectSuspended((SuspendedEvent event) -> { + assertFalse(event.getSourceSection().getSource().isInternal()); + assertEquals(expectedLine, event.getSourceSection().getStartLine()); + List bpHit = event.getBreakpoints(); + assertEquals(1, bpHit.size()); + assertSame(breakpoints[ff], bpHit.get(0)); + }); + } + } else { + // Only in the internal session + // breakpoints are hit in the internal source in their bodies + for (int f = 0; f < functions.length * 2; f++) { + int ff = f % 2; + int expectedLine = 2 + 5 * ff; + expectSuspended((SuspendedEvent event) -> { + assertTrue(event.getSourceSection().getSource().isInternal()); + assertEquals(expectedLine, event.getSourceSection().getStartLine()); + List bpHit = event.getBreakpoints(); + assertEquals(1, bpHit.size()); + assertSame(breakpoints[ff], bpHit.get(0)); + }); + } + } + expectDone(); + } + } while ((internalSession = !internalSession) == true); + } + @Test public void testStepOverBreakpoint() { final Source source = testSource("ROOT(\n" + 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 216858a9dd27..406f72763e4b 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 @@ -714,14 +714,14 @@ boolean notifyIndirectHit(EventContext context, DebuggerNode source, DebuggerNod } @TruffleBoundary - private Object doBreak(EventContext context, DebuggerNode source, SessionList breakInSessions, MaterializedFrame frame, boolean onEnter, Object result, Throwable exception, - BreakpointConditionFailure failure) { - return doBreak(context, source, breakInSessions, frame, onEnter, result, exception, source, false, null, failure); + private Object doBreak(EventContext context, DebuggerNode source, SessionList breakInSessions, boolean activeOnNoninternalCalls, MaterializedFrame frame, boolean onEnter, Object result, + Throwable exception, BreakpointConditionFailure failure) { + return doBreak(context, source, breakInSessions, activeOnNoninternalCalls, frame, onEnter, result, exception, source, false, null, failure); } @TruffleBoundary - private Object doBreak(EventContext context, DebuggerNode source, SessionList breakInSessions, MaterializedFrame frame, boolean onEnter, Object result, Throwable exception, - Node throwLocation, boolean isCatchNodeComputed, DebugException.CatchLocation catchLocation, BreakpointConditionFailure failure) { + private Object doBreak(EventContext context, DebuggerNode source, SessionList breakInSessions, boolean activeOnNoninternalCalls, MaterializedFrame frame, boolean onEnter, Object result, + Throwable exception, Node throwLocation, boolean isCatchNodeComputed, DebugException.CatchLocation catchLocation, BreakpointConditionFailure failure) { if (!isEnabled()) { // make sure we do not cause break events if we got disabled already // the instrumentation framework will make sure that this is not happening if the @@ -737,14 +737,29 @@ private Object doBreak(EventContext context, DebuggerNode source, SessionList br SessionList current = breakInSessions; while (current != null) { DebuggerSession session = current.session; + // Test if the breakpoint is active and if it is internal compliant: if (session.isBreakpointsActive(getKind())) { - DebugException de; - if (exception != null) { - de = new DebugException(session, exception, null, throwLocation, isCatchNodeComputed, catchLocation); - } else { - de = null; + boolean internalCompliant = true; + DebuggerSession.Caller caller = null; + if (activeOnNoninternalCalls && !session.isIncludeInternal()) { + // We're on an internal source in a session that does not include internals, + // but we should suspend on a non-internal caller. + caller = DebuggerSession.findCurrentCaller(session, true); + internalCompliant = caller != null && !caller.node.getRootNode().isInternal(); + } + if (internalCompliant) { + DebugException de; + if (exception != null) { + de = new DebugException(session, exception, null, throwLocation, isCatchNodeComputed, catchLocation); + } else { + de = null; + } + if (caller != null) { + newResult = session.notifyAtCaller(context, caller, null, source, anchor, newResult, de, failure); + } else { + newResult = session.notifyCallback(context, source, frame, anchor, null, newResult, de, failure); + } } - newResult = session.notifyCallback(context, source, frame, anchor, null, newResult, de, failure); } current = current.next; } @@ -1234,7 +1249,8 @@ protected void onReturnExceptional(VirtualFrame frame, Throwable exception) { @TruffleBoundary void doBreak(MaterializedFrame frame, SessionList debuggerSessions, BreakpointConditionFailure conditionError, Throwable exception, BreakpointExceptionFilter.Match matched) { Node throwLocation = getContext().getInstrumentedNode(); - getBreakpoint().doBreak(getContext(), this, debuggerSessions, frame, false, null, exception, throwLocation, matched.isCatchNodeComputed, matched.catchLocation, conditionError); + getBreakpoint().doBreak(getContext(), this, debuggerSessions, activeOnNoninternalCalls, frame, false, null, exception, throwLocation, matched.isCatchNodeComputed, matched.catchLocation, + conditionError); } } @@ -1255,6 +1271,7 @@ private abstract static class AbstractBreakpointNode extends DebuggerNode { @Child private ConditionalBreakNode breakCondition; @CompilationFinal private Assumption conditionExistsUnchanged; + @CompilationFinal protected boolean activeOnNoninternalCalls; @CompilationFinal private SessionList sessionList; @CompilationFinal private Assumption sessionsUnchanged; @@ -1271,6 +1288,11 @@ private SessionList initializeSessions() { CompilerAsserts.neverPartOfCompilation(); synchronized (breakpoint) { boolean inInternalCode = context.getInstrumentedNode().getRootNode().isInternal(); + if (inInternalCode && (breakpoint.locationKey == null || breakpoint.locationKey.containsRoot()) && context.hasTag(SourceElement.ROOT.getTag())) { + // We're in internal code, but we're on a ROOT. We'll be active when parent call + // is not internal to show the call node to this root. + activeOnNoninternalCalls = true; + } SourceSection sourceSection = context.getInstrumentedSourceSection(); Source inSource; if (sourceSection != null) { @@ -1281,9 +1303,10 @@ private SessionList initializeSessions() { SessionList listEntry = null; List allSesssions = breakpoint.sessions; // traverse in inverse order to make the linked list in correct order + boolean inactiveInInternal = inInternalCode && !activeOnNoninternalCalls; for (int i = allSesssions.size() - 1; i >= 0; i--) { DebuggerSession session = allSesssions.get(i); - if (inInternalCode && !session.isIncludeInternal()) { + if (inactiveInInternal && !session.isIncludeInternal()) { continue; // filter session } if (inSource != null && session.isSourceFilteredOut(inSource)) { @@ -1342,7 +1365,7 @@ protected final Object onNode(VirtualFrame frame, boolean onEnter, Object result conditionError = e; } breakBranch.enter(); - return breakpoint.doBreak(context, this, sessions, frame.materialize(), onEnter, result, exception, conditionError); + return breakpoint.doBreak(context, this, sessions, activeOnNoninternalCalls, frame.materialize(), onEnter, result, exception, conditionError); } @ExplodeLoop @@ -1620,6 +1643,11 @@ public int getIgnoreCount() { return delegate.getIgnoreCount(); } + @Override + public Kind getKind() { + return delegate.getKind(); + } + @Override public String getLocationDescription() { return delegate.getLocationDescription(); diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java index 883d8d30c698..13aea5345749 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java @@ -62,6 +62,12 @@ */ abstract class BreakpointLocation { + protected final SourceElement[] sourceElements; + + protected BreakpointLocation(SourceElement[] sourceElements) { + this.sourceElements = sourceElements; + } + /** * A source location with {@code key == null} that always matches. */ @@ -81,6 +87,18 @@ static BreakpointLocation create(SourceElement[] sourceElements, SuspensionFilte return new BreakpointFilteredLocation(sourceElements, filter); } + final boolean containsRoot() { + if (sourceElements == null) { + return true; + } + for (SourceElement elem : sourceElements) { + if (SourceElement.ROOT == elem) { + return true; + } + } + return false; + } + abstract SourceFilter createSourceFilter(); abstract Predicate createSourcePredicate(); @@ -102,7 +120,6 @@ private static void setTags(SourceSectionFilter.Builder f, SourceElement[] sourc private static final class BreakpointSourceLocation extends BreakpointLocation { private final Object key; - private final SourceElement[] sourceElements; private final SourceSection sourceSection; private int line; private int column; @@ -112,9 +129,9 @@ private static final class BreakpointSourceLocation extends BreakpointLocation { * @param line 1-based line number, -1 for unspecified */ BreakpointSourceLocation(Object key, SourceElement[] sourceElements, SourceSection sourceSection) { + super(sourceElements); assert key instanceof Source || key instanceof URI; this.key = key; - this.sourceElements = sourceElements; this.sourceSection = sourceSection; this.line = -1; this.column = -1; @@ -126,19 +143,19 @@ private static final class BreakpointSourceLocation extends BreakpointLocation { * @param column 1-based column number, -1 for unspecified */ BreakpointSourceLocation(Object key, SourceElement[] sourceElements, int line, int column) { + super(sourceElements); assert key instanceof Source || key instanceof URI; assert line > 0 || line == -1; assert column > 0 || column == -1; this.key = key; - this.sourceElements = sourceElements; this.line = line; this.column = column; this.sourceSection = null; } private BreakpointSourceLocation() { + super(null); this.key = null; - this.sourceElements = null; this.line = -1; this.column = -1; this.sourceSection = null; @@ -301,11 +318,10 @@ public String toString() { private static final class BreakpointFilteredLocation extends BreakpointLocation { private final SuspensionFilter filter; - private final SourceElement[] sourceElements; BreakpointFilteredLocation(SourceElement[] sourceElements, SuspensionFilter filter) { + super(sourceElements); this.filter = filter; - this.sourceElements = sourceElements; } @Override diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java index 43ec959b6bc5..41018329b673 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java @@ -971,68 +971,19 @@ private void notifyUnwindCallback(MaterializedFrame frame, InsertableNode insert // Clear the frame that is to be re-entered clearFrame(((Node) insertableNode).getRootNode(), frame); // Fake the caller context - class Caller { - final Node node; - final MaterializedFrame frame; - - Caller(FrameInstance frameInstance) { - this.node = frameInstance.getCallNode(); - this.frame = frameInstance.getFrame(FrameAccess.MATERIALIZE).materialize(); - } - } - Caller[] nearestCaller = new Caller[1]; - Caller caller = Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor() { - private int depth = 0; - - @Override - public Caller visitFrame(FrameInstance frameInstance) { - // we stop at eval root stack frames - if (!SuspendedEvent.isEvalRootStackFrame(DebuggerSession.this, frameInstance) && (depth++ == 0)) { - return null; - } - Node callNode = frameInstance.getCallNode(); - // Prefer call node with a source section - if (callNode != null && callNode.getEncapsulatingSourceSection() != null) { - return new Caller(frameInstance); - } else { - if (nearestCaller[0] == null) { - nearestCaller[0] = new Caller(frameInstance); - } - return null; - } - } - }); - if (caller == null) { - caller = nearestCaller[0]; - } + Caller caller = findCurrentCaller(this, includeInternal); SuspendedContext context = SuspendedContext.create(caller.node, ((SteppingStrategy.Unwind) s).unwind); doSuspend(context, SuspendAnchor.AFTER, caller.frame, insertableNode, null, null, null, Collections.emptyList(), Collections.emptyMap()); } - private Object notifyCallerReturn(EventContext context, SteppingStrategy s, DebuggerNode source, SuspendAnchor suspendAnchor, Object returnValue) { - // SuspensionFilter: - if (source.isStepNode()) { - if (ignoreLanguageContextInitialization.get() && !source.getContext().isLanguageContextInitialized()) { - return returnValue; - } - } - // Fake the caller context - class Caller { - final Node node; - final MaterializedFrame frame; - - Caller(FrameInstance frameInstance, Node callNode) { - this.node = callNode; - this.frame = frameInstance.getFrame(FrameAccess.MATERIALIZE).materialize(); - } - } - Caller caller = Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor() { + static Caller findCurrentCaller(DebuggerSession session, boolean includeInternal) { + return Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor() { private int depth = 0; @Override public Caller visitFrame(FrameInstance frameInstance) { // we stop at eval root stack frames - if (!SuspendedEvent.isEvalRootStackFrame(DebuggerSession.this, frameInstance) && (depth++ == 0)) { + if (!SuspendedEvent.isEvalRootStackFrame(session, frameInstance) && (depth++ == 0)) { return null; } Node callNode = frameInstance.getCallNode(); @@ -1049,10 +1000,41 @@ public Caller visitFrame(FrameInstance frameInstance) { return new Caller(frameInstance, callNode); } }); + } + + private Object notifyCallerReturn(EventContext context, SteppingStrategy s, DebuggerNode source, SuspendAnchor suspendAnchor, Object returnValue) { + // SuspensionFilter: + if (source.isStepNode()) { + if (ignoreLanguageContextInitialization.get() && !source.getContext().isLanguageContextInitialized()) { + return returnValue; + } + } + // Fake the caller context + Caller caller = findCurrentCaller(this, includeInternal); if (caller == null) { // We did not find a caller node return returnValue; } + return notifyAtCaller(context, caller, s, source, suspendAnchor, returnValue, null, null); + } + + Object notifyAtCaller(EventContext context, Caller caller, SteppingStrategy s, DebuggerNode source, SuspendAnchor suspendAnchor, Object returnValue, DebugException exception, + BreakpointConditionFailure conditionFailure) { + ThreadSuspension suspensionDisabled = threadSuspensions.get(); + if (suspensionDisabled != null && !suspensionDisabled.enabled) { + return returnValue; + } + + Thread currentThread = Thread.currentThread(); + SuspendedEvent event = currentSuspendedEventMap.get(currentThread); + if (event != null) { + if (Debugger.TRACE) { + trace("ignored suspended reason: recursive from source:%s context:%s location:%s", source, source.getContext(), source.getSuspendAnchors()); + } + // avoid recursive suspensions in non legacy mode. + return returnValue; + } + List nodes = collectDebuggerNodes(caller.node, suspendAnchor); for (DebuggerNode node : nodes) { Breakpoint breakpoint = node.getBreakpoint(); @@ -1066,12 +1048,34 @@ public Caller visitFrame(FrameInstance frameInstance) { for (DebuggerNode node : nodes) { node.markAsDuplicate(this); } - Object newReturnValue = processBreakpointsAndStep(context, nodes, s, source, caller.frame, suspendAnchor, null, returnValue, null, null, new Supplier() { - @Override - public SuspendedContext get() { - return SuspendedContext.create(caller.node, null); + nodes.add(source); + + SteppingStrategy strategy = s; + if (strategy == null) { + strategy = getSteppingStrategy(currentThread); + if (strategy == null) { + // a new Thread just appeared + strategy = notifyNewThread(currentThread); } - }); + } + + Map breakpointFailures = null; + if (conditionFailure != null) { + breakpointFailures = new HashMap<>(); + Breakpoint fb = conditionFailure.getBreakpoint(); + if (fb.isGlobal()) { + fb = fb.getROWrapper(); + } + breakpointFailures.put(fb, conditionFailure.getConditionFailure()); + } + + Object newReturnValue = processBreakpointsAndStep(context, nodes, strategy, source, caller.frame, suspendAnchor, null, returnValue, exception, breakpointFailures, + new Supplier() { + @Override + public SuspendedContext get() { + return SuspendedContext.create(caller.node, null); + } + }); return newReturnValue; } @@ -1309,6 +1313,26 @@ private static Object evalInContext(SuspendedEvent ev, Node node, MaterializedFr } } + /** + * Information about a caller node. + */ + static final class Caller { + + final Node node; + final MaterializedFrame frame; + + Caller(FrameInstance frameInstance) { + this.node = frameInstance.getCallNode(); + this.frame = frameInstance.getFrame(FrameAccess.MATERIALIZE).materialize(); + } + + Caller(FrameInstance frameInstance, Node callNode) { + this.node = callNode; + this.frame = frameInstance.getFrame(FrameAccess.MATERIALIZE).materialize(); + } + + } + static final class ThreadSuspension { static final ThreadSuspension ENABLED = new ThreadSuspension(true); 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 56de1035bb02..4ae19b76d189 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 @@ -1866,6 +1866,9 @@ protected SourceSection findSourceLocation(InstrumentContext context, Object obj if (obj != null && obj.equals(Double.POSITIVE_INFINITY)) { return Source.newBuilder(ID, "source infinity", "double").build().createSection(1); } + if (obj instanceof Function) { + return ((RootCallTarget) ((Function) obj).ct).getRootNode().getSourceSection(); + } return null; } From c6c7df10a4d8638baa19fd5d0bbd19d1e58bf029 Mon Sep 17 00:00:00 2001 From: Dean Long Date: Wed, 2 Oct 2019 15:31:24 -0700 Subject: [PATCH 039/140] Fix JAOTC issues with JAR path containing spaces. --- .../src/jdk/tools/jaotc/collect/FileSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java b/compiler/src/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java index f8478a186a64..899087c22ecd 100644 --- a/compiler/src/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java +++ b/compiler/src/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java @@ -59,7 +59,7 @@ private static URI makeJarFileURI(Path path) { try { String name = path.toAbsolutePath().toString(); name = name.replace('\\', '/'); - return new URI("jar:file:///" + name + "!/"); + return new URI("jar:file", null, "///" + name + "!/", null); } catch (URISyntaxException e) { throw new InternalError(e); } From 2c3784a2da2a3e839784a5f79a74975522777a17 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 4 Oct 2019 20:06:29 +0200 Subject: [PATCH 040/140] Isolate-independent jmethodIDs. --- .../aarch64/SubstrateAArch64Backend.java | 12 ++++++++-- .../graal/amd64/SubstrateAMD64Backend.java | 12 ++++++++-- .../core/graal/llvm/SubstrateLLVMBackend.java | 19 ++++++++++++--- .../svm/core/graal/code/SubstrateBackend.java | 3 ++- .../jni/access/JNIReflectionDictionary.java | 24 ++++++++++++++++--- .../jni/hosted/JNICallTrampolineMethod.java | 16 ++++++++++++- 6 files changed, 74 insertions(+), 12 deletions(-) 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 85a0bf875f93..6ef7e062adef 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 @@ -843,12 +843,20 @@ public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig regis } @Override - public CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, CompilationIdentifier identifier, RegisterValue methodIdArg, int offset) { + public CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, CompilationIdentifier identifier, + RegisterValue threadArg, int threadIsolateOffset, RegisterValue methodIdArg, int methodObjEntryPointOffset) { + CompilationResult result = new CompilationResult(identifier); AArch64MacroAssembler asm = new AArch64MacroAssembler(getTarget()); try (ScratchRegister scratch = asm.getScratchRegister()) { Register scratchRegister = scratch.getRegister(); - asm.ldr(64, scratchRegister, AArch64Address.createUnscaledImmediateAddress(methodIdArg.getRegister(), offset)); + if (SubstrateOptions.SpawnIsolates.getValue()) { // method id is offset from heap base + asm.ldr(64, scratchRegister, AArch64Address.createUnscaledImmediateAddress(threadArg.getRegister(), threadIsolateOffset)); + asm.add(64, scratchRegister, scratchRegister, methodIdArg.getRegister()); + asm.ldr(64, scratchRegister, AArch64Address.createUnscaledImmediateAddress(scratchRegister, methodObjEntryPointOffset)); + } else { // method id is address of method object + asm.ldr(64, scratchRegister, AArch64Address.createUnscaledImmediateAddress(methodIdArg.getRegister(), methodObjEntryPointOffset)); + } asm.jmp(scratchRegister); } result.recordMark(asm.position(), SubstrateAArch64Backend.MARK_PROLOGUE_DECD_RSP); 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 e69a43c9208b..66fd838782b4 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 @@ -956,10 +956,18 @@ public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod i } @Override - public CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, CompilationIdentifier identifier, RegisterValue methodIdArg, int offset) { + public CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, CompilationIdentifier identifier, + RegisterValue threadArg, int threadIsolateOffset, RegisterValue methodIdArg, int methodObjEntryPointOffset) { + CompilationResult result = new CompilationResult(identifier); AMD64Assembler asm = new AMD64Assembler(getTarget()); - asm.jmp(new AMD64Address(methodIdArg.getRegister(), offset)); + if (SubstrateOptions.SpawnIsolates.getValue()) { // method id is offset from heap base + asm.movq(rax, new AMD64Address(threadArg.getRegister(), threadIsolateOffset)); + asm.addq(rax, methodIdArg.getRegister()); // address of JNIAccessibleMethod + asm.jmp(new AMD64Address(rax, methodObjEntryPointOffset)); + } else { // methodId is absolute address + asm.jmp(new AMD64Address(methodIdArg.getRegister(), methodObjEntryPointOffset)); + } result.recordMark(asm.position(), SubstrateAMD64Backend.MARK_PROLOGUE_DECD_RSP); result.recordMark(asm.position(), SubstrateAMD64Backend.MARK_PROLOGUE_END); byte[] instructions = asm.close(true); diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java index 4bc63a113f2d..3faabc4dc85e 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java @@ -29,6 +29,7 @@ import java.util.Collections; +import com.oracle.svm.core.SubstrateOptions; import org.bytedeco.javacpp.LLVM; import org.bytedeco.javacpp.LLVM.LLVMValueRef; import org.bytedeco.javacpp.LLVM.LLVMBasicBlockRef; @@ -71,7 +72,9 @@ public Phase newAddressLoweringPhase(CodeCacheProvider codeCache) { } @Override - public CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, CompilationIdentifier identifier, RegisterValue methodIdArg, int offset) { + public CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, CompilationIdentifier identifier, + RegisterValue threadArg, int threadIsolateOffset, RegisterValue methodIdArg, int methodObjEntryPointOffset) { + CompilationResult result = new CompilationResult(identifier); LLVMGenerationResult genResult = new LLVMGenerationResult(method); LLVMContextRef context = LLVM.LLVMContextCreate(); @@ -87,8 +90,18 @@ public CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, Co long startPatchpointId = LLVMIRBuilder.nextPatchpointId.getAndIncrement(); builder.buildStackmap(builder.constantLong(startPatchpointId)); - LLVMValueRef methodBase = builder.buildInlineGetRegister(methodIdArg.getRegister().name); - LLVMValueRef jumpAddressAddress = builder.buildGEP(builder.buildIntToPtr(methodBase, builder.rawPointerType()), builder.constantInt(offset)); + LLVMValueRef jumpAddressAddress; + if (SubstrateOptions.SpawnIsolates.getValue()) { + LLVMValueRef thread = builder.buildInlineGetRegister(threadArg.getRegister().name); + LLVMValueRef heapBaseAddress = builder.buildGEP(builder.buildIntToPtr(thread, builder.rawPointerType()), builder.constantInt(threadIsolateOffset)); + LLVMValueRef heapBase = builder.buildLoad(heapBaseAddress, builder.rawPointerType()); + LLVMValueRef methodId = builder.buildInlineGetRegister(methodIdArg.getRegister().name); + LLVMValueRef methodBase = builder.buildGEP(builder.buildIntToPtr(heapBase, builder.rawPointerType()), builder.buildIntToPtr(methodId, builder.rawPointerType())); + jumpAddressAddress = builder.buildGEP(methodBase, builder.constantInt(methodObjEntryPointOffset)); + } else { + LLVMValueRef methodBase = builder.buildInlineGetRegister(methodIdArg.getRegister().name); + jumpAddressAddress = builder.buildGEP(builder.buildIntToPtr(methodBase, builder.rawPointerType()), builder.constantInt(methodObjEntryPointOffset)); + } LLVMValueRef jumpAddress = builder.buildLoad(jumpAddressAddress, builder.rawPointerType()); builder.buildInlineJump(jumpAddress); builder.buildUnreachable(); diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/code/SubstrateBackend.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/code/SubstrateBackend.java index 9a1f40d0de57..0693e493fe33 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/code/SubstrateBackend.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/code/SubstrateBackend.java @@ -102,5 +102,6 @@ public static ValueNode getJavaFrameAnchor(CallTargetNode callTarget) { public abstract Phase newAddressLoweringPhase(CodeCacheProvider codeCache); - public abstract CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, CompilationIdentifier identifier, RegisterValue methodIdArg, int offset); + public abstract CompilationResult createJNITrampolineMethod(ResolvedJavaMethod method, CompilationIdentifier identifier, + RegisterValue threadArg, int threadIsolateOffset, RegisterValue methodIdArg, int methodObjEntryPointOffset); } 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 f2d8e82b0f20..a14aa0e7621b 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 @@ -35,12 +35,17 @@ import java.util.function.Function; import org.graalvm.compiler.word.Word; +import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform.HOSTED_ONLY; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.Pointer; +import org.graalvm.word.SignedWord; +import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; +import com.oracle.svm.core.Isolates; +import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.jni.nativeapi.JNIFieldId; @@ -200,12 +205,25 @@ public JNIMethodId getMethodID(Class classObject, String name, String signatu } private static JNIMethodId toMethodID(JNIAccessibleMethod method) { - // Using the address is safe because JNIAccessibleMethod is immutable (non-movable) - return (method != null) ? (JNIMethodId) Word.objectToUntrackedPointer(method) : WordFactory.nullPointer(); + SignedWord value = WordFactory.zero(); + if (method != null) { + value = Word.objectToUntrackedPointer(method); // safe because it is in the image heap + if (SubstrateOptions.SpawnIsolates.getValue()) { // use offset: valid across isolates + value = value.subtract((SignedWord) Isolates.getHeapBase(CurrentIsolate.getIsolate())); + } + } + return (JNIMethodId) value; } public static JNIAccessibleMethod getMethodByID(JNIMethodId method) { - Object obj = ((Pointer) method).toObject(); + Object obj = null; + if (method.notEqual(WordFactory.zero())) { + Pointer p = (Pointer) method; + if (SubstrateOptions.SpawnIsolates.getValue()) { + p = p.add((UnsignedWord) Isolates.getHeapBase(CurrentIsolate.getIsolate())); + } + obj = p.toObject(); + } return KnownIntrinsics.convertUnknownValue(obj, JNIAccessibleMethod.class); } diff --git a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNICallTrampolineMethod.java b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNICallTrampolineMethod.java index 6a47c1860574..a2dcf18dcb62 100644 --- a/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNICallTrampolineMethod.java +++ b/substratevm/src/com.oracle.svm.jni/src/com/oracle/svm/jni/hosted/JNICallTrampolineMethod.java @@ -32,13 +32,16 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.nativeimage.ImageSingletons; import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.meta.HostedProviders; +import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.graal.code.SubstrateBackend; import com.oracle.svm.core.graal.code.SubstrateCallingConventionType; import com.oracle.svm.core.graal.nodes.DeadEndNode; import com.oracle.svm.core.graal.nodes.UnreachableNode; +import com.oracle.svm.core.thread.VMThreads; import com.oracle.svm.hosted.annotation.CustomSubstitutionMethod; import com.oracle.svm.hosted.code.CompileQueue.CompileFunction; import com.oracle.svm.hosted.code.CompileQueue.ParseFunction; @@ -46,6 +49,7 @@ import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.meta.HostedUniverse; import com.oracle.svm.hosted.phases.HostedGraphKit; +import com.oracle.svm.hosted.thread.VMThreadMTFeature; import com.oracle.svm.jni.access.JNIAccessibleMethod; import com.oracle.svm.jni.nativeapi.JNIEnvironment; import com.oracle.svm.jni.nativeapi.JNIMethodId; @@ -119,9 +123,19 @@ public CompileFunction createCustomCompileFunction() { ResolvedJavaType returnType = providers.getWordTypes().getWordImplType(); CallingConvention callingConvention = backend.getCodeCache().getRegisterConfig().getCallingConvention( SubstrateCallingConventionType.NativeCall, returnType, parameters.toArray(new JavaType[0]), backend); + RegisterValue threadArg = null; + int threadIsolateOffset = -1; + if (SubstrateOptions.SpawnIsolates.getValue()) { + threadArg = (RegisterValue) callingConvention.getArgument(0); // JNIEnv + if (SubstrateOptions.MultiThreaded.getValue()) { + threadIsolateOffset = ImageSingletons.lookup(VMThreadMTFeature.class).offsetOf(VMThreads.IsolateTL); + } + // NOTE: GR-17030: JNI is currently broken in the single-threaded, multi-isolate + // case. Fixing this also requires changes to how trampolines are generated. + } RegisterValue methodIdArg = (RegisterValue) callingConvention.getArgument(parameters.size() - 1); - return backend.createJNITrampolineMethod(method, identifier, methodIdArg, getFieldOffset(providers)); + return backend.createJNITrampolineMethod(method, identifier, threadArg, threadIsolateOffset, methodIdArg, getFieldOffset(providers)); }; } From 9ba0267291c291149a768bcd0296ca1b827688c2 Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Wed, 2 Oct 2019 14:21:01 -0700 Subject: [PATCH 041/140] Fix resource bundle access problems for JDK 11 --- .../svm/core/jdk/LocalizationSupport.java | 4 ++-- .../core/jdk/ResourceBundleSubstitutions.java | 24 ++++++++++++++++++- .../com/oracle/svm/util/ModuleSupport.java | 21 ++++++++++++++++ .../com/oracle/svm/util/ModuleSupport.java | 6 +++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LocalizationSupport.java index e26dd4065e78..53b932dfd0be 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LocalizationSupport.java @@ -41,6 +41,7 @@ import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.option.OptionUtils; import com.oracle.svm.core.option.SubstrateOptionsParser; +import com.oracle.svm.util.ModuleSupport; public class LocalizationSupport { protected final Map charsets; @@ -72,8 +73,7 @@ public void addBundleToCache(String bundleName) { @Platforms(Platform.HOSTED_ONLY.class) ResourceBundle getBundleInDefaultLocale(String bundleName) { RuntimeClassInitialization.initializeAtBuildTime(bundleName); - final ResourceBundle result = ResourceBundle.getBundle(bundleName, Locale.getDefault(), Thread.currentThread().getContextClassLoader()); - return result; + return ModuleSupport.getResourceBundle(bundleName, Locale.getDefault(), Thread.currentThread().getContextClassLoader()); } @Platforms(Platform.HOSTED_ONLY.class) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ResourceBundleSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ResourceBundleSubstitutions.java index 2e6309ac9229..038388c3080f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ResourceBundleSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ResourceBundleSubstitutions.java @@ -36,6 +36,7 @@ import com.oracle.svm.core.annotate.Alias; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.TargetElement; import com.oracle.svm.core.util.VMError; import sun.util.resources.OpenListResourceBundle; @@ -65,10 +66,31 @@ private static ResourceBundle getBundle(String baseName, Locale targetLocale, Co } @Substitute - public static ResourceBundle getBundle(String baseName, Locale locale, ClassLoader loader) { + private static ResourceBundle getBundle(String baseName, Locale locale, ClassLoader loader) { return ImageSingletons.lookup(LocalizationSupport.class).getCached(baseName, locale); } + @Substitute + private static ResourceBundle getBundle(String baseName, Locale targetLocale, ClassLoader loader, Control control) { + return ImageSingletons.lookup(LocalizationSupport.class).getCached(baseName, targetLocale); + } + + /* + * Currently there is no support for the module system at run time. Module arguments are + * therefore ignored. + */ + + @TargetElement(onlyWith = JDK11OrLater.class) + @Substitute + private static ResourceBundle getBundle(String baseName, Target_java_lang_Module module) { + return ImageSingletons.lookup(LocalizationSupport.class).getCached(baseName, Locale.getDefault()); + } + + @TargetElement(onlyWith = JDK11OrLater.class) + @Substitute + private static ResourceBundle getBundle(String baseName, Locale targetLocale, Target_java_lang_Module module) { + return ImageSingletons.lookup(LocalizationSupport.class).getCached(baseName, targetLocale); + } } @TargetClass(java.util.ListResourceBundle.class) 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 9b19276cfc67..1cf07d703d55 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 @@ -31,8 +31,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Locale; import java.util.NoSuchElementException; import java.util.Optional; +import java.util.ResourceBundle; import java.util.Set; import java.util.stream.Collectors; @@ -42,6 +44,25 @@ public final class ModuleSupport { private ModuleSupport() { } + /** + * It is not possible to open up Module access for resource bundles using a mechanism like + * {@link #openModule}. We therefore need to find the correct module that the resource bundle is + * in and access the bundle via the module system. See the discussion in JDK-8231694. + */ + public static ResourceBundle getResourceBundle(String bundleName, Locale locale, ClassLoader loader) { + Class bundleClass; + try { + bundleClass = loader.loadClass(bundleName); + } catch (ClassNotFoundException ex) { + /* + * This call will most likely throw an exception because it will also not find the + * bundle class. But it avoids special and JDK-specific handling here. + */ + return ResourceBundle.getBundle(bundleName, locale, loader); + } + return ResourceBundle.getBundle(bundleName, locale, bundleClass.getModule()); + } + public static List getModuleResources(Collection names) { List result = new ArrayList<>(); for (String name : names) { 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 e4c677449b24..c48dcbbdd9af 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 @@ -27,7 +27,9 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.NoSuchElementException; +import java.util.ResourceBundle; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; @@ -35,6 +37,10 @@ public final class ModuleSupport { private ModuleSupport() { } + public static ResourceBundle getResourceBundle(String bundleName, Locale locale, ClassLoader loader) { + return ResourceBundle.getBundle(bundleName, locale, loader); + } + /** * Gets all resources in the modules named by {@code modules} from the Java runtime image. */ From d6fdb1f63177e2e0756fd4aa00f995b7c1de7303 Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Fri, 4 Oct 2019 10:47:23 -0700 Subject: [PATCH 042/140] Make library registration thread safe --- .../oracle/svm/hosted/c/NativeLibraries.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java index 405871fcaa22..847b9fc5c618 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -93,8 +94,8 @@ public final class NativeLibraries { private final ResolvedJavaType enumType; private final ResolvedJavaType locationIdentityType; - private final ArrayList libraries; - private final ArrayList staticLibraries; + private final List libraries; + private final List staticLibraries; private final LinkedHashSet libraryPaths; private final List errors; @@ -126,8 +127,17 @@ public NativeLibraries(ConstantReflectionProvider constantReflection, MetaAccess enumType = metaAccess.lookupJavaType(Enum.class); locationIdentityType = metaAccess.lookupJavaType(LocationIdentity.class); - libraries = new ArrayList<>(); - staticLibraries = new ArrayList<>(); + /* + * Libraries can be added during the static analysis, which runs multi-threaded. So the + * lists must be synchronized. + * + * Also note that it is necessary to support duplicate entries, i.e., it must remain a List + * and not a Set. The list is passed to the linker, and duplicate entries allow linking of + * libraries that have cyclic dependencies. + */ + libraries = Collections.synchronizedList(new ArrayList<>()); + staticLibraries = Collections.synchronizedList(new ArrayList<>()); + libraryPaths = initCLibraryPath(); this.cache = new CAnnotationProcessorCache(); From 9886be0c6c8c733bcb2943a03722b6a95409bb5b Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 3 Oct 2019 00:14:54 +0200 Subject: [PATCH 043/140] fix JVMCIVersionCheck as run via mx so as to not conflict with class in the JDK --- compiler/mx.compiler/mx_compiler.py | 141 ++++++++++++++++++---------- 1 file changed, 92 insertions(+), 49 deletions(-) diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 605b19093131..c4838fab0a7a 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -106,29 +106,102 @@ def get_vm_prefix(asList=True): #: JDK9 or later is being used (checked above). isJDK8 = jdk.javaCompliance < '1.9' +class SafeDirectoryUpdater(object): + """ + Multi-thread safe context manager for creating/updating a directory. + + :Example: + # Compiles `sources` into `dst` with javac. If multiple threads/processes are + # performing this compilation concurrently, the contents of `dst` + # will reflect the complete results of one of the compilations + # from the perspective of other threads/processes. + with SafeDirectoryUpdater(dst) as sdu: + mx.run([jdk.javac, '-d', sdu.directory, sources]) + + """ + def __init__(self, directory, create=False): + """ + + :param directory: the target directory that will be created/updated within the context. + The working copy of the directory is accessed via `self.directory` + within the context. + """ + + self.target = directory + self.workspace = None + self.directory = None + self.create = create + + def __enter__(self): + parent = dirname(self.target) + self.workspace = tempfile.mkdtemp(dir=parent) + self.directory = join(self.workspace, basename(self.target)) + if self.create: + mx.ensure_dir_exists(self.directory) + self.target_timestamp = mx.TimeStampFile(self.target) + return self + + def __exit__(self, exc_type, exc_value, traceback): + if exc_type is not None: + shutil.rmtree(self.workspace) + raise + + # Try delete the target directory if it existed prior to creating + # self.workspace and has not been modified in between. + if self.target_timestamp.timestamp is not None and self.target_timestamp.timestamp == mx.TimeStampFile(self.target).timestamp: + old_target = join(self.workspace, 'to_deleted_' + basename(self.target)) + try: + os.rename(self.target, old_target) + except: + # Silently assume another process won the race to rename dst_jdk_dir + pass + + # Try atomically move self.directory to self.target + try: + os.rename(self.directory, self.target) + except: + if not exists(self.target): + raise + else: + # Silently assume another process won the race to create self.target + pass + + shutil.rmtree(self.workspace) + def _check_jvmci_version(jdk): """ Runs a Java utility to check that `jdk` supports the minimum JVMCI API required by Graal. + + This runs a version of org.graalvm.compiler.hotspot.JVMCIVersionCheck that is "moved" + to the unnamed package. Without this, on JDK 10+, the class in the jdk.internal.vm.compiler + module will be run instead of the version on the class path. """ - simplename = 'JVMCIVersionCheck' - name = 'org.graalvm.compiler.hotspot.' + simplename + unqualified_name = 'JVMCIVersionCheck' + qualified_name = 'org.graalvm.compiler.hotspot.' + unqualified_name binDir = mx.ensure_dir_exists(join(_suite.get_output_root(), '.jdk' + str(jdk.version))) + if isinstance(_suite, mx.BinarySuite): - javaSource = join(binDir, simplename + '.java') - if not exists(javaSource): - dists = [d for d in _suite.dists if d.name == 'GRAAL_HOTSPOT'] - assert len(dists) == 1, 'could not find GRAAL_HOTSPOT distribution' - d = dists[0] - assert exists(d.sourcesPath), 'missing expected file: ' + d.sourcesPath - with zipfile.ZipFile(d.sourcesPath, 'r') as zf: - with open(javaSource, 'w') as fp: - fp.write(zf.read(name.replace('.', '/') + '.java')) + dists = [d for d in _suite.dists if d.name == 'GRAAL_HOTSPOT'] + assert len(dists) == 1, 'could not find GRAAL_HOTSPOT distribution' + d = dists[0] + assert exists(d.sourcesPath), 'missing expected file: ' + d.sourcesPath + source_timestamp = getmtime(d.sourcesPath) + with zipfile.ZipFile(d.sourcesPath, 'r') as zf: + source_contents = zf.read(qualified_name.replace('.', '/') + '.java') else: - javaSource = join(_suite.dir, 'src', 'org.graalvm.compiler.hotspot', 'src', name.replace('.', '/') + '.java') - javaClass = join(binDir, name.replace('.', '/') + '.class') - if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): - mx.run([jdk.javac, '-d', binDir, javaSource]) - mx.run([jdk.java, '-cp', binDir, name]) + source_path = join(_suite.dir, 'src', 'org.graalvm.compiler.hotspot', 'src', qualified_name.replace('.', '/') + '.java') + source_timestamp = getmtime(source_path) + with open(source_path, 'r') as fp: + source_contents = fp.read() + + unqualified_class_file = join(binDir, unqualified_name + '.class') + if not exists(unqualified_class_file) or getmtime(unqualified_class_file) < source_timestamp: + with SafeDirectoryUpdater(binDir, create=True) as sdu: + source_path = join(sdu.directory, unqualified_name + '.java') + with open(source_path, 'w') as fp: + fp.write(source_contents.replace('package org.graalvm.compiler.hotspot;', '')) + mx.run([jdk.javac, '-d', sdu.directory, source_path]) + mx.run([jdk.java, '-cp', binDir, unqualified_name]) if os.environ.get('JVMCI_VERSION_CHECK', None) != 'ignore': _check_jvmci_version(jdk) @@ -256,7 +329,7 @@ def ctw(args, extraVMarguments=None): if not _get_XX_option_value(vmargs, 'UseJVMCINativeLibrary', False): if _get_XX_option_value(vmargs, 'UseJVMCICompiler', False): - if _get_XX_option_value(vmargs, 'BootstrapJVMCI', False) == None: + if _get_XX_option_value(vmargs, 'BootstrapJVMCI', False) is None: vmargs.append('-XX:+BootstrapJVMCI') mainClassAndArgs = [] @@ -1133,13 +1206,8 @@ def _update_graaljdk(src_jdk, dst_jdk_dir=None, root_module_names=None, export_t mx.log('Updating/creating {} from {} since {}'.format(dst_jdk_dir, src_jdk.home, update_reason)) - # The GraalJDK is created in a temporary directory since multiple processes - # may be racing to do the creation. - tmp_dir = tempfile.mkdtemp(prefix=basename(dst_jdk_dir), dir=dirname(dst_jdk_dir)) - tmp_dst_jdk_dir = join(tmp_dir, 'jdk') - dst_jdk_dir_timestamp = mx.TimeStampFile(dst_jdk_dir) - try: - + with SafeDirectoryUpdater(dst_jdk_dir) as sdu: + tmp_dst_jdk_dir = sdu.directory def _copy_file(src, dst): mx.log('Copying {} to {}'.format(src, dst)) shutil.copyfile(src, dst) @@ -1236,31 +1304,6 @@ def _copy_file(src, dst): with open(join(tmp_dst_jdk_dir, 'proguard.map'), 'w') as fp: fp.write(unstrip_map) - except: - shutil.rmtree(tmp_dir) - raise - - # Try delete the current dst_jdk_dir if it existed prior to creating - # tmp_dst_jdk_dir and has not be modified in between. - if dst_jdk_dir_timestamp.timestamp is not None and dst_jdk_dir_timestamp.timestamp == mx.TimeStampFile(dst_jdk_dir).timestamp: - old_dst_jdk_dir = join(tmp_dir, 'old_jdk') - try: - os.rename(dst_jdk_dir, old_dst_jdk_dir) - except: - # Silently assume another process won the race to rename dst_jdk_dir - pass - - # Try atomically move tmp_dst_jdk_dir to dst_jdk_dir - try: - os.rename(tmp_dst_jdk_dir, dst_jdk_dir) - except: - if not exists(dst_jdk_dir): - raise - else: - # Silently assume another process won the race to create dst_jdk_dir - pass - - shutil.rmtree(tmp_dir) return dst_jdk_dir, True __graal_config = None From 24a27909ccd1b7c0da5f7a3b6f27e8781b1c3f2a Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 3 Oct 2019 00:15:57 +0200 Subject: [PATCH 044/140] make JVMCIVersionCheck check JVMCI version when running on a labsjdk --- .../graalvm/compiler/hotspot/JVMCIVersionCheck.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java index 7f9f62f5e303..d7ad589bd289 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java @@ -230,6 +230,17 @@ private void run(boolean exitOnFailure, Version minVersion) { failVersionCheck(props, exitOnFailure, "Could not parse the JDK 11 early access build number from java.vm.version property: %s.%n", vmVersion); return; } + } else if (vmVersion.contains("-jvmci-")) { + // A "labsjdk" + Version v = Version.parse(vmVersion); + if (v != null) { + if (v.isLessThan(minVersion)) { + failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion); + } + return; + } + failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + "Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion); } else { // Graal is compatible with all JDK versions as of 11 GA. } From aa40152b59bc2b9a26ccb3ad022795b878f31468 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 3 Oct 2019 00:21:00 +0200 Subject: [PATCH 045/140] update to labsjdk-ee-11.0.5-jvmci-19.3-b03 --- common.hocon | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common.hocon b/common.hocon index ca2e44b0e576..6c599106837b 100644 --- a/common.hocon +++ b/common.hocon @@ -11,7 +11,7 @@ jdks: { oraclejdk8Debug: {name : oraclejdk, version : "8u221-jvmci-19.3-b03-fastdebug", platformspecific: true} oraclejdk11: {name : oraclejdk, version : "11.0.3+12", platformspecific: true} openjdk11: {name : openjdk, version : "11.0.3+7", platformspecific: true} - labsjdk11: {name : labsjdk, version : "ce-11-20190917-093434", platformspecific: true} + labsjdk11: {name : labsjdk, version : "ee-11.0.5-jvmci-19.3-b03-dev", platformspecific: true} } # This must always point to HEAD in the master branch but can be used to point @@ -28,9 +28,9 @@ download-hsdis : { ] } -oraclejdk8 : { downloads : { JAVA_HOME : ${jdks.oraclejdk8}, EXTRA_JAVA_HOMES : { pathlist :[ ${jdks.oraclejdk11} ]} }} +oraclejdk8 : { downloads : { JAVA_HOME : ${jdks.oraclejdk8}, EXTRA_JAVA_HOMES : { pathlist :[ ${jdks.labsjdk11} ]} }} oraclejdk8Only : { downloads : { JAVA_HOME : ${jdks.oraclejdk8} }} -oraclejdk8Debug : { downloads : { JAVA_HOME : ${jdks.oraclejdk8Debug}, EXTRA_JAVA_HOMES : { pathlist :[ ${jdks.oraclejdk11} ]} }} +oraclejdk8Debug : { downloads : { JAVA_HOME : ${jdks.oraclejdk8Debug}, EXTRA_JAVA_HOMES : { pathlist :[ ${jdks.labsjdk11} ]} }} openjdk8 : { downloads : { JAVA_HOME : ${jdks.openjdk8} }} From 5f8f1fd438face3512a0b2169a3e489ddc82019d Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 3 Oct 2019 11:23:19 +0200 Subject: [PATCH 046/140] clarify naming around labsjdk-11 in hocon files --- common.hocon | 11 +++-- compiler/ci_common/gate_tasks.hocon | 46 +++++++++---------- compiler/ci_common/gate_tasks_bootstrap.hocon | 14 +++--- compiler/ci_includes/gate_tasks.hocon | 4 +- examples/ci.hocon | 2 +- regex/ci.hocon | 6 +-- sdk/ci.hocon | 2 +- substratevm/ci_includes/deploy.hocon | 4 +- substratevm/ci_includes/gate.hocon | 4 +- sulong/ci.hocon | 6 +-- tools/ci.hocon | 6 +-- truffle/ci.hocon | 6 +-- vm/ci_common/common.hocon | 4 +- vm/ci_includes/vm.hocon | 8 ++-- 14 files changed, 63 insertions(+), 60 deletions(-) diff --git a/common.hocon b/common.hocon index 6c599106837b..551f706d1b64 100644 --- a/common.hocon +++ b/common.hocon @@ -11,7 +11,8 @@ jdks: { oraclejdk8Debug: {name : oraclejdk, version : "8u221-jvmci-19.3-b03-fastdebug", platformspecific: true} oraclejdk11: {name : oraclejdk, version : "11.0.3+12", platformspecific: true} openjdk11: {name : openjdk, version : "11.0.3+7", platformspecific: true} - labsjdk11: {name : labsjdk, version : "ee-11.0.5-jvmci-19.3-b03-dev", platformspecific: true} + labsjdk-ce-11: {name : labsjdk, version : "ce-11.0.5-jvmci-19.3-b03-dev", platformspecific: true} + labsjdk-ee-11: {name : labsjdk, version : "ee-11.0.5-jvmci-19.3-b03-dev", platformspecific: true} } # This must always point to HEAD in the master branch but can be used to point @@ -28,15 +29,17 @@ download-hsdis : { ] } -oraclejdk8 : { downloads : { JAVA_HOME : ${jdks.oraclejdk8}, EXTRA_JAVA_HOMES : { pathlist :[ ${jdks.labsjdk11} ]} }} +oraclejdk8 : { downloads : { JAVA_HOME : ${jdks.oraclejdk8}, EXTRA_JAVA_HOMES : { pathlist :[ ${jdks.labsjdk-ee-11} ]} }} oraclejdk8Only : { downloads : { JAVA_HOME : ${jdks.oraclejdk8} }} -oraclejdk8Debug : { downloads : { JAVA_HOME : ${jdks.oraclejdk8Debug}, EXTRA_JAVA_HOMES : { pathlist :[ ${jdks.labsjdk11} ]} }} +oraclejdk8Debug : { downloads : { JAVA_HOME : ${jdks.oraclejdk8Debug}, EXTRA_JAVA_HOMES : { pathlist :[ ${jdks.labsjdk-ee-11} ]} }} openjdk8 : { downloads : { JAVA_HOME : ${jdks.openjdk8} }} oraclejdk11 : { downloads : { JAVA_HOME : ${jdks.oraclejdk11} }} openjdk11 : { downloads : { JAVA_HOME : ${jdks.openjdk11} }} -labsjdk11 : { downloads : { JAVA_HOME : ${jdks.labsjdk11} }} + +labsjdk-ce-11 : { downloads : { JAVA_HOME : ${jdks.labsjdk-ce-11} }} +labsjdk-ee-11 : { downloads : { JAVA_HOME : ${jdks.labsjdk-ee-11} }} common : ${mx} { timelimit : "30:00" diff --git a/compiler/ci_common/gate_tasks.hocon b/compiler/ci_common/gate_tasks.hocon index af4fd58232cc..01c2527bc942 100644 --- a/compiler/ci_common/gate_tasks.hocon +++ b/compiler/ci_common/gate_tasks.hocon @@ -2,39 +2,39 @@ builds += [ # Darwin AMD64 - ${gateTest} ${oraclejdk8} ${gateDarwinAMD64} {name: "gate-compiler-test-8-darwin-amd64", timelimit: "40:00"} - ${gateTest} ${openjdk8} ${gateDarwinAMD64} {name: "weekly-test-compiler-test-openjdk8-darwin-amd64"} ${graalWeekly} - ${gateTest} ${labsjdk11} ${gateDarwinAMD64} {name: "weekly-test-compiler-test-11-darwin-amd64"} ${graalWeekly} -# ${gateTestBenchmark} ${oraclejdk8} ${gateDarwinAMD64} {name: "weekly-test-compiler-benchmarktest-8-darwin-amd64"} ${graalWeekly} + ${gateTest} ${oraclejdk8} ${gateDarwinAMD64} {name: "gate-compiler-test-8-darwin-amd64", timelimit: "40:00"} + ${gateTest} ${openjdk8} ${gateDarwinAMD64} {name: "weekly-test-compiler-test-openjdk8-darwin-amd64"} ${graalWeekly} + ${gateTest} ${labsjdk-ee-11} ${gateDarwinAMD64} {name: "weekly-test-compiler-test-labsjdk-ee-11-darwin-amd64"} ${graalWeekly} +# ${gateTestBenchmark} ${oraclejdk8} ${gateDarwinAMD64} {name: "weekly-test-compiler-benchmarktest-8-darwin-amd64"} ${graalWeekly} # Windows AMD64 ${gateTest} ${oraclejdk8} ${gateWindowsAMD64} {name: "gate-compiler-test-8-windows-amd64", timelimit: "50:00", packages: {msvc: "==10.0" }} # Linux AMD64 - ${gateTest} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-test-8-linux-amd64"} - ${gateTest} ${openjdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-openjdk8-linux-amd64"} ${graalWeekly} - ${gateTestMaxVS} ${oraclejdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-8-linux-amd64-maxvectorsize"} ${graalWeekly} - ${gateTestAVX0} ${oraclejdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-8-linux-amd64-avx0"} ${graalWeekly} - ${gateTestAVX1} ${oraclejdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-8-linux-amd64-avx1"} ${graalWeekly} - ${gateTest} ${labsjdk11} ${gateLinuxAMD64} {name: "gate-compiler-test-11-linux-amd64"} - ${gateJavaBaseTest} ${labsjdk11} ${gateLinuxAMD64} {name: "weekly-test-compiler-javabasetest-11-linux-amd64"} ${graalWeekly} - ${gateTestCTW} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-ctw-8-linux-amd64"} - ${gateTestCTWWeekly} ${openjdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-ctw-openjdk8-linux-amd64", timelimit: "2:00:00"} ${graalWeekly} - ${gateTestCTWWeekly} ${labsjdk11} ${gateLinuxAMD64} {name: "weekly-test-compiler-ctw-11-linux-amd64"} ${graalWeekly} - ${gateTest} ${oraclejdk8Debug} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-8-linux-amd64-fastdebug", timelimit: "1:50:00"} ${graalWeekly} - ${gateTestBenchmark} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-benchmarktest-8-linux-amd64"} - ${gateTestBenchmark} ${oraclejdk8Debug} ${gateLinuxAMD64} {name: "weekly-test-compiler-benchmarktest-8-linux-amd64-fastdebug"} ${graalWeekly} - ${gateStyle} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-style-linux-amd64"} - ${gateCoverage} ${oraclejdk8} ${gateLinuxAMD64} {name: "weekly-compiler-coverage-8-linux-amd64", timelimit: "1:50:00"} ${graalWeekly} + ${gateTest} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-test-8-linux-amd64"} + ${gateTest} ${openjdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-openjdk8-linux-amd64"} ${graalWeekly} + ${gateTestMaxVS} ${oraclejdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-8-linux-amd64-maxvectorsize"} ${graalWeekly} + ${gateTestAVX0} ${oraclejdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-8-linux-amd64-avx0"} ${graalWeekly} + ${gateTestAVX1} ${oraclejdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-8-linux-amd64-avx1"} ${graalWeekly} + ${gateTest} ${labsjdk-ee-11} ${gateLinuxAMD64} {name: "gate-compiler-test-labsjdk-ee-11-linux-amd64"} + ${gateJavaBaseTest} ${labsjdk-ee-11} ${gateLinuxAMD64} {name: "weekly-test-compiler-javabasetest-labsjdk-ee-11-linux-amd64"} ${graalWeekly} + ${gateTestCTW} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-ctw-8-linux-amd64"} + ${gateTestCTWWeekly} ${openjdk8} ${gateLinuxAMD64} {name: "weekly-test-compiler-ctw-openjdk8-linux-amd64", timelimit: "2:00:00"} ${graalWeekly} + ${gateTestCTWWeekly} ${labsjdk-ee-11} ${gateLinuxAMD64} {name: "weekly-test-compiler-ctw-labsjdk-ee-11-linux-amd64"} ${graalWeekly} + ${gateTest} ${oraclejdk8Debug} ${gateLinuxAMD64} {name: "weekly-test-compiler-test-8-linux-amd64-fastdebug", timelimit: "1:50:00"} ${graalWeekly} + ${gateTestBenchmark} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-benchmarktest-8-linux-amd64"} + ${gateTestBenchmark} ${oraclejdk8Debug} ${gateLinuxAMD64} {name: "weekly-test-compiler-benchmarktest-8-linux-amd64-fastdebug"} ${graalWeekly} + ${gateStyle} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-style-linux-amd64"} + ${gateCoverage} ${oraclejdk8} ${gateLinuxAMD64} {name: "weekly-compiler-coverage-8-linux-amd64", timelimit: "1:50:00"} ${graalWeekly} ${gateTestCompileImmediately} ${oraclejdk8} ${gateLinuxAMD64} {name: "gate-compiler-test-compile-immediately-8-linux-amd64"} ${gateMathStubsListener} {name: "daily-hotspot-mathstubs-listener"} # Solaris SPARC ${gateTest} ${oraclejdk8} ${gateSolarisSPARC} {name: "gate-compiler-test-8-solaris-sparcv9", timelimit: "1:00:00"} - ${gateTest} ${labsjdk11} ${gateSolarisSPARC} {name: "gate-compiler-test-11-solaris-sparcv9", timelimit: "1:00:00"} + ${gateTest} ${labsjdk-ee-11} ${gateSolarisSPARC} {name: "gate-compiler-test-labsjdk-ee-11-solaris-sparcv9", timelimit: "1:00:00"} ${gateTestCTW} ${oraclejdk8} ${gateSolarisSPARC} {name: "gate-compiler-ctw-8-solaris-sparcv9", timelimit: "1:00:00"} - ${gateTestCTWWeekly} ${labsjdk11} ${gateSolarisSPARC} {name: "weekly-test-compiler-ctw-11-solaris-sparcv9", timelimit: "1:50:00"} ${graalWeekly} + ${gateTestCTWWeekly} ${labsjdk-ee-11} ${gateSolarisSPARC} {name: "weekly-test-compiler-ctw-labsjdk-ee-11-solaris-sparcv9", timelimit: "1:50:00"} ${graalWeekly} ${gateTest} ${oraclejdk8Debug} ${gateSolarisSPARC} {name: "weekly-test-compiler-test-8-solaris-sparcv9-fastdebug", timelimit: "1:50:00"} ${graalWeekly} ${gateTestBenchmark} ${oraclejdk8} ${gateSolarisSPARC} {name: "gate-compiler-benchmarktest-8-solaris-sparcv9", timelimit: "1:00:00"} # ${gateTestBenchmark} ${oraclejdk8Debug} ${gateSolarisSPARC} {name: "gate-compiler-benchmarktest-8-solaris-sparcv9-fastdebug", timelimit: "1:50:00"} @@ -43,6 +43,6 @@ builds += [ #${gateTest} ${oraclejdk8} ${gateLinuxSPARC} {name: "weekly-test-compiler-test-8-linux-sparcv9", timelimit: "1:00:00"} ${graalWeekly} # Linux AArch64 - ${gateTest} ${labsjdk11} ${gateLinuxAArch64} {name: "gate-compiler-test-11-linux-aarch64", timelimit: "1:50:00"} - ${gateTestCTW} ${labsjdk11} ${gateLinuxAArch64} {name: "gate-compiler-ctw-11-linux-aarch64", timelimit: "1:50:00"} + ${gateTest} ${labsjdk-ce-11} ${gateLinuxAArch64} {name: "gate-compiler-test-labsjdk-ce-11-linux-aarch64", timelimit: "1:50:00"} + ${gateTestCTW} ${labsjdk-ce-11} ${gateLinuxAArch64} {name: "gate-compiler-ctw-labsjdk-ce-11-linux-aarch64", timelimit: "1:50:00"} ] diff --git a/compiler/ci_common/gate_tasks_bootstrap.hocon b/compiler/ci_common/gate_tasks_bootstrap.hocon index e9f1f160bef4..1915bde68016 100644 --- a/compiler/ci_common/gate_tasks_bootstrap.hocon +++ b/compiler/ci_common/gate_tasks_bootstrap.hocon @@ -1,15 +1,15 @@ builds += [ # Darwin AMD64 - ${gateBootstrapLite} ${oraclejdk8} ${gateDarwinAMD64Bootstrap} {name: "gate-compiler-bootstraplite-8-darwin-amd64"} - ${gateBootstrapLite} ${labsjdk11} ${gateDarwinAMD64Bootstrap} {name: "weekly-test-compiler-bootstraplite-11-darwin-amd64"} ${graalWeekly} + ${gateBootstrapLite} ${oraclejdk8} ${gateDarwinAMD64Bootstrap} {name: "gate-compiler-bootstraplite-8-darwin-amd64"} + ${gateBootstrapLite} ${labsjdk-ee-11} ${gateDarwinAMD64Bootstrap} {name: "weekly-test-compiler-bootstraplite-labsjdk-ee-11-darwin-amd64"} ${graalWeekly} # Linux AMD64 - ${gateBootstrap} ${oraclejdk8} ${gateLinuxAMD64Bootstrap} {name: "gate-compiler-bootstrap-8-linux-amd64"} - ${gateBootstrapFullVerify} ${oraclejdk8} ${gateLinuxAMD64Bootstrap} {name: "gate-compiler-bootstrapfullverify-8-linux-amd64"} - ${gateBootstrap} ${labsjdk11} ${gateLinuxAMD64Bootstrap} {name: "gate-compiler-bootstrap-11-linux-amd64"} + ${gateBootstrap} ${oraclejdk8} ${gateLinuxAMD64Bootstrap} {name: "gate-compiler-bootstrap-8-linux-amd64"} + ${gateBootstrapFullVerify} ${oraclejdk8} ${gateLinuxAMD64Bootstrap} {name: "gate-compiler-bootstrapfullverify-8-linux-amd64"} + ${gateBootstrap} ${labsjdk-ee-11} ${gateLinuxAMD64Bootstrap} {name: "gate-compiler-bootstrap-labsjdk-ee-11-linux-amd64"} # Solaris SPARC - ${gateBootstrap} ${oraclejdk8} ${gateSolarisSPARCBootstrap} {name: "gate-compiler-bootstrap-8-solaris-sparcv9", timelimit: "1:00:00"} - ${gateBootstrap} ${labsjdk11} ${gateSolarisSPARCBootstrap} {name: "weekly-test-compiler-bootstrap-11-solaris-sparcv9", timelimit: "1:00:00"} ${graalWeekly} + ${gateBootstrap} ${oraclejdk8} ${gateSolarisSPARCBootstrap} {name: "gate-compiler-bootstrap-8-solaris-sparcv9", timelimit: "1:00:00"} + ${gateBootstrap} ${labsjdk-ee-11} ${gateSolarisSPARCBootstrap} {name: "weekly-test-compiler-bootstrap-labsjdk-ee-11-solaris-sparcv9", timelimit: "1:00:00"} ${graalWeekly} ] diff --git a/compiler/ci_includes/gate_tasks.hocon b/compiler/ci_includes/gate_tasks.hocon index f59c920afcac..eed089a1d359 100644 --- a/compiler/ci_includes/gate_tasks.hocon +++ b/compiler/ci_includes/gate_tasks.hocon @@ -1,6 +1,6 @@ # Build targets builds += [ - ${gateJAOTC} ${labsjdk11} ${gateLinuxAMD64} {name: "gate-compiler-jaotc-linux-amd64"} - ${gateJAOTC} ${labsjdk11} ${gateLinuxAArch64} {name: "gate-compiler-jaotc-linux-aarch64", timelimit: "1:30:00"} + ${gateJAOTC} ${labsjdk-ce-11} ${gateLinuxAMD64} {name: "gate-compiler-jaotc-labsjdk-ce-11-linux-amd64"} + ${gateJAOTC} ${labsjdk-ce-11} ${gateLinuxAArch64} {name: "gate-compiler-jaotc-labsjdk-ce-11-linux-aarch64", timelimit: "1:30:00"} ] diff --git a/examples/ci.hocon b/examples/ci.hocon index 969ea918d4f6..54b13d91531e 100644 --- a/examples/ci.hocon +++ b/examples/ci.hocon @@ -14,7 +14,7 @@ examplesGate : ${examplesCommon} { builds += [ ${linux-amd64} ${oraclejdk8} ${examplesGate} ${eclipse} ${jdt} { name: "gate-examples-linux-8" }, - ${linux-amd64} ${oraclejdk11} ${examplesGate} ${eclipse} { name: "gate-examples-linux-11" }, + ${linux-amd64} ${oraclejdk11} ${examplesGate} ${eclipse} { name: "gate-examples-linux-oraclejdk-11" }, ${solaris-sparcv9} ${oraclejdk8} ${examplesGate} { name: "gate-examples-solaris-8" }, ${darwin-amd64} ${oraclejdk8} ${examplesGate} { name: "gate-examples-darwin-8" }, ] diff --git a/regex/ci.hocon b/regex/ci.hocon index d8755c4860a5..e1e3b485a747 100644 --- a/regex/ci.hocon +++ b/regex/ci.hocon @@ -18,17 +18,17 @@ 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-11"}, + ${linux-amd64} ${oraclejdk11} ${regexCommon} ${eclipse} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-regex-oraclejdk-11"}, ${solaris-sparcv9} ${oraclejdk8} ${gateLite} ${regexWeekly} { name: "gate-regex-solaris-lite-8" } ${solaris-sparcv9} ${oraclejdk11} ${gateLite} ${regexWeekly} { - name: "gate-regex-solaris-lite-11" + name: "gate-regex-solaris-lite-oraclejdk-11" } ${darwin-amd64} ${oraclejdk8} ${gateLite} ${regexWeekly} { name: "gate-regex-mac-lite-8" } ${darwin-amd64} ${oraclejdk11} ${gateLite} ${regexWeekly} { - name: "gate-regex-mac-lite-11" + name: "gate-regex-mac-lite-oraclejdk-11" } ] diff --git a/sdk/ci.hocon b/sdk/ci.hocon index aa3e760cf2cf..fd74e66f6bce 100644 --- a/sdk/ci.hocon +++ b/sdk/ci.hocon @@ -14,7 +14,7 @@ sdkGate : ${sdkCommon} { builds += [ ${linux-amd64} ${oraclejdk8} ${sdkGate} ${eclipse} ${jdt} { name: "gate-sdk-linux-8" }, - ${linux-amd64} ${oraclejdk11} ${sdkGate} ${eclipse} { name: "gate-sdk-linux-11" }, + ${linux-amd64} ${oraclejdk11} ${sdkGate} ${eclipse} { name: "gate-sdk-linux-oraclejdk-11" }, ${solaris-sparcv9} ${oraclejdk8} ${sdkGate} { name: "gate-sdk-solaris-8" }, ${darwin-amd64} ${oraclejdk8} ${sdkGate} { name: "gate-sdk-darwin-8" }, ] diff --git a/substratevm/ci_includes/deploy.hocon b/substratevm/ci_includes/deploy.hocon index f7c3f42ab000..640ca691140e 100644 --- a/substratevm/ci_includes/deploy.hocon +++ b/substratevm/ci_includes/deploy.hocon @@ -6,6 +6,6 @@ maven-deploy-all-suites : ${svm-common-linux-gate} { } builds += [ - ${maven-deploy-all-suites} ${linux-amd64} ${linux-deploy} ${oraclejdk8} {name: "gate-maven-dry-run-all-jdk8-linux-amd64"} - ${maven-deploy-all-suites} ${linux-amd64} ${linux-deploy} ${labsjdk11} {name: "gate-maven-dry-run-all-jdk11-linux-amd64"} + ${maven-deploy-all-suites} ${linux-amd64} ${linux-deploy} ${oraclejdk8} {name: "gate-maven-dry-run-all-jdk8-linux-amd64"} + ${maven-deploy-all-suites} ${linux-amd64} ${linux-deploy} ${labsjdk-ee-11} {name: "gate-maven-dry-run-all-labsjdk-ee-11-linux-amd64"} ] diff --git a/substratevm/ci_includes/gate.hocon b/substratevm/ci_includes/gate.hocon index 7579283f4636..b7f856db301c 100644 --- a/substratevm/ci_includes/gate.hocon +++ b/substratevm/ci_includes/gate.hocon @@ -32,8 +32,8 @@ builds += [ ${oraclejdk8} ${svm-common-darwin-gate} ${gate-svm-js} { name: "gate-svm-darwin-js" } - ${labsjdk11} ${svm-common-linux-gate} { - name: "gate-svm-build-11" + ${labsjdk-ee-11} ${svm-common-linux-gate} { + name: "gate-svm-build-ee-11" run: [ ${svm-cmd-gate} ["build,helloworld,test,relocations"] ] diff --git a/sulong/ci.hocon b/sulong/ci.hocon index f2bb139998db..886949505971 100644 --- a/sulong/ci.hocon +++ b/sulong/ci.hocon @@ -143,7 +143,7 @@ sulong-coverage-linux: ${sulong-gateTest38-linux} ${requireGCC} ${sulong-weekly- timelimit: "1:00:00" } -sulong-labsjdk11-only: ${labsjdk11} { +sulong-labsjdk-ce-11-only: ${labsjdk-ce-11} { downloads: { "EXTRA_JAVA_HOMES": {"pathlist": []} } @@ -178,8 +178,8 @@ builds += [ ${sulong-gateTest80-linux} ${sulong-ruby-downstream-test} { name: gate-sulong-ruby-downstream } - ${sulong-gateTestLLVMorg-linux} ${sulong-labsjdk11-only} ${linux-aarch64} { name: gate-sulong-build_bundled-llvm-linux-aarch64, run: [[mx, gate, --tags, "build"]] } - ${sulong-gateTestLLVMorg-linux} ${sulong-labsjdk11-only} { name: gate-sulong-build_bundled-llvm-linux-amd64-jdk11, run: [ + ${sulong-gateTestLLVMorg-linux} ${sulong-labsjdk-ce-11-only} ${linux-aarch64} { name: gate-sulong-build_bundled-llvm-linux-aarch64, run: [[mx, gate, --tags, "build"]] } + ${sulong-gateTestLLVMorg-linux} ${sulong-labsjdk-ce-11-only} { name: gate-sulong-build_bundled-llvm-linux-amd64-labsjdk-ce-11, run: [ [mx, gate, --tags, "build"] ] ${sulong-test-toolchain} } diff --git a/tools/ci.hocon b/tools/ci.hocon index 011c8d6e512e..4411fe080d22 100644 --- a/tools/ci.hocon +++ b/tools/ci.hocon @@ -18,7 +18,7 @@ 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-11"}, + ${linux-amd64} ${oraclejdk11} ${toolsCommon} ${eclipse} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-tools-oraclejdk-11"}, ${linux-amd64} ${oraclejdk8} ${toolsCommon} { run : [ ["mx", "build"], @@ -31,12 +31,12 @@ builds += [ name: "gate-tools-solaris-lite-8" } ${solaris-sparcv9} ${oraclejdk11} ${toolsGateLite} ${toolsWeekly} { - name: "gate-tools-solaris-lite-11" + name: "gate-tools-solaris-lite-oraclejdk-11" } ${darwin-amd64} ${oraclejdk8} ${toolsGateLite} ${toolsWeekly} { name: "gate-tools-mac-lite-8" } ${darwin-amd64} ${oraclejdk11} ${toolsGateLite} ${toolsWeekly} { - name: "gate-tools-mac-lite-11" + name: "gate-tools-mac-lite-oraclejdk-11" } ] diff --git a/truffle/ci.hocon b/truffle/ci.hocon index a459e2386a80..e2aabc0c1a11 100644 --- a/truffle/ci.hocon +++ b/truffle/ci.hocon @@ -33,7 +33,7 @@ truffleWeekly: ${truffle-weekly-notifications} { builds += [ ${linux-amd64} ${oraclejdk8} ${truffleCommon} ${eclipse} ${jdt} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-truffle-8"}, - ${linux-amd64} ${oraclejdk11} ${truffleCommon} ${eclipse} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-truffle-11"}, + ${linux-amd64} ${oraclejdk11} ${truffleCommon} ${eclipse} {run : [["mx", "--strict-compliance", "gate", "--strict-mode"]], targets : [gate], name: "gate-truffle-oraclejdk-11"}, ${linux-amd64} ${oraclejdk8} ${truffleCommon} { run : [ ["mx", "build"], @@ -46,13 +46,13 @@ builds += [ name: "gate-truffle-solaris-lite-8" } ${solaris-sparcv9} ${oraclejdk11} ${gateLite} ${truffleWeekly} { - name: "gate-truffle-solaris-lite-11" + name: "gate-truffle-solaris-lite-oraclejdk-11" } ${darwin-amd64} ${oraclejdk8} ${gateLite} ${truffleWeekly} { name: "gate-truffle-mac-lite-8" } ${darwin-amd64} ${oraclejdk11} ${gateLite} ${truffleWeekly} { - name: "gate-truffle-mac-lite-11" + name: "gate-truffle-mac-lite-oraclejdk-11" } ${windows-amd64} ${oraclejdk8} ${truffleCommon} { # TODO make that a full gate run diff --git a/vm/ci_common/common.hocon b/vm/ci_common/common.hocon index 5153d5b5f2e9..9fead4a22cef 100644 --- a/vm/ci_common/common.hocon +++ b/vm/ci_common/common.hocon @@ -243,7 +243,7 @@ builds += [ ] logs: ${common_vm.logs} timelimit: "1:30:00" - name: deploy-vm-jdk11-linux-amd64 + name: deploy-vm-labsjdk-ee-11-linux-amd64 } ${vm_java_8} ${full_vm_build_darwin} ${darwin-deploy} ${deploy_daily_vm_darwin} { run: [ @@ -280,7 +280,7 @@ builds += [ ${notify-nexus-deploy} ] timelimit: "1:45:00" - name: deploy-vm-base-jdk11-darwin-amd64 + name: deploy-vm-base-labsjdk-ee-11-darwin-amd64 } ${vm_java_8} ${svm-common-windows} ${deploy_daily_vm_windows} { run: [ diff --git a/vm/ci_includes/vm.hocon b/vm/ci_includes/vm.hocon index ae930faf4639..627248a6ccfe 100644 --- a/vm/ci_includes/vm.hocon +++ b/vm/ci_includes/vm.hocon @@ -1,5 +1,5 @@ vm_java_8: ${openjdk8} -vm_java_11: ${labsjdk11} +vm_java_11: ${labsjdk-ee-11} svm_suite: /substratevm vm_extra_suites: "truffleruby,graalpython,fastr" custom_vm_linux: {} @@ -18,7 +18,7 @@ vm_setup: { maven_base: ${linux-deploy} { downloads: { - JAVA_HOME: ${jdks.labsjdk11}, + JAVA_HOME: ${jdks.labsjdk-ce-11}, EXTRA_JAVA_HOMES: ${jdks.openjdk8} } mx_cmd_base: [mx, --dynamicimports, "/tools,/compiler,/graal-js"] @@ -39,13 +39,13 @@ builds += [ ${maven_base.build} ${maven_base.deploy} [--dry-run, ${binaries-repository}] ] - name: gate-vm-maven-dry-run-jdk11-linux-amd64 + name: gate-vm-maven-dry-run-labsjdk-ee-11-linux-amd64 } ${vm_java_11} ${deploy_vm_linux} ${maven_base} { run: [ ${maven_base.build} ${maven_base.deploy} [${binaries-repository}] ] - name: deploy-vm-maven-jdk11-linux-amd64 + name: deploy-vm-maven-labsjdk-ee-11-linux-amd64 } ] From 83a195867aceedb61e1578cbf18fafdf34271bf7 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 3 Oct 2019 13:11:24 +0200 Subject: [PATCH 047/140] GraalVM CE 11 must be built with labsjdk-ce-11 --- vm/ci_includes/vm.hocon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/ci_includes/vm.hocon b/vm/ci_includes/vm.hocon index 627248a6ccfe..ee9f5d8d187c 100644 --- a/vm/ci_includes/vm.hocon +++ b/vm/ci_includes/vm.hocon @@ -1,5 +1,5 @@ vm_java_8: ${openjdk8} -vm_java_11: ${labsjdk-ee-11} +vm_java_11: ${labsjdk-ce-11} svm_suite: /substratevm vm_extra_suites: "truffleruby,graalpython,fastr" custom_vm_linux: {} From 2aaee33525031fff760785a80d28ca8f6a350517 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 3 Oct 2019 23:16:22 +0200 Subject: [PATCH 048/140] update to binaries whose names include the build number --- common.hocon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common.hocon b/common.hocon index 551f706d1b64..152448022b4e 100644 --- a/common.hocon +++ b/common.hocon @@ -11,8 +11,8 @@ jdks: { oraclejdk8Debug: {name : oraclejdk, version : "8u221-jvmci-19.3-b03-fastdebug", platformspecific: true} oraclejdk11: {name : oraclejdk, version : "11.0.3+12", platformspecific: true} openjdk11: {name : openjdk, version : "11.0.3+7", platformspecific: true} - labsjdk-ce-11: {name : labsjdk, version : "ce-11.0.5-jvmci-19.3-b03-dev", platformspecific: true} - labsjdk-ee-11: {name : labsjdk, version : "ee-11.0.5-jvmci-19.3-b03-dev", platformspecific: true} + labsjdk-ce-11: {name : labsjdk, version : "ce-11.0.5+9-jvmci-19.3-b03", platformspecific: true} + labsjdk-ee-11: {name : labsjdk, version : "ee-11.0.5+1-jvmci-19.3-b03", platformspecific: true} } # This must always point to HEAD in the master branch but can be used to point From 264662d9ad38181ecde6cecff3b4188ee9251e06 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Fri, 4 Oct 2019 19:29:50 +0200 Subject: [PATCH 049/140] handle multiple class initialization failures for the same class properly --- .../core/test/CheckGraalInvariants.java | 8 +++++++ .../ClassfileBytecodeProviderTest.java | 21 ++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) 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 dff9a7cdda29..94d67127db8e 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 @@ -434,6 +434,14 @@ private static List> initializeClasses(InvariantsTool tool, List Date: Fri, 4 Oct 2019 22:37:48 +0200 Subject: [PATCH 050/140] make reading of JVMCIVersionCheck.java lazy --- compiler/mx.compiler/mx_compiler.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index c4838fab0a7a..3f505b7815f3 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -186,21 +186,23 @@ def _check_jvmci_version(jdk): d = dists[0] assert exists(d.sourcesPath), 'missing expected file: ' + d.sourcesPath source_timestamp = getmtime(d.sourcesPath) - with zipfile.ZipFile(d.sourcesPath, 'r') as zf: - source_contents = zf.read(qualified_name.replace('.', '/') + '.java') + def source_supplier(): + with zipfile.ZipFile(d.sourcesPath, 'r') as zf: + return zf.read(qualified_name.replace('.', '/') + '.java') else: source_path = join(_suite.dir, 'src', 'org.graalvm.compiler.hotspot', 'src', qualified_name.replace('.', '/') + '.java') source_timestamp = getmtime(source_path) - with open(source_path, 'r') as fp: - source_contents = fp.read() + def source_supplier(): + with open(source_path, 'r') as fp: + return fp.read() unqualified_class_file = join(binDir, unqualified_name + '.class') if not exists(unqualified_class_file) or getmtime(unqualified_class_file) < source_timestamp: with SafeDirectoryUpdater(binDir, create=True) as sdu: - source_path = join(sdu.directory, unqualified_name + '.java') - with open(source_path, 'w') as fp: - fp.write(source_contents.replace('package org.graalvm.compiler.hotspot;', '')) - mx.run([jdk.javac, '-d', sdu.directory, source_path]) + unqualified_source_path = join(sdu.directory, unqualified_name + '.java') + with open(unqualified_source_path, 'w') as fp: + fp.write(source_supplier().replace('package org.graalvm.compiler.hotspot;', '')) + mx.run([jdk.javac, '-d', sdu.directory, unqualified_source_path]) mx.run([jdk.java, '-cp', binDir, unqualified_name]) if os.environ.get('JVMCI_VERSION_CHECK', None) != 'ignore': From c248b53c16ed1e2d273396b34da967c75f3aa00f Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 5 Oct 2019 11:16:43 +0200 Subject: [PATCH 051/140] [GR-16976] Update Ruby in GraalVM --- 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 d3f18dbca2fb..2d4925fa9675 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -50,7 +50,7 @@ }, { "name": "truffleruby", - "version": "24304a356973e0e88ad6e5b377c9f874c72e66fa", + "version": "e175b3355fff3004f8c1d20a57efe68804821676", "dynamic": True, "urls": [ {"url": "https://github.com/oracle/truffleruby.git", "kind": "git"}, From 91d8b5b18901ec5838d2b499155fdc98fc0431d2 Mon Sep 17 00:00:00 2001 From: Jirka Marsik Date: Sat, 5 Oct 2019 12:47:14 +0200 Subject: [PATCH 052/140] Comments in TRegex NFA executor --- .../nodes/nfa/TRegexNFAExecutorLocals.java | 24 +++++++++++++++++++ .../nodes/nfa/TRegexNFAExecutorNode.java | 20 ++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java index 941e409981dc..96fd1e9211d8 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorLocals.java @@ -32,15 +32,39 @@ public final class TRegexNFAExecutorLocals extends TRegexExecutorLocals { + /** + * Frame size = 1 (state ID) + 2 * nCaptureGroups (start and end indices). + */ private final int frameSize; private final int maxSize; + /** + * A record of the paths that we are considering for our optimal match. Every path is + * represented as a frame which consists of the ID of the last state on the path and the capture + * group indices that have been set along the path. The paths in this array is sorted in + * priority order, from highest priority to lowest priority. + */ private int[] curStates; + /** + * A buffer of the paths that we will be considering in the next step. Every path in this array + * was created by taking a path from {@link #curStates} and following the transition labelled + * with the current character. + */ private int[] nextStates; int curStatesLength = 0; int nextStatesLength = 0; int iCurStates = 0; private long[] marks; + /** + * This array stores the best (highest priority) match found so far. Whenever a match is found, + * all lower priority paths through the NFA are discarded. Therefore, any match which would be + * found later is guaranteed to be of higher priority and can be used to overwrite this result. + */ private int[] result; + /** + * Indicates whether a path to a final state has been completed in this step. If true, then no + * further paths should be considered, as they would have a lower priority than this completed + * path. + */ private boolean resultPushed = false; public TRegexNFAExecutorLocals(Object input, int fromIndex, int index, int maxIndex, int nCaptureGroups, int nStates) { diff --git a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java index f50817ca3c5c..cf5b8f8f092b 100644 --- a/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java +++ b/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/nodes/nfa/TRegexNFAExecutorNode.java @@ -92,6 +92,14 @@ public Object execute(TRegexExecutorLocals abstractLocals, boolean compactString while (true) { if (locals.getIndex() < getInputLength(locals)) { findNextStates(locals); + // If locals.successorsEmpty() is true, then all of our paths have either been + // finished, discarded due to priority or failed to match. If we managed to finish + // any path to a final state (i.e. locals.hasResult() is true), we can terminate + // the search now. + // We can also terminate the search now if we were interested only in matches at + // the very start of the string (i.e. searching is false). Such a search would + // only have walked through the rest of the string without considering any other + // paths. if (locals.successorsEmpty() && (!searching || locals.hasResult())) { return locals.getResult(); } @@ -107,10 +115,18 @@ private void findNextStates(TRegexNFAExecutorLocals locals) { char c = getChar(locals); while (locals.hasNext()) { expandState(locals, locals.next(), c, false); + // If we have found a path to a final state, then we will trim all paths with lower + // priority (i.e. the rest of the elements in curStates). if (locals.isResultPushed()) { return; } } + // We are supposed to find the first match of the regular expression. A match starting + // at a higher index has lower priority and so we give the lowest priority to the loopback + // transition. + // The loopback priority has to be lower than the priority of any path completed so far. + // Therefore, we only follow the loopback if no path has been completed so far + // (i.e. !locals.hasResult()). if (searching && !locals.hasResult() && locals.getIndex() >= locals.getFromIndex()) { expandState(locals, nfa.getInitialLoopBackTransition().getTarget().getId(), c, true); } @@ -118,6 +134,10 @@ private void findNextStates(TRegexNFAExecutorLocals locals) { private void expandState(TRegexNFAExecutorLocals locals, int stateId, char c, boolean isLoopBack) { NFAState state = nfa.getState(stateId); + // If we manage to find a path to the (unanchored) final state, then we will trim all other + // paths leading from the current state as they all have lower priority. We do this by + // iterating through the transitions in priority order and stopping on the first transition + // to a final state. for (int i = 0; i < maxTransitionIndex(state); i++) { NFAStateTransition t = state.getNext()[i]; NFAState target = t.getTarget(); From 80c30480901df59c9d86716764b2b2a3cd686335 Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Mon, 7 Oct 2019 10:21:31 +0200 Subject: [PATCH 053/140] [GR-18561] Wrong PATH to GraalVM home on macOS. --- vscode/graalvm/src/graalVMInstall.ts | 62 ++++++++++++++++------------ 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/vscode/graalvm/src/graalVMInstall.ts b/vscode/graalvm/src/graalVMInstall.ts index ceee811c4d1b..c5fe966fc367 100644 --- a/vscode/graalvm/src/graalVMInstall.ts +++ b/vscode/graalvm/src/graalVMInstall.ts @@ -28,7 +28,11 @@ export async function installGraalVM(storagePath: string | undefined): Promise { if (file.startsWith('graalvm') && fs.statSync(path.join(targetDir, file)).isDirectory()) { - vscode.workspace.getConfiguration('graalvm').update('home', path.join(targetDir, file), true); + let graalVMHome: string = path.join(targetDir, file); + if (process.platform === 'darwin') { + graalVMHome = path.join(graalVMHome, 'Contents', 'Home'); + } + vscode.workspace.getConfiguration('graalvm').update('home', graalVMHome, true); vscode.window.showInformationMessage("GraalVM installed."); return; } @@ -55,7 +59,7 @@ export async function installGraalVMComponent(componentId: string): Promise { const vms: vscode.QuickPickItem[] = []; if (storagePath) { - findGraalVMIn(storagePath, 1, vms); + findGraalVMsIn(storagePath, vms); } if (fs.existsSync('/opt')) { - findGraalVMIn('/opt', 1, vms); + findGraalVMsIn('/opt', vms); } if (process.env.GRAALVM_HOME) { - findGraalVMIn(path.normalize(process.env.GRAALVM_HOME), 0, vms); + addGraalVMInfo(path.normalize(process.env.GRAALVM_HOME), vms); } if (process.env.JAVA_HOME) { - findGraalVMIn(path.normalize(process.env.JAVA_HOME), 0, vms); + addGraalVMInfo(path.normalize(process.env.JAVA_HOME), vms); } if (process.env.PATH) { - process.env.PATH.split(':').forEach(p => { - if (path.basename(p) === 'bin') { - findGraalVMIn(path.normalize(path.join(p, '..', '..')), 1, vms); - } - }); + process.env.PATH.split(':').filter(p => path.basename(p) === 'bin').forEach(p => addGraalVMInfo(path.dirname(p), vms)); } vms.push({ label: 'Browse...' }); const selected = await vscode.window.showQuickPick(vms, { matchOnDetail: true, placeHolder: 'Select GraalVM Home' }); @@ -209,6 +209,18 @@ async function dowloadGraalVMRelease(releaseURL: string, storagePath: string | u }); } +async function extractGraalVM(downloadedFile: string, targetDir: string): Promise { + return vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: "Installing GraalVM..." + }, (_progress, _token) => { + return tar.extract({ + cwd: targetDir, + file: downloadedFile + }); + }); +} + function deleteFolder(folder: string) { if (fs.existsSync(folder)) { fs.readdirSync(folder).forEach((file, _index) => { @@ -223,7 +235,19 @@ function deleteFolder(folder: string) { } } -function findGraalVMIn(folder: string, depth: number, vms: vscode.QuickPickItem[]) { +function findGraalVMsIn(folder: string, vms: vscode.QuickPickItem[]) { + if (folder && fs.existsSync(folder) && fs.statSync(folder).isDirectory) { + fs.readdirSync(folder).map(f => path.join(folder, f)).map(p => { + if (process.platform === 'darwin') { + let homePath: string = path.join(p, 'Contents', 'Home'); + return fs.existsSync(homePath) ? homePath : p; + } + return p; + }).filter(p => fs.statSync(p).isDirectory()).forEach(p => addGraalVMInfo(p, vms)); + } +} + +function addGraalVMInfo(folder: string, vms: vscode.QuickPickItem[]) { if (!vms.find(vm => vm.detail === folder)) { if (fs.existsSync(folder)) { const executable: string | undefined = utils.findExecutable('gu', folder); @@ -244,25 +268,11 @@ function findGraalVMIn(folder: string, depth: number, vms: vscode.QuickPickItem[ } }); } - } else if (depth > 0) { - fs.readdirSync(folder).filter(f => fs.statSync(path.join(folder, f)).isDirectory()).forEach(f => findGraalVMIn(path.join(folder, f), depth - 1, vms)); } } } } -async function extractGraalVM(downloadedFile: string, targetDir: string): Promise { - return vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: "Installing GraalVM..." - }, (_progress, _token) => { - return tar.extract({ - cwd: targetDir, - file: downloadedFile - }); - }); -} - async function selectAvailableComponent(graalVMHome: string): Promise { return new Promise((resolve, reject) => { const executablePath = utils.findExecutable('gu', graalVMHome); From f0b45da21e63bcc323fdf38eced9d033e6c5c85e Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 5 Oct 2019 11:48:36 +0200 Subject: [PATCH 054/140] [GR-15451] Build standalones from components and the the GraalVM layout * Instead of installables which might be excluded. * Skip a standalone if not all its component dependencies are available. --- vm/mx.vm/mx_vm.py | 55 ++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index 84087cd9239c..d9502b408643 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -1858,39 +1858,38 @@ def create_archive(path, **_kw_args): class GraalVmStandaloneComponent(mx.LayoutTARDistribution): # pylint: disable=too-many-ancestors - def __init__(self, installable, **kw_args): + def __init__(self, component, graalvm, **kw_args): """ - :type installable: GraalVmInstallableComponent + :type component: mx_sdk.GraalVmTruffleComponent + :type graalvm: GraalVmLayoutDistribution """ - assert isinstance(installable.main_component, mx_sdk.GraalVmTruffleComponent) other_comp_names = [] - if _get_svm_support().is_supported() and _get_launcher_configs(installable.main_component): + if _get_svm_support().is_supported() and _get_launcher_configs(component): other_comp_names += [c.short_name for c in registered_graalvm_components(stage1=True) if c.short_name in ('svm', 'svmee')] - self.main_comp_dir_name = installable.main_component.dir_name + self.main_comp_dir_name = component.dir_name name = '_'.join([self.main_comp_dir_name, 'standalone'] + other_comp_names).upper().replace('-', '_') - self.base_dir_name = installable.string_substitutions.substitute(installable.main_component.standalone_dir_name) + self.base_dir_name = graalvm.string_substitutions.substitute(component.standalone_dir_name) base_dir = './{}/'.format(self.base_dir_name) layout = {} # Compute paths from standalone component launchers to other homes home_paths = {} - for dependency_name, details in installable.main_component.standalone_dependencies.items(): + for dependency_name, details in component.standalone_dependencies.items(): dependency_path = details[0] - component = get_installable_distribution(dependency_name).main_component - home_paths[component.installable_id] = base_dir + dependency_path + comp = get_component(dependency_name, fatalIfMissing=True) + home_paths[comp.installable_id] = base_dir + dependency_path def is_jar_distribution(val): return val['source_type'] == 'dependency' and isinstance(mx.dependency(val['dependency'], fatalIfMissing=False), mx.JARDistribution) - def add_files_from_installable(installable, path_prefix, excluded_paths): - component = installable.main_component - component_base_dir = installable.path_substitutions.substitute(_get_component_type_base(component)) - support_dir_pattern = component_base_dir + component.dir_name + '/' - launcher_configs = _get_launcher_configs(component) + def add_files_from_component(comp, path_prefix, excluded_paths): + component_base_dir = graalvm.path_substitutions.substitute(_get_component_type_base(comp)) + support_dir_pattern = component_base_dir + comp.dir_name + '/' + launcher_configs = _get_launcher_configs(comp) - for path, source in installable._walk_layout(): + for path, source in graalvm._walk_layout(): if path.startswith(support_dir_pattern): path_from_home = path.split(support_dir_pattern, 1)[1] # take only the distributions that are not JAR distributions @@ -1904,14 +1903,14 @@ def add_files_from_installable(installable, path_prefix, excluded_paths): relative_path_from_launcher_dir = relpath(path_from_root, dirname(destination)) launcher_config.add_relative_home_path(language, relative_path_from_launcher_dir) - add_files_from_installable(installable, base_dir, []) + add_files_from_component(component, base_dir, []) - for dependency_name, details in installable.main_component.standalone_dependencies.items(): + for dependency_name, details in component.standalone_dependencies.items(): dependency_path = details[0] excluded_paths = details[1] if len(details) > 1 else [] - dependency = get_installable_distribution(dependency_name) + dependency = get_component(dependency_name, fatalIfMissing=True) excluded_paths = [mx_subst.path_substitutions.substitute(excluded) for excluded in excluded_paths] - add_files_from_installable(dependency, base_dir + dependency_path + '/', excluded_paths) + add_files_from_component(dependency, base_dir + dependency_path + '/', excluded_paths) self.maven = True super(GraalVmStandaloneComponent, self).__init__( @@ -1922,8 +1921,8 @@ def add_files_from_installable(installable, path_prefix, excluded_paths): path=None, platformDependent=True, theLicense=None, - path_substitutions=installable.path_substitutions, - string_substitutions=installable.string_substitutions, + path_substitutions=graalvm.path_substitutions, + string_substitutions=graalvm.string_substitutions, **kw_args) @@ -2170,18 +2169,26 @@ def mx_register_dynamic_suite_constituents(register_project, register_distributi if not _disable_installable(component) and (component.installable or (isinstance(component, mx_sdk.GraalVmLanguage) and component.dir_name != 'js')): installables.setdefault(component.installable_id, []).append(component) + # Create installables for components in installables.values(): main_component = min(components, key=lambda c: c.priority) installable_component = GraalVmInstallableComponent(main_component, extra_components=[c for c in components if c != main_component]) register_distribution(installable_component) with_debuginfo.append(installable_component) + # Create standalones for components in installables.values(): main_component = min(components, key=lambda c: c.priority) if isinstance(main_component, mx_sdk.GraalVmTruffleComponent) and has_svm_launcher(main_component): - standalone = GraalVmStandaloneComponent(get_installable_distribution(main_component.name)) - register_distribution(standalone) - with_debuginfo.append(standalone) + dependencies = main_component.standalone_dependencies.keys() + missing_dependencies = [dep for dep in dependencies if not has_component(dep)] + if missing_dependencies: + if mx.get_opts().verbose: + mx.warn("Skipping standalone {} because the components {} are excluded".format(main_component.name, missing_dependencies)) + else: + standalone = GraalVmStandaloneComponent(get_component(main_component.name, fatalIfMissing=True), get_final_graalvm_distribution()) + register_distribution(standalone) + with_debuginfo.append(standalone) if register_project: lib_polyglot_project = get_lib_polyglot_project() From c58ccf11166659318ae5f20514bbda1bc7cd346a Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 7 Oct 2019 12:15:36 +0200 Subject: [PATCH 055/140] Print the standalone layout if verbose --- vm/mx.vm/mx_vm.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index d9502b408643..92c14faba986 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -1912,6 +1912,8 @@ def add_files_from_component(comp, path_prefix, excluded_paths): excluded_paths = [mx_subst.path_substitutions.substitute(excluded) for excluded in excluded_paths] add_files_from_component(dependency, base_dir + dependency_path + '/', excluded_paths) + mx.logv("Standalone '{}' has layout:\n{}".format(name, pprint.pformat(layout))) + self.maven = True super(GraalVmStandaloneComponent, self).__init__( suite=_suite, From 9a7045f2828c35ac4fe6a9924ceee6a535b5b117 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 25 Sep 2019 17:04:43 +0200 Subject: [PATCH 056/140] [GR-18469] Remove unused suite import. --- substratevm/mx.substratevm/suite.py | 7 ------- vm/mx.vm/mx_vm.py | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 2764cef09c91..fdafd7520c38 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -32,13 +32,6 @@ {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"}, ] }, - { - "name": "regex", - "subdir": True, - "urls" : [ - {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"}, - ] - }, ] }, diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index 84087cd9239c..ea4224f06d55 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -2527,8 +2527,8 @@ def graalvm_vm_name(graalvm_dist, jdk): register_vm_config('ce-python', ['cmp', 'gu', 'gvm', 'ins', 'js', 'lg', 'llp', 'loc', 'nfi', 'ni', 'nil', 'njs', 'nju', 'polynative', 'pyn', 'pynl', 'pro', 'rgx', 'sdk', 'slg', 'svm', 'svml', 'tfl', 'tflm', 'libpoly', 'poly', 'vvm']) register_vm_config('ce-no_native', ['bgu', 'bjs', 'blli', 'bgraalvm-native-clang', 'bgraalvm-native-clang++', 'bnative-image', 'bnative-image-configure', 'bpolyglot', 'cmp', 'gu', 'gvm', 'ins', 'js', 'loc', 'nfi', 'ni', 'nil', 'njs', 'polynative', 'pro', 'rgx', 'sdk', 'slg', 'snative-image-agent', 'svm', 'svml', 'tfl', 'tflm', 'libpoly', 'poly', 'vvm']) -register_vm_config('libgraal', ['bgu', 'cmp', 'gu', 'gvm', 'lg', 'loc', 'nfi', 'poly', 'polynative', 'rgx', 'sdk', 'svm', 'svml', 'tfl', 'tflm', 'bpolyglot']) -register_vm_config('toolchain-only', ['tfl', 'tflm', 'gu', 'svm', 'gvm', 'rgx', 'polynative', 'llp', 'loc', 'nfi', 'svml', 'bgu', 'blli', 'sdk', 'slg', 'cmp']) +register_vm_config('libgraal', ['bgu', 'cmp', 'gu', 'gvm', 'lg', 'loc', 'nfi', 'poly', 'polynative', 'sdk', 'svm', 'svml', 'tfl', 'tflm', 'bpolyglot']) +register_vm_config('toolchain-only', ['tfl', 'tflm', 'gu', 'svm', 'gvm', 'polynative', 'llp', 'loc', 'nfi', 'svml', 'bgu', 'blli', 'sdk', 'slg', 'cmp']) if mx.get_os() == 'windows': register_vm_config('svm', ['bnative-image', 'bnative-image-configure', 'bpolyglot', 'cmp', 'gvm', 'loc', 'nfi', 'ni', 'nil', 'nju', 'poly', 'polynative', 'rgx', 'sdk', 'snative-image-agent', 'svm', 'svml', 'tfl', 'tflm'], env_file=False) From f6d2b4745b95e1a20badfc97049f44ad74c0e675 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 3 Oct 2019 21:18:02 +0200 Subject: [PATCH 057/140] [GR-16891] sulong: do not load libpolyglot-mock via nfi --- .../truffle/llvm/runtime/LibraryLocator.java | 6 ++++ .../llvm/runtime/NFIContextExtension.java | 32 ++++++++++++------- .../src/com/oracle/truffle/llvm/Runner.java | 2 ++ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LibraryLocator.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LibraryLocator.java index 78c56bc2581e..0cdc92256b0d 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LibraryLocator.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LibraryLocator.java @@ -69,6 +69,12 @@ public static void traceDelegateNative(LLVMContext context, Object file) { } } + public static void traceLoadNative(LLVMContext context, Object file) { + if (context != null && context.ldDebugEnabled()) { + traceLoader(context, "load library natively=%s\n", file); + } + } + public static void traceSearchPath(LLVMContext context, List paths) { if (context != null && context.ldDebugEnabled()) { traceLoader(context, " search path=%s\n", paths); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NFIContextExtension.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NFIContextExtension.java index 814e7463c65a..a0a2004fcf3c 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NFIContextExtension.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NFIContextExtension.java @@ -139,15 +139,15 @@ private void addLibraries(LLVMContext context) { } List libraries = context.getExternalLibraries(lib -> lib.isNative()); for (ExternalLibrary l : libraries) { - addLibrary(l); + addLibrary(l, context); } } - private void addLibrary(ExternalLibrary lib) throws UnsatisfiedLinkError { + private void addLibrary(ExternalLibrary lib, LLVMContext context) throws UnsatisfiedLinkError { CompilerAsserts.neverPartOfCompilation(); - if (!libraryHandles.containsKey(lib) && !handleSpecialLibraries(lib)) { + if (!libraryHandles.containsKey(lib) && !handleSpecialLibraries(lib, context)) { try { - libraryHandles.put(lib, loadLibrary(lib)); + libraryHandles.put(lib, loadLibrary(lib, context)); } catch (UnsatisfiedLinkError e) { System.err.println(lib.toString() + " not found!\n" + e.getMessage()); throw e; @@ -163,7 +163,7 @@ public static String getNativeLibrarySuffix() { } } - private boolean handleSpecialLibraries(ExternalLibrary lib) { + private boolean handleSpecialLibraries(ExternalLibrary lib, LLVMContext context) { Path fileNamePath = lib.getPath().getFileName(); if (fileNamePath == null) { throw new IllegalArgumentException("Filename path of " + lib.getPath() + " is null"); @@ -172,6 +172,9 @@ private boolean handleSpecialLibraries(ExternalLibrary lib) { if (fileName.startsWith("libc.") || fileName.startsWith("libSystem.")) { // nothing to do, since libsulong.so already links against libc.so/libSystem.B.dylib return true; + } else if (fileName.startsWith("libpolyglot-mock.")) { + // special mock library for polyglot intrinsics + return true; } else if (fileName.startsWith("libsulong++.") || fileName.startsWith("libc++.")) { /* * Dummy library that doesn't actually exist, but is implicitly replaced by libc++ if @@ -180,17 +183,17 @@ private boolean handleSpecialLibraries(ExternalLibrary lib) { */ TruffleObject cxxlib; if (System.getProperty("os.name").toLowerCase().contains("mac")) { - cxxlib = loadLibrary("libc++.dylib", true, null); + cxxlib = loadLibrary("libc++.dylib", true, null, context); } else { - cxxlib = loadLibrary("libc++.so.1", true, null); + cxxlib = loadLibrary("libc++.so.1", true, null, context); if (cxxlib == null) { /* * On Ubuntu, libc++ can not be dynamically loaded because of a missing * dependeny on libgcc_s. Work around this by loading it manually first. */ - TruffleObject libgcc = loadLibrary("libgcc_s.so.1", true, "RTLD_GLOBAL"); + TruffleObject libgcc = loadLibrary("libgcc_s.so.1", true, "RTLD_GLOBAL", context); if (libgcc != null) { - cxxlib = loadLibrary("libc++.so.1", true, null); + cxxlib = loadLibrary("libc++.so.1", true, null, context); } } } @@ -203,13 +206,18 @@ private boolean handleSpecialLibraries(ExternalLibrary lib) { } } - private TruffleObject loadLibrary(ExternalLibrary lib) { + private TruffleObject loadLibrary(ExternalLibrary lib, LLVMContext context) { CompilerAsserts.neverPartOfCompilation(); String libName = lib.getPath().toString(); - return loadLibrary(libName, false, null); + return loadLibrary(libName, false, null, context, lib); + } + + private TruffleObject loadLibrary(String libName, boolean optional, String flags, LLVMContext context) { + return loadLibrary(libName, optional, flags, context, libName); } - private TruffleObject loadLibrary(String libName, boolean optional, String flags) { + private TruffleObject loadLibrary(String libName, boolean optional, String flags, LLVMContext context, Object file) { + LibraryLocator.traceLoadNative(context, file); String loadExpression; if (flags == null) { loadExpression = String.format("load \"%s\"", libName); diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index a3987ecedb17..7031d503e0b8 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -44,6 +44,7 @@ import java.util.Objects; import java.util.UUID; +import com.oracle.truffle.llvm.runtime.LibraryLocator; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Equivalence; @@ -683,6 +684,7 @@ private LLVMParserResult parse(List parserResults, ArrayDeque< } else if (!library.isNative()) { throw new LLVMParserException("The file '" + source.getName() + "' is not a bitcode file nor an ELF or Mach-O object file with an embedded bitcode section."); } else { + LibraryLocator.traceDelegateNative(context, library); return null; } } From 105e19c1fdba2307c9b9a0d5ca550a6ff266bae7 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Fri, 4 Oct 2019 18:08:05 +0200 Subject: [PATCH 058/140] Optimize context references to be more aggressive and use strong references where possible. --- .../test/ContextLookupCompilationTest.java | 6 +- .../truffle/polyglot/EngineAccessor.java | 18 +++- .../truffle/polyglot/PolyglotLanguage.java | 23 ++++- .../polyglot/PolyglotLanguageInstance.java | 57 ++++++----- .../truffle/polyglot/PolyglotReferences.java | 95 ++++++++++++++----- 5 files changed, 138 insertions(+), 61 deletions(-) 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 ec76e8b503df..f22745c12fea 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 @@ -245,9 +245,9 @@ public void testRefTwoContextsWithSharedEngine() { private void assertLookupsInnerContext() { /* - * We currently have all optimizations disabled with inner contexts. + * We currently have some optimizations disabled with inner contexts. */ - assertBailout(createAssertConstantContextFromLookup(Exclusive.get(), Exclusive.get())); + assertCompiling(createAssertConstantContextFromLookup(Exclusive.get(), Exclusive.get())); assertBailout(createAssertConstantContextFromLookup(Exclusive.get(), Shared.get())); assertBailout(createAssertConstantContextFromLookup(Shared.get(), Exclusive.get())); assertBailout(createAssertConstantContextFromLookup(Shared.get(), Shared.get())); @@ -261,7 +261,7 @@ private void assertLookupsInnerContext() { assertCompiling(createAssertConstantLanguageFromLookup(Shared.get(), Shared.get())); assertCompiling(createAssertConstantLanguageFromLookup(null, Shared.get())); - assertMagicNumberReads(1, Exclusive.get(), Exclusive.get()); + assertMagicNumberReads(0, Exclusive.get(), Exclusive.get()); assertMagicNumberReads(1, Exclusive.get(), Shared.get()); assertMagicNumberReads(1, Shared.get(), Exclusive.get()); assertMagicNumberReads(1, Shared.get(), Shared.get()); 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 57a009cf1847..c9a615a52146 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 @@ -822,7 +822,7 @@ public , C> TruffleLanguage.ContextReference loo @Override public , C> TruffleLanguage.ContextReference getDirectContextReference(Object sourceVM, TruffleLanguage sourceLanguageSPI, Class targetLanguageClass) { assert sourceLanguageSPI == null || sourceLanguageSPI.getClass() == targetLanguageClass; - return (TruffleLanguage.ContextReference) resolveLanguage(sourceLanguageSPI).getDirectContextSupplier(); + return (TruffleLanguage.ContextReference) resolveLanguageInstance(sourceLanguageSPI).getDirectContextSupplier(); } @SuppressWarnings("unchecked") @@ -830,7 +830,7 @@ public , C> TruffleLanguage.ContextReference get public > TruffleLanguage.LanguageReference getDirectLanguageReference(Object polyglotEngineImpl, TruffleLanguage sourceLanguageSPI, Class targetLanguageClass) { assert sourceLanguageSPI == null || sourceLanguageSPI.getClass() == targetLanguageClass; - return (TruffleLanguage.LanguageReference) resolveLanguage(sourceLanguageSPI).getDirectLanguageReference(); + return (TruffleLanguage.LanguageReference) resolveLanguageInstance(sourceLanguageSPI).getDirectLanguageReference(); } @SuppressWarnings("unchecked") @@ -843,8 +843,18 @@ public > TruffleLanguage.LanguageReference looku return (TruffleLanguage.LanguageReference) instance.lookupLanguageSupplier(resolveLanguage(sourceLanguageSPI)); } - private static PolyglotLanguageInstance resolveLanguage(TruffleLanguage sourceLanguageSPI) { - return (PolyglotLanguageInstance) EngineAccessor.LANGUAGE.getLanguageInstance(sourceLanguageSPI); + private static PolyglotLanguageInstance resolveLanguageInstance(TruffleLanguage sourceLanguageSPI) { + if (sourceLanguageSPI == null) { + return null; + } + return ((PolyglotLanguageInstance) EngineAccessor.LANGUAGE.getLanguageInstance(sourceLanguageSPI)); + } + + private static PolyglotLanguage resolveLanguage(TruffleLanguage sourceLanguageSPI) { + if (sourceLanguageSPI == null) { + return null; + } + return ((PolyglotLanguageInstance) EngineAccessor.LANGUAGE.getLanguageInstance(sourceLanguageSPI)).language; } @Override diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java index 4dd55cb381ee..016e0dfe6cc2 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java @@ -56,6 +56,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; 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.ContextReference; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleLanguage.LanguageReference; @@ -78,7 +79,7 @@ final class PolyglotLanguage extends AbstractLanguageImpl implements com.oracle. private volatile boolean initialized; private volatile PolyglotLanguageInstance initLanguage; - private final LinkedList instancePool = new LinkedList<>(); + private final LinkedList instancePool; final ContextProfile profile; private final LanguageReference> multiLanguageReference; @@ -98,13 +99,31 @@ final class PolyglotLanguage extends AbstractLanguageImpl implements com.oracle. this.index = index; this.host = host; this.profile = new ContextProfile(this); + this.instancePool = cache.getPolicy() == ContextPolicy.EXCLUSIVE ? null : new LinkedList<>(); this.info = NODES.createLanguage(this, cache.getId(), cache.getName(), cache.getVersion(), cache.getDefaultMimeType(), cache.getMimeTypes(), cache.isInternal(), cache.isInteractive()); this.multiLanguageReference = PolyglotReferences.createAlwaysMultiLanguage(this); this.multiContextReference = PolyglotReferences.createAlwaysMultiContext(this); - this.singleOrMultiContextReference = PolyglotReferences.createAssumeSingleContext(this, engine.singleContext, null, multiContextReference); + + this.singleOrMultiContextReference = PolyglotReferences.createAssumeSingleContext(this, engine.singleContext, null, multiContextReference, false); this.singleOrMultiLanguageReference = PolyglotReferences.createAssumeSingleLanguage(this, null, singleInstance, multiLanguageReference); } + ContextPolicy getEffectiveContextPolicy(PolyglotLanguage inLanguage) { + ContextPolicy sourcePolicy; + if (engine.boundEngine) { + // with a bound engine context policy is effectively always exclusive + sourcePolicy = ContextPolicy.EXCLUSIVE; + } else { + if (inLanguage != null) { + sourcePolicy = inLanguage.cache.getPolicy(); + } else { + // we don't know which language we are in so null language means shared policy + sourcePolicy = ContextPolicy.SHARED; + } + } + return sourcePolicy; + } + PolyglotLanguageContext getCurrentLanguageContext() { return PolyglotContextImpl.requireContext().contexts[index]; } 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 d246936b3702..30ad6bd4cedc 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 @@ -65,10 +65,17 @@ final class PolyglotLanguageInstance implements VMObject { private volatile OptionValuesImpl firstOptionValues; private volatile boolean needsInitializeMultiContext; + private final Assumption singleContext = Truffle.getRuntime().createAssumption("Single context per language instance."); + /** + * Direct language lookups in the current language. + */ private final LanguageReference> directLanguageSupplier; + + /** + * Direct context lookups in the current language. + */ private final ContextReference directContextSupplier; - final Assumption singleContext; @SuppressWarnings("unchecked") PolyglotLanguageInstance(PolyglotLanguage language) { @@ -76,7 +83,6 @@ final class PolyglotLanguageInstance implements VMObject { this.sourceCache = new PolyglotSourceCache(); this.valueCodeCache = new ConcurrentHashMap<>(); this.hostInteropCodeCache = new ConcurrentHashMap<>(); - this.singleContext = Truffle.getRuntime().createAssumption("Single context per language instance."); try { this.spi = (TruffleLanguage) language.cache.loadLanguage(); LANGUAGE.initializeLanguage(spi, language.info, language, this); @@ -88,7 +94,21 @@ final class PolyglotLanguageInstance implements VMObject { } catch (Exception e) { throw new IllegalStateException(String.format("Error initializing language '%s' using class '%s'.", language.cache.getId(), language.cache.getClassName()), e); } - this.directContextSupplier = PolyglotReferences.createAssumeSingleContext(language, singleContext, language.engine.noInnerContexts, language.getContextReference()); + boolean mayBeUsedInInnerContext = language.cache.getPolicy() != ContextPolicy.EXCLUSIVE; + boolean currentExclusive = language.getEffectiveContextPolicy(language) == ContextPolicy.EXCLUSIVE; + Assumption useDirectSingleContext = currentExclusive ? null : singleContext; + Assumption useInnerContext = mayBeUsedInInnerContext ? language.engine.noInnerContexts : null; + + if (useDirectSingleContext == null && useInnerContext == null) { + // no checks can use direct reference + this.directContextSupplier = PolyglotReferences.createAlwaysSingleContext(language, currentExclusive); + } else { + this.directContextSupplier = PolyglotReferences.createAssumeSingleContext(language, + useInnerContext, + useDirectSingleContext, + language.getContextReference(), currentExclusive); + } + this.directLanguageSupplier = PolyglotReferences.createAlwaysSingleLanguage(language, this); } @@ -148,12 +168,13 @@ ContextReference getDirectContextSupplier() { /** * Looks up the context reference to use for a foreign language AST. */ - ContextReference lookupContextSupplier(PolyglotLanguageInstance sourceLanguage) { - assert this != sourceLanguage; + ContextReference lookupContextSupplier(PolyglotLanguage sourceLanguage) { + assert language != sourceLanguage; ContextReference ref; - switch (getEffectiveContextPolicy(sourceLanguage)) { + switch (language.getEffectiveContextPolicy(sourceLanguage)) { case EXCLUSIVE: - ref = PolyglotReferences.createAssumeSingleContext(language, language.engine.noInnerContexts, null, this.language.getContextReference()); + ref = PolyglotReferences.createAssumeSingleContext(language, language.engine.noInnerContexts, null, + language.getContextReference(), true); break; case REUSE: case SHARED: @@ -175,9 +196,9 @@ LanguageReference> getDirectLanguageReference() { /** * Looks up the language reference to use for a foreign language AST. */ - LanguageReference> lookupLanguageSupplier(PolyglotLanguageInstance sourceLanguage) { - assert this != sourceLanguage; - switch (getEffectiveContextPolicy(sourceLanguage)) { + LanguageReference> lookupLanguageSupplier(PolyglotLanguage sourceLanguage) { + assert language != sourceLanguage; + switch (language.getEffectiveContextPolicy(sourceLanguage)) { case EXCLUSIVE: return PolyglotReferences.createAssumeSingleLanguage(language, this, language.singleInstance, language.getLanguageReference()); case REUSE: @@ -188,20 +209,4 @@ LanguageReference> lookupLanguageSupplier(PolyglotLangua } } - ContextPolicy getEffectiveContextPolicy(PolyglotLanguageInstance sourceRootLanguage) { - ContextPolicy sourcePolicy; - if (language.engine.boundEngine) { - // with a bound engine context policy is effectively always exclusive - sourcePolicy = ContextPolicy.EXCLUSIVE; - } else { - if (sourceRootLanguage != null) { - sourcePolicy = sourceRootLanguage.language.cache.getPolicy(); - } else { - // null source language means shared policy - sourcePolicy = ContextPolicy.SHARED; - } - } - return sourcePolicy; - } - } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java index 5e0a07c34af0..5f2ee1b952e0 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java @@ -61,16 +61,20 @@ private PolyglotReferences() { // no instances } - static ContextReference createAlwaysSingleContext(PolyglotLanguage language) { - return new SingleContext(language); + static ContextReference createAlwaysSingleContext(PolyglotLanguage language, boolean strong) { + if (strong) { + return new StrongSingleContext(language); + } else { + return new WeakSingleContext(language); + } } static ContextReference createAssumeSingleContext(PolyglotLanguage language, Assumption validIf0, Assumption validIf1, - ContextReference fallback) { - assert !(fallback instanceof SingleContext); - return new AssumeSingleContext(language, validIf0, validIf1, fallback); + ContextReference fallback, boolean strong) { + assert !(fallback instanceof WeakSingleContext) && !(fallback instanceof StrongSingleContext); + return new AssumeSingleContext(language, validIf0, validIf1, fallback, strong); } static ContextReference createAlwaysMultiContext(PolyglotLanguage language) { @@ -108,7 +112,7 @@ private static AssertionError invalidSharingError(PolyglotEngineImpl usedEngine) break; } PolyglotLanguageInstance instance = lookupLanguageInstance(root); - ContextPolicy policy = instance.getEffectiveContextPolicy(instance); + ContextPolicy policy = instance.language.getEffectiveContextPolicy(instance.language); SourceSection sourceSection = null; Node location = stackTrace.getLocation(); @@ -150,6 +154,26 @@ private static PolyglotLanguageInstance lookupLanguageInstance(RootNode root) { return null; } + private static boolean assertDirectContextAccess(PolyglotLanguageContext languageContext, Object languageContextImpl) throws AssertionError { + if (languageContext == null) { + throw invalidSharingError(null); + } + PolyglotContextImpl otherContext = PolyglotContextImpl.requireContext(); + PolyglotLanguageContext otherLanguageContext = otherContext.getContext(languageContext.language); + boolean valid = otherLanguageContext.getContextImpl() == languageContextImpl; + if (!valid) { + throw invalidSharingError(languageContext.getEngine()); + } + return true; + } + + private static boolean checkContextCollected(Object context) { + if (context == null) { + throw invalidSharingError(null); + } + return true; + } + private static final class SingleLanguage extends LanguageReference> { private final PolyglotLanguage language; @@ -184,7 +208,7 @@ private static boolean assertDirectLanguageAccess(PolyglotLanguage language, Tru } - private static final class SingleContext extends ContextReference { + private static final class WeakSingleContext extends ContextReference { private final PolyglotLanguage language; @CompilationFinal private volatile WeakReference languageContextImpl; @@ -192,7 +216,7 @@ private static final class SingleContext extends ContextReference { // only set if assertions are enabled private volatile WeakReference languageContext; - SingleContext(PolyglotLanguage language) { + WeakSingleContext(PolyglotLanguage language) { this.language = language; } @@ -221,43 +245,62 @@ private static boolean assertDirectContextAccess(Object seenContext, WeakReferen return true; } PolyglotLanguageContext context = contextRef.get(); - if (context == null) { - throw invalidSharingError(null); - } - PolyglotContextImpl otherContext = PolyglotContextImpl.requireContext(); - PolyglotLanguageContext otherLanguageContext = otherContext.getContext(context.language); - boolean valid = otherLanguageContext.getContextImpl() == seenContext; - if (!valid) { - throw invalidSharingError(context.getEngine()); - } + return PolyglotReferences.assertDirectContextAccess(context, seenContext); + } + + private boolean setLanguageContext(PolyglotLanguageContext langContext) { + this.languageContext = new WeakReference<>(langContext); return true; } - private static boolean checkContextCollected(Object context) { - if (context == null) { - throw invalidSharingError(null); + } + + private static final class StrongSingleContext extends ContextReference { + + private static final Object NO_CONTEXT = new Object(); + + private final PolyglotLanguage language; + @CompilationFinal private volatile Object languageContextImpl = NO_CONTEXT; + + // only set if assertions are enabled + private volatile PolyglotLanguageContext languageContext; + + StrongSingleContext(PolyglotLanguage language) { + this.language = language; + } + + @Override + public Object get() { + assert language.assertCorrectEngine(); + Object context = languageContextImpl; + if (context == NO_CONTEXT) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + PolyglotLanguageContext langContext = language.getCurrentLanguageContext(); + assert setLanguageContext(langContext); + this.languageContextImpl = context = langContext.getContextImpl(); } - return true; + assert checkContextCollected(context); + assert assertDirectContextAccess(this.languageContext, context); + return context; } private boolean setLanguageContext(PolyglotLanguageContext langContext) { - this.languageContext = new WeakReference<>(langContext); + this.languageContext = langContext; return true; } - } private static final class AssumeSingleContext extends ContextReference { - private final SingleContext singleContextReference; + private final ContextReference singleContextReference; private final ContextReference fallbackReference; private final Assumption validIf0; private final Assumption validIf1; - AssumeSingleContext(PolyglotLanguage language, Assumption validIf0, Assumption validIf1, ContextReference fallback) { + AssumeSingleContext(PolyglotLanguage language, Assumption validIf0, Assumption validIf1, ContextReference fallback, boolean strong) { this.validIf0 = validIf0; this.validIf1 = validIf1; - this.singleContextReference = (SingleContext) createAlwaysSingleContext(language); + this.singleContextReference = createAlwaysSingleContext(language, strong); this.fallbackReference = fallback; } From b9ef2d8af1a3604fd1d00b7ecbeca675aa4d6e67 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Fri, 4 Oct 2019 18:10:03 +0200 Subject: [PATCH 059/140] Deprecate TruffleLanguage.getContextReference(). --- truffle/CHANGELOG.md | 1 + .../oracle/truffle/api/TruffleLanguage.java | 20 +++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 9d599b2f38cf..5b907d3fb4a9 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -16,6 +16,7 @@ This changelog summarizes major changes between Truffle versions relevant to lan * Deprecated `Shape#getPropertyList(Pred)`, `Shape#getKeyList(Pred)`, `Shape#hasTransitionWithKey(Object)`, `Shape.Allocator#locationForValue(Object, EnumSet)` without replacement. * Added [Scope.Builder#rootInstance(Object)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.Builder.html#rootInstance-java.lang.Object-), [Scope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.html#getRootInstance--) and [DebugScope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugScope.html#getRootInstance--) to provide an instance of guest language representation of the root node (e.g. a guest language function). * Debugger breakpoints can be restricted to a particular root instance via [Breakpoint.Builder#rootInstance(DebugValue)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/Breakpoint.Builder.html#rootInstance-com.oracle.truffle.api.debug.DebugValue-) and found later on via [DebugValue#getRootInstanceBreakpoints()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugValue.html#getRootInstanceBreakpoints--). +* Deprecated `TruffleLanguage.getContextReference()` as this method is inefficient in many situations. The most efficient context lookup can be achieved knowing the current AST in which it is used by calling `Node.lookupContextReference(Class)`. ## Version 19.2.0 * Added sub-process output (error output) [redirection into OutputStream](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/ProcessHandler.Redirect.html#stream-java.io.OutputStream-). 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 36a25c2b6634..d5f0034a6776 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 @@ -1175,20 +1175,20 @@ protected SourceSection findSourceLocation(C context, Object value) { } /** - * Creates a reference to the current context to be stored in an AST. The current context can be - * accessed using the {@link ContextReference#get()} method of the returned reference. If a - * context reference is created in the language class constructor an - * {@link IllegalStateException} is thrown. The exception is also thrown if the reference is - * tried to be created or accessed outside of the execution of an engine. - *

    - * The returned reference identity is undefined. It might either return always the same instance - * or a new reference for each invocation of the method. Please note that the current context - * might vary between {@link RootNode#execute(VirtualFrame) executions} if resources or code is - * shared between multiple contexts. + * @deprecated in 19.3 as this method is inefficient in many situations. The most efficient + * context lookup can be achieved knowing the current AST in which it is used. As + * this method does not know the current {@link Node node} it must be unnecessarily + * conservative about the lookup and therefore inefficient. More efficient context + * reference versions are available for fast-paths by calling + * {@link Node#lookupContextReference(Class)} or for slow-paths + * {@link TruffleLanguage#getCurrentContext(Class)}. Truffle DSL has support for + * context lookup with {@link com.oracle.truffle.api.dsl.CachedContext + * CachedContext} that uses the most efficient lookup automatically. * * @since 0.25 */ @SuppressWarnings("unchecked") + @Deprecated public final ContextReference getContextReference() { if (reference == null) { throw new IllegalStateException("TruffleLanguage instance is not initialized. Cannot get the current context reference."); From 214dd13226c436c10b6b8e738a22fe2de6032561 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Fri, 4 Oct 2019 18:52:59 +0200 Subject: [PATCH 060/140] Migrate deprecated uses of getContextReference(). --- .../test/ContextLookupCompilationTest.java | 5 +-- .../test/TruffleContextCompilationTest.java | 4 --- .../InstrumentablePositionsTestLanguage.java | 32 ++++++++++++------- .../test/TestDebugNoContentLanguage.java | 2 +- .../api/debug/test/ValueLanguageTest.java | 32 ++++++++++++------- .../test/AllocationReporterTest.java | 25 ++++++++------- .../test/InstrumentationTestLanguage.java | 8 ++--- .../instrumentation/AllocationReporter.java | 8 +++-- .../api/test/polyglot/ContextPolicyTest.java | 2 +- .../ContextPreInitializationTest.java | 2 +- .../api/test/polyglot/LanguageSPITest.java | 4 +-- .../polyglot/LanguageSPITestLanguage.java | 1 + .../api/test/polyglot/ProxyLanguage.java | 4 --- .../oracle/truffle/api/nodes/RootNode.java | 2 +- .../com/oracle/truffle/nfi/NFILanguage.java | 2 +- .../truffle/nfi/impl/FunctionExecuteNode.java | 9 ++++-- .../truffle/nfi/impl/NFILanguageImpl.java | 2 +- .../oracle/truffle/polyglot/HostLanguage.java | 9 +++++- .../truffle/polyglot/PolyglotReferences.java | 2 +- .../truffle/sl/test/SLParseInContextTest.java | 11 ++++++- .../truffle/sl/nodes/SLEvalRootNode.java | 11 ++++--- .../expression/SLFunctionLiteralNode.java | 8 ++--- .../truffle/sl/parser/SLNodeFactory.java | 2 +- 23 files changed, 109 insertions(+), 78 deletions(-) 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 f22745c12fea..38390c63de61 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 @@ -568,10 +568,6 @@ protected boolean isObjectOfLanguage(Object object) { return false; } - public static ContextReference getCurrentContextReference() { - return getCurrentLanguage(Exclusive.class).getContextReference(); - } - public static LanguageContext getCurrentContext() { return getCurrentContext(Exclusive.class); } @@ -612,6 +608,7 @@ protected boolean isObjectOfLanguage(Object object) { return false; } + @SuppressWarnings("deprecation") public static ContextReference getCurrentContextReference() { return getCurrentLanguage(Shared.class).getContextReference(); } 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 0fa2db2103f6..42150fe84b07 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 @@ -105,10 +105,6 @@ protected boolean isObjectOfLanguage(Object object) { return false; } - public static ContextReference getCurrentContextReference() { - return getCurrentLanguage(Language.class).getContextReference(); - } - public static Env getCurrentContext() { return getCurrentContext(Language.class); } 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 f4f94769ace9..5a598e1714ac 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 @@ -41,11 +41,17 @@ package com.oracle.truffle.api.debug.test; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Set; +import org.graalvm.options.OptionCategory; +import org.graalvm.options.OptionDescriptors; +import org.graalvm.options.OptionKey; + import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; +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; @@ -67,10 +73,6 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; -import java.util.Collections; -import org.graalvm.options.OptionCategory; -import org.graalvm.options.OptionDescriptors; -import org.graalvm.options.OptionKey; /** * A language for testing instruments on various positions of instrumentable nodes. @@ -134,7 +136,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { } public TestNode parse(Source code) { - int preMaterialization = getContextReference().get().getPreMaterialization(); + int preMaterialization = getCurrentContext(InstrumentablePositionsTestLanguage.class).getPreMaterialization(); return new Parser(this, code, preMaterialization).parse(); } @@ -292,7 +294,7 @@ TestNode getNode() { RootCallTarget taget = Truffle.getRuntime().createCallTarget(new TestRootNode(lang, this)); node = new CallNode(taget); } else { - node = new BaseNode(this, lang.getContextReference()); + node = new BaseNode(this); } } } @@ -338,13 +340,12 @@ private interface TestNode extends NodeInterface { private static final class TestRootNode extends RootNode implements TestNode { private final NodeDescriptor nodeDescriptor; - private final ContextReference contextRef; - private @Children TestNode[] children; + @CompilationFinal private ContextReference contextRef; + @Children private TestNode[] children; TestRootNode(InstrumentablePositionsTestLanguage lang, NodeDescriptor nodeDescriptor) { super(lang); this.nodeDescriptor = nodeDescriptor; - contextRef = lang.getContextReference(); children = resolveChildren(nodeDescriptor, false); } @@ -361,6 +362,10 @@ public SourceSection getSourceSection() { @Override @ExplodeLoop public Object execute(VirtualFrame frame) { + if (contextRef == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + this.contextRef = lookupContextReference(InstrumentablePositionsTestLanguage.class); + } Object returnValue = contextRef.get().nul; for (TestNode child : children) { if (child != null) { @@ -398,13 +403,12 @@ static class BaseNode extends Node implements TestNode, InstrumentableNode { private final NodeDescriptor nodeDescriptor; private final boolean instrumentable; - private final ContextReference contextRef; private @Children TestNode[] children; + @CompilationFinal private ContextReference contextRef; - BaseNode(NodeDescriptor nodeDescriptor, ContextReference contextRef) { + BaseNode(NodeDescriptor nodeDescriptor) { this.nodeDescriptor = nodeDescriptor; this.instrumentable = nodeDescriptor.isInstrumentable(); - this.contextRef = contextRef; } BaseNode(BaseNode node) { @@ -453,6 +457,10 @@ public InstrumentableNode materializeInstrumentableNodes(Set contextReference; + @CompilationFinal private ContextReference contextReference; @Child private InteropLibrary interop = InteropLibrary.getFactory().createDispatched(5); - @CompilerDirectives.CompilationFinal protected FrameSlot slot; + @CompilationFinal protected FrameSlot slot; - VarNode(String name, Object value, SourceSection sourceSection, ContextReference contextReference) { + VarNode(ValuesLanguage language, String name, Object value, SourceSection sourceSection) { + this.language = language; this.name = name; this.value = value; this.sourceSection = sourceSection; - this.contextReference = contextReference; } public VarNode(VarNode node) { + this.language = node.language; this.name = node.name; this.value = node.value; this.sourceSection = node.sourceSection; - this.contextReference = node.contextReference; } public WrapperNode createWrapper(ProbeNode probe) { @@ -521,7 +523,7 @@ public Object execute(VirtualFrame frame) { frame.setObject(slot, value); } try { - interop.writeMember(contextReference.get().getEnv().getPolyglotBindings(), name, value); + interop.writeMember(getContextReference().get().getEnv().getPolyglotBindings(), name, value); } catch (UnknownIdentifierException | UnsupportedTypeException | UnsupportedMessageException e) { CompilerDirectives.transferToInterpreter(); // should not happen for polyglot bindings. @@ -530,6 +532,14 @@ public Object execute(VirtualFrame frame) { return value; } + protected final ContextReference getContextReference() { + if (contextReference == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + this.contextReference = lookupContextReference(language.getClass()); + } + return this.contextReference; + } + @Override public SourceSection getSourceSection() { return sourceSection; @@ -543,8 +553,8 @@ public static class PropNode extends ValuesLanguage.VarNode { private final String prop; @Child private InteropLibrary interop = InteropLibrary.getFactory().createDispatched(5); - PropNode(String var, String prop, Object value, SourceSection sourceSection, ContextReference contextReference) { - super(null, value, sourceSection, contextReference); + PropNode(ValuesLanguage language, String var, String prop, Object value, SourceSection sourceSection) { + super(language, null, value, sourceSection); this.var = var; this.prop = prop; } @@ -581,7 +591,7 @@ public Object execute(VirtualFrame frame) { slot = frame.getFrameDescriptor().findFrameSlot(var); if (slot == null) { try { - varObj = interop.readMember(contextReference.get().getEnv().getPolyglotBindings(), var); + varObj = interop.readMember(getContextReference().get().getEnv().getPolyglotBindings(), var); } catch (UnknownIdentifierException e) { varObj = null; } catch (UnsupportedMessageException e) { 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 995fee8d6331..27c696f5075e 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 @@ -638,7 +638,7 @@ public Object execute(VirtualFrame frame) { }); } - private AllocNode parse(String code) { + private static AllocNode parse(String code) { String[] allocations = code.split("\\s"); LinkedList futures = new LinkedList<>(); FutureNode parent = new FutureNode(null, null); @@ -652,11 +652,11 @@ private AllocNode parse(String code) { continue; } if (last != null) { - parent.addChild(last.toNode(getContextReference())); + parent.addChild(last.toNode()); last = null; } if ("}".equals(allocCommand)) { - AllocNode node = parent.toNode(getContextReference()); + AllocNode node = parent.toNode(); futures.removeLast(); // the "parent" removed parent = futures.getLast(); parent.addChild(node); @@ -673,9 +673,9 @@ private AllocNode parse(String code) { } } if (last != null) { - parent.addChild(last.toNode(getContextReference())); + parent.addChild(last.toNode()); } - return futures.removeLast().toNode(getContextReference()); + return futures.removeLast().toNode(); } private static AllocValue parseValue(String allocCommand) { @@ -740,11 +740,12 @@ void addChild(AllocNode node) { children.add(node); } - AllocNode toNode(ContextReference contextRef) { + AllocNode toNode() { + AllocationReporter reporter = getCurrentContext().getEnv().lookup(AllocationReporter.class); if (children == null) { - return new AllocNode(oldValue, newValue, contextRef); + return new AllocNode(oldValue, newValue, reporter); } else { - return new AllocNode(oldValue, newValue, contextRef, children.toArray(new AllocNode[children.size()])); + return new AllocNode(oldValue, newValue, reporter, children.toArray(new AllocNode[children.size()])); } } } @@ -756,15 +757,15 @@ private static class AllocNode extends Node { @Children private final AllocNode[] children; private final AllocationReporter reporter; - AllocNode(AllocValue oldValue, AllocValue newValue, ContextReference contextRef) { - this(oldValue, newValue, contextRef, null); + AllocNode(AllocValue oldValue, AllocValue newValue, AllocationReporter reporter) { + this(oldValue, newValue, reporter, null); } - AllocNode(AllocValue oldValue, AllocValue newValue, ContextReference contextRef, AllocNode[] children) { + AllocNode(AllocValue oldValue, AllocValue newValue, AllocationReporter reporter, AllocNode[] children) { this.oldValue = oldValue; this.newValue = newValue; this.children = children; - this.reporter = contextRef.get().getEnv().lookup(AllocationReporter.class); + this.reporter = reporter; } public Object execute(VirtualFrame frame) { 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 10ede0362591..fa185af1a80d 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 @@ -265,7 +265,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { } catch (LanguageError e) { throw new IOException(e); } - RootCallTarget afterTarget = getContextReference().get().afterTarget; + RootCallTarget afterTarget = getCurrentContext(getClass()).afterTarget; return lastParsed = Truffle.getRuntime().createCallTarget(new InstrumentationTestRootNode(this, "", outer, afterTarget, node)); } @@ -493,7 +493,7 @@ private BaseNode createNode(String tag, String[] idents, SourceSection sourceSec case "CONSTANT": return new ConstantNode(idents[0], childArray); case "VARIABLE": - return new VariableNode(idents[0], idents[1], childArray, lang.getContextReference()); + return new VariableNode(idents[0], idents[1], childArray, currentEnv().lookup(AllocationReporter.class)); case "PRINT": return new PrintNode(idents[0], idents[1], childArray); case "ALLOCATION": @@ -1518,11 +1518,11 @@ private static final class VariableNode extends InstrumentedNode { @CompilationFinal private FrameSlot slot; final AllocationReporter allocationReporter; - private VariableNode(String name, String identifier, BaseNode[] children, ContextReference contextRef) { + private VariableNode(String name, String identifier, BaseNode[] children, AllocationReporter allocationReporter) { super(children); this.name = name; this.value = parseIdent(identifier); - this.allocationReporter = contextRef.get().allocationReporter; + this.allocationReporter = allocationReporter; } @Override diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/AllocationReporter.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/AllocationReporter.java index 1ecbf2a3a6c5..2989ca3bb977 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/AllocationReporter.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/AllocationReporter.java @@ -361,6 +361,10 @@ class AllocationReporterSnippets extends TruffleLanguage { void example() { } + static ContextObject getCurrentContext() { + return getCurrentContext(AllocationReporterSnippets.class); + } + // @formatter:off // BEGIN: AllocationReporterSnippets#example @Override @@ -370,7 +374,7 @@ protected ContextObject createContext(Env env) { } Object allocateNew() { - AllocationReporter reporter = getContextReference().get().getReporter(); + AllocationReporter reporter = getCurrentContext().getReporter(); // Test if the reporter is active, we should compute the size estimate if (reporter.isActive()) { long size = findSizeEstimate(); @@ -388,7 +392,7 @@ Object allocateNew() { } Object allocateComplex() { - AllocationReporter reporter = getContextReference().get().getReporter(); + AllocationReporter reporter = getCurrentContext().getReporter(); // If the allocated size is a constant, onEnter() and onReturnValue() // can be called without a fast-path performance penalty when not active reporter.onEnter(null, 0, 16); 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 0ffb11f748db..e368af5b8c12 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 @@ -794,7 +794,7 @@ LanguageReference lookupLanguageReference0(SupplierAccessor no } } - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings({"rawtypes", "unchecked", "deprecation"}) ContextReference getContextReference() { Object prev = enterInner(); try { 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 5d0754f93da9..656da4aa69e2 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 @@ -1187,7 +1187,7 @@ protected void initializeContext(CountingContext context) throws Exception { @Override protected boolean patchContext(CountingContext context, TruffleLanguage.Env newEnv) { - assertNotNull(getContextReference().get()); + assertNotNull(getCurrentContext(getClass())); assertTrue(context.preInitialized); assertFalse(context.env.isPreInitialization()); context.patchContextCount++; 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 0434fb6cdc64..e6088d8fba14 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 @@ -843,7 +843,7 @@ public void testMultiContextBoundEngineInnerContextNoCaching() throws Exception MultiContextLanguage innerLang = OneContextLanguage.getCurrentLanguage(); assertNotSame(innerLang, lang); - Env innerEnv = innerLang.getContextReference().get().env; + Env innerEnv = OneContextLanguage.getCurrentContext().env; innerEnv.parsePublic(truffleSource1); assertEquals(1, innerLang.parseCalled.size()); assertEquals(0, innerLang.initializeMultiContextCalled.size()); @@ -1965,7 +1965,7 @@ protected void initializeContext(ProxyLanguage.LanguageContext context) throws E @Override protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { try { - getContextReference().get().env.registerService(new LanguageSPITestLanguageService3() { + getCurrentContext().env.registerService(new LanguageSPITestLanguageService3() { }); fail("Illegal state exception should be thrown when calling Env.registerService outside createContext"); } catch (IllegalStateException e) { diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITestLanguage.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITestLanguage.java index 6ce74b29e02c..0bdcf3df8d66 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITestLanguage.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITestLanguage.java @@ -119,6 +119,7 @@ protected void initializeContext(LanguageContext context) throws Exception { context.initialized = true; } + @SuppressWarnings("deprecation") @Override protected void disposeContext(LanguageContext context) { if (context.initialized) { 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 ff02ab8db78a..9d9d01f3e956 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 @@ -110,10 +110,6 @@ public static ProxyLanguage getCurrentLanguage() { return getCurrentLanguage(ProxyLanguage.class); } - public static ContextReference getCurrentContextReference() { - return getCurrentLanguage(ProxyLanguage.class).getContextReference(); - } - @Override protected LanguageContext createContext(com.oracle.truffle.api.TruffleLanguage.Env env) { if (wrapper) { 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 09bcdb6ad973..c36570c439ab 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 @@ -163,7 +163,7 @@ protected RootNode(TruffleLanguage language, FrameDescriptor frameDescriptor) /** * @see TruffleLanguage#getContextReference() * @since 0.27 - * @deprecated use {@link #getContextSupplier(Class)} instead. + * @deprecated use {@link #lookupContextReference(Class)} instead. */ @SuppressWarnings("deprecation") @Deprecated 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 4333ddf2ae1d..6374327d40b6 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 @@ -73,7 +73,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception { backendId = source.getNFIBackendId(); } - NFIBackend backend = getContextReference().get().getBackend(backendId); + NFIBackend backend = getCurrentContext(NFILanguage.class).getBackend(backendId); CallTarget loadLibrary = backend.parse(source.getLibraryDescriptor()); return Truffle.getRuntime().createCallTarget(new NFIRootNode(this, loadLibrary, source)); } diff --git a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/FunctionExecuteNode.java b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/FunctionExecuteNode.java index 4a5792ebb393..1b8c6c4a2c1e 100644 --- a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/FunctionExecuteNode.java +++ b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/FunctionExecuteNode.java @@ -42,6 +42,7 @@ 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.ContextReference; @@ -239,15 +240,19 @@ static Object genericExecute(NativePointer receiver, LibFFISignature signature, static class SlowPathExecuteNode extends RootNode { - final ContextReference ctxRef; + @CompilationFinal ContextReference ctxRef; SlowPathExecuteNode(NFILanguageImpl language) { super(language); - ctxRef = language.getContextReference(); } @Override public Object execute(VirtualFrame frame) { + if (ctxRef == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + ctxRef = lookupContextReference(NFILanguageImpl.class); + } + NativePointer receiver = (NativePointer) frame.getArguments()[0]; LibFFISignature signature = (LibFFISignature) frame.getArguments()[1]; NativeArgumentBuffer.Array buffer = (NativeArgumentBuffer.Array) frame.getArguments()[2]; diff --git a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/NFILanguageImpl.java b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/NFILanguageImpl.java index fa4a64f35e6f..84b869e65555 100644 --- a/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/NFILanguageImpl.java +++ b/truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/impl/NFILanguageImpl.java @@ -185,7 +185,7 @@ private final class NFIBackendImpl implements NFIBackend { @Override public CallTarget parse(NativeLibraryDescriptor descriptor) { RootNode root; - NFIContext ctx = getContextReference().get(); + NFIContext ctx = getCurrentContext(NFILanguageImpl.class); if (descriptor.isDefaultLibrary()) { root = new GetDefaultLibraryNode(NFILanguageImpl.this); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostLanguage.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostLanguage.java index f0fb6765985a..bbdfac02c368 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostLanguage.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostLanguage.java @@ -53,6 +53,7 @@ import org.graalvm.polyglot.proxy.Proxy; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Scope; import com.oracle.truffle.api.Truffle; @@ -203,9 +204,15 @@ private static boolean isHostFunction(Object object) { protected CallTarget parse(com.oracle.truffle.api.TruffleLanguage.ParsingRequest request) throws Exception { String sourceString = request.getSource().getCharacters().toString(); return Truffle.getRuntime().createCallTarget(new RootNode(this) { + + @CompilationFinal ContextReference contextRef; + @Override public Object execute(VirtualFrame frame) { - HostContext context = getContextReference().get(); + if (contextRef == null) { + contextRef = lookupContextReference(HostLanguage.class); + } + HostContext context = contextRef.get(); Class allTarget = context.findClass(sourceString); return context.internalContext.toGuestValue(allTarget); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java index 5f2ee1b952e0..6303e38d1b71 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java @@ -307,7 +307,7 @@ private static final class AssumeSingleContext extends ContextReference @Override public Object get() { Object context; - if (validIf0.isValid() && (validIf1 == null || validIf1.isValid())) { + if ((validIf0 == null || validIf0.isValid()) && (validIf1 == null || validIf1.isValid())) { context = singleContextReference.get(); } else { context = fallbackReference.get(); 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 1cef9678f72f..3aec6c1017b9 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 @@ -51,6 +51,8 @@ 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; @@ -95,6 +97,9 @@ protected boolean isObjectOfLanguage(Object object) { @Override protected CallTarget parse(ParsingRequest request) throws Exception { return Truffle.getRuntime().createCallTarget(new RootNode(this) { + + @CompilationFinal private ContextReference reference; + @Override public Object execute(VirtualFrame frame) { return parseAndEval(); @@ -102,8 +107,12 @@ public Object execute(VirtualFrame frame) { @TruffleBoundary private Object parseAndEval() { + if (reference == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + this.reference = lookupContextReference(EvalLang.class); + } Source aPlusB = Source.newBuilder("sl", "a + b", "plus.sl").build(); - return getContextReference().get().parsePublic(aPlusB, "a", "b").call(30, 12); + return reference.get().parsePublic(aPlusB, "a", "b").call(30, 12); } }); } diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java index ab2ecb4b392d..fde54ca4f5f0 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java @@ -45,7 +45,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.RootNode; @@ -69,15 +68,12 @@ public final class SLEvalRootNode extends RootNode { private final Map functions; @CompilationFinal private boolean registered; - private final ContextReference reference; - @Child private DirectCallNode mainCallNode; public SLEvalRootNode(SLLanguage language, RootCallTarget rootFunction, Map functions) { super(language); this.functions = functions; this.mainCallNode = rootFunction != null ? DirectCallNode.create(rootFunction) : null; - this.reference = language.getContextReference(); } @Override @@ -90,6 +86,11 @@ protected boolean isInstrumentable() { return false; } + @Override + public boolean isInternal() { + return true; + } + @Override public String getName() { return "root eval"; @@ -106,7 +107,7 @@ public Object execute(VirtualFrame frame) { if (!registered) { /* Function registration is a slow-path operation that must not be compiled. */ CompilerDirectives.transferToInterpreterAndInvalidate(); - reference.get().getFunctionRegistry().register(functions); + lookupContextReference(SLLanguage.class).get().getFunctionRegistry().register(functions); registered = true; } diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java index e0a65b21432c..09fed82e782f 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.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.TruffleLanguage.ContextReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.sl.SLLanguage; @@ -72,11 +71,8 @@ public final class SLFunctionLiteralNode extends SLExpressionNode { */ @CompilationFinal private SLFunction cachedFunction; - private final ContextReference reference; - - public SLFunctionLiteralNode(SLLanguage language, String functionName) { + public SLFunctionLiteralNode(String functionName) { this.functionName = functionName; - this.reference = language.getContextReference(); } @Override @@ -85,7 +81,7 @@ public SLFunction executeGeneric(VirtualFrame frame) { /* We are about to change a @CompilationFinal field. */ CompilerDirectives.transferToInterpreterAndInvalidate(); /* First execution of the node: lookup the function in the function registry. */ - cachedFunction = reference.get().getFunctionRegistry().lookup(functionName, true); + cachedFunction = lookupContextReference(SLLanguage.class).get().getFunctionRegistry().lookup(functionName, true); } return cachedFunction; } 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 5aaab24842fe..2a90abb382b4 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 @@ -491,7 +491,7 @@ public SLExpressionNode createRead(SLExpressionNode nameNode) { result = SLReadLocalVariableNodeGen.create(frameSlot); } else { /* Read of a global name. In our language, the only global names are functions. */ - result = new SLFunctionLiteralNode(language, name); + result = new SLFunctionLiteralNode(name); } result.setSourceSection(nameNode.getSourceCharIndex(), nameNode.getSourceLength()); result.addExpressionTag(); From b1456732dc7f39352cf94ab230aad74493bf7ff7 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 7 Oct 2019 14:04:03 +0200 Subject: [PATCH 061/140] Migrate LLVM context lookups to not use deprecated APIs. --- .../com/oracle/truffle/llvm/nfi/SulongNFI.java | 2 +- .../truffle/llvm/runtime/LLVMContext.java | 7 +++++-- .../truffle/llvm/runtime/LLVMLanguage.java | 17 +++++++++++------ .../truffle/llvm/runtime/ToolchainImpl.java | 2 +- .../runtime/interop/LLVMForeignCallNode.java | 8 ++++++-- .../runtime/interop/nfi/LLVMNativeWrapper.java | 3 ++- .../llvm/runtime/nodes/api/LLVMNode.java | 2 +- .../intrinsics/llvm/debug/LLDBConstant.java | 4 ++-- .../runtime/pointer/NativePointerLibraries.java | 2 +- .../src/com/oracle/truffle/llvm/Runner.java | 12 ++++++++++-- .../llvm/tests/interop/LLVMInteropTest.java | 13 ++++++++----- 11 files changed, 48 insertions(+), 24 deletions(-) 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 f73ba3b151bb..01927badfba7 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 @@ -85,7 +85,7 @@ private final class SulongNFIBackend implements NFIBackend { @Override public CallTarget parse(NativeLibraryDescriptor descriptor) { - Env env = getContextReference().get(); + Env env = getCurrentContext(SulongNFI.class); TruffleFile file = env.getInternalTruffleFile(descriptor.getFilename()); try { Source source = Source.newBuilder("llvm", file).build(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java index a7d58b854516..96aaba51213a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java @@ -217,13 +217,12 @@ synchronized LLVMFunctionDescriptor create(String name, FunctionType type, LLVMF private static final class InitializeContextNode extends LLVMStatementNode { - private final ContextReference ctxRef; + @CompilationFinal private ContextReference ctxRef; private final FrameSlot stackPointer; @Child DirectCallNode initContext; InitializeContextNode(LLVMContext ctx, FrameDescriptor rootFrame) { - this.ctxRef = ctx.getLanguage().getContextReference(); this.stackPointer = rootFrame.findFrameSlot(LLVMStack.FRAME_ID); LLVMFunctionDescriptor initContextDescriptor = ctx.globalScope.getFunction("__sulong_init_context"); @@ -233,6 +232,10 @@ private static final class InitializeContextNode extends LLVMStatementNode { @Override public void execute(VirtualFrame frame) { + if (ctxRef == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + ctxRef = lookupContextReference(LLVMLanguage.class); + } LLVMContext ctx = ctxRef.get(); if (!ctx.initialized) { assert !ctx.cleanupNecessary; 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 51bb1e3a559c..6cce4f37dca1 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 @@ -95,10 +95,6 @@ public abstract static class Loader implements LLVMCapability { public abstract CallTarget load(LLVMContext context, Source source); } - public static ContextReference getLLVMContextReference() { - return getCurrentLanguage(LLVMLanguage.class).getContextReference(); - } - public List getLanguageContextExtension() { return contextExtensions; } @@ -121,6 +117,16 @@ public T getContextExtensionOrNull(Class type) { return null; } + /** + * Do not use this on fast-path. + */ + public static LLVMContext getContext() { + return getCurrentContext(LLVMLanguage.class); + } + + /** + * Do not use this on fast-path. + */ public static LLVMLanguage getLanguage() { return getCurrentLanguage(LLVMLanguage.class); } @@ -188,8 +194,7 @@ protected void disposeContext(LLVMContext context) { @Override protected CallTarget parse(ParsingRequest request) { Source source = request.getSource(); - LLVMContext context = getContextReference().get(); - return getCapability(Loader.class).load(context, source); + return getCapability(Loader.class).load(getContext(), source); } @Override diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/ToolchainImpl.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/ToolchainImpl.java index 895c45017823..ea5b8132aaa6 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/ToolchainImpl.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/ToolchainImpl.java @@ -62,7 +62,7 @@ public TruffleFile getToolPath(String tool) { } protected TruffleFile getRoot() { - TruffleLanguage.Env env = language.getContextReference().get().getEnv(); + TruffleLanguage.Env env = LLVMLanguage.getContext().getEnv(); String toolchainRoot = toolchainConfig.getToolchainRootOverride(); return toolchainRoot != null // ? env.getInternalTruffleFile(toolchainRoot) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java index 831fc0a13a34..43fa7745c8af 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java @@ -31,6 +31,7 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -151,7 +152,7 @@ Object[] error(Object[] arguments, @SuppressWarnings("unused") StackPointer stac } } - private final ContextReference ctxRef; + @CompilationFinal private ContextReference ctxRef; private final LLVMInteropType.Structured returnBaseType; @Child LLVMGetStackNode getStack; @@ -161,7 +162,6 @@ Object[] error(Object[] arguments, @SuppressWarnings("unused") StackPointer stac public LLVMForeignCallNode(LLVMLanguage language, LLVMFunctionDescriptor function, LLVMInteropType interopType) { super(language); - this.ctxRef = language.getContextReference(); this.returnBaseType = getReturnBaseType(interopType); this.getStack = LLVMGetStackNode.create(); this.callNode = DirectCallNode.create(getCallTarget(function)); @@ -178,6 +178,10 @@ public boolean isInternal() { @Override public Object execute(VirtualFrame frame) { Object result; + if (ctxRef == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + ctxRef = lookupContextReference(LLVMLanguage.class); + } LLVMThreadingStack threadingStack = ctxRef.get().getThreadingStack(); LLVMStack stack = getStack.executeWithTarget(threadingStack, Thread.currentThread()); try (StackPointer stackPointer = stack.newFrame()) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/nfi/LLVMNativeWrapper.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/nfi/LLVMNativeWrapper.java index 94352c04e5d1..1cf2700f3e08 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/nfi/LLVMNativeWrapper.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/nfi/LLVMNativeWrapper.java @@ -32,6 +32,7 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.CachedContext; import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; @@ -95,7 +96,7 @@ abstract static class CallbackHelperNode extends LLVMNode { Object doCached(@SuppressWarnings("unused") LLVMFunctionDescriptor function, Object[] args, @Cached("function") @SuppressWarnings("unused") LLVMFunctionDescriptor cachedFunction, @Cached LLVMGetStackNode getStack, - @Cached("getLLVMContextReference()") ContextReference ctxRef, + @CachedContext(LLVMLanguage.class) ContextReference ctxRef, @Cached("createCallNode(cachedFunction)") DirectCallNode call, @Cached("createFromNativeNodes(cachedFunction.getType())") LLVMNativeConvertNode[] convertArgs, @Cached("createToNative(cachedFunction.getType().getReturnType())") LLVMNativeConvertNode convertRet) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java index 6428242423de..d1c09d9d3910 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java @@ -114,7 +114,7 @@ protected final DataLayout getDataLayout() { assert !(datalayoutNode instanceof RootNode) : "root node must not have a parent"; datalayoutNode = datalayoutNode.getParent(); } else { - return LLVMLanguage.getLLVMContextReference().get().getLibsulongDataLayout(); + return LLVMLanguage.getContext().getLibsulongDataLayout(); } } return ((LLVMHasDatalayoutNode) datalayoutNode).getDatalayout(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLDBConstant.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLDBConstant.java index 72dcf1bb5d4a..a55066f67f3e 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLDBConstant.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLDBConstant.java @@ -358,7 +358,7 @@ public Object asInteropValue() { Object foreign = null; if (LLVMNativePointer.isInstance(pointer)) { - foreign = LLVMLanguage.getLLVMContextReference().get().getManagedObjectForHandle(LLVMNativePointer.cast(pointer)); + foreign = LLVMLanguage.getContext().getManagedObjectForHandle(LLVMNativePointer.cast(pointer)); } else if (LLVMManagedPointer.isInstance(pointer)) { foreign = LLVMManagedPointer.cast(pointer).getObject(); @@ -378,7 +378,7 @@ public boolean isInteropValue() { return false; } else if (LLVMNativePointer.isInstance(pointer)) { - return LLVMLanguage.getLLVMContextReference().get().isHandle(LLVMNativePointer.cast(pointer)); + return LLVMLanguage.getContext().isHandle(LLVMNativePointer.cast(pointer)); } else if (LLVMManagedPointer.isInstance(pointer)) { final Object target = LLVMManagedPointer.cast(pointer).getObject(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/NativePointerLibraries.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/NativePointerLibraries.java index bec0fac49b27..50a63e6a6b11 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/NativePointerLibraries.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/NativePointerLibraries.java @@ -74,7 +74,7 @@ static class Execute { @Specialization(limit = "5", guards = {"value.asNative() == cachedAddress", "cachedDescriptor != null"}) static Object doNativeCached(@SuppressWarnings("unused") LLVMPointerImpl value, Object[] args, @Cached("value.asNative()") @SuppressWarnings("unused") long cachedAddress, - @Cached("getLLVMContextReference()") ContextReference ctxRef, + @CachedContext(LLVMLanguage.class) ContextReference ctxRef, @Cached("getDescriptor(ctxRef, value)") LLVMFunctionDescriptor cachedDescriptor, @CachedLibrary("cachedDescriptor") InteropLibrary interop) throws UnsupportedTypeException, ArityException, UnsupportedMessageException { return interop.execute(cachedDescriptor, args); diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index a3987ecedb17..67589ae3324d 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -51,6 +51,7 @@ 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.RootCallTarget; import com.oracle.truffle.api.Truffle; @@ -173,7 +174,7 @@ private static class LoadModulesNode extends RootNode { final SulongLibrary sulongLibrary; final FrameSlot stackPointerSlot; - final ContextReference ctxRef; + @CompilationFinal ContextReference ctxRef; final int initContextBefore; @Child LLVMStatementNode initContext; @@ -181,11 +182,13 @@ private static class LoadModulesNode extends RootNode { @Children final InitializeSymbolsNode[] initSymbols; @Children final InitializeModuleNode[] initModules; + private final Runner runner; + LoadModulesNode(Runner runner, FrameDescriptor rootFrame, InitializationOrder order, SulongLibrary sulongLibrary) { super(runner.language, rootFrame); + this.runner = runner; this.sulongLibrary = sulongLibrary; this.stackPointerSlot = rootFrame.findFrameSlot(LLVMStack.FRAME_ID); - this.ctxRef = runner.language.getContextReference(); this.initContextBefore = order.sulongLibraries.size(); this.initContext = runner.context.createInitializeContextNode(rootFrame); @@ -209,6 +212,11 @@ private static void createNodes(Runner runner, FrameDescriptor rootFrame, List Date: Mon, 7 Oct 2019 14:04:17 +0200 Subject: [PATCH 062/140] Fix javadoc links. --- .../instrumentation/InstrumentableNode.java | 25 ++++++++----------- .../oracle/truffle/api/TruffleLanguage.java | 2 +- 2 files changed, 11 insertions(+), 16 deletions(-) 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 34778e618c2d..5483bc99c37c 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 @@ -113,8 +113,7 @@ public interface InstrumentableNode extends NodeInterface { * 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 {@link TruffleLanguage#getContextReference() - * language context} currently being active. + * threaded. The method may be invoked without a language context currently being active. * * @since 0.33 */ @@ -150,8 +149,8 @@ public interface InstrumentableNode extends NodeInterface { * delegate has just thrown an exception. * *

    - * This method is always invoked on an interpreter thread. The method is always invoked with a - * {@link TruffleLanguage#getContextReference() language context} currently being active. + * This method is always invoked on an interpreter thread. The method may be invoked without a + * language context currently being active. * * @param probe the {@link ProbeNode probe node} to be adopted and sent execution events by the * wrapper @@ -188,8 +187,7 @@ public interface InstrumentableNode extends NodeInterface { * 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 {@link TruffleLanguage#getContextReference() - * language context} currently being active. + * threaded. The method may be invoked without a language context currently being active. * * @param tag the class {@link com.oracle.truffle.api.instrumentation.ProvidedTags provided} by * the {@link TruffleLanguage language} @@ -227,9 +225,9 @@ default boolean hasTag(Class tag) { * a TruffleObject and return this instance. *

    * This method might be called in parallel from multiple threads even if the language is single - * threaded. The method may be invoked without a {@link TruffleLanguage#getContextReference() - * language context} currently being active. The {@link Node#getLock() AST lock} is held while - * {@link #getNodeObject()} object is invoked. There is no lock held when the object is read. + * threaded. The method may be invoked without a language context currently being active. The + * {@link Node#getLock() AST lock} is held while {@link #getNodeObject()} object is invoked. + * There is no lock held when the object is read. * * @return the node object as TruffleObject or null if no node object properties * are available for this instrumented node @@ -258,8 +256,7 @@ default Object getNodeObject() { * The AST lock is acquired while this method is invoked. Therefore it is not allowed to run * guest language code while this method is invoked. This method might be called in parallel * from multiple threads even if the language is single threaded. The method may be invoked - * without a {@link TruffleLanguage#getContextReference() language context} currently being - * active. + * without a language context currently being active. *

    * In the example below, we show how the IncrementNode with a * ConstantNode child is optimized into a ConstantIncrementNode and @@ -387,8 +384,7 @@ public interface WrapperNode extends NodeInterface, InstrumentableFactory.Wrappe * whose execution events the wrapper reports to the instrumentation framework. *

    * This method might be called in parallel from multiple threads. The method may be invoked - * without a {@link TruffleLanguage#getContextReference() language context} currently being - * active. + * without a language context currently being active. * * @since 0.33 */ @@ -399,8 +395,7 @@ public interface WrapperNode extends NodeInterface, InstrumentableFactory.Wrappe * guest language delegate node. *

    * This method might be called in parallel from multiple threads. The method may be invoked - * without a {@link TruffleLanguage#getContextReference() language context} currently being - * active. + * without a language context currently being active. * * @since 0.33 */ 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 d5f0034a6776..98616b1647df 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 @@ -494,7 +494,7 @@ protected boolean areOptionsCompatible(OptionValues firstOptions, OptionValues n * here-in provided env and adjust itself according to parameters provided by the * env object. *

    - * The context created by this method is accessible using {@link #getContextReference()}. An + * The context created by this method is accessible using {@link #getCurrentContext(Class)}. An * {@link IllegalStateException} is thrown if the context is tried to be accessed while the * createContext method is executed. *

    From 43b0da9cb75517705e6dd36b8a510257dd0ff864 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 7 Oct 2019 14:07:19 +0200 Subject: [PATCH 063/140] Fix missing deopt in host language implementation. --- .../src/com/oracle/truffle/polyglot/HostLanguage.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostLanguage.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostLanguage.java index bbdfac02c368..1ef084175563 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostLanguage.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/HostLanguage.java @@ -53,6 +53,7 @@ import org.graalvm.polyglot.proxy.Proxy; 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.Scope; @@ -210,6 +211,7 @@ protected CallTarget parse(com.oracle.truffle.api.TruffleLanguage.ParsingRequest @Override public Object execute(VirtualFrame frame) { if (contextRef == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); contextRef = lookupContextReference(HostLanguage.class); } HostContext context = contextRef.get(); From ce17c2c1fc68d4de4cdab6551e4ebaaac2f30535 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 7 Oct 2019 14:30:17 +0200 Subject: [PATCH 064/140] Do not eagerly load context policy in language constructor to avoid loading all languages. --- .../src/com/oracle/truffle/polyglot/PolyglotLanguage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java index 016e0dfe6cc2..d644fb134e36 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java @@ -99,7 +99,7 @@ final class PolyglotLanguage extends AbstractLanguageImpl implements com.oracle. this.index = index; this.host = host; this.profile = new ContextProfile(this); - this.instancePool = cache.getPolicy() == ContextPolicy.EXCLUSIVE ? null : new LinkedList<>(); + this.instancePool = new LinkedList<>(); this.info = NODES.createLanguage(this, cache.getId(), cache.getName(), cache.getVersion(), cache.getDefaultMimeType(), cache.getMimeTypes(), cache.isInternal(), cache.isInteractive()); this.multiLanguageReference = PolyglotReferences.createAlwaysMultiLanguage(this); this.multiContextReference = PolyglotReferences.createAlwaysMultiContext(this); From 0faa7d50fd7e379d47ccb51dbb57e34c5cbb3d9b Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 7 Oct 2019 15:20:31 +0200 Subject: [PATCH 065/140] Do not save the Runner instance. --- .../src/com/oracle/truffle/llvm/Runner.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index 67589ae3324d..783eab5fe241 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -182,11 +182,8 @@ private static class LoadModulesNode extends RootNode { @Children final InitializeSymbolsNode[] initSymbols; @Children final InitializeModuleNode[] initModules; - private final Runner runner; - LoadModulesNode(Runner runner, FrameDescriptor rootFrame, InitializationOrder order, SulongLibrary sulongLibrary) { super(runner.language, rootFrame); - this.runner = runner; this.sulongLibrary = sulongLibrary; this.stackPointerSlot = rootFrame.findFrameSlot(LLVMStack.FRAME_ID); @@ -214,7 +211,7 @@ private static void createNodes(Runner runner, FrameDescriptor rootFrame, List Date: Mon, 7 Oct 2019 15:20:48 +0200 Subject: [PATCH 066/140] Add never part of compilation assertion to LLVMLanguage.getContext() --- .../src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java | 2 ++ 1 file changed, 2 insertions(+) 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 6cce4f37dca1..e1f7ff40aeb5 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 @@ -121,6 +121,7 @@ public T getContextExtensionOrNull(Class type) { * Do not use this on fast-path. */ public static LLVMContext getContext() { + CompilerAsserts.neverPartOfCompilation("Use faster context lookup methods for the fast-path."); return getCurrentContext(LLVMLanguage.class); } @@ -128,6 +129,7 @@ public static LLVMContext getContext() { * Do not use this on fast-path. */ public static LLVMLanguage getLanguage() { + // TODO add neverPartOfCompilation. return getCurrentLanguage(LLVMLanguage.class); } From c9fe8c2d12cbebfe16a170e364f9a8aaa3bcbbf9 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 7 Oct 2019 18:15:46 +0200 Subject: [PATCH 067/140] Fix context references when runtime assertions are enabled but compile time assertions are not. --- .../com/oracle/truffle/polyglot/PolyglotReferences.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java index 6303e38d1b71..0644b34c7f03 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotReferences.java @@ -156,7 +156,11 @@ private static PolyglotLanguageInstance lookupLanguageInstance(RootNode root) { private static boolean assertDirectContextAccess(PolyglotLanguageContext languageContext, Object languageContextImpl) throws AssertionError { if (languageContext == null) { - throw invalidSharingError(null); + /* + * This case may happen if the assertions were disabled during boot image generation but + * were later enabled at runtime. See GR-14463. + */ + return true; } PolyglotContextImpl otherContext = PolyglotContextImpl.requireContext(); PolyglotLanguageContext otherLanguageContext = otherContext.getContext(languageContext.language); @@ -245,6 +249,9 @@ private static boolean assertDirectContextAccess(Object seenContext, WeakReferen return true; } PolyglotLanguageContext context = contextRef.get(); + if (context == null) { + throw invalidSharingError(null); + } return PolyglotReferences.assertDirectContextAccess(context, seenContext); } From f7d467928cdf7cd83088f254b666a6aafa620181 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Mon, 7 Oct 2019 18:37:25 +0200 Subject: [PATCH 068/140] Merge fix. --- .../src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java index fde54ca4f5f0..ed22df0ad12f 100644 --- a/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java +++ b/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLEvalRootNode.java @@ -86,11 +86,6 @@ protected boolean isInstrumentable() { return false; } - @Override - public boolean isInternal() { - return true; - } - @Override public String getName() { return "root eval"; From c6880e78ab43ed4b1455542dbf46a4d809b503c7 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Thu, 26 Sep 2019 16:00:37 +0200 Subject: [PATCH 069/140] [GR-15292] LanguageCache legacy behaviour. --- .../truffle/api/instrumentation/Tag.java | 14 +- .../api/test/polyglot/LanguageSPITest.java | 35 - .../com/oracle/truffle/api/impl/Accessor.java | 2 +- .../truffle/polyglot/EngineAccessor.java | 4 +- .../truffle/polyglot/LanguageCache.java | 728 +++++++++++------- .../truffle/polyglot/PolyglotEngineImpl.java | 7 +- 6 files changed, 466 insertions(+), 324 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/Tag.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/Tag.java index 84d943298453..7261603e6dcc 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/Tag.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/Tag.java @@ -47,9 +47,9 @@ import java.lang.annotation.Target; import java.util.Objects; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.impl.Accessor.EngineSupport; import com.oracle.truffle.api.nodes.LanguageInfo; +import java.util.Set; /** * Base class for tags used in the Truffle instrumentation framework. @@ -86,14 +86,10 @@ public static Class findProvidedTag(LanguageInfo language, String if (engine == null) { return null; } - Class> lang = engine.getLanguageClass(language); - ProvidedTags tags = lang.getAnnotation(ProvidedTags.class); - if (tags != null) { - for (Class tag : (Class[]) tags.value()) { - String alias = getIdentifier(tag); - if (alias != null && alias.equals(tagId)) { - return tag; - } + for (Class tag : (Set>) engine.getProvidedTags(language)) { + String alias = getIdentifier(tag); + if (alias != null && alias.equals(tagId)) { + return tag; } } return null; 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 0434fb6cdc64..55b51f52f671 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 @@ -51,8 +51,6 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -1847,13 +1845,11 @@ public void testLookup() { } } // Non registered service - resetLoadedLanguage(SERVICE_LANGUAGE); try (Context context = Context.newBuilder().allowPolyglotAccess(PolyglotAccess.ALL).build()) { context.initialize(ProxyLanguage.ID); context.enter(); try { assertFalse(lookupLanguage(LanguageSPITestLanguageService3.class)); - assertFalse(isLanguageLoaded(SERVICE_LANGUAGE)); } finally { context.leave(); } @@ -1909,37 +1905,6 @@ protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { static final String SERVICE_LANGUAGE = "ServiceTestLanguage"; - private static boolean isLanguageLoaded(String languageId) { - try { - Object languageCache = findLanguageCache(languageId); - Field field = languageCache.getClass().getDeclaredField("languageClass"); - field.setAccessible(true); - return field.get(languageCache) != null; - } catch (ReflectiveOperationException e) { - throw new AssertionError("Cannot reflectively read LanguageCache.languageClass field.", e); - } - } - - private static void resetLoadedLanguage(String languageId) { - try { - Object languageCache = findLanguageCache(languageId); - Field field = languageCache.getClass().getDeclaredField("languageClass"); - field.setAccessible(true); - field.set(languageCache, null); - } catch (ReflectiveOperationException e) { - throw new AssertionError("Cannot reflectively read LanguageCache.languageClass field.", e); - } - } - - @SuppressWarnings("unchecked") - private static Object findLanguageCache(String languageId) throws ReflectiveOperationException { - Class clazz = Class.forName("com.oracle.truffle.polyglot.LanguageCache"); - Method m = clazz.getDeclaredMethod("languages", ClassLoader.class); - m.setAccessible(true); - Map map = (Map) m.invoke(null, (Object) null); - return map.get(languageId); - } - @Test public void testRegisterService() { ProxyLanguage registerServiceLanguage = new ProxyLanguage() { 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 ab156963f515..4e9165e23346 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 @@ -316,7 +316,7 @@ public Thread createThread(Object vmObject, Runnable runnable, Object innerConte public abstract T getOrCreateRuntimeData(Object sourceVM, Function constructor); - public abstract Class> getLanguageClass(LanguageInfo language); + public abstract Set> getProvidedTags(LanguageInfo language); public abstract Object getPolyglotBindingsForLanguage(Object vmObject); 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 57a009cf1847..8b2dd928cebe 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 @@ -652,8 +652,8 @@ public PolyglotException wrapGuestException(String languageId, Throwable e) { } @Override - public Class> getLanguageClass(LanguageInfo language) { - return ((PolyglotLanguage) NODES.getEngineObject(language)).cache.getLanguageClass(); + public Set> getProvidedTags(LanguageInfo language) { + return ((PolyglotLanguage) NODES.getEngineObject(language)).cache.getProvidedTags(); } @SuppressWarnings("unchecked") diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java index 7629c99dee67..5d33c990aad1 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java @@ -69,6 +69,11 @@ import com.oracle.truffle.api.TruffleLanguage.Registration; import com.oracle.truffle.api.impl.TruffleJDKServices; import com.oracle.truffle.api.TruffleOptions; +import com.oracle.truffle.api.instrumentation.ProvidedTags; +import com.oracle.truffle.api.instrumentation.Tag; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Objects; /** * Ahead-of-time initialization. If the JVM is started with {@link TruffleOptions#AOT}, it populates @@ -82,7 +87,6 @@ final class LanguageCache implements Comparable { private final String className; private final Set mimeTypes; private final Set characterMimeTypes; - private final Set byteMimeTypes; private final String defaultMimeType; private final Set dependentLanguages; private final String id; @@ -91,115 +95,60 @@ final class LanguageCache implements Comparable { private final String version; private final boolean interactive; private final boolean internal; - private final ClassLoader loader; private final TruffleLanguage globalInstance; private final Set services; - private final List fileTypeDetectorClassNames; + private final LanguageReflection languageReflection; private String languageHome; - private volatile ContextPolicy policy; - private volatile Class> languageClass; - private volatile List fileTypeDetectors; - - private LanguageCache(String id, String prefix, Properties info, ClassLoader loader, String url) { - this.loader = loader; - this.className = info.getProperty(prefix + "className"); - this.name = info.getProperty(prefix + "name"); - this.implementationName = info.getProperty(prefix + "implementationName"); - this.version = info.getProperty(prefix + "version"); - TreeSet characterMimes = parseList(info, prefix + "characterMimeType"); - if (characterMimes.isEmpty()) { - characterMimes = parseList(info, prefix + "mimeType"); - } - this.characterMimeTypes = characterMimes; - this.byteMimeTypes = parseList(info, prefix + "byteMimeType"); + + private LanguageCache(String id, String name, String implementationName, String version, String className, + String languageHome, Set characterMimeTypes, Set byteMimeTypes, String defaultMimeType, + Set dependentLanguages, boolean interactive, boolean internal, Set services, + LanguageReflection languageReflection) { + this.languageReflection = languageReflection; + this.className = className; + this.name = name; + this.implementationName = implementationName; + this.version = version; + this.characterMimeTypes = characterMimeTypes; this.mimeTypes = new TreeSet<>(); - this.mimeTypes.addAll(characterMimes); + this.mimeTypes.addAll(characterMimeTypes); this.mimeTypes.addAll(byteMimeTypes); - - String defaultMime = info.getProperty(prefix + "defaultMimeType"); - if (mimeTypes.size() == 1 && defaultMime == null) { - this.defaultMimeType = mimeTypes.iterator().next(); - } else { - this.defaultMimeType = defaultMime; - } - - this.dependentLanguages = parseList(info, prefix + "dependentLanguage"); + this.defaultMimeType = mimeTypes.size() == 1 && defaultMimeType == null ? mimeTypes.iterator().next() : defaultMimeType; + this.dependentLanguages = dependentLanguages; this.id = id; - this.interactive = Boolean.valueOf(info.getProperty(prefix + "interactive")); - this.internal = Boolean.valueOf(info.getProperty(prefix + "internal")); - this.languageHome = url; - - Set servicesClassNames = new TreeSet<>(); - for (int servicesCounter = 0;; servicesCounter++) { - String nth = prefix + "service" + servicesCounter; - String serviceName = info.getProperty(nth); - if (serviceName == null) { - break; - } - servicesClassNames.add(serviceName); - } - this.services = Collections.unmodifiableSet(servicesClassNames); - - List detectorClassNames = new ArrayList<>(); - for (int fileTypeDetectorCounter = 0;; fileTypeDetectorCounter++) { - String nth = prefix + "fileTypeDetector" + fileTypeDetectorCounter; - String fileTypeDetectorClassName = info.getProperty(nth); - if (fileTypeDetectorClassName == null) { - break; - } - detectorClassNames.add(fileTypeDetectorClassName); - } - this.fileTypeDetectorClassNames = Collections.unmodifiableList(detectorClassNames); + this.interactive = interactive; + this.internal = internal; + this.languageHome = languageHome; + this.services = services; if (TruffleOptions.AOT) { - initializeLanguageClass(); - initializeFileTypeDetectors(); - assert languageClass != null; - assert policy != null; + languageReflection.aotInitializeAtBuildTime(); } this.globalInstance = null; } - private static TreeSet parseList(Properties info, String prefix) { - TreeSet mimeTypesSet = new TreeSet<>(); - for (int i = 0;; i++) { - String mt = info.getProperty(prefix + "." + i); - if (mt == null) { - break; - } - mimeTypesSet.add(mt); - } - return mimeTypesSet; - } - - @SuppressWarnings("unchecked") - LanguageCache(String id, String name, String implementationName, String version, boolean interactive, boolean internal, - TruffleLanguage instance, String... services) { - this.id = id; - this.className = instance.getClass().getName(); - this.mimeTypes = Collections.emptySet(); - this.characterMimeTypes = Collections.emptySet(); - this.byteMimeTypes = Collections.emptySet(); - this.defaultMimeType = null; - this.implementationName = implementationName; - this.name = name; - this.version = version; - this.interactive = interactive; - this.internal = internal; - this.dependentLanguages = Collections.emptySet(); - this.loader = instance.getClass().getClassLoader(); - this.languageClass = (Class>) instance.getClass(); - this.languageHome = null; - this.policy = ContextPolicy.SHARED; - this.globalInstance = instance; + static LanguageCache createHostLanguageCache(String... services) { + TruffleLanguage languageInstance = new HostLanguage(); + Set servicesClassNames; if (services.length == 0) { - this.services = Collections.emptySet(); + servicesClassNames = Collections.emptySet(); } else { - Set servicesClassNames = new TreeSet<>(); + servicesClassNames = new TreeSet<>(); Collections.addAll(servicesClassNames, services); - this.services = Collections.unmodifiableSet(servicesClassNames); - } - this.fileTypeDetectorClassNames = Collections.emptyList(); + servicesClassNames = Collections.unmodifiableSet(servicesClassNames); + } + return new LanguageCache( + PolyglotEngineImpl.HOST_LANGUAGE_ID, + "Host", + "Host", + System.getProperty("java.version"), + languageInstance.getClass().getName(), + null, + Collections.emptySet(), + Collections.emptySet(), + null, + Collections.emptySet(), + false, false, servicesClassNames, LanguageReflection.forLanguageInstance(new HostLanguage(), ContextPolicy.SHARED)); } static Map languageMimes() { @@ -245,15 +194,15 @@ static Map languages(ClassLoader additionalLoader) { private static Map createLanguages(ClassLoader additionalLoader) { List caches = new ArrayList<>(); for (ClassLoader loader : EngineAccessor.allLoaders()) { - collectLanguages(loader, caches); + Loader.load(loader, caches); } if (additionalLoader != null) { - collectLanguages(additionalLoader, caches); + Loader.load(additionalLoader, caches); } Map cacheToId = new HashMap<>(); for (LanguageCache languageCache : caches) { LanguageCache prev = cacheToId.put(languageCache.getId(), languageCache); - if (prev != null && (!prev.getClassName().equals(languageCache.getClassName()) || loadUninitialized(prev) != loadUninitialized(languageCache))) { + if (prev != null && (!prev.getClassName().equals(languageCache.getClassName()) || !prev.languageReflection.hasSameCodeSource(languageCache.languageReflection))) { String message = String.format("Duplicate language id %s. First language [%s]. Second language [%s].", languageCache.getId(), formatLanguageLocation(prev), @@ -264,111 +213,16 @@ private static Map createLanguages(ClassLoader additional return cacheToId; } - @SuppressWarnings("unchecked") - private static Class> loadUninitialized(LanguageCache cache) { - try { - return (Class>) Class.forName(cache.getClassName(), false, cache.loader); - } catch (ClassNotFoundException e) { - throw new IllegalStateException("Cannot load language " + cache.getName() + ". Language implementation class " + cache.getClassName() + " failed to load.", e); - } - } - private static String formatLanguageLocation(LanguageCache languageCache) { StringBuilder sb = new StringBuilder(); sb.append("Language class ").append(languageCache.getClassName()); - CodeSource source = languageCache.getLanguageClass().getProtectionDomain().getCodeSource(); - if (source != null) { - sb.append(", Loaded from " + source.getLocation()); + URL url = languageCache.languageReflection.getCodeSource(); + if (url != null) { + sb.append(", Loaded from " + url); } return sb.toString(); } - private static void collectLanguages(ClassLoader loader, List list) { - if (loader == null) { - return; - } - try { - Class truffleLanguageClassAsSeenByLoader = Class.forName(TruffleLanguage.class.getName(), true, loader); - if (truffleLanguageClassAsSeenByLoader != TruffleLanguage.class) { - return; - } - } catch (ClassNotFoundException ex) { - return; - } - - Enumeration en; - try { - en = loader.getResources("META-INF/truffle/language"); - } catch (IOException ex) { - throw new IllegalStateException("Cannot read list of Truffle languages", ex); - } - while (en.hasMoreElements()) { - URL u = en.nextElement(); - Properties p; - URLConnection connection; - try { - p = new Properties(); - connection = u.openConnection(); - /* Ensure truffle language jar-files are not getting cached. See GR-12018 */ - connection.setUseCaches(false); - try (InputStream is = connection.getInputStream()) { - p.load(is); - } - } catch (IOException ex) { - PrintStream out = System.err; - out.println("Cannot process " + u + " as language definition"); - ex.printStackTrace(); - continue; - } - for (int cnt = 1;; cnt++) { - String prefix = "language" + cnt + "."; - String name = p.getProperty(prefix + "name"); - if (name == null) { - break; - } - String id = p.getProperty(prefix + "id"); - if (id == null) { - id = defaultId(name, p.getProperty(prefix + "className")); - } - String languageHome = System.getProperty(id + ".home"); - if (languageHome == null && connection instanceof JarURLConnection) { - - /* - * The previous implementation used a `URL.getPath()`, but OS Windows is - * offended by leading slash and maybe other irrelevant characters. Therefore, - * for JDK 1.7+ a preferred way to go is URL -> URI -> Path. - * - * Also, Paths are more strict than Files and URLs, so we can't create an - * invalid Path from a random string like "/C:/". This leads us to the - * `URISyntaxException` for URL -> URI conversion and - * `java.nio.file.InvalidPathException` for URI -> Path conversion. - * - * For fixing further bugs at this point, please read - * http://tools.ietf.org/html/rfc1738 http://tools.ietf.org/html/rfc2396 - * (supersedes rfc1738) http://tools.ietf.org/html/rfc3986 (supersedes rfc2396) - * - * http://url.spec.whatwg.org/ does not contain URI interpretation. When you - * call `URI.toASCIIString()` all reserved and non-ASCII characters are - * percent-quoted. - */ - try { - Path path; - path = Paths.get(((JarURLConnection) connection).getJarFileURL().toURI()); - Path parent = path.getParent(); - if (parent == null) { - languageHome = null; - } else { - languageHome = parent.toString(); - } - } catch (URISyntaxException e) { - assert false : "Could not resolve path."; - } - } - list.add(new LanguageCache(id, prefix, p, loader, languageHome)); - } - } - } - private static String defaultId(final String name, final String className) { String resolvedId; if (name.isEmpty()) { @@ -451,25 +305,15 @@ TruffleLanguage loadLanguage() { if (globalInstance != null) { return globalInstance; } - TruffleLanguage instance; - try { - instance = getLanguageClass().getDeclaredConstructor().newInstance(); - } catch (Exception e) { - throw new IllegalStateException("Cannot create instance of " + name + " language implementation. Public default constructor expected in " + className + ".", e); - } - return instance; + return languageReflection.newInstance(); } - Class> getLanguageClass() { - if (!TruffleOptions.AOT) { - initializeLanguageClass(); - } - return this.languageClass; + Set> getProvidedTags() { + return languageReflection.getProvidedTags(); } ContextPolicy getPolicy() { - initializeLanguageClass(); - return policy; + return languageReflection.getContextPolicy(); } Collection getServices() { @@ -481,65 +325,7 @@ boolean supportsService(Class clazz) { } List getFileTypeDetectors() { - initializeFileTypeDetectors(); - return fileTypeDetectors; - } - - private void exportTruffle() { - if (!TruffleOptions.AOT) { - /* - * In JDK 9+, the Truffle API packages must be dynamically exported to a Truffle - * language since the Truffle API module descriptor only exports the packages to modules - * known at build time (such as the Graal module). - */ - TruffleJDKServices.exportTo(loader, null); - } - } - - @SuppressWarnings("unchecked") - private void initializeLanguageClass() { - if (languageClass == null) { - synchronized (this) { - if (languageClass == null) { - try { - exportTruffle(); - - Class loadedClass = Class.forName(className, true, loader); - Registration reg = loadedClass.getAnnotation(Registration.class); - if (reg == null) { - policy = ContextPolicy.EXCLUSIVE; - } else { - policy = loadedClass.getAnnotation(Registration.class).contextPolicy(); - } - languageClass = (Class>) loadedClass; - } catch (ClassNotFoundException e) { - throw new IllegalStateException("Cannot load language " + name + ". Language implementation class " + className + " failed to load.", e); - } - } - } - } - } - - private void initializeFileTypeDetectors() { - if (fileTypeDetectors == null) { - synchronized (this) { - if (fileTypeDetectors == null) { - exportTruffle(); - - List instances = new ArrayList<>(fileTypeDetectorClassNames.size()); - for (String fileTypeDetectorClassName : fileTypeDetectorClassNames) { - try { - Class detectorClass = Class.forName(fileTypeDetectorClassName, true, loader).asSubclass(FileTypeDetector.class); - FileTypeDetector instance = detectorClass.getDeclaredConstructor().newInstance(); - instances.add(instance); - } catch (ReflectiveOperationException e) { - throw new IllegalStateException("Cannot instantiate FileTypeDetector, class " + fileTypeDetectorClassName + ".", e); - } - } - fileTypeDetectors = Collections.unmodifiableList(instances); - } - } - } + return languageReflection.getFileTypeDetectors(); } @Override @@ -612,10 +398,410 @@ private static Collection> getLanguageClasses() { assert TruffleOptions.AOT : "Only supported during image generation"; ArrayList> list = new ArrayList<>(); for (LanguageCache cache : nativeImageCache.values()) { - assert cache.languageClass != null; - list.add(cache.languageClass); + Class> clz = cache.languageReflection.aotInitializeAtBuildTime(); + assert clz != null; + list.add(clz); } return list; } + private abstract static class LanguageReflection { + + abstract TruffleLanguage newInstance(); + + abstract List getFileTypeDetectors(); + + abstract TruffleLanguage.ContextPolicy getContextPolicy(); + + abstract Set> getProvidedTags(); + + abstract Class> aotInitializeAtBuildTime(); + + abstract boolean hasSameCodeSource(LanguageReflection other); + + abstract URL getCodeSource(); + + static void exportTruffle(ClassLoader loader) { + if (!TruffleOptions.AOT) { + /* + * In JDK 9+, the Truffle API packages must be dynamically exported to a Truffle + * language since the Truffle API module descriptor only exports the packages to + * modules known at build time (such as the Graal module). + */ + TruffleJDKServices.exportTo(loader, null); + } + } + + static LanguageReflection forLanguageInstance(TruffleLanguage language, ContextPolicy contextPolycy, FileTypeDetector... fileTypeDetectors) { + return new LanguageInstanceReflection(language, contextPolycy, fileTypeDetectors); + } + + private static final class LanguageInstanceReflection extends LanguageReflection { + + private final TruffleLanguage languageInstance; + private final ContextPolicy contextPolycy; + private final List fileTypeDetectors; + + LanguageInstanceReflection(TruffleLanguage languageInstance, ContextPolicy contextPolycy, FileTypeDetector... detectors) { + assert languageInstance != null; + assert contextPolycy != null; + this.languageInstance = languageInstance; + this.contextPolycy = contextPolycy; + if (detectors.length == 0) { + fileTypeDetectors = Collections.emptyList(); + } else { + fileTypeDetectors = Arrays.asList(detectors); + } + } + + @Override + TruffleLanguage newInstance() { + return languageInstance; + } + + @Override + List getFileTypeDetectors() { + return fileTypeDetectors; + } + + @Override + ContextPolicy getContextPolicy() { + return contextPolycy; + } + + @Override + Set> getProvidedTags() { + return Collections.emptySet(); + } + + @Override + @SuppressWarnings("unchecked") + Class> aotInitializeAtBuildTime() { + return (Class>) languageInstance.getClass(); + } + + @Override + boolean hasSameCodeSource(LanguageReflection other) { + throw new UnsupportedOperationException("Should not reach here."); + } + + @Override + URL getCodeSource() { + throw new UnsupportedOperationException("Should not reach here."); + } + } + } + + private abstract static class Loader { + + private static final Loader[] LOADERS = { + new LegacyLoader(), + new ServicesLoader() + }; + + static void load(ClassLoader loader, Collection into) { + if (loader == null) { + return; + } + try { + Class truffleLanguageClassAsSeenByLoader = Class.forName(TruffleLanguage.class.getName(), true, loader); + if (truffleLanguageClassAsSeenByLoader != TruffleLanguage.class) { + return; + } + } catch (ClassNotFoundException ex) { + return; + } + for (Loader loaderImpl : LOADERS) { + loaderImpl.loadImpl(loader, into); + } + } + + abstract void loadImpl(ClassLoader loader, Collection into); + + private static final class LegacyLoader extends Loader { + + LegacyLoader() { + } + + @Override + public void loadImpl(ClassLoader loader, Collection into) { + Enumeration en; + try { + en = loader.getResources("META-INF/truffle/language"); + } catch (IOException ex) { + throw new IllegalStateException("Cannot read list of Truffle languages", ex); + } + while (en.hasMoreElements()) { + URL u = en.nextElement(); + Properties p; + URLConnection connection; + try { + p = new Properties(); + connection = u.openConnection(); + /* Ensure truffle language jar-files are not getting cached. See GR-12018 */ + connection.setUseCaches(false); + try (InputStream is = connection.getInputStream()) { + p.load(is); + } + } catch (IOException ex) { + PrintStream out = System.err; + out.println("Cannot process " + u + " as language definition"); + ex.printStackTrace(); + continue; + } + for (int cnt = 1;; cnt++) { + String prefix = "language" + cnt + "."; + String name = p.getProperty(prefix + "name"); + if (name == null) { + break; + } + into.add(createLanguageCache(name, prefix, p, loader, connection)); + } + } + } + + private static LanguageCache createLanguageCache(String name, String prefix, Properties info, ClassLoader loader, URLConnection connection) { + String id = info.getProperty(prefix + "id"); + if (id == null) { + id = defaultId(name, info.getProperty(prefix + "className")); + } + String languageHome = System.getProperty(id + ".home"); + if (languageHome == null) { + languageHome = getLanguageHomeFromURLConnection(connection); + } + String className = info.getProperty(prefix + "className"); + String implementationName = info.getProperty(prefix + "implementationName"); + String version = info.getProperty(prefix + "version"); + TreeSet characterMimes = parseList(info, prefix + "characterMimeType"); + if (characterMimes.isEmpty()) { + characterMimes = parseList(info, prefix + "mimeType"); + } + TreeSet byteMimeTypes = parseList(info, prefix + "byteMimeType"); + String defaultMime = info.getProperty(prefix + "defaultMimeType"); + TreeSet dependentLanguages = parseList(info, prefix + "dependentLanguage"); + boolean interactive = Boolean.valueOf(info.getProperty(prefix + "interactive")); + boolean internal = Boolean.valueOf(info.getProperty(prefix + "internal")); + Set servicesClassNames = new TreeSet<>(); + for (int servicesCounter = 0;; servicesCounter++) { + String nth = prefix + "service" + servicesCounter; + String serviceName = info.getProperty(nth); + if (serviceName == null) { + break; + } + servicesClassNames.add(serviceName); + } + List detectorClassNames = new ArrayList<>(); + for (int fileTypeDetectorCounter = 0;; fileTypeDetectorCounter++) { + String nth = prefix + "fileTypeDetector" + fileTypeDetectorCounter; + String fileTypeDetectorClassName = info.getProperty(nth); + if (fileTypeDetectorClassName == null) { + break; + } + detectorClassNames.add(fileTypeDetectorClassName); + } + LegacyLanguageReflection reflection = new LegacyLanguageReflection(name, loader, className, detectorClassNames); + return new LanguageCache(id, name, implementationName, version, className, languageHome, + characterMimes, byteMimeTypes, defaultMime, dependentLanguages, + interactive, internal, servicesClassNames, reflection); + } + + private static TreeSet parseList(Properties info, String prefix) { + TreeSet mimeTypesSet = new TreeSet<>(); + for (int i = 0;; i++) { + String mt = info.getProperty(prefix + "." + i); + if (mt == null) { + break; + } + mimeTypesSet.add(mt); + } + return mimeTypesSet; + } + + private static String getLanguageHomeFromURLConnection(URLConnection connection) { + if (connection instanceof JarURLConnection) { + /* + * The previous implementation used a `URL.getPath()`, but OS Windows is + * offended by leading slash and maybe other irrelevant characters. Therefore, + * for JDK 1.7+ a preferred way to go is URL -> URI -> Path. + * + * Also, Paths are more strict than Files and URLs, so we can't create an + * invalid Path from a random string like "/C:/". This leads us to the + * `URISyntaxException` for URL -> URI conversion and + * `java.nio.file.InvalidPathException` for URI -> Path conversion. + * + * For fixing further bugs at this point, please read + * http://tools.ietf.org/html/rfc1738 http://tools.ietf.org/html/rfc2396 + * (supersedes rfc1738) http://tools.ietf.org/html/rfc3986 (supersedes rfc2396) + * + * http://url.spec.whatwg.org/ does not contain URI interpretation. When you + * call `URI.toASCIIString()` all reserved and non-ASCII characters are + * percent-quoted. + */ + try { + Path path; + path = Paths.get(((JarURLConnection) connection).getJarFileURL().toURI()); + Path parent = path.getParent(); + return parent != null ? parent.toString() : null; + } catch (URISyntaxException e) { + assert false : "Could not resolve path."; + } + } + return null; + } + + private static final class LegacyLanguageReflection extends LanguageReflection { + + private final String name; + private final ClassLoader loader; + private final String className; + private final List fileTypeDetectorClassNames; + private volatile Class> languageClass; + private volatile ContextPolicy policy; + private volatile List fileTypeDetectors; + + LegacyLanguageReflection(String name, ClassLoader loader, String className, List fileTypeDetectorClassNames) { + Objects.requireNonNull(name, "Name must be non null."); + Objects.requireNonNull(loader, "Loader must be non null."); + Objects.requireNonNull(className, "ClassName must be non null."); + Objects.requireNonNull(fileTypeDetectorClassNames, "FileTypeDetectorClassNames must be non null."); + this.name = name; + this.loader = loader; + this.className = className; + this.fileTypeDetectorClassNames = fileTypeDetectorClassNames; + } + + @Override + TruffleLanguage newInstance() { + TruffleLanguage instance; + try { + instance = getLanguageClass().getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new IllegalStateException("Cannot create instance of " + name + " language implementation. Public default constructor expected in " + className + ".", e); + } + return instance; + } + + @Override + List getFileTypeDetectors() { + initializeFileTypeDetectors(); + return fileTypeDetectors; + } + + @Override + ContextPolicy getContextPolicy() { + initializeLanguageClass(); + return policy; + } + + @Override + @SuppressWarnings("unchecked") + Set> getProvidedTags() { + initializeLanguageClass(); + ProvidedTags tags = languageClass.getAnnotation(ProvidedTags.class); + if (tags == null) { + return Collections.emptySet(); + } + Set> result = new HashSet<>(); + Collections.addAll(result, (Class[]) tags.value()); + return result; + } + + @Override + Class> aotInitializeAtBuildTime() { + initializeLanguageClass(); + initializeFileTypeDetectors(); + assert languageClass != null; + assert policy != null; + return languageClass; + } + + @Override + boolean hasSameCodeSource(LanguageReflection other) { + if (other instanceof LegacyLanguageReflection) { + return loadUnitialized() == ((LegacyLanguageReflection) other).loadUnitialized(); + } + return false; + } + + @Override + URL getCodeSource() { + CodeSource source = getLanguageClass().getProtectionDomain().getCodeSource(); + return source != null ? source.getLocation() : null; + } + + @SuppressWarnings("unchecked") + private Class> loadUnitialized() { + try { + return (Class>) Class.forName(className, false, loader); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Cannot load language " + name + ". Language implementation class " + className + " failed to load.", e); + } + } + + private Class> getLanguageClass() { + if (!TruffleOptions.AOT) { + initializeLanguageClass(); + } + return this.languageClass; + } + + @SuppressWarnings("unchecked") + private void initializeLanguageClass() { + if (languageClass == null) { + synchronized (this) { + if (languageClass == null) { + try { + exportTruffle(loader); + + Class loadedClass = Class.forName(className, true, loader); + Registration reg = loadedClass.getAnnotation(Registration.class); + if (reg == null) { + policy = ContextPolicy.EXCLUSIVE; + } else { + policy = loadedClass.getAnnotation(Registration.class).contextPolicy(); + } + languageClass = (Class>) loadedClass; + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Cannot load language " + name + ". Language implementation class " + className + " failed to load.", e); + } + } + } + } + } + + private void initializeFileTypeDetectors() { + if (fileTypeDetectors == null) { + synchronized (this) { + if (fileTypeDetectors == null) { + exportTruffle(loader); + + List instances = new ArrayList<>(fileTypeDetectorClassNames.size()); + for (String fileTypeDetectorClassName : fileTypeDetectorClassNames) { + try { + Class detectorClass = Class.forName(fileTypeDetectorClassName, true, loader).asSubclass(FileTypeDetector.class); + FileTypeDetector instance = detectorClass.getDeclaredConstructor().newInstance(); + instances.add(instance); + } catch (ReflectiveOperationException e) { + throw new IllegalStateException("Cannot instantiate FileTypeDetector, class " + fileTypeDetectorClassName + ".", e); + } + } + fileTypeDetectors = Collections.unmodifiableList(instances); + } + } + } + } + } + } + + private static final class ServicesLoader extends Loader { + + ServicesLoader() { + } + + @Override + public void loadImpl(ClassLoader loader, Collection into) { + } + } + } + } 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 4bf3d00e0c36..48a644ca848f 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 @@ -581,7 +581,7 @@ private Map initializeLanguages(Map Date: Thu, 26 Sep 2019 17:17:23 +0200 Subject: [PATCH 070/140] [GR-15292] LanguageCache for ServiceLoader loaded languages. --- .../oracle/truffle/api/TruffleLanguage.java | 9 + .../truffle/polyglot/LanguageCache.java | 233 +++++++++++++----- 2 files changed, 185 insertions(+), 57 deletions(-) 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 36a25c2b6634..1fa5ae285df6 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 @@ -77,6 +77,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.TruffleFile.FileTypeDetector; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; @@ -453,6 +454,14 @@ String[] dependentLanguages() default { Class[] fileTypeDetectors() default {}; } + public interface Provider { + String getLanguageClassName(); + + TruffleLanguage get(); + + List getFileTypeDetectors(); + } + /** * Returns true if the combination of two sets of options allow to * {@link ContextPolicy#SHARED share} or {@link ContextPolicy#REUSE reuse} the same language diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java index 5d33c990aad1..05b61740f349 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java @@ -51,14 +51,18 @@ import java.nio.file.Paths; import java.security.CodeSource; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Properties; +import java.util.ServiceLoader; import java.util.Set; import java.util.TreeSet; import java.util.WeakHashMap; @@ -71,9 +75,6 @@ import com.oracle.truffle.api.TruffleOptions; import com.oracle.truffle.api.instrumentation.ProvidedTags; import com.oracle.truffle.api.instrumentation.Tag; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Objects; /** * Ahead-of-time initialization. If the JVM is started with {@link TruffleOptions#AOT}, it populates @@ -223,25 +224,6 @@ private static String formatLanguageLocation(LanguageCache languageCache) { return sb.toString(); } - private static String defaultId(final String name, final String className) { - String resolvedId; - if (name.isEmpty()) { - int lastIndex = className.lastIndexOf('$'); - if (lastIndex == -1) { - lastIndex = className.lastIndexOf('.'); - } - resolvedId = className.substring(lastIndex + 1, className.length()); - } else { - // TODO remove this hack for single character languages - if (name.length() == 1) { - resolvedId = name; - } else { - resolvedId = name.toLowerCase(); - } - } - return resolvedId; - } - public int compareTo(LanguageCache o) { return id.compareTo(o.id); } @@ -399,8 +381,9 @@ private static Collection> getLanguageClasses() { ArrayList> list = new ArrayList<>(); for (LanguageCache cache : nativeImageCache.values()) { Class> clz = cache.languageReflection.aotInitializeAtBuildTime(); - assert clz != null; - list.add(clz); + if (clz != null) { + list.add(clz); + } } return list; } @@ -477,7 +460,7 @@ Set> getProvidedTags() { @Override @SuppressWarnings("unchecked") Class> aotInitializeAtBuildTime() { - return (Class>) languageInstance.getClass(); + return null; } @Override @@ -518,6 +501,56 @@ static void load(ClassLoader loader, Collection into) { abstract void loadImpl(ClassLoader loader, Collection into); + static String defaultId(final String name, final String className) { + String resolvedId; + if (name.isEmpty()) { + int lastIndex = className.lastIndexOf('$'); + if (lastIndex == -1) { + lastIndex = className.lastIndexOf('.'); + } + resolvedId = className.substring(lastIndex + 1, className.length()); + } else { + // TODO remove this hack for single character languages + if (name.length() == 1) { + resolvedId = name; + } else { + resolvedId = name.toLowerCase(); + } + } + return resolvedId; + } + + static String getLanguageHomeFromURLConnection(URLConnection connection) { + if (connection instanceof JarURLConnection) { + /* + * The previous implementation used a `URL.getPath()`, but OS Windows is offended by + * leading slash and maybe other irrelevant characters. Therefore, for JDK 1.7+ a + * preferred way to go is URL -> URI -> Path. + * + * Also, Paths are more strict than Files and URLs, so we can't create an invalid + * Path from a random string like "/C:/". This leads us to the `URISyntaxException` + * for URL -> URI conversion and `java.nio.file.InvalidPathException` for URI -> + * Path conversion. + * + * For fixing further bugs at this point, please read + * http://tools.ietf.org/html/rfc1738 http://tools.ietf.org/html/rfc2396 (supersedes + * rfc1738) http://tools.ietf.org/html/rfc3986 (supersedes rfc2396) + * + * http://url.spec.whatwg.org/ does not contain URI interpretation. When you call + * `URI.toASCIIString()` all reserved and non-ASCII characters are percent-quoted. + */ + try { + Path path; + path = Paths.get(((JarURLConnection) connection).getJarFileURL().toURI()); + Path parent = path.getParent(); + return parent != null ? parent.toString() : null; + } catch (URISyntaxException e) { + assert false : "Could not resolve path."; + } + } + return null; + } + private static final class LegacyLoader extends Loader { LegacyLoader() { @@ -617,38 +650,6 @@ private static TreeSet parseList(Properties info, String prefix) { return mimeTypesSet; } - private static String getLanguageHomeFromURLConnection(URLConnection connection) { - if (connection instanceof JarURLConnection) { - /* - * The previous implementation used a `URL.getPath()`, but OS Windows is - * offended by leading slash and maybe other irrelevant characters. Therefore, - * for JDK 1.7+ a preferred way to go is URL -> URI -> Path. - * - * Also, Paths are more strict than Files and URLs, so we can't create an - * invalid Path from a random string like "/C:/". This leads us to the - * `URISyntaxException` for URL -> URI conversion and - * `java.nio.file.InvalidPathException` for URI -> Path conversion. - * - * For fixing further bugs at this point, please read - * http://tools.ietf.org/html/rfc1738 http://tools.ietf.org/html/rfc2396 - * (supersedes rfc1738) http://tools.ietf.org/html/rfc3986 (supersedes rfc2396) - * - * http://url.spec.whatwg.org/ does not contain URI interpretation. When you - * call `URI.toASCIIString()` all reserved and non-ASCII characters are - * percent-quoted. - */ - try { - Path path; - path = Paths.get(((JarURLConnection) connection).getJarFileURL().toURI()); - Path parent = path.getParent(); - return parent != null ? parent.toString() : null; - } catch (URISyntaxException e) { - assert false : "Could not resolve path."; - } - } - return null; - } - private static final class LegacyLanguageReflection extends LanguageReflection { private final String name; @@ -800,6 +801,124 @@ private static final class ServicesLoader extends Loader { @Override public void loadImpl(ClassLoader loader, Collection into) { + for (TruffleLanguage.Provider provider : ServiceLoader.load(TruffleLanguage.Provider.class, loader)) { + Registration reg = provider.getClass().getAnnotation(Registration.class); + if (reg == null) { + PrintStream out = System.err; + out.println("Provider " + provider.getClass() + " is missing @Registration annotation."); + continue; + } + + String name = reg.name(); + String id = reg.id(); + if (id == null) { + id = defaultId(name, provider.getLanguageClassName()); + } + String className = provider.getLanguageClassName(); + String languageHome = System.getProperty(id + ".home"); + if (languageHome == null) { + URL url = provider.getClass().getClassLoader().getResource(className.replace('.', '/') + ".class"); + if (url != null) { + try { + languageHome = getLanguageHomeFromURLConnection(url.openConnection()); + } catch (IOException ioe) { + } + } + } + String implementationName = reg.implementationName(); + String version = reg.version(); + TreeSet characterMimes = new TreeSet<>(); + Collections.addAll(characterMimes, reg.characterMimeTypes()); + if (characterMimes.isEmpty()) { + Collections.addAll(characterMimes, getMimeTypesDepecated(reg)); + } + TreeSet byteMimeTypes = new TreeSet<>(); + Collections.addAll(byteMimeTypes, reg.byteMimeTypes()); + String defaultMime = reg.defaultMimeType(); + TreeSet dependentLanguages = new TreeSet<>(); + Collections.addAll(dependentLanguages, reg.dependentLanguages()); + boolean interactive = reg.interactive(); + boolean internal = reg.internal(); + Set servicesClassNames = new TreeSet<>(); + for (Class service : reg.services()) { + servicesClassNames.add(service.getCanonicalName()); + } + LanguageReflection reflection = new ServiceLoaderLanguageReflection(provider, reg.contextPolicy()); + into.add(new LanguageCache(id, name, implementationName, version, className, languageHome, + characterMimes, byteMimeTypes, defaultMime, dependentLanguages, interactive, internal, + servicesClassNames, reflection)); + } + } + + @SuppressWarnings("deprecation") + private static String[] getMimeTypesDepecated(Registration reg) { + return reg.mimeType(); + } + + private static final class ServiceLoaderLanguageReflection extends LanguageReflection { + + private final TruffleLanguage.Provider provider; + private final ContextPolicy contextPolicy; + private volatile Set> providedTags; + + ServiceLoaderLanguageReflection(TruffleLanguage.Provider provider, ContextPolicy contextPolicy) { + assert provider != null; + assert contextPolicy != null; + this.provider = provider; + this.contextPolicy = contextPolicy; + } + + @Override + TruffleLanguage newInstance() { + return provider.get(); + } + + @Override + List getFileTypeDetectors() { + return provider.getFileTypeDetectors(); + } + + @Override + ContextPolicy getContextPolicy() { + return contextPolicy; + } + + @Override + @SuppressWarnings("unchecked") + Set> getProvidedTags() { + Set> res = providedTags; + if (res == null) { + ProvidedTags tags = provider.getClass().getAnnotation(ProvidedTags.class); + if (tags == null) { + res = Collections.emptySet(); + } else { + res = new HashSet<>(); + Collections.addAll(res, (Class[]) tags.value()); + res = Collections.unmodifiableSet(res); + } + providedTags = res; + } + return res; + } + + @Override + Class> aotInitializeAtBuildTime() { + return null; + } + + @Override + boolean hasSameCodeSource(LanguageReflection other) { + if (other instanceof ServiceLoaderLanguageReflection) { + return provider.getClass() == ((ServiceLoaderLanguageReflection) other).provider.getClass(); + } + return false; + } + + @Override + URL getCodeSource() { + CodeSource source = providedTags.getClass().getProtectionDomain().getCodeSource(); + return source != null ? source.getLocation() : null; + } } } } From 5e9d0f045da1f15341f86a1516594c984557fcb8 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Mon, 30 Sep 2019 15:23:32 +0200 Subject: [PATCH 071/140] [GR-15292] Truffle DSL generates ServiceLoader registrations for TruffleLanguages. --- truffle/CHANGELOG.md | 1 + .../api/test/polyglot/LanguageCacheTest.java | 19 +- .../oracle/truffle/api/TruffleLanguage.java | 25 +++ .../LanguageRegistrationProcessor.java | 188 ++++++++++++------ .../truffle/polyglot/LanguageCache.java | 28 ++- 5 files changed, 185 insertions(+), 76 deletions(-) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 9d599b2f38cf..b6fa6c7070f6 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -16,6 +16,7 @@ This changelog summarizes major changes between Truffle versions relevant to lan * Deprecated `Shape#getPropertyList(Pred)`, `Shape#getKeyList(Pred)`, `Shape#hasTransitionWithKey(Object)`, `Shape.Allocator#locationForValue(Object, EnumSet)` without replacement. * Added [Scope.Builder#rootInstance(Object)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.Builder.html#rootInstance-java.lang.Object-), [Scope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.html#getRootInstance--) and [DebugScope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugScope.html#getRootInstance--) to provide an instance of guest language representation of the root node (e.g. a guest language function). * Debugger breakpoints can be restricted to a particular root instance via [Breakpoint.Builder#rootInstance(DebugValue)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/Breakpoint.Builder.html#rootInstance-com.oracle.truffle.api.debug.DebugValue-) and found later on via [DebugValue#getRootInstanceBreakpoints()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugValue.html#getRootInstanceBreakpoints--). +* `TruffleLanguage`s are registered in a `ServiceLoader` using the [TruffleLanguage.Provider](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.Provider.html) as a service interface. ## Version 19.2.0 * Added sub-process output (error output) [redirection into OutputStream](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/ProcessHandler.Redirect.html#stream-java.io.OutputStream-). diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageCacheTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageCacheTest.java index 1a153338598a..d3366c2a1b8f 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageCacheTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageCacheTest.java @@ -52,7 +52,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.junit.Assert; import org.junit.Test; @@ -105,13 +107,20 @@ protected boolean isObjectOfLanguage(Object object) { */ private static final class TestClassLoader extends ClassLoader { + private static final Set IMPORTANT_CLASSES; + static { + IMPORTANT_CLASSES = new HashSet<>(); + IMPORTANT_CLASSES.add(DuplicateIdLanguage.class.getName()); + IMPORTANT_CLASSES.add(LanguageCacheTestDuplicateIdLanguageProvider.class.getName()); + } + TestClassLoader() { super(TestClassLoader.class.getClassLoader()); } @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (!DuplicateIdLanguage.class.getName().equals(name)) { + if (!IMPORTANT_CLASSES.contains(name)) { return super.loadClass(name, resolve); } else { synchronized (getClassLoadingLock(name)) { @@ -129,16 +138,16 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE @Override protected Class findClass(String name) throws ClassNotFoundException { - if (!DuplicateIdLanguage.class.getName().equals(name)) { - throw new IllegalArgumentException("Only " + DuplicateIdLanguage.class + " can be loaded."); + if (!IMPORTANT_CLASSES.contains(name)) { + throw new IllegalArgumentException("Only " + String.join(", ", IMPORTANT_CLASSES) + " can be loaded."); } try { URL location = DuplicateIdLanguage.class.getProtectionDomain().getCodeSource().getLocation(); Path path = Paths.get(location.toURI()); if (Files.isRegularFile(path)) { - location = new URL("jar:" + location.toExternalForm() + "!/" + binaryName(DuplicateIdLanguage.class.getName()) + ".class"); + location = new URL("jar:" + location.toExternalForm() + "!/" + binaryName(name) + ".class"); } else { - location = new URL(location.toExternalForm() + binaryName(DuplicateIdLanguage.class.getName()) + ".class"); + location = new URL(location.toExternalForm() + binaryName(name) + ".class"); } try (InputStream in = location.openStream(); ByteArrayOutputStream out = new ByteArrayOutputStream()) { copy(in, out); 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 1fa5ae285df6..737dbd2f8aeb 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 @@ -91,6 +91,7 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; +import java.util.ServiceLoader; import org.graalvm.polyglot.EnvironmentAccess; /** @@ -454,11 +455,35 @@ String[] dependentLanguages() default { Class[] fileTypeDetectors() default {}; } + /** + * Used to register a {@link TruffleLanguage} using a {@link ServiceLoader}. This interface is + * not intended to be implemented directly by a language developer, rather the implementation is + * generated by the Truffle DSL. The generated implementation has to inherit the + * {@link Registration} and {@code ProvidedTags} annotations from the {@link TruffleLanguage}. + * + * @since 19.3.0 + */ public interface Provider { + + /** + * Returns the name of a class implementing the {@link TruffleLanguage}. + * + * @since 19.3.0 + */ String getLanguageClassName(); + /** + * Return a new instance of a {@link TruffleLanguage}. + * + * @since 19.3.0 + */ TruffleLanguage get(); + /** + * Returns file type detectors used by the {@link TruffleLanguage}. + * + * @since 19.3.0 + */ List getFileTypeDetectors(); } diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java index 852ec60652d1..253a25b01560 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java @@ -40,14 +40,20 @@ */ package com.oracle.truffle.dsl.processor; +import com.oracle.truffle.api.TruffleFile; import java.io.IOException; -import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; import java.util.Enumeration; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.ListIterator; +import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeSet; @@ -63,20 +69,33 @@ import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; +import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.Elements; import javax.tools.Diagnostic.Kind; import javax.tools.FileObject; import javax.tools.StandardLocation; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Registration; +import com.oracle.truffle.api.instrumentation.ProvidedTags; +import com.oracle.truffle.dsl.processor.generator.GeneratorUtils; import com.oracle.truffle.dsl.processor.java.ElementUtils; +import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; +import com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder; +import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; +import com.oracle.truffle.dsl.processor.java.transform.FixWarningsVisitor; +import com.oracle.truffle.dsl.processor.java.transform.GenerateOverrideVisitor; +import com.oracle.truffle.dsl.processor.model.Template; @SupportedAnnotationTypes("com.oracle.truffle.api.TruffleLanguage.Registration") public final class LanguageRegistrationProcessor extends AbstractProcessor { - private final List registrations = new ArrayList<>(); + private final Map registrations = new HashMap<>(); // also update list in PolyglotEngineImpl#RESERVED_IDS private static final Set RESERVED_IDS = new HashSet<>( @@ -88,71 +107,103 @@ public SourceVersion getSupportedSourceVersion() { return SourceVersion.latest(); } - @SuppressWarnings("deprecation") - private void generateFile(List languages) { - String filename = "META-INF/truffle/language"; - // sorted properties - Properties p = new SortedProperties(); - int cnt = 0; - for (TypeElement l : languages) { - Registration annotation = l.getAnnotation(Registration.class); - if (annotation == null) { - continue; - } - String prefix = "language" + ++cnt + "."; - String className = processingEnv.getElementUtils().getBinaryName(l).toString(); - String id = annotation.id(); - if (id != null && !id.isEmpty()) { - p.setProperty(prefix + "id", id); - } - p.setProperty(prefix + "name", annotation.name()); - p.setProperty(prefix + "implementationName", annotation.implementationName()); - p.setProperty(prefix + "version", annotation.version()); - p.setProperty(prefix + "className", className); + private static String generateProvider(TypeElement language) { + ProcessorContext context = ProcessorContext.getInstance(); + Elements elements = context.getEnvironment().getElementUtils(); + Template languageModel = new Template(context, language, null) { + }; + TypeElement providerElement = context.getTypeElement(TruffleLanguage.Provider.class); + CodeTypeElement providerClass = GeneratorUtils.createClass(languageModel, null, EnumSet.of(Modifier.PUBLIC), + createProviderSimpleName(language), null); + providerClass.getImplements().add(providerElement.asType()); + AnnotationMirror registration = ElementUtils.findAnnotationMirror(language.getAnnotationMirrors(), ProcessorContext.getInstance().getType(Registration.class)); + for (Element method : ElementFilter.methodsIn(providerElement.getEnclosedElements())) { + CodeExecutableElement implementedMethod = CodeExecutableElement.clone((ExecutableElement) method); + implementedMethod.getModifiers().remove(Modifier.ABSTRACT); + CodeTreeBuilder builder = implementedMethod.createBuilder(); + switch (method.getSimpleName().toString()) { + case "get": + DeclaredType languageType = (DeclaredType) language.asType(); + List typeParams = language.getTypeParameters(); + if (!typeParams.isEmpty()) { + TypeMirror[] actualTypeParams = new TypeMirror[typeParams.size()]; + for (int i = 0; i < actualTypeParams.length; i++) { + actualTypeParams[i] = typeParams.get(i).getBounds().get(0); + } + languageType = context.getEnvironment().getTypeUtils().getDeclaredType(language, actualTypeParams); + } + builder.startReturn().startNew(languageType).end().end(); + break; - if (!annotation.defaultMimeType().equals("")) { - p.setProperty(prefix + "defaultMimeType", annotation.defaultMimeType()); + case "getFileTypeDetectors": + List detectors = ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "fileTypeDetectors"); + if (detectors.isEmpty()) { + builder.startReturn().startStaticCall(context.getType(Collections.class), "emptyList").end().end(); + } else { + String varName = "result"; + DeclaredType listOfDetectors = context.getEnvironment().getTypeUtils().getDeclaredType(context.getTypeElement(ArrayList.class), + context.getType(TruffleFile.FileTypeDetector.class)); + builder.declaration(listOfDetectors, varName, builder.create().startNew(listOfDetectors).end()); + for (TypeMirror detector : detectors) { + builder.startStatement().startCall(varName, "add").startNew(detector).end(3); + } + builder.startReturn().string(varName).end(); + } + break; + case "getLanguageClassName": + builder.startReturn().doubleQuote(elements.getBinaryName(language).toString()).end(); + break; + default: + throw new IllegalStateException("Unsupported method: " + method.getSimpleName()); } + providerClass.add(implementedMethod); + } - String[] mimes = annotation.mimeType(); - for (int i = 0; i < mimes.length; i++) { - p.setProperty(prefix + "mimeType." + i, mimes[i]); - } - String[] charMimes = annotation.characterMimeTypes(); - Arrays.sort(charMimes); - for (int i = 0; i < charMimes.length; i++) { - p.setProperty(prefix + "characterMimeType." + i, charMimes[i]); - } - String[] byteMimes = annotation.byteMimeTypes(); - Arrays.sort(byteMimes); - for (int i = 0; i < byteMimes.length; i++) { - p.setProperty(prefix + "byteMimeType." + i, byteMimes[i]); - } + providerClass.addAnnotationMirror(registration); + AnnotationMirror providedTags = ElementUtils.findAnnotationMirror(language.getAnnotationMirrors(), ProcessorContext.getInstance().getType(ProvidedTags.class)); + if (providedTags != null) { + providerClass.addAnnotationMirror(providedTags); + } + DeclaredType overrideType = (DeclaredType) context.getType(Override.class); + providerClass.accept(new GenerateOverrideVisitor(overrideType), null); + providerClass.accept(new FixWarningsVisitor(language, overrideType), null); + providerClass.accept(new CodeWriter(context.getEnvironment(), language), null); + return providerClass.getQualifiedName().toString(); + } - String[] dependencies = annotation.dependentLanguages(); - Arrays.sort(dependencies); - for (int i = 0; i < dependencies.length; i++) { - p.setProperty(prefix + "dependentLanguage." + i, dependencies[i]); + private static String createProviderSimpleName(TypeElement language) { + StringBuilder nameBuilder = new StringBuilder(); + List hierarchy = ElementUtils.getElementHierarchy(language); + for (ListIterator it = hierarchy.listIterator(hierarchy.size()); it.hasPrevious();) { + Element enc = it.previous(); + if (enc.getKind().isClass() || enc.getKind().isInterface()) { + nameBuilder.append(enc.getSimpleName()); } - p.setProperty(prefix + "interactive", Boolean.toString(annotation.interactive())); - p.setProperty(prefix + "internal", Boolean.toString(annotation.internal())); + } + nameBuilder.append("Provider"); + return nameBuilder.toString(); + } - AnnotationMirror registration = ElementUtils.findAnnotationMirror(l.getAnnotationMirrors(), ProcessorContext.getInstance().getType(Registration.class)); - int serviceCounter = 0; - for (TypeMirror serviceTypeMirror : ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "services")) { - p.setProperty(prefix + "service" + serviceCounter++, processingEnv.getElementUtils().getBinaryName(ElementUtils.fromTypeMirror(serviceTypeMirror)).toString()); - } - int fileTypeDetectorCounter = 0; - for (TypeMirror fileTypeDetectorTypeMirror : ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "fileTypeDetectors")) { - p.setProperty(prefix + "fileTypeDetector" + fileTypeDetectorCounter++, - processingEnv.getElementUtils().getBinaryName(ElementUtils.fromTypeMirror(fileTypeDetectorTypeMirror)).toString()); - } + private static void generateServicesRegistration(Map providerFqns) { + ProcessorContext context = ProcessorContext.getInstance(); + ProcessingEnvironment env = context.getEnvironment(); + Elements elements = env.getElementUtils(); + Name providerBinName = elements.getBinaryName(context.getTypeElement(TruffleLanguage.Provider.class)); + String filename = "META-INF/services/" + providerBinName; + List providerClassNames = new ArrayList<>(providerFqns.size()); + for (String providerFqn : providerFqns.keySet()) { + TypeElement te = ElementUtils.getTypeElement(env, providerFqn); + providerClassNames.add(elements.getBinaryName(te).toString()); } - if (cnt > 0) { + Collections.sort(providerClassNames); + if (!providerClassNames.isEmpty()) { try { - FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, languages.toArray(new Element[0])); - try (OutputStream os = file.openOutputStream()) { - p.store(os, "Generated by " + LanguageRegistrationProcessor.class.getName()); + FileObject file = env.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, providerFqns.values().toArray(new Element[providerFqns.size()])); + try (PrintWriter out = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"))) { + out.println("# Generated by " + LanguageRegistrationProcessor.class.getName()); + for (String providerClassName : providerClassNames) { + out.println(providerClassName); + } } } catch (IOException e) { if (e instanceof FilerException) { @@ -161,7 +212,7 @@ private void generateFile(List languages) { return; } } - processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), languages.get(0)); + env.getMessager().printMessage(Kind.ERROR, e.getMessage(), providerFqns.values().iterator().next()); } } } @@ -172,7 +223,7 @@ public boolean process(Set annotations, RoundEnvironment ProcessorContext.setThreadLocalInstance(new ProcessorContext(processingEnv, null)); try { if (roundEnv.processingOver()) { - generateFile(registrations); + generateServicesRegistration(registrations); registrations.clear(); return true; } @@ -191,7 +242,13 @@ public boolean process(Set annotations, RoundEnvironment continue; } TypeMirror truffleLang = processingEnv.getTypeUtils().erasure(ElementUtils.getTypeElement(processingEnv, TruffleLanguage.class.getName()).asType()); - if (!processingEnv.getTypeUtils().isAssignable(e.asType(), truffleLang)) { + TypeMirror truffleLangProvider = ProcessorContext.getInstance().getType(TruffleLanguage.Provider.class); + boolean processingTruffleLanguage; + if (processingEnv.getTypeUtils().isAssignable(e.asType(), truffleLang)) { + processingTruffleLanguage = true; + } else if (processingEnv.getTypeUtils().isAssignable(e.asType(), truffleLangProvider)) { + processingTruffleLanguage = false; + } else { emitError("Registered language class must subclass TruffleLanguage", e); continue; } @@ -228,7 +285,7 @@ public boolean process(Set annotations, RoundEnvironment } boolean valid = true; - if (singletonElement != null) { + if (processingTruffleLanguage && singletonElement != null) { emitWarning("Using a singleton field is deprecated. Please provide a public no-argument constructor instead.", singletonElement); valid = false; } else { @@ -280,7 +337,10 @@ public boolean process(Set annotations, RoundEnvironment if (valid) { assertNoErrorExpected(e); } - registrations.add((TypeElement) e); + if (processingTruffleLanguage) { + TypeElement languageTypeElement = (TypeElement) e; + registrations.put(generateProvider(languageTypeElement), languageTypeElement); + } } } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java index 05b61740f349..da47ef6f66c5 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java @@ -75,6 +75,7 @@ import com.oracle.truffle.api.TruffleOptions; import com.oracle.truffle.api.instrumentation.ProvidedTags; import com.oracle.truffle.api.instrumentation.Tag; +import java.util.concurrent.atomic.AtomicBoolean; /** * Ahead-of-time initialization. If the JVM is started with {@link TruffleOptions#AOT}, it populates @@ -96,7 +97,6 @@ final class LanguageCache implements Comparable { private final String version; private final boolean interactive; private final boolean internal; - private final TruffleLanguage globalInstance; private final Set services; private final LanguageReflection languageReflection; private String languageHome; @@ -125,7 +125,6 @@ private LanguageCache(String id, String name, String implementationName, String if (TruffleOptions.AOT) { languageReflection.aotInitializeAtBuildTime(); } - this.globalInstance = null; } static LanguageCache createHostLanguageCache(String... services) { @@ -284,9 +283,6 @@ String getLanguageHome() { } TruffleLanguage loadLanguage() { - if (globalInstance != null) { - return globalInstance; - } return languageReflection.newInstance(); } @@ -835,6 +831,9 @@ public void loadImpl(ClassLoader loader, Collection into) TreeSet byteMimeTypes = new TreeSet<>(); Collections.addAll(byteMimeTypes, reg.byteMimeTypes()); String defaultMime = reg.defaultMimeType(); + if (defaultMime.isEmpty()) { + defaultMime = null; + } TreeSet dependentLanguages = new TreeSet<>(); Collections.addAll(dependentLanguages, reg.dependentLanguages()); boolean interactive = reg.interactive(); @@ -859,7 +858,9 @@ private static final class ServiceLoaderLanguageReflection extends LanguageRefle private final TruffleLanguage.Provider provider; private final ContextPolicy contextPolicy; + private final AtomicBoolean exported = new AtomicBoolean(); private volatile Set> providedTags; + private volatile List fileTypeDetectors; ServiceLoaderLanguageReflection(TruffleLanguage.Provider provider, ContextPolicy contextPolicy) { assert provider != null; @@ -870,12 +871,19 @@ private static final class ServiceLoaderLanguageReflection extends LanguageRefle @Override TruffleLanguage newInstance() { + exportTruffleIfNeeded(); return provider.get(); } @Override List getFileTypeDetectors() { - return provider.getFileTypeDetectors(); + List result = fileTypeDetectors; + if (result == null) { + exportTruffleIfNeeded(); + result = provider.getFileTypeDetectors(); + fileTypeDetectors = result; + } + return result; } @Override @@ -916,9 +924,15 @@ boolean hasSameCodeSource(LanguageReflection other) { @Override URL getCodeSource() { - CodeSource source = providedTags.getClass().getProtectionDomain().getCodeSource(); + CodeSource source = provider.getClass().getProtectionDomain().getCodeSource(); return source != null ? source.getLocation() : null; } + + private void exportTruffleIfNeeded() { + if (exported.compareAndSet(false, true)) { + exportTruffle(provider.getClass().getClassLoader()); + } + } } } } From 01783878e8daf7a836b593f17707897ebe32ae89 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Mon, 30 Sep 2019 18:35:01 +0200 Subject: [PATCH 072/140] [GR-15292] Renamed TruffleLanguage.Provider methods. --- .../src/com/oracle/truffle/api/TruffleLanguage.java | 8 ++++---- .../dsl/processor/LanguageRegistrationProcessor.java | 4 ++-- .../src/com/oracle/truffle/polyglot/LanguageCache.java | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) 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 737dbd2f8aeb..6afc5a401d1f 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 @@ -473,18 +473,18 @@ public interface Provider { String getLanguageClassName(); /** - * Return a new instance of a {@link TruffleLanguage}. + * Creates a new instance of a {@link TruffleLanguage}. * * @since 19.3.0 */ - TruffleLanguage get(); + TruffleLanguage create(); /** - * Returns file type detectors used by the {@link TruffleLanguage}. + * Creates file type detectors used by the {@link TruffleLanguage}. * * @since 19.3.0 */ - List getFileTypeDetectors(); + List createFileTypeDetectors(); } /** diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java index 253a25b01560..0d25d7ca4f0c 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java @@ -122,7 +122,7 @@ private static String generateProvider(TypeElement language) { implementedMethod.getModifiers().remove(Modifier.ABSTRACT); CodeTreeBuilder builder = implementedMethod.createBuilder(); switch (method.getSimpleName().toString()) { - case "get": + case "create": DeclaredType languageType = (DeclaredType) language.asType(); List typeParams = language.getTypeParameters(); if (!typeParams.isEmpty()) { @@ -135,7 +135,7 @@ private static String generateProvider(TypeElement language) { builder.startReturn().startNew(languageType).end().end(); break; - case "getFileTypeDetectors": + case "createFileTypeDetectors": List detectors = ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "fileTypeDetectors"); if (detectors.isEmpty()) { builder.startReturn().startStaticCall(context.getType(Collections.class), "emptyList").end().end(); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java index da47ef6f66c5..ede1e8ebc4cf 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java @@ -872,7 +872,7 @@ private static final class ServiceLoaderLanguageReflection extends LanguageRefle @Override TruffleLanguage newInstance() { exportTruffleIfNeeded(); - return provider.get(); + return provider.create(); } @Override @@ -880,7 +880,7 @@ List getFileTypeDetectors() { List result = fileTypeDetectors; if (result == null) { exportTruffleIfNeeded(); - result = provider.getFileTypeDetectors(); + result = provider.createFileTypeDetectors(); fileTypeDetectors = result; } return result; From 989dd990ae383e2098a91d95c2a55bd70dcce55e Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Tue, 1 Oct 2019 11:21:16 +0200 Subject: [PATCH 073/140] [GR-15292] Added an annotation to generate legacy registration. --- .../processor/LanguageRegistrationTest.java | 34 +++++++ .../processor/GenerateLegacyRegistration.java | 48 ++++++++++ .../LanguageRegistrationProcessor.java | 92 ++++++++++++++++++- 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/GenerateLegacyRegistration.java diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java index 7e6c6ce589be..adbb2b8ae4d0 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java @@ -49,7 +49,13 @@ import com.oracle.truffle.api.dsl.test.ExpectError; import com.oracle.truffle.api.test.polyglot.ProxyLanguage; import com.oracle.truffle.api.TruffleFile.FileTypeDetector; +import com.oracle.truffle.dsl.processor.GenerateLegacyRegistration; import java.nio.charset.Charset; +import java.util.Collections; +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.Language; +import org.junit.Assert; +import org.junit.Test; public class LanguageRegistrationTest { @@ -173,6 +179,16 @@ public Detector(String name) { } } + @GenerateLegacyRegistration + @Registration(id = "legacyregistration1", name = "LegacyRegistration1", implementationName = "legacy.registration1", version = "1.0.0", characterMimeTypes = "text/x-legacyregistration1") + public static class LegacyRegistration1 extends ProxyLanguage { + } + + @GenerateLegacyRegistration + @Registration(id = "legacyregistration2", name = "LegacyRegistration2", implementationName = "legacy.registration2", version = "2.0.0", byteMimeTypes = "binary/x-legacyregistration2") + public static class LegacyRegistration2 extends ProxyLanguage { + } + static class ProxyFileTypeDetector implements FileTypeDetector { @Override @@ -187,4 +203,22 @@ public Charset findEncoding(TruffleFile file) throws IOException { return null; } } + + @Test + public void testLoadLegacyRegistrations() { + try (Engine eng = Engine.create()) { + Language language = eng.getLanguages().get("legacyregistration1"); + Assert.assertNotNull(language); + Assert.assertEquals("LegacyRegistration1", language.getName()); + Assert.assertEquals("legacy.registration1", language.getImplementationName()); + Assert.assertEquals("1.0.0", language.getVersion()); + Assert.assertEquals(Collections.singleton("text/x-legacyregistration1"), language.getMimeTypes()); + language = eng.getLanguages().get("legacyregistration2"); + Assert.assertNotNull(language); + Assert.assertEquals("LegacyRegistration2", language.getName()); + Assert.assertEquals("legacy.registration2", language.getImplementationName()); + Assert.assertEquals("2.0.0", language.getVersion()); + Assert.assertEquals(Collections.singleton("binary/x-legacyregistration2"), language.getMimeTypes()); + } + } } diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/GenerateLegacyRegistration.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/GenerateLegacyRegistration.java new file mode 100644 index 000000000000..35977edc9bb4 --- /dev/null +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/GenerateLegacyRegistration.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019, 2019, 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.dsl.processor; + +/** + * Not an API. Will be removed when a support for reading legacy TruffleLanguage and + * TruffleInstrument registrations is removed. + */ +public @interface GenerateLegacyRegistration { +} diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java index 0d25d7ca4f0c..dba19a04de15 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java @@ -42,6 +42,7 @@ import com.oracle.truffle.api.TruffleFile; import java.io.IOException; +import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; @@ -96,6 +97,7 @@ @SupportedAnnotationTypes("com.oracle.truffle.api.TruffleLanguage.Registration") public final class LanguageRegistrationProcessor extends AbstractProcessor { private final Map registrations = new HashMap<>(); + private final List legacyRegistrations = new ArrayList<>(); // also update list in PolyglotEngineImpl#RESERVED_IDS private static final Set RESERVED_IDS = new HashSet<>( @@ -217,6 +219,84 @@ private static void generateServicesRegistration(Map languages) { + String filename = "META-INF/truffle/language"; + // sorted properties + Properties p = new SortedProperties(); + int cnt = 0; + for (TypeElement l : languages) { + Registration annotation = l.getAnnotation(Registration.class); + if (annotation == null) { + continue; + } + String prefix = "language" + ++cnt + "."; + String className = processingEnv.getElementUtils().getBinaryName(l).toString(); + String id = annotation.id(); + if (id != null && !id.isEmpty()) { + p.setProperty(prefix + "id", id); + } + p.setProperty(prefix + "name", annotation.name()); + p.setProperty(prefix + "implementationName", annotation.implementationName()); + p.setProperty(prefix + "version", annotation.version()); + p.setProperty(prefix + "className", className); + + if (!annotation.defaultMimeType().equals("")) { + p.setProperty(prefix + "defaultMimeType", annotation.defaultMimeType()); + } + + String[] mimes = annotation.mimeType(); + for (int i = 0; i < mimes.length; i++) { + p.setProperty(prefix + "mimeType." + i, mimes[i]); + } + String[] charMimes = annotation.characterMimeTypes(); + Arrays.sort(charMimes); + for (int i = 0; i < charMimes.length; i++) { + p.setProperty(prefix + "characterMimeType." + i, charMimes[i]); + } + String[] byteMimes = annotation.byteMimeTypes(); + Arrays.sort(byteMimes); + for (int i = 0; i < byteMimes.length; i++) { + p.setProperty(prefix + "byteMimeType." + i, byteMimes[i]); + } + + String[] dependencies = annotation.dependentLanguages(); + Arrays.sort(dependencies); + for (int i = 0; i < dependencies.length; i++) { + p.setProperty(prefix + "dependentLanguage." + i, dependencies[i]); + } + p.setProperty(prefix + "interactive", Boolean.toString(annotation.interactive())); + p.setProperty(prefix + "internal", Boolean.toString(annotation.internal())); + + AnnotationMirror registration = ElementUtils.findAnnotationMirror(l.getAnnotationMirrors(), ProcessorContext.getInstance().getType(Registration.class)); + int serviceCounter = 0; + for (TypeMirror serviceTypeMirror : ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "services")) { + p.setProperty(prefix + "service" + serviceCounter++, processingEnv.getElementUtils().getBinaryName(ElementUtils.fromTypeMirror(serviceTypeMirror)).toString()); + } + int fileTypeDetectorCounter = 0; + for (TypeMirror fileTypeDetectorTypeMirror : ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "fileTypeDetectors")) { + p.setProperty(prefix + "fileTypeDetector" + fileTypeDetectorCounter++, + processingEnv.getElementUtils().getBinaryName(ElementUtils.fromTypeMirror(fileTypeDetectorTypeMirror)).toString()); + } + } + if (cnt > 0) { + try { + FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, languages.toArray(new Element[0])); + try (OutputStream os = file.openOutputStream()) { + p.store(os, "Generated by " + LanguageRegistrationProcessor.class.getName()); + } + } catch (IOException e) { + if (e instanceof FilerException) { + if (e.getMessage().startsWith("Source file already created")) { + // ignore source file already created errors + return; + } + } + processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), languages.get(0)); + } + } + } + @SuppressWarnings("deprecation") @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { @@ -224,7 +304,9 @@ public boolean process(Set annotations, RoundEnvironment try { if (roundEnv.processingOver()) { generateServicesRegistration(registrations); + generateLegacyRegistration(legacyRegistrations); registrations.clear(); + legacyRegistrations.clear(); return true; } @@ -339,7 +421,11 @@ public boolean process(Set annotations, RoundEnvironment } if (processingTruffleLanguage) { TypeElement languageTypeElement = (TypeElement) e; - registrations.put(generateProvider(languageTypeElement), languageTypeElement); + if (requiresLegacyRegistration(languageTypeElement)) { + legacyRegistrations.add(languageTypeElement); + } else { + registrations.put(generateProvider(languageTypeElement), languageTypeElement); + } } } } @@ -350,6 +436,10 @@ public boolean process(Set annotations, RoundEnvironment } } + private static boolean requiresLegacyRegistration(TypeElement language) { + return language.getAnnotation(GenerateLegacyRegistration.class) != null; + } + private boolean validateMimeTypes(Set collectedMimeTypes, Element e, AnnotationMirror mirror, AnnotationValue value, String[] loadedMimeTypes) { for (String mimeType : loadedMimeTypes) { if (!validateMimeType(e, mirror, value, mimeType)) { From 1993f29d1200d1dd05e3108d1469567bbf133b30 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Tue, 1 Oct 2019 15:07:16 +0200 Subject: [PATCH 074/140] [GR-15292] InstrumentCache legacy behaviour. --- .../instrumentation/InstrumentAccessor.java | 5 +- .../InstrumentationHandler.java | 34 +-- .../api/instrumentation/ProbeNode.java | 3 +- .../com/oracle/truffle/api/impl/Accessor.java | 2 +- .../truffle/polyglot/InstrumentCache.java | 249 ++++++++++++------ .../truffle/polyglot/LanguageCache.java | 4 +- .../truffle/polyglot/PolyglotInstrument.java | 10 +- 7 files changed, 201 insertions(+), 106 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 66139502ee99..a36a7ec4f286 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 @@ -57,6 +57,7 @@ import java.io.InputStream; import java.util.Set; +import java.util.function.Supplier; final class InstrumentAccessor extends Accessor { @@ -93,8 +94,8 @@ public Object createInstrumentationHandler(Object vm, DispatchOutputStream out, } @Override - public void initializeInstrument(Object instrumentationHandler, Object key, Class instrumentClass) { - ((InstrumentationHandler) instrumentationHandler).initializeInstrument(key, instrumentClass); + public void initializeInstrument(Object instrumentationHandler, Object key, String instrumentClassName, Supplier instrumentSupplier) { + ((InstrumentationHandler) instrumentationHandler).initializeInstrument(key, instrumentClassName, instrumentSupplier); } @Override 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 d8d3c70aa176..3d226967db6c 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 @@ -84,6 +84,7 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; +import java.util.function.Supplier; /** * Central coordinator class for the Truffle instrumentation framework. Allocated once per @@ -354,22 +355,23 @@ void onFirstExecution(RootNode root) { } - void initializeInstrument(Object vmObject, Class instrumentClass) { - Env env = new Env(vmObject, out, err, in, messageInterceptor); - env.instrumenter = new InstrumentClientInstrumenter(env, instrumentClass); - + void initializeInstrument(Object vmObject, String instrumentClassName, Supplier instrumentSupplier) { if (TRACE) { - trace("Initialize instrument class %s %n", instrumentClass); + trace("Initialize instrument class %s %n", instrumentClassName); } + + Env env = new Env(vmObject, out, err, in, messageInterceptor); try { - env.instrumenter.instrument = (TruffleInstrument) instrumentClass.getDeclaredConstructor().newInstance(); + TruffleInstrument instrument = (TruffleInstrument) instrumentSupplier.get(); + env.instrumenter = new InstrumentClientInstrumenter(env, instrumentClassName); + env.instrumenter.instrument = instrument; } catch (Exception e) { - failInstrumentInitialization(env, String.format("Failed to create new instrumenter class %s", instrumentClass.getName()), e); + failInstrumentInitialization(env, String.format("Failed to create new instrumenter class %s", instrumentClassName), e); return; } if (TRACE) { - trace("Initialized instrument %s class %s %n", env.instrumenter.instrument, instrumentClass); + trace("Initialized instrument %s class %s %n", env.instrumenter.instrument, instrumentClassName); } addInstrumenter(vmObject, env.instrumenter); @@ -1574,13 +1576,13 @@ protected void visitInstrumented(EventBinding.Source binding, Node node, Sour */ final class InstrumentClientInstrumenter extends AbstractInstrumenter { - private final Class instrumentClass; + private final String instrumentClassName; private Object[] services; TruffleInstrument instrument; private final Env env; - InstrumentClientInstrumenter(Env env, Class instrumentClass) { - this.instrumentClass = instrumentClass; + InstrumentClientInstrumenter(Env env, String instrumentClassName) { + this.instrumentClassName = instrumentClassName; this.env = env; } @@ -1603,8 +1605,8 @@ public Set> queryTags(Node node) { void verifyFilter(SourceSectionFilter filter) { } - Class getInstrumentClass() { - return instrumentClass; + String getInstrumentClassName() { + return instrumentClassName; } Env getEnv() { @@ -1613,14 +1615,14 @@ Env getEnv() { void create(String[] expectedServices) { if (TRACE) { - trace("Create instrument %s class %s %n", instrument, instrumentClass); + trace("Create instrument %s class %s %n", instrument, instrumentClassName); } services = env.onCreate(instrument); if (expectedServices != null && !TruffleOptions.AOT) { checkServices(expectedServices); } if (TRACE) { - trace("Created instrument %s class %s %n", instrument, instrumentClass); + trace("Created instrument %s class %s %n", instrument, instrumentClassName); } } @@ -1631,7 +1633,7 @@ private boolean checkServices(String[] expectedServices) { continue LOOP; } } - failInstrumentInitialization(env, String.format("%s declares service %s but doesn't register it", instrumentClass.getName(), name), null); + failInstrumentInitialization(env, String.format("%s declares service %s but doesn't register it", instrumentClassName, name), null); } return true; } diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/ProbeNode.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/ProbeNode.java index c48ff8953ffb..75899034b0fc 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/ProbeNode.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/ProbeNode.java @@ -642,10 +642,9 @@ static void exceptionEventForClientInstrument(EventBinding.Source b, String e } // Exception is a failure in (non-language) instrumentation code; log and continue InstrumentClientInstrumenter instrumenter = (InstrumentClientInstrumenter) b.getInstrumenter(); - Class instrumentClass = instrumenter.getInstrumentClass(); String message = String.format("Event %s failed for instrument class %s and listener/factory %s.", // - eventName, instrumentClass.getName(), b.getElement()); + eventName, instrumenter.getInstrumentClassName(), b.getElement()); Exception exception = new Exception(message, t); PrintStream stream = new PrintStream(instrumenter.getEnv().err()); 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 4e9165e23346..f88b5eaa34b8 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 @@ -514,7 +514,7 @@ public abstract Env patchEnvContext(Env env, OutputStream stdOut, OutputStream s public abstract static class InstrumentSupport { - public abstract void initializeInstrument(Object instrumentationHandler, Object key, Class instrumentClass); + public abstract void initializeInstrument(Object instrumentationHandler, Object key, String instrumentClassName, Supplier instrumentSupplier); public abstract void createInstrument(Object instrumentationHandler, Object key, String[] expectedServices, OptionValues options); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java index 13231fd98040..2eecded35f28 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java @@ -60,6 +60,7 @@ import com.oracle.truffle.api.TruffleOptions; import com.oracle.truffle.api.impl.TruffleJDKServices; import com.oracle.truffle.api.instrumentation.TruffleInstrument; +import java.util.Objects; //TODO (chumer): maybe this class should share some code with LanguageCache? final class InstrumentCache { @@ -69,14 +70,13 @@ final class InstrumentCache { private static final List nativeImageCache = TruffleOptions.AOT ? new ArrayList<>() : null; private static Map> runtimeCaches = new WeakHashMap<>(); - private Class instrumentClass; private final String className; private final String id; private final String name; private final String version; private final boolean internal; - private final ClassLoader loader; private final Set services; + private final InstrumentReflection instrumentReflection; /** * Initializes state for native image generation. @@ -101,14 +101,9 @@ private static void resetNativeImageState() { runtimeCaches.clear(); } - private InstrumentCache(String prefix, Properties info, ClassLoader loader) { - this.loader = loader; - this.className = info.getProperty(prefix + "className"); - this.name = info.getProperty(prefix + "name"); - this.version = info.getProperty(prefix + "version"); - this.internal = Boolean.valueOf(info.getProperty(prefix + "internal")); - String loadedId = info.getProperty(prefix + "id"); - if (loadedId.equals("")) { + private InstrumentCache(String id, String name, String version, String className, boolean internal, Set services, InstrumentReflection instrumentReflection) { + this.instrumentReflection = instrumentReflection; + if (id.equals("")) { /* use class name default id */ int lastIndex = className.lastIndexOf('$'); if (lastIndex == -1) { @@ -116,20 +111,16 @@ private InstrumentCache(String prefix, Properties info, ClassLoader loader) { } this.id = className.substring(lastIndex + 1, className.length()); } else { - this.id = loadedId; - } - int servicesCounter = 0; - this.services = new TreeSet<>(); - for (;;) { - String nth = prefix + "service" + servicesCounter++; - String serviceName = info.getProperty(nth); - if (serviceName == null) { - break; - } - this.services.add(serviceName); + this.id = id; } + this.name = name; + this.version = version; + this.className = className; + this.internal = internal; + this.services = services; + if (TruffleOptions.AOT) { - initializeInstrumentClass(); + instrumentReflection.aotInitializeAtBuildTime(); } } @@ -155,60 +146,21 @@ private static List doLoad(Collection loaders, Cla List list = new ArrayList<>(); Set classNamesUsed = new HashSet<>(); for (ClassLoader loader : loaders) { - loadForOne(loader, list, classNamesUsed); + Loader.load(loader, list, classNamesUsed); } if (additionalLoader != null) { - loadForOne(additionalLoader, list, classNamesUsed); + Loader.load(additionalLoader, list, classNamesUsed); } if (!JDK8OrEarlier) { - loadForOne(ModuleResourceLocator.createLoader(), list, classNamesUsed); - } - return list; - } - - private static void loadForOne(ClassLoader loader, List list, Set classNamesUsed) { - if (loader == null) { - return; - } - Enumeration en; - try { - en = loader.getResources("META-INF/truffle/instrument"); - } catch (IOException ex) { - throw new IllegalStateException("Cannot read list of Truffle instruments", ex); - } - while (en.hasMoreElements()) { - URL u = en.nextElement(); - Properties p; - try { - p = new Properties(); - try (InputStream is = u.openStream()) { - p.load(is); - } - } catch (IOException ex) { - PrintStream out = System.err; - out.println("Cannot process " + u + " as language definition"); - ex.printStackTrace(); - continue; - } - for (int cnt = 1;; cnt++) { - String prefix = "instrument" + cnt + "."; - String className = p.getProperty(prefix + "className"); - if (className == null) { - break; - } - // we don't want multiple instruments with the same class name - if (!classNamesUsed.contains(className)) { - classNamesUsed.add(className); - list.add(new InstrumentCache(prefix, p, loader)); - } - } + Loader.load(ModuleResourceLocator.createLoader(), list, classNamesUsed); } Collections.sort(list, new Comparator() { - @Override - public int compare(InstrumentCache o1, InstrumentCache o2) { - return o1.getId().compareTo(o2.getId()); - } - }); + @Override + public int compare(InstrumentCache o1, InstrumentCache o2) { + return o1.getId().compareTo(o2.getId()); + } + }); + return list; } String getId() { @@ -227,11 +179,8 @@ String getVersion() { return version; } - Class getInstrumentationClass() { - if (!TruffleOptions.AOT && instrumentClass == null) { - initializeInstrumentClass(); - } - return instrumentClass; + TruffleInstrument loadInstrument() { + return instrumentReflection.newInstance(); } boolean supportsService(Class clazz) { @@ -242,8 +191,13 @@ String[] services() { return services.toArray(new String[0]); } - private void initializeInstrumentClass() { - try { + private abstract static class InstrumentReflection { + + abstract TruffleInstrument newInstance(); + + abstract Class aotInitializeAtBuildTime(); + + final void exportTruffle(ClassLoader loader) { if (!TruffleOptions.AOT) { // In JDK 9+, the Truffle API packages must be dynamically exported to // a Truffle instrument since the Truffle API module descriptor only @@ -251,9 +205,144 @@ private void initializeInstrumentClass() { // Graal module). TruffleJDKServices.exportTo(loader, null); } - instrumentClass = Class.forName(className, true, loader).asSubclass(TruffleInstrument.class); - } catch (Exception ex) { - throw new IllegalStateException("Cannot initialize " + getName() + " instrument with implementation " + className, ex); + } + } + + private static abstract class Loader { + + private static final Loader[] INSTANCES = new Loader[] { + new LegacyLoader(), + new ServicesLoader() + }; + + static void load (ClassLoader loader, List list, Set classNamesUsed) { + if (loader == null) { + return; + } + for (Loader instance : INSTANCES) { + instance.loadImpl(loader, list, classNamesUsed); + } + } + + abstract void loadImpl(ClassLoader loader, List list, Set classNamesUsed); + } + + private static final class LegacyLoader extends Loader { + + @Override + void loadImpl(ClassLoader loader, List list, Set classNamesUsed) { + Enumeration en; + try { + en = loader.getResources("META-INF/truffle/instrument"); + } catch (IOException ex) { + throw new IllegalStateException("Cannot read list of Truffle instruments", ex); + } + while (en.hasMoreElements()) { + URL u = en.nextElement(); + Properties p; + try { + p = new Properties(); + try (InputStream is = u.openStream()) { + p.load(is); + } + } catch (IOException ex) { + PrintStream out = System.err; + out.println("Cannot process " + u + " as language definition"); + ex.printStackTrace(); + continue; + } + for (int cnt = 1;; cnt++) { + String prefix = "instrument" + cnt + "."; + String className = p.getProperty(prefix + "className"); + if (className == null) { + break; + } + // we don't want multiple instruments with the same class name + if (!classNamesUsed.contains(className)) { + classNamesUsed.add(className); + list.add(createInstrumentCache(prefix, p, loader)); + } + } + } + } + + private InstrumentCache createInstrumentCache(String prefix, Properties info, ClassLoader loader) { + String className = info.getProperty(prefix + "className"); + String name = info.getProperty(prefix + "name"); + String version = info.getProperty(prefix + "version"); + boolean internal = Boolean.valueOf(info.getProperty(prefix + "internal")); + String id = info.getProperty(prefix + "id"); + int servicesCounter = 0; + Set services = new TreeSet<>(); + for (;;) { + String nth = prefix + "service" + servicesCounter++; + String serviceName = info.getProperty(nth); + if (serviceName == null) { + break; + } + services.add(serviceName); + } + InstrumentReflection reflection = new LegacyInstrumentReflection(name, loader, className); + return new InstrumentCache(id, name, version, className, internal, services, reflection); + } + + private static final class LegacyInstrumentReflection extends InstrumentReflection { + + private final String name; + private final ClassLoader loader; + private final String className; + private volatile Class instrumentClass; + + LegacyInstrumentReflection(String name, ClassLoader loader, String className) { + Objects.requireNonNull(name, "Name must be non null."); + Objects.requireNonNull(loader, "Loader must be non null."); + Objects.requireNonNull(className, "ClassName must be non null."); + this.name = name; + this.loader = loader; + this.className = className; + } + + @Override + TruffleInstrument newInstance() { + try { + return getInstrumentationClass().getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new IllegalStateException("Cannot create instance of " + name + " language implementation. Public default constructor expected in " + className + ".", e); + } + } + + @Override + Class aotInitializeAtBuildTime() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + private Class getInstrumentationClass() { + if (!TruffleOptions.AOT) { + initializeInstrumentClass(); + } + return instrumentClass; + } + + private void initializeInstrumentClass() { + if (instrumentClass == null) { + synchronized (this) { + if (instrumentClass == null) { + try { + exportTruffle(loader); + instrumentClass = Class.forName(className, true, loader).asSubclass(TruffleInstrument.class); + } catch (Exception ex) { + throw new IllegalStateException("Cannot initialize " + name + " instrument with implementation " + className, ex); + } + } + } + } + } + } + } + + private static final class ServicesLoader extends Loader { + @Override + void loadImpl(ClassLoader loader, List list, Set classNamesUsed) { } } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java index ede1e8ebc4cf..4e13f200f7cf 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java @@ -669,13 +669,11 @@ private static final class LegacyLanguageReflection extends LanguageReflection { @Override TruffleLanguage newInstance() { - TruffleLanguage instance; try { - instance = getLanguageClass().getDeclaredConstructor().newInstance(); + return getLanguageClass().getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new IllegalStateException("Cannot create instance of " + name + " language implementation. Public default constructor expected in " + className + ".", e); } - return instance; } @Override diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotInstrument.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotInstrument.java index 4b697b16b06e..1f4cbd9875e7 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotInstrument.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotInstrument.java @@ -47,6 +47,8 @@ import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractInstrumentImpl; import com.oracle.truffle.api.InstrumentInfo; +import com.oracle.truffle.api.instrumentation.TruffleInstrument; +import java.util.function.Supplier; class PolyglotInstrument extends AbstractInstrumentImpl implements com.oracle.truffle.polyglot.PolyglotImpl.VMObject { @@ -95,8 +97,12 @@ void ensureInitialized() { synchronized (instrumentLock) { if (!initialized) { try { - Class loadedInstrument = cache.getInstrumentationClass(); - INSTRUMENT.initializeInstrument(engine.instrumentationHandler, this, loadedInstrument); + INSTRUMENT.initializeInstrument(engine.instrumentationHandler, this, cache.getClassName(), new Supplier() { + @Override + public TruffleInstrument get() { + return cache.loadInstrument(); + } + }); this.options = INSTRUMENT.describeOptions(engine.instrumentationHandler, this, cache.getId()); } catch (Exception e) { throw new IllegalStateException(String.format("Error initializing instrument '%s' using class '%s'.", cache.getId(), cache.getClassName()), e); From 6dc4005011bde997e2d9a84451c8d3a3fcee8832 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Tue, 1 Oct 2019 16:21:25 +0200 Subject: [PATCH 075/140] [GR-15292] InstrumentCache for ServiceLoader loaded languages. --- truffle/CHANGELOG.md | 1 + .../instrumentation/TruffleInstrument.java | 26 +++++ .../truffle/polyglot/InstrumentCache.java | 105 ++++++++++++++---- .../truffle/polyglot/LanguageCache.java | 7 +- 4 files changed, 114 insertions(+), 25 deletions(-) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index b6fa6c7070f6..0175aa0d5927 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -17,6 +17,7 @@ This changelog summarizes major changes between Truffle versions relevant to lan * Added [Scope.Builder#rootInstance(Object)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.Builder.html#rootInstance-java.lang.Object-), [Scope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.html#getRootInstance--) and [DebugScope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugScope.html#getRootInstance--) to provide an instance of guest language representation of the root node (e.g. a guest language function). * Debugger breakpoints can be restricted to a particular root instance via [Breakpoint.Builder#rootInstance(DebugValue)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/Breakpoint.Builder.html#rootInstance-com.oracle.truffle.api.debug.DebugValue-) and found later on via [DebugValue#getRootInstanceBreakpoints()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugValue.html#getRootInstanceBreakpoints--). * `TruffleLanguage`s are registered in a `ServiceLoader` using the [TruffleLanguage.Provider](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.Provider.html) as a service interface. +* `TruffleInstrument`s are registered in a `ServiceLoader` using the [TruffleInstrument.Provider](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/TruffleInstrument.Provider.html) as a service interface. ## Version 19.2.0 * Added sub-process output (error output) [redirection into OutputStream](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/ProcessHandler.Redirect.html#stream-java.io.OutputStream-). 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 1a6eec0c5455..0d6c2520b898 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 @@ -53,6 +53,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.ServiceLoader; import org.graalvm.options.OptionDescriptor; import org.graalvm.options.OptionDescriptors; @@ -833,6 +834,31 @@ public void sendClose() throws IOException { Class[] services() default {}; } + /** + * Used to register a {@link TruffleInstrument} using a {@link ServiceLoader}. This interface is + * not intended to be implemented directly by an instrument developer, rather the implementation + * is generated by the Truffle DSL. The generated implementation has to inherit the + * {@link Registration} annotations from the {@link TruffleInstrument}. + * + * @since 19.3.0 + */ + public interface Provider { + + /** + * Returns the name of a class implementing the {@link TruffleInstrument}. + * + * @since 19.3.0 + */ + String getInstrumentClassName(); + + /** + * Creates a new instance of a {@link TruffleInstrument}. + * + * @since 19.3.0 + */ + TruffleInstrument create(); + } + static { try { // Instrument is loaded by Engine which should load InstrumentationHandler diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java index 2eecded35f28..11328c2cd4df 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java @@ -60,7 +60,10 @@ import com.oracle.truffle.api.TruffleOptions; import com.oracle.truffle.api.impl.TruffleJDKServices; import com.oracle.truffle.api.instrumentation.TruffleInstrument; +import com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration; import java.util.Objects; +import java.util.ServiceLoader; +import java.util.concurrent.atomic.AtomicBoolean; //TODO (chumer): maybe this class should share some code with LanguageCache? final class InstrumentCache { @@ -103,16 +106,7 @@ private static void resetNativeImageState() { private InstrumentCache(String id, String name, String version, String className, boolean internal, Set services, InstrumentReflection instrumentReflection) { this.instrumentReflection = instrumentReflection; - if (id.equals("")) { - /* use class name default id */ - int lastIndex = className.lastIndexOf('$'); - if (lastIndex == -1) { - lastIndex = className.lastIndexOf('.'); - } - this.id = className.substring(lastIndex + 1, className.length()); - } else { - this.id = id; - } + this.id = id; this.name = name; this.version = version; this.className = className; @@ -155,11 +149,11 @@ private static List doLoad(Collection loaders, Cla Loader.load(ModuleResourceLocator.createLoader(), list, classNamesUsed); } Collections.sort(list, new Comparator() { - @Override - public int compare(InstrumentCache o1, InstrumentCache o2) { - return o1.getId().compareTo(o2.getId()); - } - }); + @Override + public int compare(InstrumentCache o1, InstrumentCache o2) { + return o1.getId().compareTo(o2.getId()); + } + }); return list; } @@ -208,14 +202,14 @@ final void exportTruffle(ClassLoader loader) { } } - private static abstract class Loader { + private abstract static class Loader { - private static final Loader[] INSTANCES = new Loader[] { - new LegacyLoader(), - new ServicesLoader() + private static final Loader[] INSTANCES = new Loader[]{ + new LegacyLoader(), + new ServicesLoader() }; - static void load (ClassLoader loader, List list, Set classNamesUsed) { + static void load(ClassLoader loader, List list, Set classNamesUsed) { if (loader == null) { return; } @@ -225,6 +219,15 @@ static void load (ClassLoader loader, List list, Set list, Set classNamesUsed); + + static String defaultId(String className) { + /* use class name default id */ + int lastIndex = className.lastIndexOf('$'); + if (lastIndex == -1) { + lastIndex = className.lastIndexOf('.'); + } + return className.substring(lastIndex + 1, className.length()); + } } private static final class LegacyLoader extends Loader { @@ -272,6 +275,9 @@ private InstrumentCache createInstrumentCache(String prefix, Properties info, Cl String version = info.getProperty(prefix + "version"); boolean internal = Boolean.valueOf(info.getProperty(prefix + "internal")); String id = info.getProperty(prefix + "id"); + if (id == null || id.isEmpty()) { + id = defaultId(className); + } int servicesCounter = 0; Set services = new TreeSet<>(); for (;;) { @@ -313,7 +319,10 @@ TruffleInstrument newInstance() { @Override Class aotInitializeAtBuildTime() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); // To change body of + // generated methods, + // choose Tools | + // Templates. } private Class getInstrumentationClass() { @@ -341,8 +350,62 @@ private void initializeInstrumentClass() { } private static final class ServicesLoader extends Loader { + + ServicesLoader() { + } + @Override void loadImpl(ClassLoader loader, List list, Set classNamesUsed) { + for (TruffleInstrument.Provider provider : ServiceLoader.load(TruffleInstrument.Provider.class, loader)) { + Registration reg = provider.getClass().getAnnotation(Registration.class); + if (reg == null) { + PrintStream out = System.err; + out.println("Provider " + provider.getClass() + " is missing @Registration annotation."); + continue; + } + String className = provider.getInstrumentClassName(); + String name = reg.name(); + String id = reg.id(); + if (id == null || id.isEmpty()) { + id = defaultId(className); + } + String version = reg.version(); + boolean internal = reg.internal(); + Set servicesClassNames = new TreeSet<>(); + for (Class service : reg.services()) { + servicesClassNames.add(service.getCanonicalName()); + } + // we don't want multiple instruments with the same class name + if (!classNamesUsed.contains(className)) { + classNamesUsed.add(className); + InstrumentReflection reflection = new ServiceLoaderInstrumentReflection(provider); + list.add(new InstrumentCache(id, name, version, className, internal, servicesClassNames, reflection)); + } + } + } + + private static final class ServiceLoaderInstrumentReflection extends InstrumentReflection { + + private final TruffleInstrument.Provider provider; + private final AtomicBoolean exported = new AtomicBoolean(); + + ServiceLoaderInstrumentReflection(TruffleInstrument.Provider provider) { + assert provider != null; + this.provider = provider; + } + + @Override + TruffleInstrument newInstance() { + if (exported.compareAndSet(false, true)) { + exportTruffle(provider.getClass().getClassLoader()); + } + return provider.create(); + } + + @Override + Class aotInitializeAtBuildTime() { + return null; + } } } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java index 4e13f200f7cf..ab2077d5d98d 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java @@ -802,13 +802,12 @@ public void loadImpl(ClassLoader loader, Collection into) out.println("Provider " + provider.getClass() + " is missing @Registration annotation."); continue; } - + String className = provider.getLanguageClassName(); String name = reg.name(); String id = reg.id(); - if (id == null) { - id = defaultId(name, provider.getLanguageClassName()); + if (id == null || id.isEmpty()) { + id = defaultId(name, className); } - String className = provider.getLanguageClassName(); String languageHome = System.getProperty(id + ".home"); if (languageHome == null) { URL url = provider.getClass().getClassLoader().getResource(className.replace('.', '/') + ".class"); From 82449a344fa875ca260a39a0655ea493173810b6 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Tue, 1 Oct 2019 17:59:12 +0200 Subject: [PATCH 076/140] [GR-15292] Truffle DSL generates ServiceLoader registrations for TruffleInstruments. --- .../InstrumentRegistrationProcessor.java | 172 +++++++++++++++--- 1 file changed, 147 insertions(+), 25 deletions(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java index 12a0c4742fae..5b8f0c594564 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java @@ -43,8 +43,10 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -62,7 +64,10 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.Elements; import javax.tools.Diagnostic.Kind; import javax.tools.FileObject; import javax.tools.StandardLocation; @@ -70,11 +75,24 @@ import com.oracle.truffle.api.instrumentation.TruffleInstrument; import com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration; import com.oracle.truffle.dsl.processor.LanguageRegistrationProcessor.SortedProperties; +import com.oracle.truffle.dsl.processor.generator.GeneratorUtils; import com.oracle.truffle.dsl.processor.java.ElementUtils; +import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; +import com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder; +import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; +import com.oracle.truffle.dsl.processor.java.transform.FixWarningsVisitor; +import com.oracle.truffle.dsl.processor.java.transform.GenerateOverrideVisitor; +import com.oracle.truffle.dsl.processor.model.Template; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.Collections; +import java.util.HashMap; +import javax.annotation.processing.FilerException; @SupportedAnnotationTypes("com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration") public final class InstrumentRegistrationProcessor extends AbstractProcessor { - private final List registrations = new ArrayList<>(); + private final Map registrations = new HashMap<>(); + private final List legacyRegistrations = new ArrayList<>(); @Override public SourceVersion getSupportedSourceVersion() { @@ -83,7 +101,88 @@ public SourceVersion getSupportedSourceVersion() { private static final int NUMBER_OF_PROPERTIES_PER_ENTRY = 4; - private void generateFile(List instruments) { + private static String generateProvider(TypeElement instrument) { + ProcessorContext context = ProcessorContext.getInstance(); + Elements elements = context.getEnvironment().getElementUtils(); + Template instrumentModel = new Template(context, instrument, null) { + }; + TypeElement providerElement = context.getTypeElement(TruffleInstrument.Provider.class); + CodeTypeElement providerClass = GeneratorUtils.createClass(instrumentModel, null, EnumSet.of(Modifier.PUBLIC), + createProviderSimpleName(instrument), null); + providerClass.getImplements().add(providerElement.asType()); + AnnotationMirror registration = ElementUtils.findAnnotationMirror(instrument.getAnnotationMirrors(), ProcessorContext.getInstance().getType(Registration.class)); + for (Element method : ElementFilter.methodsIn(providerElement.getEnclosedElements())) { + CodeExecutableElement implementedMethod = CodeExecutableElement.clone((ExecutableElement) method); + implementedMethod.getModifiers().remove(Modifier.ABSTRACT); + CodeTreeBuilder builder = implementedMethod.createBuilder(); + switch (method.getSimpleName().toString()) { + case "create": + builder.startReturn().startNew(instrument.asType()).end().end(); + break; + case "getInstrumentClassName": + builder.startReturn().doubleQuote(elements.getBinaryName(instrument).toString()).end(); + break; + default: + throw new IllegalStateException("Unsupported method: " + method.getSimpleName()); + } + providerClass.add(implementedMethod); + } + + providerClass.addAnnotationMirror(registration); + DeclaredType overrideType = (DeclaredType) context.getType(Override.class); + providerClass.accept(new GenerateOverrideVisitor(overrideType), null); + providerClass.accept(new FixWarningsVisitor(instrument, overrideType), null); + providerClass.accept(new CodeWriter(context.getEnvironment(), instrument), null); + return providerClass.getQualifiedName().toString(); + } + + private static String createProviderSimpleName(TypeElement language) { + StringBuilder nameBuilder = new StringBuilder(); + List hierarchy = ElementUtils.getElementHierarchy(language); + for (ListIterator it = hierarchy.listIterator(hierarchy.size()); it.hasPrevious();) { + Element enc = it.previous(); + if (enc.getKind().isClass() || enc.getKind().isInterface()) { + nameBuilder.append(enc.getSimpleName()); + } + } + nameBuilder.append("Provider"); + return nameBuilder.toString(); + } + + private static void generateServicesRegistration(Map providerFqns) { + ProcessorContext context = ProcessorContext.getInstance(); + ProcessingEnvironment env = context.getEnvironment(); + Elements elements = env.getElementUtils(); + Name providerBinName = elements.getBinaryName(context.getTypeElement(TruffleInstrument.Provider.class)); + String filename = "META-INF/services/" + providerBinName; + List providerClassNames = new ArrayList<>(providerFqns.size()); + for (String providerFqn : providerFqns.keySet()) { + TypeElement te = ElementUtils.getTypeElement(env, providerFqn); + providerClassNames.add(elements.getBinaryName(te).toString()); + } + Collections.sort(providerClassNames); + if (!providerClassNames.isEmpty()) { + try { + FileObject file = env.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, providerFqns.values().toArray(new Element[providerFqns.size()])); + try (PrintWriter out = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"))) { + out.println("# Generated by " + InstrumentRegistrationProcessor.class.getName()); + for (String providerClassName : providerClassNames) { + out.println(providerClassName); + } + } + } catch (IOException e) { + if (e instanceof FilerException) { + if (e.getMessage().startsWith("Source file already created")) { + // ignore source file already created errors + return; + } + } + env.getMessager().printMessage(Kind.ERROR, e.getMessage(), providerFqns.values().iterator().next()); + } + } + } + + private void generateLegacyRegistration(List instruments) { String filename = "META-INF/truffle/instrument"; Properties p = new SortedProperties(); int numInstruments = loadIfFileAlreadyExists(filename, p); @@ -196,33 +295,56 @@ static void loadExistingTypes(ProcessingEnvironment env, List instr @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { - if (roundEnv.processingOver()) { - generateFile(registrations); - registrations.clear(); - return true; - } - for (Element e : roundEnv.getElementsAnnotatedWith(Registration.class)) { - Registration annotation = e.getAnnotation(Registration.class); - if (annotation != null && e.getKind() == ElementKind.CLASS) { - if (!e.getModifiers().contains(Modifier.PUBLIC)) { - emitError("Registered instrument class must be public", e); - continue; - } - if (e.getEnclosingElement().getKind() != ElementKind.PACKAGE && !e.getModifiers().contains(Modifier.STATIC)) { - emitError("Registered instrument inner-class must be static", e); - continue; - } - TypeMirror truffleLang = processingEnv.getTypeUtils().erasure(ElementUtils.getTypeElement(processingEnv, TruffleInstrument.class.getName()).asType()); - if (!processingEnv.getTypeUtils().isAssignable(e.asType(), truffleLang)) { - emitError("Registered instrument class must subclass TruffleInstrument", e); - continue; + ProcessorContext.setThreadLocalInstance(new ProcessorContext(processingEnv, null)); + try { + if (roundEnv.processingOver()) { + generateServicesRegistration(registrations); + generateLegacyRegistration(legacyRegistrations); + registrations.clear(); + legacyRegistrations.clear(); + return true; + } + for (Element e : roundEnv.getElementsAnnotatedWith(Registration.class)) { + Registration annotation = e.getAnnotation(Registration.class); + if (annotation != null && e.getKind() == ElementKind.CLASS) { + if (!e.getModifiers().contains(Modifier.PUBLIC)) { + emitError("Registered instrument class must be public", e); + continue; + } + if (e.getEnclosingElement().getKind() != ElementKind.PACKAGE && !e.getModifiers().contains(Modifier.STATIC)) { + emitError("Registered instrument inner-class must be static", e); + continue; + } + TypeMirror truffleInstrument = ProcessorContext.getInstance().getType(TruffleInstrument.class); + TypeMirror truffleInstrumentProvider = ProcessorContext.getInstance().getType(TruffleInstrument.Provider.class); + boolean processingTruffleInstrument; + if (processingEnv.getTypeUtils().isAssignable(e.asType(), truffleInstrument)) { + processingTruffleInstrument = true; + } else if (processingEnv.getTypeUtils().isAssignable(e.asType(), truffleInstrumentProvider)) { + processingTruffleInstrument = false; + } else { + emitError("Registered instrument class must subclass TruffleInstrument", e); + continue; + } + assertNoErrorExpected(e); + if (processingTruffleInstrument) { + TypeElement languageTypeElement = (TypeElement) e; + if (requiresLegacyRegistration(languageTypeElement)) { + legacyRegistrations.add(languageTypeElement); + } else { + registrations.put(generateProvider(languageTypeElement), languageTypeElement); + } + } } - assertNoErrorExpected(e); - registrations.add((TypeElement) e); } + return true; + } finally { + ProcessorContext.setThreadLocalInstance(null); } + } - return true; + private static boolean requiresLegacyRegistration(TypeElement language) { + return language.getAnnotation(GenerateLegacyRegistration.class) != null; } void assertNoErrorExpected(Element e) { From 24a59923e5161d3ea2a773854d8aa0fe185d8ace Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Wed, 2 Oct 2019 09:41:46 +0200 Subject: [PATCH 077/140] [GR-15292] Fixed ServiceConfigurationError. --- .../src/com/oracle/truffle/polyglot/InstrumentCache.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java index 11328c2cd4df..0735fa63375f 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java @@ -213,6 +213,14 @@ static void load(ClassLoader loader, List list, Set truffleInstrumentClassAsSeenByLoader = Class.forName(TruffleInstrument.class.getName(), true, loader); + if (truffleInstrumentClassAsSeenByLoader != TruffleInstrument.class) { + return; + } + } catch (ClassNotFoundException ex) { + return; + } for (Loader instance : INSTANCES) { instance.loadImpl(loader, list, classNamesUsed); } From c83aa609f5607b31efec445426243095663e18dc Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Wed, 2 Oct 2019 15:46:14 +0200 Subject: [PATCH 078/140] [GR-15292] Introduced common super class for InstrumentRegistrationProcessor and LanguageRegistrationProcessor. --- .../AbstractRegistrationProcessor.java | 292 ++++++++++ .../InstrumentRegistrationProcessor.java | 279 ++-------- .../LanguageRegistrationProcessor.java | 527 ++++++------------ 3 files changed, 530 insertions(+), 568 deletions(-) create mode 100644 truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java new file mode 100644 index 000000000000..c1c910a77343 --- /dev/null +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2019, 2019, 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.dsl.processor; + +import com.oracle.truffle.dsl.processor.generator.GeneratorUtils; +import com.oracle.truffle.dsl.processor.java.ElementUtils; +import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; +import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; +import com.oracle.truffle.dsl.processor.java.transform.FixWarningsVisitor; +import com.oracle.truffle.dsl.processor.java.transform.GenerateOverrideVisitor; +import com.oracle.truffle.dsl.processor.model.Template; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TreeSet; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.FilerException; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.Elements; +import javax.tools.Diagnostic; +import javax.tools.Diagnostic.Kind; +import javax.tools.FileObject; +import javax.tools.StandardLocation; + +abstract class AbstractRegistrationProcessor extends AbstractProcessor { + + private final Map registrations = new HashMap<>(); + private final List legacyRegistrations = new ArrayList<>(); + + @Override + public final SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + @SuppressWarnings({"deprecation", "unchecked"}) + @Override + public final boolean process(Set annotations, RoundEnvironment roundEnv) { + ProcessorContext.setThreadLocalInstance(new ProcessorContext(processingEnv, null)); + try { + if (roundEnv.processingOver()) { + generateServicesRegistration(registrations); + generateLegacyRegistration(legacyRegistrations); + registrations.clear(); + legacyRegistrations.clear(); + return true; + } + String[] supportedAnnotations = this.getClass().getAnnotation(SupportedAnnotationTypes.class).value(); + Class registrationAnnotationClass; + try { + TypeElement supportedAnnotation = processingEnv.getElementUtils().getTypeElement(supportedAnnotations[0]); + if (supportedAnnotation == null) { + throw new IllegalStateException("Cannot resolve " + supportedAnnotations[0]); + } + registrationAnnotationClass = (Class) Class.forName(processingEnv.getElementUtils().getBinaryName(supportedAnnotation).toString()); + } catch (ClassNotFoundException cnf) { + throw new IllegalStateException(cnf); + } + TypeMirror registration = ProcessorContext.getInstance().getType(registrationAnnotationClass); + for (Element e : roundEnv.getElementsAnnotatedWith(registrationAnnotationClass)) { + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(e.getAnnotationMirrors(), registration); + Annotation annotation = e.getAnnotation(registrationAnnotationClass); + if (annotation != null && e.getKind() == ElementKind.CLASS) { + if (validateRegistration(e, mirror, annotation)) { + TypeElement annotatedElement = (TypeElement) e; + if (requiresLegacyRegistration(annotatedElement)) { + legacyRegistrations.add(annotatedElement); + } else { + registrations.put(generateProvider(annotatedElement), annotatedElement); + } + } + } + } + return true; + } finally { + ProcessorContext.setThreadLocalInstance(null); + } + } + + abstract boolean validateRegistration(Element annotatedElement, AnnotationMirror registrationMirror, Annotation registration); + + abstract Class getProviderClass(); + + abstract Iterable getProviderAnnotations(TypeElement annotatedElement); + + abstract void implementMethod(TypeElement annotatedElement, CodeExecutableElement methodToImplement); + + abstract String getRegistrationFileName(); + + abstract void storeRegistrations(Properties into, Iterable annotatedElements); + + final void assertNoErrorExpected(Element e) { + ExpectError.assertNoErrorExpected(processingEnv, e); + } + + final void emitError(String msg, Element e) { + if (ExpectError.isExpectedError(processingEnv, e, msg)) { + return; + } + processingEnv.getMessager().printMessage(Kind.ERROR, msg, e); + } + + final void emitError(String msg, Element e, AnnotationMirror mirror, AnnotationValue value) { + if (ExpectError.isExpectedError(processingEnv, e, msg)) { + return; + } + processingEnv.getMessager().printMessage(Kind.ERROR, msg, e, mirror, value); + } + + final void emitWarning(String msg, Element e) { + if (ExpectError.isExpectedError(processingEnv, e, msg)) { + return; + } + processingEnv.getMessager().printMessage(Kind.WARNING, msg, e); + } + + final void emitWarning(String msg, Element e, AnnotationMirror mirror, AnnotationValue value) { + if (ExpectError.isExpectedError(processingEnv, e, msg)) { + return; + } + processingEnv.getMessager().printMessage(Kind.WARNING, msg, e, mirror, value); + } + + private static boolean requiresLegacyRegistration(TypeElement annotatedElement) { + return annotatedElement.getAnnotation(GenerateLegacyRegistration.class) != null; + } + + private String generateProvider(TypeElement annotatedElement) { + ProcessorContext context = ProcessorContext.getInstance(); + Template model = new Template(context, annotatedElement, null) { + }; + TypeElement providerElement = context.getTypeElement(getProviderClass()); + CodeTypeElement providerClass = GeneratorUtils.createClass(model, null, EnumSet.of(Modifier.PUBLIC), + createProviderSimpleName(annotatedElement), null); + providerClass.getImplements().add(providerElement.asType()); + for (Element method : ElementFilter.methodsIn(providerElement.getEnclosedElements())) { + CodeExecutableElement implementedMethod = CodeExecutableElement.clone((ExecutableElement) method); + implementedMethod.getModifiers().remove(Modifier.ABSTRACT); + implementMethod(annotatedElement, implementedMethod); + providerClass.add(implementedMethod); + } + + for (AnnotationMirror annotationMirror : getProviderAnnotations(annotatedElement)) { + providerClass.addAnnotationMirror(annotationMirror); + } + DeclaredType overrideType = (DeclaredType) context.getType(Override.class); + providerClass.accept(new GenerateOverrideVisitor(overrideType), null); + providerClass.accept(new FixWarningsVisitor(annotatedElement, overrideType), null); + providerClass.accept(new CodeWriter(context.getEnvironment(), annotatedElement), null); + return providerClass.getQualifiedName().toString(); + } + + private static String createProviderSimpleName(TypeElement annotatedElement) { + StringBuilder nameBuilder = new StringBuilder(); + List hierarchy = ElementUtils.getElementHierarchy(annotatedElement); + for (ListIterator it = hierarchy.listIterator(hierarchy.size()); it.hasPrevious();) { + Element enc = it.previous(); + if (enc.getKind().isClass() || enc.getKind().isInterface()) { + nameBuilder.append(enc.getSimpleName()); + } + } + nameBuilder.append("Provider"); + return nameBuilder.toString(); + } + + private void generateServicesRegistration(Map providerFqns) { + ProcessorContext context = ProcessorContext.getInstance(); + ProcessingEnvironment env = context.getEnvironment(); + Elements elements = env.getElementUtils(); + Name providerBinName = elements.getBinaryName(context.getTypeElement(getProviderClass())); + String filename = "META-INF/services/" + providerBinName; + List providerClassNames = new ArrayList<>(providerFqns.size()); + for (String providerFqn : providerFqns.keySet()) { + TypeElement te = ElementUtils.getTypeElement(env, providerFqn); + providerClassNames.add(elements.getBinaryName(te).toString()); + } + Collections.sort(providerClassNames); + if (!providerClassNames.isEmpty()) { + try { + FileObject file = env.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, providerFqns.values().toArray(new Element[providerFqns.size()])); + try (PrintWriter out = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"))) { + out.println("# Generated by " + LanguageRegistrationProcessor.class.getName()); + for (String providerClassName : providerClassNames) { + out.println(providerClassName); + } + } + } catch (IOException e) { + if (e instanceof FilerException) { + if (e.getMessage().startsWith("Source file already created")) { + // ignore source file already created errors + return; + } + } + env.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage(), providerFqns.values().iterator().next()); + } + } + } + + private void generateLegacyRegistration(List annotatedElements) { + String filename = getRegistrationFileName(); + // sorted properties + Properties p = new SortedProperties(); + storeRegistrations(p, annotatedElements); + if (!p.isEmpty()) { + try { + FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, annotatedElements.toArray(new Element[0])); + try (OutputStream os = file.openOutputStream()) { + p.store(os, "Generated by " + getClass().getName()); + } + } catch (IOException e) { + if (e instanceof FilerException) { + if (e.getMessage().startsWith("Source file already created")) { + // ignore source file already created errors + return; + } + } + processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), annotatedElements.get(0)); + } + } + } + + @SuppressWarnings("serial") + static class SortedProperties extends Properties { + @Override + public synchronized Enumeration keys() { + return Collections.enumeration(new TreeSet<>(super.keySet())); + } + } +} diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java index 5b8f0c594564..f124f063ac26 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java @@ -41,21 +41,10 @@ package com.oracle.truffle.dsl.processor; import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.HashSet; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.Properties; -import java.util.Set; - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.SourceVersion; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; @@ -64,136 +53,90 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; -import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; -import javax.tools.Diagnostic.Kind; import javax.tools.FileObject; import javax.tools.StandardLocation; import com.oracle.truffle.api.instrumentation.TruffleInstrument; import com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration; -import com.oracle.truffle.dsl.processor.LanguageRegistrationProcessor.SortedProperties; -import com.oracle.truffle.dsl.processor.generator.GeneratorUtils; import com.oracle.truffle.dsl.processor.java.ElementUtils; import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; import com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder; -import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; -import com.oracle.truffle.dsl.processor.java.transform.FixWarningsVisitor; -import com.oracle.truffle.dsl.processor.java.transform.GenerateOverrideVisitor; -import com.oracle.truffle.dsl.processor.model.Template; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; +import java.lang.annotation.Annotation; import java.util.Collections; -import java.util.HashMap; -import javax.annotation.processing.FilerException; @SupportedAnnotationTypes("com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration") -public final class InstrumentRegistrationProcessor extends AbstractProcessor { - private final Map registrations = new HashMap<>(); - private final List legacyRegistrations = new ArrayList<>(); - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latest(); - } +public final class InstrumentRegistrationProcessor extends AbstractRegistrationProcessor { private static final int NUMBER_OF_PROPERTIES_PER_ENTRY = 4; - private static String generateProvider(TypeElement instrument) { - ProcessorContext context = ProcessorContext.getInstance(); - Elements elements = context.getEnvironment().getElementUtils(); - Template instrumentModel = new Template(context, instrument, null) { - }; - TypeElement providerElement = context.getTypeElement(TruffleInstrument.Provider.class); - CodeTypeElement providerClass = GeneratorUtils.createClass(instrumentModel, null, EnumSet.of(Modifier.PUBLIC), - createProviderSimpleName(instrument), null); - providerClass.getImplements().add(providerElement.asType()); - AnnotationMirror registration = ElementUtils.findAnnotationMirror(instrument.getAnnotationMirrors(), ProcessorContext.getInstance().getType(Registration.class)); - for (Element method : ElementFilter.methodsIn(providerElement.getEnclosedElements())) { - CodeExecutableElement implementedMethod = CodeExecutableElement.clone((ExecutableElement) method); - implementedMethod.getModifiers().remove(Modifier.ABSTRACT); - CodeTreeBuilder builder = implementedMethod.createBuilder(); - switch (method.getSimpleName().toString()) { - case "create": - builder.startReturn().startNew(instrument.asType()).end().end(); - break; - case "getInstrumentClassName": - builder.startReturn().doubleQuote(elements.getBinaryName(instrument).toString()).end(); - break; - default: - throw new IllegalStateException("Unsupported method: " + method.getSimpleName()); - } - providerClass.add(implementedMethod); + boolean validateRegistration(Element annotatedElement, AnnotationMirror registrationMirror, Annotation registration) { + if (!annotatedElement.getModifiers().contains(Modifier.PUBLIC)) { + emitError("Registered instrument class must be public", annotatedElement); + return false; + } + if (annotatedElement.getEnclosingElement().getKind() != ElementKind.PACKAGE && !annotatedElement.getModifiers().contains(Modifier.STATIC)) { + emitError("Registered instrument inner-class must be static", annotatedElement); + return false; } + TypeMirror truffleInstrument = ProcessorContext.getInstance().getType(TruffleInstrument.class); + TypeMirror truffleInstrumentProvider = ProcessorContext.getInstance().getType(TruffleInstrument.Provider.class); + boolean processingTruffleInstrument; + if (processingEnv.getTypeUtils().isAssignable(annotatedElement.asType(), truffleInstrument)) { + processingTruffleInstrument = true; + } else if (processingEnv.getTypeUtils().isAssignable(annotatedElement.asType(), truffleInstrumentProvider)) { + processingTruffleInstrument = false; + } else { + emitError("Registered instrument class must subclass TruffleInstrument", annotatedElement); + return false; + } + assertNoErrorExpected(annotatedElement); + return processingTruffleInstrument; + } - providerClass.addAnnotationMirror(registration); - DeclaredType overrideType = (DeclaredType) context.getType(Override.class); - providerClass.accept(new GenerateOverrideVisitor(overrideType), null); - providerClass.accept(new FixWarningsVisitor(instrument, overrideType), null); - providerClass.accept(new CodeWriter(context.getEnvironment(), instrument), null); - return providerClass.getQualifiedName().toString(); + @Override + Class getProviderClass() { + return TruffleInstrument.Provider.class; } - private static String createProviderSimpleName(TypeElement language) { - StringBuilder nameBuilder = new StringBuilder(); - List hierarchy = ElementUtils.getElementHierarchy(language); - for (ListIterator it = hierarchy.listIterator(hierarchy.size()); it.hasPrevious();) { - Element enc = it.previous(); - if (enc.getKind().isClass() || enc.getKind().isInterface()) { - nameBuilder.append(enc.getSimpleName()); - } - } - nameBuilder.append("Provider"); - return nameBuilder.toString(); + @Override + Iterable getProviderAnnotations(TypeElement annotatedElement) { + return Collections.singleton(ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(TruffleInstrument.Registration.class))); } - private static void generateServicesRegistration(Map providerFqns) { - ProcessorContext context = ProcessorContext.getInstance(); - ProcessingEnvironment env = context.getEnvironment(); - Elements elements = env.getElementUtils(); - Name providerBinName = elements.getBinaryName(context.getTypeElement(TruffleInstrument.Provider.class)); - String filename = "META-INF/services/" + providerBinName; - List providerClassNames = new ArrayList<>(providerFqns.size()); - for (String providerFqn : providerFqns.keySet()) { - TypeElement te = ElementUtils.getTypeElement(env, providerFqn); - providerClassNames.add(elements.getBinaryName(te).toString()); - } - Collections.sort(providerClassNames); - if (!providerClassNames.isEmpty()) { - try { - FileObject file = env.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, providerFqns.values().toArray(new Element[providerFqns.size()])); - try (PrintWriter out = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"))) { - out.println("# Generated by " + InstrumentRegistrationProcessor.class.getName()); - for (String providerClassName : providerClassNames) { - out.println(providerClassName); - } - } - } catch (IOException e) { - if (e instanceof FilerException) { - if (e.getMessage().startsWith("Source file already created")) { - // ignore source file already created errors - return; - } - } - env.getMessager().printMessage(Kind.ERROR, e.getMessage(), providerFqns.values().iterator().next()); - } + @Override + void implementMethod(TypeElement annotatedElement, CodeExecutableElement methodToImplement) { + CodeTreeBuilder builder = methodToImplement.createBuilder(); + switch (methodToImplement.getSimpleName().toString()) { + case "create": + builder.startReturn().startNew(annotatedElement.asType()).end().end(); + break; + case "getInstrumentClassName": + ProcessorContext context = ProcessorContext.getInstance(); + Elements elements = context.getEnvironment().getElementUtils(); + builder.startReturn().doubleQuote(elements.getBinaryName(annotatedElement).toString()).end(); + break; + default: + throw new IllegalStateException("Unsupported method: " + methodToImplement.getSimpleName()); } } - private void generateLegacyRegistration(List instruments) { - String filename = "META-INF/truffle/instrument"; - Properties p = new SortedProperties(); - int numInstruments = loadIfFileAlreadyExists(filename, p); + @Override + String getRegistrationFileName() { + return "META-INF/truffle/instrument"; + } + @Override + void storeRegistrations(Properties into, Iterable instruments) { + int numInstruments = loadIfFileAlreadyExists(getRegistrationFileName(), into); for (TypeElement l : instruments) { Registration annotation = l.getAnnotation(Registration.class); if (annotation == null) { continue; } - int instNum = findInstrument(annotation.id(), p); + int instNum = findInstrument(annotation.id(), into); if (instNum == 0) { // not found numInstruments += 1; instNum = numInstruments; @@ -202,11 +145,11 @@ private void generateLegacyRegistration(List instruments) { String prefix = "instrument" + instNum + "."; String className = processingEnv.getElementUtils().getBinaryName(l).toString(); - p.setProperty(prefix + "id", annotation.id()); - p.setProperty(prefix + "name", annotation.name()); - p.setProperty(prefix + "version", annotation.version()); - p.setProperty(prefix + "className", className); - p.setProperty(prefix + "internal", Boolean.toString(annotation.internal())); + into.setProperty(prefix + "id", annotation.id()); + into.setProperty(prefix + "name", annotation.name()); + into.setProperty(prefix + "version", annotation.version()); + into.setProperty(prefix + "className", className); + into.setProperty(prefix + "internal", Boolean.toString(annotation.internal())); int serviceCounter = 0; for (AnnotationMirror anno : l.getAnnotationMirrors()) { @@ -219,23 +162,13 @@ private void generateLegacyRegistration(List instruments) { List classes = (List) attrValue.getValue(); for (Object clazz : classes) { AnnotationValue clazzValue = (AnnotationValue) clazz; - p.setProperty(prefix + "service" + serviceCounter++, clazzValue.getValue().toString()); + into.setProperty(prefix + "service" + serviceCounter++, clazzValue.getValue().toString()); } } } } } } - if (numInstruments > 0) { - try { - FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename); - try (OutputStream os = file.openOutputStream()) { - p.store(os, "Generated by " + InstrumentRegistrationProcessor.class.getName()); - } - } catch (IOException e) { - processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), instruments.get(0)); - } - } } private static int findInstrument(String id, Properties p) { @@ -262,100 +195,4 @@ private int loadIfFileAlreadyExists(String filename, Properties p) { return 0; } } - - static void loadExistingTypes(ProcessingEnvironment env, List instruments, String filename, String pre) { - Set typeNames = new HashSet<>(); - for (TypeElement type : instruments) { - typeNames.add(ElementUtils.getQualifiedName(type)); - } - - Properties current = new Properties(); - try { - FileObject object = env.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", filename); - current.load(object.openInputStream()); - } catch (IOException e1) { - env.getMessager().printMessage(Kind.NOTE, filename + e1.getMessage(), null); - // does not exist yet. - // better way to detect this? - } - - for (int cnt = 1;; cnt++) { - String prefix = pre + cnt + "."; - String className = current.getProperty(prefix + "className"); - if (className == null) { - break; - } - env.getMessager().printMessage(Kind.NOTE, filename + className, null); - TypeElement foundType = ElementUtils.getTypeElement(env, className); - if (foundType != null && !typeNames.contains(ElementUtils.getQualifiedName(foundType))) { - instruments.add(foundType); - } - } - } - - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - ProcessorContext.setThreadLocalInstance(new ProcessorContext(processingEnv, null)); - try { - if (roundEnv.processingOver()) { - generateServicesRegistration(registrations); - generateLegacyRegistration(legacyRegistrations); - registrations.clear(); - legacyRegistrations.clear(); - return true; - } - for (Element e : roundEnv.getElementsAnnotatedWith(Registration.class)) { - Registration annotation = e.getAnnotation(Registration.class); - if (annotation != null && e.getKind() == ElementKind.CLASS) { - if (!e.getModifiers().contains(Modifier.PUBLIC)) { - emitError("Registered instrument class must be public", e); - continue; - } - if (e.getEnclosingElement().getKind() != ElementKind.PACKAGE && !e.getModifiers().contains(Modifier.STATIC)) { - emitError("Registered instrument inner-class must be static", e); - continue; - } - TypeMirror truffleInstrument = ProcessorContext.getInstance().getType(TruffleInstrument.class); - TypeMirror truffleInstrumentProvider = ProcessorContext.getInstance().getType(TruffleInstrument.Provider.class); - boolean processingTruffleInstrument; - if (processingEnv.getTypeUtils().isAssignable(e.asType(), truffleInstrument)) { - processingTruffleInstrument = true; - } else if (processingEnv.getTypeUtils().isAssignable(e.asType(), truffleInstrumentProvider)) { - processingTruffleInstrument = false; - } else { - emitError("Registered instrument class must subclass TruffleInstrument", e); - continue; - } - assertNoErrorExpected(e); - if (processingTruffleInstrument) { - TypeElement languageTypeElement = (TypeElement) e; - if (requiresLegacyRegistration(languageTypeElement)) { - legacyRegistrations.add(languageTypeElement); - } else { - registrations.put(generateProvider(languageTypeElement), languageTypeElement); - } - } - } - } - return true; - } finally { - ProcessorContext.setThreadLocalInstance(null); - } - } - - private static boolean requiresLegacyRegistration(TypeElement language) { - return language.getAnnotation(GenerateLegacyRegistration.class) != null; - } - - void assertNoErrorExpected(Element e) { - ExpectError.assertNoErrorExpected(processingEnv, e); - } - - void emitError(String msg, Element e) { - if (ExpectError.isExpectedError(processingEnv, e, msg)) { - return; - } - processingEnv.getMessager().printMessage(Kind.ERROR, msg, e); - } - } diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java index dba19a04de15..6e4fc9cc714e 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java @@ -41,403 +41,276 @@ package com.oracle.truffle.dsl.processor; import com.oracle.truffle.api.TruffleFile; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.EnumSet; -import java.util.Enumeration; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.ListIterator; -import java.util.Map; import java.util.Properties; import java.util.Set; -import java.util.TreeSet; - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.FilerException; -import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.SourceVersion; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; -import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeParameterElement; -import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; -import javax.tools.Diagnostic.Kind; -import javax.tools.FileObject; -import javax.tools.StandardLocation; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Registration; import com.oracle.truffle.api.instrumentation.ProvidedTags; -import com.oracle.truffle.dsl.processor.generator.GeneratorUtils; import com.oracle.truffle.dsl.processor.java.ElementUtils; import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; import com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder; -import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; -import com.oracle.truffle.dsl.processor.java.transform.FixWarningsVisitor; -import com.oracle.truffle.dsl.processor.java.transform.GenerateOverrideVisitor; -import com.oracle.truffle.dsl.processor.model.Template; +import java.lang.annotation.Annotation; @SupportedAnnotationTypes("com.oracle.truffle.api.TruffleLanguage.Registration") -public final class LanguageRegistrationProcessor extends AbstractProcessor { - private final Map registrations = new HashMap<>(); - private final List legacyRegistrations = new ArrayList<>(); +public final class LanguageRegistrationProcessor extends AbstractRegistrationProcessor { // also update list in PolyglotEngineImpl#RESERVED_IDS private static final Set RESERVED_IDS = new HashSet<>( Arrays.asList("host", "graal", "truffle", "language", "instrument", "graalvm", "context", "polyglot", "compiler", "vm", "engine", "log", "image-build-time")); - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latest(); - } + @SuppressWarnings("deprecation") + boolean validateRegistration(Element annotatedElement, AnnotationMirror registrationMirror, Annotation registration) { + if (!annotatedElement.getModifiers().contains(Modifier.PUBLIC)) { + emitError("Registered language class must be public", annotatedElement); + return false; + } + if (annotatedElement.getEnclosingElement().getKind() != ElementKind.PACKAGE && !annotatedElement.getModifiers().contains(Modifier.STATIC)) { + emitError("Registered language inner-class must be static", annotatedElement); + return false; + } + TypeMirror truffleLang = processingEnv.getTypeUtils().erasure(ElementUtils.getTypeElement(processingEnv, TruffleLanguage.class.getName()).asType()); + TypeMirror truffleLangProvider = ProcessorContext.getInstance().getType(TruffleLanguage.Provider.class); + boolean processingTruffleLanguage; + if (processingEnv.getTypeUtils().isAssignable(annotatedElement.asType(), truffleLang)) { + processingTruffleLanguage = true; + } else if (processingEnv.getTypeUtils().isAssignable(annotatedElement.asType(), truffleLangProvider)) { + processingTruffleLanguage = false; + } else { + emitError("Registered language class must subclass TruffleLanguage", annotatedElement); + return false; + } + boolean foundConstructor = false; + for (ExecutableElement constructor : ElementFilter.constructorsIn(annotatedElement.getEnclosedElements())) { + if (!constructor.getModifiers().contains(Modifier.PUBLIC)) { + continue; + } + if (!constructor.getParameters().isEmpty()) { + continue; + } + foundConstructor = true; + break; + } - private static String generateProvider(TypeElement language) { - ProcessorContext context = ProcessorContext.getInstance(); - Elements elements = context.getEnvironment().getElementUtils(); - Template languageModel = new Template(context, language, null) { - }; - TypeElement providerElement = context.getTypeElement(TruffleLanguage.Provider.class); - CodeTypeElement providerClass = GeneratorUtils.createClass(languageModel, null, EnumSet.of(Modifier.PUBLIC), - createProviderSimpleName(language), null); - providerClass.getImplements().add(providerElement.asType()); - AnnotationMirror registration = ElementUtils.findAnnotationMirror(language.getAnnotationMirrors(), ProcessorContext.getInstance().getType(Registration.class)); - for (Element method : ElementFilter.methodsIn(providerElement.getEnclosedElements())) { - CodeExecutableElement implementedMethod = CodeExecutableElement.clone((ExecutableElement) method); - implementedMethod.getModifiers().remove(Modifier.ABSTRACT); - CodeTreeBuilder builder = implementedMethod.createBuilder(); - switch (method.getSimpleName().toString()) { - case "create": - DeclaredType languageType = (DeclaredType) language.asType(); - List typeParams = language.getTypeParameters(); - if (!typeParams.isEmpty()) { - TypeMirror[] actualTypeParams = new TypeMirror[typeParams.size()]; - for (int i = 0; i < actualTypeParams.length; i++) { - actualTypeParams[i] = typeParams.get(i).getBounds().get(0); - } - languageType = context.getEnvironment().getTypeUtils().getDeclaredType(language, actualTypeParams); - } - builder.startReturn().startNew(languageType).end().end(); - break; + Element singletonElement = null; + for (Element mem : annotatedElement.getEnclosedElements()) { + if (!mem.getModifiers().contains(Modifier.PUBLIC)) { + continue; + } + if (mem.getKind() != ElementKind.FIELD) { + continue; + } + if (!mem.getModifiers().contains(Modifier.FINAL)) { + continue; + } + if (!"INSTANCE".equals(mem.getSimpleName().toString())) { + continue; + } + if (processingEnv.getTypeUtils().isAssignable(mem.asType(), truffleLang)) { + singletonElement = mem; + break; + } + } + boolean valid = true; - case "createFileTypeDetectors": - List detectors = ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "fileTypeDetectors"); - if (detectors.isEmpty()) { - builder.startReturn().startStaticCall(context.getType(Collections.class), "emptyList").end().end(); - } else { - String varName = "result"; - DeclaredType listOfDetectors = context.getEnvironment().getTypeUtils().getDeclaredType(context.getTypeElement(ArrayList.class), - context.getType(TruffleFile.FileTypeDetector.class)); - builder.declaration(listOfDetectors, varName, builder.create().startNew(listOfDetectors).end()); - for (TypeMirror detector : detectors) { - builder.startStatement().startCall(varName, "add").startNew(detector).end(3); - } - builder.startReturn().string(varName).end(); - } - break; - case "getLanguageClassName": - builder.startReturn().doubleQuote(elements.getBinaryName(language).toString()).end(); - break; - default: - throw new IllegalStateException("Unsupported method: " + method.getSimpleName()); + if (processingTruffleLanguage && singletonElement != null) { + emitWarning("Using a singleton field is deprecated. Please provide a public no-argument constructor instead.", singletonElement); + valid = false; + } else { + if (!foundConstructor) { + emitError("A TruffleLanguage subclass must have a public no argument constructor.", annotatedElement); + return false; } - providerClass.add(implementedMethod); } - providerClass.addAnnotationMirror(registration); - AnnotationMirror providedTags = ElementUtils.findAnnotationMirror(language.getAnnotationMirrors(), ProcessorContext.getInstance().getType(ProvidedTags.class)); - if (providedTags != null) { - providerClass.addAnnotationMirror(providedTags); + TruffleLanguage.Registration annotation = (TruffleLanguage.Registration) registration; + Set mimeTypes = new HashSet<>(); + if (!validateMimeTypes(mimeTypes, annotatedElement, registrationMirror, ElementUtils.getAnnotationValue(registrationMirror, "characterMimeTypes"), annotation.characterMimeTypes())) { + return false; + } + if (!validateMimeTypes(mimeTypes, annotatedElement, registrationMirror, ElementUtils.getAnnotationValue(registrationMirror, "byteMimeTypes"), annotation.byteMimeTypes())) { + return false; + } + + String defaultMimeType = annotation.defaultMimeType(); + if (mimeTypes.size() > 1 && (defaultMimeType == null || defaultMimeType.equals(""))) { + emitError("No defaultMimeType attribute specified. " + + "The defaultMimeType attribute needs to be specified if more than one MIME type was specified.", annotatedElement, + registrationMirror, ElementUtils.getAnnotationValue(registrationMirror, "defaultMimeType")); + return false; + } + + if (defaultMimeType != null && !defaultMimeType.equals("") && !mimeTypes.contains(defaultMimeType)) { + emitError("The defaultMimeType is not contained in the list of supported characterMimeTypes or byteMimeTypes. Add the specified default MIME type to" + + " character or byte MIME types to resolve this.", annotatedElement, + registrationMirror, ElementUtils.getAnnotationValue(registrationMirror, "defaultMimeType")); + return false; } - DeclaredType overrideType = (DeclaredType) context.getType(Override.class); - providerClass.accept(new GenerateOverrideVisitor(overrideType), null); - providerClass.accept(new FixWarningsVisitor(language, overrideType), null); - providerClass.accept(new CodeWriter(context.getEnvironment(), language), null); - return providerClass.getQualifiedName().toString(); - } - private static String createProviderSimpleName(TypeElement language) { - StringBuilder nameBuilder = new StringBuilder(); - List hierarchy = ElementUtils.getElementHierarchy(language); - for (ListIterator it = hierarchy.listIterator(hierarchy.size()); it.hasPrevious();) { - Element enc = it.previous(); - if (enc.getKind().isClass() || enc.getKind().isInterface()) { - nameBuilder.append(enc.getSimpleName()); + if (annotation.mimeType().length == 0) { + String id = annotation.id(); + if (id.isEmpty()) { + emitError("The attribute id is mandatory.", annotatedElement, registrationMirror, null); + return false; + } + if (RESERVED_IDS.contains(id)) { + emitError(String.format("Id '%s' is reserved for other use and must not be used as id.", id), annotatedElement, registrationMirror, + ElementUtils.getAnnotationValue(registrationMirror, "id")); + return false; } } - nameBuilder.append("Provider"); - return nameBuilder.toString(); + + if (!validateFileTypeDetectors(annotatedElement, registrationMirror)) { + return false; + } + + if (valid) { + assertNoErrorExpected(annotatedElement); + } + return processingTruffleLanguage; } - private static void generateServicesRegistration(Map providerFqns) { - ProcessorContext context = ProcessorContext.getInstance(); - ProcessingEnvironment env = context.getEnvironment(); - Elements elements = env.getElementUtils(); - Name providerBinName = elements.getBinaryName(context.getTypeElement(TruffleLanguage.Provider.class)); - String filename = "META-INF/services/" + providerBinName; - List providerClassNames = new ArrayList<>(providerFqns.size()); - for (String providerFqn : providerFqns.keySet()) { - TypeElement te = ElementUtils.getTypeElement(env, providerFqn); - providerClassNames.add(elements.getBinaryName(te).toString()); + @Override + Class getProviderClass() { + return TruffleLanguage.Provider.class; + } + + @Override + Iterable getProviderAnnotations(TypeElement annotatedElement) { + List result = new ArrayList<>(2); + result.add(ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(TruffleLanguage.Registration.class))); + AnnotationMirror providedTags = ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(ProvidedTags.class)); + if (providedTags != null) { + result.add(providedTags); } - Collections.sort(providerClassNames); - if (!providerClassNames.isEmpty()) { - try { - FileObject file = env.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, providerFqns.values().toArray(new Element[providerFqns.size()])); - try (PrintWriter out = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"))) { - out.println("# Generated by " + LanguageRegistrationProcessor.class.getName()); - for (String providerClassName : providerClassNames) { - out.println(providerClassName); + return result; + } + + @Override + void implementMethod(TypeElement annotatedElement, CodeExecutableElement methodToImplement) { + ProcessorContext context = ProcessorContext.getInstance(); + CodeTreeBuilder builder = methodToImplement.createBuilder(); + switch (methodToImplement.getSimpleName().toString()) { + case "create": + DeclaredType languageType = (DeclaredType) annotatedElement.asType(); + List typeParams = annotatedElement.getTypeParameters(); + if (!typeParams.isEmpty()) { + TypeMirror[] actualTypeParams = new TypeMirror[typeParams.size()]; + for (int i = 0; i < actualTypeParams.length; i++) { + actualTypeParams[i] = typeParams.get(i).getBounds().get(0); } + languageType = context.getEnvironment().getTypeUtils().getDeclaredType(annotatedElement, actualTypeParams); } - } catch (IOException e) { - if (e instanceof FilerException) { - if (e.getMessage().startsWith("Source file already created")) { - // ignore source file already created errors - return; + builder.startReturn().startNew(languageType).end().end(); + break; + + case "createFileTypeDetectors": + AnnotationMirror registration = ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(TruffleLanguage.Registration.class)); + List detectors = ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "fileTypeDetectors"); + if (detectors.isEmpty()) { + builder.startReturn().startStaticCall(context.getType(Collections.class), "emptyList").end().end(); + } else { + String varName = "result"; + DeclaredType listOfDetectors = context.getEnvironment().getTypeUtils().getDeclaredType(context.getTypeElement(ArrayList.class), + context.getType(TruffleFile.FileTypeDetector.class)); + builder.declaration(listOfDetectors, varName, builder.create().startNew(listOfDetectors).end()); + for (TypeMirror detector : detectors) { + builder.startStatement().startCall(varName, "add").startNew(detector).end(3); } + builder.startReturn().string(varName).end(); } - env.getMessager().printMessage(Kind.ERROR, e.getMessage(), providerFqns.values().iterator().next()); - } + break; + case "getLanguageClassName": + Elements elements = context.getEnvironment().getElementUtils(); + builder.startReturn().doubleQuote(elements.getBinaryName(annotatedElement).toString()).end(); + break; + default: + throw new IllegalStateException("Unsupported method: " + methodToImplement.getSimpleName()); } } + @Override + String getRegistrationFileName() { + return "META-INF/truffle/language"; + } + + @Override @SuppressWarnings("deprecation") - private void generateLegacyRegistration(List languages) { - String filename = "META-INF/truffle/language"; - // sorted properties - Properties p = new SortedProperties(); + void storeRegistrations(Properties into, Iterable annotatedElements) { int cnt = 0; - for (TypeElement l : languages) { - Registration annotation = l.getAnnotation(Registration.class); + for (TypeElement annotatedElement : annotatedElements) { + String prefix = "language" + ++cnt + "."; + Registration annotation = annotatedElement.getAnnotation(Registration.class); if (annotation == null) { - continue; + return; } - String prefix = "language" + ++cnt + "."; - String className = processingEnv.getElementUtils().getBinaryName(l).toString(); + String className = processingEnv.getElementUtils().getBinaryName(annotatedElement).toString(); String id = annotation.id(); if (id != null && !id.isEmpty()) { - p.setProperty(prefix + "id", id); + into.setProperty(prefix + "id", id); } - p.setProperty(prefix + "name", annotation.name()); - p.setProperty(prefix + "implementationName", annotation.implementationName()); - p.setProperty(prefix + "version", annotation.version()); - p.setProperty(prefix + "className", className); + into.setProperty(prefix + "name", annotation.name()); + into.setProperty(prefix + "implementationName", annotation.implementationName()); + into.setProperty(prefix + "version", annotation.version()); + into.setProperty(prefix + "className", className); if (!annotation.defaultMimeType().equals("")) { - p.setProperty(prefix + "defaultMimeType", annotation.defaultMimeType()); + into.setProperty(prefix + "defaultMimeType", annotation.defaultMimeType()); } String[] mimes = annotation.mimeType(); for (int i = 0; i < mimes.length; i++) { - p.setProperty(prefix + "mimeType." + i, mimes[i]); + into.setProperty(prefix + "mimeType." + i, mimes[i]); } String[] charMimes = annotation.characterMimeTypes(); Arrays.sort(charMimes); for (int i = 0; i < charMimes.length; i++) { - p.setProperty(prefix + "characterMimeType." + i, charMimes[i]); + into.setProperty(prefix + "characterMimeType." + i, charMimes[i]); } String[] byteMimes = annotation.byteMimeTypes(); Arrays.sort(byteMimes); for (int i = 0; i < byteMimes.length; i++) { - p.setProperty(prefix + "byteMimeType." + i, byteMimes[i]); + into.setProperty(prefix + "byteMimeType." + i, byteMimes[i]); } String[] dependencies = annotation.dependentLanguages(); Arrays.sort(dependencies); for (int i = 0; i < dependencies.length; i++) { - p.setProperty(prefix + "dependentLanguage." + i, dependencies[i]); + into.setProperty(prefix + "dependentLanguage." + i, dependencies[i]); } - p.setProperty(prefix + "interactive", Boolean.toString(annotation.interactive())); - p.setProperty(prefix + "internal", Boolean.toString(annotation.internal())); + into.setProperty(prefix + "interactive", Boolean.toString(annotation.interactive())); + into.setProperty(prefix + "internal", Boolean.toString(annotation.internal())); - AnnotationMirror registration = ElementUtils.findAnnotationMirror(l.getAnnotationMirrors(), ProcessorContext.getInstance().getType(Registration.class)); + AnnotationMirror registration = ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(Registration.class)); int serviceCounter = 0; for (TypeMirror serviceTypeMirror : ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "services")) { - p.setProperty(prefix + "service" + serviceCounter++, processingEnv.getElementUtils().getBinaryName(ElementUtils.fromTypeMirror(serviceTypeMirror)).toString()); + into.setProperty(prefix + "service" + serviceCounter++, processingEnv.getElementUtils().getBinaryName(ElementUtils.fromTypeMirror(serviceTypeMirror)).toString()); } int fileTypeDetectorCounter = 0; for (TypeMirror fileTypeDetectorTypeMirror : ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "fileTypeDetectors")) { - p.setProperty(prefix + "fileTypeDetector" + fileTypeDetectorCounter++, + into.setProperty(prefix + "fileTypeDetector" + fileTypeDetectorCounter++, processingEnv.getElementUtils().getBinaryName(ElementUtils.fromTypeMirror(fileTypeDetectorTypeMirror)).toString()); } } - if (cnt > 0) { - try { - FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, languages.toArray(new Element[0])); - try (OutputStream os = file.openOutputStream()) { - p.store(os, "Generated by " + LanguageRegistrationProcessor.class.getName()); - } - } catch (IOException e) { - if (e instanceof FilerException) { - if (e.getMessage().startsWith("Source file already created")) { - // ignore source file already created errors - return; - } - } - processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), languages.get(0)); - } - } - } - - @SuppressWarnings("deprecation") - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - ProcessorContext.setThreadLocalInstance(new ProcessorContext(processingEnv, null)); - try { - if (roundEnv.processingOver()) { - generateServicesRegistration(registrations); - generateLegacyRegistration(legacyRegistrations); - registrations.clear(); - legacyRegistrations.clear(); - return true; - } - - TypeMirror registration = ProcessorContext.getInstance().getType(Registration.class); - for (Element e : roundEnv.getElementsAnnotatedWith(Registration.class)) { - AnnotationMirror mirror = ElementUtils.findAnnotationMirror(e.getAnnotationMirrors(), registration); - Registration annotation = e.getAnnotation(Registration.class); - if (annotation != null && e.getKind() == ElementKind.CLASS) { - if (!e.getModifiers().contains(Modifier.PUBLIC)) { - emitError("Registered language class must be public", e); - continue; - } - if (e.getEnclosingElement().getKind() != ElementKind.PACKAGE && !e.getModifiers().contains(Modifier.STATIC)) { - emitError("Registered language inner-class must be static", e); - continue; - } - TypeMirror truffleLang = processingEnv.getTypeUtils().erasure(ElementUtils.getTypeElement(processingEnv, TruffleLanguage.class.getName()).asType()); - TypeMirror truffleLangProvider = ProcessorContext.getInstance().getType(TruffleLanguage.Provider.class); - boolean processingTruffleLanguage; - if (processingEnv.getTypeUtils().isAssignable(e.asType(), truffleLang)) { - processingTruffleLanguage = true; - } else if (processingEnv.getTypeUtils().isAssignable(e.asType(), truffleLangProvider)) { - processingTruffleLanguage = false; - } else { - emitError("Registered language class must subclass TruffleLanguage", e); - continue; - } - boolean foundConstructor = false; - for (ExecutableElement constructor : ElementFilter.constructorsIn(e.getEnclosedElements())) { - if (!constructor.getModifiers().contains(Modifier.PUBLIC)) { - continue; - } - if (!constructor.getParameters().isEmpty()) { - continue; - } - foundConstructor = true; - break; - } - - Element singletonElement = null; - for (Element mem : e.getEnclosedElements()) { - if (!mem.getModifiers().contains(Modifier.PUBLIC)) { - continue; - } - if (mem.getKind() != ElementKind.FIELD) { - continue; - } - if (!mem.getModifiers().contains(Modifier.FINAL)) { - continue; - } - if (!"INSTANCE".equals(mem.getSimpleName().toString())) { - continue; - } - if (processingEnv.getTypeUtils().isAssignable(mem.asType(), truffleLang)) { - singletonElement = mem; - break; - } - } - boolean valid = true; - - if (processingTruffleLanguage && singletonElement != null) { - emitWarning("Using a singleton field is deprecated. Please provide a public no-argument constructor instead.", singletonElement); - valid = false; - } else { - if (!foundConstructor) { - emitError("A TruffleLanguage subclass must have a public no argument constructor.", e); - continue; - } - } - - Set mimeTypes = new HashSet<>(); - if (!validateMimeTypes(mimeTypes, e, mirror, ElementUtils.getAnnotationValue(mirror, "characterMimeTypes"), annotation.characterMimeTypes())) { - continue; - } - if (!validateMimeTypes(mimeTypes, e, mirror, ElementUtils.getAnnotationValue(mirror, "byteMimeTypes"), annotation.byteMimeTypes())) { - continue; - } - - String defaultMimeType = annotation.defaultMimeType(); - if (mimeTypes.size() > 1 && (defaultMimeType == null || defaultMimeType.equals(""))) { - emitError("No defaultMimeType attribute specified. " + - "The defaultMimeType attribute needs to be specified if more than one MIME type was specified.", e, - mirror, ElementUtils.getAnnotationValue(mirror, "defaultMimeType")); - continue; - } - - if (defaultMimeType != null && !defaultMimeType.equals("") && !mimeTypes.contains(defaultMimeType)) { - emitError("The defaultMimeType is not contained in the list of supported characterMimeTypes or byteMimeTypes. Add the specified default MIME type to" + - " character or byte MIME types to resolve this.", e, - mirror, ElementUtils.getAnnotationValue(mirror, "defaultMimeType")); - continue; - } - - if (annotation.mimeType().length == 0) { - String id = annotation.id(); - if (id.isEmpty()) { - emitError("The attribute id is mandatory.", e, mirror, null); - continue; - } - if (RESERVED_IDS.contains(id)) { - emitError(String.format("Id '%s' is reserved for other use and must not be used as id.", id), e, mirror, ElementUtils.getAnnotationValue(mirror, "id")); - continue; - } - } - - if (!validateFileTypeDetectors(e, mirror)) { - continue; - } - - if (valid) { - assertNoErrorExpected(e); - } - if (processingTruffleLanguage) { - TypeElement languageTypeElement = (TypeElement) e; - if (requiresLegacyRegistration(languageTypeElement)) { - legacyRegistrations.add(languageTypeElement); - } else { - registrations.put(generateProvider(languageTypeElement), languageTypeElement); - } - } - } - } - - return true; - } finally { - ProcessorContext.setThreadLocalInstance(null); - } - } - - private static boolean requiresLegacyRegistration(TypeElement language) { - return language.getAnnotation(GenerateLegacyRegistration.class) != null; } private boolean validateMimeTypes(Set collectedMimeTypes, Element e, AnnotationMirror mirror, AnnotationValue value, String[] loadedMimeTypes) { @@ -498,44 +371,4 @@ private boolean validateFileTypeDetectors(Element annotatedElement, AnnotationMi } return true; } - - void assertNoErrorExpected(Element e) { - ExpectError.assertNoErrorExpected(processingEnv, e); - } - - void emitError(String msg, Element e) { - if (ExpectError.isExpectedError(processingEnv, e, msg)) { - return; - } - processingEnv.getMessager().printMessage(Kind.ERROR, msg, e); - } - - void emitError(String msg, Element e, AnnotationMirror mirror, AnnotationValue value) { - if (ExpectError.isExpectedError(processingEnv, e, msg)) { - return; - } - processingEnv.getMessager().printMessage(Kind.ERROR, msg, e, mirror, value); - } - - void emitWarning(String msg, Element e) { - if (ExpectError.isExpectedError(processingEnv, e, msg)) { - return; - } - processingEnv.getMessager().printMessage(Kind.WARNING, msg, e); - } - - void emitWarning(String msg, Element e, AnnotationMirror mirror, AnnotationValue value) { - if (ExpectError.isExpectedError(processingEnv, e, msg)) { - return; - } - processingEnv.getMessager().printMessage(Kind.WARNING, msg, e, mirror, value); - } - - @SuppressWarnings("serial") - static class SortedProperties extends Properties { - @Override - public synchronized Enumeration keys() { - return Collections.enumeration(new TreeSet<>(super.keySet())); - } - } } From a7940ad3b347139afbad91244a34923000aad610 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Wed, 2 Oct 2019 18:36:28 +0200 Subject: [PATCH 079/140] [GR-15292] Fixed compiler warnings. --- .../InstrumentRegistrationProcessor.java | 1 + .../LanguageRegistrationProcessor.java | 22 +++++++------------ .../truffle/polyglot/InstrumentCache.java | 4 ++-- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java index f124f063ac26..538ae34fb21f 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java @@ -71,6 +71,7 @@ public final class InstrumentRegistrationProcessor extends AbstractRegistrationP private static final int NUMBER_OF_PROPERTIES_PER_ENTRY = 4; + @Override boolean validateRegistration(Element annotatedElement, AnnotationMirror registrationMirror, Annotation registration) { if (!annotatedElement.getModifiers().contains(Modifier.PUBLIC)) { emitError("Registered instrument class must be public", annotatedElement); diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java index 6e4fc9cc714e..47a0374c3fc4 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java @@ -40,7 +40,6 @@ */ package com.oracle.truffle.dsl.processor; -import com.oracle.truffle.api.TruffleFile; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -79,6 +78,7 @@ public final class LanguageRegistrationProcessor extends AbstractRegistrationPro "engine", "log", "image-build-time")); @SuppressWarnings("deprecation") + @Override boolean validateRegistration(Element annotatedElement, AnnotationMirror registrationMirror, Annotation registration) { if (!annotatedElement.getModifiers().contains(Modifier.PUBLIC)) { emitError("Registered language class must be public", annotatedElement); @@ -214,29 +214,23 @@ void implementMethod(TypeElement annotatedElement, CodeExecutableElement methodT DeclaredType languageType = (DeclaredType) annotatedElement.asType(); List typeParams = annotatedElement.getTypeParameters(); if (!typeParams.isEmpty()) { - TypeMirror[] actualTypeParams = new TypeMirror[typeParams.size()]; - for (int i = 0; i < actualTypeParams.length; i++) { - actualTypeParams[i] = typeParams.get(i).getBounds().get(0); - } - languageType = context.getEnvironment().getTypeUtils().getDeclaredType(annotatedElement, actualTypeParams); + builder.startReturn().string("new " + annotatedElement.getQualifiedName() + "<>()").end(); + } else { + builder.startReturn().startNew(languageType).end(2); } - builder.startReturn().startNew(languageType).end().end(); break; - case "createFileTypeDetectors": AnnotationMirror registration = ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(TruffleLanguage.Registration.class)); List detectors = ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "fileTypeDetectors"); if (detectors.isEmpty()) { builder.startReturn().startStaticCall(context.getType(Collections.class), "emptyList").end().end(); } else { - String varName = "result"; - DeclaredType listOfDetectors = context.getEnvironment().getTypeUtils().getDeclaredType(context.getTypeElement(ArrayList.class), - context.getType(TruffleFile.FileTypeDetector.class)); - builder.declaration(listOfDetectors, varName, builder.create().startNew(listOfDetectors).end()); + builder.startReturn(); + builder.startStaticCall(context.getType(Arrays.class), "asList"); for (TypeMirror detector : detectors) { - builder.startStatement().startCall(varName, "add").startNew(detector).end(3); + builder.startGroup().startNew(detector).end(2); } - builder.startReturn().string(varName).end(); + builder.end(2); } break; case "getLanguageClassName": diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java index 0735fa63375f..cf34e7c02b58 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java @@ -191,7 +191,7 @@ private abstract static class InstrumentReflection { abstract Class aotInitializeAtBuildTime(); - final void exportTruffle(ClassLoader loader) { + static void exportTruffle(ClassLoader loader) { if (!TruffleOptions.AOT) { // In JDK 9+, the Truffle API packages must be dynamically exported to // a Truffle instrument since the Truffle API module descriptor only @@ -277,7 +277,7 @@ void loadImpl(ClassLoader loader, List list, Set Date: Thu, 3 Oct 2019 17:35:45 +0200 Subject: [PATCH 080/140] [GR-15292] Fixed review comments. --- truffle/mx.truffle/suite.py | 2 + .../processor/LanguageRegistrationTest.java | 4 +- .../instrumentation/TruffleInstrument.java | 8 ++++ .../oracle/truffle/api/TruffleLanguage.java | 7 +++ .../AbstractRegistrationProcessor.java | 22 ++++++++- .../processor/GenerateLegacyRegistration.java | 48 ------------------- .../InstrumentRegistrationProcessor.java | 38 +++++++++++++-- .../LanguageRegistrationProcessor.java | 37 ++++++++++++-- .../truffle/polyglot/InstrumentCache.java | 29 +++++------ .../truffle/polyglot/LanguageCache.java | 33 +++++-------- 10 files changed, 133 insertions(+), 95 deletions(-) delete mode 100644 truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/GenerateLegacyRegistration.java diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 27f58c6f0798..cbf5bdd49265 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -756,6 +756,8 @@ "com.oracle.truffle.api.TruffleRuntimeAccess", "java.nio.file.spi.FileTypeDetector", "com.oracle.truffle.api.impl.TruffleLocator", + "com.oracle.truffle.api.TruffleLanguage.Provider", + "com.oracle.truffle.api.instrumentation.TruffleInstrument.Provider" ], }, "moduleInfo:open" : { diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java index adbb2b8ae4d0..b2c71f1f9e45 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java @@ -49,7 +49,6 @@ import com.oracle.truffle.api.dsl.test.ExpectError; import com.oracle.truffle.api.test.polyglot.ProxyLanguage; import com.oracle.truffle.api.TruffleFile.FileTypeDetector; -import com.oracle.truffle.dsl.processor.GenerateLegacyRegistration; import java.nio.charset.Charset; import java.util.Collections; import org.graalvm.polyglot.Engine; @@ -179,6 +178,9 @@ public Detector(String name) { } } + @interface GenerateLegacyRegistration { + } + @GenerateLegacyRegistration @Registration(id = "legacyregistration1", name = "LegacyRegistration1", implementationName = "legacy.registration1", version = "1.0.0", characterMimeTypes = "text/x-legacyregistration1") public static class LegacyRegistration1 extends ProxyLanguage { 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 0d6c2520b898..9d7a1c8a6a6b 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 @@ -50,6 +50,7 @@ import java.net.URI; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; @@ -857,6 +858,13 @@ public interface Provider { * @since 19.3.0 */ TruffleInstrument create(); + + /** + * Returns the class names of provided services. + * + * @since 19.3.0 + */ + Collection getServicesClassNames(); } static { 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 6afc5a401d1f..162ca8306ee1 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 @@ -485,6 +485,13 @@ public interface Provider { * @since 19.3.0 */ List createFileTypeDetectors(); + + /** + * Returns the class names of provided services. + * + * @since 19.3.0 + */ + Collection getServicesClassNames(); } /** diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java index c1c910a77343..500db0fd6b7c 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java @@ -42,6 +42,7 @@ import com.oracle.truffle.dsl.processor.generator.GeneratorUtils; import com.oracle.truffle.dsl.processor.java.ElementUtils; +import com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror; import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; import com.oracle.truffle.dsl.processor.java.transform.FixWarningsVisitor; @@ -63,6 +64,7 @@ import java.util.Properties; import java.util.Set; import java.util.TreeSet; +import java.util.function.Predicate; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.FilerException; import javax.annotation.processing.ProcessingEnvironment; @@ -184,8 +186,26 @@ final void emitWarning(String msg, Element e, AnnotationMirror mirror, Annotatio processingEnv.getMessager().printMessage(Kind.WARNING, msg, e, mirror, value); } + static AnnotationMirror copyAnnotations(AnnotationMirror mirror, Predicate filter) { + CodeAnnotationMirror res = new CodeAnnotationMirror(mirror.getAnnotationType()); + for (Map.Entry e : mirror.getElementValues().entrySet()) { + ExecutableElement executable = e.getKey(); + AnnotationValue value = e.getValue(); + if (filter.test(executable)) { + res.setElementValue(executable, value); + } + } + return res; + } + private static boolean requiresLegacyRegistration(TypeElement annotatedElement) { - return annotatedElement.getAnnotation(GenerateLegacyRegistration.class) != null; + for (AnnotationMirror mirror : annotatedElement.getAnnotationMirrors()) { + Element annotationType = mirror.getAnnotationType().asElement(); + if ("GenerateLegacyRegistration".contentEquals(annotationType.getSimpleName())) { + return true; + } + } + return false; } private String generateProvider(TypeElement annotatedElement) { diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/GenerateLegacyRegistration.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/GenerateLegacyRegistration.java deleted file mode 100644 index 35977edc9bb4..000000000000 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/GenerateLegacyRegistration.java +++ /dev/null @@ -1,48 +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. - * - * 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.dsl.processor; - -/** - * Not an API. Will be removed when a support for reading legacy TruffleLanguage and - * TruffleInstrument registrations is removed. - */ -public @interface GenerateLegacyRegistration { -} diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java index 538ae34fb21f..318137f9d2eb 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentRegistrationProcessor.java @@ -41,6 +41,8 @@ package com.oracle.truffle.dsl.processor; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; @@ -53,8 +55,10 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; import javax.tools.FileObject; import javax.tools.StandardLocation; @@ -64,7 +68,7 @@ import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; import com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder; import java.lang.annotation.Annotation; -import java.util.Collections; +import java.util.function.Predicate; @SupportedAnnotationTypes("com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration") public final class InstrumentRegistrationProcessor extends AbstractRegistrationProcessor { @@ -103,7 +107,15 @@ Class getProviderClass() { @Override Iterable getProviderAnnotations(TypeElement annotatedElement) { - return Collections.singleton(ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(TruffleInstrument.Registration.class))); + DeclaredType registrationType = (DeclaredType) ProcessorContext.getInstance().getType(TruffleInstrument.Registration.class); + AnnotationMirror registration = copyAnnotations(ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), registrationType), + new Predicate() { + @Override + public boolean test(ExecutableElement t) { + return !"services".contentEquals(t.getSimpleName()); + } + }); + return Collections.singleton(registration); } @Override @@ -113,11 +125,31 @@ void implementMethod(TypeElement annotatedElement, CodeExecutableElement methodT case "create": builder.startReturn().startNew(annotatedElement.asType()).end().end(); break; - case "getInstrumentClassName": + case "getInstrumentClassName": { ProcessorContext context = ProcessorContext.getInstance(); Elements elements = context.getEnvironment().getElementUtils(); builder.startReturn().doubleQuote(elements.getBinaryName(annotatedElement).toString()).end(); break; + } + case "getServicesClassNames": { + ProcessorContext context = ProcessorContext.getInstance(); + AnnotationMirror registration = ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), + ProcessorContext.getInstance().getType(TruffleInstrument.Registration.class)); + List services = ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "services"); + if (services.isEmpty()) { + builder.startReturn().startStaticCall(context.getType(Collections.class), "emptySet").end().end(); + } else { + builder.startReturn(); + builder.startStaticCall(context.getType(Arrays.class), "asList"); + for (TypeMirror service : services) { + Elements elements = context.getEnvironment().getElementUtils(); + Types types = context.getEnvironment().getTypeUtils(); + builder.startGroup().doubleQuote(elements.getBinaryName((TypeElement) ((DeclaredType) types.erasure(service)).asElement()).toString()).end(); + } + builder.end(2); + } + break; + } default: throw new IllegalStateException("Unsupported method: " + methodToImplement.getSimpleName()); } diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java index 47a0374c3fc4..7811dc1435e4 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java @@ -40,6 +40,7 @@ */ package com.oracle.truffle.dsl.processor; +import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -60,6 +61,7 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Registration; @@ -67,7 +69,7 @@ import com.oracle.truffle.dsl.processor.java.ElementUtils; import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; import com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder; -import java.lang.annotation.Annotation; +import java.util.function.Predicate; @SupportedAnnotationTypes("com.oracle.truffle.api.TruffleLanguage.Registration") public final class LanguageRegistrationProcessor extends AbstractRegistrationProcessor { @@ -197,7 +199,15 @@ Class getProviderClass() { @Override Iterable getProviderAnnotations(TypeElement annotatedElement) { List result = new ArrayList<>(2); - result.add(ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(TruffleLanguage.Registration.class))); + DeclaredType registrationType = (DeclaredType) ProcessorContext.getInstance().getType(TruffleLanguage.Registration.class); + AnnotationMirror registration = copyAnnotations(ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), registrationType), + new Predicate() { + @Override + public boolean test(ExecutableElement t) { + return !"services".contentEquals(t.getSimpleName()) && !"fileTypeDetectors".contentEquals(t.getSimpleName()); + } + }); + result.add(registration); AnnotationMirror providedTags = ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(ProvidedTags.class)); if (providedTags != null) { result.add(providedTags); @@ -219,7 +229,7 @@ void implementMethod(TypeElement annotatedElement, CodeExecutableElement methodT builder.startReturn().startNew(languageType).end(2); } break; - case "createFileTypeDetectors": + case "createFileTypeDetectors": { AnnotationMirror registration = ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(TruffleLanguage.Registration.class)); List detectors = ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "fileTypeDetectors"); if (detectors.isEmpty()) { @@ -233,10 +243,29 @@ void implementMethod(TypeElement annotatedElement, CodeExecutableElement methodT builder.end(2); } break; - case "getLanguageClassName": + } + case "getLanguageClassName": { Elements elements = context.getEnvironment().getElementUtils(); builder.startReturn().doubleQuote(elements.getBinaryName(annotatedElement).toString()).end(); break; + } + case "getServicesClassNames": { + AnnotationMirror registration = ElementUtils.findAnnotationMirror(annotatedElement.getAnnotationMirrors(), ProcessorContext.getInstance().getType(TruffleLanguage.Registration.class)); + List services = ElementUtils.getAnnotationValueList(TypeMirror.class, registration, "services"); + if (services.isEmpty()) { + builder.startReturn().startStaticCall(context.getType(Collections.class), "emptySet").end().end(); + } else { + builder.startReturn(); + builder.startStaticCall(context.getType(Arrays.class), "asList"); + for (TypeMirror service : services) { + Elements elements = context.getEnvironment().getElementUtils(); + Types types = context.getEnvironment().getTypeUtils(); + builder.startGroup().doubleQuote(elements.getBinaryName((TypeElement) ((DeclaredType) types.erasure(service)).asElement()).toString()).end(); + } + builder.end(2); + } + break; + } default: throw new IllegalStateException("Unsupported method: " + methodToImplement.getSimpleName()); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java index cf34e7c02b58..3cb98f9a5de0 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java @@ -63,7 +63,6 @@ import com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration; import java.util.Objects; import java.util.ServiceLoader; -import java.util.concurrent.atomic.AtomicBoolean; //TODO (chumer): maybe this class should share some code with LanguageCache? final class InstrumentCache { @@ -204,11 +203,6 @@ static void exportTruffle(ClassLoader loader) { private abstract static class Loader { - private static final Loader[] INSTANCES = new Loader[]{ - new LegacyLoader(), - new ServicesLoader() - }; - static void load(ClassLoader loader, List list, Set classNamesUsed) { if (loader == null) { return; @@ -221,9 +215,8 @@ static void load(ClassLoader loader, List list, Set list, Set classNamesUsed); @@ -240,6 +233,11 @@ static String defaultId(String className) { private static final class LegacyLoader extends Loader { + static final Loader INSTANCE = new LegacyLoader(); + + private LegacyLoader() { + } + @Override void loadImpl(ClassLoader loader, List list, Set classNamesUsed) { Enumeration en; @@ -359,7 +357,9 @@ private void initializeInstrumentClass() { private static final class ServicesLoader extends Loader { - ServicesLoader() { + static final Loader INSTANCE = new ServicesLoader(); + + private ServicesLoader() { } @Override @@ -380,8 +380,8 @@ void loadImpl(ClassLoader loader, List list, Set servicesClassNames = new TreeSet<>(); - for (Class service : reg.services()) { - servicesClassNames.add(service.getCanonicalName()); + for (String service : provider.getServicesClassNames()) { + servicesClassNames.add(service); } // we don't want multiple instruments with the same class name if (!classNamesUsed.contains(className)) { @@ -395,18 +395,15 @@ void loadImpl(ClassLoader loader, List list, Set into) { if (loader == null) { return; @@ -490,9 +484,8 @@ static void load(ClassLoader loader, Collection into) { } catch (ClassNotFoundException ex) { return; } - for (Loader loaderImpl : LOADERS) { - loaderImpl.loadImpl(loader, into); - } + LegacyLoader.INSTANCE.loadImpl(loader, into); + ServicesLoader.INSTANCE.loadImpl(loader, into); } abstract void loadImpl(ClassLoader loader, Collection into); @@ -549,7 +542,9 @@ static String getLanguageHomeFromURLConnection(URLConnection connection) { private static final class LegacyLoader extends Loader { - LegacyLoader() { + static final Loader INSTANCE = new LegacyLoader(); + + private LegacyLoader() { } @Override @@ -790,7 +785,9 @@ private void initializeFileTypeDetectors() { private static final class ServicesLoader extends Loader { - ServicesLoader() { + static final Loader INSTANCE = new ServicesLoader(); + + private ServicesLoader() { } @Override @@ -836,8 +833,8 @@ public void loadImpl(ClassLoader loader, Collection into) boolean interactive = reg.interactive(); boolean internal = reg.internal(); Set servicesClassNames = new TreeSet<>(); - for (Class service : reg.services()) { - servicesClassNames.add(service.getCanonicalName()); + for (String service : provider.getServicesClassNames()) { + servicesClassNames.add(service); } LanguageReflection reflection = new ServiceLoaderLanguageReflection(provider, reg.contextPolicy()); into.add(new LanguageCache(id, name, implementationName, version, className, languageHome, @@ -855,7 +852,6 @@ private static final class ServiceLoaderLanguageReflection extends LanguageRefle private final TruffleLanguage.Provider provider; private final ContextPolicy contextPolicy; - private final AtomicBoolean exported = new AtomicBoolean(); private volatile Set> providedTags; private volatile List fileTypeDetectors; @@ -864,11 +860,11 @@ private static final class ServiceLoaderLanguageReflection extends LanguageRefle assert contextPolicy != null; this.provider = provider; this.contextPolicy = contextPolicy; + exportTruffle(provider.getClass().getClassLoader()); } @Override TruffleLanguage newInstance() { - exportTruffleIfNeeded(); return provider.create(); } @@ -876,7 +872,6 @@ TruffleLanguage newInstance() { List getFileTypeDetectors() { List result = fileTypeDetectors; if (result == null) { - exportTruffleIfNeeded(); result = provider.createFileTypeDetectors(); fileTypeDetectors = result; } @@ -924,12 +919,6 @@ URL getCodeSource() { CodeSource source = provider.getClass().getProtectionDomain().getCodeSource(); return source != null ? source.getLocation() : null; } - - private void exportTruffleIfNeeded() { - if (exported.compareAndSet(false, true)) { - exportTruffle(provider.getClass().getClassLoader()); - } - } } } } From 47c0550d21b4e2a1c426bfd73788acbddc56006c Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Fri, 4 Oct 2019 11:39:22 +0200 Subject: [PATCH 081/140] [GR-15292] The mx incorrectly handles comments in service files. --- .../truffle/dsl/processor/AbstractRegistrationProcessor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java index 500db0fd6b7c..c4e88111c9e7 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractRegistrationProcessor.java @@ -262,7 +262,6 @@ private void generateServicesRegistration(Map pro try { FileObject file = env.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, providerFqns.values().toArray(new Element[providerFqns.size()])); try (PrintWriter out = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"))) { - out.println("# Generated by " + LanguageRegistrationProcessor.class.getName()); for (String providerClassName : providerClassNames) { out.println(providerClassName); } From eadd564430d563baf138eaec9a0319ae47bc2453 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Fri, 4 Oct 2019 15:55:49 +0200 Subject: [PATCH 082/140] [GR-15292] Fixed nfi module-info. --- truffle/mx.truffle/suite.py | 5 ++++ .../truffle/polyglot/InstrumentCache.java | 22 ++++++++--------- .../truffle/polyglot/LanguageCache.java | 24 +++++++++---------- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index cbf5bdd49265..ec3b6e4365a4 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -812,6 +812,11 @@ # This distribution defines a module. "moduleInfo" : { "name" : "com.oracle.truffle.truffle_nfi", + "requiresConcealed" : { + "org.graalvm.truffle" : [ + "com.oracle.truffle.api" + ], + } }, "subDir" : "src", "javaCompliance" : "8+", diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java index 3cb98f9a5de0..593414313b69 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java @@ -189,16 +189,6 @@ private abstract static class InstrumentReflection { abstract TruffleInstrument newInstance(); abstract Class aotInitializeAtBuildTime(); - - static void exportTruffle(ClassLoader loader) { - if (!TruffleOptions.AOT) { - // In JDK 9+, the Truffle API packages must be dynamically exported to - // a Truffle instrument since the Truffle API module descriptor only - // exports the packages to modules known at build time (such as the - // Graal module). - TruffleJDKServices.exportTo(loader, null); - } - } } private abstract static class Loader { @@ -219,6 +209,16 @@ static void load(ClassLoader loader, List list, Set list, Set classNamesUsed); static String defaultId(String className) { @@ -364,6 +364,7 @@ private ServicesLoader() { @Override void loadImpl(ClassLoader loader, List list, Set classNamesUsed) { + exportTruffle(loader); for (TruffleInstrument.Provider provider : ServiceLoader.load(TruffleInstrument.Provider.class, loader)) { Registration reg = provider.getClass().getAnnotation(Registration.class); if (reg == null) { @@ -399,7 +400,6 @@ private static final class ServiceLoaderInstrumentReflection extends InstrumentR ServiceLoaderInstrumentReflection(TruffleInstrument.Provider provider) { assert provider != null; this.provider = provider; - exportTruffle(provider.getClass().getClassLoader()); } @Override diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java index ed95a3006d53..fe71fcedcc66 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/LanguageCache.java @@ -399,17 +399,6 @@ private abstract static class LanguageReflection { abstract URL getCodeSource(); - static void exportTruffle(ClassLoader loader) { - if (!TruffleOptions.AOT) { - /* - * In JDK 9+, the Truffle API packages must be dynamically exported to a Truffle - * language since the Truffle API module descriptor only exports the packages to - * modules known at build time (such as the Graal module). - */ - TruffleJDKServices.exportTo(loader, null); - } - } - static LanguageReflection forLanguageInstance(TruffleLanguage language, ContextPolicy contextPolycy, FileTypeDetector... fileTypeDetectors) { return new LanguageInstanceReflection(language, contextPolycy, fileTypeDetectors); } @@ -488,6 +477,17 @@ static void load(ClassLoader loader, Collection into) { ServicesLoader.INSTANCE.loadImpl(loader, into); } + static void exportTruffle(ClassLoader loader) { + if (!TruffleOptions.AOT) { + /* + * In JDK 9+, the Truffle API packages must be dynamically exported to a Truffle + * language since the Truffle API module descriptor only exports the packages to + * modules known at build time (such as the Graal module). + */ + TruffleJDKServices.exportTo(loader, null); + } + } + abstract void loadImpl(ClassLoader loader, Collection into); static String defaultId(final String name, final String className) { @@ -792,6 +792,7 @@ private ServicesLoader() { @Override public void loadImpl(ClassLoader loader, Collection into) { + exportTruffle(loader); for (TruffleLanguage.Provider provider : ServiceLoader.load(TruffleLanguage.Provider.class, loader)) { Registration reg = provider.getClass().getAnnotation(Registration.class); if (reg == null) { @@ -860,7 +861,6 @@ private static final class ServiceLoaderLanguageReflection extends LanguageRefle assert contextPolicy != null; this.provider = provider; this.contextPolicy = contextPolicy; - exportTruffle(provider.getClass().getClassLoader()); } @Override From 6f651194ba03dd27c89794d49f1ff7fd3df3c829 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Mon, 7 Oct 2019 17:29:20 +0200 Subject: [PATCH 083/140] [GR-15292] Updating truffleruby. --- .../src/com/oracle/truffle/polyglot/InstrumentCache.java | 7 +++---- vm/mx.vm/suite.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java index 593414313b69..b2257e15fac3 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InstrumentCache.java @@ -325,10 +325,9 @@ TruffleInstrument newInstance() { @Override Class aotInitializeAtBuildTime() { - throw new UnsupportedOperationException("Not supported yet."); // To change body of - // generated methods, - // choose Tools | - // Templates. + initializeInstrumentClass(); + assert instrumentClass != null; + return instrumentClass; } private Class getInstrumentationClass() { diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 2d4925fa9675..51b2303821ff 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -50,7 +50,7 @@ }, { "name": "truffleruby", - "version": "e175b3355fff3004f8c1d20a57efe68804821676", + "version": "fedd3884ef601ac92b43098139b9604876b91121", "dynamic": True, "urls": [ {"url": "https://github.com/oracle/truffleruby.git", "kind": "git"}, From fd6c408fe9cd8a6e04b2328755561b4dfbff79f3 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 26 Sep 2019 13:47:08 +0200 Subject: [PATCH 084/140] Added nodefactory into the Runner and the LLVMParserRuntime. --- .../llvm/parser/LLVMParserRuntime.java | 9 ++++- .../truffle/llvm/runtime/LLVMLanguage.java | 7 ++++ .../src/com/oracle/truffle/llvm/Runner.java | 40 ++++++++++--------- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParserRuntime.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParserRuntime.java index fc5f4f75b793..3805b2b9a41d 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParserRuntime.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParserRuntime.java @@ -34,17 +34,20 @@ import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMScope; import com.oracle.truffle.llvm.runtime.LLVMSymbol; +import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; public final class LLVMParserRuntime { private final LLVMContext context; private final ExternalLibrary library; private final LLVMScope fileScope; + private final NodeFactory nodeFactory; - public LLVMParserRuntime(LLVMContext context, ExternalLibrary library, LLVMScope fileScope) { + public LLVMParserRuntime(LLVMContext context, ExternalLibrary library, LLVMScope fileScope, NodeFactory nodeFactory) { this.context = context; this.library = library; this.fileScope = fileScope; + this.nodeFactory = nodeFactory; } public ExternalLibrary getLibrary() { @@ -63,6 +66,10 @@ public LLVMScope getGlobalScope() { return context.getGlobalScope(); } + public NodeFactory getNodeFactory() { + return nodeFactory; + } + public LLVMFunctionDescriptor lookupFunction(String name, boolean preferGlobalScope) { LLVMSymbol symbol = lookupSymbolImpl(name, preferGlobalScope); if (symbol != null && symbol.isFunction()) { 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 e1f7ff40aeb5..ce65891f3ba0 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 @@ -152,6 +152,13 @@ public final String getLLVMLanguageHome() { return getLanguageHome(); } + public Configuration getActiveConfiguration(){ + if (activeConfiguration != null) { + return activeConfiguration; + } + throw new IllegalStateException("No context, please create the context before accessing the configuration."); + } + @Override protected LLVMContext createContext(Env env) { if (activeConfiguration == null) { diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index 783eab5fe241..57c73158052c 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -135,11 +135,13 @@ final class Runner { private final LLVMContext context; private final DefaultLoader loader; private final LLVMLanguage language; + private final NodeFactory nodeFactory; Runner(LLVMContext context, DefaultLoader loader) { this.context = context; this.loader = loader; this.language = context.getLanguage(); + this.nodeFactory = language.getActiveConfiguration().createNodeFactory(context); } /** @@ -202,7 +204,7 @@ private static void createNodes(Runner runner, FrameDescriptor rootFrame, List parserResults, ArrayDeque< } } LLVMScope fileScope = new LLVMScope(); - LLVMParserRuntime runtime = new LLVMParserRuntime(context, library, fileScope); + LLVMParserRuntime runtime = new LLVMParserRuntime(context, library, fileScope, nodeFactory); LLVMParser parser = new LLVMParser(source, runtime); LLVMParserResult parserResult = parser.parse(module); parserResults.add(parserResult); @@ -875,7 +877,7 @@ private static final class InitializeModuleNode extends LLVMNode implements LLVM this.dataLayout = parserResult.getDataLayout(); this.globalVarInit = runner.createGlobalVariableInitializer(rootFrame, parserResult); - this.protectRoData = runner.language.getNodeFactory().createProtectGlobalsBlock(); + this.protectRoData = runner.nodeFactory.createProtectGlobalsBlock(); this.constructor = runner.createConstructor(parserResult); } @@ -924,13 +926,13 @@ private LLVMStatementNode createGlobalInitialization(LLVMParserRuntime runtime, // for fetching the address of the global that we want to initialize, we must use the // file scope because we are initializing the globals of the current file LLVMGlobal globalDescriptor = runtime.getFileScope().getGlobalVariable(global.getName()); - final LLVMExpressionNode globalVarAddress = language.getNodeFactory().createLiteral(globalDescriptor, new PointerType(global.getType())); + final LLVMExpressionNode globalVarAddress = nodeFactory.createLiteral(globalDescriptor, new PointerType(global.getType())); if (size != 0) { if (type instanceof ArrayType || type instanceof StructureType) { - return language.getNodeFactory().createStore(globalVarAddress, constant, type); + return nodeFactory.createStore(globalVarAddress, constant, type); } else { Type t = global.getValue().getType(); - return language.getNodeFactory().createStore(globalVarAddress, constant, t); + return nodeFactory.createStore(globalVarAddress, constant, t); } } } @@ -980,17 +982,17 @@ private LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable final ArrayList> structors = new ArrayList<>(elemCount); FrameDescriptor rootFrame = StackManager.createRootFrame(); for (int i = 0; i < elemCount; i++) { - final LLVMExpressionNode globalVarAddress = language.getNodeFactory().createLiteral(global, new PointerType(globalSymbol.getType())); - final LLVMExpressionNode iNode = language.getNodeFactory().createLiteral(i, PrimitiveType.I32); - final LLVMExpressionNode structPointer = language.getNodeFactory().createTypedElementPointer(globalVarAddress, iNode, elementSize, elementType); - final LLVMExpressionNode loadedStruct = language.getNodeFactory().createLoad(elementType, structPointer); - - final LLVMExpressionNode oneLiteralNode = language.getNodeFactory().createLiteral(1, PrimitiveType.I32); - final LLVMExpressionNode functionLoadTarget = language.getNodeFactory().createTypedElementPointer(loadedStruct, oneLiteralNode, indexedTypeLength, functionType); - final LLVMExpressionNode loadedFunction = language.getNodeFactory().createLoad(functionType, functionLoadTarget); + final LLVMExpressionNode globalVarAddress = nodeFactory.createLiteral(global, new PointerType(globalSymbol.getType())); + final LLVMExpressionNode iNode = nodeFactory.createLiteral(i, PrimitiveType.I32); + final LLVMExpressionNode structPointer = nodeFactory.createTypedElementPointer(globalVarAddress, iNode, elementSize, elementType); + final LLVMExpressionNode loadedStruct = nodeFactory.createLoad(elementType, structPointer); + + final LLVMExpressionNode oneLiteralNode = nodeFactory.createLiteral(1, PrimitiveType.I32); + final LLVMExpressionNode functionLoadTarget = nodeFactory.createTypedElementPointer(loadedStruct, oneLiteralNode, indexedTypeLength, functionType); + final LLVMExpressionNode loadedFunction = nodeFactory.createLoad(functionType, functionLoadTarget); final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[]{ - language.getNodeFactory().createFrameRead(PointerType.VOID, rootFrame.findFrameSlot(LLVMStack.FRAME_ID))}; - final LLVMStatementNode functionCall = LLVMVoidStatementNodeGen.create(language.getNodeFactory().createFunctionCall(loadedFunction, argNodes, functionType)); + nodeFactory.createFrameRead(PointerType.VOID, rootFrame.findFrameSlot(LLVMStack.FRAME_ID))}; + final LLVMStatementNode functionCall = LLVMVoidStatementNodeGen.create(nodeFactory.createFunctionCall(loadedFunction, argNodes, functionType)); final StructureConstant structorDefinition = (StructureConstant) arrayConstant.getElement(i); final SymbolImpl prioritySymbol = structorDefinition.getElement(0); From 6ccc6383d1f7d7afa2cbd371991c815aa677fb6d Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 26 Sep 2019 13:49:07 +0200 Subject: [PATCH 085/140] Formatting. --- .../src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java | 2 +- .../src/com/oracle/truffle/llvm/Runner.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 ce65891f3ba0..1bce218cb400 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 @@ -152,7 +152,7 @@ public final String getLLVMLanguageHome() { return getLanguageHome(); } - public Configuration getActiveConfiguration(){ + public Configuration getActiveConfiguration() { if (activeConfiguration != null) { return activeConfiguration; } diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index 57c73158052c..b9ce12459809 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -991,7 +991,7 @@ private LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable final LLVMExpressionNode functionLoadTarget = nodeFactory.createTypedElementPointer(loadedStruct, oneLiteralNode, indexedTypeLength, functionType); final LLVMExpressionNode loadedFunction = nodeFactory.createLoad(functionType, functionLoadTarget); final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[]{ - nodeFactory.createFrameRead(PointerType.VOID, rootFrame.findFrameSlot(LLVMStack.FRAME_ID))}; + nodeFactory.createFrameRead(PointerType.VOID, rootFrame.findFrameSlot(LLVMStack.FRAME_ID))}; final LLVMStatementNode functionCall = LLVMVoidStatementNodeGen.create(nodeFactory.createFunctionCall(loadedFunction, argNodes, functionType)); final StructureConstant structorDefinition = (StructureConstant) arrayConstant.getElement(i); From 7433c8fa04d871b969d4b586dcc1d961dc68936f Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 26 Sep 2019 14:01:14 +0200 Subject: [PATCH 086/140] Move createFreeGlobalsBlock (node) into LLVMContext. --- .../llvm/parser/factories/BasicNodeFactory.java | 9 --------- .../oracle/truffle/llvm/runtime/LLVMContext.java | 15 +++++++++++++-- .../oracle/truffle/llvm/runtime/NodeFactory.java | 2 -- 3 files changed, 13 insertions(+), 13 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 9f071fcd7d6a..04587f0db5fd 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 @@ -2354,15 +2354,6 @@ public LLVMMemoryOpNode createProtectGlobalsBlock() { return new ProtectReadOnlyGlobalsBlockNode(context); } - @Override - public LLVMMemoryOpNode createFreeGlobalsBlock(boolean readOnly) { - if (readOnly) { - return new FreeReadOnlyGlobalsBlockNode(context); - } else { - return LLVMFreeNodeGen.create(null); - } - } - @Override public LLVMMemSetNode createMemSet() { return NativeMemSetNodeGen.create(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java index 96aaba51213a..3e9b729ec40d 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java @@ -81,6 +81,8 @@ import com.oracle.truffle.llvm.runtime.memory.LLVMStack.StackPointer; import com.oracle.truffle.llvm.runtime.memory.LLVMThreadingStack; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemoryIntrinsicFactory.LLVMFreeNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.FreeReadOnlyGlobalsBlockNode; import com.oracle.truffle.llvm.runtime.options.SulongEngineOption; import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer; import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; @@ -389,8 +391,8 @@ private void initFreeGlobalBlocks() { if (freeGlobalBlocks == null) { freeGlobalBlocks = Truffle.getRuntime().createCallTarget(new RootNode(language) { - @Child LLVMMemoryOpNode freeRo = language.getNodeFactory().createFreeGlobalsBlock(true); - @Child LLVMMemoryOpNode freeRw = language.getNodeFactory().createFreeGlobalsBlock(false); + @Child LLVMMemoryOpNode freeRo = createFreeGlobalsBlock(true); + @Child LLVMMemoryOpNode freeRw = createFreeGlobalsBlock(false); @Override public Object execute(VirtualFrame frame) { @@ -411,6 +413,15 @@ public Object execute(VirtualFrame frame) { } } + public LLVMMemoryOpNode createFreeGlobalsBlock(boolean readOnly) { + if (readOnly) { + return new FreeReadOnlyGlobalsBlockNode(this); + } else { + return LLVMFreeNodeGen.create(null); + } + } + + void dispose(LLVMMemory memory) { printNativeCallStatistic(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 7aeecf15b028..85835441e5ad 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -235,8 +235,6 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMMemoryOpNode createProtectGlobalsBlock(); - LLVMMemoryOpNode createFreeGlobalsBlock(boolean readOnly); - LLVMExpressionNode createStackSave(); LLVMExpressionNode createStackRestore(LLVMExpressionNode stackPointer); From ca9fd28319a3d462b5f03a539c7e904f5e1a8a13 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 26 Sep 2019 14:17:25 +0200 Subject: [PATCH 087/140] Passing nodefactory into asmfactory. --- .../src/com/oracle/truffle/llvm/asm/amd64/AsmFactory.java | 4 ++-- .../oracle/truffle/llvm/asm/amd64/InlineAssemblyParser.java | 5 +++-- .../truffle/llvm/parser/factories/BasicNodeFactory.java | 2 +- .../src/com/oracle/truffle/llvm/runtime/LLVMContext.java | 1 - 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/AsmFactory.java b/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/AsmFactory.java index 27c07281394d..dbc6abf80c03 100644 --- a/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/AsmFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/AsmFactory.java @@ -273,9 +273,9 @@ class AsmFactory { private final LLVMLanguage language; private final NodeFactory nodeFactory; - AsmFactory(LLVMLanguage language, Type[] argTypes, String asmFlags, Type retType, Type[] retTypes, int[] retOffsets) { + AsmFactory(LLVMLanguage language, Type[] argTypes, String asmFlags, Type retType, Type[] retTypes, int[] retOffsets, NodeFactory nodeFactory) { this.language = language; - this.nodeFactory = language.getNodeFactory(); + this.nodeFactory = nodeFactory; this.argTypes = argTypes; this.asmFlags = asmFlags; this.frameDescriptor = new FrameDescriptor(); diff --git a/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/InlineAssemblyParser.java b/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/InlineAssemblyParser.java index b4dbe5099945..940f89b69fc0 100644 --- a/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/InlineAssemblyParser.java +++ b/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/InlineAssemblyParser.java @@ -34,6 +34,7 @@ // DO NOT MODIFY - generated from InlineAssembly.g4 using "mx create-asm-parser" import com.oracle.truffle.llvm.runtime.LLVMLanguage; +import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.nodes.func.LLVMInlineAssemblyRootNode; import com.oracle.truffle.llvm.runtime.types.Type; @@ -354,7 +355,7 @@ public void syntaxError(Recognizer recognizer, Object offendingSymbol, int } } - public static LLVMInlineAssemblyRootNode parseInlineAssembly(LLVMLanguage language, String asmSnippet, String asmFlags, Type[] argTypes, Type retType, Type[] retTypes, int[] retOffsets) { + public static LLVMInlineAssemblyRootNode parseInlineAssembly(LLVMLanguage language, String asmSnippet, String asmFlags, Type[] argTypes, Type retType, Type[] retTypes, int[] retOffsets, NodeFactory nodeFactory) { InlineAssemblyLexer lexer = new InlineAssemblyLexer(CharStreams.fromString(asmSnippet)); InlineAssemblyParser parser = new InlineAssemblyParser(new CommonTokenStream(lexer)); lexer.removeErrorListeners(); @@ -363,7 +364,7 @@ public static LLVMInlineAssemblyRootNode parseInlineAssembly(LLVMLanguage langua lexer.addErrorListener(listener); parser.addErrorListener(listener); parser.snippet = asmSnippet; - parser.factory = new AsmFactory(language, argTypes, asmFlags, retType, retTypes, retOffsets); + parser.factory = new AsmFactory(language, argTypes, asmFlags, retType, retTypes, retOffsets, nodeFactory); parser.inline_assembly(); if (parser.root == null) { throw new IllegalStateException("no roots produced by inline assembly snippet"); 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 04587f0db5fd..2f14d545da13 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 @@ -1721,7 +1721,7 @@ public LLVMExpressionNode createInlineAssemblerExpression(ExternalLibrary librar LLVMInlineAssemblyRootNode assemblyRoot; try { - assemblyRoot = InlineAssemblyParser.parseInlineAssembly(context.getLanguage(), asmExpression, asmFlags, argTypes, retType, retTypes, retOffsets); + assemblyRoot = InlineAssemblyParser.parseInlineAssembly(context.getLanguage(), asmExpression, asmFlags, argTypes, retType, retTypes, retOffsets, this); } catch (AsmParseException e) { assemblyRoot = getLazyUnsupportedInlineRootNode(asmExpression, e); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java index 3e9b729ec40d..83eab9aed459 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java @@ -421,7 +421,6 @@ public LLVMMemoryOpNode createFreeGlobalsBlock(boolean readOnly) { } } - void dispose(LLVMMemory memory) { printNativeCallStatistic(); From 25bb9b81b8e424524bb5bb37e8e3a0c3cb88e1e2 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 26 Sep 2019 14:18:15 +0200 Subject: [PATCH 088/140] Formatting --- .../oracle/truffle/llvm/parser/factories/BasicNodeFactory.java | 2 -- 1 file changed, 2 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 2f14d545da13..d625531fa93f 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 @@ -205,7 +205,6 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemCopyNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemMoveFactory.LLVMMemMoveI64NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemSetNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemoryIntrinsicFactory.LLVMFreeNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMNoOpNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMPrefetchNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMReturnAddressNodeGen; @@ -269,7 +268,6 @@ import com.oracle.truffle.llvm.runtime.nodes.literals.LLVMVectorLiteralNodeFactory.LLVMPointerVectorLiteralNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.AllocateGlobalsBlockNode; import com.oracle.truffle.llvm.runtime.nodes.memory.AllocateReadOnlyGlobalsBlockNode; -import com.oracle.truffle.llvm.runtime.nodes.memory.FreeReadOnlyGlobalsBlockNode; import com.oracle.truffle.llvm.runtime.nodes.memory.LLVMCompareExchangeNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.LLVMFenceNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.LLVMGetElementPtrNodeGen; From f708030948212a540b7ad0422b61e1a36700c467 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 26 Sep 2019 14:29:50 +0200 Subject: [PATCH 089/140] Passed nodefactory from runner to parser, to be used in creating the debuginfo. --- .../truffle/llvm/parser/LLVMParser.java | 18 +++++---------- .../truffle/llvm/runtime/LLVMLanguage.java | 4 ---- .../src/com/oracle/truffle/llvm/Runner.java | 22 ++++++++++--------- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java index 5972daf2a633..d0296f3004cb 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java @@ -73,13 +73,8 @@ public LLVMParser(Source source, LLVMParserRuntime runtime) { this.library = runtime.getLibrary(); } - public LLVMParserResult parse(ModelModule module) { - TargetDataLayout layout = module.getTargetDataLayout(); - DataLayout targetDataLayout = new DataLayout(layout.getDataLayout()); - NodeFactory nodeFactory = context.getLanguage().getActiveConfiguration().createNodeFactory(context, targetDataLayout); - context.getLanguage().setNodeFactory(nodeFactory); - - List externalGlobals = new ArrayList<>(); + public LLVMParserResult parse(ModelModule module, DataLayout targetDataLayout, NodeFactory nodeFactory) { + List externalGlobals = new ArrayList<>(); List definedGlobals = new ArrayList<>(); List externalFunctions = new ArrayList<>(); List importedSymbols = new ArrayList<>(); @@ -89,8 +84,7 @@ public LLVMParserResult parse(ModelModule module) { defineAliases(module.getAliases(), importedSymbols); LLVMSymbolReadResolver symbolResolver = new LLVMSymbolReadResolver(runtime, StackManager.createRootFrame(), GetStackSpaceFactory.createAllocaFactory(), targetDataLayout); - createDebugInfo(module, symbolResolver); - + createDebugInfo(module, symbolResolver, nodeFactory); return new LLVMParserResult(runtime, externalFunctions, definedGlobals, externalGlobals, importedSymbols, targetDataLayout); } @@ -228,19 +222,19 @@ private void defineAlias(String existingName, boolean existingExported, String n } } - private void createDebugInfo(ModelModule model, LLVMSymbolReadResolver symbolResolver) { + private void createDebugInfo(ModelModule model, LLVMSymbolReadResolver symbolResolver, NodeFactory nodeFactory) { if (context.getEnv().getOptions().get(SulongEngineOption.ENABLE_LVI)) { final LLVMSourceContext sourceContext = context.getSourceContext(); model.getSourceGlobals().forEach((symbol, irValue) -> { final LLVMExpressionNode node = symbolResolver.resolve(irValue); - final LLVMDebugObjectBuilder value = context.getLanguage().getNodeFactory().createDebugStaticValue(node, irValue instanceof GlobalVariable); + final LLVMDebugObjectBuilder value = nodeFactory.createDebugStaticValue(node, irValue instanceof GlobalVariable); sourceContext.registerStatic(symbol, value); }); model.getSourceStaticMembers().forEach(((type, symbol) -> { final LLVMExpressionNode node = symbolResolver.resolve(symbol); - final LLVMDebugObjectBuilder value = context.getLanguage().getNodeFactory().createDebugStaticValue(node, symbol instanceof GlobalVariable); + final LLVMDebugObjectBuilder value = nodeFactory.createDebugStaticValue(node, symbol instanceof GlobalVariable); type.setValue(value); })); } 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 1bce218cb400..54c7be683e3f 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 @@ -180,10 +180,6 @@ public NodeFactory getNodeFactory() { return nodeFactory; } - public Configuration getActiveConfiguration() { - return activeConfiguration; - } - @Override protected void initializeContext(LLVMContext context) { context.initialize(); diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index b9ce12459809..7e39386c79cb 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -75,6 +75,7 @@ import com.oracle.truffle.llvm.parser.model.symbols.constants.aggregate.ArrayConstant; import com.oracle.truffle.llvm.parser.model.symbols.constants.aggregate.StructureConstant; import com.oracle.truffle.llvm.parser.model.symbols.globals.GlobalVariable; +import com.oracle.truffle.llvm.parser.model.target.TargetDataLayout; import com.oracle.truffle.llvm.parser.nodes.LLVMSymbolReadResolver; import com.oracle.truffle.llvm.parser.scanner.LLVMScanner; import com.oracle.truffle.llvm.parser.util.Pair; @@ -135,13 +136,11 @@ final class Runner { private final LLVMContext context; private final DefaultLoader loader; private final LLVMLanguage language; - private final NodeFactory nodeFactory; Runner(LLVMContext context, DefaultLoader loader) { this.context = context; this.loader = loader; this.language = context.getLanguage(); - this.nodeFactory = language.getActiveConfiguration().createNodeFactory(context); } /** @@ -204,7 +203,7 @@ private static void createNodes(Runner runner, FrameDescriptor rootFrame, List parserResults, ArrayDeque< dependencyQueue.addLast(dependency); } } + TargetDataLayout layout = module.getTargetDataLayout(); + DataLayout targetDataLayout = new DataLayout(layout.getDataLayout()); + NodeFactory nodeFactory = context.getLanguage().getActiveConfiguration().createNodeFactory(context, targetDataLayout); LLVMScope fileScope = new LLVMScope(); LLVMParserRuntime runtime = new LLVMParserRuntime(context, library, fileScope, nodeFactory); LLVMParser parser = new LLVMParser(source, runtime); - LLVMParserResult parserResult = parser.parse(module); + LLVMParserResult parserResult = parser.parse(module, targetDataLayout, nodeFactory); parserResults.add(parserResult); return parserResult; } else if (!library.isNative()) { @@ -877,7 +879,7 @@ private static final class InitializeModuleNode extends LLVMNode implements LLVM this.dataLayout = parserResult.getDataLayout(); this.globalVarInit = runner.createGlobalVariableInitializer(rootFrame, parserResult); - this.protectRoData = runner.nodeFactory.createProtectGlobalsBlock(); + this.protectRoData = parserResult.getRuntime().getNodeFactory().createProtectGlobalsBlock(); this.constructor = runner.createConstructor(parserResult); } @@ -926,13 +928,13 @@ private LLVMStatementNode createGlobalInitialization(LLVMParserRuntime runtime, // for fetching the address of the global that we want to initialize, we must use the // file scope because we are initializing the globals of the current file LLVMGlobal globalDescriptor = runtime.getFileScope().getGlobalVariable(global.getName()); - final LLVMExpressionNode globalVarAddress = nodeFactory.createLiteral(globalDescriptor, new PointerType(global.getType())); + final LLVMExpressionNode globalVarAddress = runtime.getNodeFactory().createLiteral(globalDescriptor, new PointerType(global.getType())); if (size != 0) { if (type instanceof ArrayType || type instanceof StructureType) { - return nodeFactory.createStore(globalVarAddress, constant, type); + return runtime.getNodeFactory().createStore(globalVarAddress, constant, type); } else { Type t = global.getValue().getType(); - return nodeFactory.createStore(globalVarAddress, constant, t); + return runtime.getNodeFactory().createStore(globalVarAddress, constant, t); } } } @@ -957,13 +959,13 @@ private RootCallTarget createDestructor(LLVMParserResult parserResult) { private LLVMStatementNode[] createStructor(String name, LLVMParserResult parserResult, Comparator> priorityComparator) { for (GlobalVariable globalVariable : parserResult.getDefinedGlobals()) { if (globalVariable.getName().equals(name)) { - return resolveStructor(parserResult.getRuntime().getFileScope(), globalVariable, priorityComparator, parserResult.getDataLayout()); + return resolveStructor(parserResult.getRuntime().getFileScope(), globalVariable, priorityComparator, parserResult.getDataLayout(), parserResult.getRuntime().getNodeFactory()); } } return LLVMStatementNode.NO_STATEMENTS; } - private LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable globalSymbol, Comparator> priorityComparator, DataLayout dataLayout) { + private LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable globalSymbol, Comparator> priorityComparator, DataLayout dataLayout, NodeFactory nodeFactory) { if (!(globalSymbol.getValue() instanceof ArrayConstant)) { // array globals of length 0 may be initialized with scalar null return LLVMStatementNode.NO_STATEMENTS; From 78b9cc53a75727f0f44b53b0565483ae9c08a4b6 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 26 Sep 2019 15:43:45 +0200 Subject: [PATCH 090/140] GetStackSpaceFactory takes a nodeFactory instead of context. --- .../truffle/llvm/parser/factories/BasicNodeFactory.java | 6 +++--- .../truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java | 6 +++--- .../oracle/truffle/llvm/runtime/GetStackSpaceFactory.java | 6 +++--- 3 files changed, 9 insertions(+), 9 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 d625531fa93f..2d8c6213f822 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 @@ -1510,7 +1510,7 @@ public LLVMControlFlowNode createUnconditionalBranch(int unconditionalIndex, LLV @Override public LLVMExpressionNode createArrayLiteral(LLVMExpressionNode[] arrayValues, ArrayType arrayType, GetStackSpaceFactory arrayGetStackSpaceFactory) { assert arrayType.getNumberOfElements() == arrayValues.length; - LLVMExpressionNode arrayGetStackSpace = arrayGetStackSpaceFactory.createGetStackSpace(context, arrayType); + LLVMExpressionNode arrayGetStackSpace = arrayGetStackSpaceFactory.createGetStackSpace(this, arrayType); Type elementType = arrayType.getElementType(); int elementSize = getByteSize(elementType); if (elementSize == 0) { @@ -1636,7 +1636,7 @@ public LLVMExpressionNode createStructureConstantNode(Type structType, GetStackS int[] offsets = new int[types.length]; LLVMStoreNode[] nodes = new LLVMStoreNode[types.length]; int currentOffset = 0; - LLVMExpressionNode getStackSpace = getStackSpaceFactory.createGetStackSpace(context, structType); + LLVMExpressionNode getStackSpace = getStackSpaceFactory.createGetStackSpace(this, structType); for (int i = 0; i < types.length; i++) { Type resolvedType = types[i]; if (!packed) { @@ -2196,7 +2196,7 @@ public LLVMStatementNode createPhi(LLVMExpressionNode[] from, FrameSlot[] to, Ty @Override public LLVMExpressionNode createCopyStructByValue(Type type, GetStackSpaceFactory getStackSpaceFactory, LLVMExpressionNode parameterNode) { - LLVMExpressionNode getStackSpaceNode = getStackSpaceFactory.createGetStackSpace(context, type); + LLVMExpressionNode getStackSpaceNode = getStackSpaceFactory.createGetStackSpace(this, type); return LLVMStructByValueNodeGen.create(createMemMove(), getStackSpaceNode, parameterNode, getByteSize(type)); } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java index d523852ab2f3..b3e2d6410f67 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java @@ -169,7 +169,7 @@ public void visit(ArrayType type) { if (arraySize == 0) { resolvedNode = null; } else { - LLVMExpressionNode target = getStackSpaceFactory.createGetStackSpace(context, type); + LLVMExpressionNode target = getStackSpaceFactory.createGetStackSpace(nodeFactory, type); resolvedNode = nodeFactory.createZeroNode(target, arraySize); } } @@ -181,7 +181,7 @@ public void visit(StructureType structureType) { final LLVMNativePointer minusOneNode = LLVMNativePointer.create(-1); resolvedNode = nodeFactory.createLiteral(minusOneNode, new PointerType(structureType)); } else { - LLVMExpressionNode addressnode = getStackSpaceFactory.createGetStackSpace(context, structureType); + LLVMExpressionNode addressnode = getStackSpaceFactory.createGetStackSpace(nodeFactory, structureType); resolvedNode = nodeFactory.createZeroNode(addressnode, structSize); } } @@ -430,7 +430,7 @@ public void visitValueInstruction(ValueInstruction value) { public LLVMSymbolReadResolver(LLVMParserRuntime runtime, FrameDescriptor frame, GetStackSpaceFactory getStackSpaceFactory, DataLayout dataLayout) { this.runtime = runtime; this.context = runtime.getContext(); - this.nodeFactory = context.getLanguage().getNodeFactory(); + this.nodeFactory = runtime.getNodeFactory(); this.frame = frame; this.getStackSpaceFactory = getStackSpaceFactory; this.dataLayout = dataLayout; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/GetStackSpaceFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/GetStackSpaceFactory.java index b51a4b8492ce..a85fedbf83af 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/GetStackSpaceFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/GetStackSpaceFactory.java @@ -35,14 +35,14 @@ public interface GetStackSpaceFactory { - LLVMExpressionNode createGetStackSpace(LLVMContext context, Type type); + LLVMExpressionNode createGetStackSpace(NodeFactory nodeFactory, Type type); static GetStackSpaceFactory createAllocaFactory() { - return (context, type) -> context.getLanguage().getNodeFactory().createAlloca(type); + return (nodeFactory, type) -> nodeFactory.createAlloca(type); } static GetStackSpaceFactory createGetUniqueStackSpaceFactory(UniquesRegion uniquesRegion) { - return (context, type) -> context.getLanguage().getNodeFactory().createGetUniqueStackSpace(type, uniquesRegion); + return (nodeFactory, type) -> nodeFactory.createGetUniqueStackSpace(type, uniquesRegion); } } From 728cf4d2db260c88c19c07e97cdcbcced7b71aa2 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 26 Sep 2019 16:08:31 +0200 Subject: [PATCH 091/140] Get nodeFactory from the parser runtime. --- .../llvm/parser/LazyToTruffleConverterImpl.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 b1c063012aa6..fcf3b4747e23 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 @@ -140,11 +140,11 @@ private RootCallTarget generateCallTarget() { List copyArgumentsToFrame = copyArgumentsToFrame(frame); LLVMStatementNode[] copyArgumentsToFrameArray = copyArgumentsToFrame.toArray(LLVMStatementNode.NO_STATEMENTS); - LLVMExpressionNode body = runtime.getContext().getLanguage().getNodeFactory().createFunctionBlockNode(frame.findFrameSlot(LLVMUserException.FRAME_SLOT_ID), visitor.getBlocks(), + LLVMExpressionNode body = runtime.getNodeFactory().createFunctionBlockNode(frame.findFrameSlot(LLVMUserException.FRAME_SLOT_ID), visitor.getBlocks(), uniquesRegion.build(), nullableBeforeBlock, nullableAfterBlock, copyArgumentsToFrameArray, location, frame); - RootNode rootNode = runtime.getContext().getLanguage().getNodeFactory().createFunctionStartNode(body, frame, method.getName(), method.getSourceName(), + RootNode rootNode = runtime.getNodeFactory().createFunctionStartNode(body, frame, method.getName(), method.getSourceName(), method.getParameters().size(), source, location); method.onAfterParse(); @@ -183,23 +183,23 @@ private static FrameSlot[][] getNullableFrameSlots(FrameSlot[] frameSlots, BitSe private List copyArgumentsToFrame(FrameDescriptor frame) { List parameters = method.getParameters(); List formalParamInits = new ArrayList<>(); - LLVMExpressionNode stackPointerNode = runtime.getContext().getLanguage().getNodeFactory().createFunctionArgNode(0, PrimitiveType.I64); - formalParamInits.add(runtime.getContext().getLanguage().getNodeFactory().createFrameWrite(PointerType.VOID, stackPointerNode, frame.findFrameSlot(LLVMStack.FRAME_ID))); + LLVMExpressionNode stackPointerNode = runtime.getNodeFactory().createFunctionArgNode(0, PrimitiveType.I64); + formalParamInits.add(runtime.getNodeFactory().createFrameWrite(PointerType.VOID, stackPointerNode, frame.findFrameSlot(LLVMStack.FRAME_ID))); int argIndex = 1; if (method.getType().getReturnType() instanceof StructureType) { argIndex++; } for (FunctionParameter parameter : parameters) { - LLVMExpressionNode parameterNode = runtime.getContext().getLanguage().getNodeFactory().createFunctionArgNode(argIndex++, parameter.getType()); + LLVMExpressionNode parameterNode = runtime.getNodeFactory().createFunctionArgNode(argIndex++, parameter.getType()); FrameSlot slot = frame.findFrameSlot(parameter.getName()); if (isStructByValue(parameter)) { Type type = ((PointerType) parameter.getType()).getPointeeType(); formalParamInits.add( - runtime.getContext().getLanguage().getNodeFactory().createFrameWrite(parameter.getType(), - runtime.getContext().getLanguage().getNodeFactory().createCopyStructByValue(type, GetStackSpaceFactory.createAllocaFactory(), parameterNode), slot)); + runtime.getNodeFactory().createFrameWrite(parameter.getType(), + runtime.getNodeFactory().createCopyStructByValue(type, GetStackSpaceFactory.createAllocaFactory(), parameterNode), slot)); } else { - formalParamInits.add(runtime.getContext().getLanguage().getNodeFactory().createFrameWrite(parameter.getType(), parameterNode, slot)); + formalParamInits.add(runtime.getNodeFactory().createFrameWrite(parameter.getType(), parameterNode, slot)); } } return formalParamInits; From d9452a87d4c30d92b0d1a0c76adb9749b9f3b7ea Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 26 Sep 2019 17:00:21 +0200 Subject: [PATCH 092/140] Removing unused contexts. --- .../oracle/truffle/llvm/parser/LLVMParser.java | 3 +-- .../parser/nodes/LLVMSymbolReadResolver.java | 3 --- .../src/com/oracle/truffle/llvm/Runner.java | 18 +++++++++--------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java index d0296f3004cb..5a85adebfb56 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java @@ -41,7 +41,6 @@ import com.oracle.truffle.llvm.parser.model.symbols.constants.CastConstant; import com.oracle.truffle.llvm.parser.model.symbols.globals.GlobalAlias; import com.oracle.truffle.llvm.parser.model.symbols.globals.GlobalVariable; -import com.oracle.truffle.llvm.parser.model.target.TargetDataLayout; import com.oracle.truffle.llvm.parser.nodes.LLVMSymbolReadResolver; import com.oracle.truffle.llvm.runtime.GetStackSpaceFactory; import com.oracle.truffle.llvm.runtime.LLVMAlias; @@ -74,7 +73,7 @@ public LLVMParser(Source source, LLVMParserRuntime runtime) { } public LLVMParserResult parse(ModelModule module, DataLayout targetDataLayout, NodeFactory nodeFactory) { - List externalGlobals = new ArrayList<>(); + List externalGlobals = new ArrayList<>(); List definedGlobals = new ArrayList<>(); List externalFunctions = new ArrayList<>(); List importedSymbols = new ArrayList<>(); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java index b3e2d6410f67..225314683078 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java @@ -65,7 +65,6 @@ import com.oracle.truffle.llvm.parser.model.visitors.ValueInstructionVisitor; import com.oracle.truffle.llvm.parser.util.LLVMBitcodeTypeHelper; import com.oracle.truffle.llvm.runtime.GetStackSpaceFactory; -import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMSymbol; import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; @@ -91,7 +90,6 @@ public final class LLVMSymbolReadResolver { private final LLVMParserRuntime runtime; - private final LLVMContext context; private final NodeFactory nodeFactory; private final FrameDescriptor frame; private final GetStackSpaceFactory getStackSpaceFactory; @@ -429,7 +427,6 @@ public void visitValueInstruction(ValueInstruction value) { public LLVMSymbolReadResolver(LLVMParserRuntime runtime, FrameDescriptor frame, GetStackSpaceFactory getStackSpaceFactory, DataLayout dataLayout) { this.runtime = runtime; - this.context = runtime.getContext(); this.nodeFactory = runtime.getNodeFactory(); this.frame = frame; this.getStackSpaceFactory = getStackSpaceFactory; diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index 7e39386c79cb..ed0e26380993 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -203,7 +203,7 @@ private static void createNodes(Runner runner, FrameDescriptor rootFrame, List globalNodes = new ArrayList<>(); @@ -915,7 +915,7 @@ private StaticInitsNode createGlobalVariableInitializer(FrameDescriptor rootFram return new StaticInitsNode(initNodes); } - private LLVMStatementNode createGlobalInitialization(LLVMParserRuntime runtime, LLVMSymbolReadResolver symbolResolver, GlobalVariable global, DataLayout dataLayout) { + private static LLVMStatementNode createGlobalInitialization(LLVMParserRuntime runtime, LLVMSymbolReadResolver symbolResolver, GlobalVariable global, DataLayout dataLayout) { if (global == null || global.getValue() == null) { return null; } @@ -942,7 +942,7 @@ private LLVMStatementNode createGlobalInitialization(LLVMParserRuntime runtime, return null; } - private StaticInitsNode createConstructor(LLVMParserResult parserResult) { + private static StaticInitsNode createConstructor(LLVMParserResult parserResult) { return new StaticInitsNode(createStructor(CONSTRUCTORS_VARNAME, parserResult, ASCENDING_PRIORITY)); } @@ -956,7 +956,7 @@ private RootCallTarget createDestructor(LLVMParserResult parserResult) { } } - private LLVMStatementNode[] createStructor(String name, LLVMParserResult parserResult, Comparator> priorityComparator) { + private static LLVMStatementNode[] createStructor(String name, LLVMParserResult parserResult, Comparator> priorityComparator) { for (GlobalVariable globalVariable : parserResult.getDefinedGlobals()) { if (globalVariable.getName().equals(name)) { return resolveStructor(parserResult.getRuntime().getFileScope(), globalVariable, priorityComparator, parserResult.getDataLayout(), parserResult.getRuntime().getNodeFactory()); @@ -965,7 +965,7 @@ private LLVMStatementNode[] createStructor(String name, LLVMParserResult parserR return LLVMStatementNode.NO_STATEMENTS; } - private LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable globalSymbol, Comparator> priorityComparator, DataLayout dataLayout, NodeFactory nodeFactory) { + private static LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable globalSymbol, Comparator> priorityComparator, DataLayout dataLayout, NodeFactory nodeFactory) { if (!(globalSymbol.getValue() instanceof ArrayConstant)) { // array globals of length 0 may be initialized with scalar null return LLVMStatementNode.NO_STATEMENTS; From 8614ca781d35b2856e49f777fdff0193f3ee4f72 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Fri, 27 Sep 2019 15:05:02 +0200 Subject: [PATCH 093/140] Created a new node factory: CommonNodeFactory. Moved createLoadNode, createStoreNode, and createForeigntoLLVMNode as static methods into the new node factory. --- .../llvm/runtime/CommonNodeFactory.java | 107 ++++++++++++++++++ .../runtime/interop/LLVMForeignCallNode.java | 3 +- .../interop/export/LLVMForeignReadNode.java | 4 +- .../interop/export/LLVMForeignWriteNode.java | 6 +- 4 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java new file mode 100644 index 000000000000..fa96b6d00ef7 --- /dev/null +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -0,0 +1,107 @@ +package com.oracle.truffle.llvm.runtime; + +import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; +import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; +import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; +import com.oracle.truffle.llvm.runtime.interop.convert.ToDoubleNodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToFloatNodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI16NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI1NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI32NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI64NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI8NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer; +import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; +import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStoreNode; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMPointerDirectLoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDoubleLoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMFloatLoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI16LoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI1LoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI32LoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI64LoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI8LoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMDoubleStoreNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMFloatStoreNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI16StoreNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI1StoreNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI32StoreNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI64StoreNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI8StoreNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMPointerStoreNodeGen; + +public class CommonNodeFactory { + + public CommonNodeFactory(){ + + } + + public static LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind) { + switch (kind) { + case I1: + return LLVMI1LoadNodeGen.create(null); + case I8: + return LLVMI8LoadNodeGen.create(null); + case I16: + return LLVMI16LoadNodeGen.create(null); + case I32: + return LLVMI32LoadNodeGen.create(null); + case I64: + return LLVMI64LoadNodeGen.create(null); + case FLOAT: + return LLVMFloatLoadNodeGen.create(null); + case DOUBLE: + return LLVMDoubleLoadNodeGen.create(null); + case POINTER: + return LLVMPointerDirectLoadNodeGen.create(null); + default: + throw new IllegalStateException("unexpected interop kind " + kind); + } + } + + public static LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind) { + switch (kind) { + case I1: + return LLVMI1StoreNodeGen.create(null, null); + case I8: + return LLVMI8StoreNodeGen.create(null, null); + case I16: + return LLVMI16StoreNodeGen.create(null, null); + case I32: + return LLVMI32StoreNodeGen.create(null, null); + case I64: + return LLVMI64StoreNodeGen.create(null, null); + case FLOAT: + return LLVMFloatStoreNodeGen.create(null, null); + case DOUBLE: + return LLVMDoubleStoreNodeGen.create(null, null); + case POINTER: + return LLVMPointerStoreNodeGen.create(null, null); + default: + throw new IllegalStateException("unexpected interop kind " + kind); + } + } + + public static ForeignToLLVM createForeignToLLVM(Value type) { + switch (type.getKind()) { + case I1: + return ToI1NodeGen.create(); + case I8: + return ToI8NodeGen.create(); + case I16: + return ToI16NodeGen.create(); + case I32: + return ToI32NodeGen.create(); + case I64: + return ToI64NodeGen.create(); + case FLOAT: + return ToFloatNodeGen.create(); + case DOUBLE: + return ToDoubleNodeGen.create(); + case POINTER: + return ToPointer.create(type.getBaseType()); + default: + throw new IllegalStateException("unexpected interop kind " + type.getKind()); + } + } +} diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java index 43fa7745c8af..643c4e870860 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java @@ -40,6 +40,7 @@ import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMGetStackNode; @@ -75,7 +76,7 @@ abstract static class PackForeignArgumentsNode extends LLVMNode { for (int i = 0; i < parameterTypes.length; i++) { LLVMInteropType interopParameterType = interopFunctionType.getParameter(i); if (interopParameterType instanceof LLVMInteropType.Value) { - toLLVM[i] = nodeFactory.createForeignToLLVM((LLVMInteropType.Value) interopParameterType); + toLLVM[i] = CommonNodeFactory.createForeignToLLVM((LLVMInteropType.Value) interopParameterType); } else { // interop only supported for value types toLLVM[i] = nodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignReadNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignReadNode.java index 38444d1abe14..cc727ec4830d 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignReadNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignReadNode.java @@ -34,7 +34,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.llvm.runtime.LLVMLanguage; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.interop.LLVMDataEscapeNode; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; @@ -72,6 +72,6 @@ Object doValueUncached(LLVMPointer ptr, LLVMInteropType.Value type) { LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind) { CompilerAsserts.neverPartOfCompilation(); - return LLVMLanguage.getLanguage().getNodeFactory().createLoadNode(kind); + return CommonNodeFactory.createLoadNode(kind); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java index 1d9e0e12720e..5340427195e1 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java @@ -35,7 +35,7 @@ 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.llvm.runtime.LLVMLanguage; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.ValueKind; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -74,10 +74,10 @@ static void doStructured(LLVMPointer ptr, LLVMInteropType.Structured type, Objec LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind) { CompilerAsserts.neverPartOfCompilation(); - return LLVMLanguage.getLanguage().getNodeFactory().createStoreNode(kind); + return CommonNodeFactory.createStoreNode(kind); } protected ForeignToLLVM createForeignToLLVM(LLVMInteropType.Value type) { - return getNodeFactory().createForeignToLLVM(type); + return CommonNodeFactory.createForeignToLLVM(type); } } From ca6e03056dfe7430633852bed830ffcaa24e16fa Mon Sep 17 00:00:00 2001 From: Paley Li Date: Fri, 27 Sep 2019 15:22:34 +0200 Subject: [PATCH 094/140] Added createForeignToLLVM to CommonNodeFactory. --- .../factories/BasicIntrinsicsProvider.java | 7 +- .../parser/factories/BasicNodeFactory.java | 65 ------------------- .../llvm/runtime/CommonNodeFactory.java | 30 +++++++++ .../truffle/llvm/runtime/NodeFactory.java | 7 -- .../runtime/interop/LLVMForeignCallNode.java | 11 ++-- .../llvm/runtime/interop/convert/ToLLVM.java | 17 ++--- .../runtime/nodes/cast/LLVMToDoubleNode.java | 3 +- .../runtime/nodes/cast/LLVMToFloatNode.java | 3 +- .../runtime/nodes/cast/LLVMToI16Node.java | 3 +- .../llvm/runtime/nodes/cast/LLVMToI1Node.java | 3 +- .../runtime/nodes/cast/LLVMToI32Node.java | 3 +- .../llvm/runtime/nodes/cast/LLVMToI8Node.java | 3 +- .../runtime/nodes/func/LLVMDispatchNode.java | 3 +- .../intrinsics/interop/LLVMPolyglotEval.java | 3 +- .../interop/LLVMPolyglotImport.java | 3 +- .../interop/LLVMPolyglotJavaType.java | 3 +- .../interop/LLVMPolyglotNewInstance.java | 3 +- .../runtime/nodes/op/ToComparableValue.java | 3 +- 18 files changed, 71 insertions(+), 102 deletions(-) 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 821b9cf33022..f1483e85115a 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 @@ -43,6 +43,7 @@ import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.func.LLVMRaiseExceptionNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMSyscall; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotAsPrimitive; @@ -384,10 +385,10 @@ private static void registerTruffleIntrinsics() { add("polyglot_set_array_element", (args, language, types) -> LLVMPolyglotSetArrayElementNodeGen.create(types, args.get(1), args.get(2), args.get(3))); - add("polyglot_get_member", (args, language) -> LLVMPolyglotGetMemberNodeGen.create(language.getNodeFactory().createForeignToLLVM(POINTER), args.get(1), args.get(2))); + add("polyglot_get_member", (args, language) -> LLVMPolyglotGetMemberNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); add("polyglot_get_array_element", - (args, language) -> LLVMPolyglotGetArrayElementNodeGen.create(language.getNodeFactory().createForeignToLLVM(POINTER), args.get(1), args.get(2))); + (args, language) -> LLVMPolyglotGetArrayElementNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); add("polyglot_remove_member", (args, language) -> LLVMPolyglotRemoveMemberNodeGen.create(args.get(1), args.get(2))); @@ -407,7 +408,7 @@ private static void registerTruffleIntrinsics() { args.get(1))); add("polyglot_invoke", - (args, language, types) -> LLVMPolyglotInvokeNodeGen.create(language.getNodeFactory().createForeignToLLVM(POINTER), argumentsArray(args, 3, args.size() - 3), + (args, language, types) -> LLVMPolyglotInvokeNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), argumentsArray(args, 3, args.size() - 3), Arrays.copyOfRange(types, 3, types.length), args.get(1), args.get(2))); 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 2d8c6213f822..ce9a02c7110f 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 @@ -73,19 +73,6 @@ import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; -import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; -import com.oracle.truffle.llvm.runtime.interop.convert.ToAnyLLVMNodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToDoubleNodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToFloatNodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI16NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI1NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI32NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI64NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI8NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer; -import com.oracle.truffle.llvm.runtime.interop.convert.ToVoidLLVMNodeGen; import com.oracle.truffle.llvm.runtime.memory.LLVMAllocateNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemSetNode; @@ -2538,58 +2525,6 @@ private LLVMStatementNode createStore(LLVMExpressionNode pointerNode, LLVMExpres } } - @Override - public ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type) { - switch (type) { - case VOID: - return ToVoidLLVMNodeGen.create(); - case ANY: - return ToAnyLLVMNodeGen.create(); - case I1: - return ToI1NodeGen.create(); - case I8: - return ToI8NodeGen.create(); - case I16: - return ToI16NodeGen.create(); - case I32: - return ToI32NodeGen.create(); - case I64: - return ToI64NodeGen.create(); - case FLOAT: - return ToFloatNodeGen.create(); - case DOUBLE: - return ToDoubleNodeGen.create(); - case POINTER: - return ToPointer.create(); - default: - throw new IllegalStateException(type.toString()); - } - } - - @Override - public ForeignToLLVM createForeignToLLVM(Value type) { - switch (type.getKind()) { - case I1: - return ToI1NodeGen.create(); - case I8: - return ToI8NodeGen.create(); - case I16: - return ToI16NodeGen.create(); - case I32: - return ToI32NodeGen.create(); - case I64: - return ToI64NodeGen.create(); - case FLOAT: - return ToFloatNodeGen.create(); - case DOUBLE: - return ToDoubleNodeGen.create(); - case POINTER: - return ToPointer.create(type.getBaseType()); - default: - throw new IllegalStateException("unexpected interop kind " + type.getKind()); - } - } - private static AssertionError unsupportedCast(Type targetType) { throw new LLVMParserException("Cannot cast to " + targetType); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index fa96b6d00ef7..6f87369d5032 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -3,6 +3,8 @@ import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; +import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; +import com.oracle.truffle.llvm.runtime.interop.convert.ToAnyLLVMNodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToDoubleNodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToFloatNodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToI16NodeGen; @@ -11,6 +13,7 @@ import com.oracle.truffle.llvm.runtime.interop.convert.ToI64NodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToI8NodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer; +import com.oracle.truffle.llvm.runtime.interop.convert.ToVoidLLVMNodeGen; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStoreNode; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMPointerDirectLoadNodeGen; @@ -104,4 +107,31 @@ public static ForeignToLLVM createForeignToLLVM(Value type) { throw new IllegalStateException("unexpected interop kind " + type.getKind()); } } + + public static ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type) { + switch (type) { + case VOID: + return ToVoidLLVMNodeGen.create(); + case ANY: + return ToAnyLLVMNodeGen.create(); + case I1: + return ToI1NodeGen.create(); + case I8: + return ToI8NodeGen.create(); + case I16: + return ToI16NodeGen.create(); + case I32: + return ToI32NodeGen.create(); + case I64: + return ToI64NodeGen.create(); + case FLOAT: + return ToFloatNodeGen.create(); + case DOUBLE: + return ToDoubleNodeGen.create(); + case POINTER: + return ToPointer.create(); + default: + throw new IllegalStateException(type.toString()); + } + } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 85835441e5ad..04f33d919094 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -41,9 +41,6 @@ import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObjectBuilder; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; import com.oracle.truffle.llvm.runtime.debug.value.LLVMFrameValueAccess; -import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; import com.oracle.truffle.llvm.runtime.interop.export.InteropNodeFactory; import com.oracle.truffle.llvm.runtime.memory.LLVMAllocateNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode; @@ -238,8 +235,4 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMExpressionNode createStackSave(); LLVMExpressionNode createStackRestore(LLVMExpressionNode stackPointer); - - ForeignToLLVM createForeignToLLVM(LLVMInteropType.Value type); - - ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java index 643c4e870860..e3a255789c29 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java @@ -45,7 +45,6 @@ import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMGetStackNode; import com.oracle.truffle.llvm.runtime.LLVMLanguage; -import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.interop.LLVMForeignCallNodeFactory.PackForeignArgumentsNodeGen; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -68,7 +67,6 @@ abstract static class PackForeignArgumentsNode extends LLVMNode { @Children final ForeignToLLVM[] toLLVM; PackForeignArgumentsNode(Type[] parameterTypes, LLVMInteropType interopType) { - NodeFactory nodeFactory = getNodeFactory(); this.toLLVM = new ForeignToLLVM[parameterTypes.length]; if (interopType instanceof LLVMInteropType.Function) { LLVMInteropType.Function interopFunctionType = (LLVMInteropType.Function) interopType; @@ -79,13 +77,13 @@ abstract static class PackForeignArgumentsNode extends LLVMNode { toLLVM[i] = CommonNodeFactory.createForeignToLLVM((LLVMInteropType.Value) interopParameterType); } else { // interop only supported for value types - toLLVM[i] = nodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); + toLLVM[i] = CommonNodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); } } } else { // no interop parameter types available for (int i = 0; i < parameterTypes.length; i++) { - toLLVM[i] = nodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); + toLLVM[i] = CommonNodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); } } } @@ -105,10 +103,9 @@ Object[] packNonVarargs(Object[] arguments, StackPointer stackPointer) { ForeignToLLVM[] createVarargsToLLVM(int argCount) { int count = argCount - toLLVM.length; if (count > 0) { - NodeFactory nodeFactory = LLVMNode.getNodeFactory(); ForeignToLLVM[] ret = new ForeignToLLVM[count]; for (int i = 0; i < count; i++) { - ret[i] = nodeFactory.createForeignToLLVM(ForeignToLLVMType.ANY); + ret[i] = CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.ANY); } return ret; } else { @@ -133,7 +130,7 @@ Object[] packCachedArgCount(Object[] arguments, StackPointer stackPointer, } ForeignToLLVM createVarargsToLLVM() { - return LLVMNode.getNodeFactory().createForeignToLLVM(ForeignToLLVMType.ANY); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.ANY); } @Specialization(guards = "arguments.length >= toLLVM.length", replaces = "packCachedArgCount") diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java index 7fcf5619a1af..6f4be4a1957e 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java @@ -37,6 +37,7 @@ import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.interop.LLVMTypedForeignObject; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; @@ -321,35 +322,35 @@ static boolean isPointer(ForeignToLLVMType targetType) { } protected ForeignToLLVM createToI1() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I1); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I1); } protected ForeignToLLVM createToI8() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I8); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I8); } protected ForeignToLLVM createToI16() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I16); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I16); } protected ForeignToLLVM createToI32() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I32); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I32); } protected ForeignToLLVM createToI64() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I64); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I64); } protected ForeignToLLVM createToFloat() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.FLOAT); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.FLOAT); } protected ForeignToLLVM createToDouble() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.DOUBLE); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.DOUBLE); } protected ForeignToLLVM createToPointer() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java index 773025e63dd2..8c85a8aea6d8 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -77,7 +78,7 @@ protected double doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.DOUBLE); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.DOUBLE); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java index 1ffb7b7bcdb3..6e315db2c661 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -75,7 +76,7 @@ protected float doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.FLOAT); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.FLOAT); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java index 4d8e36b2cf6d..de657355f54b 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; @@ -61,7 +62,7 @@ protected short doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I16); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I16); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java index 8f3068a3da3e..6de8800935c6 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -58,7 +59,7 @@ protected boolean doPointer(LLVMNativePointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I1); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I1); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java index 38d89edb80dd..6d519533ff5f 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; @@ -63,7 +64,7 @@ protected int doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I32); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I32); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java index 72506cd615b2..6a52ad0a8503 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; @@ -60,7 +61,7 @@ protected byte doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I8); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I8); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java index df65f07f0847..5cef7fd50343 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java @@ -45,6 +45,7 @@ import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.IndirectCallNode; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor.Intrinsic; @@ -318,7 +319,7 @@ private Object[] getForeignArguments(LLVMDataEscapeNode[] dataEscapeNodes, Objec } protected ForeignToLLVM createToLLVMNode() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVM.convert(type.getReturnType())); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVM.convert(type.getReturnType())); } @TruffleBoundary diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java index 2aa4eb47f8f0..6cebfdaa6385 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java @@ -42,6 +42,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.LanguageInfo; import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; @@ -88,7 +89,7 @@ protected Object doEval(Object idPointer, Object srcPointer, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } abstract static class GetSourceNode extends LLVMNode { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java index c84b329683fa..b4495d77bff2 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java @@ -39,6 +39,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; @@ -73,6 +74,6 @@ protected Object doImport(Object name, } ForeignToLLVM createToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java index 8e8882d44985..1147b0564b81 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java @@ -33,6 +33,7 @@ import com.oracle.truffle.api.dsl.CachedContext; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; @@ -56,6 +57,6 @@ protected Object doImport(Object name, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java index 229dba8a1155..719aca986c0a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java @@ -43,6 +43,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMGetStackNode; @@ -127,6 +128,6 @@ public Object fallback(Object value) { } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java index bd050ebb60ea..a5edb315afda 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java @@ -35,6 +35,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; import com.oracle.truffle.llvm.runtime.library.internal.LLVMNativeLibrary; @@ -108,7 +109,7 @@ public static ManagedToComparableValue createUseOffset() { } protected ForeignToLLVM createForeignToI64() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I64); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I64); } } } From 94ff443a3a7b05b1adf811aa9c5d7111f5e76127 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Fri, 27 Sep 2019 15:26:48 +0200 Subject: [PATCH 095/140] Removed getNodeFactory from LLVMNode. --- .../com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java index d1c09d9d3910..90710c075d52 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java @@ -39,7 +39,6 @@ import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMLanguage; -import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.memory.LLVMMemory; import com.oracle.truffle.llvm.runtime.memory.UnsafeArrayAccess; @@ -69,11 +68,6 @@ public abstract class LLVMNode extends Node { public static final int ADDRESS_SIZE_IN_BYTES = 8; - public static NodeFactory getNodeFactory() { - CompilerAsserts.neverPartOfCompilation(); - return LLVMLanguage.getLanguage().getNodeFactory(); - } - public static LLVMMemory getLLVMMemory() { CompilerAsserts.neverPartOfCompilation(); return LLVMLanguage.getLanguage().getCapability(LLVMMemory.class); From 92b0026a39d6a100b3d13dd9acff9809aa9eca16 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Mon, 30 Sep 2019 10:56:52 +0200 Subject: [PATCH 096/140] Removed the ability to set the nodeFactory in the language. Need a different plan for the DebuggerScopeFactory and the SourceTypeFactory. --- .../llvm/runtime/CommonNodeFactory.java | 52 ++++++++++++++++++- .../truffle/llvm/runtime/LLVMLanguage.java | 4 -- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 6f87369d5032..0cb21521ade4 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -36,7 +36,6 @@ public class CommonNodeFactory { public CommonNodeFactory(){ - } public static LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind) { @@ -134,4 +133,55 @@ public static ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type) { throw new IllegalStateException(type.toString()); } } + + /*public static TruffleObject toGenericDebuggerValue(Object llvmType, Object value) { + final TruffleObject complexObject = asDebuggerIRValue(llvmType, value); + if (complexObject != null) { + return complexObject; + } + + return LLVMDebugManagedValue.create(llvmType, value); + } + + private static TruffleObject asDebuggerIRValue(Object llvmType, Object value) { + final Type type; + if (llvmType instanceof Type) { + type = (Type) llvmType; + } else { + return null; + } + + // e.g. debugger symbols + if (type instanceof MetaType) { + return null; + } + + final LLVMSourceType sourceType = LLVMSourceTypeFactory.resolveType(type, dataLayout); + if (sourceType == null) { + return null; + } + + // after frame-nulling the actual vector length does not correspond to the type anymore + if (value instanceof LLVMVector && ((LLVMVector) value).getLength() == 0) { + return null; + } + + // after frame-nulling the actual bitsize does not correspond to the type anymore + if (value instanceof LLVMIVarBit && ((LLVMIVarBit) value).getBitSize() == 0) { + return null; + } + + final LLVMDebugValue debugValue = createDebugValueBuilder().build(value); + if (debugValue == LLVMDebugValue.UNAVAILABLE) { + return null; + } + + return LLVMDebugObject.instantiate(sourceType, 0L, debugValue, null); + } + + public static LLVMDebugValue.Builder createDebugValueBuilder() { + return LLVMToDebugValueNodeGen.create(); + }*/ + + } 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 54c7be683e3f..817b33f0ef89 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 @@ -172,10 +172,6 @@ protected LLVMContext createContext(Env env) { return context; } - public void setNodeFactory(NodeFactory nodeFactory) { - this.nodeFactory = nodeFactory; - } - public NodeFactory getNodeFactory() { return nodeFactory; } From 108ae2562f99e983329199f68dd133b7da601faa Mon Sep 17 00:00:00 2001 From: Paley Li Date: Mon, 30 Sep 2019 17:03:55 +0200 Subject: [PATCH 097/140] Moved toGenericDebuggerValue into the CommonNodeFactory. --- .../parser/factories/BasicNodeFactory.java | 52 ------------------- .../llvm/runtime/CommonNodeFactory.java | 19 +++++-- .../truffle/llvm/runtime/NodeFactory.java | 3 -- .../debug/scope/LLVMDebuggerScopeFactory.java | 30 +++++------ .../llvm/runtime/nodes/api/LLVMNode.java | 2 +- 5 files changed, 31 insertions(+), 75 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 ce9a02c7110f..23fde0dbab45 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 @@ -39,7 +39,6 @@ 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.interop.TruffleObject; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.llvm.asm.amd64.AsmParseException; @@ -62,13 +61,9 @@ import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMDebugGlobalVariable; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; -import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceType; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugManagedValue; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObject; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObjectBuilder; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; import com.oracle.truffle.llvm.runtime.debug.value.LLVMFrameValueAccess; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMSourceTypeFactory; import com.oracle.truffle.llvm.runtime.except.LLVMParserException; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; @@ -432,7 +427,6 @@ import com.oracle.truffle.llvm.runtime.types.VectorType; import com.oracle.truffle.llvm.runtime.types.VoidType; import com.oracle.truffle.llvm.runtime.types.symbols.Symbol; -import com.oracle.truffle.llvm.runtime.vector.LLVMVector; public class BasicNodeFactory implements NodeFactory { protected final LLVMContext context; @@ -2274,52 +2268,6 @@ public LLVMStatementNode createDebugTrap() { return new LLVMDebugTrapNode(); } - private TruffleObject asDebuggerIRValue(Object llvmType, Object value) { - final Type type; - if (llvmType instanceof Type) { - type = (Type) llvmType; - } else { - return null; - } - - // e.g. debugger symbols - if (type instanceof MetaType) { - return null; - } - - final LLVMSourceType sourceType = LLVMSourceTypeFactory.resolveType(type, dataLayout); - if (sourceType == null) { - return null; - } - - // after frame-nulling the actual vector length does not correspond to the type anymore - if (value instanceof LLVMVector && ((LLVMVector) value).getLength() == 0) { - return null; - } - - // after frame-nulling the actual bitsize does not correspond to the type anymore - if (value instanceof LLVMIVarBit && ((LLVMIVarBit) value).getBitSize() == 0) { - return null; - } - - final LLVMDebugValue debugValue = createDebugValueBuilder().build(value); - if (debugValue == LLVMDebugValue.UNAVAILABLE) { - return null; - } - - return LLVMDebugObject.instantiate(sourceType, 0L, debugValue, null); - } - - @Override - public TruffleObject toGenericDebuggerValue(Object llvmType, Object value) { - final TruffleObject complexObject = asDebuggerIRValue(llvmType, value); - if (complexObject != null) { - return complexObject; - } - - return LLVMDebugManagedValue.create(llvmType, value); - } - @Override public LLVMMemMoveNode createMemMove() { return NativeProfiledMemMoveNodeGen.create(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 0cb21521ade4..331954578646 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -1,5 +1,12 @@ package com.oracle.truffle.llvm.runtime; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; +import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceType; +import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugManagedValue; +import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObject; +import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; +import com.oracle.truffle.llvm.runtime.debug.value.LLVMSourceTypeFactory; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -16,6 +23,7 @@ import com.oracle.truffle.llvm.runtime.interop.convert.ToVoidLLVMNodeGen; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStoreNode; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugValueNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMPointerDirectLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDoubleLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMFloatLoadNodeGen; @@ -32,6 +40,9 @@ import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI64StoreNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI8StoreNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMPointerStoreNodeGen; +import com.oracle.truffle.llvm.runtime.types.MetaType; +import com.oracle.truffle.llvm.runtime.types.Type; +import com.oracle.truffle.llvm.runtime.vector.LLVMVector; public class CommonNodeFactory { @@ -134,8 +145,8 @@ public static ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type) { } } - /*public static TruffleObject toGenericDebuggerValue(Object llvmType, Object value) { - final TruffleObject complexObject = asDebuggerIRValue(llvmType, value); + public static TruffleObject toGenericDebuggerValue(Object llvmType, Object value, DataLayout dataLayout) { + final TruffleObject complexObject = asDebuggerIRValue(llvmType, value, dataLayout); if (complexObject != null) { return complexObject; } @@ -143,7 +154,7 @@ public static ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type) { return LLVMDebugManagedValue.create(llvmType, value); } - private static TruffleObject asDebuggerIRValue(Object llvmType, Object value) { + private static TruffleObject asDebuggerIRValue(Object llvmType, Object value, DataLayout dataLayout) { final Type type; if (llvmType instanceof Type) { type = (Type) llvmType; @@ -181,7 +192,7 @@ private static TruffleObject asDebuggerIRValue(Object llvmType, Object value) { public static LLVMDebugValue.Builder createDebugValueBuilder() { return LLVMToDebugValueNodeGen.create(); - }*/ + } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 04f33d919094..14b4524b24d6 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -33,7 +33,6 @@ import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.llvm.runtime.LLVMContext.ExternalLibrary; @@ -222,8 +221,6 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMStatementNode createDebugTrap(); - TruffleObject toGenericDebuggerValue(Object llvmType, Object value); - LLVMMemMoveNode createMemMove(); LLVMMemSetNode createMemSet(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/scope/LLVMDebuggerScopeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/scope/LLVMDebuggerScopeFactory.java index 56b2dbc31cef..13bc3f5b9ab7 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/scope/LLVMDebuggerScopeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/scope/LLVMDebuggerScopeFactory.java @@ -44,16 +44,18 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMScope; import com.oracle.truffle.llvm.runtime.LLVMSymbol; -import com.oracle.truffle.llvm.runtime.NodeFactory; +import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.debug.LLVMSourceContext; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObject; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObjectBuilder; import com.oracle.truffle.llvm.runtime.debug.value.LLVMFrameValueAccess; import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMInstrumentableNode; +import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode; import com.oracle.truffle.llvm.runtime.options.SulongEngineOption; import com.oracle.truffle.llvm.runtime.types.PointerType; import com.oracle.truffle.llvm.runtime.types.symbols.LLVMIdentifier; @@ -75,12 +77,11 @@ private static LLVMSourceLocation findSourceLocation(Node suspendedNode) { } @TruffleBoundary - private static LLVMDebuggerScopeEntries getIRLevelEntries(Frame frame, LLVMContext context) { + private static LLVMDebuggerScopeEntries getIRLevelEntries(Frame frame, LLVMContext context, DataLayout dataLayout) { if (frame == null || frame.getFrameDescriptor().getSlots().isEmpty()) { return LLVMDebuggerScopeEntries.EMPTY_SCOPE; } - final NodeFactory wrapperFactory = context.getLanguage().getNodeFactory(); final LLVMDebuggerScopeEntries entries = new LLVMDebuggerScopeEntries(); for (final FrameSlot slot : frame.getFrameDescriptor().getSlots()) { final String identifier = String.valueOf(slot.getIdentifier()); @@ -88,7 +89,7 @@ private static LLVMDebuggerScopeEntries getIRLevelEntries(Frame frame, LLVMConte if (slotValue == null) { // slots are null if they are cleared by LLVMFrameNuller slotValue = ""; } - final TruffleObject value = wrapperFactory.toGenericDebuggerValue(slot.getInfo(), slotValue); + final TruffleObject value = CommonNodeFactory.toGenericDebuggerValue(slot.getInfo(), slotValue, dataLayout); entries.add(convertIdentifier(identifier, context), value); } @@ -96,13 +97,12 @@ private static LLVMDebuggerScopeEntries getIRLevelEntries(Frame frame, LLVMConte } @TruffleBoundary - private static LLVMDebuggerScopeEntries toDebuggerScope(LLVMScope scope, LLVMContext context) { - final NodeFactory wrapperFactory = context.getLanguage().getNodeFactory(); + private static LLVMDebuggerScopeEntries toDebuggerScope(LLVMScope scope, DataLayout dataLayout ) { final LLVMDebuggerScopeEntries entries = new LLVMDebuggerScopeEntries(); for (LLVMSymbol symbol : scope.values()) { if (symbol.isGlobalVariable()) { final LLVMGlobal global = symbol.asGlobalVariable(); - final TruffleObject value = wrapperFactory.toGenericDebuggerValue(global.getPointeeType(), global.getTarget()); + final TruffleObject value = CommonNodeFactory.toGenericDebuggerValue(global.getPointeeType(), global.getTarget(), dataLayout); entries.add(LLVMIdentifier.toGlobalIdentifier(global.getName()), value); } } @@ -110,30 +110,30 @@ private static LLVMDebuggerScopeEntries toDebuggerScope(LLVMScope scope, LLVMCon } @TruffleBoundary - private static LLVMDebuggerScopeEntries toDebuggerScope(LLVMSourceLocation.TextModule irScope, LLVMContext context) { - final NodeFactory wrapperFactory = context.getLanguage().getNodeFactory(); + private static LLVMDebuggerScopeEntries toDebuggerScope(LLVMSourceLocation.TextModule irScope, DataLayout dataLayout) { final LLVMDebuggerScopeEntries entries = new LLVMDebuggerScopeEntries(); for (LLVMGlobal global : irScope) { - final TruffleObject value = wrapperFactory.toGenericDebuggerValue(new PointerType(global.getPointeeType()), global.getTarget()); + final TruffleObject value = CommonNodeFactory.toGenericDebuggerValue(new PointerType(global.getPointeeType()), global.getTarget(), dataLayout); entries.add(LLVMIdentifier.toGlobalIdentifier(global.getName()), value); } return entries; } @TruffleBoundary - private static LLVMDebuggerScopeEntries getIRLevelEntries(Node node, LLVMContext context) { + private static LLVMDebuggerScopeEntries getIRLevelEntries(Node node, LLVMContext context, DataLayout dataLayout) { for (LLVMSourceLocation location = findSourceLocation(node); location != null; location = location.getParent()) { if (location instanceof LLVMSourceLocation.TextModule) { - return toDebuggerScope((LLVMSourceLocation.TextModule) location, context); + return toDebuggerScope((LLVMSourceLocation.TextModule) location, dataLayout); } } - return toDebuggerScope(context.getGlobalScope(), context); + return toDebuggerScope(context.getGlobalScope(), dataLayout); } @TruffleBoundary public static Iterable createIRLevelScope(Node node, Frame frame, LLVMContext context) { - final Scope localScope = Scope.newBuilder("function", getIRLevelEntries(frame, context)).node(node).build(); - final Scope globalScope = Scope.newBuilder("module", getIRLevelEntries(node, context)).build(); + DataLayout dataLayout = ((LLVMNode) node).getDataLayout(); + final Scope localScope = Scope.newBuilder("function", getIRLevelEntries(frame, context, dataLayout)).node(node).build(); + final Scope globalScope = Scope.newBuilder("module", getIRLevelEntries(node, context, dataLayout)).build(); return Arrays.asList(localScope, globalScope); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java index 90710c075d52..499955d70615 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java @@ -101,7 +101,7 @@ protected static boolean isSameObject(Object a, Object b) { return a == b; } - protected final DataLayout getDataLayout() { + public final DataLayout getDataLayout() { Node datalayoutNode = this; while (!(datalayoutNode instanceof LLVMHasDatalayoutNode)) { if (datalayoutNode.getParent() != null) { From d37ac619d534d608523ba4e4e9b482c8cb326082 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Tue, 1 Oct 2019 15:40:05 +0200 Subject: [PATCH 098/140] Revert "Move createFreeGlobalsBlock (node) into LLVMContext." This reverts commit 15d3c61c6e797c158b7fae0e46928d14a69727dc. --- .../llvm/parser/factories/BasicNodeFactory.java | 11 +++++++++++ .../oracle/truffle/llvm/runtime/LLVMContext.java | 14 ++------------ .../oracle/truffle/llvm/runtime/NodeFactory.java | 2 ++ 3 files changed, 15 insertions(+), 12 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 23fde0dbab45..fd0fbab93862 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 @@ -187,6 +187,7 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemCopyNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemMoveFactory.LLVMMemMoveI64NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemSetNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemoryIntrinsicFactory.LLVMFreeNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMNoOpNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMPrefetchNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMReturnAddressNodeGen; @@ -250,6 +251,7 @@ import com.oracle.truffle.llvm.runtime.nodes.literals.LLVMVectorLiteralNodeFactory.LLVMPointerVectorLiteralNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.AllocateGlobalsBlockNode; import com.oracle.truffle.llvm.runtime.nodes.memory.AllocateReadOnlyGlobalsBlockNode; +import com.oracle.truffle.llvm.runtime.nodes.memory.FreeReadOnlyGlobalsBlockNode; import com.oracle.truffle.llvm.runtime.nodes.memory.LLVMCompareExchangeNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.LLVMFenceNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.LLVMGetElementPtrNodeGen; @@ -2287,6 +2289,15 @@ public LLVMMemoryOpNode createProtectGlobalsBlock() { return new ProtectReadOnlyGlobalsBlockNode(context); } + @Override + public LLVMMemoryOpNode createFreeGlobalsBlock(boolean readOnly) { + if (readOnly) { + return new FreeReadOnlyGlobalsBlockNode(context); + } else { + return LLVMFreeNodeGen.create(null); + } + } + @Override public LLVMMemSetNode createMemSet() { return NativeMemSetNodeGen.create(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java index 83eab9aed459..96aaba51213a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java @@ -81,8 +81,6 @@ import com.oracle.truffle.llvm.runtime.memory.LLVMStack.StackPointer; import com.oracle.truffle.llvm.runtime.memory.LLVMThreadingStack; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemoryIntrinsicFactory.LLVMFreeNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.memory.FreeReadOnlyGlobalsBlockNode; import com.oracle.truffle.llvm.runtime.options.SulongEngineOption; import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer; import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; @@ -391,8 +389,8 @@ private void initFreeGlobalBlocks() { if (freeGlobalBlocks == null) { freeGlobalBlocks = Truffle.getRuntime().createCallTarget(new RootNode(language) { - @Child LLVMMemoryOpNode freeRo = createFreeGlobalsBlock(true); - @Child LLVMMemoryOpNode freeRw = createFreeGlobalsBlock(false); + @Child LLVMMemoryOpNode freeRo = language.getNodeFactory().createFreeGlobalsBlock(true); + @Child LLVMMemoryOpNode freeRw = language.getNodeFactory().createFreeGlobalsBlock(false); @Override public Object execute(VirtualFrame frame) { @@ -413,14 +411,6 @@ public Object execute(VirtualFrame frame) { } } - public LLVMMemoryOpNode createFreeGlobalsBlock(boolean readOnly) { - if (readOnly) { - return new FreeReadOnlyGlobalsBlockNode(this); - } else { - return LLVMFreeNodeGen.create(null); - } - } - void dispose(LLVMMemory memory) { printNativeCallStatistic(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 14b4524b24d6..1af3faf92c53 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -229,6 +229,8 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMMemoryOpNode createProtectGlobalsBlock(); + LLVMMemoryOpNode createFreeGlobalsBlock(boolean readOnly); + LLVMExpressionNode createStackSave(); LLVMExpressionNode createStackRestore(LLVMExpressionNode stackPointer); From 1af8fa4ed8c20b2af1a0b04c735e5e86dc9c9075 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Tue, 1 Oct 2019 15:57:45 +0200 Subject: [PATCH 099/140] Revert "Added createForeignToLLVM to CommonNodeFactory." This reverts commit 7d7e95fce8ba006312de8f1d22c6a8da5b2189e3. --- .../factories/BasicIntrinsicsProvider.java | 7 +- .../parser/factories/BasicNodeFactory.java | 65 +++++++++++++++++++ .../llvm/runtime/CommonNodeFactory.java | 55 ---------------- .../truffle/llvm/runtime/NodeFactory.java | 7 ++ .../runtime/interop/LLVMForeignCallNode.java | 11 ++-- .../llvm/runtime/interop/convert/ToLLVM.java | 17 +++-- .../runtime/nodes/cast/LLVMToDoubleNode.java | 3 +- .../runtime/nodes/cast/LLVMToFloatNode.java | 3 +- .../runtime/nodes/cast/LLVMToI16Node.java | 3 +- .../llvm/runtime/nodes/cast/LLVMToI1Node.java | 3 +- .../runtime/nodes/cast/LLVMToI32Node.java | 3 +- .../llvm/runtime/nodes/cast/LLVMToI8Node.java | 3 +- .../runtime/nodes/func/LLVMDispatchNode.java | 3 +- .../intrinsics/interop/LLVMPolyglotEval.java | 3 +- .../interop/LLVMPolyglotImport.java | 3 +- .../interop/LLVMPolyglotJavaType.java | 3 +- .../interop/LLVMPolyglotNewInstance.java | 3 +- .../runtime/nodes/op/ToComparableValue.java | 3 +- 18 files changed, 102 insertions(+), 96 deletions(-) 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 f1483e85115a..821b9cf33022 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 @@ -43,7 +43,6 @@ import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.func.LLVMRaiseExceptionNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMSyscall; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotAsPrimitive; @@ -385,10 +384,10 @@ private static void registerTruffleIntrinsics() { add("polyglot_set_array_element", (args, language, types) -> LLVMPolyglotSetArrayElementNodeGen.create(types, args.get(1), args.get(2), args.get(3))); - add("polyglot_get_member", (args, language) -> LLVMPolyglotGetMemberNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); + add("polyglot_get_member", (args, language) -> LLVMPolyglotGetMemberNodeGen.create(language.getNodeFactory().createForeignToLLVM(POINTER), args.get(1), args.get(2))); add("polyglot_get_array_element", - (args, language) -> LLVMPolyglotGetArrayElementNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); + (args, language) -> LLVMPolyglotGetArrayElementNodeGen.create(language.getNodeFactory().createForeignToLLVM(POINTER), args.get(1), args.get(2))); add("polyglot_remove_member", (args, language) -> LLVMPolyglotRemoveMemberNodeGen.create(args.get(1), args.get(2))); @@ -408,7 +407,7 @@ private static void registerTruffleIntrinsics() { args.get(1))); add("polyglot_invoke", - (args, language, types) -> LLVMPolyglotInvokeNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), argumentsArray(args, 3, args.size() - 3), + (args, language, types) -> LLVMPolyglotInvokeNodeGen.create(language.getNodeFactory().createForeignToLLVM(POINTER), argumentsArray(args, 3, args.size() - 3), Arrays.copyOfRange(types, 3, types.length), args.get(1), args.get(2))); 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 fd0fbab93862..c38f61fa3027 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 @@ -68,6 +68,19 @@ import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; +import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; +import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; +import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; +import com.oracle.truffle.llvm.runtime.interop.convert.ToAnyLLVMNodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToDoubleNodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToFloatNodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI16NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI1NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI32NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI64NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI8NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer; +import com.oracle.truffle.llvm.runtime.interop.convert.ToVoidLLVMNodeGen; import com.oracle.truffle.llvm.runtime.memory.LLVMAllocateNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemSetNode; @@ -2484,6 +2497,58 @@ private LLVMStatementNode createStore(LLVMExpressionNode pointerNode, LLVMExpres } } + @Override + public ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type) { + switch (type) { + case VOID: + return ToVoidLLVMNodeGen.create(); + case ANY: + return ToAnyLLVMNodeGen.create(); + case I1: + return ToI1NodeGen.create(); + case I8: + return ToI8NodeGen.create(); + case I16: + return ToI16NodeGen.create(); + case I32: + return ToI32NodeGen.create(); + case I64: + return ToI64NodeGen.create(); + case FLOAT: + return ToFloatNodeGen.create(); + case DOUBLE: + return ToDoubleNodeGen.create(); + case POINTER: + return ToPointer.create(); + default: + throw new IllegalStateException(type.toString()); + } + } + + @Override + public ForeignToLLVM createForeignToLLVM(Value type) { + switch (type.getKind()) { + case I1: + return ToI1NodeGen.create(); + case I8: + return ToI8NodeGen.create(); + case I16: + return ToI16NodeGen.create(); + case I32: + return ToI32NodeGen.create(); + case I64: + return ToI64NodeGen.create(); + case FLOAT: + return ToFloatNodeGen.create(); + case DOUBLE: + return ToDoubleNodeGen.create(); + case POINTER: + return ToPointer.create(type.getBaseType()); + default: + throw new IllegalStateException("unexpected interop kind " + type.getKind()); + } + } + private static AssertionError unsupportedCast(Type targetType) { throw new LLVMParserException("Cannot cast to " + targetType); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 331954578646..1e333597b45a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -10,8 +10,6 @@ import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; -import com.oracle.truffle.llvm.runtime.interop.convert.ToAnyLLVMNodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToDoubleNodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToFloatNodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToI16NodeGen; @@ -20,7 +18,6 @@ import com.oracle.truffle.llvm.runtime.interop.convert.ToI64NodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToI8NodeGen; import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer; -import com.oracle.truffle.llvm.runtime.interop.convert.ToVoidLLVMNodeGen; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStoreNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugValueNodeGen; @@ -95,56 +92,6 @@ public static LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind) { } } - public static ForeignToLLVM createForeignToLLVM(Value type) { - switch (type.getKind()) { - case I1: - return ToI1NodeGen.create(); - case I8: - return ToI8NodeGen.create(); - case I16: - return ToI16NodeGen.create(); - case I32: - return ToI32NodeGen.create(); - case I64: - return ToI64NodeGen.create(); - case FLOAT: - return ToFloatNodeGen.create(); - case DOUBLE: - return ToDoubleNodeGen.create(); - case POINTER: - return ToPointer.create(type.getBaseType()); - default: - throw new IllegalStateException("unexpected interop kind " + type.getKind()); - } - } - - public static ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type) { - switch (type) { - case VOID: - return ToVoidLLVMNodeGen.create(); - case ANY: - return ToAnyLLVMNodeGen.create(); - case I1: - return ToI1NodeGen.create(); - case I8: - return ToI8NodeGen.create(); - case I16: - return ToI16NodeGen.create(); - case I32: - return ToI32NodeGen.create(); - case I64: - return ToI64NodeGen.create(); - case FLOAT: - return ToFloatNodeGen.create(); - case DOUBLE: - return ToDoubleNodeGen.create(); - case POINTER: - return ToPointer.create(); - default: - throw new IllegalStateException(type.toString()); - } - } - public static TruffleObject toGenericDebuggerValue(Object llvmType, Object value, DataLayout dataLayout) { final TruffleObject complexObject = asDebuggerIRValue(llvmType, value, dataLayout); if (complexObject != null) { @@ -193,6 +140,4 @@ private static TruffleObject asDebuggerIRValue(Object llvmType, Object value, Da public static LLVMDebugValue.Builder createDebugValueBuilder() { return LLVMToDebugValueNodeGen.create(); } - - } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 1af3faf92c53..05f525227f05 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -40,6 +40,9 @@ import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObjectBuilder; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; import com.oracle.truffle.llvm.runtime.debug.value.LLVMFrameValueAccess; +import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; +import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; +import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; import com.oracle.truffle.llvm.runtime.interop.export.InteropNodeFactory; import com.oracle.truffle.llvm.runtime.memory.LLVMAllocateNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode; @@ -234,4 +237,8 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMExpressionNode createStackSave(); LLVMExpressionNode createStackRestore(LLVMExpressionNode stackPointer); + + ForeignToLLVM createForeignToLLVM(LLVMInteropType.Value type); + + ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java index e3a255789c29..643c4e870860 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java @@ -45,6 +45,7 @@ import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMGetStackNode; import com.oracle.truffle.llvm.runtime.LLVMLanguage; +import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.interop.LLVMForeignCallNodeFactory.PackForeignArgumentsNodeGen; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -67,6 +68,7 @@ abstract static class PackForeignArgumentsNode extends LLVMNode { @Children final ForeignToLLVM[] toLLVM; PackForeignArgumentsNode(Type[] parameterTypes, LLVMInteropType interopType) { + NodeFactory nodeFactory = getNodeFactory(); this.toLLVM = new ForeignToLLVM[parameterTypes.length]; if (interopType instanceof LLVMInteropType.Function) { LLVMInteropType.Function interopFunctionType = (LLVMInteropType.Function) interopType; @@ -77,13 +79,13 @@ abstract static class PackForeignArgumentsNode extends LLVMNode { toLLVM[i] = CommonNodeFactory.createForeignToLLVM((LLVMInteropType.Value) interopParameterType); } else { // interop only supported for value types - toLLVM[i] = CommonNodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); + toLLVM[i] = nodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); } } } else { // no interop parameter types available for (int i = 0; i < parameterTypes.length; i++) { - toLLVM[i] = CommonNodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); + toLLVM[i] = nodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); } } } @@ -103,9 +105,10 @@ Object[] packNonVarargs(Object[] arguments, StackPointer stackPointer) { ForeignToLLVM[] createVarargsToLLVM(int argCount) { int count = argCount - toLLVM.length; if (count > 0) { + NodeFactory nodeFactory = LLVMNode.getNodeFactory(); ForeignToLLVM[] ret = new ForeignToLLVM[count]; for (int i = 0; i < count; i++) { - ret[i] = CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.ANY); + ret[i] = nodeFactory.createForeignToLLVM(ForeignToLLVMType.ANY); } return ret; } else { @@ -130,7 +133,7 @@ Object[] packCachedArgCount(Object[] arguments, StackPointer stackPointer, } ForeignToLLVM createVarargsToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.ANY); + return LLVMNode.getNodeFactory().createForeignToLLVM(ForeignToLLVMType.ANY); } @Specialization(guards = "arguments.length >= toLLVM.length", replaces = "packCachedArgCount") diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java index 6f4be4a1957e..7fcf5619a1af 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java @@ -37,7 +37,6 @@ import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; -import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.interop.LLVMTypedForeignObject; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; @@ -322,35 +321,35 @@ static boolean isPointer(ForeignToLLVMType targetType) { } protected ForeignToLLVM createToI1() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I1); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I1); } protected ForeignToLLVM createToI8() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I8); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I8); } protected ForeignToLLVM createToI16() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I16); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I16); } protected ForeignToLLVM createToI32() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I32); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I32); } protected ForeignToLLVM createToI64() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I64); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I64); } protected ForeignToLLVM createToFloat() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.FLOAT); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.FLOAT); } protected ForeignToLLVM createToDouble() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.DOUBLE); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.DOUBLE); } protected ForeignToLLVM createToPointer() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); } } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java index 8c85a8aea6d8..773025e63dd2 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java @@ -32,7 +32,6 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -78,7 +77,7 @@ protected double doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.DOUBLE); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.DOUBLE); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java index 6e315db2c661..1ffb7b7bcdb3 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java @@ -32,7 +32,6 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -76,7 +75,7 @@ protected float doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.FLOAT); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.FLOAT); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java index de657355f54b..4d8e36b2cf6d 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java @@ -32,7 +32,6 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; @@ -62,7 +61,7 @@ protected short doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I16); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I16); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java index 6de8800935c6..8f3068a3da3e 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java @@ -32,7 +32,6 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -59,7 +58,7 @@ protected boolean doPointer(LLVMNativePointer from, } protected ForeignToLLVM createForeignToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I1); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I1); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java index 6d519533ff5f..38d89edb80dd 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java @@ -32,7 +32,6 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; @@ -64,7 +63,7 @@ protected int doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I32); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I32); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java index 6a52ad0a8503..72506cd615b2 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java @@ -32,7 +32,6 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; @@ -61,7 +60,7 @@ protected byte doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I8); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I8); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java index 5cef7fd50343..df65f07f0847 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java @@ -45,7 +45,6 @@ import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.IndirectCallNode; -import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor.Intrinsic; @@ -319,7 +318,7 @@ private Object[] getForeignArguments(LLVMDataEscapeNode[] dataEscapeNodes, Objec } protected ForeignToLLVM createToLLVMNode() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVM.convert(type.getReturnType())); + return getNodeFactory().createForeignToLLVM(ForeignToLLVM.convert(type.getReturnType())); } @TruffleBoundary diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java index 6cebfdaa6385..2aa4eb47f8f0 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java @@ -42,7 +42,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.LanguageInfo; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; @@ -89,7 +88,7 @@ protected Object doEval(Object idPointer, Object srcPointer, } protected ForeignToLLVM createForeignToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); } abstract static class GetSourceNode extends LLVMNode { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java index b4495d77bff2..c84b329683fa 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java @@ -39,7 +39,6 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; @@ -74,6 +73,6 @@ protected Object doImport(Object name, } ForeignToLLVM createToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java index 1147b0564b81..8e8882d44985 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java @@ -33,7 +33,6 @@ import com.oracle.truffle.api.dsl.CachedContext; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; @@ -57,6 +56,6 @@ protected Object doImport(Object name, } protected ForeignToLLVM createForeignToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java index 719aca986c0a..229dba8a1155 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java @@ -43,7 +43,6 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.nodes.ExplodeLoop; -import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMGetStackNode; @@ -128,6 +127,6 @@ public Object fallback(Object value) { } protected ForeignToLLVM createForeignToLLVM() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java index a5edb315afda..bd050ebb60ea 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java @@ -35,7 +35,6 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; import com.oracle.truffle.llvm.runtime.library.internal.LLVMNativeLibrary; @@ -109,7 +108,7 @@ public static ManagedToComparableValue createUseOffset() { } protected ForeignToLLVM createForeignToI64() { - return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I64); + return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I64); } } } From cd95fe01fc9775da583c6f524c2ff278e6b96d71 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Tue, 1 Oct 2019 16:19:08 +0200 Subject: [PATCH 100/140] Added the nodeFactory back to LLVMNode because it is still required by ForeignToLLVM -- which is overwritten by managed for the I64 case. --- .../oracle/truffle/llvm/runtime/CommonNodeFactory.java | 10 ---------- .../llvm/runtime/interop/LLVMForeignCallNode.java | 3 +-- .../runtime/interop/export/LLVMForeignWriteNode.java | 2 +- .../truffle/llvm/runtime/nodes/api/LLVMNode.java | 6 ++++++ 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 1e333597b45a..f28c8d061e49 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -8,16 +8,6 @@ import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; import com.oracle.truffle.llvm.runtime.debug.value.LLVMSourceTypeFactory; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; -import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; -import com.oracle.truffle.llvm.runtime.interop.convert.ToDoubleNodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToFloatNodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI16NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI1NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI32NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI64NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI8NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStoreNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugValueNodeGen; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java index 643c4e870860..43fa7745c8af 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java @@ -40,7 +40,6 @@ import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMGetStackNode; @@ -76,7 +75,7 @@ abstract static class PackForeignArgumentsNode extends LLVMNode { for (int i = 0; i < parameterTypes.length; i++) { LLVMInteropType interopParameterType = interopFunctionType.getParameter(i); if (interopParameterType instanceof LLVMInteropType.Value) { - toLLVM[i] = CommonNodeFactory.createForeignToLLVM((LLVMInteropType.Value) interopParameterType); + toLLVM[i] = nodeFactory.createForeignToLLVM((LLVMInteropType.Value) interopParameterType); } else { // interop only supported for value types toLLVM[i] = nodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java index 5340427195e1..7594516df3f0 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java @@ -78,6 +78,6 @@ LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind) { } protected ForeignToLLVM createForeignToLLVM(LLVMInteropType.Value type) { - return CommonNodeFactory.createForeignToLLVM(type); + return getNodeFactory().createForeignToLLVM(type); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java index 499955d70615..d9af2ed429d5 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java @@ -39,6 +39,7 @@ import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMLanguage; +import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.memory.LLVMMemory; import com.oracle.truffle.llvm.runtime.memory.UnsafeArrayAccess; @@ -68,6 +69,11 @@ public abstract class LLVMNode extends Node { public static final int ADDRESS_SIZE_IN_BYTES = 8; + public static NodeFactory getNodeFactory() { + CompilerAsserts.neverPartOfCompilation(); + return LLVMLanguage.getLanguage().getNodeFactory(); + } + public static LLVMMemory getLLVMMemory() { CompilerAsserts.neverPartOfCompilation(); return LLVMLanguage.getLanguage().getCapability(LLVMMemory.class); From fa4e8ba8496479a74adf66604a603e87fbd7e436 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Wed, 2 Oct 2019 15:20:58 +0200 Subject: [PATCH 101/140] Move CreateDebugFrameValue and CreateDebugStaticValue to CommonNodeFactory. --- .../parser/factories/BasicNodeFactory.java | 90 ------------------- .../parser/LLVMBitcodeFunctionVisitor.java | 12 ++- .../truffle/llvm/parser/LLVMParser.java | 12 +-- .../parser/LazyToTruffleConverterImpl.java | 5 +- .../nodes/LLVMBitcodeInstructionVisitor.java | 8 +- .../nodes/LLVMRuntimeDebugInformation.java | 7 +- .../llvm/runtime/CommonNodeFactory.java | 68 ++++++++++++++ .../truffle/llvm/runtime/NodeFactory.java | 8 -- .../interop/export/InteropNodeFactory.java | 8 +- .../src/com/oracle/truffle/llvm/Runner.java | 2 +- 10 files changed, 97 insertions(+), 123 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 c38f61fa3027..657d44ba553d 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 @@ -59,15 +59,11 @@ import com.oracle.truffle.llvm.runtime.LLVMUnsupportedException.UnsupportedReason; import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; -import com.oracle.truffle.llvm.runtime.debug.scope.LLVMDebugGlobalVariable; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObjectBuilder; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMFrameValueAccess; import com.oracle.truffle.llvm.runtime.except.LLVMParserException; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; -import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; @@ -223,10 +219,8 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountTrailingZeroesNodeFactory.CountTrailingZeroesI8NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugBuilder; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugInitNodeFactory; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugSimpleObjectBuilder; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugTrapNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugWriteNodeFactory; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMFrameValueAccessImpl; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugDeclarationNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugValueNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.x86.LLVMX86_64BitVACopyNodeGen; @@ -1677,12 +1671,6 @@ private LLVMStoreNode createMemoryStore(Type resolvedType) { throw new AssertionError(resolvedType); } - @Override - public LLVMStatementNode createBasicBlockNode(LLVMStatementNode[] statementNodes, LLVMControlFlowNode terminatorNode, int blockId, - String blockName) { - return LLVMBasicBlockNode.createBasicBlockNode(context, statementNodes, terminatorNode, blockId, blockName); - } - @Override public LLVMExpressionNode createFunctionBlockNode(FrameSlot exceptionValueSlot, List allFunctionNodes, UniquesRegionAllocator uniquesRegionAllocator, FrameSlot[][] beforeBlockNuller, FrameSlot[][] afterBlockNuller, LLVMStatementNode[] copyArgumentsToFrame, LLVMSourceLocation location, FrameDescriptor frameDescriptor) { @@ -2229,12 +2217,6 @@ public LLVMStatementNode createDebugValueUpdate(boolean isDeclaration, LLVMExpre } } - @Override - public LLVMFrameValueAccess createDebugFrameValue(FrameSlot slot, boolean isDeclaration) { - final LLVMDebugValue.Builder builder = getDebugDynamicValueBuilder(isDeclaration).createBuilder(); - return new LLVMFrameValueAccessImpl(slot, builder); - } - @Override public LLVMStatementNode createDebugValueInit(FrameSlot targetSlot, int[] offsets, int[] lengths) { if (offsets == null || lengths == null) { @@ -2244,30 +2226,6 @@ public LLVMStatementNode createDebugValueInit(FrameSlot targetSlot, int[] offset } } - @Override - public LLVMDebugObjectBuilder createDebugStaticValue(LLVMExpressionNode valueNode, boolean isGlobal) { - LLVMDebugValue.Builder toDebugNode = createDebugValueBuilder(); - - Object value = null; - if (isGlobal) { - assert valueNode instanceof LLVMAccessGlobalVariableStorageNode; - LLVMAccessGlobalVariableStorageNode node = (LLVMAccessGlobalVariableStorageNode) valueNode; - value = new LLVMDebugGlobalVariable(node.getDescriptor()); - } else { - try { - value = valueNode.executeGeneric(null); - } catch (Throwable ignored) { - // constant values should not need frame access - } - } - - if (value != null) { - return LLVMDebugSimpleObjectBuilder.create(toDebugNode, value); - } else { - return LLVMDebugObjectBuilder.UNAVAILABLE; - } - } - @Override public LLVMDebugValue.Builder createDebugValueBuilder() { return LLVMToDebugValueNodeGen.create(); @@ -2380,30 +2338,6 @@ private static LLVMExpressionNode[] createNullAddressLiteralNodes(int nrElements return addressZeroInits; } - @Override - public LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind) { - switch (kind) { - case I1: - return LLVMI1LoadNodeGen.create(null); - case I8: - return LLVMI8LoadNodeGen.create(null); - case I16: - return LLVMI16LoadNodeGen.create(null); - case I32: - return LLVMI32LoadNodeGen.create(null); - case I64: - return LLVMI64LoadNodeGen.create(null); - case FLOAT: - return LLVMFloatLoadNodeGen.create(null); - case DOUBLE: - return LLVMDoubleLoadNodeGen.create(null); - case POINTER: - return LLVMPointerDirectLoadNodeGen.create(null); - default: - throw new IllegalStateException("unexpected interop kind " + kind); - } - } - private static LLVMLoadNode createLoad(Type resultType, LLVMExpressionNode loadTarget, int bits) { if (resultType instanceof PrimitiveType) { switch (((PrimitiveType) resultType).getPrimitiveKind()) { @@ -2437,30 +2371,6 @@ private static LLVMLoadNode createLoad(Type resultType, LLVMExpressionNode loadT } } - @Override - public LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind) { - switch (kind) { - case I1: - return LLVMI1StoreNodeGen.create(null, null); - case I8: - return LLVMI8StoreNodeGen.create(null, null); - case I16: - return LLVMI16StoreNodeGen.create(null, null); - case I32: - return LLVMI32StoreNodeGen.create(null, null); - case I64: - return LLVMI64StoreNodeGen.create(null, null); - case FLOAT: - return LLVMFloatStoreNodeGen.create(null, null); - case DOUBLE: - return LLVMDoubleStoreNodeGen.create(null, null); - case POINTER: - return LLVMPointerStoreNodeGen.create(null, null); - default: - throw new IllegalStateException("unexpected interop kind " + kind); - } - } - private LLVMStatementNode createStore(LLVMExpressionNode pointerNode, LLVMExpressionNode valueNode, Type type, int size) { if (type instanceof PrimitiveType) { switch (((PrimitiveType) type).getPrimitiveKind()) { diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMBitcodeFunctionVisitor.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMBitcodeFunctionVisitor.java index bcd08d707859..81d950503cfe 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMBitcodeFunctionVisitor.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMBitcodeFunctionVisitor.java @@ -46,8 +46,10 @@ import com.oracle.truffle.llvm.parser.nodes.LLVMBitcodeInstructionVisitor; import com.oracle.truffle.llvm.parser.nodes.LLVMRuntimeDebugInformation; import com.oracle.truffle.llvm.parser.nodes.LLVMSymbolReadResolver; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMContext.ExternalLibrary; +import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.memory.LLVMStack.UniquesRegion; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode; @@ -68,10 +70,11 @@ final class LLVMBitcodeFunctionVisitor implements FunctionVisitor { private final LLVMRuntimeDebugInformation dbgInfoHandler; private boolean initDebugValues; private final DataLayout dataLayout; + private final NodeFactory nodeFactory; LLVMBitcodeFunctionVisitor(LLVMContext context, ExternalLibrary library, FrameDescriptor frame, UniquesRegion uniquesRegion, Map> phis, int argCount, - LLVMSymbolReadResolver symbols, FunctionDefinition functionDefinition, LLVMLivenessAnalysisResult liveness, List notNullable, - LLVMRuntimeDebugInformation dbgInfoHandler, DataLayout dataLayout) { + LLVMSymbolReadResolver symbols, FunctionDefinition functionDefinition, LLVMLivenessAnalysisResult liveness, List notNullable, + LLVMRuntimeDebugInformation dbgInfoHandler, DataLayout dataLayout, NodeFactory nodeFactory) { this.context = context; this.library = library; this.frame = frame; @@ -86,6 +89,7 @@ final class LLVMBitcodeFunctionVisitor implements FunctionVisitor { this.blocks = new ArrayList<>(); this.initDebugValues = dbgInfoHandler.isEnabled(); this.dataLayout = dataLayout; + this.nodeFactory = nodeFactory; } public List getBlocks() { @@ -101,7 +105,7 @@ public void visit(InstructionBlock block) { List blockPhis = phis.get(block); ArrayList blockNullerInfos = liveness.getNullableWithinBlock()[block.getBlockIndex()]; LLVMBitcodeInstructionVisitor visitor = LLVMBitcodeInstructionVisitor.create(frame, uniquesRegion, blockPhis, argCount, symbols, context, library, blockNullerInfos, notNullable, - dbgInfoHandler, dataLayout); + dbgInfoHandler, dataLayout, nodeFactory); if (initDebugValues) { for (SourceVariable variable : function.getSourceFunction().getVariables()) { @@ -118,6 +122,6 @@ public void visit(InstructionBlock block) { visitor.setInstructionIndex(i); instruction.accept(visitor); } - blocks.add(context.getLanguage().getNodeFactory().createBasicBlockNode(visitor.getInstructions(), visitor.getControlFlowNode(), block.getBlockIndex(), block.getName())); + blocks.add(CommonNodeFactory.createBasicBlockNode(visitor.getInstructions(), visitor.getControlFlowNode(), block.getBlockIndex(), block.getName(), context)); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java index 5a85adebfb56..e7ea3425e63a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMParser.java @@ -42,6 +42,7 @@ import com.oracle.truffle.llvm.parser.model.symbols.globals.GlobalAlias; import com.oracle.truffle.llvm.parser.model.symbols.globals.GlobalVariable; import com.oracle.truffle.llvm.parser.nodes.LLVMSymbolReadResolver; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.GetStackSpaceFactory; import com.oracle.truffle.llvm.runtime.LLVMAlias; import com.oracle.truffle.llvm.runtime.LLVMContext; @@ -50,7 +51,6 @@ import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor.Function; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor.LazyLLVMIRFunction; import com.oracle.truffle.llvm.runtime.LLVMSymbol; -import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.debug.LLVMSourceContext; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObjectBuilder; @@ -72,7 +72,7 @@ public LLVMParser(Source source, LLVMParserRuntime runtime) { this.library = runtime.getLibrary(); } - public LLVMParserResult parse(ModelModule module, DataLayout targetDataLayout, NodeFactory nodeFactory) { + public LLVMParserResult parse(ModelModule module, DataLayout targetDataLayout) { List externalGlobals = new ArrayList<>(); List definedGlobals = new ArrayList<>(); List externalFunctions = new ArrayList<>(); @@ -83,7 +83,7 @@ public LLVMParserResult parse(ModelModule module, DataLayout targetDataLayout, N defineAliases(module.getAliases(), importedSymbols); LLVMSymbolReadResolver symbolResolver = new LLVMSymbolReadResolver(runtime, StackManager.createRootFrame(), GetStackSpaceFactory.createAllocaFactory(), targetDataLayout); - createDebugInfo(module, symbolResolver, nodeFactory); + createDebugInfo(module, symbolResolver); return new LLVMParserResult(runtime, externalFunctions, definedGlobals, externalGlobals, importedSymbols, targetDataLayout); } @@ -221,19 +221,19 @@ private void defineAlias(String existingName, boolean existingExported, String n } } - private void createDebugInfo(ModelModule model, LLVMSymbolReadResolver symbolResolver, NodeFactory nodeFactory) { + private void createDebugInfo(ModelModule model, LLVMSymbolReadResolver symbolResolver) { if (context.getEnv().getOptions().get(SulongEngineOption.ENABLE_LVI)) { final LLVMSourceContext sourceContext = context.getSourceContext(); model.getSourceGlobals().forEach((symbol, irValue) -> { final LLVMExpressionNode node = symbolResolver.resolve(irValue); - final LLVMDebugObjectBuilder value = nodeFactory.createDebugStaticValue(node, irValue instanceof GlobalVariable); + final LLVMDebugObjectBuilder value = CommonNodeFactory.createDebugStaticValue(node, irValue instanceof GlobalVariable); sourceContext.registerStatic(symbol, value); }); model.getSourceStaticMembers().forEach(((type, symbol) -> { final LLVMExpressionNode node = symbolResolver.resolve(symbol); - final LLVMDebugObjectBuilder value = nodeFactory.createDebugStaticValue(node, symbol instanceof GlobalVariable); + final LLVMDebugObjectBuilder value = CommonNodeFactory.createDebugStaticValue(node, symbol instanceof GlobalVariable); type.setValue(value); })); } 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 fcf3b4747e23..9d3da7c59028 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 @@ -59,6 +59,7 @@ import com.oracle.truffle.llvm.parser.nodes.LLVMSymbolReadResolver; import com.oracle.truffle.llvm.runtime.GetStackSpaceFactory; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor.LazyToTruffleConverter; +import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceFunctionType; @@ -80,6 +81,7 @@ public class LazyToTruffleConverterImpl implements LazyToTruffleConverter { private final LazyFunctionParser parser; private final DebugInfoFunctionProcessor diProcessor; private final DataLayout dataLayout; + private final NodeFactory nodeFactory; private RootCallTarget resolved; @@ -92,6 +94,7 @@ public class LazyToTruffleConverterImpl implements LazyToTruffleConverter { this.diProcessor = diProcessor; this.resolved = null; this.dataLayout = dataLayout; + this.nodeFactory = runtime.getNodeFactory(); } @Override @@ -132,7 +135,7 @@ private RootCallTarget generateCallTarget() { dbgInfoHandler.registerStaticDebugSymbols(method); LLVMBitcodeFunctionVisitor visitor = new LLVMBitcodeFunctionVisitor(runtime.getContext(), runtime.getLibrary(), frame, uniquesRegion, phis, method.getParameters().size(), symbols, method, - liveness, notNullable, dbgInfoHandler, dataLayout); + liveness, notNullable, dbgInfoHandler, dataLayout, nodeFactory); method.accept(visitor); FrameSlot[][] nullableBeforeBlock = getNullableFrameSlots(liveness.getFrameSlots(), liveness.getNullableBeforeBlock(), notNullable); FrameSlot[][] nullableAfterBlock = getNullableFrameSlots(liveness.getFrameSlots(), liveness.getNullableAfterBlock(), notNullable); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java index 0bc61577ad7a..982010e7abc0 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java @@ -116,8 +116,8 @@ public final class LLVMBitcodeInstructionVisitor implements SymbolVisitor { public static LLVMBitcodeInstructionVisitor create(FrameDescriptor frame, UniquesRegion uniquesRegion, List blockPhis, int argCount, LLVMSymbolReadResolver symbols, LLVMContext context, ExternalLibrary library, ArrayList nullerInfos, List notNullable, LLVMRuntimeDebugInformation dbgInfoHandler, - DataLayout dataLayout) { - return new LLVMBitcodeInstructionVisitor(frame, uniquesRegion, blockPhis, argCount, symbols, context, library, nullerInfos, notNullable, dbgInfoHandler, dataLayout); + DataLayout dataLayout, NodeFactory nodeFactory) { + return new LLVMBitcodeInstructionVisitor(frame, uniquesRegion, blockPhis, argCount, symbols, context, library, nullerInfos, notNullable, dbgInfoHandler, dataLayout, nodeFactory); } private final LLVMContext context; @@ -142,9 +142,9 @@ public static LLVMBitcodeInstructionVisitor create(FrameDescriptor frame, Unique private LLVMBitcodeInstructionVisitor(FrameDescriptor frame, LLVMStack.UniquesRegion uniquesRegion, List blockPhis, int argCount, LLVMSymbolReadResolver symbols, LLVMContext context, LLVMContext.ExternalLibrary library, ArrayList nullerInfos, List notNullable, - LLVMRuntimeDebugInformation dbgInfoHandler, DataLayout dataLayout) { + LLVMRuntimeDebugInformation dbgInfoHandler, DataLayout dataLayout, NodeFactory nodeFactory) { this.context = context; - this.nodeFactory = context.getLanguage().getNodeFactory(); + this.nodeFactory = nodeFactory; this.frame = frame; this.blockPhis = blockPhis; this.argCount = argCount; diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java index 32cfc439b20b..50b6762ef266 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java @@ -56,6 +56,7 @@ import com.oracle.truffle.llvm.parser.model.symbols.instructions.DbgValueInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ValueInstruction; import com.oracle.truffle.llvm.parser.model.visitors.ValueInstructionVisitor; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceSymbol; import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceType; @@ -111,7 +112,7 @@ void registerStaticAccess(SourceVariable descriptor, SymbolImpl value, boolean m private void visitFrameValue(String name) { final FrameSlot slot = frame.findFrameSlot(name); assert slot != null; - final LLVMFrameValueAccess valueAccess = context.getLanguage().getNodeFactory().createDebugFrameValue(slot, isDeclaration); + final LLVMFrameValueAccess valueAccess = CommonNodeFactory.createDebugFrameValue(slot, isDeclaration); context.getSourceContext().registerFrameValue(symbol, valueAccess); notNullableSlots.add(slot); variable.addStaticValue(); @@ -120,7 +121,7 @@ private void visitFrameValue(String name) { private void visitSimpleConstant(SymbolImpl constant) { final LLVMExpressionNode node = symbols.resolve(constant); assert node != null; - final LLVMDebugObjectBuilder value = context.getLanguage().getNodeFactory().createDebugStaticValue(node, false); + final LLVMDebugObjectBuilder value = CommonNodeFactory.createDebugStaticValue(node, false); context.getSourceContext().registerStatic(symbol, value); variable.addStaticValue(); } @@ -204,7 +205,7 @@ public void registerStaticDebugSymbols(FunctionDefinition fn) { } final LLVMSourceSymbol symbol = local.getSymbol(); - final LLVMFrameValueAccess alloc = context.getLanguage().getNodeFactory().createDebugFrameValue(frameSlot, true); + final LLVMFrameValueAccess alloc = CommonNodeFactory.createDebugFrameValue(frameSlot, true); notNullableSlots.add(frameSlot); context.getSourceContext().registerFrameValue(symbol, alloc); local.addStaticValue(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index f28c8d061e49..71932cccdae0 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -1,15 +1,27 @@ package com.oracle.truffle.llvm.runtime; +import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; +import com.oracle.truffle.llvm.runtime.debug.scope.LLVMDebugGlobalVariable; import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceType; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugManagedValue; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObject; +import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObjectBuilder; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; +import com.oracle.truffle.llvm.runtime.debug.value.LLVMFrameValueAccess; import com.oracle.truffle.llvm.runtime.debug.value.LLVMSourceTypeFactory; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; +import com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode; +import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; +import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStoreNode; +import com.oracle.truffle.llvm.runtime.nodes.base.LLVMBasicBlockNode; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugBuilder; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugSimpleObjectBuilder; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMFrameValueAccessImpl; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugDeclarationNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugValueNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMPointerDirectLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDoubleLoadNodeGen; @@ -27,6 +39,7 @@ import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI64StoreNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI8StoreNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMPointerStoreNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.others.LLVMAccessGlobalVariableStorageNode; import com.oracle.truffle.llvm.runtime.types.MetaType; import com.oracle.truffle.llvm.runtime.types.Type; import com.oracle.truffle.llvm.runtime.vector.LLVMVector; @@ -127,6 +140,61 @@ private static TruffleObject asDebuggerIRValue(Object llvmType, Object value, Da return LLVMDebugObject.instantiate(sourceType, 0L, debugValue, null); } + public static LLVMStatementNode createBasicBlockNode(LLVMStatementNode[] statementNodes, LLVMControlFlowNode terminatorNode, int blockId, + String blockName, LLVMContext context) { + return LLVMBasicBlockNode.createBasicBlockNode(context, statementNodes, terminatorNode, blockId, blockName); + } + + public static LLVMFrameValueAccess createDebugFrameValue(FrameSlot slot, boolean isDeclaration) { + final LLVMDebugValue.Builder builder = getDebugDynamicValueBuilder(isDeclaration).createBuilder(); + return new LLVMFrameValueAccessImpl(slot, builder); + } + + // these have no internal state but are used often, so we cache and reuse them + private static LLVMDebugBuilder debugDeclarationBuilder = null; + private static LLVMDebugBuilder debugValueBuilder = null; + + private static LLVMDebugBuilder getDebugDynamicValueBuilder(boolean isDeclaration) { + if (isDeclaration) { + if (debugDeclarationBuilder == null) { + debugDeclarationBuilder = CommonNodeFactory::createDebugDeclarationBuilder; + } + return debugDeclarationBuilder; + } else { + if (debugValueBuilder == null) { + debugValueBuilder = CommonNodeFactory::createDebugValueBuilder; + } + return debugValueBuilder; + } + } + + public static LLVMDebugObjectBuilder createDebugStaticValue(LLVMExpressionNode valueNode, boolean isGlobal) { + LLVMDebugValue.Builder toDebugNode = createDebugValueBuilder(); + + Object value = null; + if (isGlobal) { + assert valueNode instanceof LLVMAccessGlobalVariableStorageNode; + LLVMAccessGlobalVariableStorageNode node = (LLVMAccessGlobalVariableStorageNode) valueNode; + value = new LLVMDebugGlobalVariable(node.getDescriptor()); + } else { + try { + value = valueNode.executeGeneric(null); + } catch (Throwable ignored) { + // constant values should not need frame access + } + } + + if (value != null) { + return LLVMDebugSimpleObjectBuilder.create(toDebugNode, value); + } else { + return LLVMDebugObjectBuilder.UNAVAILABLE; + } + } + + public static LLVMDebugValue.Builder createDebugDeclarationBuilder() { + return LLVMToDebugDeclarationNodeGen.create(); + } + public static LLVMDebugValue.Builder createDebugValueBuilder() { return LLVMToDebugValueNodeGen.create(); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 05f525227f05..ff72a18cb356 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -37,9 +37,7 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.llvm.runtime.LLVMContext.ExternalLibrary; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObjectBuilder; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMFrameValueAccess; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; @@ -184,8 +182,6 @@ LLVMExpressionNode createInsertValue(LLVMExpressionNode resultAggregate, LLVMExp LLVMExpressionNode createStructureConstantNode(Type structureType, GetStackSpaceFactory getStackSpaceFactory, boolean packed, Type[] types, LLVMExpressionNode[] constants); - LLVMStatementNode createBasicBlockNode(LLVMStatementNode[] statementNodes, LLVMControlFlowNode terminatorNode, int blockId, String blockName); - LLVMExpressionNode createFunctionBlockNode(FrameSlot exceptionValueSlot, List basicBlockNodes, UniquesRegionAllocator uniquesRegionAllocator, FrameSlot[][] beforeBlockNuller, FrameSlot[][] afterBlockNuller, LLVMStatementNode[] copyArgumentsToFrame, LLVMSourceLocation location, FrameDescriptor frameDescriptor); @@ -214,14 +210,10 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMStatementNode createDebugValueInit(FrameSlot targetSlot, int[] offsets, int[] lengths); - LLVMDebugObjectBuilder createDebugStaticValue(LLVMExpressionNode valueNode, boolean isGlobal); - LLVMDebugValue.Builder createDebugDeclarationBuilder(); LLVMDebugValue.Builder createDebugValueBuilder(); - LLVMFrameValueAccess createDebugFrameValue(FrameSlot slot, boolean isDeclaration); - LLVMStatementNode createDebugTrap(); LLVMMemMoveNode createMemMove(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java index 29713a1c3c01..5a7a6a2cec5b 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java @@ -29,13 +29,9 @@ */ package com.oracle.truffle.llvm.runtime.interop.export; -import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; -import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; -import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStoreNode; - public interface InteropNodeFactory { - LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind); + //LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind); - LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind); + //LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind); } diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index ed0e26380993..342cd0a3eaf0 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -686,7 +686,7 @@ private LLVMParserResult parse(List parserResults, ArrayDeque< LLVMScope fileScope = new LLVMScope(); LLVMParserRuntime runtime = new LLVMParserRuntime(context, library, fileScope, nodeFactory); LLVMParser parser = new LLVMParser(source, runtime); - LLVMParserResult parserResult = parser.parse(module, targetDataLayout, nodeFactory); + LLVMParserResult parserResult = parser.parse(module, targetDataLayout); parserResults.add(parserResult); return parserResult; } else if (!library.isNative()) { From c373487f6e35da0eae870c9f9eb3b962e8601973 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Wed, 2 Oct 2019 15:38:51 +0200 Subject: [PATCH 102/140] Format --- .../llvm/parser/factories/BasicNodeFactory.java | 10 ---------- .../llvm/parser/LLVMBitcodeFunctionVisitor.java | 4 ++-- .../parser/nodes/LLVMRuntimeDebugInformation.java | 2 +- .../truffle/llvm/runtime/CommonNodeFactory.java | 13 +++++++++++-- .../oracle/truffle/llvm/runtime/NodeFactory.java | 2 -- .../debug/scope/LLVMDebuggerScopeFactory.java | 2 +- .../runtime/interop/export/InteropNodeFactory.java | 4 ++-- .../src/com/oracle/truffle/llvm/Runner.java | 5 +++-- 8 files changed, 20 insertions(+), 22 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 657d44ba553d..83325d4f4952 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 @@ -218,7 +218,6 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountTrailingZeroesNodeFactory.CountTrailingZeroesI64NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountTrailingZeroesNodeFactory.CountTrailingZeroesI8NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugBuilder; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugInitNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugTrapNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugWriteNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugDeclarationNodeGen; @@ -2217,15 +2216,6 @@ public LLVMStatementNode createDebugValueUpdate(boolean isDeclaration, LLVMExpre } } - @Override - public LLVMStatementNode createDebugValueInit(FrameSlot targetSlot, int[] offsets, int[] lengths) { - if (offsets == null || lengths == null) { - return null; - } else { - return LLVMDebugInitNodeFactory.AggregateInitNodeGen.create(targetSlot, offsets, lengths); - } - } - @Override public LLVMDebugValue.Builder createDebugValueBuilder() { return LLVMToDebugValueNodeGen.create(); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMBitcodeFunctionVisitor.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMBitcodeFunctionVisitor.java index 81d950503cfe..b0e25975c5c6 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMBitcodeFunctionVisitor.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LLVMBitcodeFunctionVisitor.java @@ -73,8 +73,8 @@ final class LLVMBitcodeFunctionVisitor implements FunctionVisitor { private final NodeFactory nodeFactory; LLVMBitcodeFunctionVisitor(LLVMContext context, ExternalLibrary library, FrameDescriptor frame, UniquesRegion uniquesRegion, Map> phis, int argCount, - LLVMSymbolReadResolver symbols, FunctionDefinition functionDefinition, LLVMLivenessAnalysisResult liveness, List notNullable, - LLVMRuntimeDebugInformation dbgInfoHandler, DataLayout dataLayout, NodeFactory nodeFactory) { + LLVMSymbolReadResolver symbols, FunctionDefinition functionDefinition, LLVMLivenessAnalysisResult liveness, List notNullable, + LLVMRuntimeDebugInformation dbgInfoHandler, DataLayout dataLayout, NodeFactory nodeFactory) { this.context = context; this.library = library; this.frame = frame; diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java index 50b6762ef266..cf1438b961be 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java @@ -246,7 +246,7 @@ public LLVMStatementNode createInitializer(SourceVariable variable) { } } - return context.getLanguage().getNodeFactory().createDebugValueInit(targetSlot, offsets, lengths); + return CommonNodeFactory.createDebugValueInit(targetSlot, offsets, lengths); } private static final int[] CLEAR_NONE = new int[0]; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 71932cccdae0..1259de4dceb8 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -19,6 +19,7 @@ import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStoreNode; import com.oracle.truffle.llvm.runtime.nodes.base.LLVMBasicBlockNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugBuilder; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugInitNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugSimpleObjectBuilder; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMFrameValueAccessImpl; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugDeclarationNodeGen; @@ -46,7 +47,7 @@ public class CommonNodeFactory { - public CommonNodeFactory(){ + public CommonNodeFactory() { } public static LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind) { @@ -141,7 +142,7 @@ private static TruffleObject asDebuggerIRValue(Object llvmType, Object value, Da } public static LLVMStatementNode createBasicBlockNode(LLVMStatementNode[] statementNodes, LLVMControlFlowNode terminatorNode, int blockId, - String blockName, LLVMContext context) { + String blockName, LLVMContext context) { return LLVMBasicBlockNode.createBasicBlockNode(context, statementNodes, terminatorNode, blockId, blockName); } @@ -191,6 +192,14 @@ public static LLVMDebugObjectBuilder createDebugStaticValue(LLVMExpressionNode v } } + public static LLVMStatementNode createDebugValueInit(FrameSlot targetSlot, int[] offsets, int[] lengths) { + if (offsets == null || lengths == null) { + return null; + } else { + return LLVMDebugInitNodeFactory.AggregateInitNodeGen.create(targetSlot, offsets, lengths); + } + } + public static LLVMDebugValue.Builder createDebugDeclarationBuilder() { return LLVMToDebugDeclarationNodeGen.create(); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index ff72a18cb356..43a547f7703d 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -208,8 +208,6 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMStatementNode createDebugValueUpdate(boolean isDeclaration, LLVMExpressionNode valueRead, FrameSlot targetSlot, LLVMExpressionNode aggregateRead, int partIndex, int[] clearParts); - LLVMStatementNode createDebugValueInit(FrameSlot targetSlot, int[] offsets, int[] lengths); - LLVMDebugValue.Builder createDebugDeclarationBuilder(); LLVMDebugValue.Builder createDebugValueBuilder(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/scope/LLVMDebuggerScopeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/scope/LLVMDebuggerScopeFactory.java index 13bc3f5b9ab7..080d8cc1ea1d 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/scope/LLVMDebuggerScopeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/scope/LLVMDebuggerScopeFactory.java @@ -97,7 +97,7 @@ private static LLVMDebuggerScopeEntries getIRLevelEntries(Frame frame, LLVMConte } @TruffleBoundary - private static LLVMDebuggerScopeEntries toDebuggerScope(LLVMScope scope, DataLayout dataLayout ) { + private static LLVMDebuggerScopeEntries toDebuggerScope(LLVMScope scope, DataLayout dataLayout) { final LLVMDebuggerScopeEntries entries = new LLVMDebuggerScopeEntries(); for (LLVMSymbol symbol : scope.values()) { if (symbol.isGlobalVariable()) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java index 5a7a6a2cec5b..a2b403b46922 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java @@ -31,7 +31,7 @@ public interface InteropNodeFactory { - //LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind); + // LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind); - //LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind); + // LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind); } diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index 342cd0a3eaf0..9a0c25c4ef7b 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -362,7 +362,7 @@ private static final class InitializeSymbolsNode extends LLVMNode { final LLVMScope fileScope; - InitializeSymbolsNode(LLVMParserResult res, NodeFactory nodeFactory) { + InitializeSymbolsNode(LLVMParserResult res, NodeFactory nodeFactory) { DataLayout dataLayout = res.getDataLayout(); // allocate all non-pointer types as two structs @@ -965,7 +965,8 @@ private static LLVMStatementNode[] createStructor(String name, LLVMParserResult return LLVMStatementNode.NO_STATEMENTS; } - private static LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable globalSymbol, Comparator> priorityComparator, DataLayout dataLayout, NodeFactory nodeFactory) { + private static LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable globalSymbol, Comparator> priorityComparator, DataLayout dataLayout, + NodeFactory nodeFactory) { if (!(globalSymbol.getValue() instanceof ArrayConstant)) { // array globals of length 0 may be initialized with scalar null return LLVMStatementNode.NO_STATEMENTS; From 240120145241b9f1e5eb6c873dafd6dc099d8af1 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Wed, 2 Oct 2019 15:43:44 +0200 Subject: [PATCH 103/140] Move CreateFrameRead into CommonNodeFactory --- .../parser/factories/BasicNodeFactory.java | 76 ----------------- .../nodes/LLVMBitcodeInstructionVisitor.java | 11 +-- .../nodes/LLVMRuntimeDebugInformation.java | 2 +- .../parser/nodes/LLVMSymbolReadResolver.java | 5 +- .../llvm/runtime/CommonNodeFactory.java | 85 +++++++++++++++++++ .../truffle/llvm/runtime/NodeFactory.java | 2 - .../src/com/oracle/truffle/llvm/Runner.java | 3 +- 7 files changed, 97 insertions(+), 87 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 83325d4f4952..9182a0e4f6d2 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 @@ -368,24 +368,6 @@ import com.oracle.truffle.llvm.runtime.nodes.others.LLVMVectorSelectNodeFactory.LLVMI32VectorSelectNodeGen; import com.oracle.truffle.llvm.runtime.nodes.others.LLVMVectorSelectNodeFactory.LLVMI64VectorSelectNodeGen; import com.oracle.truffle.llvm.runtime.nodes.others.LLVMVectorSelectNodeFactory.LLVMI8VectorSelectNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVM80BitFloatReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMAddressReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMDoubleReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMFloatReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI16ReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI1ReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI32ReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI64ReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI8ReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMIReadVarBitNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMDoubleVectorReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMFloatVectorReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI16VectorReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI1VectorReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI32VectorReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI64VectorReadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI8VectorReadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMWriteNode; import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMWriteNodeFactory.LLVMWrite80BitFloatingNodeGen; import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMWriteNodeFactory.LLVMWriteDoubleNodeGen; @@ -433,7 +415,6 @@ import com.oracle.truffle.llvm.runtime.types.Type; import com.oracle.truffle.llvm.runtime.types.VariableBitWidthType; import com.oracle.truffle.llvm.runtime.types.VectorType; -import com.oracle.truffle.llvm.runtime.types.VoidType; import com.oracle.truffle.llvm.runtime.types.symbols.Symbol; public class BasicNodeFactory implements NodeFactory { @@ -852,63 +833,6 @@ public LLVMExpressionNode createFunctionCall(LLVMExpressionNode functionNode, LL return LLVMValueProfilingNode.create(callNode, type.getReturnType()); } - @Override - public LLVMExpressionNode createFrameRead(Type llvmType, FrameSlot frameSlot) { - if (llvmType instanceof PrimitiveType) { - switch (((PrimitiveType) llvmType).getPrimitiveKind()) { - case I1: - return LLVMI1ReadNodeGen.create(frameSlot); - case I8: - return LLVMI8ReadNodeGen.create(frameSlot); - case I16: - return LLVMI16ReadNodeGen.create(frameSlot); - case I32: - return LLVMI32ReadNodeGen.create(frameSlot); - case I64: - return LLVMI64ReadNodeGen.create(frameSlot); - case FLOAT: - return LLVMFloatReadNodeGen.create(frameSlot); - case DOUBLE: - return LLVMDoubleReadNodeGen.create(frameSlot); - case X86_FP80: - return LLVM80BitFloatReadNodeGen.create(frameSlot); - } - } else if (llvmType instanceof VectorType) { - Type elemType = ((VectorType) llvmType).getElementType(); - if (elemType instanceof PrimitiveType) { - switch (((PrimitiveType) elemType).getPrimitiveKind()) { - case I1: - return LLVMI1VectorReadNodeGen.create(frameSlot); - case I8: - return LLVMI8VectorReadNodeGen.create(frameSlot); - case I16: - return LLVMI16VectorReadNodeGen.create(frameSlot); - case I32: - return LLVMI32VectorReadNodeGen.create(frameSlot); - case I64: - return LLVMI64VectorReadNodeGen.create(frameSlot); - case FLOAT: - return LLVMFloatVectorReadNodeGen.create(frameSlot); - case DOUBLE: - return LLVMDoubleVectorReadNodeGen.create(frameSlot); - } - } else if (elemType instanceof PointerType || elemType instanceof FunctionType) { - return LLVMI64VectorReadNodeGen.create(frameSlot); - } - } else if (llvmType instanceof VariableBitWidthType) { - return LLVMIReadVarBitNodeGen.create(frameSlot); - } else if (llvmType instanceof PointerType || llvmType instanceof FunctionType) { - return LLVMAddressReadNodeGen.create(frameSlot); - } else if (llvmType instanceof StructureType || llvmType instanceof ArrayType) { - return LLVMAddressReadNodeGen.create(frameSlot); - } else if (llvmType instanceof VoidType) { - return LLVMUnsupportedInstructionNode.createExpression(UnsupportedReason.PARSER_ERROR_VOID_SLOT); - } else if (llvmType == MetaType.DEBUG) { - return LLVMReadNodeFactory.LLVMDebugReadNodeGen.create(frameSlot); - } - throw new AssertionError(llvmType + " for " + frameSlot.getIdentifier()); - } - @Override public LLVMWriteNode createFrameWrite(Type llvmType, LLVMExpressionNode result, FrameSlot slot) { if (llvmType instanceof VectorType) { diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java index 982010e7abc0..4f7f37a5e4bc 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java @@ -86,6 +86,7 @@ import com.oracle.truffle.llvm.parser.model.symbols.instructions.VoidInvokeInstruction; import com.oracle.truffle.llvm.parser.model.visitors.SymbolVisitor; import com.oracle.truffle.llvm.parser.util.LLVMBitcodeTypeHelper; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMContext.ExternalLibrary; import com.oracle.truffle.llvm.runtime.NodeFactory; @@ -250,7 +251,7 @@ public void visit(CallInstruction call) { final Type[] argTypes = new Type[argumentCount]; int argIndex = 0; // stack pointer - argNodes[argIndex] = nodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); + argNodes[argIndex] = CommonNodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); argTypes[argIndex] = new PointerType(null); argIndex++; @@ -300,7 +301,7 @@ public void visit(LandingpadInstruction landingpadInstruction) { for (int i = 0; i < entries.length; i++) { entries[i] = symbols.resolve(landingpadInstruction.getClauseSymbols()[i]); } - LLVMExpressionNode getStack = nodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); + LLVMExpressionNode getStack = CommonNodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); LLVMExpressionNode landingPad = nodeFactory.createLandingPad(allocateLandingPadValue, getExceptionSlot(), landingpadInstruction.isCleanup(), landingpadInstruction.getClauseTypes(), entries, getStack); createFrameWrite(landingPad, landingpadInstruction); @@ -355,7 +356,7 @@ public void visit(VoidCallInstruction call) { final Type[] argsType = new Type[argumentCount]; int argIndex = 0; - args[argIndex] = nodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); + args[argIndex] = CommonNodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); argsType[argIndex] = new PointerType(null); argIndex++; @@ -399,7 +400,7 @@ public void visit(InvokeInstruction call) { final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[argumentCount]; final Type[] argTypes = new Type[argumentCount]; int argIndex = 0; - argNodes[argIndex] = nodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); + argNodes[argIndex] = CommonNodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); argTypes[argIndex] = new PointerType(null); argIndex++; if (targetType instanceof StructureType) { @@ -465,7 +466,7 @@ public void visit(VoidInvokeInstruction call) { final Type[] argsType = new Type[argumentCount]; int argIndex = 0; - args[argIndex] = nodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); + args[argIndex] = CommonNodeFactory.createFrameRead(PointerType.VOID, getStackSlot()); argsType[argIndex] = new PointerType(null); argIndex++; diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java index cf1438b961be..56b18b5ebf5b 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java @@ -320,7 +320,7 @@ LLVMStatementNode handleDebugIntrinsic(SymbolImpl value, SourceVariable variable final boolean mustDereference = isDeclaration || mustDereferenceValue(expression, variable.getSourceType(), value); final FrameSlot targetSlot = frame.findOrAddFrameSlot(variable.getSymbol(), MetaType.DEBUG, FrameSlotKind.Object); - final LLVMExpressionNode containerRead = context.getLanguage().getNodeFactory().createFrameRead(MetaType.DEBUG, targetSlot); + final LLVMExpressionNode containerRead = CommonNodeFactory.createFrameRead(MetaType.DEBUG, targetSlot); return context.getLanguage().getNodeFactory().createDebugValueUpdate(mustDereference, valueRead, targetSlot, containerRead, partIndex, clearParts); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java index 225314683078..6467ef825085 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java @@ -64,6 +64,7 @@ import com.oracle.truffle.llvm.parser.model.symbols.instructions.ValueInstruction; import com.oracle.truffle.llvm.parser.model.visitors.ValueInstructionVisitor; import com.oracle.truffle.llvm.parser.util.LLVMBitcodeTypeHelper; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.GetStackSpaceFactory; import com.oracle.truffle.llvm.runtime.LLVMSymbol; import com.oracle.truffle.llvm.runtime.NodeFactory; @@ -415,13 +416,13 @@ public void visit(GlobalVariable global) { @Override public void visit(FunctionParameter param) { final FrameSlot slot = frame.findFrameSlot(param.getName()); - resolvedNode = nodeFactory.createFrameRead(param.getType(), slot); + resolvedNode = CommonNodeFactory.createFrameRead(param.getType(), slot); } @Override public void visitValueInstruction(ValueInstruction value) { final FrameSlot slot = frame.findFrameSlot(value.getName()); - resolvedNode = nodeFactory.createFrameRead(value.getType(), slot); + resolvedNode = CommonNodeFactory.createFrameRead(value.getType(), slot); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 1259de4dceb8..afc130a57f30 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -2,6 +2,7 @@ import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.llvm.runtime.LLVMUnsupportedException.UnsupportedReason; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMDebugGlobalVariable; import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceType; @@ -41,8 +42,35 @@ import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI8StoreNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMPointerStoreNodeGen; import com.oracle.truffle.llvm.runtime.nodes.others.LLVMAccessGlobalVariableStorageNode; +import com.oracle.truffle.llvm.runtime.nodes.others.LLVMUnsupportedInstructionNode; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVM80BitFloatReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMAddressReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMDoubleReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMFloatReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI16ReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI1ReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI32ReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI64ReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMI8ReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadNodeFactory.LLVMIReadVarBitNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMDoubleVectorReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMFloatVectorReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI16VectorReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI1VectorReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI32VectorReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI64VectorReadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMReadVectorNodeFactory.LLVMI8VectorReadNodeGen; +import com.oracle.truffle.llvm.runtime.types.ArrayType; +import com.oracle.truffle.llvm.runtime.types.FunctionType; import com.oracle.truffle.llvm.runtime.types.MetaType; +import com.oracle.truffle.llvm.runtime.types.PointerType; +import com.oracle.truffle.llvm.runtime.types.PrimitiveType; +import com.oracle.truffle.llvm.runtime.types.StructureType; import com.oracle.truffle.llvm.runtime.types.Type; +import com.oracle.truffle.llvm.runtime.types.VariableBitWidthType; +import com.oracle.truffle.llvm.runtime.types.VectorType; +import com.oracle.truffle.llvm.runtime.types.VoidType; import com.oracle.truffle.llvm.runtime.vector.LLVMVector; public class CommonNodeFactory { @@ -200,6 +228,63 @@ public static LLVMStatementNode createDebugValueInit(FrameSlot targetSlot, int[] } } + public static LLVMExpressionNode createFrameRead(Type llvmType, FrameSlot frameSlot) { + if (llvmType instanceof PrimitiveType) { + switch (((PrimitiveType) llvmType).getPrimitiveKind()) { + case I1: + return LLVMI1ReadNodeGen.create(frameSlot); + case I8: + return LLVMI8ReadNodeGen.create(frameSlot); + case I16: + return LLVMI16ReadNodeGen.create(frameSlot); + case I32: + return LLVMI32ReadNodeGen.create(frameSlot); + case I64: + return LLVMI64ReadNodeGen.create(frameSlot); + case FLOAT: + return LLVMFloatReadNodeGen.create(frameSlot); + case DOUBLE: + return LLVMDoubleReadNodeGen.create(frameSlot); + case X86_FP80: + return LLVM80BitFloatReadNodeGen.create(frameSlot); + } + } else if (llvmType instanceof VectorType) { + Type elemType = ((VectorType) llvmType).getElementType(); + if (elemType instanceof PrimitiveType) { + switch (((PrimitiveType) elemType).getPrimitiveKind()) { + case I1: + return LLVMI1VectorReadNodeGen.create(frameSlot); + case I8: + return LLVMI8VectorReadNodeGen.create(frameSlot); + case I16: + return LLVMI16VectorReadNodeGen.create(frameSlot); + case I32: + return LLVMI32VectorReadNodeGen.create(frameSlot); + case I64: + return LLVMI64VectorReadNodeGen.create(frameSlot); + case FLOAT: + return LLVMFloatVectorReadNodeGen.create(frameSlot); + case DOUBLE: + return LLVMDoubleVectorReadNodeGen.create(frameSlot); + } + } else if (elemType instanceof PointerType || elemType instanceof FunctionType) { + return LLVMI64VectorReadNodeGen.create(frameSlot); + } + } else if (llvmType instanceof VariableBitWidthType) { + return LLVMIReadVarBitNodeGen.create(frameSlot); + } else if (llvmType instanceof PointerType || llvmType instanceof FunctionType) { + return LLVMAddressReadNodeGen.create(frameSlot); + } else if (llvmType instanceof StructureType || llvmType instanceof ArrayType) { + return LLVMAddressReadNodeGen.create(frameSlot); + } else if (llvmType instanceof VoidType) { + return LLVMUnsupportedInstructionNode.createExpression(UnsupportedReason.PARSER_ERROR_VOID_SLOT); + } else if (llvmType == MetaType.DEBUG) { + return LLVMReadNodeFactory.LLVMDebugReadNodeGen.create(frameSlot); + } + throw new AssertionError(llvmType + " for " + frameSlot.getIdentifier()); + } + + public static LLVMDebugValue.Builder createDebugDeclarationBuilder() { return LLVMToDebugDeclarationNodeGen.create(); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 43a547f7703d..c672b0c6f948 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -118,8 +118,6 @@ LLVMControlFlowNode createFunctionInvoke(FrameSlot resultLocation, LLVMExpressio int unwindIndex, LLVMStatementNode normalPhiWriteNodes, LLVMStatementNode unwindPhiWriteNodes); - LLVMExpressionNode createFrameRead(Type llvmType, FrameSlot frameSlot); - LLVMStatementNode createFrameWrite(Type llvmType, LLVMExpressionNode result, FrameSlot slot); LLVMExpressionNode createComparison(CompareOperator operator, Type type, LLVMExpressionNode lhs, LLVMExpressionNode rhs); diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index 9a0c25c4ef7b..d3dc6f4e284d 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -79,6 +79,7 @@ import com.oracle.truffle.llvm.parser.nodes.LLVMSymbolReadResolver; import com.oracle.truffle.llvm.parser.scanner.LLVMScanner; import com.oracle.truffle.llvm.parser.util.Pair; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.GetStackSpaceFactory; import com.oracle.truffle.llvm.runtime.LLVMAlias; import com.oracle.truffle.llvm.runtime.LLVMContext; @@ -994,7 +995,7 @@ private static LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVa final LLVMExpressionNode functionLoadTarget = nodeFactory.createTypedElementPointer(loadedStruct, oneLiteralNode, indexedTypeLength, functionType); final LLVMExpressionNode loadedFunction = nodeFactory.createLoad(functionType, functionLoadTarget); final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[]{ - nodeFactory.createFrameRead(PointerType.VOID, rootFrame.findFrameSlot(LLVMStack.FRAME_ID))}; + CommonNodeFactory.createFrameRead(PointerType.VOID, rootFrame.findFrameSlot(LLVMStack.FRAME_ID))}; final LLVMStatementNode functionCall = LLVMVoidStatementNodeGen.create(nodeFactory.createFunctionCall(loadedFunction, argNodes, functionType)); final StructureConstant structorDefinition = (StructureConstant) arrayConstant.getElement(i); From 6f854801064bf2f16381544408583500b3501152 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Wed, 2 Oct 2019 15:59:51 +0200 Subject: [PATCH 104/140] Move CreateDebugValueUpdate into CommonNodeFactory --- .../parser/factories/BasicNodeFactory.java | 30 ------------------- .../nodes/LLVMRuntimeDebugInformation.java | 2 +- .../llvm/runtime/CommonNodeFactory.java | 9 ++++++ .../truffle/llvm/runtime/NodeFactory.java | 2 -- 4 files changed, 10 insertions(+), 33 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 9182a0e4f6d2..d576a6f2e9d8 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 @@ -217,9 +217,7 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountTrailingZeroesNodeFactory.CountTrailingZeroesI32NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountTrailingZeroesNodeFactory.CountTrailingZeroesI64NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountTrailingZeroesNodeFactory.CountTrailingZeroesI8NodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugBuilder; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugTrapNode; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugWriteNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugDeclarationNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugValueNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.x86.LLVMX86_64BitVACopyNodeGen; @@ -2112,34 +2110,6 @@ public LLVMExpressionNode createVarArgCompoundValue(int length, int alignment, L return LLVMVarArgCompoundAddressNodeGen.create(parameterNode, length, alignment); } - // these have no internal state but are used often, so we cache and reuse them - private LLVMDebugBuilder debugDeclarationBuilder = null; - private LLVMDebugBuilder debugValueBuilder = null; - - private LLVMDebugBuilder getDebugDynamicValueBuilder(boolean isDeclaration) { - if (isDeclaration) { - if (debugDeclarationBuilder == null) { - debugDeclarationBuilder = LLVMDebugBuilder.createDeclaration(this); - } - return debugDeclarationBuilder; - } else { - if (debugValueBuilder == null) { - debugValueBuilder = LLVMDebugBuilder.createValue(this); - } - return debugValueBuilder; - } - } - - @Override - public LLVMStatementNode createDebugValueUpdate(boolean isDeclaration, LLVMExpressionNode valueRead, FrameSlot targetSlot, LLVMExpressionNode containerRead, int partIndex, int[] clearParts) { - final LLVMDebugBuilder builder = getDebugDynamicValueBuilder(isDeclaration); - if (partIndex < 0 || clearParts == null) { - return LLVMDebugWriteNodeFactory.SimpleWriteNodeGen.create(builder, targetSlot, valueRead); - } else { - return LLVMDebugWriteNodeFactory.AggregateWriteNodeGen.create(builder, partIndex, clearParts, containerRead, valueRead); - } - } - @Override public LLVMDebugValue.Builder createDebugValueBuilder() { return LLVMToDebugValueNodeGen.create(); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java index 56b18b5ebf5b..ea160c18dd20 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMRuntimeDebugInformation.java @@ -321,6 +321,6 @@ LLVMStatementNode handleDebugIntrinsic(SymbolImpl value, SourceVariable variable final FrameSlot targetSlot = frame.findOrAddFrameSlot(variable.getSymbol(), MetaType.DEBUG, FrameSlotKind.Object); final LLVMExpressionNode containerRead = CommonNodeFactory.createFrameRead(MetaType.DEBUG, targetSlot); - return context.getLanguage().getNodeFactory().createDebugValueUpdate(mustDereference, valueRead, targetSlot, containerRead, partIndex, clearParts); + return CommonNodeFactory.createDebugValueUpdate(mustDereference, valueRead, targetSlot, containerRead, partIndex, clearParts); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index afc130a57f30..9ac0f7a5e3f9 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -22,6 +22,7 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugBuilder; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugInitNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugSimpleObjectBuilder; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugWriteNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMFrameValueAccessImpl; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugDeclarationNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugValueNodeGen; @@ -284,6 +285,14 @@ public static LLVMExpressionNode createFrameRead(Type llvmType, FrameSlot frameS throw new AssertionError(llvmType + " for " + frameSlot.getIdentifier()); } + public static LLVMStatementNode createDebugValueUpdate(boolean isDeclaration, LLVMExpressionNode valueRead, FrameSlot targetSlot, LLVMExpressionNode containerRead, int partIndex, int[] clearParts) { + final LLVMDebugBuilder builder = getDebugDynamicValueBuilder(isDeclaration); + if (partIndex < 0 || clearParts == null) { + return LLVMDebugWriteNodeFactory.SimpleWriteNodeGen.create(builder, targetSlot, valueRead); + } else { + return LLVMDebugWriteNodeFactory.AggregateWriteNodeGen.create(builder, partIndex, clearParts, containerRead, valueRead); + } + } public static LLVMDebugValue.Builder createDebugDeclarationBuilder() { return LLVMToDebugDeclarationNodeGen.create(); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index c672b0c6f948..9984f40aef23 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -204,8 +204,6 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMExpressionNode createVarArgCompoundValue(int length, int alignment, LLVMExpressionNode parameterNode); - LLVMStatementNode createDebugValueUpdate(boolean isDeclaration, LLVMExpressionNode valueRead, FrameSlot targetSlot, LLVMExpressionNode aggregateRead, int partIndex, int[] clearParts); - LLVMDebugValue.Builder createDebugDeclarationBuilder(); LLVMDebugValue.Builder createDebugValueBuilder(); From a6e1b318e2506788c61e6d4c1e94da3d6d54a57b Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 3 Oct 2019 12:00:31 +0200 Subject: [PATCH 105/140] Initialise the nodeFactory inside the language, this will be removed once the nodeFactory is removed from the language. --- .../src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java | 6 +++++- .../src/com/oracle/truffle/llvm/Runner.java | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) 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 817b33f0ef89..3e126c4a57a1 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 @@ -87,7 +87,7 @@ public class LLVMLanguage extends TruffleLanguage { public static final String ID = "llvm"; static final String NAME = "LLVM"; - @CompilationFinal private NodeFactory nodeFactory; + private NodeFactory nodeFactory; @CompilationFinal private List contextExtensions; public abstract static class Loader implements LLVMCapability { @@ -176,6 +176,10 @@ public NodeFactory getNodeFactory() { return nodeFactory; } + public void setNodeFactory(NodeFactory nodeFactory){ + this.nodeFactory = nodeFactory; + } + @Override protected void initializeContext(LLVMContext context) { context.initialize(); diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index d3dc6f4e284d..a6c9e29a0f6a 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -684,6 +684,8 @@ private LLVMParserResult parse(List parserResults, ArrayDeque< TargetDataLayout layout = module.getTargetDataLayout(); DataLayout targetDataLayout = new DataLayout(layout.getDataLayout()); NodeFactory nodeFactory = context.getLanguage().getActiveConfiguration().createNodeFactory(context, targetDataLayout); + //This needs to be removed once the nodefactory is taken out of the language. + context.getLanguage().setNodeFactory(nodeFactory); LLVMScope fileScope = new LLVMScope(); LLVMParserRuntime runtime = new LLVMParserRuntime(context, library, fileScope, nodeFactory); LLVMParser parser = new LLVMParser(source, runtime); From b0efb7f243ad25c6833bf1ab19a223d13b35ce39 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 3 Oct 2019 12:43:11 +0200 Subject: [PATCH 106/140] Moved createLoad into CommonNodeFactory --- .../parser/factories/BasicNodeFactory.java | 71 ---------------- .../nodes/LLVMBitcodeInstructionVisitor.java | 2 +- .../llvm/runtime/CommonNodeFactory.java | 81 +++++++++++++++++++ .../truffle/llvm/runtime/LLVMContext.java | 14 ++-- .../truffle/llvm/runtime/NodeFactory.java | 2 - .../llvm/runtime/debug/LLDBSupport.java | 3 +- .../src/com/oracle/truffle/llvm/Runner.java | 10 ++- 7 files changed, 97 insertions(+), 86 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 d576a6f2e9d8..c0b30ad736cf 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 @@ -512,44 +512,6 @@ public LLVMExpressionNode createShuffleVector(Type llvmType, LLVMExpressionNode throw new AssertionError(resultType + " is not supported for shufflevector"); } - @Override - public LLVMLoadNode createLoad(Type resolvedResultType, LLVMExpressionNode loadTarget) { - if (resolvedResultType instanceof VectorType) { - return createLoadVector((VectorType) resolvedResultType, loadTarget, ((VectorType) resolvedResultType).getNumberOfElements()); - } else { - int bits = resolvedResultType instanceof VariableBitWidthType ? resolvedResultType.getBitSize() : 0; - return createLoad(resolvedResultType, loadTarget, bits); - } - } - - private static LLVMLoadNode createLoadVector(VectorType resultType, LLVMExpressionNode loadTarget, int size) { - Type elemType = resultType.getElementType(); - if (elemType instanceof PrimitiveType) { - switch (((PrimitiveType) elemType).getPrimitiveKind()) { - case I1: - return LLVMLoadI1VectorNodeGen.create(loadTarget, size); - case I8: - return LLVMLoadI8VectorNodeGen.create(loadTarget, size); - case I16: - return LLVMLoadI16VectorNodeGen.create(loadTarget, size); - case I32: - return LLVMLoadI32VectorNodeGen.create(loadTarget, size); - case I64: - return LLVMLoadI64VectorNodeGen.create(loadTarget, size); - case FLOAT: - return LLVMLoadFloatVectorNodeGen.create(loadTarget, size); - case DOUBLE: - return LLVMLoadDoubleVectorNodeGen.create(loadTarget, size); - default: - throw new AssertionError(elemType + " vectors not supported"); - } - } else if (elemType instanceof PointerType || elemType instanceof FunctionType) { - return LLVMLoadPointerVectorNodeGen.create(loadTarget, size); - } else { - throw new AssertionError(elemType + " vectors not supported"); - } - } - @Override public LLVMStatementNode createStore(LLVMExpressionNode pointerNode, LLVMExpressionNode valueNode, Type type) { return createStore(pointerNode, valueNode, type, getByteSize(type)); @@ -2222,39 +2184,6 @@ private static LLVMExpressionNode[] createNullAddressLiteralNodes(int nrElements return addressZeroInits; } - private static LLVMLoadNode createLoad(Type resultType, LLVMExpressionNode loadTarget, int bits) { - if (resultType instanceof PrimitiveType) { - switch (((PrimitiveType) resultType).getPrimitiveKind()) { - case I1: - return LLVMI1LoadNodeGen.create(loadTarget); - case I8: - return LLVMI8LoadNodeGen.create(loadTarget); - case I16: - return LLVMI16LoadNodeGen.create(loadTarget); - case I32: - return LLVMI32LoadNodeGen.create(loadTarget); - case I64: - return LLVMI64LoadNodeGen.create(loadTarget); - case FLOAT: - return LLVMFloatLoadNodeGen.create(loadTarget); - case DOUBLE: - return LLVMDoubleLoadNodeGen.create(loadTarget); - case X86_FP80: - return LLVM80BitFloatDirectLoadNodeGen.create(loadTarget); - default: - throw new AssertionError(resultType); - } - } else if (resultType instanceof VariableBitWidthType) { - return LLVMIVarBitDirectLoadNodeGen.create(loadTarget, bits); - } else if (resultType instanceof StructureType || resultType instanceof ArrayType) { - return LLVMStructDirectLoadNodeGen.create(loadTarget); - } else if (resultType instanceof PointerType || resultType instanceof FunctionType) { - return LLVMPointerDirectLoadNodeGen.create(loadTarget); - } else { - throw new AssertionError(resultType); - } - } - private LLVMStatementNode createStore(LLVMExpressionNode pointerNode, LLVMExpressionNode valueNode, Type type, int size) { if (type instanceof PrimitiveType) { switch (((PrimitiveType) type).getPrimitiveKind()) { diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java index 4f7f37a5e4bc..235854682a25 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java @@ -658,7 +658,7 @@ public void visit(InsertValueInstruction insert) { @Override public void visit(LoadInstruction load) { LLVMExpressionNode source = symbols.resolve(load.getSource()); - LLVMExpressionNode result = nodeFactory.createLoad(load.getType(), source); + LLVMExpressionNode result = CommonNodeFactory.createLoad(load.getType(), source); createFrameWrite(result, load); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 9ac0f7a5e3f9..8c3ed1e2a651 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -26,7 +26,10 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMFrameValueAccessImpl; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugDeclarationNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugValueNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVM80BitFloatDirectLoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMIVarBitDirectLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMPointerDirectLoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMStructDirectLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDoubleLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMFloatLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI16LoadNodeGen; @@ -34,6 +37,14 @@ import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI32LoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI64LoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI8LoadNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMLoadVectorNodeFactory.LLVMLoadDoubleVectorNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMLoadVectorNodeFactory.LLVMLoadFloatVectorNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMLoadVectorNodeFactory.LLVMLoadI16VectorNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMLoadVectorNodeFactory.LLVMLoadI1VectorNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMLoadVectorNodeFactory.LLVMLoadI32VectorNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMLoadVectorNodeFactory.LLVMLoadI64VectorNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMLoadVectorNodeFactory.LLVMLoadI8VectorNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMLoadVectorNodeFactory.LLVMLoadPointerVectorNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMDoubleStoreNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMFloatStoreNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.store.LLVMI16StoreNodeGen; @@ -294,6 +305,76 @@ public static LLVMStatementNode createDebugValueUpdate(boolean isDeclaration, LL } } + public static LLVMLoadNode createLoad(Type resolvedResultType, LLVMExpressionNode loadTarget) { + if (resolvedResultType instanceof VectorType) { + return createLoadVector((VectorType) resolvedResultType, loadTarget, ((VectorType) resolvedResultType).getNumberOfElements()); + } else { + int bits = resolvedResultType instanceof VariableBitWidthType ? resolvedResultType.getBitSize() : 0; + return createLoad(resolvedResultType, loadTarget, bits); + } + } + + private static LLVMLoadNode createLoadVector(VectorType resultType, LLVMExpressionNode loadTarget, int size) { + Type elemType = resultType.getElementType(); + if (elemType instanceof PrimitiveType) { + switch (((PrimitiveType) elemType).getPrimitiveKind()) { + case I1: + return LLVMLoadI1VectorNodeGen.create(loadTarget, size); + case I8: + return LLVMLoadI8VectorNodeGen.create(loadTarget, size); + case I16: + return LLVMLoadI16VectorNodeGen.create(loadTarget, size); + case I32: + return LLVMLoadI32VectorNodeGen.create(loadTarget, size); + case I64: + return LLVMLoadI64VectorNodeGen.create(loadTarget, size); + case FLOAT: + return LLVMLoadFloatVectorNodeGen.create(loadTarget, size); + case DOUBLE: + return LLVMLoadDoubleVectorNodeGen.create(loadTarget, size); + default: + throw new AssertionError(elemType + " vectors not supported"); + } + } else if (elemType instanceof PointerType || elemType instanceof FunctionType) { + return LLVMLoadPointerVectorNodeGen.create(loadTarget, size); + } else { + throw new AssertionError(elemType + " vectors not supported"); + } + } + + private static LLVMLoadNode createLoad(Type resultType, LLVMExpressionNode loadTarget, int bits) { + if (resultType instanceof PrimitiveType) { + switch (((PrimitiveType) resultType).getPrimitiveKind()) { + case I1: + return LLVMI1LoadNodeGen.create(loadTarget); + case I8: + return LLVMI8LoadNodeGen.create(loadTarget); + case I16: + return LLVMI16LoadNodeGen.create(loadTarget); + case I32: + return LLVMI32LoadNodeGen.create(loadTarget); + case I64: + return LLVMI64LoadNodeGen.create(loadTarget); + case FLOAT: + return LLVMFloatLoadNodeGen.create(loadTarget); + case DOUBLE: + return LLVMDoubleLoadNodeGen.create(loadTarget); + case X86_FP80: + return LLVM80BitFloatDirectLoadNodeGen.create(loadTarget); + default: + throw new AssertionError(resultType); + } + } else if (resultType instanceof VariableBitWidthType) { + return LLVMIVarBitDirectLoadNodeGen.create(loadTarget, bits); + } else if (resultType instanceof StructureType || resultType instanceof ArrayType) { + return LLVMStructDirectLoadNodeGen.create(loadTarget); + } else if (resultType instanceof PointerType || resultType instanceof FunctionType) { + return LLVMPointerDirectLoadNodeGen.create(loadTarget); + } else { + throw new AssertionError(resultType); + } + } + public static LLVMDebugValue.Builder createDebugDeclarationBuilder() { return LLVMToDebugDeclarationNodeGen.create(); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java index 96aaba51213a..74b0a20e2ca5 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java @@ -384,13 +384,13 @@ void finalizeContext() { private CallTarget freeGlobalBlocks; - private void initFreeGlobalBlocks() { + private void initFreeGlobalBlocks(NodeFactory nodeFactory) { // lazily initialized, this is not necessary if there are no global blocks allocated if (freeGlobalBlocks == null) { freeGlobalBlocks = Truffle.getRuntime().createCallTarget(new RootNode(language) { - @Child LLVMMemoryOpNode freeRo = language.getNodeFactory().createFreeGlobalsBlock(true); - @Child LLVMMemoryOpNode freeRw = language.getNodeFactory().createFreeGlobalsBlock(false); + @Child LLVMMemoryOpNode freeRo = nodeFactory.createFreeGlobalsBlock(true); + @Child LLVMMemoryOpNode freeRw = nodeFactory.createFreeGlobalsBlock(false); @Override public Object execute(VirtualFrame frame) { @@ -759,17 +759,17 @@ public LLVMGlobal findGlobal(LLVMPointer pointer) { } @TruffleBoundary - public void registerReadOnlyGlobals(LLVMPointer nonPointerStore) { + public void registerReadOnlyGlobals(LLVMPointer nonPointerStore, NodeFactory nodeFactory) { synchronized (globalsStoreLock) { - initFreeGlobalBlocks(); + initFreeGlobalBlocks(nodeFactory); globalsReadOnlyStore.add(nonPointerStore); } } @TruffleBoundary - public void registerGlobals(LLVMPointer nonPointerStore) { + public void registerGlobals(LLVMPointer nonPointerStore, NodeFactory nodeFactory) { synchronized (globalsStoreLock) { - initFreeGlobalBlocks(); + initFreeGlobalBlocks(nodeFactory); globalsNonPointerStore.add(nonPointerStore); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 9984f40aef23..faf33e144d61 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -76,8 +76,6 @@ public interface NodeFactory extends InteropNodeFactory { LLVMExpressionNode createShuffleVector(Type llvmType, LLVMExpressionNode vector1, LLVMExpressionNode vector2, LLVMExpressionNode mask); - LLVMLoadNode createLoad(Type resolvedResultType, LLVMExpressionNode loadTarget); - LLVMStatementNode createStore(LLVMExpressionNode pointerNode, LLVMExpressionNode valueNode, Type type); LLVMExpressionNode createRMWXchg(LLVMExpressionNode pointerNode, LLVMExpressionNode valueNode, Type type); 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 b902dae26c15..fa756b3492bd 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 @@ -38,6 +38,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.object.DynamicObject; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMLanguage; import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; @@ -66,7 +67,7 @@ private static final class LoadRootNode extends RootNode { LoadRootNode(LLDBSupport dbSupport, Type loadType) { super(dbSupport.language); - loadNode = dbSupport.getNodeFactory().createLoad(loadType, null); + loadNode = CommonNodeFactory.createLoad(loadType, null); } @Override diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index a6c9e29a0f6a..6f1c651807fe 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -362,9 +362,11 @@ private static final class InitializeSymbolsNode extends LLVMNode { @Children final AllocGlobalNode[] allocGlobals; final LLVMScope fileScope; + private NodeFactory nodeFactory; InitializeSymbolsNode(LLVMParserResult res, NodeFactory nodeFactory) { DataLayout dataLayout = res.getDataLayout(); + this.nodeFactory = nodeFactory; // allocate all non-pointer types as two structs // one for read-only and one for read-write @@ -400,10 +402,10 @@ public LLVMPointer execute(LLVMContext ctx) { allocGlobals(ctx, roBase, rwBase); if (allocRoSection != null) { - ctx.registerReadOnlyGlobals(roBase); + ctx.registerReadOnlyGlobals(roBase, nodeFactory); } if (allocRwSection != null) { - ctx.registerGlobals(rwBase); + ctx.registerGlobals(rwBase, nodeFactory); } bindUnresolvedSymbols(ctx); @@ -991,11 +993,11 @@ private static LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVa final LLVMExpressionNode globalVarAddress = nodeFactory.createLiteral(global, new PointerType(globalSymbol.getType())); final LLVMExpressionNode iNode = nodeFactory.createLiteral(i, PrimitiveType.I32); final LLVMExpressionNode structPointer = nodeFactory.createTypedElementPointer(globalVarAddress, iNode, elementSize, elementType); - final LLVMExpressionNode loadedStruct = nodeFactory.createLoad(elementType, structPointer); + final LLVMExpressionNode loadedStruct = CommonNodeFactory.createLoad(elementType, structPointer); final LLVMExpressionNode oneLiteralNode = nodeFactory.createLiteral(1, PrimitiveType.I32); final LLVMExpressionNode functionLoadTarget = nodeFactory.createTypedElementPointer(loadedStruct, oneLiteralNode, indexedTypeLength, functionType); - final LLVMExpressionNode loadedFunction = nodeFactory.createLoad(functionType, functionLoadTarget); + final LLVMExpressionNode loadedFunction = CommonNodeFactory.createLoad(functionType, functionLoadTarget); final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[]{ CommonNodeFactory.createFrameRead(PointerType.VOID, rootFrame.findFrameSlot(LLVMStack.FRAME_ID))}; final LLVMStatementNode functionCall = LLVMVoidStatementNodeGen.create(nodeFactory.createFunctionCall(loadedFunction, argNodes, functionType)); From 9559c3bce00e1acf0fea811f5907f09c033610ce Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 3 Oct 2019 13:04:59 +0200 Subject: [PATCH 107/140] Switched the use of getNodeFactory in LLDBSupport for createDebugValueBuilder and createDebugDeclarationBuilder to CommonNodeFactory --- .../parser/factories/BasicNodeFactory.java | 21 ------------------- .../nodes/LLVMBitcodeInstructionVisitor.java | 2 +- .../llvm/runtime/CommonNodeFactory.java | 9 ++++++-- .../truffle/llvm/runtime/NodeFactory.java | 6 ------ .../llvm/runtime/debug/LLDBSupport.java | 4 ++-- .../llvm/debug/LLVMDebugBuilder.java | 9 ++++---- 6 files changed, 15 insertions(+), 36 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 c0b30ad736cf..2d76b8163e1d 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 @@ -60,7 +60,6 @@ import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; import com.oracle.truffle.llvm.runtime.except.LLVMParserException; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; @@ -217,9 +216,6 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountTrailingZeroesNodeFactory.CountTrailingZeroesI32NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountTrailingZeroesNodeFactory.CountTrailingZeroesI64NodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.bit.CountTrailingZeroesNodeFactory.CountTrailingZeroesI8NodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugTrapNode; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugDeclarationNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugValueNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.x86.LLVMX86_64BitVACopyNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.x86.LLVMX86_64BitVAEnd; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.x86.LLVMX86_64VAStartNodeGen; @@ -274,9 +270,7 @@ import com.oracle.truffle.llvm.runtime.nodes.memory.literal.LLVMArrayLiteralNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.literal.LLVMStructArrayLiteralNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVM80BitFloatDirectLoadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMIVarBitDirectLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMPointerDirectLoadNodeGen; -import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDirectLoadNodeFactory.LLVMStructDirectLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMDoubleLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMFloatLoadNodeGen; import com.oracle.truffle.llvm.runtime.nodes.memory.load.LLVMI16LoadNodeGen; @@ -2072,21 +2066,6 @@ public LLVMExpressionNode createVarArgCompoundValue(int length, int alignment, L return LLVMVarArgCompoundAddressNodeGen.create(parameterNode, length, alignment); } - @Override - public LLVMDebugValue.Builder createDebugValueBuilder() { - return LLVMToDebugValueNodeGen.create(); - } - - @Override - public LLVMDebugValue.Builder createDebugDeclarationBuilder() { - return LLVMToDebugDeclarationNodeGen.create(); - } - - @Override - public LLVMStatementNode createDebugTrap() { - return new LLVMDebugTrapNode(); - } - @Override public LLVMMemMoveNode createMemMove() { return NativeProfiledMemMoveNodeGen.create(); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java index 235854682a25..2756ff5b0ef7 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java @@ -344,7 +344,7 @@ public void visit(DbgValueInstruction inst) { @Override public void visit(DebugTrapInstruction inst) { - final LLVMStatementNode debugTrap = nodeFactory.createDebugTrap(); + final LLVMStatementNode debugTrap = CommonNodeFactory.createDebugTrap(); assignSourceLocation(debugTrap, inst, SourceInstrumentationStrategy.FORCED); addInstruction(debugTrap); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 8c3ed1e2a651..60e4ff7995c7 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -22,6 +22,7 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugBuilder; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugInitNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugSimpleObjectBuilder; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugTrapNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMDebugWriteNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMFrameValueAccessImpl; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug.LLVMToDebugDeclarationNodeGen; @@ -198,12 +199,12 @@ public static LLVMFrameValueAccess createDebugFrameValue(FrameSlot slot, boolean private static LLVMDebugBuilder getDebugDynamicValueBuilder(boolean isDeclaration) { if (isDeclaration) { if (debugDeclarationBuilder == null) { - debugDeclarationBuilder = CommonNodeFactory::createDebugDeclarationBuilder; + debugDeclarationBuilder = LLVMDebugBuilder.createDeclaration(); } return debugDeclarationBuilder; } else { if (debugValueBuilder == null) { - debugValueBuilder = CommonNodeFactory::createDebugValueBuilder; + debugValueBuilder = LLVMDebugBuilder.createValue(); } return debugValueBuilder; } @@ -375,6 +376,10 @@ private static LLVMLoadNode createLoad(Type resultType, LLVMExpressionNode loadT } } + public static LLVMStatementNode createDebugTrap() { + return new LLVMDebugTrapNode(); + } + public static LLVMDebugValue.Builder createDebugDeclarationBuilder() { return LLVMToDebugDeclarationNodeGen.create(); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index faf33e144d61..0a6adab70c13 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -202,12 +202,6 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMExpressionNode createVarArgCompoundValue(int length, int alignment, LLVMExpressionNode parameterNode); - LLVMDebugValue.Builder createDebugDeclarationBuilder(); - - LLVMDebugValue.Builder createDebugValueBuilder(); - - LLVMStatementNode createDebugTrap(); - LLVMMemMoveNode createMemMove(); LLVMMemSetNode createMemSet(); 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 fa756b3492bd..8d667291fd0b 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 @@ -133,14 +133,14 @@ public LLVMDebugValue build(Object irValue) { public LLVMDebugValue.Builder createDebugValueBuilder() { if (cachedDebugValueBuilder == null) { - cachedDebugValueBuilder = new WrappedBuilder(getNodeFactory().createDebugValueBuilder(), language); + cachedDebugValueBuilder = new WrappedBuilder(CommonNodeFactory.createDebugValueBuilder(), language); } return cachedDebugValueBuilder; } public LLVMDebugValue.Builder createDebugDeclarationBuilder() { if (cachedDebugDeclarationBuilder == null) { - cachedDebugDeclarationBuilder = new WrappedBuilder(getNodeFactory().createDebugDeclarationBuilder(), language); + cachedDebugDeclarationBuilder = new WrappedBuilder(CommonNodeFactory.createDebugDeclarationBuilder(), language); } return cachedDebugDeclarationBuilder; } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLVMDebugBuilder.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLVMDebugBuilder.java index 9d9b47b623b2..b9063749fc97 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLVMDebugBuilder.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLVMDebugBuilder.java @@ -29,18 +29,19 @@ */ package com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; @FunctionalInterface public interface LLVMDebugBuilder { - static LLVMDebugBuilder createDeclaration(NodeFactory nodeFactory) { - return nodeFactory::createDebugDeclarationBuilder; + static LLVMDebugBuilder createDeclaration() { + return CommonNodeFactory::createDebugDeclarationBuilder; } - static LLVMDebugBuilder createValue(NodeFactory nodeFactory) { - return nodeFactory::createDebugValueBuilder; + static LLVMDebugBuilder createValue() { + return CommonNodeFactory::createDebugValueBuilder; } LLVMDebugValue.Builder createBuilder(); From e04249e283aad2d9518de78c173efff88da4a37e Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 3 Oct 2019 13:09:19 +0200 Subject: [PATCH 108/140] Removed getNodeFactory from LLDBSupport, also some formatting. --- .../com/oracle/truffle/llvm/runtime/CommonNodeFactory.java | 3 ++- .../src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java | 2 +- .../src/com/oracle/truffle/llvm/runtime/NodeFactory.java | 2 -- .../com/oracle/truffle/llvm/runtime/debug/LLDBSupport.java | 5 ----- .../nodes/intrinsics/llvm/debug/LLVMDebugBuilder.java | 1 - .../src/com/oracle/truffle/llvm/Runner.java | 2 +- 6 files changed, 4 insertions(+), 11 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 60e4ff7995c7..7ce70e9e033b 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -297,7 +297,8 @@ public static LLVMExpressionNode createFrameRead(Type llvmType, FrameSlot frameS throw new AssertionError(llvmType + " for " + frameSlot.getIdentifier()); } - public static LLVMStatementNode createDebugValueUpdate(boolean isDeclaration, LLVMExpressionNode valueRead, FrameSlot targetSlot, LLVMExpressionNode containerRead, int partIndex, int[] clearParts) { + public static LLVMStatementNode createDebugValueUpdate(boolean isDeclaration, LLVMExpressionNode valueRead, FrameSlot targetSlot, LLVMExpressionNode containerRead, int partIndex, + int[] clearParts) { final LLVMDebugBuilder builder = getDebugDynamicValueBuilder(isDeclaration); if (partIndex < 0 || clearParts == null) { return LLVMDebugWriteNodeFactory.SimpleWriteNodeGen.create(builder, targetSlot, valueRead); 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 3e126c4a57a1..fd66b4073708 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 @@ -176,7 +176,7 @@ public NodeFactory getNodeFactory() { return nodeFactory; } - public void setNodeFactory(NodeFactory nodeFactory){ + public void setNodeFactory(NodeFactory nodeFactory) { this.nodeFactory = nodeFactory; } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 0a6adab70c13..65a06d50f52a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -37,7 +37,6 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.llvm.runtime.LLVMContext.ExternalLibrary; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; @@ -51,7 +50,6 @@ import com.oracle.truffle.llvm.runtime.memory.VarargsAreaStackAllocationNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; -import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode; import com.oracle.truffle.llvm.runtime.types.AggregateType; import com.oracle.truffle.llvm.runtime.types.ArrayType; 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 8d667291fd0b..11fec71b3c0d 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 @@ -40,7 +40,6 @@ import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMLanguage; -import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMObjectAccess; @@ -87,10 +86,6 @@ public CallTarget getLoadFunction(Type loadType) { return ret; } - private NodeFactory getNodeFactory() { - return language.getNodeFactory(); - } - public static boolean pointsToObjectAccess(LLVMPointer pointer) { if (!LLVMManagedPointer.isInstance(pointer)) { return false; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLVMDebugBuilder.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLVMDebugBuilder.java index b9063749fc97..2fe6ece8bf24 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLVMDebugBuilder.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/llvm/debug/LLVMDebugBuilder.java @@ -30,7 +30,6 @@ package com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.debug; import com.oracle.truffle.llvm.runtime.CommonNodeFactory; -import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; @FunctionalInterface diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index 6f1c651807fe..f105685e3af1 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -686,7 +686,7 @@ private LLVMParserResult parse(List parserResults, ArrayDeque< TargetDataLayout layout = module.getTargetDataLayout(); DataLayout targetDataLayout = new DataLayout(layout.getDataLayout()); NodeFactory nodeFactory = context.getLanguage().getActiveConfiguration().createNodeFactory(context, targetDataLayout); - //This needs to be removed once the nodefactory is taken out of the language. + // This needs to be removed once the nodefactory is taken out of the language. context.getLanguage().setNodeFactory(nodeFactory); LLVMScope fileScope = new LLVMScope(); LLVMParserRuntime runtime = new LLVMParserRuntime(context, library, fileScope, nodeFactory); From b380fef6528d07d8b010dfc5a43e5c9f554070cd Mon Sep 17 00:00:00 2001 From: Paley Li Date: Thu, 3 Oct 2019 15:20:04 +0200 Subject: [PATCH 109/140] Moved both createForeignToLLVM to CommonNodeFactory --- .../factories/BasicIntrinsicsProvider.java | 7 ++- .../parser/factories/BasicNodeFactory.java | 56 ----------------- .../llvm/runtime/CommonNodeFactory.java | 63 +++++++++++++++++++ .../truffle/llvm/runtime/NodeFactory.java | 4 -- .../runtime/interop/LLVMForeignCallNode.java | 13 ++-- .../llvm/runtime/interop/convert/ToLLVM.java | 17 ++--- .../interop/export/LLVMForeignWriteNode.java | 2 +- .../runtime/nodes/cast/LLVMToDoubleNode.java | 3 +- .../runtime/nodes/cast/LLVMToFloatNode.java | 3 +- .../runtime/nodes/cast/LLVMToI16Node.java | 3 +- .../llvm/runtime/nodes/cast/LLVMToI1Node.java | 3 +- .../runtime/nodes/cast/LLVMToI32Node.java | 3 +- .../llvm/runtime/nodes/cast/LLVMToI8Node.java | 3 +- .../runtime/nodes/func/LLVMDispatchNode.java | 3 +- .../intrinsics/interop/LLVMPolyglotEval.java | 3 +- .../interop/LLVMPolyglotImport.java | 3 +- .../interop/LLVMPolyglotJavaType.java | 3 +- .../interop/LLVMPolyglotNewInstance.java | 3 +- .../runtime/nodes/op/ToComparableValue.java | 3 +- 19 files changed, 107 insertions(+), 91 deletions(-) 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 821b9cf33022..f1483e85115a 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 @@ -43,6 +43,7 @@ import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.func.LLVMRaiseExceptionNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMSyscall; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotAsPrimitive; @@ -384,10 +385,10 @@ private static void registerTruffleIntrinsics() { add("polyglot_set_array_element", (args, language, types) -> LLVMPolyglotSetArrayElementNodeGen.create(types, args.get(1), args.get(2), args.get(3))); - add("polyglot_get_member", (args, language) -> LLVMPolyglotGetMemberNodeGen.create(language.getNodeFactory().createForeignToLLVM(POINTER), args.get(1), args.get(2))); + add("polyglot_get_member", (args, language) -> LLVMPolyglotGetMemberNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); add("polyglot_get_array_element", - (args, language) -> LLVMPolyglotGetArrayElementNodeGen.create(language.getNodeFactory().createForeignToLLVM(POINTER), args.get(1), args.get(2))); + (args, language) -> LLVMPolyglotGetArrayElementNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); add("polyglot_remove_member", (args, language) -> LLVMPolyglotRemoveMemberNodeGen.create(args.get(1), args.get(2))); @@ -407,7 +408,7 @@ private static void registerTruffleIntrinsics() { args.get(1))); add("polyglot_invoke", - (args, language, types) -> LLVMPolyglotInvokeNodeGen.create(language.getNodeFactory().createForeignToLLVM(POINTER), argumentsArray(args, 3, args.size() - 3), + (args, language, types) -> LLVMPolyglotInvokeNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), argumentsArray(args, 3, args.size() - 3), Arrays.copyOfRange(types, 3, types.length), args.get(1), args.get(2))); 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 2d76b8163e1d..2ad8527e4288 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 @@ -2199,58 +2199,6 @@ private LLVMStatementNode createStore(LLVMExpressionNode pointerNode, LLVMExpres } } - @Override - public ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type) { - switch (type) { - case VOID: - return ToVoidLLVMNodeGen.create(); - case ANY: - return ToAnyLLVMNodeGen.create(); - case I1: - return ToI1NodeGen.create(); - case I8: - return ToI8NodeGen.create(); - case I16: - return ToI16NodeGen.create(); - case I32: - return ToI32NodeGen.create(); - case I64: - return ToI64NodeGen.create(); - case FLOAT: - return ToFloatNodeGen.create(); - case DOUBLE: - return ToDoubleNodeGen.create(); - case POINTER: - return ToPointer.create(); - default: - throw new IllegalStateException(type.toString()); - } - } - - @Override - public ForeignToLLVM createForeignToLLVM(Value type) { - switch (type.getKind()) { - case I1: - return ToI1NodeGen.create(); - case I8: - return ToI8NodeGen.create(); - case I16: - return ToI16NodeGen.create(); - case I32: - return ToI32NodeGen.create(); - case I64: - return ToI64NodeGen.create(); - case FLOAT: - return ToFloatNodeGen.create(); - case DOUBLE: - return ToDoubleNodeGen.create(); - case POINTER: - return ToPointer.create(type.getBaseType()); - default: - throw new IllegalStateException("unexpected interop kind " + type.getKind()); - } - } - private static AssertionError unsupportedCast(Type targetType) { throw new LLVMParserException("Cannot cast to " + targetType); } @@ -2274,8 +2222,4 @@ public int getBytePadding(long offset, Type type) { public long getIndexOffset(long index, AggregateType type) { return type.getOffsetOf(index, dataLayout); } - - public DataLayout getDataSpecConverter() { - return dataLayout; - } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index 7ce70e9e033b..ec40106092a4 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -13,6 +13,19 @@ import com.oracle.truffle.llvm.runtime.debug.value.LLVMFrameValueAccess; import com.oracle.truffle.llvm.runtime.debug.value.LLVMSourceTypeFactory; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; +import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; +import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; +import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; +import com.oracle.truffle.llvm.runtime.interop.convert.ToAnyLLVMNodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToDoubleNodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToFloatNodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI16NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI1NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI32NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI64NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToI8NodeGen; +import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer; +import com.oracle.truffle.llvm.runtime.interop.convert.ToVoidLLVMNodeGen; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; @@ -377,6 +390,56 @@ private static LLVMLoadNode createLoad(Type resultType, LLVMExpressionNode loadT } } + public static ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type) { + switch (type) { + case VOID: + return ToVoidLLVMNodeGen.create(); + case ANY: + return ToAnyLLVMNodeGen.create(); + case I1: + return ToI1NodeGen.create(); + case I8: + return ToI8NodeGen.create(); + case I16: + return ToI16NodeGen.create(); + case I32: + return ToI32NodeGen.create(); + case I64: + return ToI64NodeGen.create(); + case FLOAT: + return ToFloatNodeGen.create(); + case DOUBLE: + return ToDoubleNodeGen.create(); + case POINTER: + return ToPointer.create(); + default: + throw new IllegalStateException(type.toString()); + } + } + + public static ForeignToLLVM createForeignToLLVM(Value type) { + switch (type.getKind()) { + case I1: + return ToI1NodeGen.create(); + case I8: + return ToI8NodeGen.create(); + case I16: + return ToI16NodeGen.create(); + case I32: + return ToI32NodeGen.create(); + case I64: + return ToI64NodeGen.create(); + case FLOAT: + return ToFloatNodeGen.create(); + case DOUBLE: + return ToDoubleNodeGen.create(); + case POINTER: + return ToPointer.create(type.getBaseType()); + default: + throw new IllegalStateException("unexpected interop kind " + type.getKind()); + } + } + public static LLVMStatementNode createDebugTrap() { return new LLVMDebugTrapNode(); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 65a06d50f52a..0331539063d1 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -213,8 +213,4 @@ LLVMExpressionNode createCompareExchangeInstruction(AggregateType returnType, Ty LLVMExpressionNode createStackSave(); LLVMExpressionNode createStackRestore(LLVMExpressionNode stackPointer); - - ForeignToLLVM createForeignToLLVM(LLVMInteropType.Value type); - - ForeignToLLVM createForeignToLLVM(ForeignToLLVMType type); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java index 43fa7745c8af..40a4145a649a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java @@ -40,6 +40,7 @@ import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMGetStackNode; @@ -67,7 +68,6 @@ abstract static class PackForeignArgumentsNode extends LLVMNode { @Children final ForeignToLLVM[] toLLVM; PackForeignArgumentsNode(Type[] parameterTypes, LLVMInteropType interopType) { - NodeFactory nodeFactory = getNodeFactory(); this.toLLVM = new ForeignToLLVM[parameterTypes.length]; if (interopType instanceof LLVMInteropType.Function) { LLVMInteropType.Function interopFunctionType = (LLVMInteropType.Function) interopType; @@ -75,16 +75,16 @@ abstract static class PackForeignArgumentsNode extends LLVMNode { for (int i = 0; i < parameterTypes.length; i++) { LLVMInteropType interopParameterType = interopFunctionType.getParameter(i); if (interopParameterType instanceof LLVMInteropType.Value) { - toLLVM[i] = nodeFactory.createForeignToLLVM((LLVMInteropType.Value) interopParameterType); + toLLVM[i] = CommonNodeFactory.createForeignToLLVM((LLVMInteropType.Value) interopParameterType); } else { // interop only supported for value types - toLLVM[i] = nodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); + toLLVM[i] = CommonNodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); } } } else { // no interop parameter types available for (int i = 0; i < parameterTypes.length; i++) { - toLLVM[i] = nodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); + toLLVM[i] = CommonNodeFactory.createForeignToLLVM(ForeignToLLVM.convert(parameterTypes[i])); } } } @@ -104,10 +104,9 @@ Object[] packNonVarargs(Object[] arguments, StackPointer stackPointer) { ForeignToLLVM[] createVarargsToLLVM(int argCount) { int count = argCount - toLLVM.length; if (count > 0) { - NodeFactory nodeFactory = LLVMNode.getNodeFactory(); ForeignToLLVM[] ret = new ForeignToLLVM[count]; for (int i = 0; i < count; i++) { - ret[i] = nodeFactory.createForeignToLLVM(ForeignToLLVMType.ANY); + ret[i] = CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.ANY); } return ret; } else { @@ -132,7 +131,7 @@ Object[] packCachedArgCount(Object[] arguments, StackPointer stackPointer, } ForeignToLLVM createVarargsToLLVM() { - return LLVMNode.getNodeFactory().createForeignToLLVM(ForeignToLLVMType.ANY); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.ANY); } @Specialization(guards = "arguments.length >= toLLVM.length", replaces = "packCachedArgCount") diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java index 7fcf5619a1af..6f4be4a1957e 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/convert/ToLLVM.java @@ -37,6 +37,7 @@ import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.interop.LLVMTypedForeignObject; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; @@ -321,35 +322,35 @@ static boolean isPointer(ForeignToLLVMType targetType) { } protected ForeignToLLVM createToI1() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I1); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I1); } protected ForeignToLLVM createToI8() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I8); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I8); } protected ForeignToLLVM createToI16() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I16); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I16); } protected ForeignToLLVM createToI32() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I32); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I32); } protected ForeignToLLVM createToI64() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I64); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I64); } protected ForeignToLLVM createToFloat() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.FLOAT); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.FLOAT); } protected ForeignToLLVM createToDouble() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.DOUBLE); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.DOUBLE); } protected ForeignToLLVM createToPointer() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java index 7594516df3f0..5340427195e1 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/LLVMForeignWriteNode.java @@ -78,6 +78,6 @@ LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind) { } protected ForeignToLLVM createForeignToLLVM(LLVMInteropType.Value type) { - return getNodeFactory().createForeignToLLVM(type); + return CommonNodeFactory.createForeignToLLVM(type); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java index 773025e63dd2..8c85a8aea6d8 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToDoubleNode.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -77,7 +78,7 @@ protected double doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.DOUBLE); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.DOUBLE); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java index 1ffb7b7bcdb3..6e315db2c661 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToFloatNode.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -75,7 +76,7 @@ protected float doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.FLOAT); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.FLOAT); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java index 4d8e36b2cf6d..de657355f54b 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI16Node.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; @@ -61,7 +62,7 @@ protected short doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I16); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I16); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java index 8f3068a3da3e..6de8800935c6 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI1Node.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; @@ -58,7 +59,7 @@ protected boolean doPointer(LLVMNativePointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I1); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I1); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java index 38d89edb80dd..6d519533ff5f 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI32Node.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; @@ -63,7 +64,7 @@ protected int doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I32); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I32); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java index 72506cd615b2..6a52ad0a8503 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/cast/LLVMToI8Node.java @@ -32,6 +32,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.cast.LLVMToI64Node.LLVMBitcastToI64Node; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; @@ -60,7 +61,7 @@ protected byte doPointer(LLVMPointer from, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I8); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I8); } protected boolean isForeign(LLVMManagedPointer pointer) { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java index df65f07f0847..5cef7fd50343 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/func/LLVMDispatchNode.java @@ -45,6 +45,7 @@ import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.IndirectCallNode; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor.Intrinsic; @@ -318,7 +319,7 @@ private Object[] getForeignArguments(LLVMDataEscapeNode[] dataEscapeNodes, Objec } protected ForeignToLLVM createToLLVMNode() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVM.convert(type.getReturnType())); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVM.convert(type.getReturnType())); } @TruffleBoundary diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java index 2aa4eb47f8f0..6cebfdaa6385 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotEval.java @@ -42,6 +42,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.LanguageInfo; import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; @@ -88,7 +89,7 @@ protected Object doEval(Object idPointer, Object srcPointer, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } abstract static class GetSourceNode extends LLVMNode { diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java index c84b329683fa..b4495d77bff2 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotImport.java @@ -39,6 +39,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; @@ -73,6 +74,6 @@ protected Object doImport(Object name, } ForeignToLLVM createToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java index 8e8882d44985..1147b0564b81 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotJavaType.java @@ -33,6 +33,7 @@ import com.oracle.truffle.api.dsl.CachedContext; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; @@ -56,6 +57,6 @@ protected Object doImport(Object name, } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java index 229dba8a1155..719aca986c0a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/intrinsics/interop/LLVMPolyglotNewInstance.java @@ -43,6 +43,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsic; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMGetStackNode; @@ -127,6 +128,6 @@ public Object fallback(Object value) { } protected ForeignToLLVM createForeignToLLVM() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.POINTER); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.POINTER); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java index bd050ebb60ea..a5edb315afda 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/ToComparableValue.java @@ -35,6 +35,7 @@ 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.llvm.runtime.CommonNodeFactory; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; import com.oracle.truffle.llvm.runtime.library.internal.LLVMNativeLibrary; @@ -108,7 +109,7 @@ public static ManagedToComparableValue createUseOffset() { } protected ForeignToLLVM createForeignToI64() { - return getNodeFactory().createForeignToLLVM(ForeignToLLVMType.I64); + return CommonNodeFactory.createForeignToLLVM(ForeignToLLVMType.I64); } } } From e0eb6aed8625ca886b4b1de471b76dd61d0df892 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Fri, 4 Oct 2019 12:12:38 +0200 Subject: [PATCH 110/140] Removed the getNodeFactory from LLVMNode. --- .../com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java index d9af2ed429d5..d17d1fad5925 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java @@ -69,11 +69,6 @@ public abstract class LLVMNode extends Node { public static final int ADDRESS_SIZE_IN_BYTES = 8; - public static NodeFactory getNodeFactory() { - CompilerAsserts.neverPartOfCompilation(); - return LLVMLanguage.getLanguage().getNodeFactory(); - } - public static LLVMMemory getLLVMMemory() { CompilerAsserts.neverPartOfCompilation(); return LLVMLanguage.getLanguage().getCapability(LLVMMemory.class); From b6dafdedfac69725e2d1f63f2ace19428cf81290 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Fri, 4 Oct 2019 14:13:12 +0200 Subject: [PATCH 111/140] Created new IntrinsicsFactory that takes a nodeFactory. The Intrinsics in the FunctionDescriptor now takes a nodeFactory. --- .../factories/BasicIntrinsicsProvider.java | 283 +++++++++--------- .../parser/factories/BasicNodeFactory.java | 15 +- .../llvm/runtime/LLVMFunctionDescriptor.java | 12 +- .../llvm/runtime/LLVMIntrinsicProvider.java | 4 +- .../truffle/llvm/runtime/NodeFactory.java | 3 - .../runtime/interop/LLVMForeignCallNode.java | 1 - .../llvm/runtime/nodes/api/LLVMNode.java | 1 - .../src/com/oracle/truffle/llvm/Runner.java | 9 +- 8 files changed, 157 insertions(+), 171 deletions(-) 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 f1483e85115a..fe66f9f02e84 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 @@ -44,25 +44,13 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.llvm.runtime.CommonNodeFactory; -import com.oracle.truffle.llvm.runtime.nodes.func.LLVMRaiseExceptionNode; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMSyscall; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotAsPrimitive; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotAsString; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotEval; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotFromString; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.typed.LLVMArrayTypeIDNode; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.typed.LLVMPolyglotAsTyped; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.typed.LLVMPolyglotFromTyped; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.typed.LLVMTypeIDNode; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplexDoubleDiv; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplexDoubleMul; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplexFloatDiv; -import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplexFloatMul; import com.oracle.truffle.llvm.runtime.LLVMContext.ExternalLibrary; import com.oracle.truffle.llvm.runtime.LLVMIntrinsicProvider; import com.oracle.truffle.llvm.runtime.LLVMLanguage; +import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; import com.oracle.truffle.llvm.runtime.nodes.func.LLVMArgNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.func.LLVMRaiseExceptionNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMAbortNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMCMathsIntrinsicsFactory.LLVMACosNodeGen; @@ -103,9 +91,14 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMMemIntrinsicFactory.LLVMLibcMemcpyNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMMemIntrinsicFactory.LLVMLibcMemsetNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMSignalNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMSyscall; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMLoadLibraryNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotAsPrimitive; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotAsString; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotBoxedPredicateNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotEval; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotExportNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotFromString; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotGetArraySizeNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotGetStringSizeNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMPolyglotHasMemberNodeGen; @@ -130,6 +123,10 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMTruffleReleaseHandleNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMTruffleWriteManagedToGlobalNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.LLVMVirtualMallocNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.typed.LLVMArrayTypeIDNode; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.typed.LLVMPolyglotAsTyped; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.typed.LLVMPolyglotFromTyped; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.interop.typed.LLVMTypeIDNode; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMIntrinsicRootNodeFactory.LLVMIntrinsicExpressionNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemoryIntrinsicFactory.LLVMCallocNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemoryIntrinsicFactory.LLVMFreeNodeGen; @@ -137,6 +134,10 @@ import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.LLVMMemoryIntrinsicFactory.LLVMReallocNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplex80BitFloatDivNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplex80BitFloatMulNodeGen; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplexDoubleDiv; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplexDoubleMul; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplexFloatDiv; +import com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.arith.LLVMComplexFloatMul; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.rust.LLVMPanicNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.rust.LLVMStartFactory.LLVMLangStartInternalNodeGen; import com.oracle.truffle.llvm.runtime.nodes.intrinsics.rust.LLVMStartFactory.LLVMLangStartNodeGen; @@ -165,7 +166,7 @@ public final boolean isIntrinsified(String name) { } @Override - public final RootCallTarget generateIntrinsicTarget(String name, Type[] argTypes) { + public final RootCallTarget generateIntrinsicTarget(String name, Type[] argTypes, NodeFactory nodeFactory) { CompilerAsserts.neverPartOfCompilation(); LLVMTypedIntrinsicFactory factory = getFactory(name); if (factory == null) { @@ -181,17 +182,17 @@ public LLVMExpressionNode get(int index) { public int size() { return argTypes.length; } - }, language, argTypes)); + }, nodeFactory, language, argTypes)); } @Override - public final LLVMExpressionNode generateIntrinsicNode(String name, LLVMExpressionNode[] arguments, Type[] argTypes) { + public final LLVMExpressionNode generateIntrinsicNode(String name, LLVMExpressionNode[] arguments, Type[] argTypes, NodeFactory nodeFactory) { CompilerAsserts.neverPartOfCompilation(); LLVMTypedIntrinsicFactory factory = getFactory(name); if (factory == null) { return null; } - return factory.generate(Arrays.asList(arguments), language, argTypes); + return factory.generate(Arrays.asList(arguments), nodeFactory, language, argTypes); } private LLVMTypedIntrinsicFactory getFactory(String name) { @@ -229,15 +230,15 @@ public abstract static class LLVMIntrinsicArgFactory { } public interface LLVMTypedIntrinsicFactory { - LLVMExpressionNode generate(List args, LLVMLanguage language, Type[] argTypes); + LLVMExpressionNode generate(List args, NodeFactory nodeFactory, LLVMLanguage language, Type[] argTypes); } public interface LLVMIntrinsicFactory extends LLVMTypedIntrinsicFactory { - LLVMExpressionNode generate(List args, LLVMLanguage language); + LLVMExpressionNode generate(List args, NodeFactory nodeFactory); @Override - default LLVMExpressionNode generate(List args, LLVMLanguage language, Type[] argTypes) { - return generate(args, language); + default LLVMExpressionNode generate(List args, NodeFactory nodeFactory, LLVMLanguage language, Type[] argTypes) { + return generate(args, nodeFactory); } } @@ -358,178 +359,178 @@ protected static LLVMExpressionNode[] argumentsArray(List ar } private static void registerSulongIntrinsics() { - add("__sulong_destructor_functions", (args, language) -> LLVMRunDestructorFunctionsNodeGen.create()); - add("__sulong_print_stacktrace", (args, language) -> LLVMPrintStackTraceNodeGen.create()); - add("__sulong_should_print_stacktrace_on_abort", (args, language) -> LLVMShouldPrintStackTraceOnAbortNodeGen.create()); + add("__sulong_destructor_functions", (args, nodeFactory) -> LLVMRunDestructorFunctionsNodeGen.create()); + add("__sulong_print_stacktrace", (args, nodeFactory) -> LLVMPrintStackTraceNodeGen.create()); + add("__sulong_should_print_stacktrace_on_abort", (args, nodeFactory) -> LLVMShouldPrintStackTraceOnAbortNodeGen.create()); } private static void registerTruffleIntrinsics() { - add("polyglot_import", (args, language) -> LLVMPolyglotImportNodeGen.create(args.get(1))); - add("polyglot_export", (args, language) -> LLVMPolyglotExportNodeGen.create(args.get(1), args.get(2))); - add("polyglot_eval", (args, language) -> LLVMPolyglotEval.create(args.get(1), args.get(2))); - add("polyglot_eval_file", (args, language) -> LLVMPolyglotEval.createFile(args.get(1), args.get(2))); - add("polyglot_java_type", (args, language) -> LLVMPolyglotJavaTypeNodeGen.create(args.get(1))); + add("polyglot_import", (args, nodeFactory) -> LLVMPolyglotImportNodeGen.create(args.get(1))); + add("polyglot_export", (args, nodeFactory) -> LLVMPolyglotExportNodeGen.create(args.get(1), args.get(2))); + add("polyglot_eval", (args, nodeFactory) -> LLVMPolyglotEval.create(args.get(1), args.get(2))); + add("polyglot_eval_file", (args, nodeFactory) -> LLVMPolyglotEval.createFile(args.get(1), args.get(2))); + add("polyglot_java_type", (args, nodeFactory) -> LLVMPolyglotJavaTypeNodeGen.create(args.get(1))); - add("polyglot_is_value", (args, language) -> LLVMPolyglotIsValueNodeGen.create(args.get(1))); - add("polyglot_is_number", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isNumber, args.get(1))); - add("polyglot_is_boolean", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isBoolean, args.get(1))); - add("polyglot_is_string", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isString, args.get(1))); - add("polyglot_fits_in_i8", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInByte, args.get(1))); - add("polyglot_fits_in_i16", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInShort, args.get(1))); - add("polyglot_fits_in_i32", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInInt, args.get(1))); - add("polyglot_fits_in_i64", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInLong, args.get(1))); - add("polyglot_fits_in_float", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInFloat, args.get(1))); - add("polyglot_fits_in_double", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInDouble, args.get(1))); + add("polyglot_is_value", (args, nodeFactory) -> LLVMPolyglotIsValueNodeGen.create(args.get(1))); + add("polyglot_is_number", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isNumber, args.get(1))); + add("polyglot_is_boolean", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isBoolean, args.get(1))); + add("polyglot_is_string", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isString, args.get(1))); + add("polyglot_fits_in_i8", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInByte, args.get(1))); + add("polyglot_fits_in_i16", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInShort, args.get(1))); + add("polyglot_fits_in_i32", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInInt, args.get(1))); + add("polyglot_fits_in_i64", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInLong, args.get(1))); + add("polyglot_fits_in_float", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInFloat, args.get(1))); + add("polyglot_fits_in_double", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::fitsInDouble, args.get(1))); - add("polyglot_put_member", (args, language, types) -> LLVMPolyglotPutMemberNodeGen.create(types, args.get(1), args.get(2), args.get(3))); + add("polyglot_put_member", (args, nodeFactory, language, types) -> LLVMPolyglotPutMemberNodeGen.create(types, args.get(1), args.get(2), args.get(3))); - add("polyglot_set_array_element", (args, language, types) -> LLVMPolyglotSetArrayElementNodeGen.create(types, args.get(1), args.get(2), args.get(3))); + add("polyglot_set_array_element", (args, nodeFactory, language, types) -> LLVMPolyglotSetArrayElementNodeGen.create(types, args.get(1), args.get(2), args.get(3))); - add("polyglot_get_member", (args, language) -> LLVMPolyglotGetMemberNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); + add("polyglot_get_member", (args, nodeFactory) -> LLVMPolyglotGetMemberNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); add("polyglot_get_array_element", - (args, language) -> LLVMPolyglotGetArrayElementNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); + (args, nodeFactory) -> LLVMPolyglotGetArrayElementNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), args.get(1), args.get(2))); - add("polyglot_remove_member", (args, language) -> LLVMPolyglotRemoveMemberNodeGen.create(args.get(1), args.get(2))); + add("polyglot_remove_member", (args, nodeFactory) -> LLVMPolyglotRemoveMemberNodeGen.create(args.get(1), args.get(2))); - add("polyglot_remove_array_element", (args, language) -> LLVMPolyglotRemoveArrayElementNodeGen.create(args.get(1), args.get(2))); + add("polyglot_remove_array_element", (args, nodeFactory) -> LLVMPolyglotRemoveArrayElementNodeGen.create(args.get(1), args.get(2))); - add("polyglot_as_i8", (args, language) -> LLVMPolyglotAsPrimitive.AsI8.create(args.get(1))); - add("polyglot_as_i16", (args, language) -> LLVMPolyglotAsPrimitive.AsI16.create(args.get(1))); - add("polyglot_as_i32", (args, language) -> LLVMPolyglotAsPrimitive.AsI32.create(args.get(1))); - add("polyglot_as_i64", (args, language) -> LLVMPolyglotAsPrimitive.AsI64.create(args.get(1))); - add("polyglot_as_float", (args, language) -> LLVMPolyglotAsPrimitive.AsFloat.create(args.get(1))); - add("polyglot_as_double", (args, language) -> LLVMPolyglotAsPrimitive.AsDouble.create(args.get(1))); - add("polyglot_as_boolean", (args, language) -> LLVMPolyglotAsPrimitive.AsBoolean.create(args.get(1))); + add("polyglot_as_i8", (args, nodeFactory) -> LLVMPolyglotAsPrimitive.AsI8.create(args.get(1))); + add("polyglot_as_i16", (args, nodeFactory) -> LLVMPolyglotAsPrimitive.AsI16.create(args.get(1))); + add("polyglot_as_i32", (args, nodeFactory) -> LLVMPolyglotAsPrimitive.AsI32.create(args.get(1))); + add("polyglot_as_i64", (args, nodeFactory) -> LLVMPolyglotAsPrimitive.AsI64.create(args.get(1))); + add("polyglot_as_float", (args, nodeFactory) -> LLVMPolyglotAsPrimitive.AsFloat.create(args.get(1))); + add("polyglot_as_double", (args, nodeFactory) -> LLVMPolyglotAsPrimitive.AsDouble.create(args.get(1))); + add("polyglot_as_boolean", (args, nodeFactory) -> LLVMPolyglotAsPrimitive.AsBoolean.create(args.get(1))); add("polyglot_new_instance", - (args, language, types) -> LLVMPolyglotNewInstanceNodeGen.create(argumentsArray(args, 2, args.size() - 2), + (args, nodeFactory, language, types) -> LLVMPolyglotNewInstanceNodeGen.create(argumentsArray(args, 2, args.size() - 2), Arrays.copyOfRange(types, 2, types.length), args.get(1))); add("polyglot_invoke", - (args, language, types) -> LLVMPolyglotInvokeNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), argumentsArray(args, 3, args.size() - 3), + (args, nodeFactory, language, types) -> LLVMPolyglotInvokeNodeGen.create(CommonNodeFactory.createForeignToLLVM(POINTER), argumentsArray(args, 3, args.size() - 3), Arrays.copyOfRange(types, 3, types.length), args.get(1), args.get(2))); - add("truffle_decorate_function", (args, language) -> LLVMTruffleDecorateFunctionNodeGen.create(args.get(1), args.get(2))); - add("polyglot_can_execute", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isExecutable, args.get(1))); - add("polyglot_can_instantiate", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isInstantiable, args.get(1))); - add("polyglot_is_null", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isNull, args.get(1))); - add("polyglot_has_array_elements", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::hasArrayElements, args.get(1))); - add("polyglot_has_members", (args, language) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::hasMembers, args.get(1))); - add("polyglot_has_member", (args, language) -> LLVMPolyglotHasMemberNodeGen.create(args.get(1), args.get(2))); - add("polyglot_get_array_size", (args, language) -> LLVMPolyglotGetArraySizeNodeGen.create(args.get(1))); - - add("polyglot_get_string_size", (args, language) -> LLVMPolyglotGetStringSizeNodeGen.create(args.get(1))); - add("polyglot_as_string", (args, language) -> LLVMPolyglotAsString.create(args.get(1), args.get(2), args.get(3), args.get(4))); - add("polyglot_from_string", (args, language) -> LLVMPolyglotFromString.create(args.get(1), args.get(2))); - add("polyglot_from_string_n", (args, language) -> LLVMPolyglotFromString.createN(args.get(1), args.get(2), args.get(3))); - - add("truffle_load_library", (args, language) -> LLVMLoadLibraryNodeGen.create(args.get(1))); - - add("__polyglot_as_typeid", (args, language) -> LLVMTypeIDNode.create(args.get(1))); - add("polyglot_as_typed", (args, language) -> LLVMPolyglotAsTyped.create(args.get(1), args.get(2))); - add("polyglot_from_typed", (args, language) -> LLVMPolyglotFromTyped.create(args.get(1), args.get(2))); - add("polyglot_array_typeid", (args, language) -> LLVMArrayTypeIDNode.create(args.get(1), args.get(2))); + add("truffle_decorate_function", (args, nodeFactory) -> LLVMTruffleDecorateFunctionNodeGen.create(args.get(1), args.get(2))); + add("polyglot_can_execute", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isExecutable, args.get(1))); + add("polyglot_can_instantiate", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isInstantiable, args.get(1))); + add("polyglot_is_null", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::isNull, args.get(1))); + add("polyglot_has_array_elements", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::hasArrayElements, args.get(1))); + add("polyglot_has_members", (args, nodeFactory) -> LLVMPolyglotBoxedPredicateNodeGen.create(InteropLibrary::hasMembers, args.get(1))); + add("polyglot_has_member", (args, nodeFactory) -> LLVMPolyglotHasMemberNodeGen.create(args.get(1), args.get(2))); + add("polyglot_get_array_size", (args, nodeFactory) -> LLVMPolyglotGetArraySizeNodeGen.create(args.get(1))); + + add("polyglot_get_string_size", (args, nodeFactory) -> LLVMPolyglotGetStringSizeNodeGen.create(args.get(1))); + add("polyglot_as_string", (args, nodeFactory) -> LLVMPolyglotAsString.create(args.get(1), args.get(2), args.get(3), args.get(4))); + add("polyglot_from_string", (args, nodeFactory) -> LLVMPolyglotFromString.create(args.get(1), args.get(2))); + add("polyglot_from_string_n", (args, nodeFactory) -> LLVMPolyglotFromString.createN(args.get(1), args.get(2), args.get(3))); + + add("truffle_load_library", (args, nodeFactory) -> LLVMLoadLibraryNodeGen.create(args.get(1))); + + add("__polyglot_as_typeid", (args, nodeFactory) -> LLVMTypeIDNode.create(args.get(1))); + add("polyglot_as_typed", (args, nodeFactory) -> LLVMPolyglotAsTyped.create(args.get(1), args.get(2))); + add("polyglot_from_typed", (args, nodeFactory) -> LLVMPolyglotFromTyped.create(args.get(1), args.get(2))); + add("polyglot_array_typeid", (args, nodeFactory) -> LLVMArrayTypeIDNode.create(args.get(1), args.get(2))); } private static void registerManagedAllocationIntrinsics() { - add("truffle_managed_malloc", (args, language) -> LLVMTruffleManagedMallocNodeGen.create(args.get(1))); - add("truffle_handle_for_managed", (args, language) -> LLVMTruffleManagedToHandleNodeGen.create(args.get(1))); - add("truffle_deref_handle_for_managed", (args, language) -> LLVMTruffleDerefHandleToManagedNodeGen.create(args.get(1))); - add("truffle_release_handle", (args, language) -> LLVMTruffleReleaseHandleNodeGen.create(args.get(1))); - add("truffle_managed_from_handle", (args, language) -> LLVMTruffleHandleToManagedNodeGen.create(args.get(1))); - add("truffle_is_handle_to_managed", (args, language) -> LLVMTruffleIsHandleToManagedNodeGen.create(args.get(1))); - add("truffle_cannot_be_handle", (args, language) -> LLVMTruffleCannotBeHandleNodeGen.create(args.get(1))); - add("truffle_assign_managed", (args, language) -> LLVMTruffleWriteManagedToGlobalNodeGen.create(args.get(1), args.get(2))); - add("truffle_virtual_malloc", (args, language) -> LLVMVirtualMallocNodeGen.create(args.get(1))); + add("truffle_managed_malloc", (args, nodeFactory) -> LLVMTruffleManagedMallocNodeGen.create(args.get(1))); + add("truffle_handle_for_managed", (args, nodeFactory) -> LLVMTruffleManagedToHandleNodeGen.create(args.get(1))); + add("truffle_deref_handle_for_managed", (args, nodeFactory) -> LLVMTruffleDerefHandleToManagedNodeGen.create(args.get(1))); + add("truffle_release_handle", (args, nodeFactory) -> LLVMTruffleReleaseHandleNodeGen.create(args.get(1))); + add("truffle_managed_from_handle", (args, nodeFactory) -> LLVMTruffleHandleToManagedNodeGen.create(args.get(1))); + add("truffle_is_handle_to_managed", (args, nodeFactory) -> LLVMTruffleIsHandleToManagedNodeGen.create(args.get(1))); + add("truffle_cannot_be_handle", (args, nodeFactory) -> LLVMTruffleCannotBeHandleNodeGen.create(args.get(1))); + add("truffle_assign_managed", (args, nodeFactory) -> LLVMTruffleWriteManagedToGlobalNodeGen.create(args.get(1), args.get(2))); + add("truffle_virtual_malloc", (args, nodeFactory) -> LLVMVirtualMallocNodeGen.create(args.get(1))); } private static void registerAbortIntrinsics() { - add("_gfortran_abort", (args, language) -> LLVMAbortNodeGen.create()); - add("signal", (args, language) -> LLVMSignalNodeGen.create(args.get(1), args.get(2))); - add("syscall", "__syscall", (args, language) -> LLVMSyscall.create(argumentsArray(args, 1, args.size() - 1))); + add("_gfortran_abort", (args, nodeFactory) -> LLVMAbortNodeGen.create()); + add("signal", (args, nodeFactory) -> LLVMSignalNodeGen.create(args.get(1), args.get(2))); + add("syscall", "__syscall", (args, nodeFactory) -> LLVMSyscall.create(argumentsArray(args, 1, args.size() - 1))); } private static void registerRustIntrinsics() { - add("std::rt::lang_start", (args, language) -> LLVMLangStartNodeGen.create(args.get(0), args.get(1), args.get(2), args.get(3))); - add("std::rt::lang_start_internal", (args, language) -> LLVMLangStartInternalNodeGen.create(args.get(0), args.get(1), args.get(2), args.get(3), args.get(4))); - add("std::process::exit", (args, language) -> LLVMExitNodeGen.create(args.get(1))); - add("core::panicking::panic", (args, language) -> LLVMPanicNodeGen.create(args.get(1))); + add("std::rt::lang_start", (args, nodeFactory) -> LLVMLangStartNodeGen.create(args.get(0), args.get(1), args.get(2), args.get(3))); + add("std::rt::lang_start_internal", (args, nodeFactory) -> LLVMLangStartInternalNodeGen.create(args.get(0), args.get(1), args.get(2), args.get(3), args.get(4))); + add("std::process::exit", (args, nodeFactory) -> LLVMExitNodeGen.create(args.get(1))); + add("core::panicking::panic", (args, nodeFactory) -> LLVMPanicNodeGen.create(args.get(1))); } private static void registerMathFunctionIntrinsics() { // TODO (chaeubl): There is no doubt that not all of these intrinsics are valid as they use // double arithmetics to simulate floating arithmetics, which can change the precision. // Furthermore, it is possible that there are mismatches between Java and C semantics. - addFloatingPointMathFunction("sqrt", (args, language) -> LLVMSqrtNodeGen.create(args.get(1))); - addFloatingPointMathFunction("log", (args, language) -> LLVMLogNodeGen.create(args.get(1))); - addFloatingPointMathFunction("log2", (args, language) -> LLVMLog2NodeGen.create(args.get(1))); - addFloatingPointMathFunction("log10", (args, language) -> LLVMLog10NodeGen.create(args.get(1))); - addFloatingPointMathFunction("log1p", (args, language) -> LLVMLog1pNodeGen.create(args.get(1))); - addFloatingPointMathFunction("rint", (args, language) -> LLVMRintNodeGen.create(args.get(1))); - addFloatingPointMathFunction("ceil", (args, language) -> LLVMCeilNodeGen.create(args.get(1))); - addFloatingPointMathFunction("floor", (args, language) -> LLVMFloorNodeGen.create(args.get(1))); - addFloatingPointMathFunction("fabs", (args, language) -> LLVMFAbsNodeGen.create(args.get(1))); - addFloatingPointMathFunction("minnum", (args, language) -> LLVMMinnumNodeGen.create(args.get(1), args.get(2))); - addFloatingPointMathFunction("maxnum", (args, language) -> LLVMMaxnumNodeGen.create(args.get(1), args.get(2))); - addFloatingPointMathFunction("pow", (args, language) -> LLVMPowNodeGen.create(args.get(1), args.get(2))); - addFloatingPointMathFunction("exp", (args, language) -> LLVMExpNodeGen.create(args.get(1))); - addFloatingPointMathFunction("exp2", (args, language) -> LLVMExp2NodeGen.create(args.get(1))); - addFloatingPointMathFunction("expm1", (args, language) -> LLVMExpm1NodeGen.create(args.get(1))); - addFloatingPointMathFunction("sin", (args, language) -> LLVMSinNodeGen.create(args.get(1))); - addFloatingPointMathFunction("cos", (args, language) -> LLVMCosNodeGen.create(args.get(1))); - addFloatingPointMathFunction("tan", (args, language) -> LLVMTanNodeGen.create(args.get(1))); - addFloatingPointMathFunction("atan2", (args, language) -> LLVMATan2NodeGen.create(args.get(1), args.get(2))); - addFloatingPointMathFunction("asin", (args, language) -> LLVMASinNodeGen.create(args.get(1))); - addFloatingPointMathFunction("acos", (args, language) -> LLVMACosNodeGen.create(args.get(1))); - addFloatingPointMathFunction("atan", (args, language) -> LLVMATanNodeGen.create(args.get(1))); - addFloatingPointMathFunction("sinh", (args, language) -> LLVMSinhNodeGen.create(args.get(1))); - addFloatingPointMathFunction("cosh", (args, language) -> LLVMCoshNodeGen.create(args.get(1))); - addFloatingPointMathFunction("tanh", (args, language) -> LLVMTanhNodeGen.create(args.get(1))); - addFloatingPointMathFunction("ldexp", (args, language) -> LLVMLdexpNodeGen.create(args.get(1), args.get(2))); - addFloatingPointMathFunction("modf", (args, language) -> LLVMModfNodeGen.create(args.get(1), args.get(2))); - addFloatingPointMathFunction("fmod", (args, language) -> LLVMFmodNodeGen.create(args.get(1), args.get(2))); - addFloatingPointMathFunction("copysign", (args, language) -> LLVMCMathsIntrinsicsFactory.LLVMCopySignNodeGen.create(args.get(1), args.get(2))); - - addIntegerMathFunction("abs", (args, language) -> LLVMAbsNodeGen.create(args.get(1))); + addFloatingPointMathFunction("sqrt", (args, nodeFactory) -> LLVMSqrtNodeGen.create(args.get(1))); + addFloatingPointMathFunction("log", (args, nodeFactory) -> LLVMLogNodeGen.create(args.get(1))); + addFloatingPointMathFunction("log2", (args, nodeFactory) -> LLVMLog2NodeGen.create(args.get(1))); + addFloatingPointMathFunction("log10", (args, nodeFactory) -> LLVMLog10NodeGen.create(args.get(1))); + addFloatingPointMathFunction("log1p", (args, nodeFactory) -> LLVMLog1pNodeGen.create(args.get(1))); + addFloatingPointMathFunction("rint", (args, nodeFactory) -> LLVMRintNodeGen.create(args.get(1))); + addFloatingPointMathFunction("ceil", (args, nodeFactory) -> LLVMCeilNodeGen.create(args.get(1))); + addFloatingPointMathFunction("floor", (args, nodeFactory) -> LLVMFloorNodeGen.create(args.get(1))); + addFloatingPointMathFunction("fabs", (args, nodeFactory) -> LLVMFAbsNodeGen.create(args.get(1))); + addFloatingPointMathFunction("minnum", (args, nodeFactory) -> LLVMMinnumNodeGen.create(args.get(1), args.get(2))); + addFloatingPointMathFunction("maxnum", (args, nodeFactory) -> LLVMMaxnumNodeGen.create(args.get(1), args.get(2))); + addFloatingPointMathFunction("pow", (args, nodeFactory) -> LLVMPowNodeGen.create(args.get(1), args.get(2))); + addFloatingPointMathFunction("exp", (args, nodeFactory) -> LLVMExpNodeGen.create(args.get(1))); + addFloatingPointMathFunction("exp2", (args, nodeFactory) -> LLVMExp2NodeGen.create(args.get(1))); + addFloatingPointMathFunction("expm1", (args, nodeFactory) -> LLVMExpm1NodeGen.create(args.get(1))); + addFloatingPointMathFunction("sin", (args, nodeFactory) -> LLVMSinNodeGen.create(args.get(1))); + addFloatingPointMathFunction("cos", (args, nodeFactory) -> LLVMCosNodeGen.create(args.get(1))); + addFloatingPointMathFunction("tan", (args, nodeFactory) -> LLVMTanNodeGen.create(args.get(1))); + addFloatingPointMathFunction("atan2", (args, nodeFactory) -> LLVMATan2NodeGen.create(args.get(1), args.get(2))); + addFloatingPointMathFunction("asin", (args, nodeFactory) -> LLVMASinNodeGen.create(args.get(1))); + addFloatingPointMathFunction("acos", (args, nodeFactory) -> LLVMACosNodeGen.create(args.get(1))); + addFloatingPointMathFunction("atan", (args, nodeFactory) -> LLVMATanNodeGen.create(args.get(1))); + addFloatingPointMathFunction("sinh", (args, nodeFactory) -> LLVMSinhNodeGen.create(args.get(1))); + addFloatingPointMathFunction("cosh", (args, nodeFactory) -> LLVMCoshNodeGen.create(args.get(1))); + addFloatingPointMathFunction("tanh", (args, nodeFactory) -> LLVMTanhNodeGen.create(args.get(1))); + addFloatingPointMathFunction("ldexp", (args, nodeFactory) -> LLVMLdexpNodeGen.create(args.get(1), args.get(2))); + addFloatingPointMathFunction("modf", (args, nodeFactory) -> LLVMModfNodeGen.create(args.get(1), args.get(2))); + addFloatingPointMathFunction("fmod", (args, nodeFactory) -> LLVMFmodNodeGen.create(args.get(1), args.get(2))); + addFloatingPointMathFunction("copysign", (args, nodeFactory) -> LLVMCMathsIntrinsicsFactory.LLVMCopySignNodeGen.create(args.get(1), args.get(2))); + + addIntegerMathFunction("abs", (args, nodeFactory) -> LLVMAbsNodeGen.create(args.get(1))); } private static void registerCTypeIntrinsics() { - add("isalpha", (args, language) -> LLVMIsalphaNodeGen.create(args.get(1))); - add("tolower", (args, language) -> LLVMTolowerNodeGen.create(args.get(1))); - add("toupper", (args, language) -> LLVMToUpperNodeGen.create(args.get(1))); - add("isspace", (args, language) -> LLVMIsspaceNodeGen.create(args.get(1))); - add("isupper", (args, language) -> LLVMIsupperNodeGen.create(args.get(1))); + add("isalpha", (args, nodeFactory) -> LLVMIsalphaNodeGen.create(args.get(1))); + add("tolower", (args, nodeFactory) -> LLVMTolowerNodeGen.create(args.get(1))); + add("toupper", (args, nodeFactory) -> LLVMToUpperNodeGen.create(args.get(1))); + add("isspace", (args, nodeFactory) -> LLVMIsspaceNodeGen.create(args.get(1))); + add("isupper", (args, nodeFactory) -> LLVMIsupperNodeGen.create(args.get(1))); } private static void registerMemoryFunctionIntrinsics() { - add("malloc", (args, language) -> LLVMMallocNodeGen.create(args.get(1))); - add("calloc", (args, language) -> LLVMCallocNodeGen.create(language.getNodeFactory().createMemSet(), args.get(1), args.get(2))); - add("realloc", (args, language) -> LLVMReallocNodeGen.create(args.get(1), args.get(2))); - add("free", (args, language) -> LLVMFreeNodeGen.create(args.get(1))); - add("memset", "__memset_chk", (args, language) -> LLVMLibcMemsetNodeGen.create(language.getNodeFactory().createMemSet(), args.get(1), args.get(2), args.get(3))); - add("memcpy", "__memcpy_chk", (args, language) -> LLVMLibcMemcpyNodeGen.create(language.getNodeFactory().createMemMove(), args.get(1), args.get(2), args.get(3))); + add("malloc", (args, nodeFactory) -> LLVMMallocNodeGen.create(args.get(1))); + add("calloc", (args, nodeFactory) -> LLVMCallocNodeGen.create(nodeFactory.createMemSet(), args.get(1), args.get(2))); + add("realloc", (args, nodeFactory) -> LLVMReallocNodeGen.create(args.get(1), args.get(2))); + add("free", (args, nodeFactory) -> LLVMFreeNodeGen.create(args.get(1))); + add("memset", "__memset_chk", (args, nodeFactory) -> LLVMLibcMemsetNodeGen.create(nodeFactory.createMemSet(), args.get(1), args.get(2), args.get(3))); + add("memcpy", "__memcpy_chk", (args, nodeFactory) -> LLVMLibcMemcpyNodeGen.create(nodeFactory.createMemMove(), args.get(1), args.get(2), args.get(3))); } private static void registerExceptionIntrinsics() { - add("_Unwind_RaiseException", (args, language) -> new LLVMRaiseExceptionNode(args.get(1))); - add("__cxa_call_unexpected", (args, language) -> LLVMAbortNodeGen.create()); + add("_Unwind_RaiseException", (args, nodeFactory) -> new LLVMRaiseExceptionNode(args.get(1))); + add("__cxa_call_unexpected", (args, nodeFactory) -> LLVMAbortNodeGen.create()); } private static void registerComplexNumberIntrinsics() { // float functions return a vector of <2x float> - add("__divsc3", (args, language) -> new LLVMComplexFloatDiv(args.get(1), args.get(2), args.get(3), args.get(4))); - add("__mulsc3", (args, language) -> new LLVMComplexFloatMul(args.get(1), args.get(2), args.get(3), args.get(4))); + add("__divsc3", (args, nodeFactory) -> new LLVMComplexFloatDiv(args.get(1), args.get(2), args.get(3), args.get(4))); + add("__mulsc3", (args, nodeFactory) -> new LLVMComplexFloatMul(args.get(1), args.get(2), args.get(3), args.get(4))); // double functions store their double results in the structure that is passed as arg1 - add("__divdc3", (args, language) -> new LLVMComplexDoubleDiv(args.get(1), args.get(2), args.get(3), args.get(4), args.get(5))); - add("__muldc3", (args, language) -> new LLVMComplexDoubleMul(args.get(1), args.get(2), args.get(3), args.get(4), args.get(5))); + add("__divdc3", (args, nodeFactory) -> new LLVMComplexDoubleDiv(args.get(1), args.get(2), args.get(3), args.get(4), args.get(5))); + add("__muldc3", (args, nodeFactory) -> new LLVMComplexDoubleMul(args.get(1), args.get(2), args.get(3), args.get(4), args.get(5))); // 80-bit FP functions store their results in the structure that is passed as arg1 - add("__divxc3", (args, language) -> LLVMComplex80BitFloatDivNodeGen.create(args.get(1), args.get(2), args.get(3), args.get(4), args.get(5))); - add("__mulxc3", (args, language) -> LLVMComplex80BitFloatMulNodeGen.create(args.get(1), args.get(2), args.get(3), args.get(4), args.get(5))); + add("__divxc3", (args, nodeFactory) -> LLVMComplex80BitFloatDivNodeGen.create(args.get(1), args.get(2), args.get(3), args.get(4), args.get(5))); + add("__mulxc3", (args, nodeFactory) -> LLVMComplex80BitFloatMulNodeGen.create(args.get(1), args.get(2), args.get(3), args.get(4), args.get(5))); } private static void add(String name, LLVMTypedIntrinsicFactory factory) { 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 2ad8527e4288..9d7ed45149dc 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 @@ -63,19 +63,6 @@ import com.oracle.truffle.llvm.runtime.except.LLVMParserException; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; -import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType.Value; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; -import com.oracle.truffle.llvm.runtime.interop.convert.ToAnyLLVMNodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToDoubleNodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToFloatNodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI16NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI1NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI32NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI64NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToI8NodeGen; -import com.oracle.truffle.llvm.runtime.interop.convert.ToPointer; -import com.oracle.truffle.llvm.runtime.interop.convert.ToVoidLLVMNodeGen; import com.oracle.truffle.llvm.runtime.memory.LLVMAllocateNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemSetNode; @@ -1675,7 +1662,7 @@ public LLVMExpressionNode createLLVMBuiltin(Symbol target, LLVMExpressionNode[] // Inline Sulong intrinsics directly at their call site, to avoid the overhead of a // call node and extra argument nodes. LLVMIntrinsicProvider intrinsicProvider = context.getLanguage().getCapability(LLVMIntrinsicProvider.class); - return intrinsicProvider.generateIntrinsicNode(name, args, argsTypes); + return intrinsicProvider.generateIntrinsicNode(name, args, argsTypes, this); } } return null; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMFunctionDescriptor.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMFunctionDescriptor.java index 72299056ac60..15a671407bb8 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMFunctionDescriptor.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMFunctionDescriptor.java @@ -108,11 +108,13 @@ public static final class Intrinsic { private final String intrinsicName; private final Map overloadingMap; private final LLVMIntrinsicProvider provider; + private final NodeFactory nodeFactory; - public Intrinsic(LLVMIntrinsicProvider provider, String name) { + public Intrinsic(LLVMIntrinsicProvider provider, String name, NodeFactory nodeFactory) { this.intrinsicName = name; this.overloadingMap = new HashMap<>(); this.provider = provider; + this.nodeFactory = nodeFactory; } public RootCallTarget cachedCallTarget(FunctionType type) { @@ -135,7 +137,7 @@ private RootCallTarget get(FunctionType type) { private RootCallTarget generateTarget(FunctionType type) { CompilerDirectives.transferToInterpreterAndInvalidate(); - RootCallTarget newTarget = provider.generateIntrinsicTarget(intrinsicName, type.getArgumentTypes()); + RootCallTarget newTarget = provider.generateIntrinsicTarget(intrinsicName, type.getArgumentTypes(), nodeFactory); assert newTarget != null; overloadingMap.put(type, newTarget); return newTarget; @@ -143,7 +145,7 @@ private RootCallTarget generateTarget(FunctionType type) { public LLVMExpressionNode generateNode(FunctionType type, LLVMExpressionNode[] arguments) { CompilerAsserts.neverPartOfCompilation(); - LLVMExpressionNode node = provider.generateIntrinsicNode(intrinsicName, arguments, type.getArgumentTypes()); + LLVMExpressionNode node = provider.generateIntrinsicNode(intrinsicName, arguments, type.getArgumentTypes(), nodeFactory); assert node != null; return node; } @@ -332,9 +334,9 @@ public boolean isDefined() { return !(getFunction() instanceof UnresolvedFunction); } - public void define(LLVMIntrinsicProvider intrinsicProvider) { + public void define(LLVMIntrinsicProvider intrinsicProvider, NodeFactory nodeFactory) { assert intrinsicProvider.isIntrinsified(name); - Intrinsic intrinsification = new Intrinsic(intrinsicProvider, name); + Intrinsic intrinsification = new Intrinsic(intrinsicProvider, name, nodeFactory); define(intrinsicProvider.getLibrary(), new LLVMFunctionDescriptor.IntrinsicFunction(intrinsification), true); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMIntrinsicProvider.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMIntrinsicProvider.java index 0f7d37a0f19c..1d5219d81085 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMIntrinsicProvider.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMIntrinsicProvider.java @@ -39,9 +39,9 @@ public interface LLVMIntrinsicProvider extends LLVMCapability { boolean isIntrinsified(String name); - RootCallTarget generateIntrinsicTarget(String name, Type[] argTypes); + RootCallTarget generateIntrinsicTarget(String name, Type[] argTypes, NodeFactory nodeFactory); - LLVMExpressionNode generateIntrinsicNode(String name, LLVMExpressionNode[] arguments, Type[] argTypes); + LLVMExpressionNode generateIntrinsicNode(String name, LLVMExpressionNode[] arguments, Type[] argTypes, NodeFactory nodeFactory); ExternalLibrary getLibrary(); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index 0331539063d1..e5206b98d6b2 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -37,9 +37,6 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.llvm.runtime.LLVMContext.ExternalLibrary; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; -import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; -import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM.ForeignToLLVMType; import com.oracle.truffle.llvm.runtime.interop.export.InteropNodeFactory; import com.oracle.truffle.llvm.runtime.memory.LLVMAllocateNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java index 40a4145a649a..e3a255789c29 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMForeignCallNode.java @@ -45,7 +45,6 @@ import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMGetStackNode; import com.oracle.truffle.llvm.runtime.LLVMLanguage; -import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.interop.LLVMForeignCallNodeFactory.PackForeignArgumentsNodeGen; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.interop.convert.ForeignToLLVM; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java index d17d1fad5925..499955d70615 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMNode.java @@ -39,7 +39,6 @@ import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMLanguage; -import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.memory.LLVMMemory; import com.oracle.truffle.llvm.runtime.memory.UnsafeArrayAccess; diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index f105685e3af1..731aedb47112 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -439,7 +439,7 @@ private void bindUnresolvedSymbols(LLVMContext ctx) { bindGlobal(ctx, global, nfiContextExtension); } else if (symbol instanceof LLVMFunctionDescriptor) { LLVMFunctionDescriptor function = (LLVMFunctionDescriptor) symbol; - bindUnresolvedFunction(ctx, function, nfiContextExtension, intrinsicProvider); + bindUnresolvedFunction(ctx, function, nfiContextExtension, intrinsicProvider, nodeFactory); } else if (symbol instanceof LLVMAlias) { // nothing to do } else { @@ -756,11 +756,12 @@ private static void bindGlobal(LLVMContext ctx, LLVMGlobal global, NFIContextExt } } - private static void bindUnresolvedFunction(LLVMContext ctx, LLVMFunctionDescriptor function, NFIContextExtension nfiContextExtension, LLVMIntrinsicProvider intrinsicProvider) { + private static void bindUnresolvedFunction(LLVMContext ctx, LLVMFunctionDescriptor function, NFIContextExtension nfiContextExtension, LLVMIntrinsicProvider intrinsicProvider, + NodeFactory nodeFactory) { if (function.getName().startsWith("llvm.")) { // llvm intrinsic } else if (intrinsicProvider.isIntrinsified(function.getName())) { - function.define(intrinsicProvider); + function.define(intrinsicProvider, nodeFactory); } else if (nfiContextExtension != null) { NativeLookupResult nativeFunction = nfiContextExtension.getNativeFunctionOrNull(ctx, function.getName()); if (nativeFunction != null) { @@ -1089,7 +1090,7 @@ private void overrideSulongLibraryFunctionsWithIntrinsics(List throw new UnsupportedOperationException("Replacing an alias with an intrinsic is not supported at the moment"); } else if (symbol instanceof LLVMFunctionDescriptor) { LLVMFunctionDescriptor function = (LLVMFunctionDescriptor) symbol; - function.define(intrinsicProvider); + function.define(intrinsicProvider, parserResult.getRuntime().getNodeFactory()); } else { throw new IllegalStateException("Unknown symbol: " + symbol.getClass()); } From d67b33d614ec28834ff4f383eb3869769f8c8d8c Mon Sep 17 00:00:00 2001 From: Paley Li Date: Fri, 4 Oct 2019 14:28:39 +0200 Subject: [PATCH 112/140] Copyright and format --- .../llvm/runtime/CommonNodeFactory.java | 29 +++++++++++++++++++ .../interop/export/InteropNodeFactory.java | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java index ec40106092a4..60e8fd61164f 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/CommonNodeFactory.java @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2019, 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.runtime; import com.oracle.truffle.api.frame.FrameSlot; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java index a2b403b46922..980c6354b634 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. * * All rights reserved. * From d9c0b40ced6d9aa57165bfb9bdcdfc0245b6ebec Mon Sep 17 00:00:00 2001 From: Paley Li Date: Fri, 4 Oct 2019 15:37:16 +0200 Subject: [PATCH 113/140] Create how the InlineAssemblyParser is generated as the ASMFactory now requires a nodeFacotry --- .../src/com/oracle/truffle/llvm/asm/amd64/InlineAssembly.g4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/InlineAssembly.g4 b/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/InlineAssembly.g4 index 627e7b189a48..cef8272a598c 100644 --- a/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/InlineAssembly.g4 +++ b/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/InlineAssembly.g4 @@ -39,6 +39,7 @@ grammar InlineAssembly; // DO NOT MODIFY - generated from InlineAssembly.g4 using "mx create-asm-parser" import com.oracle.truffle.llvm.runtime.LLVMLanguage; +import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.nodes.func.LLVMInlineAssemblyRootNode; import com.oracle.truffle.llvm.runtime.types.Type; } @@ -66,7 +67,7 @@ private static final class BailoutErrorListener extends BaseErrorListener { } } -public static LLVMInlineAssemblyRootNode parseInlineAssembly(LLVMLanguage language, String asmSnippet, String asmFlags, Type[] argTypes, Type retType, Type[] retTypes, int[] retOffsets) { +public static LLVMInlineAssemblyRootNode parseInlineAssembly(LLVMLanguage language, String asmSnippet, String asmFlags, Type[] argTypes, Type retType, Type[] retTypes, int[] retOffsets, NodeFactory nodeFactory) { InlineAssemblyLexer lexer = new InlineAssemblyLexer(CharStreams.fromString(asmSnippet)); InlineAssemblyParser parser = new InlineAssemblyParser(new CommonTokenStream(lexer)); lexer.removeErrorListeners(); @@ -75,7 +76,7 @@ public static LLVMInlineAssemblyRootNode parseInlineAssembly(LLVMLanguage langua lexer.addErrorListener(listener); parser.addErrorListener(listener); parser.snippet = asmSnippet; - parser.factory = new AsmFactory(language, argTypes, asmFlags, retType, retTypes, retOffsets); + parser.factory = new AsmFactory(language, argTypes, asmFlags, retType, retTypes, retOffsets, nodeFactory); parser.inline_assembly(); if (parser.root == null) { throw new IllegalStateException("no roots produced by inline assembly snippet"); From 259118481412ea8f46521145953348b3fb56c2f9 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Mon, 7 Oct 2019 11:37:24 +0200 Subject: [PATCH 114/140] Take the nodeFactory out of LLVMLanguage. --- .../com/oracle/truffle/llvm/runtime/LLVMLanguage.java | 9 --------- .../src/com/oracle/truffle/llvm/Runner.java | 1 - 2 files changed, 10 deletions(-) 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 fd66b4073708..279f5080d240 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 @@ -87,7 +87,6 @@ public class LLVMLanguage extends TruffleLanguage { public static final String ID = "llvm"; static final String NAME = "LLVM"; - private NodeFactory nodeFactory; @CompilationFinal private List contextExtensions; public abstract static class Loader implements LLVMCapability { @@ -172,14 +171,6 @@ protected LLVMContext createContext(Env env) { return context; } - public NodeFactory getNodeFactory() { - return nodeFactory; - } - - public void setNodeFactory(NodeFactory nodeFactory) { - this.nodeFactory = nodeFactory; - } - @Override protected void initializeContext(LLVMContext context) { context.initialize(); diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index 731aedb47112..29304d777434 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -687,7 +687,6 @@ private LLVMParserResult parse(List parserResults, ArrayDeque< DataLayout targetDataLayout = new DataLayout(layout.getDataLayout()); NodeFactory nodeFactory = context.getLanguage().getActiveConfiguration().createNodeFactory(context, targetDataLayout); // This needs to be removed once the nodefactory is taken out of the language. - context.getLanguage().setNodeFactory(nodeFactory); LLVMScope fileScope = new LLVMScope(); LLVMParserRuntime runtime = new LLVMParserRuntime(context, library, fileScope, nodeFactory); LLVMParser parser = new LLVMParser(source, runtime); From ed6404e35b0c1594406322fbcc23143127e568cd Mon Sep 17 00:00:00 2001 From: Paley Li Date: Tue, 8 Oct 2019 09:29:51 +0200 Subject: [PATCH 115/140] Remove InteropNodeFactory. --- .../truffle/llvm/runtime/NodeFactory.java | 3 +- .../interop/export/InteropNodeFactory.java | 37 ------------------- 2 files changed, 1 insertion(+), 39 deletions(-) delete mode 100644 sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java index e5206b98d6b2..fb687efad05b 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/NodeFactory.java @@ -37,7 +37,6 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.llvm.runtime.LLVMContext.ExternalLibrary; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; -import com.oracle.truffle.llvm.runtime.interop.export.InteropNodeFactory; import com.oracle.truffle.llvm.runtime.memory.LLVMAllocateNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemSetNode; @@ -62,7 +61,7 @@ * {@link LLVMExpressionNode} and {@link LLVMExpressionNode} visible. The parser should not directly * instantiate a node, but instead use the factory facade. */ -public interface NodeFactory extends InteropNodeFactory { +public interface NodeFactory { LLVMExpressionNode createInsertElement(Type resultType, LLVMExpressionNode vector, LLVMExpressionNode element, LLVMExpressionNode index); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java deleted file mode 100644 index 980c6354b634..000000000000 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/export/InteropNodeFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2018, 2019, 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.runtime.interop.export; - -public interface InteropNodeFactory { - - // LLVMLoadNode createLoadNode(LLVMInteropType.ValueKind kind); - - // LLVMStoreNode createStoreNode(LLVMInteropType.ValueKind kind); -} From b76e266f4d58ed870a771cd613f2ce2ce64e10e8 Mon Sep 17 00:00:00 2001 From: Paley Li Date: Tue, 8 Oct 2019 09:31:57 +0200 Subject: [PATCH 116/140] Remove the nodeFactory field -- single use. --- .../truffle/llvm/parser/LazyToTruffleConverterImpl.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 9d3da7c59028..e556d3d63f35 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 @@ -59,7 +59,6 @@ import com.oracle.truffle.llvm.parser.nodes.LLVMSymbolReadResolver; import com.oracle.truffle.llvm.runtime.GetStackSpaceFactory; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor.LazyToTruffleConverter; -import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceFunctionType; @@ -81,7 +80,6 @@ public class LazyToTruffleConverterImpl implements LazyToTruffleConverter { private final LazyFunctionParser parser; private final DebugInfoFunctionProcessor diProcessor; private final DataLayout dataLayout; - private final NodeFactory nodeFactory; private RootCallTarget resolved; @@ -94,7 +92,6 @@ public class LazyToTruffleConverterImpl implements LazyToTruffleConverter { this.diProcessor = diProcessor; this.resolved = null; this.dataLayout = dataLayout; - this.nodeFactory = runtime.getNodeFactory(); } @Override @@ -135,7 +132,7 @@ private RootCallTarget generateCallTarget() { dbgInfoHandler.registerStaticDebugSymbols(method); LLVMBitcodeFunctionVisitor visitor = new LLVMBitcodeFunctionVisitor(runtime.getContext(), runtime.getLibrary(), frame, uniquesRegion, phis, method.getParameters().size(), symbols, method, - liveness, notNullable, dbgInfoHandler, dataLayout, nodeFactory); + liveness, notNullable, dbgInfoHandler, dataLayout, runtime.getNodeFactory()); method.accept(visitor); FrameSlot[][] nullableBeforeBlock = getNullableFrameSlots(liveness.getFrameSlots(), liveness.getNullableBeforeBlock(), notNullable); FrameSlot[][] nullableAfterBlock = getNullableFrameSlots(liveness.getFrameSlots(), liveness.getNullableAfterBlock(), notNullable); From 2e95e96c214b0017e68f84dcd4f6b6f82770af88 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Tue, 8 Oct 2019 11:46:33 +0200 Subject: [PATCH 117/140] [GR-15292] Fixed CHANGELOG.md, added more tests. --- truffle/CHANGELOG.md | 3 +- .../processor/InstrumentRegistrationTest.java | 94 +++++++++++++++++++ 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/InstrumentRegistrationTest.java diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 0175aa0d5927..36d80d72095a 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -16,8 +16,7 @@ This changelog summarizes major changes between Truffle versions relevant to lan * Deprecated `Shape#getPropertyList(Pred)`, `Shape#getKeyList(Pred)`, `Shape#hasTransitionWithKey(Object)`, `Shape.Allocator#locationForValue(Object, EnumSet)` without replacement. * Added [Scope.Builder#rootInstance(Object)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.Builder.html#rootInstance-java.lang.Object-), [Scope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/Scope.html#getRootInstance--) and [DebugScope#getRootInstance()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugScope.html#getRootInstance--) to provide an instance of guest language representation of the root node (e.g. a guest language function). * Debugger breakpoints can be restricted to a particular root instance via [Breakpoint.Builder#rootInstance(DebugValue)](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/Breakpoint.Builder.html#rootInstance-com.oracle.truffle.api.debug.DebugValue-) and found later on via [DebugValue#getRootInstanceBreakpoints()](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/debug/DebugValue.html#getRootInstanceBreakpoints--). -* `TruffleLanguage`s are registered in a `ServiceLoader` using the [TruffleLanguage.Provider](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.Provider.html) as a service interface. -* `TruffleInstrument`s are registered in a `ServiceLoader` using the [TruffleInstrument.Provider](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/TruffleInstrument.Provider.html) as a service interface. +* Truffle languages and instruments no longer create `META-INF/truffle` files, but generate service implementations for [TruffleLanguage.Provider](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/TruffleLanguage.Provider.html) and [TruffleInstrument.Provider](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/instrumentation/TruffleInstrument.Provider.html) automatically. Recompiling the TruffleLanguage using the Truffle annotation processor automatically migrates the language. ## Version 19.2.0 * Added sub-process output (error output) [redirection into OutputStream](https://www.graalvm.org/truffle/javadoc/org/graalvm/polyglot/io/ProcessHandler.Redirect.html#stream-java.io.OutputStream-). diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/InstrumentRegistrationTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/InstrumentRegistrationTest.java new file mode 100644 index 000000000000..7f2901fac250 --- /dev/null +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/InstrumentRegistrationTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2019, 2019, 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.processor; + +import com.oracle.truffle.api.dsl.test.ExpectError; +import com.oracle.truffle.api.dsl.test.processor.LanguageRegistrationTest.GenerateLegacyRegistration; +import com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration; +import com.oracle.truffle.api.test.polyglot.ProxyInstrument; +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.Instrument; +import org.junit.Assert; +import org.junit.Test; + +public class InstrumentRegistrationTest { + + @ExpectError("Registered instrument class must be public") + @Registration(id = "NonPublicInstrument") + static final class NonPublicInstrument extends ProxyInstrument { + } + + @ExpectError("Registered instrument class must subclass TruffleInstrument") + @Registration(id = "WrongSuperClassInstrument") + public static final class WrongSuperClassInstrument { + } + + @Registration(id = "MyInstrumentGood", name = "MyInstrumentGood") + public static final class MyInstrumentGood extends ProxyInstrument { + } + + @Registration(id = "MyInstrumentGoodWithServices", name = "MyInstrumentGoodWithServices", services = Service1.class) + public static final class MyInstrumentGoodWithServices extends ProxyInstrument { + + } + + @GenerateLegacyRegistration + @Registration(id = "legacyregistration", name = "LegacyRegistration", version = "1.0.0", services = {Service1.class, Service2.class}) + public static final class LegacyRegistration extends ProxyInstrument { + + } + + interface Service1 { + } + + interface Service2 { + } + + @Test + public void testLoadLegacyRegistrations() { + try (Engine eng = Engine.create()) { + Instrument instrument = eng.getInstruments().get("legacyregistration"); + Assert.assertNotNull(instrument); + Assert.assertEquals("LegacyRegistration", instrument.getName()); + Assert.assertEquals("1.0.0", instrument.getVersion()); + } + } +} From 5c260a08be25465eb0b1bf39d5492e255cc9dc77 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Tue, 8 Oct 2019 14:23:39 +0200 Subject: [PATCH 118/140] Copy static libs in jlink_new_jdk --- sdk/mx.sdk/mx_sdk.py | 11 ++++++ .../oracle/svm/hosted/c/NativeLibraries.java | 35 +++++++++---------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/sdk/mx.sdk/mx_sdk.py b/sdk/mx.sdk/mx_sdk.py index 8c228f9538ed..53b50f70203b 100644 --- a/sdk/mx.sdk/mx_sdk.py +++ b/sdk/mx.sdk/mx_sdk.py @@ -583,6 +583,17 @@ def jlink_new_jdk(jdk, dst_jdk_dir, module_dists, root_module_names=None, missin for name, contents in sorted(dst_src_zip_contents.items()): zf.writestr(name, contents) + mx.logv('[Copying static libraries]') + lib_prefix = mx.add_lib_prefix('') + lib_suffix = '.lib' if mx.is_windows() else '.a' + lib_directory = join(jdk.home, 'lib') + dst_lib_directory = join(dst_jdk_dir, 'lib') + for f in os.listdir(lib_directory): + if f.startswith(lib_prefix) and f.endswith(lib_suffix): + lib_path = join(lib_directory, f) + if isfile(lib_path): + shutil.copy2(lib_path, dst_lib_directory) + # Build the list of modules whose classes might have annotations # to be processed by native-image (GR-15192). with open(join(dst_jdk_dir, 'lib', 'native-image-modules.list'), 'w') as fp: diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java index 847b9fc5c618..9f0d6e87a5c4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java @@ -38,6 +38,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.function.Predicate; import java.util.stream.Collectors; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; @@ -162,28 +163,21 @@ private static LinkedHashSet initCLibraryPath() { LinkedHashSet libraryPaths = new LinkedHashSet<>(); Path staticLibsDir = null; + String hint = null; /* Probe for static JDK libraries in JDK lib directory */ try { Path jdkLibDir = Paths.get(System.getProperty("java.home")).resolve("lib").toRealPath(); - if (Files.isDirectory(jdkLibDir)) { - List defaultBuiltInLibraries = Arrays.asList(PlatformNativeLibrarySupport.defaultBuiltInLibraries); - if (Files.list(jdkLibDir).filter(path -> { - if (Files.isDirectory(path)) { - return false; - } - String libName = path.getFileName().toString(); - if (!(libName.startsWith(libPrefix) && libName.endsWith(libSuffix))) { - return false; - } - String lib = libName.substring(libPrefix.length(), libName.length() - libSuffix.length()); - return defaultBuiltInLibraries.contains(lib); - }).count() == defaultBuiltInLibraries.size()) { - staticLibsDir = jdkLibDir; - } + List defaultBuiltInLibraries = Arrays.asList(PlatformNativeLibrarySupport.defaultBuiltInLibraries); + Predicate hasStaticLibrary = s -> Files.isRegularFile(jdkLibDir.resolve(libPrefix + s + libSuffix)); + if (defaultBuiltInLibraries.stream().allMatch(hasStaticLibrary)) { + staticLibsDir = jdkLibDir; + } else { + hint = defaultBuiltInLibraries.stream().filter(hasStaticLibrary.negate()).collect(Collectors.joining(", ", "Missing libraries:", "")); } - } catch (Exception e) { + } catch (IOException e) { /* Fallthrough to next strategy */ + hint = e.getMessage(); } if (staticLibsDir == null) { @@ -193,9 +187,12 @@ private static LinkedHashSet initCLibraryPath() { if (staticLibsDir != null) { libraryPaths.add(staticLibsDir.toString()); } else { - UserError.guarantee(!Platform.includedIn(InternalPlatform.PLATFORM_JNI.class), - "Building images for " + ImageSingletons.lookup(Platform.class).getClass().getName() + " requires static JDK libraries." + - "\nUse JDK from https://github.com/graalvm/openjdk8-jvmci-builder/releases"); + String message = "Building images for " + ImageSingletons.lookup(Platform.class).getClass().getName() + " requires static JDK libraries." + + "\nUse JDK from https://github.com/graalvm/openjdk8-jvmci-builder/releases"; + if (hint != null) { + message += "\n" + hint; + } + UserError.guarantee(!Platform.includedIn(InternalPlatform.PLATFORM_JNI.class), message); } return libraryPaths; } From 13863cdb18ddbdc318f9416ef547c851ef27d6eb Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Tue, 8 Oct 2019 15:01:20 +0200 Subject: [PATCH 119/140] Add URL for JDK11 builds --- .../src/com/oracle/svm/hosted/c/NativeLibraries.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java index 9f0d6e87a5c4..90dca5e3ee7d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/NativeLibraries.java @@ -188,7 +188,7 @@ private static LinkedHashSet initCLibraryPath() { libraryPaths.add(staticLibsDir.toString()); } else { String message = "Building images for " + ImageSingletons.lookup(Platform.class).getClass().getName() + " requires static JDK libraries." + - "\nUse JDK from https://github.com/graalvm/openjdk8-jvmci-builder/releases"; + "\nUse JDK from https://github.com/graalvm/openjdk8-jvmci-builder/releases or https://github.com/graalvm/labs-openjdk-11/releases"; if (hint != null) { message += "\n" + hint; } From b92ff3eed8dbc26bd862f0e43821e7c6a98870f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Tue, 1 Oct 2019 17:55:00 +0200 Subject: [PATCH 120/140] Switch to PLATFORM_JNI for Java 8 native-image generation --- .../src/com/oracle/svm/hosted/NativeImageGenerator.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index d5a4b145c5e3..4bfda8d92cce 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 @@ -126,6 +126,7 @@ import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.Feature.OnAnalysisExitAccess; import org.graalvm.nativeimage.impl.CConstantValueSupport; +import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import org.graalvm.nativeimage.impl.SizeOfSupport; import org.graalvm.word.PointerBase; @@ -338,11 +339,12 @@ public static Platform defaultPlatform(ClassLoader classLoader) { final Architecture hostedArchitecture = GraalAccess.getOriginalTarget().arch; final OS currentOs = OS.getCurrent(); + boolean isJava8 = JavaVersionUtil.JAVA_SPEC == 8; if (hostedArchitecture instanceof AMD64) { if (currentOs == OS.LINUX) { - return new Platform.LINUX_AMD64(); + return isJava8 ? new InternalPlatform.LINUX_JNI_AMD64() : new Platform.LINUX_AMD64(); } else if (currentOs == OS.DARWIN) { - return new Platform.DARWIN_AMD64(); + return isJava8 ? new InternalPlatform.DARWIN_JNI_AMD64() : new Platform.DARWIN_AMD64(); } else if (currentOs == OS.WINDOWS) { return new Platform.WINDOWS_AMD64(); } else { From a0f2fb8f0065226d823bbf0c3c9e9f700f52d497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Mon, 7 Oct 2019 12:48:11 +0200 Subject: [PATCH 121/140] [GR-18686] Make SegfaultHandlerFeature usable in Posix JNI_PLATFORMS. --- .../core/posix/SegfaultHandlerFeature.java | 3 ++- .../amd64/AMD64UContextRegisterDumper.java | 5 +++-- .../darwin/DarwinUContextRegisterDumper.java | 7 ++++--- .../oracle/svm/core/posix/headers/Signal.java | 20 +++++++++---------- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java index 1ed7dce45ed4..1afb646afae9 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java @@ -35,6 +35,7 @@ import org.graalvm.nativeimage.c.function.CEntryPointLiteral; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.annotate.AutomaticFeature; @@ -55,7 +56,7 @@ import com.oracle.svm.core.posix.headers.Signal.ucontext_t; import com.oracle.svm.core.thread.VMThreads; -@Platforms({Platform.LINUX_AMD64.class, Platform.DARWIN_AMD64.class}) +@Platforms({Platform.LINUX_AMD64.class, Platform.DARWIN_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) @AutomaticFeature public class SegfaultHandlerFeature implements Feature { 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 index 7eac9df8b5ba..669223d1eae0 100644 --- 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 @@ -24,10 +24,11 @@ */ package com.oracle.svm.core.posix.amd64; -import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.SubstrateUtil; @@ -38,7 +39,7 @@ import com.oracle.svm.core.posix.headers.Signal.GregsPointer; import com.oracle.svm.core.posix.headers.Signal.ucontext_t; -@Platforms(Platform.LINUX_AMD64.class) +@Platforms({Platform.LINUX_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) @AutomaticFeature class AMD64UContextRegisterDumperFeature implements Feature { @Override 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/darwin/DarwinUContextRegisterDumper.java index 79ef34fcd37e..041e26fee646 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/darwin/DarwinUContextRegisterDumper.java @@ -24,22 +24,23 @@ */ package com.oracle.svm.core.posix.darwin; -import com.oracle.svm.core.posix.headers.Signal; -import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CLongPointer; +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.annotate.AutomaticFeature; 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.posix.headers.Signal.ucontext_t; -@Platforms(Platform.DARWIN_AMD64.class) +@Platforms({Platform.DARWIN_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) @AutomaticFeature class DarwinUContextRegisterDumperFeature implements Feature { @Override 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 044d508f0c64..40ad84e0b0e1 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 @@ -87,13 +87,13 @@ public interface siginfo_t extends PointerBase { /* Fields unused */ } - @Platforms(Platform.LINUX.class) + @Platforms(InternalPlatform.LINUX_AND_JNI.class) @CPointerTo(nameOfCType = "long long int") public interface GregsPointer extends PointerBase { long read(int index); } - @Platforms(Platform.LINUX_AMD64.class) + @Platforms({Platform.LINUX_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) @CEnum @CContext(PosixDirectives.class) public enum GregEnum { @@ -125,7 +125,7 @@ public enum GregEnum { public native int getCValue(); } - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) @CStruct public interface ucontext_t extends PointerBase { /*- @@ -139,7 +139,7 @@ public interface ucontext_t extends PointerBase { __sigset_t uc_sigmask; struct _libc_fpstate __fpregs_mem; } ucontext_t; - + // Context to describe whole processor state. typedef struct { @@ -150,7 +150,7 @@ public interface ucontext_t extends PointerBase { } mcontext_t; */ @CFieldAddress("uc_mcontext.gregs") - @Platforms(Platform.LINUX_AMD64.class) + @Platforms({Platform.LINUX_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) GregsPointer uc_mcontext_gregs(); /*- @@ -176,16 +176,16 @@ public interface ucontext_t extends PointerBase { }; */ @CFieldAddress("uc_mcontext") - @Platforms(Platform.LINUX_AArch64.class) + @Platforms({Platform.LINUX_AArch64.class, InternalPlatform.LINUX_JNI_AArch64.class}) mcontext_t uc_mcontext(); @CField("uc_mcontext") - @Platforms(Platform.DARWIN_AMD64.class) + @Platforms({Platform.DARWIN_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) MContext64 uc_mcontext64(); } - @Platforms({Platform.DARWIN_AMD64.class}) + @Platforms({Platform.DARWIN_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) @CStruct(value = "__darwin_mcontext64", addStructKeyword = true) public interface MContext64 extends PointerBase { @@ -245,7 +245,7 @@ public interface MContext64 extends PointerBase { } @CStruct - @Platforms(Platform.LINUX_AArch64.class) + @Platforms({Platform.LINUX_AArch64.class, InternalPlatform.LINUX_JNI_AArch64.class}) public interface mcontext_t extends PointerBase { @CField long fault_address(); @@ -270,7 +270,7 @@ public interface AdvancedSignalDispatcher extends CFunctionPointer { void dispatch(int signum, siginfo_t siginfo, WordPointer opaque); } - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) @CConstant public static native int SA_SIGINFO(); From 9500bf01d3bdc4b34dbe7170448faa7f23e0f96f Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Tue, 16 Jul 2019 16:30:31 +0200 Subject: [PATCH 122/140] Turn InstalledCodeObserverHandle into a @RawStructure. --- .../core/graal/meta/InstalledCodeBuilder.java | 4 +- .../com/oracle/svm/core/code/CodeInfo.java | 14 ++-- .../oracle/svm/core/code/ImageCodeInfo.java | 10 +++ .../svm/core/code/InstalledCodeObserver.java | 47 +++++++++++--- .../code/InstalledCodeObserverSupport.java | 65 +++++++++++++------ .../oracle/svm/core/code/RuntimeCodeInfo.java | 2 - .../core/code/RuntimeMethodInfoAccess.java | 19 +++--- 7 files changed, 111 insertions(+), 50 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/InstalledCodeBuilder.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/InstalledCodeBuilder.java index 417514ab1fa9..6086d42c565d 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/InstalledCodeBuilder.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/InstalledCodeBuilder.java @@ -49,6 +49,7 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.c.NonmovableArray; import com.oracle.svm.core.code.CodeInfo; import com.oracle.svm.core.code.CodeInfoAccess; import com.oracle.svm.core.code.CodeInfoEncoder; @@ -56,6 +57,7 @@ import com.oracle.svm.core.code.DeoptimizationSourcePositionEncoder; import com.oracle.svm.core.code.FrameInfoEncoder; import com.oracle.svm.core.code.InstalledCodeObserver; +import com.oracle.svm.core.code.InstalledCodeObserver.InstalledCodeObserverHandle; import com.oracle.svm.core.code.InstalledCodeObserverSupport; import com.oracle.svm.core.code.RuntimeMethodInfoAccess; import com.oracle.svm.core.config.ConfigurationValues; @@ -304,7 +306,7 @@ private void installOperation() { createCodeChunkInfos(); - InstalledCodeObserver.InstalledCodeObserverHandle[] observerHandles = InstalledCodeObserverSupport.installObservers(codeObservers); + NonmovableArray observerHandles = InstalledCodeObserverSupport.installObservers(codeObservers); RuntimeMethodInfoAccess.setData(runtimeMethodInfo, installedCode, tier, observerHandles); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfo.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfo.java index c2cffd3d882d..d25da27f665f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfo.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfo.java @@ -69,14 +69,8 @@ public interface CodeInfo extends PointerBase { */ int INSTALLEDCODE_OBJFIELD = NAME_OBJFIELD + 1; - /** - * Index of element of type {@link InstalledCodeObserverHandle}[] in {@link #getObjectFields}: - * observers for installation and removal of this code. - */ - int OBSERVERS_OBJFIELD = INSTALLEDCODE_OBJFIELD + 1; - /** The size of the array in {@link #getObjectFields}. */ - int OBJFIELDS_COUNT = OBSERVERS_OBJFIELD + 1; + int OBJFIELDS_COUNT = INSTALLEDCODE_OBJFIELD + 1; /** * The object "fields" of this structure, managed as an array for simplicity. @@ -192,4 +186,10 @@ public interface CodeInfo extends PointerBase { @RawField void setDeoptimizationObjectConstants(NonmovableObjectArray deoptimizationObjectConstants); + + @RawField + NonmovableArray getCodeObserverHandles(); + + @RawField + void setCodeObserverHandles(NonmovableArray handles); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ImageCodeInfo.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ImageCodeInfo.java index 099043c5f471..3337bbef1842 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ImageCodeInfo.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ImageCodeInfo.java @@ -293,6 +293,16 @@ public void setDeoptimizationObjectConstants(NonmovableObjectArray deopt throw VMError.shouldNotReachHere("not supported for image code"); } + @Override + public NonmovableArray getCodeObserverHandles() { + throw VMError.shouldNotReachHere("not supported for image code"); + } + + @Override + public void setCodeObserverHandles(NonmovableArray handles) { + throw VMError.shouldNotReachHere("not supported for image code"); + } + @Override public boolean isNull() { return false; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserver.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserver.java index e8392aa34879..8e86dd9310b7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserver.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserver.java @@ -26,27 +26,54 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.nativeimage.c.struct.RawField; +import org.graalvm.nativeimage.c.struct.RawStructure; import org.graalvm.word.Pointer; +import org.graalvm.word.PointerBase; import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.c.struct.PinnedObjectField; import com.oracle.svm.core.meta.SharedMethod; +/** Observes the life of one piece of runtime-compiled code. */ public interface InstalledCodeObserver { - public interface InstalledCodeObserverHandle { - default void activate() { + + interface Factory { + /** Creates an observer for the specified code. */ + InstalledCodeObserver create(DebugContext debug, SharedMethod method, CompilationResult compilation, Pointer code); + } + + /** + * Installs the observer and returns a handle to its state in unmanaged memory. Use the + * {@linkplain InstalledCodeObserverHandle#getAccessor() accessor} to activate the observer and + * for further actions. + */ + InstalledCodeObserverHandle install(); + + @RawStructure + interface InstalledCodeObserverHandle extends PointerBase { + /** + * Provides an accessor object to perform actions with this handle. This object lives in the + * image heap so it is safe to access even across different isolates of the same image. + */ + @PinnedObjectField + @RawField + InstalledCodeObserverHandleAccessor getAccessor(); + + @PinnedObjectField + @RawField + void setAccessor(InstalledCodeObserverHandleAccessor accessor); + } + + interface InstalledCodeObserverHandleAccessor { + default void activate(InstalledCodeObserverHandle handle) { } - default void release() { + default void release(InstalledCodeObserverHandle handle) { } @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) - default void releaseOnTearDown() { + default void releaseOnTearDown(InstalledCodeObserverHandle handle) { } } - - InstalledCodeObserverHandle install(); - - interface Factory { - InstalledCodeObserver create(DebugContext debug, SharedMethod method, CompilationResult compilation, Pointer code); - } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserverSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserverSupport.java index c4395d22daef..8d16460789a4 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserverSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserverSupport.java @@ -32,16 +32,20 @@ import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.Pointer; +import org.graalvm.word.WordFactory; import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.c.NonmovableArray; +import com.oracle.svm.core.c.NonmovableArrays; import com.oracle.svm.core.code.InstalledCodeObserver.InstalledCodeObserverHandle; import com.oracle.svm.core.meta.SharedMethod; +import com.oracle.svm.core.snippets.KnownIntrinsics; public final class InstalledCodeObserverSupport { private final List observerFactories = new ArrayList<>(); @Platforms(Platform.HOSTED_ONLY.class) - public InstalledCodeObserverSupport() { + InstalledCodeObserverSupport() { } public void addObserverFactory(InstalledCodeObserver.Factory observerFactory) { @@ -57,36 +61,57 @@ public InstalledCodeObserver[] createObservers(DebugContext debug, SharedMethod return observers; } - public static InstalledCodeObserver.InstalledCodeObserverHandle[] installObservers(InstalledCodeObserver[] observers) { - InstalledCodeObserver.InstalledCodeObserverHandle[] observerHandles = new InstalledCodeObserver.InstalledCodeObserverHandle[observers.length]; - int index = 0; - for (InstalledCodeObserver observer : observers) { - observerHandles[index++] = observer.install(); + public static NonmovableArray installObservers(InstalledCodeObserver[] observers) { + if (observers.length == 0) { + return NonmovableArrays.nullArray(); + } + NonmovableArray observerHandles = NonmovableArrays.createWordArray(observers.length); + for (int i = 0; i < observers.length; i++) { + InstalledCodeObserverHandle handle = observers[i].install(); + NonmovableArrays.setWord(observerHandles, i, handle); } return observerHandles; } - public static void activateObservers(InstalledCodeObserver.InstalledCodeObserverHandle[] observerHandles) { - for (InstalledCodeObserverHandle handle : observerHandles) { - if (handle != null) { - handle.activate(); - } - } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static InstalledCodeObserver.InstalledCodeObserverHandleAccessor getAccessor(InstalledCodeObserverHandle handle) { + return KnownIntrinsics.convertUnknownValue(handle.getAccessor(), InstalledCodeObserver.InstalledCodeObserverHandleAccessor.class); + } + + public static void activateObservers(NonmovableArray observerHandles) { + forEach(observerHandles, h -> getAccessor(h).activate(h)); + } + + public static void removeObservers(NonmovableArray observerHandles) { + forEach(observerHandles, h -> getAccessor(h).release(h)); + } + + private interface InstalledCodeObserverHandleAction { + void invoke(InstalledCodeObserverHandle handle); } - public static void removeObservers(InstalledCodeObserver.InstalledCodeObserverHandle[] observerHandles) { - for (InstalledCodeObserverHandle handle : observerHandles) { - if (handle != null) { - handle.release(); + private static void forEach(NonmovableArray array, InstalledCodeObserverHandleAction action) { + if (array.isNonNull()) { + int length = NonmovableArrays.lengthOf(array); + for (int i = 0; i < length; i++) { + InstalledCodeObserverHandle handle = NonmovableArrays.getWord(array, i); + if (handle.isNonNull()) { + action.invoke(handle); + } } } } @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) - public static void removeObserversOnTearDown(InstalledCodeObserverHandle[] observerHandles) { - for (InstalledCodeObserverHandle handle : observerHandles) { - if (handle != null) { - handle.releaseOnTearDown(); + public static void removeObserversOnTearDown(NonmovableArray observerHandles) { + if (observerHandles.isNonNull()) { + int length = NonmovableArrays.lengthOf(observerHandles); + for (int i = 0; i < length; i++) { + InstalledCodeObserverHandle handle = NonmovableArrays.getWord(observerHandles, i); + if (handle.isNonNull()) { + getAccessor(handle).releaseOnTearDown(handle); + NonmovableArrays.setWord(observerHandles, i, WordFactory.nullPointer()); + } } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeCodeInfo.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeCodeInfo.java index 7bd542e9f128..d30ebae6e6a0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeCodeInfo.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeCodeInfo.java @@ -214,8 +214,6 @@ protected void invalidateMethod(CodeInfo info) { installedCode.clearAddress(); } - InstalledCodeObserverSupport.removeObservers(RuntimeMethodInfoAccess.getCodeObserverHandles(info)); - /* * Deoptimize all invocations that are on the stack. This performs a stack walk, so all * metadata must be intact (even though the method was already marked as non-invokable). diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoAccess.java index a081755a5a7b..3af39b9d8e07 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoAccess.java @@ -56,8 +56,8 @@ static SubstrateInstalledCode getInstalledCode(CodeInfo info) { } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - static InstalledCodeObserverHandle[] getCodeObserverHandles(CodeInfo info) { - return CodeInfoAccess.getObjectField(info, CodeInfo.OBSERVERS_OBJFIELD); + static NonmovableArray getCodeObserverHandles(CodeInfo info) { + return info.getCodeObserverHandles(); } public static void setCodeLocation(CodeInfo info, Pointer start, int size) { @@ -84,13 +84,13 @@ static void setDeoptimizationMetadata(CodeInfo info, NonmovableArray st info.setDeoptimizationObjectConstants(objectConstants); } - public static void setData(CodeInfo info, SubstrateInstalledCode installedCode, int tier, InstalledCodeObserverHandle[] codeObserverHandles) { + public static void setData(CodeInfo info, SubstrateInstalledCode installedCode, int tier, NonmovableArray codeObserverHandles) { assert codeObserverHandles != null; NonmovableObjectArray objectFields = info.getObjectFields(); NonmovableArrays.setObject(objectFields, CodeInfo.NAME_OBJFIELD, installedCode.getName()); NonmovableArrays.setObject(objectFields, CodeInfo.INSTALLEDCODE_OBJFIELD, new WeakReference<>(installedCode)); - NonmovableArrays.setObject(objectFields, CodeInfo.OBSERVERS_OBJFIELD, codeObserverHandles); info.setTier(tier); + info.setCodeObserverHandles(codeObserverHandles); } static void walkReferences(CodeInfo info, ObjectReferenceVisitor visitor) { @@ -138,11 +138,13 @@ public void run() { static void partialReleaseAfterInvalidate(CodeInfo info) { assert NonmovableArrays.getObject(info.getObjectFields(), CodeInfo.TETHER_OBJFIELD) != null : "already released"; + InstalledCodeObserverSupport.removeObservers(RuntimeMethodInfoAccess.getCodeObserverHandles(info)); + NonmovableArrays.releaseUnmanagedArray(info.getCodeObserverHandles()); + info.setCodeObserverHandles(NonmovableArrays.nullArray()); + info.setCodeConstantsLive(false); releaseInstalledCode(info); - NonmovableArrays.setObject(info.getObjectFields(), CodeInfo.OBSERVERS_OBJFIELD, null); - /* * Set our reference to the tether object to null so that the Cleaner object can free our * memory as soon as any other references, e.g. from ongoing stack walks, are gone. @@ -156,10 +158,7 @@ private static void releaseInstalledCode(CodeInfo codeInfo) { @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) static void releaseMethodInfoOnTearDown(CodeInfo info) { - InstalledCodeObserverHandle[] handles = getCodeObserverHandles(info); - if (handles != null) { - InstalledCodeObserverSupport.removeObserversOnTearDown(handles); - } + InstalledCodeObserverSupport.removeObserversOnTearDown(getCodeObserverHandles(info)); releaseMethodInfoMemory(info); } From 4758f4b800f0516f315ac65d052eb3a49bf785a4 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Mon, 2 Sep 2019 15:52:55 +0200 Subject: [PATCH 123/140] Move OptionsEncoder to org.graalvm.util and factor out TypedData{Input,Output}Stream. --- compiler/mx.compiler/suite.py | 2 + .../libgraal/HotSpotToSVMEntryPoints.java | 2 +- .../runtime/SVMHotSpotGraalRuntimeMBean.java | 2 +- .../hotspot/test/CompileTheWorld.java | 2 +- .../libgraal/HotSpotToSVMEntryPoints.java | 2 +- .../runtime/hotspot/libgraal/IgvSupport.java | 2 +- .../libgraal/LibGraalTruffleRuntime.java | 2 +- .../libgraal/SVMHotSpotTruffleCompiler.java | 2 +- .../org/graalvm/libgraal/OptionsEncoder.java | 173 ------------------ .../src/org/graalvm/util/OptionsEncoder.java | 96 ++++++++++ .../graalvm/util/TypedDataInputStream.java | 82 +++++++++ .../graalvm/util/TypedDataOutputStream.java | 102 +++++++++++ .../hotspot/libgraal/LibGraalEntryPoints.java | 2 +- 13 files changed, 290 insertions(+), 181 deletions(-) delete mode 100644 compiler/src/org.graalvm.libgraal/src/org/graalvm/libgraal/OptionsEncoder.java create mode 100644 compiler/src/org.graalvm.util/src/org/graalvm/util/OptionsEncoder.java create mode 100644 compiler/src/org.graalvm.util/src/org/graalvm/util/TypedDataInputStream.java create mode 100644 compiler/src/org.graalvm.util/src/org/graalvm/util/TypedDataOutputStream.java diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index 8b824911534f..5ec959f92268 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -437,6 +437,7 @@ "dependencies" : [ "sdk:GRAAL_SDK", "JVMCI_HOTSPOT", + "org.graalvm.util", ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "8+", @@ -2314,6 +2315,7 @@ "distDependencies" : [ "sdk:GRAAL_SDK", "JVMCI_HOTSPOT", + "GRAAL_API", ], "maven": False, }, diff --git a/compiler/src/org.graalvm.compiler.hotspot.management.libgraal/src/org/graalvm/compiler/hotspot/management/libgraal/HotSpotToSVMEntryPoints.java b/compiler/src/org.graalvm.compiler.hotspot.management.libgraal/src/org/graalvm/compiler/hotspot/management/libgraal/HotSpotToSVMEntryPoints.java index 9fda61363ec9..48d6357a2ccd 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.management.libgraal/src/org/graalvm/compiler/hotspot/management/libgraal/HotSpotToSVMEntryPoints.java +++ b/compiler/src/org.graalvm.compiler.hotspot.management.libgraal/src/org/graalvm/compiler/hotspot/management/libgraal/HotSpotToSVMEntryPoints.java @@ -36,7 +36,6 @@ import javax.management.MBeanParameterInfo; import javax.management.ReflectionException; import org.graalvm.compiler.hotspot.management.HotSpotGraalRuntimeMBean; -import org.graalvm.libgraal.OptionsEncoder; import org.graalvm.libgraal.jni.HotSpotToSVMScope; import org.graalvm.libgraal.jni.JNI; import org.graalvm.libgraal.jni.JNIUtil; @@ -45,6 +44,7 @@ import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CLongPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.util.OptionsEncoder; import org.graalvm.word.WordFactory; /** diff --git a/compiler/src/org.graalvm.compiler.hotspot.management.libgraal/src/org/graalvm/compiler/hotspot/management/libgraal/runtime/SVMHotSpotGraalRuntimeMBean.java b/compiler/src/org.graalvm.compiler.hotspot.management.libgraal/src/org/graalvm/compiler/hotspot/management/libgraal/runtime/SVMHotSpotGraalRuntimeMBean.java index adaea289b846..4f622f397efa 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.management.libgraal/src/org/graalvm/compiler/hotspot/management/libgraal/runtime/SVMHotSpotGraalRuntimeMBean.java +++ b/compiler/src/org.graalvm.compiler.hotspot.management.libgraal/src/org/graalvm/compiler/hotspot/management/libgraal/runtime/SVMHotSpotGraalRuntimeMBean.java @@ -57,9 +57,9 @@ import org.graalvm.compiler.hotspot.management.HotSpotGraalRuntimeMBean; import org.graalvm.libgraal.LibGraal; import org.graalvm.libgraal.LibGraalScope; -import org.graalvm.libgraal.OptionsEncoder; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.util.OptionsEncoder; /** * Encapsulates a handle to a {@link HotSpotGraalRuntimeMBean} object in the SVM heap. Implements 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 95255bb5495e..8423577c804f 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 @@ -104,7 +104,7 @@ import org.graalvm.compiler.test.ModuleSupport; import org.graalvm.libgraal.LibGraal; import org.graalvm.libgraal.LibGraalScope; -import org.graalvm.libgraal.OptionsEncoder; +import org.graalvm.util.OptionsEncoder; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HotSpotToSVMEntryPoints.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HotSpotToSVMEntryPoints.java index 466bfe1a3d9e..5351d8d3f473 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HotSpotToSVMEntryPoints.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.libgraal/src/org/graalvm/compiler/truffle/compiler/hotspot/libgraal/HotSpotToSVMEntryPoints.java @@ -120,7 +120,6 @@ import org.graalvm.libgraal.jni.JNI.JString; import org.graalvm.graphio.GraphOutput; import org.graalvm.libgraal.LibGraal; -import org.graalvm.libgraal.OptionsEncoder; import org.graalvm.nativeimage.Isolate; import org.graalvm.nativeimage.Platform.HOSTED_ONLY; import org.graalvm.nativeimage.Platforms; @@ -128,6 +127,7 @@ import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; import org.graalvm.nativeimage.c.type.VoidPointer; +import org.graalvm.util.OptionsEncoder; import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.ResolvedJavaType; diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/IgvSupport.java b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/IgvSupport.java index aa1b261f4a63..038914518f01 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/IgvSupport.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/IgvSupport.java @@ -44,7 +44,7 @@ import org.graalvm.compiler.truffle.common.TruffleDebugJavaMethod; import org.graalvm.graphio.GraphOutput; import org.graalvm.libgraal.LibGraalScope; -import org.graalvm.libgraal.OptionsEncoder; +import org.graalvm.util.OptionsEncoder; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.services.Services; diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalTruffleRuntime.java b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalTruffleRuntime.java index 25dfff956124..c45272f861bd 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalTruffleRuntime.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/LibGraalTruffleRuntime.java @@ -32,7 +32,7 @@ import org.graalvm.compiler.truffle.runtime.hotspot.AbstractHotSpotTruffleRuntime; import org.graalvm.libgraal.LibGraal; import org.graalvm.libgraal.LibGraalScope; -import org.graalvm.libgraal.OptionsEncoder; +import org.graalvm.util.OptionsEncoder; import com.oracle.truffle.api.TruffleRuntime; diff --git a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/SVMHotSpotTruffleCompiler.java b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/SVMHotSpotTruffleCompiler.java index ccaab740d6f8..425cec655f29 100644 --- a/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/SVMHotSpotTruffleCompiler.java +++ b/compiler/src/org.graalvm.compiler.truffle.runtime.hotspot.libgraal/src/org/graalvm/compiler/truffle/runtime/hotspot/libgraal/SVMHotSpotTruffleCompiler.java @@ -40,7 +40,7 @@ import org.graalvm.compiler.truffle.common.TruffleInliningPlan; import org.graalvm.compiler.truffle.common.hotspot.HotSpotTruffleCompiler; import org.graalvm.libgraal.LibGraalScope; -import org.graalvm.libgraal.OptionsEncoder; +import org.graalvm.util.OptionsEncoder; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; diff --git a/compiler/src/org.graalvm.libgraal/src/org/graalvm/libgraal/OptionsEncoder.java b/compiler/src/org.graalvm.libgraal/src/org/graalvm/libgraal/OptionsEncoder.java deleted file mode 100644 index 8baa0ee91b49..000000000000 --- a/compiler/src/org.graalvm.libgraal/src/org/graalvm/libgraal/OptionsEncoder.java +++ /dev/null @@ -1,173 +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.libgraal; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Facilities for encoding/decoding a set of options to/from a byte array. - */ -public final class OptionsEncoder { - - private OptionsEncoder() { - } - - /** - * Determines if {@code value} is supported by {@link #encode(Map)}. - */ - public static boolean isValueSupported(Object value) { - if (value == null) { - return false; - } - Class valueClass = value.getClass(); - return valueClass == Boolean.class || - valueClass == Byte.class || - valueClass == Short.class || - valueClass == Character.class || - valueClass == Integer.class || - valueClass == Long.class || - valueClass == Float.class || - valueClass == Double.class || - valueClass == String.class || - value.getClass().isEnum(); - } - - /** - * Encodes {@code options} into a byte array. - * - * @throws IllegalArgumentException if any value in {@code options} is not - * {@linkplain #isValueSupported(Object) supported} - */ - public static byte[] encode(final Map options) { - try (ByteArrayOutputStream baout = new ByteArrayOutputStream()) { - try (DataOutputStream out = new DataOutputStream(baout)) { - out.writeInt(options.size()); - for (Map.Entry e : options.entrySet()) { - final String key = e.getKey(); - out.writeUTF(key); - final Object value = e.getValue(); - final Class valueClz = value.getClass(); - if (valueClz == Boolean.class) { - out.writeByte('Z'); - out.writeBoolean((Boolean) value); - } else if (valueClz == Byte.class) { - out.writeByte('B'); - out.writeByte((Byte) value); - } else if (valueClz == Short.class) { - out.writeByte('S'); - out.writeShort((Short) value); - } else if (valueClz == Character.class) { - out.writeByte('C'); - out.writeChar((Character) value); - } else if (valueClz == Integer.class) { - out.writeByte('I'); - out.writeInt((Integer) value); - } else if (valueClz == Long.class) { - out.writeByte('J'); - out.writeLong((Long) value); - } else if (valueClz == Float.class) { - out.writeByte('F'); - out.writeFloat((Float) value); - } else if (valueClz == Double.class) { - out.writeByte('D'); - out.writeDouble((Double) value); - } else if (valueClz == String.class) { - out.writeByte('U'); - out.writeUTF((String) value); - } else if (valueClz.isEnum()) { - out.writeByte('U'); - out.writeUTF(((Enum) value).name()); - } else { - throw new IllegalArgumentException(String.format("Key: %s, Value: %s, Value type: %s", key, value, valueClz)); - } - } - } - return baout.toByteArray(); - } catch (IOException ioe) { - throw new IllegalArgumentException(ioe); - } - } - - /** - * Decodes {@code input} into a name/value map. - * - * @throws IllegalArgumentException if {@code input} cannot be decoded - */ - public static Map decode(byte[] input) { - Map res = new LinkedHashMap<>(); - try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(input))) { - final int size = in.readInt(); - for (int i = 0; i < size; i++) { - final String key = in.readUTF(); - final Object value; - final byte type = in.readByte(); - switch (type) { - case 'Z': - value = in.readBoolean(); - break; - case 'B': - value = in.readByte(); - break; - case 'S': - value = in.readShort(); - break; - case 'C': - value = in.readChar(); - break; - case 'I': - value = in.readInt(); - break; - case 'J': - value = in.readLong(); - break; - case 'F': - value = in.readFloat(); - break; - case 'D': - value = in.readDouble(); - break; - case 'U': - value = in.readUTF(); - break; - default: - throw new IllegalArgumentException("Unsupported value type: " + Integer.toHexString(type)); - } - res.put(key, value); - } - if (in.available() != 0) { - throw new IllegalArgumentException(in.available() + " undecoded bytes"); - } - } catch (IOException ioe) { - throw new IllegalArgumentException(ioe); - } - return res; - } -} diff --git a/compiler/src/org.graalvm.util/src/org/graalvm/util/OptionsEncoder.java b/compiler/src/org.graalvm.util/src/org/graalvm/util/OptionsEncoder.java new file mode 100644 index 000000000000..9ad1e6ce31ad --- /dev/null +++ b/compiler/src/org.graalvm.util/src/org/graalvm/util/OptionsEncoder.java @@ -0,0 +1,96 @@ +/* + * 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.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Facilities for encoding/decoding a set of options to/from a byte array. + */ +public final class OptionsEncoder { + + private OptionsEncoder() { + } + + /** + * Determines if {@code value} is supported by {@link #encode(Map)}. + */ + public static boolean isValueSupported(Object value) { + return TypedDataOutputStream.isValueSupported(value); + } + + /** + * Encodes {@code options} into a byte array. + * + * @throws IllegalArgumentException if any value in {@code options} is not + * {@linkplain #isValueSupported(Object) supported} + */ + public static byte[] encode(final Map options) { + try (ByteArrayOutputStream baout = new ByteArrayOutputStream()) { + try (TypedDataOutputStream out = new TypedDataOutputStream(baout)) { + out.writeInt(options.size()); + for (Map.Entry e : options.entrySet()) { + out.writeUTF(e.getKey()); + try { + out.writeTypedValue(e.getValue()); + } catch (IllegalArgumentException iae) { + throw new IllegalArgumentException(String.format("Key: %s, Value: %s, Value type: %s", + e.getKey(), e.getValue(), e.getValue().getClass()), iae); + } + } + } + return baout.toByteArray(); + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); + } + } + + /** + * Decodes {@code input} into a name/value map. + * + * @throws IllegalArgumentException if {@code input} cannot be decoded + */ + public static Map decode(byte[] input) { + Map res = new LinkedHashMap<>(); + try (TypedDataInputStream in = new TypedDataInputStream(new ByteArrayInputStream(input))) { + final int size = in.readInt(); + for (int i = 0; i < size; i++) { + final String key = in.readUTF(); + final Object value = in.readTypedValue(); + res.put(key, value); + } + if (in.available() != 0) { + throw new IllegalArgumentException(in.available() + " undecoded bytes"); + } + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); + } + return res; + } +} diff --git a/compiler/src/org.graalvm.util/src/org/graalvm/util/TypedDataInputStream.java b/compiler/src/org.graalvm.util/src/org/graalvm/util/TypedDataInputStream.java new file mode 100644 index 000000000000..b0e765d7d177 --- /dev/null +++ b/compiler/src/org.graalvm.util/src/org/graalvm/util/TypedDataInputStream.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 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.util; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * A stream that can read (trivial) values using their in-band data type information, intended for + * use with {@link TypedDataOutputStream}. + */ +public class TypedDataInputStream extends DataInputStream { + public TypedDataInputStream(InputStream in) { + super(in); + } + + /** + * Reads a single value, using the data type encoded in the stream. + * + * @return The read value, such as a boxed primitive or a {@link String}. + * @exception IOException in case of an I/O error. + */ + public Object readTypedValue() throws IOException { + Object value; + final byte type = readByte(); + switch (type) { + case 'Z': + value = readBoolean(); + break; + case 'B': + value = readByte(); + break; + case 'S': + value = readShort(); + break; + case 'C': + value = readChar(); + break; + case 'I': + value = readInt(); + break; + case 'J': + value = readLong(); + break; + case 'F': + value = readFloat(); + break; + case 'D': + value = readDouble(); + break; + case 'U': + value = readUTF(); + break; + default: + throw new IOException("Unsupported type: " + Integer.toHexString(type)); + } + return value; + } +} diff --git a/compiler/src/org.graalvm.util/src/org/graalvm/util/TypedDataOutputStream.java b/compiler/src/org.graalvm.util/src/org/graalvm/util/TypedDataOutputStream.java new file mode 100644 index 000000000000..168ed5617ead --- /dev/null +++ b/compiler/src/org.graalvm.util/src/org/graalvm/util/TypedDataOutputStream.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 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.util; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * A stream that can write (trivial) values together with their data type, for use with + * {@link TypedDataInputStream}. + */ +public class TypedDataOutputStream extends DataOutputStream { + /** Determines if {@code value} is supported by {@link #writeTypedValue(Object)}. */ + public static boolean isValueSupported(Object value) { + if (value == null) { + return false; + } + Class valueClass = value.getClass(); + return valueClass == Boolean.class || + valueClass == Byte.class || + valueClass == Short.class || + valueClass == Character.class || + valueClass == Integer.class || + valueClass == Long.class || + valueClass == Float.class || + valueClass == Double.class || + valueClass == String.class || + value.getClass().isEnum(); + } + + public TypedDataOutputStream(OutputStream out) { + super(out); + } + + /** + * Writes the value that is represented by the given non-null object, together with information + * on the value's data type. + * + * @param value A value of a {@linkplain #isValueSupported supported type}. + * @exception IllegalArgumentException when the provided type is not supported. + * @exception IOException in case of an I/O error. + */ + public void writeTypedValue(Object value) throws IOException { + Class valueClz = value.getClass(); + if (valueClz == Boolean.class) { + this.writeByte('Z'); + this.writeBoolean((Boolean) value); + } else if (valueClz == Byte.class) { + this.writeByte('B'); + this.writeByte((Byte) value); + } else if (valueClz == Short.class) { + this.writeByte('S'); + this.writeShort((Short) value); + } else if (valueClz == Character.class) { + this.writeByte('C'); + this.writeChar((Character) value); + } else if (valueClz == Integer.class) { + this.writeByte('I'); + this.writeInt((Integer) value); + } else if (valueClz == Long.class) { + this.writeByte('J'); + this.writeLong((Long) value); + } else if (valueClz == Float.class) { + this.writeByte('F'); + this.writeFloat((Float) value); + } else if (valueClz == Double.class) { + this.writeByte('D'); + this.writeDouble((Double) value); + } else if (valueClz == String.class) { + this.writeByte('U'); + this.writeUTF((String) value); + } else if (valueClz.isEnum()) { + this.writeByte('U'); + this.writeUTF(((Enum) value).name()); + } else { + throw new IllegalArgumentException(String.format("Unsupported type: Value: %s, Value type: %s", value, valueClz)); + } + } +} 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 2ffe0da6bf51..60c5cbec76bf 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 @@ -41,7 +41,6 @@ import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import org.graalvm.libgraal.LibGraal; -import org.graalvm.libgraal.OptionsEncoder; import org.graalvm.nativeimage.Isolate; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.c.function.CEntryPoint; @@ -49,6 +48,7 @@ import org.graalvm.nativeimage.c.function.CEntryPoint.IsolateContext; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.util.OptionsEncoder; import org.graalvm.word.PointerBase; import com.oracle.svm.core.c.function.CEntryPointOptions; From a908e771e95b4bc9bc1992d11dbd23b0f39dcca6 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Thu, 18 Jul 2019 14:51:33 +0200 Subject: [PATCH 124/140] Refactor aspects of runtime compilation and code installation. --- compiler/mx.compiler/suite.py | 2 +- .../aarch64/AArch64NativeImagePatcher.java | 30 +-- .../graal/amd64/AMD64NativeImagePatcher.java | 29 +-- .../core/graal/code/NativeImagePatcher.java | 18 +- .../graal/meta/SharedCodeCacheProvider.java | 82 +++++++ .../SharedConstantReflectionProvider.java | 4 +- .../oracle/svm/core/c/NonmovableArrays.java | 14 +- .../oracle/svm/core/code/CodeInfoEncoder.java | 9 +- .../svm/core/code/FrameInfoEncoder.java | 31 +-- .../svm/core/code/InstalledCodeObserver.java | 7 + .../code/InstalledCodeObserverSupport.java | 8 + .../core/code/InstantReferenceAdjuster.java | 70 ++++++ .../svm/core/code/ReferenceAdjuster.java | 92 +++++++ .../core/code/RuntimeMethodInfoAccess.java | 86 ++++--- .../core/code/RuntimeMethodInfoMemory.java | 2 +- .../svm/core/handles/ThreadLocalHandles.java | 4 + .../svm/core/heap/ReferenceAccessImpl.java | 6 +- .../meta/DirectSubstrateObjectConstant.java | 132 ++++++++++ .../core/meta/SubstrateObjectConstant.java | 128 +++------- .../oracle/svm/graal/SubstrateGraalUtils.java | 69 +----- .../oracle/svm/graal/hosted/GraalFeature.java | 11 +- .../svm/graal/hosted/GraalObjectReplacer.java | 29 +-- .../GraalProviderObjectReplacements.java | 79 ++++++ .../svm/graal/hosted/RuntimeGraalSetup.java | 35 +++ .../hosted/SubstrateRuntimeGraalSetup.java | 35 +++ .../svm/graal/meta/RuntimeCodeInstaller.java} | 231 +++++++----------- .../meta/SubstrateCodeCacheProvider.java | 58 +---- .../SubstrateConstantReflectionProvider.java | 2 +- .../oracle/svm/graal/meta/SubstrateField.java | 4 +- .../SubstrateMemoryAccessProviderImpl.java | 4 +- .../svm/graal/meta/SubstrateMetaAccess.java | 2 +- .../SubstrateRuntimeConfigurationBuilder.java | 7 + .../hosted/code/HostedCodeCacheProvider.java | 46 ++++ .../HostedRuntimeConfigurationBuilder.java | 6 + .../SharedRuntimeConfigurationBuilder.java | 5 +- .../hosted/image/NativeImageCodeCache.java | 8 +- .../truffle/api/SubstrateTruffleRuntime.java | 15 +- 37 files changed, 881 insertions(+), 519 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedCodeCacheProvider.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstantReferenceAdjuster.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ReferenceAdjuster.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java create mode 100644 substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalProviderObjectReplacements.java create mode 100644 substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeGraalSetup.java create mode 100644 substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/SubstrateRuntimeGraalSetup.java rename substratevm/src/{com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/InstalledCodeBuilder.java => com.oracle.svm.graal/src/com/oracle/svm/graal/meta/RuntimeCodeInstaller.java} (68%) rename substratevm/src/{com.oracle.svm.core.graal/src/com/oracle/svm/core => com.oracle.svm.graal/src/com/oracle/svm}/graal/meta/SubstrateCodeCacheProvider.java (63%) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index 5ec959f92268..46ef04ffdaa9 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -437,7 +437,6 @@ "dependencies" : [ "sdk:GRAAL_SDK", "JVMCI_HOTSPOT", - "org.graalvm.util", ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "8+", @@ -1979,6 +1978,7 @@ "org.graalvm.libgraal", "org.graalvm.compiler.truffle.runtime.hotspot", "org.graalvm.compiler.truffle.common.hotspot.libgraal", + "org.graalvm.util", ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "8,11+", 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 d0e7e27c1e40..a164fab60a78 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 @@ -29,14 +29,12 @@ import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandDataAnnotation; import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.word.Pointer; +import org.graalvm.nativeimage.hosted.Feature; import com.oracle.svm.core.annotate.AutomaticFeature; -import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.graal.code.NativeImagePatcher; import com.oracle.svm.core.graal.code.PatchConsumerFactory; @@ -70,7 +68,7 @@ public AArch64NativeImagePatcher(int instructionStartPosition, OperandDataAnnota } @Override - public void patch(int codePos, int relative, byte[] code) { + public void patchCode(int relative, byte[] code) { // int curValue = relative - (annotation.nextInstructionPosition - // annotation.instructionPosition); // @@ -82,30 +80,14 @@ public void patch(int codePos, int relative, byte[] code) { // assert curValue == 0; } - @Uninterruptible(reason = "The patcher is intended to work with raw pointers") @Override - public void patchData(Pointer pointer, Object object) { - // Pointer address = pointer.add(annotation.operandPosition); - // if (annotation.operandSize == Long.BYTES && annotation.operandSize > - // ConfigurationValues.getObjectLayout().getReferenceSize()) { - // /* - // * Some instructions use 8-byte immediates even for narrow (4-byte) compressed - // * references. We zero all 8 bytes and patch a narrow reference at the offset, which - // * results in the same 8-byte value with little-endian order. - // */ - // address.writeLong(0, 0); - // } else { - // assert annotation.operandSize == ConfigurationValues.getObjectLayout().getReferenceSize() - // : - // "Unsupported reference constant size"; - // } - // boolean compressed = ReferenceAccess.singleton().haveCompressedReferences(); - // ReferenceAccess.singleton().writeObjectAt(address, object, compressed); + public int getOffset() { + return annotation.operandPosition; } @Override - public int getPosition() { - return annotation.operandPosition; + public int getLength() { + return annotation.operandSize; } @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 2d09216f3a57..7147ba6f98c1 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 @@ -29,18 +29,14 @@ import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandDataAnnotation; import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.word.Pointer; +import org.graalvm.nativeimage.hosted.Feature; import com.oracle.svm.core.annotate.AutomaticFeature; -import com.oracle.svm.core.annotate.Uninterruptible; -import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.graal.code.NativeImagePatcher; import com.oracle.svm.core.graal.code.PatchConsumerFactory; -import com.oracle.svm.core.heap.ReferenceAccess; @AutomaticFeature @Platforms({Platform.AMD64.class}) @@ -72,7 +68,7 @@ public AMD64NativeImagePatcher(int instructionStartPosition, OperandDataAnnotati } @Override - public void patch(int codePos, int relative, byte[] code) { + public void patchCode(int relative, byte[] code) { int curValue = relative - (annotation.nextInstructionPosition - annotation.instructionPosition); for (int i = 0; i < annotation.operandSize; i++) { @@ -83,27 +79,14 @@ public void patch(int codePos, int relative, byte[] code) { assert curValue == 0; } - @Uninterruptible(reason = "The patcher is intended to work with raw pointers") @Override - public void patchData(Pointer pointer, Object object) { - Pointer address = pointer.add(annotation.operandPosition); - if (annotation.operandSize == Long.BYTES && annotation.operandSize > ConfigurationValues.getObjectLayout().getReferenceSize()) { - /* - * Some instructions use 8-byte immediates even for narrow (4-byte) compressed - * references. We zero all 8 bytes and patch a narrow reference at the offset, which - * results in the same 8-byte value with little-endian order. - */ - address.writeLong(0, 0); - } else { - assert annotation.operandSize == ConfigurationValues.getObjectLayout().getReferenceSize() : "Unsupported reference constant size"; - } - boolean compressed = ReferenceAccess.singleton().haveCompressedReferences(); - ReferenceAccess.singleton().writeObjectAt(address, object, compressed); + public int getOffset() { + return annotation.operandPosition; } @Override - public int getPosition() { - return annotation.operandPosition; + public int getLength() { + return annotation.operandSize; } @Override diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/code/NativeImagePatcher.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/code/NativeImagePatcher.java index 5f0fe11acd4d..1bbd5db4ad3c 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/code/NativeImagePatcher.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/code/NativeImagePatcher.java @@ -24,27 +24,23 @@ */ package com.oracle.svm.core.graal.code; -import org.graalvm.word.Pointer; - -import com.oracle.svm.core.annotate.Uninterruptible; - /** * Patcher used during native image runtime. */ public interface NativeImagePatcher { /** - * Patch the code buffer. + * Patch directly in the code buffer with an offset relative to the start of this instruction. */ - void patch(int codePos, int relative, byte[] code); + void patchCode(int relative, byte[] code); /** - * Patch a VMConstant in the native-image. + * The position from the beginning of the method where the patch is applied. This offset is used + * in the reference map. */ - @Uninterruptible(reason = "The patcher is intended to work with raw pointers") - void patchData(Pointer pointer, Object object); + int getOffset(); /** - * Return the position where the patch is applied. This offset is used in the reference map. + * The length of the value to patch in bytes, e.g., the size of an operand. */ - int getPosition(); + int getLength(); } diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedCodeCacheProvider.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedCodeCacheProvider.java new file mode 100644 index 000000000000..5f1e8d4964b3 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedCodeCacheProvider.java @@ -0,0 +1,82 @@ +/* + * 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.core.graal.meta; + +import static com.oracle.svm.core.util.VMError.unimplemented; + +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +import jdk.vm.ci.code.CodeCacheProvider; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.SpeculationLog; + +public abstract class SharedCodeCacheProvider implements CodeCacheProvider { + protected final TargetDescription target; + protected final RegisterConfig registerConfig; + + @Platforms(Platform.HOSTED_ONLY.class) + public SharedCodeCacheProvider(TargetDescription target, RegisterConfig registerConfig) { + this.target = target; + this.registerConfig = registerConfig; + } + + @Override + public void invalidateInstalledCode(InstalledCode installedCode) { + throw unimplemented(); + } + + @Override + public long getMaxCallTargetOffset(long address) { + throw unimplemented(); + } + + @Override + public boolean shouldDebugNonSafepoints() { + return false; + } + + @Override + public SpeculationLog createSpeculationLog() { + throw unimplemented(); + } + + @Override + public RegisterConfig getRegisterConfig() { + return registerConfig; + } + + @Override + public int getMinimumOutgoingSize() { + return 0; + } + + @Override + public TargetDescription getTarget() { + return target; + } +} diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java index 7893dc2479d0..527c4e03b1d9 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java @@ -49,7 +49,7 @@ public Boolean constantEquals(Constant x, Constant y) { if (x == y) { return true; } else if (x instanceof SubstrateObjectConstant) { - return y instanceof SubstrateObjectConstant && ((SubstrateObjectConstant) x).getObject() == ((SubstrateObjectConstant) y).getObject(); + return y instanceof SubstrateObjectConstant && SubstrateObjectConstant.asObject(x) == SubstrateObjectConstant.asObject(y); } else { return x.equals(y); } @@ -69,7 +69,7 @@ public JavaConstant readArrayElement(JavaConstant array, int index) { return null; } - Object a = KnownIntrinsics.convertUnknownValue(((SubstrateObjectConstant) array).getObject(), Object.class); + Object a = KnownIntrinsics.convertUnknownValue(SubstrateObjectConstant.asObject(array), Object.class); if (index < 0 || index >= Array.getLength(a)) { return null; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/NonmovableArrays.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/NonmovableArrays.java index b98c33b5b00b..a300749e8037 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/NonmovableArrays.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/NonmovableArrays.java @@ -94,10 +94,16 @@ private static > T createArray(int length, Class Heap.getHeap().getObjectHeader().initializeHeaderOfNewObject(array, hub, HeapKind.Unmanaged); array.writeInt(ConfigurationValues.getObjectLayout().getArrayLengthOffset(), length); // already zero-initialized thanks to calloc() - assert runtimeArraysInExistence.incrementAndGet() > 0 : "overflow"; + trackUnmanagedArray((NonmovableArray) array); return (T) array; } + /** Begins tracking an array, e.g. when it is handed over from a different isolate. */ + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static void trackUnmanagedArray(@SuppressWarnings("unused") NonmovableArray array) { + assert runtimeArraysInExistence.incrementAndGet() > 0 : "overflow"; + } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static DynamicHub readHub(NonmovableArray array) { ObjectHeader objectHeader = Heap.getHeap().getObjectHeader(); @@ -229,6 +235,12 @@ public static NonmovableObjectArray copyOfObjectArray(T[] source) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void releaseUnmanagedArray(NonmovableArray array) { ImageSingletons.lookup(UnmanagedMemorySupport.class).free(array); + untrackUnmanagedArray(array); + } + + /** Untracks an array created at runtime, e.g. before it is handed over to another isolate. */ + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static void untrackUnmanagedArray(NonmovableArray array) { assert array.isNull() || runtimeArraysInExistence.getAndDecrement() > 0; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java index 9268848204ad..b140987923fa 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java @@ -177,9 +177,9 @@ private IPData makeEntry(long ip) { return result; } - public void encodeAllAndInstall(CodeInfo target) { + public void encodeAllAndInstall(CodeInfo target, ReferenceAdjuster adjuster) { encodeReferenceMaps(); - frameInfoEncoder.encodeAllAndInstall(target); + frameInfoEncoder.encodeAllAndInstall(target, adjuster); encodeIPData(); install(target); @@ -383,6 +383,11 @@ public static boolean verifyMethod(CompilationResult compilation, int compilatio CodeInfoVerifier.verifyMethod(compilation, compilationOffset, info); return true; } + + public boolean verifyFrameInfo(CodeInfo info) { + frameInfoEncoder.verifyEncoding(info); + return true; + } } class CodeInfoVerifier { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoEncoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoEncoder.java index bbda3f454be0..5a590f896f34 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoEncoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoEncoder.java @@ -51,7 +51,6 @@ import com.oracle.svm.core.meta.SharedMethod; import com.oracle.svm.core.meta.SharedType; import com.oracle.svm.core.meta.SubstrateObjectConstant; -import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.util.ByteArrayReader; import com.oracle.svm.core.util.HostedStringDeduplication; @@ -482,12 +481,8 @@ private static int computeOffset(List valueInfos) { return result; } - protected void encodeAllAndInstall(CodeInfo target) { - final JavaConstant[] encodedJavaConstants = objectConstants.encodeAll(new JavaConstant[objectConstants.getLength()]); - Object[] objectConstantsArray = new Object[encodedJavaConstants.length]; - for (int i = 0; i < encodedJavaConstants.length; i++) { - objectConstantsArray[i] = KnownIntrinsics.convertUnknownValue(SubstrateObjectConstant.asObject(encodedJavaConstants[i]), Object.class); - } + protected void encodeAllAndInstall(CodeInfo target, ReferenceAdjuster adjuster) { + JavaConstant[] encodedJavaConstants = objectConstants.encodeAll(new JavaConstant[objectConstants.getLength()]); Class[] sourceClassesArray = null; String[] sourceMethodNamesArray = null; String[] namesArray = null; @@ -500,17 +495,17 @@ protected void encodeAllAndInstall(CodeInfo target) { namesArray = names.encodeAll(new String[names.getLength()]); } NonmovableArray frameInfoEncodings = encodeFrameDatas(); - install(target, frameInfoEncodings, objectConstantsArray, sourceClassesArray, sourceMethodNamesArray, namesArray); + install(target, frameInfoEncodings, encodedJavaConstants, sourceClassesArray, sourceMethodNamesArray, namesArray, adjuster); } @Uninterruptible(reason = "Nonmovable object arrays are not visible to GC until installed in target.") - private void install(CodeInfo target, NonmovableArray frameInfoEncodings, Object[] objectConstantsArray, - Class[] sourceClassesArray, String[] sourceMethodNamesArray, String[] namesArray) { + private static void install(CodeInfo target, NonmovableArray frameInfoEncodings, JavaConstant[] objectConstantsArray, Class[] sourceClassesArray, + String[] sourceMethodNamesArray, String[] namesArray, ReferenceAdjuster adjuster) { - NonmovableObjectArray frameInfoObjectConstants = NonmovableArrays.copyOfObjectArray(objectConstantsArray); - NonmovableObjectArray> frameInfoSourceClasses = (sourceClassesArray != null) ? NonmovableArrays.copyOfObjectArray(sourceClassesArray) : NonmovableArrays.nullArray(); - NonmovableObjectArray frameInfoSourceMethodNames = (sourceMethodNamesArray != null) ? NonmovableArrays.copyOfObjectArray(sourceMethodNamesArray) : NonmovableArrays.nullArray(); - NonmovableObjectArray frameInfoNames = (namesArray != null) ? NonmovableArrays.copyOfObjectArray(namesArray) : NonmovableArrays.nullArray(); + NonmovableObjectArray frameInfoObjectConstants = adjuster.copyOfObjectConstantArray(objectConstantsArray); + NonmovableObjectArray> frameInfoSourceClasses = (sourceClassesArray != null) ? adjuster.copyOfObjectArray(sourceClassesArray) : NonmovableArrays.nullArray(); + NonmovableObjectArray frameInfoSourceMethodNames = (sourceMethodNamesArray != null) ? adjuster.copyOfObjectArray(sourceMethodNamesArray) : NonmovableArrays.nullArray(); + NonmovableObjectArray frameInfoNames = (namesArray != null) ? adjuster.copyOfObjectArray(namesArray) : NonmovableArrays.nullArray(); CodeInfoAccess.setFrameInfo(target, frameInfoEncodings, frameInfoObjectConstants, frameInfoSourceClasses, frameInfoSourceMethodNames, frameInfoNames); @@ -518,10 +513,7 @@ private void install(CodeInfo target, NonmovableArray frameInfoEncodings, } @Uninterruptible(reason = "Safe for GC, but called from uninterruptible code.", calleeMustBe = false) - private void afterInstallation(CodeInfo info) { - - assert verifyEncoding(info); - + private static void afterInstallation(CodeInfo info) { ImageSingletons.lookup(Counters.class).frameInfoSize.add( ConfigurationValues.getObjectLayout().getArrayElementOffset(JavaKind.Byte, NonmovableArrays.lengthOf(info.getFrameInfoEncodings())) + ConfigurationValues.getObjectLayout().getArrayElementOffset(JavaKind.Object, NonmovableArrays.lengthOf(info.getFrameInfoObjectConstants()))); @@ -638,13 +630,12 @@ public static long encodeBci(int bci, boolean duringCall, boolean rethrowExcepti return (((long) bci) << FrameInfoDecoder.BCI_SHIFT) | (duringCall ? FrameInfoDecoder.DURING_CALL_MASK : 0) | (rethrowException ? FrameInfoDecoder.RETHROW_EXCEPTION_MASK : 0); } - private boolean verifyEncoding(CodeInfo info) { + void verifyEncoding(CodeInfo info) { for (FrameData expectedData : allDebugInfos) { FrameInfoQueryResult actualFrame = FrameInfoDecoder.decodeFrameInfo(expectedData.frame.isDeoptEntry, new ReusableTypeReader(info.getFrameInfoEncodings(), expectedData.indexInEncodings), info, FrameInfoDecoder.HeapBasedFrameInfoQueryResultAllocator, FrameInfoDecoder.HeapBasedValueInfoAllocator, true); FrameInfoVerifier.verifyFrames(expectedData, expectedData.frame, actualFrame); } - return true; } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserver.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserver.java index 8e86dd9310b7..5b7e6c072037 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserver.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserver.java @@ -65,6 +65,7 @@ interface InstalledCodeObserverHandle extends PointerBase { void setAccessor(InstalledCodeObserverHandleAccessor accessor); } + @SuppressWarnings("unused") interface InstalledCodeObserverHandleAccessor { default void activate(InstalledCodeObserverHandle handle) { } @@ -72,6 +73,12 @@ default void activate(InstalledCodeObserverHandle handle) { default void release(InstalledCodeObserverHandle handle) { } + default void detachFromCurrentIsolate(InstalledCodeObserverHandle handle) { + } + + default void attachToCurrentIsolate(InstalledCodeObserverHandle handle) { + } + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) default void releaseOnTearDown(InstalledCodeObserverHandle handle) { } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserverSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserverSupport.java index 8d16460789a4..57a4dcadfe42 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserverSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstalledCodeObserverSupport.java @@ -82,6 +82,14 @@ public static void activateObservers(NonmovableArray getAccessor(h).activate(h)); } + public static void detachFromCurrentIsolate(NonmovableArray observerHandles) { + forEach(observerHandles, h -> getAccessor(h).detachFromCurrentIsolate(h)); + } + + public static void attachToCurrentIsolate(NonmovableArray observerHandles) { + forEach(observerHandles, h -> getAccessor(h).attachToCurrentIsolate(h)); + } + public static void removeObservers(NonmovableArray observerHandles) { forEach(observerHandles, h -> getAccessor(h).release(h)); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstantReferenceAdjuster.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstantReferenceAdjuster.java new file mode 100644 index 000000000000..8c3ef86a385d --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/InstantReferenceAdjuster.java @@ -0,0 +1,70 @@ +/* + * 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.core.code; + +import org.graalvm.word.Pointer; +import org.graalvm.word.PointerBase; + +import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.c.NonmovableArrays; +import com.oracle.svm.core.c.NonmovableObjectArray; +import com.oracle.svm.core.meta.DirectSubstrateObjectConstant; +import com.oracle.svm.core.meta.SubstrateObjectConstant; + +/** + * Immediately writes object references and fails if it cannot do so. + */ +public class InstantReferenceAdjuster implements ReferenceAdjuster { + @Override + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public void setObjectInArray(NonmovableObjectArray array, int index, T object) { + NonmovableArrays.setObject(array, index, object); + } + + @Override + @SuppressWarnings("unchecked") + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public void setConstantTargetInArray(NonmovableObjectArray array, int index, SubstrateObjectConstant constant) { + NonmovableArrays.setObject(array, index, (T) ((DirectSubstrateObjectConstant) constant).getObject()); + } + + @Override + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public void setConstantTargetAt(PointerBase address, int length, SubstrateObjectConstant constant) { + ReferenceAdjuster.writeReference((Pointer) address, length, ((DirectSubstrateObjectConstant) constant).getObject()); + } + + @Override + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public NonmovableObjectArray copyOfObjectArray(T[] source) { + return NonmovableArrays.copyOfObjectArray(source); + } + + @Override + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public boolean isFinished() { + return true; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ReferenceAdjuster.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ReferenceAdjuster.java new file mode 100644 index 000000000000..92aaebf39ada --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ReferenceAdjuster.java @@ -0,0 +1,92 @@ +/* + * 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.core.code; + +import java.nio.ByteOrder; + +import org.graalvm.compiler.api.replacements.Fold; +import org.graalvm.word.Pointer; +import org.graalvm.word.PointerBase; + +import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.c.NonmovableArrays; +import com.oracle.svm.core.c.NonmovableObjectArray; +import com.oracle.svm.core.config.ConfigurationValues; +import com.oracle.svm.core.heap.ReferenceAccess; +import com.oracle.svm.core.meta.SubstrateObjectConstant; + +import jdk.vm.ci.meta.Constant; + +/** + * Tool for adjusting references to objects in non-movable data structures. + */ +public interface ReferenceAdjuster { + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + void setConstantTargetInArray(NonmovableObjectArray array, int index, SubstrateObjectConstant constant); + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + void setObjectInArray(NonmovableObjectArray array, int index, T object); + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + void setConstantTargetAt(PointerBase address, int length, SubstrateObjectConstant constant); + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + default NonmovableObjectArray copyOfObjectConstantArray(T[] constants) { + NonmovableObjectArray objects = NonmovableArrays.createObjectArray(constants.length); + for (int i = 0; i < constants.length; i++) { + setConstantTargetInArray(objects, i, (SubstrateObjectConstant) constants[i]); + } + return objects; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + NonmovableObjectArray copyOfObjectArray(T[] source); + + /** Indicates whether all object references have been written. */ + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + boolean isFinished(); + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + static void writeReference(Pointer address, int length, Object obj) { + if (length == Long.BYTES && length > ConfigurationValues.getObjectLayout().getReferenceSize()) { + /* + * For 8-byte immediates in instructions despite using narrow 4-byte references: we zero + * all 8 bytes and patch a narrow reference at the offset, which results in the same + * 8-byte value with little-endian order. + */ + assert nativeByteOrder() == ByteOrder.LITTLE_ENDIAN; + address.writeLong(0, 0L); + } else { + assert length == ConfigurationValues.getObjectLayout().getReferenceSize() : "Unsupported reference constant size"; + } + boolean compressed = ReferenceAccess.singleton().haveCompressedReferences(); + ReferenceAccess.singleton().writeObjectAt(address, obj, compressed); + } + + @Fold + static ByteOrder nativeByteOrder() { + return ConfigurationValues.getTarget().arch.getByteOrder(); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoAccess.java index 3af39b9d8e07..5722e339e289 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoAccess.java @@ -33,8 +33,10 @@ import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.impl.UnmanagedMemorySupport; import org.graalvm.word.Pointer; +import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; +import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.c.NonmovableArray; import com.oracle.svm.core.c.NonmovableArrays; @@ -60,9 +62,11 @@ static NonmovableArray getCodeObserverHandles(CodeI return info.getCodeObserverHandles(); } - public static void setCodeLocation(CodeInfo info, Pointer start, int size) { + public static void initialize(CodeInfo info, Pointer start, int size, int tier, NonmovableArray observerHandles) { info.setCodeStart((CodePointer) start); info.setCodeSize(WordFactory.unsigned(size)); + info.setTier(tier); + info.setCodeObserverHandles(observerHandles); } public static void setCodeObjectConstantsInfo(CodeInfo info, NonmovableArray refMapEncoding, long refMapIndex) { @@ -84,13 +88,15 @@ static void setDeoptimizationMetadata(CodeInfo info, NonmovableArray st info.setDeoptimizationObjectConstants(objectConstants); } - public static void setData(CodeInfo info, SubstrateInstalledCode installedCode, int tier, NonmovableArray codeObserverHandles) { - assert codeObserverHandles != null; - NonmovableObjectArray objectFields = info.getObjectFields(); + public static void beforeInstallInCurrentIsolate(CodeInfo info, SubstrateInstalledCode installedCode) { + assert info.getObjectFields().isNull(); + NonmovableObjectArray objectFields = NonmovableArrays.createObjectArray(CodeInfo.OBJFIELDS_COUNT); + info.setObjectFields(objectFields); // must be first to ensure references are visible to GC + Object tether = CodeInfoAccess.haveAssertions() ? new UninterruptibleUtils.AtomicInteger(0) : new Object(); + NonmovableArrays.setObject(objectFields, CodeInfo.TETHER_OBJFIELD, tether); NonmovableArrays.setObject(objectFields, CodeInfo.NAME_OBJFIELD, installedCode.getName()); NonmovableArrays.setObject(objectFields, CodeInfo.INSTALLEDCODE_OBJFIELD, new WeakReference<>(installedCode)); - info.setTier(tier); - info.setCodeObserverHandles(codeObserverHandles); + createCleaner(info, tether); } static void walkReferences(CodeInfo info, ObjectReferenceVisitor visitor) { @@ -106,13 +112,8 @@ static void walkReferences(CodeInfo info, ObjectReferenceVisitor visitor) { } public static CodeInfo allocateMethodInfo() { - CodeInfo info = ImageSingletons.lookup(UnmanagedMemorySupport.class).calloc(WordFactory.unsigned(SizeOf.get(CodeInfo.class))); + CodeInfo info = ImageSingletons.lookup(UnmanagedMemorySupport.class).calloc(SizeOf.unsigned(CodeInfo.class)); RuntimeMethodInfoMemory.singleton().add(info); - NonmovableObjectArray objectFields = NonmovableArrays.createObjectArray(CodeInfo.OBJFIELDS_COUNT); - Object obj = CodeInfoAccess.haveAssertions() ? new UninterruptibleUtils.AtomicInteger(0) : new Object(); - NonmovableArrays.setObject(objectFields, CodeInfo.TETHER_OBJFIELD, obj); - info.setObjectFields(objectFields); - createCleaner(info, obj); return info; } @@ -143,7 +144,7 @@ static void partialReleaseAfterInvalidate(CodeInfo info) { info.setCodeObserverHandles(NonmovableArrays.nullArray()); info.setCodeConstantsLive(false); - releaseInstalledCode(info); + releaseCodeMemory(info.getCodeStart(), info.getCodeSize()); /* * Set our reference to the tether object to null so that the Cleaner object can free our @@ -152,8 +153,12 @@ static void partialReleaseAfterInvalidate(CodeInfo info) { NonmovableArrays.setObject(info.getObjectFields(), CodeInfo.TETHER_OBJFIELD, null); } - private static void releaseInstalledCode(CodeInfo codeInfo) { - CommittedMemoryProvider.get().free(codeInfo.getCodeStart(), codeInfo.getCodeSize(), CommittedMemoryProvider.UNALIGNED, true); + public static CodePointer allocateCodeMemory(UnsignedWord size) { + return (CodePointer) CommittedMemoryProvider.get().allocate(size, WordFactory.unsigned(SubstrateOptions.codeAlignment()), true); + } + + public static void releaseCodeMemory(CodePointer codeStart, UnsignedWord codeSize) { + CommittedMemoryProvider.get().free(codeStart, codeSize, WordFactory.unsigned(SubstrateOptions.codeAlignment()), true); } @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) @@ -162,22 +167,45 @@ static void releaseMethodInfoOnTearDown(CodeInfo info) { releaseMethodInfoMemory(info); } + public interface NonmovableArrayAction { + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) + void apply(NonmovableArray array); + } + + private static final NonmovableArrayAction RELEASE_ACTION = new NonmovableArrayAction() { + @Override + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) + public void apply(NonmovableArray array) { + NonmovableArrays.releaseUnmanagedArray(array); + } + }; + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) private static void releaseMethodInfoMemory(CodeInfo info) { - NonmovableArrays.releaseUnmanagedArray(info.getObjectFields()); - NonmovableArrays.releaseUnmanagedArray(info.getCodeInfoIndex()); - NonmovableArrays.releaseUnmanagedArray(info.getCodeInfoEncodings()); - NonmovableArrays.releaseUnmanagedArray(info.getReferenceMapEncoding()); - NonmovableArrays.releaseUnmanagedArray(info.getFrameInfoEncodings()); - NonmovableArrays.releaseUnmanagedArray(info.getFrameInfoObjectConstants()); - NonmovableArrays.releaseUnmanagedArray(info.getFrameInfoSourceClasses()); - NonmovableArrays.releaseUnmanagedArray(info.getFrameInfoSourceMethodNames()); - NonmovableArrays.releaseUnmanagedArray(info.getFrameInfoNames()); - NonmovableArrays.releaseUnmanagedArray(info.getDeoptimizationStartOffsets()); - NonmovableArrays.releaseUnmanagedArray(info.getDeoptimizationEncodings()); - NonmovableArrays.releaseUnmanagedArray(info.getDeoptimizationObjectConstants()); - NonmovableArrays.releaseUnmanagedArray(info.getObjectsReferenceMapEncoding()); - + forEachArray(info, RELEASE_ACTION); ImageSingletons.lookup(UnmanagedMemorySupport.class).free(info); } + + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) + public static void forEachArray(CodeInfo info, NonmovableArrayAction action) { + action.apply(info.getCodeInfoIndex()); + action.apply(info.getCodeInfoEncodings()); + action.apply(info.getReferenceMapEncoding()); + action.apply(info.getFrameInfoEncodings()); + action.apply(info.getDeoptimizationStartOffsets()); + action.apply(info.getDeoptimizationEncodings()); + action.apply(info.getObjectsReferenceMapEncoding()); + action.apply(info.getCodeObserverHandles()); + forEachObjectArray(info, action); + } + + @Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true) + public static void forEachObjectArray(CodeInfo info, NonmovableArrayAction action) { + action.apply(info.getObjectFields()); + action.apply(info.getFrameInfoObjectConstants()); + action.apply(info.getFrameInfoSourceClasses()); + action.apply(info.getFrameInfoSourceMethodNames()); + action.apply(info.getFrameInfoNames()); + action.apply(info.getDeoptimizationObjectConstants()); + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoMemory.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoMemory.java index 8831a71d8f50..38698774f87d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoMemory.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMethodInfoMemory.java @@ -48,7 +48,7 @@ *

    * Implementation: linear probing hash table adapted from OpenJDK {@link java.util.IdentityHashMap}. */ -class RuntimeMethodInfoMemory extends ObjectReferenceWalker { +public class RuntimeMethodInfoMemory extends ObjectReferenceWalker { @Fold public static RuntimeMethodInfoMemory singleton() { return ImageSingletons.lookup(RuntimeMethodInfoMemory.class); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/handles/ThreadLocalHandles.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/handles/ThreadLocalHandles.java index 6394a279849a..058465f05623 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/handles/ThreadLocalHandles.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/handles/ThreadLocalHandles.java @@ -28,6 +28,8 @@ import org.graalvm.word.SignedWord; import org.graalvm.word.WordFactory; +import com.oracle.svm.core.annotate.Uninterruptible; + /** * Implementation of local object handles, which are bound to a specific thread and can be created * and destroyed implicitly or explicitly. Local handles can be managed in frames and a frame can be @@ -57,6 +59,7 @@ public ThreadLocalHandles(int initialNumberOfHandles) { objects = new Object[MIN_VALUE + initialNumberOfHandles]; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static int toIndex(T handle) { return (int) handle.rawValue(); } @@ -90,6 +93,7 @@ public T create(Object obj) { } @SuppressWarnings("unchecked") + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public U getObject(T handle) { return (U) objects[toIndex(handle)]; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessImpl.java index 1f39fa55c232..d35a7712ac5f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessImpl.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessImpl.java @@ -24,12 +24,13 @@ */ package com.oracle.svm.core.heap; +import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.word.BarrieredAccess; import org.graalvm.compiler.word.ObjectAccess; import org.graalvm.compiler.word.Word; -import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.word.Pointer; import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; @@ -95,8 +96,7 @@ public void writeObjectBarrieredAt(Object object, UnsignedWord offsetInObject, O public native Object uncompressReference(UnsignedWord ref); @Override - @AlwaysInline("Performance") - @Uninterruptible(reason = "for uninterruptible callers", mayBeInlined = true) + @Fold public boolean haveCompressedReferences() { return SubstrateOptions.SpawnIsolates.getValue(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java new file mode 100644 index 000000000000..c7952d4f7aa2 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2014, 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.meta; + +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +import com.oracle.svm.core.SubstrateUtil; +import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.snippets.KnownIntrinsics; + +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; + +/** An object constant that holds a direct reference to the object. */ +public final class DirectSubstrateObjectConstant extends SubstrateObjectConstant { + + @Platforms(Platform.HOSTED_ONLY.class) // + private static final AtomicReferenceFieldUpdater ROOT_UPDATER = // + AtomicReferenceFieldUpdater.newUpdater(DirectSubstrateObjectConstant.class, Object.class, "root"); + + /** The raw object wrapped by this constant. */ + private final Object object; + + /** + * An object specifying the origin of this constant. This value is used to distinguish between + * various constants of the same type. Only objects coming from static final fields and + * from @Fold annotations processing have a root. The static final field originated objects use + * the field itself as a root while the @Fold originated objects use the folded method as a + * root. The subtree of a root object shares the same root information as the root object, i.e., + * the root information is transiently passed to the statically reachable objects. Other + * constants, embedded in the code, might not have a root. The root is only used at image build + * time. + */ + @Platforms(Platform.HOSTED_ONLY.class) // + private volatile Object root; + + DirectSubstrateObjectConstant(Object object, boolean compressed) { + super(compressed); + this.object = object; + assert object != null; + if (SubstrateUtil.isInLibgraal()) { + throw new InternalError(); + } + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public Object getObject() { + return object; + } + + @Override + public ResolvedJavaType getType(MetaAccessProvider provider) { + return provider.lookupJavaType(object.getClass()); + } + + @Override + public SubstrateObjectConstant compress() { + assert !compressed; + return new DirectSubstrateObjectConstant(object, true); + } + + @Override + public SubstrateObjectConstant uncompress() { + assert compressed; + return new DirectSubstrateObjectConstant(object, false); + } + + @Override + public boolean setRoot(Object newRoot) { + if (root == null && newRoot != null) { + /* + * It is possible that the same constant is reached on paths from different roots. We + * can only register one, we choose the first one. + */ + return ROOT_UPDATER.compareAndSet(this, null, newRoot); + } + return false; + } + + @Override + public Object getRoot() { + return root; + } + + @Override + public int hashCode() { + return super.hashCode() * 31 + System.identityHashCode(object); + } + + @Override + public boolean equals(Object obj) { + if (this != obj && obj instanceof DirectSubstrateObjectConstant) { + DirectSubstrateObjectConstant other = (DirectSubstrateObjectConstant) obj; + return object == other.object && super.equals(other); + } + return (this == obj); + } + + @Override + public String toValueString() { + Object obj = KnownIntrinsics.convertUnknownValue(object, Object.class); + if (obj instanceof String) { + return (String) obj; + } + return obj.getClass().getName(); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java index 4760132aafcd..b4098719f8fc 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,25 +24,14 @@ */ package com.oracle.svm.core.meta; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - -import com.oracle.svm.core.SubstrateUtil; -import com.oracle.svm.core.snippets.KnownIntrinsics; - import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.VMConstant; -public final class SubstrateObjectConstant implements JavaConstant, CompressibleConstant, VMConstant { - - @Platforms(Platform.HOSTED_ONLY.class) // - private static final AtomicReferenceFieldUpdater ROOT_UPDATER = AtomicReferenceFieldUpdater.newUpdater(SubstrateObjectConstant.class, Object.class, "root"); - +public abstract class SubstrateObjectConstant implements JavaConstant, CompressibleConstant, VMConstant { public static JavaConstant forObject(Object object) { return forObject(object, false); } @@ -51,7 +40,7 @@ public static JavaConstant forObject(Object object, boolean compressed) { if (object == null) { return compressed ? CompressedNullConstant.COMPRESSED_NULL : JavaConstant.NULL_POINTER; } - return new SubstrateObjectConstant(object, compressed); + return new DirectSubstrateObjectConstant(object, compressed); } public static JavaConstant forBoxedValue(JavaKind kind, Object value) { @@ -65,12 +54,12 @@ public static Object asObject(Constant constant) { if (JavaConstant.isNull(constant)) { return null; } - return ((SubstrateObjectConstant) constant).object; + return ((DirectSubstrateObjectConstant) constant).getObject(); } public static T asObject(Class type, JavaConstant constant) { if (constant.isNonNull()) { - Object object = ((SubstrateObjectConstant) constant).object; + Object object = ((DirectSubstrateObjectConstant) constant).getObject(); if (type.isInstance(object)) { return type.cast(object); } @@ -79,8 +68,8 @@ public static T asObject(Class type, JavaConstant constant) { } public static Object asObject(ResolvedJavaType type, JavaConstant constant) { - if (constant.isNonNull() && constant instanceof SubstrateObjectConstant) { - Object object = ((SubstrateObjectConstant) constant).object; + if (constant.isNonNull() && constant instanceof DirectSubstrateObjectConstant) { + Object object = ((DirectSubstrateObjectConstant) constant).getObject(); if (type.isInstance(constant)) { return object; } @@ -92,35 +81,10 @@ public static boolean isCompressed(JavaConstant constant) { return constant instanceof CompressibleConstant && ((CompressibleConstant) constant).isCompressed(); } - /** The raw object wrapped by this constant. */ - private final Object object; - private final boolean compressed; - - /** - * An object specifying the origin of this constant. This value is used to distinguish between - * various constants of the same type. Only objects coming from static final fields and - * from @Fold annotations processing have a root. The static final field originated objects use - * the field itself as a root while the @Fold originated objects use the folded method as a - * root. The subtree of a root object shares the same root information as the root object, i.e., - * the root information is transiently passed to the statically reachable objects. Other - * constants, embedded in the code, might not have a root. The root is only used at image build - * time. - */ - @Platforms(Platform.HOSTED_ONLY.class) // - private volatile Object root; - - // As object hsp const - private SubstrateObjectConstant(Object object, boolean compressed) { - this.object = object; - this.compressed = compressed; - assert object != null; - if (SubstrateUtil.isInLibgraal()) { - throw new InternalError(); - } - } + protected final boolean compressed; - public Object getObject() { - return object; + protected SubstrateObjectConstant(boolean compressed) { + this.compressed = compressed; } @Override @@ -128,33 +92,6 @@ public boolean isCompressed() { return compressed; } - @Override - public JavaConstant compress() { - assert !compressed; - return new SubstrateObjectConstant(object, true); - } - - @Override - public JavaConstant uncompress() { - assert compressed; - return new SubstrateObjectConstant(object, false); - } - - public boolean setRoot(Object newRoot) { - if (root == null && newRoot != null) { - /* - * It is possible that the same constant is reached on paths from different roots. We - * can only register one, we choose the first one. - */ - return ROOT_UPDATER.compareAndSet(this, null, newRoot); - } - return false; - } - - public Object getRoot() { - return root; - } - @Override public boolean isNull() { return false; @@ -196,40 +133,37 @@ public double asDouble() { } @Override - public int hashCode() { - return System.identityHashCode(object); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o instanceof SubstrateObjectConstant) { - SubstrateObjectConstant other = (SubstrateObjectConstant) o; - if (object == other.object && compressed == other.compressed) { - return true; - } - } - return false; + public JavaKind getJavaKind() { + return JavaKind.Object; } @Override - public String toValueString() { - Object obj = KnownIntrinsics.convertUnknownValue(object, Object.class); - if (obj instanceof String) { - return (String) obj; + public boolean equals(Object obj) { + if (obj != this && obj instanceof SubstrateObjectConstant) { + return compressed == ((SubstrateObjectConstant) obj).compressed; } - return obj.getClass().getName(); + return obj == this; } @Override - public JavaKind getJavaKind() { - return JavaKind.Object; + public int hashCode() { + return Boolean.hashCode(compressed); } @Override public String toString() { return getJavaKind().getJavaName(); // + "[" + toValueString() + "]" + object; } + + public abstract ResolvedJavaType getType(MetaAccessProvider provider); + + @Override + public abstract SubstrateObjectConstant compress(); + + @Override + public abstract SubstrateObjectConstant uncompress(); + + public abstract boolean setRoot(Object newRoot); + + public abstract Object getRoot(); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java index 1f0bcd03723f..b3946334ddb5 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java @@ -44,93 +44,30 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.tiers.Suites; -import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.nativeimage.ImageSingletons; import com.oracle.svm.core.CPUFeatureAccess; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.graal.code.SubstrateCompilationIdentifier; import com.oracle.svm.core.graal.code.SubstrateCompilationResult; -import com.oracle.svm.core.graal.meta.InstalledCodeBuilder; import com.oracle.svm.core.graal.meta.RuntimeConfiguration; -import com.oracle.svm.core.log.Log; import com.oracle.svm.core.meta.SharedMethod; import com.oracle.svm.core.option.RuntimeOptionKey; -import com.oracle.svm.graal.meta.SubstrateInstalledCodeImpl; import com.oracle.svm.graal.meta.SubstrateMethod; import jdk.vm.ci.code.Architecture; -import jdk.vm.ci.code.InstalledCode; public class SubstrateGraalUtils { - /** Compile and install the method. Return the installed code descriptor. */ - public static InstalledCode compileAndInstall(OptionValues options, SubstrateMethod method) { - return compileAndInstall(options, GraalSupport.getRuntimeConfig(), GraalSupport.getSuites(), GraalSupport.getLIRSuites(), method); - } - - public static InstalledCode compileAndInstall(OptionValues options, RuntimeConfiguration runtimeConfig, Suites suites, LIRSuites lirSuites, SubstrateMethod method) { - return compileAndInstall(options, runtimeConfig, suites, lirSuites, method, false); - } - - public static InstalledCode compileAndInstall(OptionValues options, SubstrateMethod method, boolean testTrampolineJumps) { - return compileAndInstall(options, GraalSupport.getRuntimeConfig(), GraalSupport.getSuites(), GraalSupport.getLIRSuites(), method, testTrampolineJumps); - } - - public static InstalledCode compileAndInstall(OptionValues options, RuntimeConfiguration runtimeConfig, Suites suites, LIRSuites lirSuites, SubstrateMethod method, boolean testTrampolineJumps) { - updateGraalArchitectureWithHostCPUFeatures(runtimeConfig.lookupBackend(method)); - - DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(GraalSupport.getRuntimeConfig().getSnippetReflection())); - - // create the installed code descriptor - SubstrateInstalledCodeImpl installedCode = new SubstrateInstalledCodeImpl(method); - // do compilation and code installation and update the installed code descriptor - SubstrateGraalUtils.doCompileAndInstall(debug, runtimeConfig, suites, lirSuites, method, installedCode, testTrampolineJumps); - // return the installed code - return installedCode; - } - - /** - * This method does the actual compilation and installation of the method. Nothing is returned - * by this call. The code is installed via pinned objects and the address is updated in the - * {@link InstalledCode} argument. - * - * For zone allocation this is where the zone boundary can be placed when the code needs to be - * compiled and installed. - */ - private static void doCompileAndInstall(DebugContext debug, RuntimeConfiguration runtimeConfig, Suites suites, LIRSuites lirSuites, SubstrateMethod method, - SubstrateInstalledCodeImpl installedCode, boolean testTrampolineJumps) { - CompilationResult compilationResult = doCompile(debug, runtimeConfig, suites, lirSuites, method); - installMethod(method, compilationResult, installedCode, testTrampolineJumps); - } - - private static void installMethod(SubstrateMethod method, CompilationResult result, SubstrateInstalledCodeImpl installedCode, boolean testTrampolineJumps) { - InstalledCodeBuilder installedCodeBuilder = new InstalledCodeBuilder(method, result, installedCode, null, testTrampolineJumps); - installedCodeBuilder.install(); - - Log.log().string("Installed code for " + method.format("%H.%n(%p)") + ": " + result.getTargetCodeSize() + " bytes").newline(); - } - /** Does the compilation of the method and returns the compilation result. */ public static CompilationResult compile(DebugContext debug, final SubstrateMethod method) { - return compile(debug, GraalSupport.getRuntimeConfig(), GraalSupport.getSuites(), GraalSupport.getLIRSuites(), method); - } - - public static CompilationResult compile(DebugContext debug, RuntimeConfiguration runtimeConfig, Suites suites, LIRSuites lirSuites, final SubstrateMethod method) { - updateGraalArchitectureWithHostCPUFeatures(runtimeConfig.lookupBackend(method)); - return doCompile(debug, runtimeConfig, suites, lirSuites, method); + return doCompile(debug, GraalSupport.getRuntimeConfig(), GraalSupport.getSuites(), GraalSupport.getLIRSuites(), method); } private static final Map compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class); - /** - * Actual method compilation. - * - * For zone allocation this is where the zone boundary can be placed when the code is only - * compiled. However using the returned compilation result would result into a zone allocation - * invariant violation. - */ - private static CompilationResult doCompile(DebugContext initialDebug, RuntimeConfiguration runtimeConfig, Suites suites, LIRSuites lirSuites, final SubstrateMethod method) { + public static CompilationResult doCompile(DebugContext initialDebug, RuntimeConfiguration runtimeConfig, Suites suites, LIRSuites lirSuites, final SubstrateMethod method) { + updateGraalArchitectureWithHostCPUFeatures(runtimeConfig.lookupBackend(method)); String methodString = method.format("%H.%n(%p)"); SubstrateCompilationIdentifier compilationId = new SubstrateCompilationIdentifier(); 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 e0eb398e0309..430e16a42afb 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 @@ -73,8 +73,8 @@ import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.truffle.compiler.phases.DeoptimizeOnExceptionPhase; import org.graalvm.compiler.word.WordTypes; -import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.Feature; import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.flow.InvokeTypeFlow; @@ -306,6 +306,7 @@ public List> getRequiredFeatures() { @Override public void duringSetup(DuringSetupAccess c) { DuringSetupAccessImpl config = (DuringSetupAccessImpl) c; + AnalysisMetaAccess aMetaAccess = config.getMetaAccess(); try { /* @@ -313,14 +314,18 @@ public void duringSetup(DuringSetupAccess c) { * is the NodeClass from Truffle. So we require Truffle on the class path for any images * and tests that use Graal at run time. */ - config.getMetaAccess().lookupJavaType(SubstrateType.class); + aMetaAccess.lookupJavaType(SubstrateType.class); } catch (NoClassDefFoundError ex) { throw VMError.shouldNotReachHere("Building a native image with Graal support requires Truffle on the class path. For unit tests run with 'svmtest', add the option '--truffle'."); } ImageSingletons.add(GraalSupport.class, new GraalSupport()); - objectReplacer = new GraalObjectReplacer(config.getUniverse(), config.getMetaAccess()); + if (!ImageSingletons.contains(RuntimeGraalSetup.class)) { + ImageSingletons.add(RuntimeGraalSetup.class, new SubstrateRuntimeGraalSetup()); + } + GraalProviderObjectReplacements providerReplacements = ImageSingletons.lookup(RuntimeGraalSetup.class).getProviderObjectReplacements(aMetaAccess); + objectReplacer = new GraalObjectReplacer(config.getUniverse(), aMetaAccess, providerReplacements); config.registerObjectReplacer(objectReplacer); config.registerClassReachabilityListener(GraalSupport::registerPhaseStatistics); 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 9eb415cdb006..0a03a9d38d1e 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 @@ -32,6 +32,7 @@ import java.util.Map; import java.util.function.Function; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalRuntime; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.nodes.FieldLocationIdentity; @@ -50,12 +51,8 @@ import com.oracle.svm.core.meta.ReadableJavaField; import com.oracle.svm.core.util.HostedStringDeduplication; import com.oracle.svm.core.util.Replaced; -import com.oracle.svm.graal.GraalSupport; import com.oracle.svm.graal.SubstrateGraalRuntime; -import com.oracle.svm.graal.meta.SubstrateConstantFieldProvider; -import com.oracle.svm.graal.meta.SubstrateConstantReflectionProvider; import com.oracle.svm.graal.meta.SubstrateField; -import com.oracle.svm.graal.meta.SubstrateMetaAccess; import com.oracle.svm.graal.meta.SubstrateMethod; import com.oracle.svm.graal.meta.SubstrateSignature; import com.oracle.svm.graal.meta.SubstrateType; @@ -65,7 +62,6 @@ import com.oracle.svm.hosted.analysis.Inflation; import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedMethod; -import com.oracle.svm.hosted.meta.HostedSnippetReflectionProvider; import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.meta.HostedUniverse; @@ -95,20 +91,16 @@ public class GraalObjectReplacer implements Function { private final HashMap fieldLocationIdentities = new HashMap<>(); private final HashMap types = new HashMap<>(); private final HashMap signatures = new HashMap<>(); - private final SubstrateMetaAccess sMetaAccess; - private final SubstrateConstantReflectionProvider sConstantReflectionProvider; - private final SubstrateConstantFieldProvider sConstantFieldProvider; + private final GraalProviderObjectReplacements providerReplacements; private SubstrateGraalRuntime sGraalRuntime; private final HostedStringDeduplication stringTable; - public GraalObjectReplacer(AnalysisUniverse aUniverse, AnalysisMetaAccess aMetaAccess) { + public GraalObjectReplacer(AnalysisUniverse aUniverse, AnalysisMetaAccess aMetaAccess, GraalProviderObjectReplacements providerReplacements) { this.aUniverse = aUniverse; this.aMetaAccess = aMetaAccess; - this.sMetaAccess = new SubstrateMetaAccess(); + this.providerReplacements = providerReplacements; this.stringTable = HostedStringDeduplication.singleton(); - this.sConstantReflectionProvider = new SubstrateConstantReflectionProvider(sMetaAccess); - this.sConstantFieldProvider = new SubstrateConstantFieldProvider(aMetaAccess); } public void setGraalRuntime(SubstrateGraalRuntime sGraalRuntime) { @@ -130,20 +122,19 @@ public Object apply(Object source) { } if (source instanceof MetaAccessProvider) { - dest = sMetaAccess; + dest = providerReplacements.getMetaAccessProvider(); } else if (source instanceof HotSpotJVMCIRuntime) { - // Throw UnsupportedFeatureException since that provides better diagnostics throw new UnsupportedFeatureException("HotSpotJVMCIRuntime should not appear in the image: " + source); } else if (source instanceof GraalRuntime) { dest = sGraalRuntime; } else if (source instanceof AnalysisConstantReflectionProvider) { - dest = sConstantReflectionProvider; + dest = providerReplacements.getConstantReflectionProvider(); } else if (source instanceof AnalysisConstantFieldProvider) { - dest = sConstantFieldProvider; + dest = providerReplacements.getConstantFieldProvider(); } else if (source instanceof ForeignCallsProvider) { - dest = GraalSupport.getRuntimeConfig().getProviders().getForeignCalls(); - } else if (source instanceof HostedSnippetReflectionProvider) { - dest = GraalSupport.getRuntimeConfig().getSnippetReflection(); + dest = providerReplacements.getForeignCallsProvider(); + } else if (source instanceof SnippetReflectionProvider) { + dest = providerReplacements.getSnippetReflectionProvider(); } else if (shouldBeReplaced(source)) { /* diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalProviderObjectReplacements.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalProviderObjectReplacements.java new file mode 100644 index 000000000000..e0f628bf1890 --- /dev/null +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalProviderObjectReplacements.java @@ -0,0 +1,79 @@ +/* + * 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.graal.hosted; + +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; + +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.svm.graal.GraalSupport; +import com.oracle.svm.graal.meta.SubstrateConstantFieldProvider; +import com.oracle.svm.graal.meta.SubstrateConstantReflectionProvider; +import com.oracle.svm.graal.meta.SubstrateMetaAccess; + +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; + +/** + * The set of provider objects that are installed via {@link GraalObjectReplacer}. + */ +public class GraalProviderObjectReplacements { + private final SubstrateMetaAccess metaAccess; + private final ConstantFieldProvider constantFieldProvider; + private final ConstantReflectionProvider constantReflection; + + GraalProviderObjectReplacements(AnalysisMetaAccess aMetaAccess) { + this.metaAccess = new SubstrateMetaAccess(); + this.constantFieldProvider = new SubstrateConstantFieldProvider(aMetaAccess); + this.constantReflection = new SubstrateConstantReflectionProvider(metaAccess); + } + + protected GraalProviderObjectReplacements(SubstrateMetaAccess metaAccess, ConstantFieldProvider constantFieldProvider, ConstantReflectionProvider constantReflection) { + this.metaAccess = metaAccess; + this.constantFieldProvider = constantFieldProvider; + this.constantReflection = constantReflection; + } + + public MetaAccessProvider getMetaAccessProvider() { + return metaAccess; + } + + public ConstantFieldProvider getConstantFieldProvider() { + return constantFieldProvider; + } + + public ConstantReflectionProvider getConstantReflectionProvider() { + return constantReflection; + } + + public SnippetReflectionProvider getSnippetReflectionProvider() { + return GraalSupport.getRuntimeConfig().getSnippetReflection(); + } + + public ForeignCallsProvider getForeignCallsProvider() { + return GraalSupport.getRuntimeConfig().getProviders().getForeignCalls(); + } +} diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeGraalSetup.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeGraalSetup.java new file mode 100644 index 000000000000..fca0c558733d --- /dev/null +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeGraalSetup.java @@ -0,0 +1,35 @@ +/* + * 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.graal.hosted; + +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; + +/** + * Provides functionality during the image build for setting up Graal for compilation at runtime. + */ +public interface RuntimeGraalSetup { + + GraalProviderObjectReplacements getProviderObjectReplacements(AnalysisMetaAccess aMetaAccess); +} diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/SubstrateRuntimeGraalSetup.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/SubstrateRuntimeGraalSetup.java new file mode 100644 index 000000000000..82610c413a50 --- /dev/null +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/SubstrateRuntimeGraalSetup.java @@ -0,0 +1,35 @@ +/* + * 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.graal.hosted; + +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; + +public class SubstrateRuntimeGraalSetup implements RuntimeGraalSetup { + + @Override + public GraalProviderObjectReplacements getProviderObjectReplacements(AnalysisMetaAccess aMetaAccess) { + return new GraalProviderObjectReplacements(aMetaAccess); + } +} diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/InstalledCodeBuilder.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/RuntimeCodeInstaller.java similarity index 68% rename from substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/InstalledCodeBuilder.java rename to substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/RuntimeCodeInstaller.java index 6086d42c565d..78915ab27493 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/InstalledCodeBuilder.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/RuntimeCodeInstaller.java @@ -22,9 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.graal.meta; - -import static com.oracle.svm.core.util.VMError.shouldNotReachHere; +package com.oracle.svm.graal.meta; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -42,12 +40,12 @@ import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.truffle.common.TruffleCompiler; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.c.function.CodePointer; import org.graalvm.nativeimage.c.type.CTypeConversion; import org.graalvm.word.Pointer; -import org.graalvm.word.UnsignedWord; +import org.graalvm.word.PointerBase; import org.graalvm.word.WordFactory; -import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.c.NonmovableArray; import com.oracle.svm.core.code.CodeInfo; @@ -59,19 +57,19 @@ import com.oracle.svm.core.code.InstalledCodeObserver; import com.oracle.svm.core.code.InstalledCodeObserver.InstalledCodeObserverHandle; import com.oracle.svm.core.code.InstalledCodeObserverSupport; +import com.oracle.svm.core.code.InstantReferenceAdjuster; +import com.oracle.svm.core.code.ReferenceAdjuster; import com.oracle.svm.core.code.RuntimeMethodInfoAccess; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.deopt.SubstrateInstalledCode; import com.oracle.svm.core.graal.code.NativeImagePatcher; import com.oracle.svm.core.graal.code.SubstrateCompilationResult; +import com.oracle.svm.core.graal.meta.SharedRuntimeMethod; import com.oracle.svm.core.heap.CodeReferenceMapEncoder; import com.oracle.svm.core.heap.ReferenceAccess; import com.oracle.svm.core.heap.SubstrateReferenceMap; -import com.oracle.svm.core.log.Log; import com.oracle.svm.core.meta.SharedMethod; import com.oracle.svm.core.meta.SubstrateObjectConstant; -import com.oracle.svm.core.os.CommittedMemoryProvider; -import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.thread.JavaVMOperation; import com.oracle.svm.core.util.VMError; @@ -84,31 +82,30 @@ import jdk.vm.ci.meta.JavaKind; /** - * Represents the installed code of a runtime compiled method. - *

    - * It allocates executable memory for the machine code + the constants. In addition it allocates - * data memory (not on the regular heap!) for the needed system objects: code chunk infos, encoded - * pointer map for the constants. - *

    - * The SubstrateInstalledCode also acts as an allocator to allocate all these system objects. - * + * Handles the installation of runtime-compiled code, allocating memory for code, data, and metadata + * and patching call and jump targets, primitive constants, and object constants. */ -public class InstalledCodeBuilder { - private final SharedRuntimeMethod method; - private final SubstrateInstalledCode installedCode; - private final int tier; - private final Map allInstalledCode; - protected Pointer code; - private final int codeSize; - private final int constantsOffset; - private final InstalledCodeObserver[] codeObservers; +public class RuntimeCodeInstaller { - private SubstrateCompilationResult compilation; - private byte[] compiledBytes; + /** Installs the code in the current isolate, in a single step. */ + public static void install(SharedRuntimeMethod method, CompilationResult compilation, SubstrateInstalledCode installedCode) { + install(method, compilation, installedCode, false); + } - private CodeInfo runtimeMethodInfo; + public static void install(SharedRuntimeMethod method, CompilationResult compilation, SubstrateInstalledCode installedCode, boolean testTrampolineJumps) { + new RuntimeCodeInstaller(method, compilation, testTrampolineJumps).doInstall(installedCode); + } + private final SharedRuntimeMethod method; + private final int tier; private final boolean testTrampolineJumps; + private SubstrateCompilationResult compilation; + + private Pointer code; + private int codeSize; + private int constantsOffset; + private InstalledCodeObserver[] codeObservers; + private byte[] compiledBytes; /** * The size for trampoline jumps: jmp [rip+offset] @@ -117,24 +114,18 @@ public class InstalledCodeBuilder { * The jump instructions reference the 8-byte destination addresses, which are allocated after * the jumps. */ - static final int TRAMPOLINE_JUMP_SIZE = 6; - - public InstalledCodeBuilder(SharedRuntimeMethod method, CompilationResult compilation, SubstrateInstalledCode installedCode, Map allInstalledCode) { - this(method, compilation, installedCode, allInstalledCode, false); - } + private static final int TRAMPOLINE_JUMP_SIZE = 6; - @SuppressWarnings("try") - public InstalledCodeBuilder(SharedRuntimeMethod method, CompilationResult compilation, SubstrateInstalledCode installedCode, Map allInstalledCode, - boolean testTrampolineJumps) { + protected RuntimeCodeInstaller(SharedRuntimeMethod method, CompilationResult compilation, boolean testTrampolineJumps) { this.method = method; this.compilation = (SubstrateCompilationResult) compilation; this.tier = compilation.getName().endsWith(TruffleCompiler.FIRST_TIER_COMPILATION_SUFFIX) ? TruffleCompiler.FIRST_TIER_INDEX : TruffleCompiler.LAST_TIER_INDEX; - this.installedCode = installedCode; - this.allInstalledCode = allInstalledCode; this.testTrampolineJumps = testTrampolineJumps; + } - DebugContext debug = DebugContext.forCurrentThread(); - try (Indent indent = debug.logAndIndent("create installed code of %s.%s", method.getDeclaringClass().getName(), method.getName())) { + @SuppressWarnings("try") + private void prepareCodeMemory() { + try (Indent indent = DebugContext.forCurrentThread().logAndIndent("create installed code of %s.%s", method.getDeclaringClass().getName(), method.getName())) { TargetDescription target = ConfigurationValues.getTarget(); if (target.arch.getPlatformKind(JavaKind.Object).getSizeInBytes() != 8) { @@ -147,7 +138,7 @@ public InstalledCodeBuilder(SharedRuntimeMethod method, CompilationResult compil int tmpMemorySize = tmpConstantsOffset + constantsSize; // Allocate executable memory. It contains the compiled code and the constants - code = allocateOSMemory(WordFactory.unsigned(tmpMemorySize)); + code = allocateCodeMemory(tmpMemorySize); /* * Check if we there are some direct calls where the PC displacement is out of the 32 @@ -179,7 +170,7 @@ public InstalledCodeBuilder(SharedRuntimeMethod method, CompilationResult compil * re-allocate the memory (it got larger). So we don't know which calls will need * trampoline jumps with the new code address. */ - freeOSMemory(code, WordFactory.unsigned(tmpMemorySize)); + releaseCodeMemory(code, tmpMemorySize); // Add space for the actual trampoline jump instructions: jmp [rip+offset] tmpConstantsOffset = NumUtil.roundUp(codeSize + directTargets.size() * TRAMPOLINE_JUMP_SIZE, 8); @@ -191,82 +182,52 @@ public InstalledCodeBuilder(SharedRuntimeMethod method, CompilationResult compil } tmpMemorySize = tmpConstantsOffset + constantsSize; - code = allocateOSMemory(WordFactory.unsigned(tmpMemorySize)); + code = allocateCodeMemory(tmpMemorySize); } constantsOffset = tmpConstantsOffset; - codeObservers = ImageSingletons.lookup(InstalledCodeObserverSupport.class).createObservers(debug, method, compilation, code); + codeObservers = ImageSingletons.lookup(InstalledCodeObserverSupport.class).createObservers(DebugContext.forCurrentThread(), method, compilation, code); } - - } - - public SubstrateInstalledCode getInstalledCode() { - return installedCode; } - static class ObjectConstantsHolder { + private static class ObjectConstantsHolder { final SubstrateReferenceMap referenceMap; final int[] offsets; - final NativeImagePatcher[] patchers; - final Object[] values; + final int[] lengths; + final SubstrateObjectConstant[] constants; int count; ObjectConstantsHolder(CompilationResult compilation) { /* Conservative estimate on the maximum number of object constants we might have. */ int maxDataRefs = compilation.getDataSection().getSectionSize() / ConfigurationValues.getObjectLayout().getReferenceSize(); int maxCodeRefs = compilation.getDataPatches().size(); - offsets = new int[maxDataRefs + maxCodeRefs]; - patchers = new NativeImagePatcher[offsets.length]; - values = new Object[offsets.length]; + int maxTotalRefs = maxDataRefs + maxCodeRefs; + offsets = new int[maxTotalRefs]; + lengths = new int[maxTotalRefs]; + constants = new SubstrateObjectConstant[maxTotalRefs]; referenceMap = new SubstrateReferenceMap(); } - void add(NativeImagePatcher patchingAnnotation, SubstrateObjectConstant constant) { + void add(int offset, int length, SubstrateObjectConstant constant) { assert constant.isCompressed() == ReferenceAccess.singleton().haveCompressedReferences() : "Object reference constants in code must be compressed"; - patchers[count] = patchingAnnotation; - values[count] = KnownIntrinsics.convertUnknownValue(constant.getObject(), Object.class); - referenceMap.markReferenceAtOffset(patchingAnnotation.getPosition(), true); + offsets[count] = offset; + lengths[count] = length; + constants[count] = constant; + referenceMap.markReferenceAtOffset(offset, true); count++; } } - public void install() { - this.installOperation(); - } - - /** - * The layout of the data-section is determined by Substratevm and not by the underlying - * architecture. We can use the same patcher for all architectures. - */ - private static class DataSectionPatcher implements NativeImagePatcher { - private final int position; - - DataSectionPatcher(int position) { - this.position = position; - } - - @Override - public void patch(int codePos, int relative, byte[] code) { - shouldNotReachHere("Datasection can only be patched with an VM constant"); - } + private void doInstall(SubstrateInstalledCode installedCode) { + ReferenceAdjuster adjuster = new InstantReferenceAdjuster(); + CodeInfo info = doPrepareInstall(adjuster); - @Uninterruptible(reason = "The patcher is intended to work with raw pointers") - @Override - public void patchData(Pointer pointer, Object object) { - boolean compressed = ReferenceAccess.singleton().haveCompressedReferences(); - Pointer address = pointer.add(position); - ReferenceAccess.singleton().writeObjectAt(address, object, compressed); - } - - @Uninterruptible(reason = ".", mayBeInlined = true) - @Override - public int getPosition() { - return position; - } + doInstallPrepared(method, info, installedCode); } - @SuppressWarnings("try") - private void installOperation() { + protected CodeInfo doPrepareInstall(ReferenceAdjuster adjuster) { + prepareCodeMemory(); + /* * Object reference constants are stored in this holder first, then written and made visible * in a single step that is atomic regarding to GC. @@ -293,32 +254,39 @@ private void installOperation() { /* Write primitive constants to the buffer, record object constants with offsets */ ByteBuffer constantsBuffer = CTypeConversion.asByteBuffer(code.add(constantsOffset), compilation.getDataSection().getSectionSize()); compilation.getDataSection().buildDataSection(constantsBuffer, (position, constant) -> { - objectConstants.add(new DataSectionPatcher(constantsOffset + position), (SubstrateObjectConstant) constant); + objectConstants.add(constantsOffset + position, + ConfigurationValues.getObjectLayout().getReferenceSize(), + (SubstrateObjectConstant) constant); }); - runtimeMethodInfo = RuntimeMethodInfoAccess.allocateMethodInfo(); - RuntimeMethodInfoAccess.setCodeLocation(runtimeMethodInfo, code, codeSize); + CodeInfo runtimeMethodInfo = RuntimeMethodInfoAccess.allocateMethodInfo(); + NonmovableArray observerHandles = InstalledCodeObserverSupport.installObservers(codeObservers); + RuntimeMethodInfoAccess.initialize(runtimeMethodInfo, code, codeSize, tier, observerHandles); CodeReferenceMapEncoder encoder = new CodeReferenceMapEncoder(); encoder.add(objectConstants.referenceMap); RuntimeMethodInfoAccess.setCodeObjectConstantsInfo(runtimeMethodInfo, encoder.encodeAll(), encoder.lookupEncoding(objectConstants.referenceMap)); - writeObjectConstantsToCode(objectConstants); + patchDirectObjectConstants(objectConstants, runtimeMethodInfo, adjuster); - createCodeChunkInfos(); + createCodeChunkInfos(runtimeMethodInfo, adjuster); - NonmovableArray observerHandles = InstalledCodeObserverSupport.installObservers(codeObservers); + compilation = null; + return runtimeMethodInfo; + } - RuntimeMethodInfoAccess.setData(runtimeMethodInfo, installedCode, tier, observerHandles); + protected static void doInstallPrepared(SharedMethod method, CodeInfo codeInfo, SubstrateInstalledCode installedCode) { + RuntimeMethodInfoAccess.beforeInstallInCurrentIsolate(codeInfo, installedCode); Throwable[] errorBox = {null}; JavaVMOperation.enqueueBlockingSafepoint("Install code", () -> { try { - CodeInfoTable.getRuntimeCodeCache().addMethod(runtimeMethodInfo); + CodeInfoTable.getRuntimeCodeCache().addMethod(codeInfo); /* * This call makes the new code visible, i.e., other threads can start executing it * immediately. So all metadata must be registered at this point. */ - installedCode.setAddress(code.rawValue(), method); + CodePointer codeStart = CodeInfoAccess.getCodeStart(codeInfo); + installedCode.setAddress(codeStart.rawValue(), method); } catch (Throwable e) { errorBox[0] = e; } @@ -326,28 +294,29 @@ private void installOperation() { if (errorBox[0] != null) { throw rethrow(errorBox[0]); } - - compilation = null; } @SuppressWarnings({"unchecked"}) - static RuntimeException rethrow(Throwable ex) throws E { + private static RuntimeException rethrow(Throwable ex) throws E { throw (E) ex; } @Uninterruptible(reason = "Must be atomic with regard to garbage collection.") - private void writeObjectConstantsToCode(ObjectConstantsHolder objectConstants) { + private void patchDirectObjectConstants(ObjectConstantsHolder objectConstants, CodeInfo runtimeMethodInfo, ReferenceAdjuster adjuster) { for (int i = 0; i < objectConstants.count; i++) { - objectConstants.patchers[i].patchData(code, objectConstants.values[i]); + SubstrateObjectConstant constant = objectConstants.constants[i]; + adjuster.setConstantTargetAt(code.add(objectConstants.offsets[i]), objectConstants.lengths[i], constant); } RuntimeMethodInfoAccess.setCodeConstantsLive(runtimeMethodInfo); } - private void createCodeChunkInfos() { + private void createCodeChunkInfos(CodeInfo runtimeMethodInfo, ReferenceAdjuster adjuster) { CodeInfoEncoder codeInfoEncoder = new CodeInfoEncoder(new FrameInfoEncoder.NamesFromImage()); codeInfoEncoder.addMethod(method, compilation, 0); - codeInfoEncoder.encodeAllAndInstall(runtimeMethodInfo); - assert CodeInfoEncoder.verifyMethod(compilation, 0, runtimeMethodInfo); + codeInfoEncoder.encodeAllAndInstall(runtimeMethodInfo, adjuster); + + assert !adjuster.isFinished() || CodeInfoEncoder.verifyMethod(compilation, 0, runtimeMethodInfo); + assert !adjuster.isFinished() || codeInfoEncoder.verifyFrameInfo(runtimeMethodInfo); DeoptimizationSourcePositionEncoder sourcePositionEncoder = new DeoptimizationSourcePositionEncoder(); sourcePositionEncoder.encodeAndInstall(compilation.getDeoptimizationSourcePositions(), runtimeMethodInfo); @@ -359,11 +328,11 @@ private void patchData(Map patcher, @SuppressWarnin if (dataPatch.reference instanceof DataSectionReference) { DataSectionReference ref = (DataSectionReference) dataPatch.reference; int pcDisplacement = constantsOffset + ref.getOffset() - dataPatch.pcOffset; - patch.patch(dataPatch.pcOffset, pcDisplacement, compiledBytes); + patch.patchCode(pcDisplacement, compiledBytes); } else if (dataPatch.reference instanceof ConstantReference) { ConstantReference ref = (ConstantReference) dataPatch.reference; SubstrateObjectConstant refConst = (SubstrateObjectConstant) ref.getConstant(); - objectConstants.add(patch, refConst); + objectConstants.add(patch.getOffset(), patch.getLength(), refConst); } } } @@ -397,7 +366,7 @@ private int patchCalls(Map patches) { assert pcDisplacement == (int) pcDisplacement; // Patch a PC-relative call. - patches.get(call.pcOffset).patch(call.pcOffset, (int) pcDisplacement, compiledBytes); + patches.get(call.pcOffset).patchCode((int) pcDisplacement, compiledBytes); } } if (directTargets.size() > 0) { @@ -424,48 +393,24 @@ private int patchCalls(Map patches) { return currentPos; } - private long getTargetCodeAddress(Call callInfo) { - - // NOTE that for the moment, we don't make static calls to external - // (e.g. native) functions. - // This will change, and we will have to case-split here... but not yet. + private static long getTargetCodeAddress(Call callInfo) { SharedMethod targetMethod = (SharedMethod) callInfo.target; long callTargetStart = CodeInfoAccess.absoluteIP(CodeInfoTable.getImageCodeInfo(), targetMethod.getCodeOffsetInImage()).rawValue(); - - if (allInstalledCode != null) { - InstalledCodeBuilder targetInstalledCodeBuilder = allInstalledCode.get(targetMethod); - if (targetInstalledCodeBuilder != null) { - SubstrateInstalledCode targetInstalledCode = targetInstalledCodeBuilder.getInstalledCode(); - if (targetInstalledCode != null && targetInstalledCode.isValid()) { - callTargetStart = targetInstalledCode.getAddress(); - } - } - } if (callTargetStart == 0) { throw VMError.shouldNotReachHere("target method not compiled: " + targetMethod.format("%H.%n(%p)")); } return callTargetStart; } - private static Pointer allocateOSMemory(final UnsignedWord size) { - final Log trace = Log.noopLog(); - trace.string("[SubstrateInstalledCode.allocateAlignedMemory:"); - trace.string(" size: ").unsigned(size); - final Pointer result = CommittedMemoryProvider.get().allocate(size, WordFactory.unsigned(SubstrateOptions.codeAlignment()), true); - trace.string(" returns: ").hex(result); - trace.string("]").newline(); + protected Pointer allocateCodeMemory(long size) { + PointerBase result = RuntimeMethodInfoAccess.allocateCodeMemory(WordFactory.unsigned(size)); if (result.isNull()) { throw new OutOfMemoryError(); } - return result; + return (Pointer) result; } - private static void freeOSMemory(final Pointer start, final UnsignedWord size) { - final Log trace = Log.noopLog(); - trace.string("[SubstrateInstalledCode.freeOSMemory:"); - trace.string(" start: ").hex(start); - trace.string(" size: ").unsigned(size); - CommittedMemoryProvider.get().free(start, size, WordFactory.unsigned(SubstrateOptions.codeAlignment()), true); - trace.string("]").newline(); + protected void releaseCodeMemory(Pointer start, long size) { + RuntimeMethodInfoAccess.releaseCodeMemory((CodePointer) start, WordFactory.unsigned(size)); } } diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SubstrateCodeCacheProvider.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java similarity index 63% rename from substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SubstrateCodeCacheProvider.java rename to substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java index 21811a577b67..df250f21e84d 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SubstrateCodeCacheProvider.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java @@ -22,20 +22,17 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.graal.meta; - -import static com.oracle.svm.core.util.VMError.unimplemented; +package com.oracle.svm.graal.meta; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.SuppressFBWarnings; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; import com.oracle.svm.core.deopt.SubstrateInstalledCode; import com.oracle.svm.core.graal.code.SubstrateCompiledCode; +import com.oracle.svm.core.graal.meta.SharedCodeCacheProvider; +import com.oracle.svm.core.graal.meta.SharedRuntimeMethod; import com.oracle.svm.core.util.VMError; -import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.RegisterConfig; @@ -43,15 +40,10 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.SpeculationLog; -public class SubstrateCodeCacheProvider implements CodeCacheProvider { - - private final TargetDescription target; - private final RegisterConfig registerConfig; +public class SubstrateCodeCacheProvider extends SharedCodeCacheProvider { - @Platforms(Platform.HOSTED_ONLY.class) - public SubstrateCodeCacheProvider(TargetDescription target, RegisterConfig registerConfig) { - this.target = target; - this.registerConfig = registerConfig; + SubstrateCodeCacheProvider(TargetDescription target, RegisterConfig registerConfig) { + super(target, registerConfig); } @Override @@ -66,43 +58,7 @@ public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compile substrateInstalledCode = (SubstrateInstalledCode) predefinedInstalledCode; } CompilationResult compResult = ((SubstrateCompiledCode) compiledCode).getCompilationResult(); - InstalledCodeBuilder builder = new InstalledCodeBuilder((SharedRuntimeMethod) method, compResult, substrateInstalledCode, null); - builder.install(); + RuntimeCodeInstaller.install((SharedRuntimeMethod) method, compResult, substrateInstalledCode); return predefinedInstalledCode; } - - @Override - public void invalidateInstalledCode(InstalledCode installedCode) { - throw unimplemented(); - } - - @Override - public long getMaxCallTargetOffset(long address) { - throw unimplemented(); - } - - @Override - public boolean shouldDebugNonSafepoints() { - return false; - } - - @Override - public SpeculationLog createSpeculationLog() { - throw unimplemented(); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } - - @Override - public int getMinimumOutgoingSize() { - return 0; - } - - @Override - public TargetDescription getTarget() { - return target; - } } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateConstantReflectionProvider.java index 901fd72f463f..acdfb5b0ea1f 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateConstantReflectionProvider.java @@ -75,7 +75,7 @@ public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receive return readFieldValue((SubstrateField) field, receiver); } - private static JavaConstant readFieldValue(SubstrateField field, JavaConstant receiver) { + public static JavaConstant readFieldValue(SubstrateField field, JavaConstant receiver) { if (field.constantValue != null) { return field.constantValue; } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateField.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateField.java index 2cb37a2755d7..841366564d6d 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateField.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateField.java @@ -34,8 +34,8 @@ import com.oracle.svm.core.annotate.UnknownObjectField; import com.oracle.svm.core.annotate.UnknownPrimitiveField; import com.oracle.svm.core.hub.AnnotationsEncoding; +import com.oracle.svm.core.meta.DirectSubstrateObjectConstant; import com.oracle.svm.core.meta.SharedField; -import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.core.util.HostedStringDeduplication; import com.oracle.svm.core.util.Replaced; import com.oracle.truffle.api.nodes.Node.Child; @@ -63,7 +63,7 @@ public class SubstrateField implements SharedField, Replaced { @UnknownPrimitiveField int location; @UnknownPrimitiveField private boolean isAccessed; @UnknownPrimitiveField private boolean isWritten; - @UnknownObjectField(types = {SubstrateObjectConstant.class, PrimitiveConstant.class}, fullyQualifiedTypes = "jdk.vm.ci.meta.NullConstant")// + @UnknownObjectField(types = {DirectSubstrateObjectConstant.class, PrimitiveConstant.class}, fullyQualifiedTypes = "jdk.vm.ci.meta.NullConstant")// JavaConstant constantValue; /* Truffle access this information frequently, so it is worth caching it in a field. */ diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMemoryAccessProviderImpl.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMemoryAccessProviderImpl.java index a9c9f1543f27..2eb915c3074f 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMemoryAccessProviderImpl.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMemoryAccessProviderImpl.java @@ -163,7 +163,7 @@ private static JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseCo long rawValue; if (baseConstant instanceof SubstrateObjectConstant) { - Object baseObject = ((SubstrateObjectConstant) baseConstant).getObject(); + Object baseObject = SubstrateObjectConstant.asObject(baseConstant); assert baseObject != null : "SubstrateObjectConstant does not wrap null value"; switch (bits) { @@ -219,7 +219,7 @@ private static JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseCo return toConstant(kind, rawValue); } - private static JavaConstant toConstant(JavaKind kind, long rawValue) { + public static JavaConstant toConstant(JavaKind kind, long rawValue) { switch (kind) { case Boolean: return JavaConstant.forBoolean(rawValue != 0); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMetaAccess.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMetaAccess.java index e2e5ed8c6da3..67c52c016967 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMetaAccess.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMetaAccess.java @@ -98,7 +98,7 @@ public ResolvedJavaType lookupJavaType(JavaConstant constant) { if (constant.getJavaKind() != JavaKind.Object || constant.isNull()) { return null; } - return lookupJavaType(SubstrateObjectConstant.asObject(constant).getClass()); + return ((SubstrateObjectConstant) constant).getType(this); } @Override diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java index c7e3cf803817..6a7534787fdf 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java @@ -37,6 +37,7 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.graal.code.SubstrateBackend; +import com.oracle.svm.core.graal.meta.SharedCodeCacheProvider; import com.oracle.svm.core.graal.meta.SubstrateReplacements; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.ameta.AnalysisConstantFieldProvider; @@ -46,6 +47,7 @@ import com.oracle.svm.hosted.code.SharedRuntimeConfigurationBuilder; import com.oracle.svm.hosted.code.SubstrateGraphMakerFactory; +import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; @@ -79,4 +81,9 @@ protected Replacements createReplacements(Providers p, SnippetReflectionProvider BytecodeProvider bytecodeProvider = new ResolvedJavaMethodBytecodeProvider(); return new SubstrateReplacements(p, snippetReflection, bytecodeProvider, ConfigurationValues.getTarget(), new SubstrateGraphMakerFactory(wordTypes)); } + + @Override + protected SharedCodeCacheProvider createCodeCacheProvider(RegisterConfig registerConfig) { + return new SubstrateCodeCacheProvider(ConfigurationValues.getTarget(), registerConfig); + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java new file mode 100644 index 000000000000..cb71a25dc37a --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java @@ -0,0 +1,46 @@ +/* + * 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.hosted.code; + +import com.oracle.svm.core.graal.meta.SharedCodeCacheProvider; +import com.oracle.svm.core.util.VMError; + +import jdk.vm.ci.code.CompiledCode; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.SpeculationLog; + +public class HostedCodeCacheProvider extends SharedCodeCacheProvider { + HostedCodeCacheProvider(TargetDescription target, RegisterConfig registerConfig) { + super(target, registerConfig); + } + + @Override + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault) { + throw VMError.unimplemented(); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java index 195f164c113d..013138180b08 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java @@ -49,6 +49,7 @@ import com.oracle.svm.hosted.meta.HostedUniverse; import jdk.vm.ci.code.CodeCacheProvider; +import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.meta.ConstantReflectionProvider; public class HostedRuntimeConfigurationBuilder extends SharedRuntimeConfigurationBuilder { @@ -86,6 +87,11 @@ protected Replacements createReplacements(Providers p, SnippetReflectionProvider return new HostedReplacements(universe, p, reflectionProvider, ConfigurationValues.getTarget(), analysisProviders, bytecodeProvider); } + @Override + protected CodeCacheProvider createCodeCacheProvider(RegisterConfig registerConfig) { + return new HostedCodeCacheProvider(ConfigurationValues.getTarget(), registerConfig); + } + @Override protected ConstantFieldProvider createConstantFieldProvider(Providers p) { return new HostedConstantFieldProvider(p.getMetaAccess()); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java index d5c8cd216543..f4831129d1c5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java @@ -48,7 +48,6 @@ import com.oracle.svm.core.graal.code.SubstrateBackend; import com.oracle.svm.core.graal.code.SubstrateRegisterConfigFactory; import com.oracle.svm.core.graal.meta.RuntimeConfiguration; -import com.oracle.svm.core.graal.meta.SubstrateCodeCacheProvider; import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider; import com.oracle.svm.core.graal.meta.SubstrateLoweringProvider; import com.oracle.svm.core.graal.meta.SubstrateRegisterConfig.ConfigKind; @@ -160,9 +159,7 @@ protected LoweringProvider createLoweringProvider(Providers p) { protected abstract Replacements createReplacements(Providers p, SnippetReflectionProvider snippetReflection); - protected SubstrateCodeCacheProvider createCodeCacheProvider(RegisterConfig registerConfig) { - return new SubstrateCodeCacheProvider(ConfigurationValues.getTarget(), registerConfig); - } + protected abstract CodeCacheProvider createCodeCacheProvider(RegisterConfig registerConfig); public void updateLazyState(HostedMetaAccess hMetaAccess) { HybridLayout hubLayout = new HybridLayout<>(DynamicHub.class, ConfigurationValues.getObjectLayout(), hMetaAccess); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java index 14e43bee57d7..884cd5663e2d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java @@ -55,6 +55,7 @@ import com.oracle.svm.core.code.CodeInfoTable; import com.oracle.svm.core.code.FrameInfoDecoder; import com.oracle.svm.core.code.FrameInfoEncoder; +import com.oracle.svm.core.code.InstantReferenceAdjuster; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.deopt.DeoptEntryInfopoint; import com.oracle.svm.core.graal.code.SubstrateDataBuilder; @@ -207,7 +208,7 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code } CodeInfo codeInfo = CodeInfoTable.getImageCodeCache().getHostedImageCodeInfo(); - codeInfoEncoder.encodeAllAndInstall(codeInfo); + codeInfoEncoder.encodeAllAndInstall(codeInfo, new InstantReferenceAdjuster()); codeInfo.setCodeStart(firstMethod); codeInfo.setCodeSize(codeSize); @@ -225,7 +226,7 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code verifyDeoptEntries(codeInfo); } - assert verifyMethods(codeInfo); + assert verifyMethods(codeInfoEncoder, codeInfo); } private void verifyDeoptEntries(CodeInfo codeInfo) { @@ -269,10 +270,11 @@ private static boolean error(HostedMethod method, long encodedBci, String msg) { return true; } - private boolean verifyMethods(CodeInfo codeInfo) { + private boolean verifyMethods(CodeInfoEncoder codeInfoEncoder, CodeInfo codeInfo) { for (Entry entry : compilations.entrySet()) { CodeInfoEncoder.verifyMethod(entry.getValue(), entry.getKey().getCodeAddressOffset(), codeInfo); } + codeInfoEncoder.verifyFrameInfo(codeInfo); return true; } 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 84b52d3b2a92..ab0a6eed7937 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 @@ -33,12 +33,10 @@ import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; -import java.util.function.Supplier; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; -import org.graalvm.compiler.api.runtime.GraalRuntime; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.OptionDescriptor; import org.graalvm.compiler.options.OptionKey; @@ -63,8 +61,10 @@ import com.oracle.svm.core.deopt.SubstrateSpeculationLog; import com.oracle.svm.core.jdk.RuntimeSupport; import com.oracle.svm.core.log.Log; +import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.core.option.RuntimeOptionParser; import com.oracle.svm.core.option.RuntimeOptionValues; +import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.stack.SubstrateStackIntrospection; import com.oracle.svm.graal.GraalSupport; import com.oracle.svm.graal.hosted.GraalFeature; @@ -87,7 +87,6 @@ public final class SubstrateTruffleRuntime extends GraalTruffleRuntime { private BackgroundCompileQueue compileQueue; private CallMethods hostedCallMethods; private boolean initialized; - private final Supplier graalRuntimeProvider; @Override protected BackgroundCompileQueue getCompileQueue() { @@ -98,7 +97,6 @@ protected BackgroundCompileQueue getCompileQueue() { @Platforms(Platform.HOSTED_ONLY.class) public SubstrateTruffleRuntime() { super(Collections.emptyList()); - this.graalRuntimeProvider = () -> ImageSingletons.lookup(GraalRuntime.class); /* Ensure the factory class gets initialized. */ super.getLoopNodeFactory(); } @@ -360,17 +358,14 @@ public void resetNativeImageState() { } @Override + @SuppressWarnings("unchecked") protected T asObject(Class type, JavaConstant constant) { - final GraalRuntime graalRuntime = graalRuntimeProvider.get(); - final SnippetReflectionProvider snippetReflection = graalRuntime.getRequiredCapability(SnippetReflectionProvider.class); - return snippetReflection.asObject(type, constant); + return (T) KnownIntrinsics.convertUnknownValue(SubstrateObjectConstant.asObject(type, constant), Object.class); } @Override protected JavaConstant forObject(Object object) { - final GraalRuntime graalRuntime = graalRuntimeProvider.get(); - final SnippetReflectionProvider snippetReflection = graalRuntime.getRequiredCapability(SnippetReflectionProvider.class); - return snippetReflection.forObject(object); + return SubstrateObjectConstant.forObject(object); } @Override From a4c74e2cd596b5a20f3066c5be28bb14f1630dd1 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Tue, 10 Sep 2019 18:47:10 +0200 Subject: [PATCH 125/140] Implement comparing different forms of object constants. --- .../SharedConstantReflectionProvider.java | 3 +- .../meta/DirectSubstrateObjectConstant.java | 13 +---- .../svm/core/meta/ObjectConstantEquality.java | 50 +++++++++++++++++ .../core/meta/SubstrateObjectConstant.java | 11 ++-- ...ubstrateObjectConstantEqualityFeature.java | 53 +++++++++++++++++++ 5 files changed, 114 insertions(+), 16 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/ObjectConstantEquality.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstantEqualityFeature.java diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java index 527c4e03b1d9..6886bc8c106d 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java @@ -30,6 +30,7 @@ import java.lang.reflect.Array; +import com.oracle.svm.core.meta.ObjectConstantEquality; import com.oracle.svm.core.meta.ReadableJavaField; import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.core.snippets.KnownIntrinsics; @@ -49,7 +50,7 @@ public Boolean constantEquals(Constant x, Constant y) { if (x == y) { return true; } else if (x instanceof SubstrateObjectConstant) { - return y instanceof SubstrateObjectConstant && SubstrateObjectConstant.asObject(x) == SubstrateObjectConstant.asObject(y); + return y instanceof SubstrateObjectConstant && ObjectConstantEquality.get().test((SubstrateObjectConstant) x, (SubstrateObjectConstant) y); } else { return x.equals(y); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java index c7952d4f7aa2..33ba7036feeb 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java @@ -108,17 +108,8 @@ public Object getRoot() { } @Override - public int hashCode() { - return super.hashCode() * 31 + System.identityHashCode(object); - } - - @Override - public boolean equals(Object obj) { - if (this != obj && obj instanceof DirectSubstrateObjectConstant) { - DirectSubstrateObjectConstant other = (DirectSubstrateObjectConstant) obj; - return object == other.object && super.equals(other); - } - return (this == obj); + protected int getIdentityHashCode() { + return System.identityHashCode(object); } @Override diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/ObjectConstantEquality.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/ObjectConstantEquality.java new file mode 100644 index 000000000000..5b7bbeb7b86e --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/ObjectConstantEquality.java @@ -0,0 +1,50 @@ +/* + * 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.core.meta; + +import org.graalvm.compiler.api.replacements.Fold; +import org.graalvm.compiler.truffle.compiler.nodes.ObjectLocationIdentity; +import org.graalvm.nativeimage.ImageSingletons; + +import jdk.vm.ci.meta.ConstantReflectionProvider; + +/** + * Tests if two {@linkplain SubstrateObjectConstant object constants} reference the same object. + * + * This class is needed because different subclasses of {@link SubstrateObjectConstant} must be + * comparable, but their {@link Object#equals} methods should not and cannot (due to dependencies) + * have direct knowledge of other classes, so their methods delegate to this class. This code + * overlaps with {@link ConstantReflectionProvider#constantEquals}, but existing code relies on + * directly testing object equality on constants, such as the {@link ObjectLocationIdentity} class, + * which is crucial for the alias analysis of memory accesses during compilation. + */ +public interface ObjectConstantEquality { + @Fold + static ObjectConstantEquality get() { + return ImageSingletons.lookup(ObjectConstantEquality.class); + } + + boolean test(SubstrateObjectConstant x, SubstrateObjectConstant y); +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java index b4098719f8fc..36415f5655aa 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java @@ -138,18 +138,21 @@ public JavaKind getJavaKind() { } @Override - public boolean equals(Object obj) { + public final boolean equals(Object obj) { if (obj != this && obj instanceof SubstrateObjectConstant) { - return compressed == ((SubstrateObjectConstant) obj).compressed; + SubstrateObjectConstant other = (SubstrateObjectConstant) obj; + return isCompressed() == other.isCompressed() && ObjectConstantEquality.get().test(this, other); } return obj == this; } @Override - public int hashCode() { - return Boolean.hashCode(compressed); + public final int hashCode() { + return getIdentityHashCode(); } + protected abstract int getIdentityHashCode(); + @Override public String toString() { return getJavaKind().getJavaName(); // + "[" + toValueString() + "]" + object; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstantEqualityFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstantEqualityFeature.java new file mode 100644 index 000000000000..d925fd15d024 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstantEqualityFeature.java @@ -0,0 +1,53 @@ +/* + * 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.core.meta; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.Feature; + +import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.util.VMError; + +final class SubstrateObjectConstantEquality implements ObjectConstantEquality { + @Override + public boolean test(SubstrateObjectConstant x, SubstrateObjectConstant y) { + if (x == y) { + return true; + } else if (x instanceof DirectSubstrateObjectConstant && y instanceof DirectSubstrateObjectConstant) { + return ((DirectSubstrateObjectConstant) x).getObject() == ((DirectSubstrateObjectConstant) y).getObject(); + } + throw VMError.shouldNotReachHere("Unknown object constants: " + x + " and " + y); + } +} + +@AutomaticFeature +final class SubstrateObjectConstantEqualityFeature implements Feature { + @Override + public void duringSetup(DuringSetupAccess access) { + if (!ImageSingletons.contains(ObjectConstantEquality.class)) { + ImageSingletons.add(ObjectConstantEquality.class, new SubstrateObjectConstantEquality()); + } + } +} From 1bceaca3639ef73b528b22cfe1c5f5709fc3831d Mon Sep 17 00:00:00 2001 From: Martin Entlicher Date: Tue, 8 Oct 2019 16:23:01 +0200 Subject: [PATCH 126/140] [GR-18720] Removed recursion in LinkedNodes. --- .../api/debug/SuspendableLocationFinder.java | 68 ++++++++++--------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/SuspendableLocationFinder.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/SuspendableLocationFinder.java index d1755d128df5..2237ba155f44 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/SuspendableLocationFinder.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/SuspendableLocationFinder.java @@ -348,43 +348,47 @@ void append(LinkedNodes lns) { } Node getInner(int sectionLength) { - if (next == null) { - return node; - } - Node o1 = node; - Node o2 = next.getInner(sectionLength); - if (isParentOf(o1, o2)) { - return o1; - } - if (isParentOf(o2, o1)) { - return o2; - } - // They are in different functions, find out which encloses the other - if (hasLargerParent(o2, sectionLength)) { - return o1; - } else { - return o2; + Node inner = this.node; + LinkedNodes linkedNodes = this.next; + while (linkedNodes != null) { + Node inner2 = linkedNodes.node; + if (isParentOf(inner, inner2)) { + // inner stays + } else if (isParentOf(inner2, inner)) { + inner = inner2; + } else { + // They are in different functions, find out which encloses the other + if (hasLargerParent(inner2, sectionLength)) { + // inner stays + } else { + inner = inner2; + } + } + linkedNodes = linkedNodes.next; } + return inner; } Node getOuter(int sectionLength) { - if (next == null) { - return node; - } - Node o1 = node; - Node o2 = next.getOuter(sectionLength); - if (isParentOf(o1, o2)) { - return o2; - } - if (isParentOf(o2, o1)) { - return o1; - } - // They are in different functions, find out which encloses the other - if (hasLargerParent(o2, sectionLength)) { - return o2; - } else { - return o1; + Node outer = this.node; + LinkedNodes linkedNodes = this.next; + while (linkedNodes != null) { + Node outer2 = linkedNodes.node; + if (isParentOf(outer, outer2)) { + outer = outer2; + } else if (isParentOf(outer2, outer)) { + // outer stays + } else { + // They are in different functions, find out which encloses the other + if (hasLargerParent(outer2, sectionLength)) { + outer = outer2; + } else { + // outer stays + } + } + linkedNodes = linkedNodes.next; } + return outer; } @Override From 2cd48b15c2fef183844fe5acc3a5795bd01fc58d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Tue, 8 Oct 2019 16:43:46 +0200 Subject: [PATCH 127/140] Make assert distinguishable --- .../src/com/oracle/svm/jni/JNIObjectHandles.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 17dd3c41ff0a..b95c534c01aa 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 @@ -363,7 +363,7 @@ static JNIObjectHandle toWeakGlobal(JNIObjectHandle handle) { } private static JNIObjectHandle toRange(JNIObjectHandle handle, SignedWord rangeMin) { - assert isInRange(handle); + assert isInRange(handle) : "assert isInRange(handle) failed"; return (JNIObjectHandle) ((SignedWord) handle).and(OBJ_OFFSET_BITS_MASK).add(rangeMin); } From c5164fbd9a4c5ffca043294aa95065d1cd13c9f6 Mon Sep 17 00:00:00 2001 From: Roland Schatz Date: Tue, 8 Oct 2019 17:25:58 +0200 Subject: [PATCH 128/140] Support pointer values in LLVM switch bitcode. --- .../nodes/api/LLVMTypesLongPointer.java | 68 +++++++++++++++++++ .../runtime/nodes/control/LLVMSwitchNode.java | 2 +- .../runtime/nodes/op/LLVMCompareNode.java | 24 +++++-- 3 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMTypesLongPointer.java diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMTypesLongPointer.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMTypesLongPointer.java new file mode 100644 index 000000000000..4e63cf68c189 --- /dev/null +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMTypesLongPointer.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019, 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.runtime.nodes.api; + +import com.oracle.truffle.api.dsl.ImplicitCast; +import com.oracle.truffle.api.dsl.TypeSystem; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.llvm.runtime.LLVMIVarBit; +import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; +import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer; +import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; +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; +import com.oracle.truffle.llvm.runtime.vector.LLVMPointerVector; + +/** + * Special subclass of LLVMTypes for nodes that consider i64 and pointer to be the same type. + */ +@TypeSystem({boolean.class, byte.class, short.class, int.class, char.class, long.class, double.class, float.class, byte[].class, + LLVMI1Vector.class, LLVMI8Vector.class, LLVMI16Vector.class, LLVMI32Vector.class, LLVMI64Vector.class, + LLVMPointerVector.class, LLVMFloatVector.class, LLVMDoubleVector.class, + LLVMNativePointer.class, LLVMManagedPointer.class, LLVMPointer.class, + LLVMIVarBit.class, LLVM80BitFloat.class, TruffleObject.class}) +public class LLVMTypesLongPointer extends LLVMTypes { + + @ImplicitCast + public static LLVMNativePointer asNativePointer(long value) { + return LLVMNativePointer.create(value); + } + + @ImplicitCast + public static LLVMPointer asPointer(long value) { + return LLVMNativePointer.create(value); + } +} diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/control/LLVMSwitchNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/control/LLVMSwitchNode.java index 33a4e4bb8cc2..1d53f24d5455 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/control/LLVMSwitchNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/control/LLVMSwitchNode.java @@ -97,7 +97,7 @@ public LLVMStatementNode getPhiNode(int successorIndex) { @Override public boolean executeIsCase(VirtualFrame frame, int i, Object value) { - return caseEquals[i].executeCompare(cases[i].executeGeneric(frame), value); + return caseEquals[i].executeWithTarget(cases[i].executeGeneric(frame), value); } } } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/LLVMCompareNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/LLVMCompareNode.java index 6e982fb62732..139c8e3ff1fa 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/LLVMCompareNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/LLVMCompareNode.java @@ -29,18 +29,22 @@ */ package com.oracle.truffle.llvm.runtime.nodes.op; +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.dsl.TypeSystemReference; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; +import com.oracle.truffle.llvm.runtime.nodes.api.LLVMTypesLongPointer; +import com.oracle.truffle.llvm.runtime.nodes.op.LLVMAddressEqualsNode.LLVMPointerEqualsNode; +import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer; @NodeChild(type = LLVMExpressionNode.class) @NodeChild(type = LLVMExpressionNode.class) +@TypeSystemReference(LLVMTypesLongPointer.class) public abstract class LLVMCompareNode extends LLVMAbstractCompareNode { - public abstract boolean executeCompare(Object val1, Object val2); - public abstract static class LLVMEqNode extends LLVMCompareNode { @Specialization protected boolean eq(boolean val1, boolean val2) { @@ -63,10 +67,16 @@ protected boolean eq(int val1, int val2) { } @Specialization - protected boolean eq(long val1, long val2) { + protected boolean eqLong(long val1, long val2) { return val1 == val2; } + @Specialization(replaces = "eqLong") + protected boolean eqPointer(LLVMPointer val1, LLVMPointer val2, + @Cached LLVMPointerEqualsNode equals) { + return equals.execute(val1, val2); + } + @Specialization protected boolean eq(LLVMIVarBit val1, LLVMIVarBit val2) { return val1.isEqual(val2); @@ -95,10 +105,16 @@ protected boolean nq(int val1, int val2) { } @Specialization - protected boolean nq(long val1, long val2) { + protected boolean nqLong(long val1, long val2) { return val1 != val2; } + @Specialization(replaces = "nqLong") + protected boolean nqPointer(LLVMPointer val1, LLVMPointer val2, + @Cached LLVMPointerEqualsNode equals) { + return !equals.execute(val1, val2); + } + @Specialization protected boolean nq(LLVMIVarBit val1, LLVMIVarBit val2) { return !val1.isEqual(val2); From 0fce1c30dfac74af7439a0bf69e1be4a036e42f3 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Tue, 8 Oct 2019 18:36:36 +0200 Subject: [PATCH 129/140] [GR-18682] NPE when instrument asks for TruffleFile in onLanguageContextInitialized with SVM patching. --- .../truffle/polyglot/EngineAccessor.java | 2 +- .../truffle/polyglot/PolyglotContextImpl.java | 48 +++++++++++++------ .../truffle/polyglot/PolyglotEngineImpl.java | 11 ++--- .../polyglot/PolyglotLanguageContext.java | 8 ++-- 4 files changed, 42 insertions(+), 27 deletions(-) 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 57a009cf1847..15f8cf78a774 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 @@ -536,7 +536,7 @@ public void closeInternalContext(Object impl) { if (context.isActive()) { throw new IllegalStateException("The context is currently entered and cannot be closed."); } - context.closeImpl(false, false); + context.closeImpl(false, false, true); } @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 a50e1109ca69..785c39056187 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 @@ -79,6 +79,7 @@ import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.impl.Accessor.CastUnsafe; +import com.oracle.truffle.api.nodes.LanguageInfo; import com.oracle.truffle.polyglot.HostLanguage.HostContext; import com.oracle.truffle.polyglot.PolyglotEngineImpl.CancelExecution; @@ -867,7 +868,7 @@ public Engine getEngineImpl(Context sourceContext) { @Override public void close(Context sourceContext, boolean cancelIfExecuting) { checkCreatorAccess(sourceContext, "closed"); - boolean closeCompleted = closeImpl(cancelIfExecuting, cancelIfExecuting); + boolean closeCompleted = closeImpl(cancelIfExecuting, cancelIfExecuting, true); if (cancelIfExecuting) { engine.getCancelHandler().cancel(Arrays.asList(this)); } else if (!closeCompleted) { @@ -913,7 +914,7 @@ public Value asValue(Object hostValue) { } void waitForClose() { - while (!closeImpl(false, true)) { + while (!closeImpl(false, true, true)) { try { synchronized (this) { wait(1000); @@ -970,7 +971,7 @@ synchronized void notifyThreadClosed() { } } - boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { + boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads, boolean notifyInstruments) { /* * As a first step we prepare for close by waiting for other threads to finish closing and * checking whether other threads are still executing. This block performs the following @@ -1060,9 +1061,9 @@ boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { assert !closed; Object prev = engine.enter(this); try { - closeChildContexts(cancelIfExecuting, waitForPolyglotThreads); + closeChildContexts(cancelIfExecuting, waitForPolyglotThreads, notifyInstruments); - finalizeContext(); + finalizeContext(notifyInstruments); // finalization performed commit close -> no reinitialization allowed @@ -1097,7 +1098,7 @@ boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { */ if (disposedContexts != null) { for (PolyglotLanguageContext context : disposedContexts) { - context.notifyDisposed(); + context.notifyDisposed(notifyInstruments); } } @@ -1106,14 +1107,16 @@ boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { synchronized (parent) { parent.childContexts.remove(this); } - } else { + } else if (notifyInstruments) { engine.removeContext(this); } - for (Thread thread : remainingThreads) { - EngineAccessor.INSTRUMENT.notifyThreadFinished(engine, truffleContext, thread); + if (notifyInstruments) { + for (Thread thread : remainingThreads) { + EngineAccessor.INSTRUMENT.notifyThreadFinished(engine, truffleContext, thread); + } + EngineAccessor.INSTRUMENT.notifyContextClosed(engine, truffleContext); } - EngineAccessor.INSTRUMENT.notifyContextClosed(engine, truffleContext); if (parent == null) { if (!this.config.logLevels.isEmpty()) { EngineAccessor.LANGUAGE.configureLoggers(this, null, getAllLoggers(engine)); @@ -1126,13 +1129,13 @@ boolean closeImpl(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { return true; } - private void closeChildContexts(boolean cancelIfExecuting, boolean waitForPolyglotThreads) { + private void closeChildContexts(boolean cancelIfExecuting, boolean waitForPolyglotThreads, boolean notifyInstruments) { PolyglotContextImpl[] childrenToClose; synchronized (this) { childrenToClose = childContexts.toArray(new PolyglotContextImpl[childContexts.size()]); } for (PolyglotContextImpl childContext : childrenToClose) { - childContext.closeImpl(cancelIfExecuting, waitForPolyglotThreads); + childContext.closeImpl(cancelIfExecuting, waitForPolyglotThreads, notifyInstruments); } } @@ -1160,7 +1163,7 @@ private List disposeContext() { } } - private void finalizeContext() { + private void finalizeContext(boolean notifyInstruments) { // we need to run finalization at least twice in case a finalization run has // initialized a new contexts boolean finalizationPerformed; @@ -1172,7 +1175,7 @@ private void finalizeContext() { PolyglotLanguageContext context = contexts[i]; if (context.isInitialized()) { try { - finalizationPerformed |= context.finalizeContext(); + finalizationPerformed |= context.finalizeContext(notifyInstruments); } catch (Exception | Error ex) { throw PolyglotImpl.wrapGuestException(context, ex); } @@ -1229,12 +1232,29 @@ boolean patch(PolyglotContextConfig newConfig) { return false; } } + replayInstrumentationEvents(); } finally { engine.leave(prev, this); } return true; } + private void replayInstrumentationEvents() { + notifyContextCreated(); + for (PolyglotLanguageContext lc : contexts) { + LanguageInfo language = lc.language.info; + if (lc.eventsEnabled && lc.env != null) { + EngineAccessor.INSTRUMENT.notifyLanguageContextCreated(this, truffleContext, language); + if (lc.isInitialized()) { + EngineAccessor.INSTRUMENT.notifyLanguageContextInitialized(this, truffleContext, language); + if (lc.finalized) { + EngineAccessor.INSTRUMENT.notifyLanguageContextFinalized(this, truffleContext, language); + } + } + } + } + } + synchronized void checkSubProcessFinished() { ProcessHandlers.ProcessDecorator[] processes = subProcesses.toArray(new ProcessHandlers.ProcessDecorator[subProcesses.size()]); for (ProcessHandlers.ProcessDecorator process : processes) { 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 4bf3d00e0c36..4fd219a70dba 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 @@ -834,7 +834,7 @@ synchronized void ensureClosed(boolean cancelIfExecuting, boolean ignoreCloseFai for (PolyglotContextImpl context : localContexts) { assert !Thread.holdsLock(context); try { - boolean closeCompleted = context.closeImpl(cancelIfExecuting, cancelIfExecuting); + boolean closeCompleted = context.closeImpl(cancelIfExecuting, cancelIfExecuting, true); if (!closeCompleted && !cancelIfExecuting) { if (!ignoreCloseFailure) { throw new IllegalStateException(String.format("One of the context instances is currently executing. " + @@ -973,7 +973,6 @@ static PolyglotEngineImpl preInitialize(PolyglotImpl impl, DispatchOutputStream synchronized (engine) { try { engine.preInitializedContext = PolyglotContextImpl.preInitialize(engine); - engine.addContext(engine.preInitializedContext); } finally { // Reset language homes from native-image compilatio time, will be recomputed in // image execution time @@ -1282,12 +1281,8 @@ public synchronized Context createContext(OutputStream configOut, OutputStream c PolyglotContextImpl context = loadPreinitializedContext(config); if (context == null) { context = new PolyglotContextImpl(this, config); - addContext(context); - } else { - // don't add contexts for preinitialized contexts as they have been added already - assert Thread.holdsLock(this); - assert contexts.contains(context.weakReference); } + addContext(context); if (polyglotLimits != null) { EngineLimits l = this.limits; @@ -1322,7 +1317,7 @@ private PolyglotContextImpl loadPreinitializedContext(PolyglotContextConfig conf patchResult = context.patch(config); } finally { if (!patchResult) { - context.closeImpl(false, false); + context.closeImpl(false, false, false); context = null; PolyglotContextImpl.disposeStaticContext(context); config.fileSystem = oldFileSystem; 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 a0647209ef77..499a7fe277b9 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 @@ -331,11 +331,11 @@ Env requireEnv() { return localEnv; } - boolean finalizeContext() { + boolean finalizeContext(boolean notifyInstruments) { if (!finalized) { finalized = true; LANGUAGE.finalizeContext(env); - if (eventsEnabled) { + if (eventsEnabled && notifyInstruments) { EngineAccessor.INSTRUMENT.notifyLanguageContextFinalized(context.engine, context.truffleContext, language.info); } return true; @@ -365,8 +365,8 @@ boolean dispose() { return false; } - void notifyDisposed() { - if (eventsEnabled) { + void notifyDisposed(boolean notifyInstruments) { + if (eventsEnabled && notifyInstruments) { EngineAccessor.INSTRUMENT.notifyLanguageContextDisposed(context.engine, context.truffleContext, language.info); } language.freeInstance(lazy.languageInstance); From 41e7c0c18ea53fdc92fc9f22f5674f5214f49757 Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Tue, 8 Oct 2019 13:52:47 -0700 Subject: [PATCH 130/140] Force early call of C method initializeEncoding() also on JDK 8 --- .../jdk/JNIPlatformNativeLibrarySupport.java | 48 +++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JNIPlatformNativeLibrarySupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JNIPlatformNativeLibrarySupport.java index 5d8bb51b0939..9928309e8626 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JNIPlatformNativeLibrarySupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JNIPlatformNativeLibrarySupport.java @@ -35,6 +35,8 @@ import com.oracle.svm.core.annotate.Alias; import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.c.CGlobalData; +import com.oracle.svm.core.c.CGlobalDataFactory; public abstract class JNIPlatformNativeLibrarySupport extends PlatformNativeLibrarySupport { @@ -45,23 +47,53 @@ protected void loadJavaLibrary() { Target_java_io_FileDescriptor_JNI.initIDs(); Target_java_io_FileInputStream_JNI.initIDs(); Target_java_io_FileOutputStream_JNI.initIDs(); + + initializeEncoding(); + } + + /** + * The JDK C code has a field `fastEncoding` to speed up conversions between C string and Java + * strings. We need to ensure that the initialization code runs early: + * + * On JDK 8, the C method initializeEncoding() is called lazily from various places. But + * unfortunately the implementation is not thread safe: a second thread can use unititialized + * state while the first thread is still in the initialization. So we need to force + * initialization here where we are still single threaded. + * + * On JDK 11, the initialization is performed from Java during `System.initPhase1` by + * `System.initProperties`. We do invoke that part of the system initialization because we + * already have many system properties pre-initialized in the image heap. + * + * On both JDK 8 and 11, the system property `sun.jnu.encoding` decides which encoding to use. + * Currently, we inherit this system property from image build time (see + * {@link SystemPropertiesSupport}), i.e., we do not allow it to be specified at run time and + * (more importantly) also do not look at environment variables to determine the encoding. + */ + private static void initializeEncoding() { if (JavaVersionUtil.JAVA_SPEC >= 11) { /* - * Unlike JDK 8, where platform encoding is initialized from native code, in JDK 11 the - * initialization of platform encoding is performed from Java during `System.initPhase1` - * by `System.initProperties`. Hence, we do it here. - * - * Note that the value of `sun.jnu.encoding` property is determined at image build time, - * see `SystemPropertiesSupport.HOSTED_PROPERTIES`. + * On JDK 11 and later, the method InitializeEncoding is an exported JNI function and we + * can call it directly. */ try (CTypeConversion.CCharPointerHolder name = CTypeConversion.toCString(System.getProperty("sun.jnu.encoding"))) { - initializeEncoding(CurrentIsolate.getCurrentThread(), name.get()); + nativeInitializeEncoding(CurrentIsolate.getCurrentThread(), name.get()); } + } else { + /* + * On JDK 8, the method initializeEncoding is not an exported JNI function. We call an + * exported function that unconditionally triggers the initialization. + */ + nativeNewStringPlatform(CurrentIsolate.getCurrentThread(), EMPTY_C_STRING.get()); } } @CFunction("InitializeEncoding") - private static native void initializeEncoding(PointerBase env, CCharPointer name); + private static native void nativeInitializeEncoding(PointerBase env, CCharPointer name); + + private static final CGlobalData EMPTY_C_STRING = CGlobalDataFactory.createCString(""); + + @CFunction("JNU_NewStringPlatform") + private static native void nativeNewStringPlatform(PointerBase env, CCharPointer str); @Platforms(InternalPlatform.PLATFORM_JNI.class) protected void loadZipLibrary() { From 686127a678ec10ebc97717875fc03d95826e449d Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Tue, 8 Oct 2019 15:56:29 -0700 Subject: [PATCH 131/140] Add SUBSTITUTION suffix to old LINUX and DARWIN platforms --- .../src/org/graalvm/nativeimage/Platform.java | 83 +----------- .../nativeimage/impl/DeprecatedPlatform.java | 126 ++++++++++++++++++ .../svm/core/graal/llvm/LLVMFeature.java | 3 +- .../snippets/PosixAArch64VaListSnippets.java | 5 +- .../snippets/PosixAMD64VaListSnippets.java | 5 +- ...PosixJavaIOSubstitutions_JDK11OrLater.java | 4 +- .../Target_java_lang_ProcessHandleImpl.java | 4 +- ...tPlainDatagramSocketImpl_JDK11OrLater.java | 5 +- ..._AbstractPlainSocketImpl_JDK11OrLater.java | 5 +- .../jdk11/PosixJavaNIOSubstitutions.java | 8 +- .../Target_java_net_SocketCleanable.java | 4 +- .../posix/jdk11/Target_java_util_Zip.java | 6 +- .../Target_jdk_net_MacOSXSocketOptions.java | 4 +- .../Target_jdk_net_LinuxSocketOptions.java | 4 +- .../oracle/svm/core/posix/JavaNetNetUtil.java | 33 ++--- .../core/posix/JavaNetNetworkInterface.java | 4 +- .../core/posix/JavaUtilZipSubstitutions.java | 12 +- .../posix/Java_lang_Process_Supplement.java | 5 +- .../core/posix/PosixInterruptSignalUtils.java | 4 +- .../core/posix/PosixJaasSubstitutions.java | 4 +- .../core/posix/PosixJavaIOSubstitutions.java | 14 +- .../posix/PosixJavaLangSubstitutions.java | 35 ++--- .../core/posix/PosixJavaNIOSubstitutions.java | 73 +++++----- .../svm/core/posix/PosixJavaNetClose.java | 4 +- .../core/posix/PosixJavaNetSubstitutions.java | 54 ++++---- .../core/posix/PosixLoggingSubstitutions.java | 4 +- .../core/posix/PosixSunNioSubstitutions.java | 6 +- .../posix/PosixSunSecuritySubstitutions.java | 8 +- .../com/oracle/svm/core/posix/PosixUtils.java | 3 +- .../core/posix/SegfaultHandlerFeature.java | 4 +- .../svm/core/posix/SunMiscSubstitutions.java | 3 +- .../com/oracle/svm/core/posix/VmPrimsJVM.java | 4 +- .../AArch64UContextRegisterDumper.java | 4 +- .../amd64/AMD64UContextRegisterDumper.java | 4 +- .../posix/darwin/DarwinJavaNetCloseImpl.java | 6 +- .../darwin/DarwinJavaNetNetworkInterface.java | 4 +- .../posix/darwin/DarwinNIOSubstitutions.java | 10 +- .../darwin/DarwinUContextRegisterDumper.java | 4 +- .../oracle/svm/core/posix/headers/Fcntl.java | 6 +- .../svm/core/posix/headers/Ifaddrs.java | 5 +- .../oracle/svm/core/posix/headers/Locale.java | 14 +- .../oracle/svm/core/posix/headers/NetIf.java | 16 +-- .../svm/core/posix/headers/NetIfDl.java | 4 +- .../oracle/svm/core/posix/headers/Netdb.java | 5 +- .../svm/core/posix/headers/NetinetIn.java | 15 +-- .../svm/core/posix/headers/NetinetTcp.java | 14 +- .../oracle/svm/core/posix/headers/Poll.java | 5 +- .../oracle/svm/core/posix/headers/Signal.java | 14 +- .../oracle/svm/core/posix/headers/Socket.java | 10 +- .../svm/core/posix/headers/SysParam.java | 5 +- .../svm/core/posix/headers/SysSelect.java | 5 +- .../oracle/svm/core/posix/headers/ZLib.java | 4 +- .../posix/headers/darwin/DarwinEvent.java | 4 +- .../headers/darwin/DarwinInode64Suffix.java | 4 +- .../headers/darwin/DarwinNetinet6In6_var.java | 4 +- .../posix/headers/darwin/DarwinSendfile.java | 4 +- .../posix/headers/linux/Linux64Suffix.java | 4 +- .../core/posix/headers/linux/LinuxEPoll.java | 4 +- .../svm/core/posix/headers/linux/LinuxIn.java | 5 +- .../core/posix/headers/linux/LinuxSched.java | 4 +- .../svm/core/posix/headers/linux/Mntent.java | 4 +- .../posix/linux/LinuxJavaNetCloseImpl.java | 6 +- .../linux/LinuxJavaNetNetworkInterface.java | 4 +- .../posix/linux/LinuxNIOSubstitutions.java | 10 +- .../core/posix/linux/LinuxSubstitutions.java | 4 +- .../com/oracle/svm/core/headers/Errno.java | 94 ++++++------- .../svm/hosted/NativeImageGenerator.java | 7 +- 67 files changed, 450 insertions(+), 406 deletions(-) create mode 100644 sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/DeprecatedPlatform.java diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java index 756805452b2d..dd90b817f05b 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java @@ -87,6 +87,7 @@ static boolean includedIn(Class platformGroup) { /* * The standard architectures that are supported. */ + /** * Supported architecture: x86 64-bit. * @@ -108,23 +109,6 @@ interface AArch64 extends Platform { /* * The standard operating systems that are supported. */ - /** - * Supported operating system: Linux. - * - * @since 19.0 - */ - interface LINUX extends Platform { - - } - - /** - * Supported operating system: Darwin (MacOS). - * - * @since 19.0 - */ - interface DARWIN extends Platform { - - } /** * Supported operating system: Windows. @@ -138,71 +122,6 @@ interface WINDOWS extends InternalPlatform.PLATFORM_JNI { /* * The standard leaf platforms, i.e., OS-architecture combinations that we support. */ - /** - * Supported leaf platform: Linux on x86 64-bit. - * - * @since 19.0 - */ - class LINUX_AMD64 implements LINUX, InternalPlatform.LINUX_AND_JNI, AMD64 { - - /** - * Instantiates a marker instance of this platform. - * - * @since 19.0 - */ - public LINUX_AMD64() { - } - - } - - /** - * Supported leaf platform: Linux on AArch64 64-bit. - * - * @since 19.0 - */ - final class LINUX_AArch64 implements LINUX, InternalPlatform.LINUX_AND_JNI, AArch64 { - - /** - * Instantiates a marker instance of this platform. - * - * @since 19.0 - */ - public LINUX_AArch64() { - } - - } - - /** - * Supported leaf platform: Darwin (MacOS) on x86 64-bit. - * - * @since 19.0 - */ - class DARWIN_AMD64 implements DARWIN, InternalPlatform.DARWIN_AND_JNI, AMD64 { - - /** - * Instantiates a marker instance of this platform. - * - * @since 19.0 - */ - public DARWIN_AMD64() { - } - } - - /** - * Supported leaf platform: Darwin (MacOS) on AArch 64-bit. - * - * @since 2.0 - */ - final class DARWIN_AArch64 implements DARWIN, InternalPlatform.DARWIN_AND_JNI, AArch64 { - - /** - * Instantiates a marker instance of this platform. - * - * @since 2.0 - */ - public DARWIN_AArch64() { - } - } /** * Supported leaf platform: Windows on x86 64-bit. diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/DeprecatedPlatform.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/DeprecatedPlatform.java new file mode 100644 index 000000000000..a291c6d2830a --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/DeprecatedPlatform.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2019, 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.nativeimage.impl; + +import org.graalvm.nativeimage.Platform; + +public interface DeprecatedPlatform { + + /** + * Supported operating system: Linux. + * + * @since 19.0 + */ + interface LINUX_SUBSTITUTION extends Platform { + } + + /** + * Supported operating system: Darwin (MacOS). + * + * @since 19.0 + */ + interface DARWIN_SUBSTITUTION extends Platform { + } + + /** + * Supported leaf platform: Linux on x86 64-bit. + * + * @since 19.0 + */ + class LINUX_SUBSTITUTION_AMD64 implements DeprecatedPlatform.LINUX_SUBSTITUTION, InternalPlatform.LINUX_AND_JNI, Platform.AMD64 { + + /** + * Instantiates a marker instance of this platform. + * + * @since 19.0 + */ + public LINUX_SUBSTITUTION_AMD64() { + } + } + + /** + * Supported leaf platform: Linux on AArch64 64-bit. + * + * @since 19.0 + */ + class LINUX_SUBSTITUTION_AArch64 implements DeprecatedPlatform.LINUX_SUBSTITUTION, InternalPlatform.LINUX_AND_JNI, Platform.AArch64 { + + /** + * Instantiates a marker instance of this platform. + * + * @since 19.0 + */ + public LINUX_SUBSTITUTION_AArch64() { + } + } + + /** + * Supported leaf platform: Darwin (MacOS) on x86 64-bit. + * + * @since 19.0 + */ + class DARWIN_SUBSTITUTION_AMD64 implements DeprecatedPlatform.DARWIN_SUBSTITUTION, InternalPlatform.DARWIN_AND_JNI, Platform.AMD64 { + + /** + * Instantiates a marker instance of this platform. + * + * @since 19.0 + */ + public DARWIN_SUBSTITUTION_AMD64() { + } + } + + /** + * Supported leaf platform: Darwin (MacOS) on AArch 64-bit. + * + * @since 2.0 + */ + class DARWIN_SUBSTITUTION_AArch64 implements DeprecatedPlatform.DARWIN_SUBSTITUTION, InternalPlatform.DARWIN_AND_JNI, Platform.AArch64 { + + /** + * Instantiates a marker instance of this platform. + * + * @since 2.0 + */ + public DARWIN_SUBSTITUTION_AArch64() { + } + } +} diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java index 6ab8188e8fef..151f481b01fb 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java @@ -54,6 +54,7 @@ import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.function.CLibrary; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.Pointer; @@ -81,7 +82,7 @@ @AutomaticFeature @CLibrary("m") -@Platforms({Platform.LINUX.class, InternalPlatform.LINUX_AND_JNI.class, Platform.DARWIN.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, InternalPlatform.LINUX_AND_JNI.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.DARWIN_AND_JNI.class}) public class LLVMFeature implements Feature, GraalFeature { private static HostedMethod personalityStub; diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAArch64VaListSnippets.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAArch64VaListSnippets.java index fa001b3af83d..a871ddf96c14 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAArch64VaListSnippets.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAArch64VaListSnippets.java @@ -38,8 +38,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platform.DARWIN_AArch64; -import org.graalvm.nativeimage.Platform.LINUX_AArch64; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_JNI_AArch64; import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_JNI_AArch64; import org.graalvm.word.Pointer; @@ -54,7 +53,7 @@ class PosixAArch64VaListSnippetsFeature implements GraalFeature { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { - return Platform.includedIn(LINUX_AArch64.class) || Platform.includedIn(DARWIN_AArch64.class) || + return Platform.includedIn(DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64.class) || Platform.includedIn(DeprecatedPlatform.DARWIN_SUBSTITUTION_AArch64.class) || Platform.includedIn(LINUX_JNI_AArch64.class) || Platform.includedIn(DARWIN_JNI_AArch64.class); } diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAMD64VaListSnippets.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAMD64VaListSnippets.java index 0edbf15b3dc2..8439d40056ab 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAMD64VaListSnippets.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAMD64VaListSnippets.java @@ -38,8 +38,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platform.DARWIN_AMD64; -import org.graalvm.nativeimage.Platform.LINUX_AMD64; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_JNI_AMD64; import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_JNI_AMD64; import org.graalvm.word.Pointer; @@ -54,7 +53,7 @@ class PosixAMD64VaListSnippetsFeature implements GraalFeature { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { - return Platform.includedIn(LINUX_AMD64.class) || Platform.includedIn(DARWIN_AMD64.class) || + return Platform.includedIn(DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class) || Platform.includedIn(DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class) || Platform.includedIn(LINUX_JNI_AMD64.class) || Platform.includedIn(DARWIN_JNI_AMD64.class); } diff --git a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/PosixJavaIOSubstitutions_JDK11OrLater.java b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/PosixJavaIOSubstitutions_JDK11OrLater.java index 6928f4878975..e339b948c67f 100644 --- a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/PosixJavaIOSubstitutions_JDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/PosixJavaIOSubstitutions_JDK11OrLater.java @@ -24,9 +24,9 @@ */ package com.oracle.svm.core.posix; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; @@ -38,7 +38,7 @@ public final class PosixJavaIOSubstitutions_JDK11OrLater { } -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(className = "java.io.UnixFileSystem", onlyWith = JDK11OrLater.class) final class Target_java_io_UnixFileSystem_JDK11OrLater { diff --git a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_lang_ProcessHandleImpl.java b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_lang_ProcessHandleImpl.java index 1c87b9d75f23..61c300a430e4 100644 --- a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_lang_ProcessHandleImpl.java +++ b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_lang_ProcessHandleImpl.java @@ -26,9 +26,9 @@ import java.util.concurrent.Executor; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.ProcessProperties; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import com.oracle.svm.core.annotate.Delete; import com.oracle.svm.core.annotate.Substitute; @@ -36,7 +36,7 @@ import com.oracle.svm.core.jdk.JDK11OrLater; import com.oracle.svm.core.util.VMError; -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(className = "java.lang.ProcessHandleImpl", onlyWith = JDK11OrLater.class) final class Target_java_lang_ProcessHandleImpl { diff --git a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_net_AbstractPlainDatagramSocketImpl_JDK11OrLater.java b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_net_AbstractPlainDatagramSocketImpl_JDK11OrLater.java index 21191bf5d7f8..0aa354da1770 100644 --- a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_net_AbstractPlainDatagramSocketImpl_JDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_net_AbstractPlainDatagramSocketImpl_JDK11OrLater.java @@ -27,11 +27,12 @@ import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; import com.oracle.svm.core.jdk.JDK11OrLater; -import org.graalvm.nativeimage.Platform; + import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; @TargetClass(className = "java.net.AbstractPlainDatagramSocketImpl", onlyWith = JDK11OrLater.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_AbstractPlainDatagramSocketImpl_JDK11OrLater { // This class must not hide the "normal" Posix variant, and should be additive diff --git a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_net_AbstractPlainSocketImpl_JDK11OrLater.java b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_net_AbstractPlainSocketImpl_JDK11OrLater.java index ce09f4541e42..fc1c399bd94a 100644 --- a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_net_AbstractPlainSocketImpl_JDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/Target_java_net_AbstractPlainSocketImpl_JDK11OrLater.java @@ -27,11 +27,12 @@ import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; import com.oracle.svm.core.jdk.JDK11OrLater; -import org.graalvm.nativeimage.Platform; + import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; @TargetClass(className = "java.net.AbstractPlainSocketImpl", onlyWith = JDK11OrLater.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_AbstractPlainSocketImpl_JDK11OrLater { // This class must not hide the "normal" Posix variant, and should be additive diff --git a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/PosixJavaNIOSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/PosixJavaNIOSubstitutions.java index 1bc053f782e0..39bfd3be8e36 100644 --- a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/PosixJavaNIOSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/PosixJavaNIOSubstitutions.java @@ -30,10 +30,10 @@ import java.io.FileDescriptor; import java.io.IOException; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.annotate.Substitute; @@ -44,11 +44,11 @@ import com.oracle.svm.core.posix.headers.Fcntl; import com.oracle.svm.core.posix.headers.Statvfs; -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public class PosixJavaNIOSubstitutions { @TargetClass(className = "sun.nio.ch.IOUtil", onlyWith = JDK11OrLater.class) - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_IOUtil { // ported from {jdk11}/src/java.base/unix/native/libnio/ch/IOUtil.c // 107 JNIEXPORT jint JNICALL @@ -64,7 +64,7 @@ static int write1(int fd, byte b) throws IOException { } @TargetClass(className = "sun.nio.ch.FileDispatcherImpl", onlyWith = JDK11OrLater.class) - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_FileDispatcherImpl { /* Do not re-format commented out C code. @formatter:off */ diff --git a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/Target_java_net_SocketCleanable.java b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/Target_java_net_SocketCleanable.java index 1cd5cff397ad..854489ca7cad 100644 --- a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/Target_java_net_SocketCleanable.java +++ b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/Target_java_net_SocketCleanable.java @@ -30,10 +30,10 @@ import com.oracle.svm.core.annotate.TargetClass; import com.oracle.svm.core.posix.PosixJavaNetClose; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(className = "java.net.SocketCleanable") final class Target_java_net_SocketCleanable { diff --git a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/Target_java_util_Zip.java b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/Target_java_util_Zip.java index e41d06bc7c14..065d216d7674 100644 --- a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/Target_java_util_Zip.java +++ b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/Target_java_util_Zip.java @@ -35,17 +35,17 @@ import com.oracle.svm.core.posix.JavaUtilZipSubstitutions; import com.oracle.svm.core.posix.headers.ZLib; import org.graalvm.nativeimage.PinnedObject; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.WordFactory; // Dummy class for file name. public class Target_java_util_Zip { } -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(value = java.util.zip.Deflater.class, onlyWith = JDK11OrLater.class) final class Target_java_util_zip_Deflater { @@ -194,7 +194,7 @@ static long doDeflate(long addr, } } -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(value = java.util.zip.Inflater.class, onlyWith = JDK11OrLater.class) final class Target_java_util_zip_Inflater { diff --git a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/darwin/Target_jdk_net_MacOSXSocketOptions.java b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/darwin/Target_jdk_net_MacOSXSocketOptions.java index cab20bc7ae6b..7b0ed9ec8af5 100644 --- a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/darwin/Target_jdk_net_MacOSXSocketOptions.java +++ b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/darwin/Target_jdk_net_MacOSXSocketOptions.java @@ -34,11 +34,11 @@ import com.oracle.svm.core.posix.PosixUtils; import com.oracle.svm.core.posix.headers.Socket; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.c.type.CIntPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import static com.oracle.svm.core.posix.headers.NetinetIn.IPPROTO_TCP; import static com.oracle.svm.core.posix.headers.NetinetTcp.TCP_KEEPALIVE; @@ -48,7 +48,7 @@ import static com.oracle.svm.core.posix.jdk11.darwin.Util_jdk_net_MacOSXSocketOptions.socketOptionSupported; @TargetClass(className = "jdk.net.MacOSXSocketOptions", onlyWith = JDK11OrLater.class) -@Platforms({Platform.DARWIN_AMD64.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class}) public final class Target_jdk_net_MacOSXSocketOptions { // ported from {jdk11}/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c diff --git a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/linux/Target_jdk_net_LinuxSocketOptions.java b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/linux/Target_jdk_net_LinuxSocketOptions.java index fad573dbc0af..fad631bebfb0 100644 --- a/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/linux/Target_jdk_net_LinuxSocketOptions.java +++ b/substratevm/src/com.oracle.svm.core.posix.jdk11/src/com/oracle/svm/core/posix/jdk11/linux/Target_jdk_net_LinuxSocketOptions.java @@ -36,11 +36,11 @@ import com.oracle.svm.core.posix.headers.NetinetTcp; import com.oracle.svm.core.posix.headers.Socket; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.c.type.CIntPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import static com.oracle.svm.core.posix.headers.NetinetTcp.SOL_TCP; import static com.oracle.svm.core.posix.headers.NetinetTcp.TCP_KEEPIDLE; @@ -57,7 +57,7 @@ import static com.oracle.svm.core.posix.jdk11.linux.Util_jdk_net_LinuxSocketOptions.socketOptionSupported; @TargetClass(className = "jdk.net.LinuxSocketOptions", onlyWith = JDK11OrLater.class) -@Platforms({Platform.LINUX.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) public final class Target_jdk_net_LinuxSocketOptions { // ported from {jdk11}/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaNetNetUtil.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaNetNetUtil.java index ce9ba6dad239..19718f07ae06 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaNetNetUtil.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaNetNetUtil.java @@ -47,6 +47,7 @@ import org.graalvm.nativeimage.c.type.CLongPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; import org.graalvm.nativeimage.c.type.WordPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import org.graalvm.word.WordFactory; @@ -71,7 +72,7 @@ // TODO: This should be in some other package (svm.core.jdk?) // but then it can not use the non-public classes in this package. /** Native methods from jdk/src/share/native/java/net/net_util.c translated to Java. */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) class JavaNetNetUtil { /* Private constructor: No instances. */ @@ -553,7 +554,7 @@ static int MAX_PACKET_LEN() { } /** Native methods from jdk/src/solaris/native/java/net/net_util_md.c translated to Java. */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) class JavaNetNetUtilMD { /* Private constructor: No instances. */ @@ -947,23 +948,23 @@ static boolean reuseport_supported() { } /* @formatter:on */ - @Platforms(Platform.LINUX.class)// + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class)// /* TODO: This will be evaluated during native image generation. */ // 219 static int vinit = 0; static int vinit = 0; - @Platforms(Platform.LINUX.class)// + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class)// /* TODO: This will be evaluated during native image generation. */ // 220 static int kernelV24 = 0; static int kernelV24 = 0; - @Platforms(Platform.LINUX.class)// + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class)// /* TODO: This will be evaluated during native image generation. */ // 221 static int vinit24 = 0; static int vinit24 = 0; /* Do not re-wrap comments. @formatter:off */ - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) // 223 int kernelIsV24 () { static boolean kernelIsV24() { // 224 if (!vinit24) { @@ -984,13 +985,13 @@ static boolean kernelIsV24() { } /* @formatter:on */ - @Platforms(Platform.LINUX.class)// + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class)// /* TODO: This will be evaluated during native image generation. */ // 492 static int lo_scope_id = 0; static int lo_scope_id = 0; /* Do not re-wrap comments. @formatter:off */ - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) // 504 static jboolean needsLoopbackRoute (struct in6_addr* dest_addr) { static boolean needsLoopbackRoute(@SuppressWarnings("unused") NetinetIn.in6_addr dest_addr) { VMError.unimplemented(); @@ -1030,7 +1031,7 @@ static boolean needsLoopbackRoute(@SuppressWarnings("unused") NetinetIn.in6_addr /* @formatter:on */ /* Do not re-wrap comments. @formatter:off */ - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) // 539 static void initLoopbackRoutes() { static void initLoopbackRoutes() { VMError.unimplemented(); @@ -1150,7 +1151,7 @@ static void initLoopbackRoutes() { /* @formatter:on */ /* Do not re-wrap comments. @formatter:off */ - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) // 721 /* return the scope_id (interface index) of the // 722 * interface corresponding to the given address // 723 * returns 0 if no match found @@ -1176,7 +1177,7 @@ static int getLocalScopeID(NetinetIn.in6_addr addr) { /* @formatter:on */ /* Do not re-wrap comments. @formatter:off */ - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) // 1043 /* // 1044 * Determine the default interface for an IPv6 address. // 1045 * @@ -1336,7 +1337,7 @@ static int getDefaultIPv6Interface(NetinetIn.in6_addr target_addr) { // 088 void setDefaultScopeID(JNIEnv *env, struct sockaddr *him) static void setDefaultScopeID(Socket.sockaddr him) { // 090 #ifdef MACOSX - if (Platform.includedIn(Platform.DARWIN.class)) { + if (Platform.includedIn(DeprecatedPlatform.DARWIN_SUBSTITUTION.class)) { // 091 static jclass ni_class = NULL; // 092 static jfieldID ni_defaultIndexID; // 093 if (ni_class == NULL) { @@ -2194,7 +2195,7 @@ static int NET_Bind(int fd, Socket.sockaddr him, int len) { } /** Native methods (and macros) from src/share/vm/prims/jni.cpp translated to Java. */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) class VmPrimsJNI { /* Do not re-format commented-out code: @formatter:off */ @@ -2279,7 +2280,7 @@ static void SetByteArrayRegion(byte[] array, int start, int len, CCharPointer bu /** Translations of methods from src/os/bsd/vm/os_bsd.inline.hpp or src/os/bsd/vm/os_bsd.cpp. */ // TODO: Maybe this should be Target_bsd_vm_os? -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) class Target_os { /* Do not re-format commented-out code: @formatter:off */ @@ -2466,7 +2467,7 @@ static int accept(int fd, Socket.sockaddr him, CIntPointer len_Pointer) { } /** Translations from src/share/vm/runtime/os.hpp. */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) class VmRuntimeOS { /* Do not re-format commented-out code: @formatter:off */ @@ -2509,7 +2510,7 @@ static int OS_NORESOURCE() { } /** Translations from src/share/javavm/export/jvm.h. */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) class JavavmExportJvm { // 1100 #define JVM_IO_ERR (-1) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaNetNetworkInterface.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaNetNetworkInterface.java index 7aba82de1203..da221291ec24 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaNetNetworkInterface.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaNetNetworkInterface.java @@ -34,13 +34,13 @@ import com.oracle.svm.core.util.Utf8; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.PinnedObject; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CIntPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import org.graalvm.word.WordFactory; @@ -80,7 +80,7 @@ // So one can look at the quoted line numbers on the C code to see which platform // the code applies to. -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public class JavaNetNetworkInterface { /* diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaUtilZipSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaUtilZipSubstitutions.java index 8139ddd344a9..fe74631b2b57 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaUtilZipSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/JavaUtilZipSubstitutions.java @@ -27,12 +27,12 @@ import java.util.zip.DataFormatException; import org.graalvm.nativeimage.PinnedObject; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.SubstrateUtil; @@ -45,7 +45,7 @@ import com.oracle.svm.core.posix.headers.ZLib; import com.oracle.svm.core.posix.headers.ZLib.z_stream; -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(java.util.zip.Adler32.class) final class Target_java_util_zip_Adler32 { // Adler32.c-Java_java_util_zip_Adler32_update(JNIEnv *env, jclass cls, jint adler, jint b) @@ -75,7 +75,7 @@ private static int updateByteBuffer(int adler, long addr, int off, int len) { } } -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(java.util.zip.CRC32.class) final class Target_java_util_zip_CRC32 { // CRC32.c-Java_java_util_zip_CRC32_update(JNIEnv *env, jclass cls, jint crc, jint b) @@ -105,7 +105,7 @@ private static int updateByteBuffer(int crc, long addr, int off, int len) { } } -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(value = java.util.zip.Deflater.class) final class Target_java_util_zip_Deflater { @Alias // @@ -269,7 +269,7 @@ static int update(Object obj, int len, z_stream strm) { } } -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(value = java.util.zip.Inflater.class) final class Target_java_util_zip_Inflater { @@ -399,7 +399,7 @@ private static void end(long addr) { } /** Dummy class to have a class with the file's name. */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public final class JavaUtilZipSubstitutions { public static class Util_java_util_zip_Deflater { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/Java_lang_Process_Supplement.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/Java_lang_Process_Supplement.java index 10230d7f384b..bef1990a24b1 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/Java_lang_Process_Supplement.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/Java_lang_Process_Supplement.java @@ -38,6 +38,7 @@ import org.graalvm.nativeimage.c.type.CIntPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.Pointer; import org.graalvm.word.PointerBase; import org.graalvm.word.SignedWord; @@ -60,7 +61,7 @@ import com.oracle.svm.core.posix.headers.UnistdNoTransitions; import com.oracle.svm.core.util.VMError; -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public final class Java_lang_Process_Supplement { static final ThreadFactory reaperFactory = new ThreadFactory() { @@ -78,7 +79,7 @@ public Thread newThread(Runnable reaper) { @SuppressWarnings("try") static int doForkAndExec(CCharPointer file, CCharPointer dir, CCharPointerPointer argv, CCharPointerPointer envp, int[] stdioFds, int failFd, boolean redirectErrorStream) { final int buflen = SizeOf.get(dirent.class) + Limits.PATH_MAX() + 1; - final boolean haveProcFs = Platform.includedIn(Platform.LINUX.class); + final boolean haveProcFs = Platform.includedIn(DeprecatedPlatform.LINUX_SUBSTITUTION.class); try (// Allocate any objects we need in the child after the fork() ahead of time here, since // only this thread will exist in the child and garbage collection is not possible. PinnedObject bufferPin = PinnedObject.create(new byte[buflen]); diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixInterruptSignalUtils.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixInterruptSignalUtils.java index a5637646ebf5..f09e8927e868 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixInterruptSignalUtils.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixInterruptSignalUtils.java @@ -27,11 +27,11 @@ import java.io.IOException; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.function.CEntryPoint; import org.graalvm.nativeimage.c.function.CEntryPointLiteral; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.c.function.CEntryPointOptions; @@ -55,7 +55,7 @@ * Adapted from /jdk8u-dev/jdk/src/solaris/native/sun/nio/ch/NativeThread.c, but shared by anyone * who sends C signals to interrupt blocked operations. */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public class PosixInterruptSignalUtils { /** diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJaasSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJaasSubstitutions.java index 5401a9f5e94d..75e350666fc7 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJaasSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJaasSubstitutions.java @@ -26,11 +26,11 @@ import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.PinnedObject; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.annotate.Alias; @@ -52,7 +52,7 @@ private PosixJaasSubstitutions() { } } -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(className = "com.sun.security.auth.module.UnixSystem") final class Target_com_sun_security_auth_module_UnixSystem { @Alias String username; diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaIOSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaIOSubstitutions.java index 7307fcb92a7b..0265687f779c 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaIOSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaIOSubstitutions.java @@ -90,7 +90,6 @@ import java.util.concurrent.locks.ReentrantLock; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; @@ -98,6 +97,7 @@ import org.graalvm.nativeimage.c.type.CIntPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.SignedWord; import org.graalvm.word.WordFactory; @@ -122,12 +122,12 @@ import com.oracle.svm.core.util.VMError; @TargetClass(className = "java.io.ExpiringCache") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_io_ExpiringCache { } @TargetClass(className = "java.io.UnixFileSystem") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @SuppressWarnings("static-method") final class Target_java_io_UnixFileSystem { @@ -447,7 +447,7 @@ public boolean setLastModifiedTime(File f, long time) { } @TargetClass(java.io.FileInputStream.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_io_FileInputStream { @Alias private FileDescriptor fd; @@ -548,7 +548,7 @@ static boolean isSock(int mode) { } @TargetClass(java.io.FileOutputStream.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_io_FileOutputStream { @Substitute @@ -574,7 +574,7 @@ private void write(int b, boolean append) throws IOException { } @TargetClass(java.io.RandomAccessFile.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_io_RandomAccessFile { // Checkstyle: stop @@ -691,7 +691,7 @@ public void setLength(long newLength) throws IOException { } @TargetClass(java.io.Console.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_io_Console { @Alias // diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaLangSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaLangSubstitutions.java index 58d4496a4fb0..1657ea58cf11 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaLangSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaLangSubstitutions.java @@ -40,6 +40,7 @@ import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CCharPointerPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; @@ -65,7 +66,7 @@ import com.oracle.svm.core.util.PointerUtils; @TargetClass(className = "java.lang.ProcessEnvironment") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_lang_ProcessEnvironment { /* @@ -158,7 +159,7 @@ static byte[][] environ() { } @TargetClass(className = "java.lang.ProcessEnvironment", innerClass = "StringEnvironment") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_lang_ProcessEnvironment_StringEnvironment { @Alias @SuppressWarnings("unused") @@ -171,14 +172,14 @@ final class Target_java_lang_ProcessEnvironment_StringEnvironment { } @TargetClass(className = "java.lang.ProcessEnvironment", innerClass = "Variable") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_lang_ProcessEnvironment_Variable { @Alias public static native Target_java_lang_ProcessEnvironment_Variable valueOf(byte[] bytes); } @TargetClass(className = "java.lang.ProcessEnvironment", innerClass = "Value") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_lang_ProcessEnvironment_Value { @Alias public static native Target_java_lang_ProcessEnvironment_Value valueOf(byte[] bytes); @@ -203,7 +204,7 @@ final class Target_java_lang_UNIXProcess { // The reaper thread pool and thread groups (currently) confuse the analysis, so we launch // reaper threads individually (with the only difference being that threads are not recycled) - @Platforms({Platform.LINUX.class, Platform.DARWIN.class})// + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class})// @TargetElement(onlyWith = JDK8OrEarlier.class)// @Delete static Executor processReaperExecutor; @@ -222,7 +223,7 @@ final class Target_java_lang_UNIXProcess { */ @Substitute - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @SuppressWarnings({"unused", "static-method"}) int forkAndExec(int mode, byte[] helperpath, byte[] file, @@ -237,20 +238,20 @@ int forkAndExec(int mode, byte[] helperpath, @Substitute @TargetElement(onlyWith = JDK8OrEarlier.class) - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) void initStreams(int[] fds) { UNIXProcess_Support.doInitStreams(this, fds, false); } @Substitute @TargetElement(onlyWith = JDK11OrLater.class) - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) void initStreams(int[] fds, boolean forceNullOutputStream) { UNIXProcess_Support.doInitStreams(this, fds, forceNullOutputStream); } @Substitute - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetElement(onlyWith = JDK8OrEarlier.class) @SuppressWarnings({"static-method"}) int waitForProcessExit(int ppid) { @@ -259,7 +260,7 @@ int waitForProcessExit(int ppid) { @Substitute @TargetElement(onlyWith = JDK8OrEarlier.class) - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static void destroyProcess(int ppid, boolean force) { int sig = force ? Signal.SignalEnum.SIGKILL.getCValue() : Signal.SignalEnum.SIGTERM.getCValue(); Signal.kill(ppid, sig); @@ -317,7 +318,7 @@ public void run() { } @TargetClass(classNameProvider = ProcessNameProvider.class, innerClass = "ProcessPipeInputStream") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_lang_UNIXProcess_ProcessPipeInputStream { @Alias Target_java_lang_UNIXProcess_ProcessPipeInputStream(@SuppressWarnings("unused") int fd) { @@ -328,7 +329,7 @@ final class Target_java_lang_UNIXProcess_ProcessPipeInputStream { } @TargetClass(classNameProvider = ProcessNameProvider.class, innerClass = "ProcessPipeOutputStream") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_lang_UNIXProcess_ProcessPipeOutputStream { @Alias Target_java_lang_UNIXProcess_ProcessPipeOutputStream(@SuppressWarnings("unused") int fd) { @@ -339,19 +340,19 @@ final class Target_java_lang_UNIXProcess_ProcessPipeOutputStream { } @TargetClass(className = "java.lang.ProcessBuilder", innerClass = "NullInputStream") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_lang_ProcessBuilder_NullInputStream { @Alias static Target_java_lang_ProcessBuilder_NullInputStream INSTANCE; } @TargetClass(className = "java.lang.ProcessBuilder", innerClass = "NullOutputStream") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_lang_ProcessBuilder_NullOutputStream { @Alias static Target_java_lang_ProcessBuilder_NullOutputStream INSTANCE; } @TargetClass(java.lang.System.class) -@Platforms({Platform.LINUX.class, InternalPlatform.LINUX_JNI.class, Platform.DARWIN.class, InternalPlatform.DARWIN_JNI.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.DARWIN_JNI.class}) final class Target_java_lang_System { @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)// @@ -368,7 +369,7 @@ public static long currentTimeMillis() { } @TargetClass(className = "java.lang.Shutdown") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_lang_Shutdown { @Substitute @@ -378,7 +379,7 @@ static void halt0(int status) { } @TargetClass(java.lang.Runtime.class) -@Platforms({Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @SuppressWarnings({"static-method"}) final class Target_java_lang_Runtime { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNIOSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNIOSubstitutions.java index 0d80a55249cb..5799e8c8d0b0 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNIOSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNIOSubstitutions.java @@ -133,6 +133,7 @@ import org.graalvm.nativeimage.c.type.VoidPointer; import org.graalvm.nativeimage.c.type.WordPointer; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import org.graalvm.word.PointerBase; import org.graalvm.word.SignedWord; @@ -189,12 +190,12 @@ import com.oracle.svm.core.posix.headers.linux.Mntent; import com.oracle.svm.core.posix.headers.linux.Mntent.mntent; -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public final class PosixJavaNIOSubstitutions { // Checkstyle: stop @TargetClass(className = "sun.nio.ch.IOStatus") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public static final class Target_sun_nio_ch_IOStatus { @Alias @TargetElement(name = "EOF")// public static int IOS_EOF; @@ -211,7 +212,7 @@ public static final class Target_sun_nio_ch_IOStatus { } @TargetClass(className = "sun.nio.ch.FileDispatcher") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_FileDispatcher { @Alias @TargetElement(name = "NO_LOCK")// protected static int FD_NO_LOCK; @@ -305,7 +306,7 @@ protected static T dlsym(PointerBase handle, String name } @TargetClass(className = "sun.nio.fs.Cancellable") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_fs_Cancellable { @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Manual)// private long pollingAddress; @@ -314,7 +315,7 @@ static final class Target_sun_nio_fs_Cancellable { /** See the comments on {@link sun.nio.ch.NativeThread}. */ /* Translated from: jdk/src/solaris/native/sun/nio/ch/NativeThread.c?v=Java_1.8.0_40_b10 */ @TargetClass(className = "sun.nio.ch.NativeThread") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_NativeThread { /* { Do not re-format commented code: @formatter:off */ @@ -387,7 +388,7 @@ private static void signal(long thread) throws IOException { */ @TargetClass(className = "sun.nio.ch.IOUtil") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_IOUtil { @Substitute @@ -527,7 +528,7 @@ static int configureBlocking(int fd, boolean blocking) { /** Translations of src/solaris/native/sun/nio/ch/Net.c?v=Java_1.8.0_40_b10. */ @TargetClass(className = "sun.nio.ch.Net") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_Net { /* Do not re-format commented-out code: @formatter:off */ @@ -770,7 +771,7 @@ static int socket0(boolean preferIPv6, boolean stream, boolean reuse, @SuppressW } } // 276 #if defined(__linux__) - if (Platform.includedIn(Platform.LINUX.class)) { + if (Platform.includedIn(DeprecatedPlatform.LINUX_SUBSTITUTION.class)) { // 277 if (type == SOCK_DGRAM) { if (type == Socket.SOCK_DGRAM()) { // 278 int arg = 0; @@ -798,7 +799,7 @@ static int socket0(boolean preferIPv6, boolean stream, boolean reuse, @SuppressW } // 289 #endif // 291 #if defined(__linux__) && defined(AF_INET6) - if (Platform.includedIn(Platform.LINUX.class)) { + if (Platform.includedIn(DeprecatedPlatform.LINUX_SUBSTITUTION.class)) { // 292 /* By default, Linux uses the route default */ // 293 if (domain == AF_INET6 && type == SOCK_DGRAM) { if ((domain == Socket.AF_INET6()) && (type == Socket.SOCK_DGRAM())) { @@ -1092,7 +1093,7 @@ static void shutdown(FileDescriptor fdo, int jhow) throws IOException { } @TargetClass(className = "sun.nio.ch.ServerSocketChannelImpl") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_ServerSocketChannelImpl { // jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java?v=Java_1.8.0_40_b10 @@ -1281,7 +1282,7 @@ private static InternalError throwInternalError(String msg) { /** Translations of src/solaris/native/sun/nio/ch/FileDispatcherImpl.c?v=Java_1.8.0_40_b10. */ @TargetClass(className = "sun.nio.ch.FileDispatcherImpl") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_FileDispatcherImpl { @Substitute @@ -1527,7 +1528,7 @@ static void initialize() { } @TargetClass(className = "sun.nio.fs.UnixException") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @SuppressWarnings({"unused"}) static final class Target_sun_nio_fs_UnixException { @Alias @@ -1537,7 +1538,7 @@ protected Target_sun_nio_fs_UnixException(int errno) { // Checkstyle: stop @TargetClass(className = "sun.nio.fs.UnixFileAttributes") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_fs_UnixFileAttributes { @Alias int st_mode; @Alias long st_ino; @@ -1558,7 +1559,7 @@ static final class Target_sun_nio_fs_UnixFileAttributes { } @TargetClass(className = "sun.nio.fs.UnixFileStoreAttributes") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_fs_UnixFileStoreAttributes { @Alias long f_frsize; @Alias long f_blocks; @@ -1567,7 +1568,7 @@ static final class Target_sun_nio_fs_UnixFileStoreAttributes { } @TargetClass(className = "sun.nio.fs.UnixMountEntry") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_fs_UnixMountEntry { @Alias byte[] name; @Alias byte[] dir; @@ -1648,7 +1649,7 @@ interface fdopendir_func extends CFunctionPointer { // Checkstyle: resume @TargetClass(className = "sun.nio.fs.UnixNativeDispatcher") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_fs_UnixNativeDispatcher { @Substitute @@ -2494,7 +2495,7 @@ private static boolean openatSupported() { } } - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Util_sun_nio_fs_UnixNativeDispatcher { /** * Size of password or group entry when not available via sysconf. @@ -2595,7 +2596,7 @@ interface flistxattr_func extends CFunctionPointer { // Checkstyle: resume @TargetClass(className = "sun.nio.fs.LinuxNativeDispatcher") - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) static final class Target_sun_nio_fs_LinuxNativeDispatcher { @Substitute @@ -2726,7 +2727,7 @@ private static void init() { } - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) static final class Util_sun_nio_fs_LinuxNativeDispatcher { // Checkstyle: stop @@ -2754,7 +2755,7 @@ static void initialize() { */ @TargetClass(className = "sun.nio.fs.MacOSXNativeDispatcher") - @Platforms(Platform.DARWIN.class) + @Platforms(DeprecatedPlatform.DARWIN_SUBSTITUTION.class) static final class Target_sun_nio_fs_MacOSXNativeDispatcher { @Substitute @@ -2772,7 +2773,7 @@ private static char[] normalizepath(char[] path, int form) { */ @TargetClass(className = "sun.nio.ch.FileChannelImpl") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @SuppressWarnings("static-method") static final class Target_sun_nio_ch_FileChannelImpl { @Alias @TargetElement(name = "fd") private FileDescriptor fdfield; @@ -2848,7 +2849,7 @@ private static int unmap0(long address, long len) throws IOException { @Substitute @TargetElement(name = "transferTo0") - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) private long transferTo0Linux(FileDescriptor src, long position, long count, FileDescriptor dst) throws IOException { CLongPointer offset = StackValue.get(CLongPointer.class); offset.write(position); @@ -2871,7 +2872,7 @@ private long transferTo0Linux(FileDescriptor src, long position, long count, Fil @Substitute @TargetElement(name = "transferTo0") - @Platforms(Platform.DARWIN.class) + @Platforms(DeprecatedPlatform.DARWIN_SUBSTITUTION.class) private long transferTo0Darwin(FileDescriptor src, long position, long count, FileDescriptor dst) throws IOException { CLongPointer numBytes = StackValue.get(CLongPointer.class); int result; @@ -2908,7 +2909,7 @@ private long transferTo0Darwin(FileDescriptor src, long position, long count, Fi */ @TargetClass(className = "sun.nio.ch.FileKey") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_FileKey { // Checkstyle: stop @Alias long st_dev; @@ -2944,7 +2945,7 @@ private void init(FileDescriptor fdo) throws IOException { */ @TargetClass(className = "sun.nio.fs.UnixCopyFile") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_fs_UnixCopyFile { /** @@ -2993,7 +2994,7 @@ private static void transfer(int dst, int src, long cancelAddress) throws Except } @TargetClass(className = "sun.nio.ch.SocketChannelImpl") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_SocketChannelImpl { @Substitute @@ -3158,7 +3159,7 @@ static int checkConnect(FileDescriptor fdo, boolean block) throws IOException { } @TargetClass(className = "sun.nio.ch.UnixAsynchronousSocketChannelImpl") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_UnixAsynchronousSocketChannelImpl { /* { Do not format quoted code: @formatter:off */ @@ -3195,7 +3196,7 @@ static void checkConnect(int fd) throws IOException { } @TargetClass(className = "sun.nio.ch.UnixAsynchronousServerSocketChannelImpl") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl { /* { Do not format quoted code: @formatter:off */ @@ -3218,12 +3219,12 @@ int accept0(FileDescriptor ssfd, FileDescriptor newfd, InetSocketAddress[] isaa) } @TargetClass(className = "sun.nio.fs.UnixFileSystem") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_fs_UnixFileSystem { } @TargetClass(className = "sun.nio.fs.UnixFileSystemProvider") - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_sun_nio_fs_UnixFileSystemProvider { @Alias native Target_sun_nio_fs_UnixFileSystem newFileSystem(String s); @@ -3235,7 +3236,7 @@ static final class Util_Target_java_nio_file_FileSystems { } @TargetClass(FileSystems.class) - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) static final class Target_java_nio_file_FileSystems { @Substitute static FileSystem getDefault() { @@ -3257,7 +3258,7 @@ static final class Target_java_nio_file_FileSystems_DefaultFileSystemHolder { * Translated from: * jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c?v=Java_1.8.0_40_b10 */ - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @TargetClass(className = "sun.nio.fs.GnomeFileTypeDetector", onlyWith = JDK8OrEarlier.class) static final class Target_sun_nio_fs_GnomeFileTypeDetector { @@ -3558,7 +3559,7 @@ static boolean getGnomeVfsAvailable(Target_sun_nio_fs_GnomeFileTypeDetector that } } - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) static final class Util_sun_nio_fs_GnomeFileTypeDetector { /* { Do not format quoted code: @formatter:off */ @@ -3685,7 +3686,7 @@ interface gnome_vfs_mime_type_from_name_function extends CFunctionPointer { * Translated from: * jdk/src/solaris/native/sun/nio/fs/MagicFileTypeDetector.c?v=Java_1.8.0_40_b10 */ - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @TargetClass(className = "sun.nio.fs.MagicFileTypeDetector", onlyWith = JDK8OrEarlier.class) static final class Target_sun_nio_fs_MagicFileTypeDetector { /* { Do not format quoted code: @formatter:off */ @@ -3843,7 +3844,7 @@ static boolean getLibmagicAvailable(Target_sun_nio_fs_MagicFileTypeDetector that } } - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) static class Util_sun_nio_fs_MagicFileTypeDetector { /* { Do not format quoted code: @formatter:off */ @@ -3898,7 +3899,7 @@ interface magic_close_func extends CFunctionPointer { /* { Allow names with non-standard names: Checkstyle: stop */ @SuppressWarnings({"unused", "static-method"}) @TargetClass(className = "sun.nio.ch.DatagramChannelImpl") - @Platforms({Platform.DARWIN.class, Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) static final class Target_sun_nio_ch_DatagramChannelImpl { @Alias // diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNetClose.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNetClose.java index f42276dc8ef2..98293a87058a 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNetClose.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNetClose.java @@ -31,9 +31,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.IntSupplier; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.type.CIntPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import org.graalvm.word.WordFactory; @@ -52,7 +52,7 @@ * operations. This translation is not a direct translation of the methods. Rather the mechanism is * implemented using Java data structures. */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public abstract class PosixJavaNetClose { /** diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNetSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNetSubstitutions.java index 2590fd8cd5b4..6b65eb2f949b 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNetSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaNetSubstitutions.java @@ -53,7 +53,6 @@ import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.PinnedObject; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; @@ -63,6 +62,7 @@ import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder; import org.graalvm.nativeimage.c.type.WordPointer; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import org.graalvm.word.PointerBase; import org.graalvm.word.WordFactory; @@ -101,7 +101,7 @@ public final class PosixJavaNetSubstitutions { /* { Allow names with non-standard names: Checkstyle: stop */ @TargetClass(className = "java.net.PlainDatagramSocketImpl", onlyWith = JDK11OrEarlier.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_PlainDatagramSocketImpl { // translated from {jdk8}/src/solaris/native/java/net/PlainDatagramSocketImpl.c @@ -1543,7 +1543,7 @@ protected void leave(InetAddress ia, NetworkInterface ni) throws IOException { /* } Allow names with non-standard names: Checkstyle: resume */ @TargetClass(java.net.DatagramSocket.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_DatagramSocket { @Substitute @@ -1554,7 +1554,7 @@ private void checkOldImpl() { } @TargetClass(java.net.DatagramPacket.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_DatagramPacket { /* Aliases to get visibility for substituted methods. */ @Alias byte[] buf; @@ -1566,7 +1566,7 @@ final class Target_java_net_DatagramPacket { } @TargetClass(java.net.DatagramSocketImpl.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_DatagramSocketImpl { /* Aliases to get visibility for substituted methods. */ @Alias FileDescriptor fd; @@ -3164,7 +3164,7 @@ static void mcast_join_leave(Target_java_net_PlainDatagramSocketImpl self, InetA /* } Allow names with non-standard names: Checkstyle: resume */ @TargetClass(java.net.ServerSocket.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_ServerSocket { @TargetElement(onlyWith = JDK11OrEarlier.class) // @@ -3183,7 +3183,7 @@ private void checkOldImpl() { // Allow methods with non-standard names: Checkstyle: stop @TargetClass(className = "java.net.InetAddress") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_InetAddress { /* @@ -3259,7 +3259,7 @@ final class Target_java_net_InetAddress { } @TargetClass(className = "java.net.InetAddress", innerClass = "Cache", onlyWith = JDK8OrEarlier.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_InetAddress_Cache { @Alias @RecomputeFieldValue(kind = Kind.NewInstance, declClass = LinkedHashMap.class)// @@ -3267,7 +3267,7 @@ final class Target_java_net_InetAddress_Cache { } @TargetClass(className = "java.net.InetAddress", innerClass = "CachedLocalHost", onlyWith = JDK11OrLater.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_InetAddress_CachedLocalHost { } @@ -3311,7 +3311,7 @@ static void Java_java_net_InetAddress_init() { } @TargetClass(className = "java.net.InterfaceAddress") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_InterfaceAddress { @Alias InetAddress address; @@ -3343,7 +3343,7 @@ static InterfaceAddress newInterfaceAddress() { */ /** Aliases to get visibility to fields. */ @TargetClass(className = "java.net.InetAddress", innerClass = "InetAddressHolder") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_InetAddress_InetAddressHolder { /* Aliases to get visibility. */ @@ -3364,7 +3364,7 @@ final class Target_java_net_InetAddress_InetAddressHolder { } @TargetClass(className = "java.net.InetAddressContainer") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_InetAddressContainer { @Alias InetAddress addr; } @@ -3395,7 +3395,7 @@ static Target_java_net_InetAddressContainer narrow(Object obj) { } @TargetClass(className = "java.net.Inet4Address") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_Inet4Address { @Alias @@ -3461,7 +3461,7 @@ static void Java_java_net_Inet4Address_init() { /* branch */ /** Substitutions for the code from src/solaris/native/java/net/Inet4AddressImpl.c?v=Java_1.8.0_40_b10. */ @TargetClass(className = "java.net.Inet4AddressImpl") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_Inet4AddressImpl { @Alias @RecomputeFieldValue(kind = Kind.Reset)// @@ -3828,7 +3828,7 @@ static boolean initializeInetClasses() { /** Aliases to get visibility to fields. */ @TargetClass(className = "java.net.Inet6Address") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_Inet6Address { @Alias static int INADDRSZ; @@ -3891,7 +3891,7 @@ static void Java_java_net_Inet6Address_init() { /** Aliases to get visibility to fields. */ @TargetClass(className = "java.net.Inet6Address", innerClass = "Inet6AddressHolder") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_Inet6Address_Inet6AddressHolder { // Aliases to get visibility for substituted methods. @@ -3912,7 +3912,7 @@ final class Target_java_net_Inet6Address_Inet6AddressHolder { } @TargetClass(className = "java.net.Inet6AddressImpl") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_Inet6AddressImpl { @Alias @RecomputeFieldValue(kind = Kind.Reset)// @@ -4398,7 +4398,7 @@ static InetAddress[] lookupIfLocalhost(CCharPointer hostname, boolean includeV6) } @TargetClass(java.net.NetworkInterface.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_NetworkInterface { /* Aliases to get visibility to fields. */ @@ -4874,7 +4874,7 @@ public static NetworkInterface newNetworkInterface() { } @TargetClass(java.net.Socket.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_Socket { @TargetElement(onlyWith = JDK11OrEarlier.class) // @@ -4895,7 +4895,7 @@ private void checkOldImpl() { * class. */ @TargetClass(className = "java.net.SocketInputStream") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_SocketInputStream { /* Do not re-format commeted-out code: @formatter:off */ @@ -5061,7 +5061,7 @@ private int socketRead0(FileDescriptor fdObj, byte[] data, int off, int lenArg, /** Translations from src/solaris/native/java/net/SocketOutputStream.c. */ @TargetClass(className = "java.net.SocketOutputStream") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_SocketOutputStream { /* Do not re-format commented-out code: @formatter:off */ @@ -5190,7 +5190,7 @@ private void socketWrite0(FileDescriptor fdObj, byte[] data, int offArg, int len } @TargetClass(className = "java.net.SocketImpl") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_SocketImpl { /* Aliases to get visibility for substituted methods. */ @@ -5210,7 +5210,7 @@ final class Target_java_net_SocketImpl { // 044 abstract class AbstractPlainSocketImpl extends SocketImpl @TargetClass(className = "java.net.AbstractPlainSocketImpl") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_AbstractPlainSocketImpl { /* Aliases to get visibility for substituted methods. */ @@ -5225,7 +5225,7 @@ final class Target_java_net_AbstractPlainSocketImpl { /** Translations from jdk/src/solaris/native/java/net/PlainSocketImpl.c. */ @TargetClass(className = "java.net.PlainSocketImpl") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_net_PlainSocketImpl { /* Substitutions for native methods. */ @@ -6650,7 +6650,7 @@ public void duringSetup(DuringSetupAccess access) { } @TargetClass(sun.net.spi.DefaultProxySelector.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_sun_net_spi_DefaultProxySelector { /** Private constructor: No instances. */ @@ -6677,7 +6677,7 @@ private Target_sun_net_spi_DefaultProxySelector() { } @TargetClass(sun.net.sdp.SdpSupport.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_sun_net_sdp_SdpSupport { /** Private constructor: No instances. */ @@ -6757,7 +6757,7 @@ final class Util_sun_net_sdp_SdpSupport { // 036 #define AF_INET_SDP 27 // 037 #endif // 038 #endif - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) static int AF_INET_SDP() { return 27; } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLoggingSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLoggingSubstitutions.java index ab92e9d7a304..fca834eb4dae 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLoggingSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLoggingSubstitutions.java @@ -24,8 +24,8 @@ */ package com.oracle.svm.core.posix; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; @@ -33,7 +33,7 @@ import com.oracle.svm.core.jdk.JDK8OrEarlier; @TargetClass(java.util.logging.FileHandler.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_java_util_logging_FileHandler { /* diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSunNioSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSunNioSubstitutions.java index f578286284fd..166a8ff264ba 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSunNioSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSunNioSubstitutions.java @@ -28,7 +28,7 @@ import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.type.CIntPointer; -import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.WordFactory; @@ -42,11 +42,11 @@ /* Do not reformat commented-out code: @formatter:off */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public final class PosixSunNioSubstitutions { /** Translations of jdk/src/solaris/native/sun/nio/ch/PollArrayWrapper.c?v=Java_1.8.0_40_b10. */ - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(className = "sun.nio.ch.PollArrayWrapper", onlyWith = JDK8OrEarlier.class) static final class Target_sun_nio_ch_PollArrayWrapper { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSunSecuritySubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSunSecuritySubstitutions.java index a553206c8888..1a0358009fe3 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSunSecuritySubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSunSecuritySubstitutions.java @@ -29,9 +29,9 @@ import java.io.OutputStream; import java.security.SecureRandom; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import com.oracle.svm.core.annotate.Alias; import com.oracle.svm.core.annotate.AutomaticFeature; @@ -45,7 +45,7 @@ * handles on isolate tear-down. */ @AutomaticFeature -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) class NativeSecureRandomFilesCloser implements Feature { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { @@ -70,13 +70,13 @@ private static void registerShutdownHook(@SuppressWarnings("unused") DuringAnaly } @TargetClass(className = "sun.security.provider.NativePRNG") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_sun_security_provider_NativePRNG { @Alias static Target_sun_security_provider_NativePRNG_RandomIO INSTANCE; } @TargetClass(className = "sun.security.provider.NativePRNG", innerClass = "RandomIO") -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_sun_security_provider_NativePRNG_RandomIO { @Alias InputStream seedIn; @Alias InputStream nextIn; diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java index 89d78d3603ae..1f301b5e4b16 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java @@ -48,6 +48,7 @@ import org.graalvm.nativeimage.c.type.CIntPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.PointerBase; import org.graalvm.word.SignedWord; @@ -109,7 +110,7 @@ private static int getCategory(String category) { case "LC_MESSAGES": return Locale.LC_MESSAGES(); } - if (Platform.includedIn(Platform.LINUX.class)) { + if (Platform.includedIn(DeprecatedPlatform.LINUX_SUBSTITUTION.class)) { switch (category) { case "LC_PAPER": return Locale.LC_PAPER(); diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java index 1afb646afae9..ea4d9f613408 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java @@ -28,13 +28,13 @@ import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.LogHandler; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.function.CEntryPoint; import org.graalvm.nativeimage.c.function.CEntryPointLiteral; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; @@ -56,7 +56,7 @@ import com.oracle.svm.core.posix.headers.Signal.ucontext_t; import com.oracle.svm.core.thread.VMThreads; -@Platforms({Platform.LINUX_AMD64.class, Platform.DARWIN_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) @AutomaticFeature public class SegfaultHandlerFeature implements Feature { 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 33515718b877..9cf959ddf1b5 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 @@ -35,6 +35,7 @@ import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; @@ -386,7 +387,7 @@ protected long decrementCount() { /** Translated from: jdk/src/share/native/sun/misc/NativeSignalHandler.c?v=Java_1.8.0_40_b10. */ @TargetClass(className = "sun.misc.NativeSignalHandler", onlyWith = JDK8OrEarlier.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) final class Target_sun_misc_NativeSignalHandler { /** diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/VmPrimsJVM.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/VmPrimsJVM.java index faa9cfdd7b15..54532080eb36 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/VmPrimsJVM.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/VmPrimsJVM.java @@ -24,16 +24,16 @@ */ package com.oracle.svm.core.posix; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CIntPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import com.oracle.svm.core.posix.headers.Socket; /** Native methods (and macros) from src/share/vm/prims/jvm.cpp translated to Java. */ -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public final class VmPrimsJVM { /* { Do not re-wrap commented-out code. @formatter:off */ /* { Allow names with underscores: @Checkstyle: stop */ 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/AArch64UContextRegisterDumper.java index 8f762e98d144..1c5c7a479ad2 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/AArch64UContextRegisterDumper.java @@ -25,8 +25,8 @@ package com.oracle.svm.core.posix.aarch64; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.WordFactory; @@ -38,7 +38,7 @@ import com.oracle.svm.core.posix.headers.Signal.mcontext_t; import com.oracle.svm.core.posix.headers.Signal.ucontext_t; -@Platforms(Platform.LINUX_AArch64.class) +@Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64.class) @AutomaticFeature class AArch64UContextRegisterDumperFeature implements Feature { @Override 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 index 669223d1eae0..c16eac7f8f13 100644 --- 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 @@ -25,9 +25,9 @@ package com.oracle.svm.core.posix.amd64; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; @@ -39,7 +39,7 @@ import com.oracle.svm.core.posix.headers.Signal.GregsPointer; import com.oracle.svm.core.posix.headers.Signal.ucontext_t; -@Platforms({Platform.LINUX_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) @AutomaticFeature class AMD64UContextRegisterDumperFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinJavaNetCloseImpl.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinJavaNetCloseImpl.java index 92ee9f9cfd71..eabbc7c05210 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinJavaNetCloseImpl.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinJavaNetCloseImpl.java @@ -25,8 +25,8 @@ package com.oracle.svm.core.posix.darwin; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; @@ -53,7 +53,7 @@ * operations. Where the implementations are identical between platforms, the shared code lives in * {@link PosixJavaNetClose}. */ -@Platforms({Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public final class DarwinJavaNetCloseImpl extends PosixJavaNetClose { protected DarwinJavaNetCloseImpl() { @@ -279,7 +279,7 @@ public int NET_Timeout0(int s, long timeoutArg, long currentTime) { /* } Allow names with underscores: Checkstyle: resume */ } -@Platforms({Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @AutomaticFeature class DarwinJavaNetCloseFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinJavaNetNetworkInterface.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinJavaNetNetworkInterface.java index 83e82ac84146..75641df728e9 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinJavaNetNetworkInterface.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinJavaNetNetworkInterface.java @@ -27,8 +27,8 @@ import java.net.SocketException; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; @@ -56,7 +56,7 @@ /* { Do not format quoted code: @formatter:off */ /* { Allow non-standard names: Checkstyle: stop */ -@Platforms(Platform.DARWIN.class) +@Platforms(DeprecatedPlatform.DARWIN_SUBSTITUTION.class) public class DarwinJavaNetNetworkInterface { /** Register the Darwin implementation. */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinNIOSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinNIOSubstitutions.java index 45b37c897986..1125659710dd 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinNIOSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinNIOSubstitutions.java @@ -26,13 +26,13 @@ import java.io.IOException; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CIntPointer; import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.annotate.Substitute; @@ -47,7 +47,7 @@ import com.oracle.svm.core.posix.headers.Unistd; import com.oracle.svm.core.posix.headers.darwin.DarwinEvent; -@Platforms({Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public final class DarwinNIOSubstitutions { /* Private constructor: No instances. */ @@ -56,7 +56,7 @@ private DarwinNIOSubstitutions() { /* { Do not reformat commented-out code: @formatter:off */ /** Translations of jdk/src/solaris/native/sun/nio/ch/KQueue.c?v=Java_1.8.0_40_b10. */ - @Platforms({Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(className = "sun.nio.ch.KQueue") static final class Target_sun_nio_ch_KQueue { @@ -218,7 +218,7 @@ static int poll(int kqfd, long address, int nevents) throws IOException { /* { Do not reformat commented-out code: @formatter:off */ /** Translations of jdk/src/macosx/native/sun/nio/ch/KQueueArrayWrapper.c?v=Java_1.8.0_40_b10. */ - @Platforms({Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(className = "sun.nio.ch.KQueueArrayWrapper", onlyWith = JDK8OrEarlier.class) static final class Target_sun_nio_ch_KQueueArrayWrapper { @@ -350,7 +350,7 @@ static void interrupt(int fd) throws IOException { /* { Do not reformat commented-out code: @formatter:off */ /** Translations of jdk/src/solaris/native/sun/nio/ch/KQueuePort.c?v=Java_1.8.0_40_b10. */ - @Platforms({Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @TargetClass(className = "sun.nio.ch.KQueuePort") static final class Target_sun_nio_ch_KQueuePort { 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/darwin/DarwinUContextRegisterDumper.java index 041e26fee646..a3bc8016fc7f 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/darwin/DarwinUContextRegisterDumper.java @@ -25,11 +25,11 @@ package com.oracle.svm.core.posix.darwin; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CLongPointer; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; @@ -40,7 +40,7 @@ import com.oracle.svm.core.posix.headers.Signal; import com.oracle.svm.core.posix.headers.Signal.ucontext_t; -@Platforms({Platform.DARWIN_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) @AutomaticFeature class DarwinUContextRegisterDumperFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Fcntl.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Fcntl.java index b88624efa34c..9e41d60775df 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Fcntl.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Fcntl.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -33,6 +32,7 @@ import org.graalvm.nativeimage.c.struct.CField; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import org.graalvm.word.SignedWord; @@ -125,7 +125,7 @@ public interface flock extends PointerBase { public static native int F_SETLKW(); @CConstant - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) public static native int O_DIRECT(); @CConstant @@ -153,7 +153,7 @@ public interface flock extends PointerBase { public static native short F_UNLCK(); @CConstant - @Platforms({Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public static native int F_NOCACHE(); @CFunction diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Ifaddrs.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Ifaddrs.java index 072c27b66949..0fc1b6b51a5e 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Ifaddrs.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Ifaddrs.java @@ -24,8 +24,6 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform.DARWIN; -import org.graalvm.nativeimage.Platform.LINUX; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.function.CFunction; @@ -33,6 +31,7 @@ import org.graalvm.nativeimage.c.struct.CPointerTo; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; // Allow methods with non-standard names: Checkstyle: stop @@ -40,7 +39,7 @@ /* * The definitions I need, manually translated from the C header file. */ -@Platforms({DARWIN.class, LINUX.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CContext(PosixDirectives.class) public class Ifaddrs { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Locale.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Locale.java index d114234d377f..3e79070e40d8 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Locale.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Locale.java @@ -24,12 +24,12 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; //Checkstyle: stop @@ -57,27 +57,27 @@ public class Locale { @CConstant public static native int LC_MESSAGES(); - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @CConstant public static native int LC_PAPER(); - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @CConstant public static native int LC_NAME(); - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @CConstant public static native int LC_ADDRESS(); - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @CConstant public static native int LC_TELEPHONE(); - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @CConstant public static native int LC_MEASUREMENT(); - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @CConstant public static native int LC_IDENTIFICATION(); diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetIf.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetIf.java index 59cbc5817ca2..12a900409b75 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetIf.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetIf.java @@ -24,9 +24,6 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platform.DARWIN; -import org.graalvm.nativeimage.Platform.LINUX; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -36,12 +33,13 @@ import org.graalvm.nativeimage.c.struct.CFieldAddress; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; // Allow methods with non-standard names: Checkstyle: stop /** The definitions I need, manually translated from the C header file. */ -@Platforms({DARWIN.class, LINUX.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CContext(PosixDirectives.class) public class NetIf { @@ -64,7 +62,7 @@ public class NetIf { public static native int IFNAMSIZ(); @CConstant - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) public static native int IFHWADDRLEN(); @CConstant @@ -72,7 +70,7 @@ public class NetIf { /* { Do not reformat commented out C code: @formatter:off */ @CContext(PosixDirectives.class) - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @CStruct(addStructKeyword = true) public interface ifreq extends PointerBase { // /* @@ -147,13 +145,13 @@ public interface ifreq extends PointerBase { @AllowWideningCast short ifr_flags(); - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @CField int ifr_ifindex(); NetIf.ifreq addressOf(int index); - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @CFieldAddress Socket.sockaddr ifr_hwaddr(); @@ -162,7 +160,7 @@ public interface ifreq extends PointerBase { /* { Do not reformat commented out C code: @formatter:off */ @CContext(PosixDirectives.class) - @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @CStruct(addStructKeyword = true) public interface ifconf extends PointerBase { // /* diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetIfDl.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetIfDl.java index 883c81140f37..322e105ed98c 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetIfDl.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetIfDl.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform.DARWIN; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.struct.AllowWideningCast; @@ -32,9 +31,10 @@ import org.graalvm.nativeimage.c.struct.CFieldAddress; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; -@Platforms({DARWIN.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @CContext(PosixDirectives.class) public class NetIfDl { /* { Do not format quoted code: @formatter:off */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Netdb.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Netdb.java index 94a77ca6bc5f..2a71aae0ccc0 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Netdb.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Netdb.java @@ -24,8 +24,6 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform.DARWIN; -import org.graalvm.nativeimage.Platform.LINUX; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -34,6 +32,7 @@ import org.graalvm.nativeimage.c.struct.CPointerTo; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; // Allow methods with non-standard names: Checkstyle: stop @@ -42,7 +41,7 @@ * The definitions I need, manually translated from the C header file /usr/include/netdb.h. */ -@Platforms({DARWIN.class, LINUX.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CContext(PosixDirectives.class) public final class Netdb { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetinetIn.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetinetIn.java index c48eaf4f978f..681f03ee159b 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetinetIn.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetinetIn.java @@ -24,8 +24,6 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform.DARWIN; -import org.graalvm.nativeimage.Platform.LINUX; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -35,12 +33,13 @@ import org.graalvm.nativeimage.c.struct.CFieldAddress; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; // Allow methods with non-standard names: Checkstyle: stop /** The definitions I need, manually translated from the C header file. */ -@Platforms({DARWIN.class, LINUX.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CContext(PosixDirectives.class) public class NetinetIn { @@ -85,7 +84,7 @@ private NetinetIn() { public static native int IPV6_TCLASS(); /** From linux/in.h, which exists only on Linux. */ - @Platforms({LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CConstant public static native int IP_MULTICAST_ALL(); @@ -98,19 +97,19 @@ private NetinetIn() { @CConstant public static native int IP_DROP_MEMBERSHIP(); - @Platforms({LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CConstant public static native int IPV6_ADD_MEMBERSHIP(); - @Platforms({LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CConstant public static native int IPV6_DROP_MEMBERSHIP(); - @Platforms({DARWIN.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @CConstant public static native int IPV6_JOIN_GROUP(); - @Platforms({DARWIN.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @CConstant public static native int IPV6_LEAVE_GROUP(); diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetinetTcp.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetinetTcp.java index ad95ce6a92d9..b11bb3d8a4a2 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetinetTcp.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/NetinetTcp.java @@ -24,17 +24,15 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.Platform.DARWIN; -import org.graalvm.nativeimage.Platform.LINUX; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; //Allow methods with non-standard names: Checkstyle: stop /** The definitions I need, manually translated from the C header file. */ -@Platforms({DARWIN.class, LINUX.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CContext(PosixDirectives.class) public class NetinetTcp { @@ -44,22 +42,22 @@ public class NetinetTcp { @CConstant public static native int TCP_KEEPINTVL(); - @Platforms({Platform.DARWIN.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) @CConstant public static native int TCP_KEEPALIVE(); - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CConstant public static native int TCP_KEEPIDLE(); @CConstant public static native int TCP_KEEPCNT(); - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CConstant public static native int SOL_TCP(); - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CConstant public static native int TCP_QUICKACK(); diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Poll.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Poll.java index 44dbd82c3333..1e5a108990b4 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Poll.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Poll.java @@ -24,8 +24,6 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform.DARWIN; -import org.graalvm.nativeimage.Platform.LINUX; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -34,6 +32,7 @@ import org.graalvm.nativeimage.c.struct.AllowWideningCast; import org.graalvm.nativeimage.c.struct.CField; import org.graalvm.nativeimage.c.struct.CStruct; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; //Allow methods with non-standard names: Checkstyle: stop @@ -42,7 +41,7 @@ * The definitions I need, manually translated from the C header file. */ -@Platforms({DARWIN.class, LINUX.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CContext(PosixDirectives.class) public class Poll { 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 40ad84e0b0e1..06cdb3ba0f20 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 @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -39,6 +38,7 @@ import org.graalvm.nativeimage.c.struct.CPointerTo; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.WordPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.PointerBase; @@ -93,7 +93,7 @@ public interface GregsPointer extends PointerBase { long read(int index); } - @Platforms({Platform.LINUX_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) @CEnum @CContext(PosixDirectives.class) public enum GregEnum { @@ -150,7 +150,7 @@ public interface ucontext_t extends PointerBase { } mcontext_t; */ @CFieldAddress("uc_mcontext.gregs") - @Platforms({Platform.LINUX_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) GregsPointer uc_mcontext_gregs(); /*- @@ -176,16 +176,16 @@ public interface ucontext_t extends PointerBase { }; */ @CFieldAddress("uc_mcontext") - @Platforms({Platform.LINUX_AArch64.class, InternalPlatform.LINUX_JNI_AArch64.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64.class, InternalPlatform.LINUX_JNI_AArch64.class}) mcontext_t uc_mcontext(); @CField("uc_mcontext") - @Platforms({Platform.DARWIN_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) MContext64 uc_mcontext64(); } - @Platforms({Platform.DARWIN_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) @CStruct(value = "__darwin_mcontext64", addStructKeyword = true) public interface MContext64 extends PointerBase { @@ -245,7 +245,7 @@ public interface MContext64 extends PointerBase { } @CStruct - @Platforms({Platform.LINUX_AArch64.class, InternalPlatform.LINUX_JNI_AArch64.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64.class, InternalPlatform.LINUX_JNI_AArch64.class}) public interface mcontext_t extends PointerBase { @CField long fault_address(); diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Socket.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Socket.java index b77c76a009db..d37a0c580a18 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Socket.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Socket.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -37,6 +36,7 @@ import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CIntPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import org.graalvm.word.SignedWord; import org.graalvm.word.UnsignedWord; @@ -67,7 +67,7 @@ public class Socket { public static native int AF_UNSPEC(); @CConstant - @Platforms(Platform.DARWIN.class) + @Platforms(DeprecatedPlatform.DARWIN_SUBSTITUTION.class) public static native int AF_LINK(); @CConstant @@ -82,7 +82,7 @@ public class Socket { @CStruct(addStructKeyword = true) public interface sockaddr extends PointerBase { - @Platforms(Platform.DARWIN.class) + @Platforms(DeprecatedPlatform.DARWIN_SUBSTITUTION.class) @CField @AllowWideningCast int sa_len(); @@ -200,14 +200,14 @@ public interface cmsghdr extends PointerBase { public static native long SIOCGIFBRDADDR(); @CConstant - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) public static native int SIOCGIFHWADDR(); @CConstant public static native long SIOCGIFNETMASK(); @CConstant - @Platforms(Platform.LINUX.class) + @Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) public static native int SIOCGIFINDEX(); @CConstant diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/SysParam.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/SysParam.java index df825a7dffe7..245416083a6b 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/SysParam.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/SysParam.java @@ -25,13 +25,12 @@ package com.oracle.svm.core.posix.headers; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.Platform.DARWIN; -import org.graalvm.nativeimage.Platform.LINUX; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.function.CFunction.Transition; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; -@Platforms({DARWIN.class, LINUX.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CContext(PosixDirectives.class) public class SysParam { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/SysSelect.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/SysSelect.java index 62b1bf3014c3..deb0d33920e0 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/SysSelect.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/SysSelect.java @@ -24,17 +24,16 @@ */ package com.oracle.svm.core.posix.headers; -import org.graalvm.nativeimage.Platform.DARWIN; -import org.graalvm.nativeimage.Platform.LINUX; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.function.CFunction.Transition; import org.graalvm.nativeimage.c.struct.CStruct; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; -@Platforms({DARWIN.class, LINUX.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CContext(PosixDirectives.class) public class SysSelect { /* ( Allow names with underscores: Checkstyle: stop */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/ZLib.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/ZLib.java index 924ae1c466eb..623542e02d53 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/ZLib.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/ZLib.java @@ -25,7 +25,6 @@ package com.oracle.svm.core.posix.headers; import org.graalvm.nativeimage.PinnedObject; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -39,6 +38,7 @@ import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CLongPointer; import org.graalvm.nativeimage.c.type.WordPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import org.graalvm.word.UnsignedWord; @@ -49,7 +49,7 @@ * * We only include this class in the JNI implementation in order to add -lz to the link line. */ -@Platforms({Platform.DARWIN.class, Platform.LINUX.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class, DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @CContext(PosixDirectives.class) @CLibrary("z") public class ZLib { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinEvent.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinEvent.java index 5d7ef9bc97d7..2baf411f39d8 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinEvent.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinEvent.java @@ -25,7 +25,6 @@ package com.oracle.svm.core.posix.headers.darwin; import org.graalvm.compiler.word.Word; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -34,6 +33,7 @@ import org.graalvm.nativeimage.c.struct.CFieldOffset; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.WordPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import com.oracle.svm.core.posix.headers.PosixDirectives; @@ -42,7 +42,7 @@ /* Allow underscores in names: Checkstyle: stop. */ @CContext(PosixDirectives.class) -@Platforms({Platform.DARWIN.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION.class}) public class DarwinEvent { /* { Do not reformat commented-out code: @formatter:off */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinInode64Suffix.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinInode64Suffix.java index 912e5707c7aa..5584f96afd56 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinInode64Suffix.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinInode64Suffix.java @@ -24,10 +24,10 @@ */ package com.oracle.svm.core.posix.headers.darwin; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; @@ -38,7 +38,7 @@ //Checkstyle: stop -@Platforms(Platform.DARWIN.class) +@Platforms(DeprecatedPlatform.DARWIN_SUBSTITUTION.class) class DarwinInode64Suffix { @TargetClass(com.oracle.svm.core.posix.headers.Dirent.class) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinNetinet6In6_var.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinNetinet6In6_var.java index b4d19a8efc4b..356c818cf706 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinNetinet6In6_var.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinNetinet6In6_var.java @@ -24,13 +24,13 @@ */ package com.oracle.svm.core.posix.headers.darwin; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; import org.graalvm.nativeimage.c.struct.CFieldAddress; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import com.oracle.svm.core.posix.headers.NetinetIn; @@ -39,7 +39,7 @@ /* { Do not format quoted code: @formatter:off */ /* { Allow non-standard names: Checkstyle: stop */ -@Platforms(Platform.DARWIN.class) +@Platforms(DeprecatedPlatform.DARWIN_SUBSTITUTION.class) @CContext(PosixDirectives.class) public class DarwinNetinet6In6_var { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSendfile.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSendfile.java index ffc5ce6854cc..0dba65701e42 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSendfile.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSendfile.java @@ -24,13 +24,13 @@ */ package com.oracle.svm.core.posix.headers.darwin; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.struct.CField; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CLongPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import com.oracle.svm.core.posix.headers.PosixDirectives; @@ -39,7 +39,7 @@ //Checkstyle: stop @CContext(PosixDirectives.class) -@Platforms(Platform.DARWIN.class) +@Platforms(DeprecatedPlatform.DARWIN_SUBSTITUTION.class) public class DarwinSendfile { @CStruct(addStructKeyword = true) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Linux64Suffix.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Linux64Suffix.java index 5df15dc06c77..ea1d5d104275 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Linux64Suffix.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Linux64Suffix.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.posix.headers.linux; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -32,6 +31,7 @@ import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CLongPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.Pointer; import org.graalvm.word.PointerBase; import org.graalvm.word.SignedWord; @@ -50,7 +50,7 @@ //Checkstyle: stop -@Platforms(Platform.LINUX.class) +@Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) class Linux64Suffix { @TargetClass(com.oracle.svm.core.posix.headers.Dirent.dirent.class) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxEPoll.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxEPoll.java index 7760ccf5a319..dea5707a871c 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxEPoll.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxEPoll.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.posix.headers.linux; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.function.CFunction; @@ -33,6 +32,7 @@ import org.graalvm.nativeimage.c.struct.CFieldOffset; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.WordPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import com.oracle.svm.core.posix.headers.PosixDirectives; @@ -40,7 +40,7 @@ /* Allow underscores in names: Checkstyle: stop. */ @CContext(PosixDirectives.class) -@Platforms({Platform.LINUX.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) public class LinuxEPoll { /* { Do not reformat commented-out code: @formatter:off */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxIn.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxIn.java index 30f29c35b137..0e0c4e77a89e 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxIn.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxIn.java @@ -28,16 +28,17 @@ import com.oracle.svm.core.posix.headers.NetinetIn; import com.oracle.svm.core.posix.headers.PosixDirectives; -import org.graalvm.nativeimage.Platform; + import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.struct.CField; import org.graalvm.nativeimage.c.struct.CFieldAddress; import org.graalvm.nativeimage.c.struct.CStruct; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; @CContext(PosixDirectives.class) -@Platforms(Platform.LINUX.class) +@Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) public class LinuxIn { // @formatter:off // struct ip_mreqn { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxSched.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxSched.java index dc376d34390f..043910a0b4db 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxSched.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxSched.java @@ -24,18 +24,18 @@ */ package com.oracle.svm.core.posix.headers.linux; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.function.CMacroInfo; import org.graalvm.nativeimage.c.struct.CStruct; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import com.oracle.svm.core.posix.headers.PosixDirectives; @CContext(PosixDirectives.class) -@Platforms({Platform.LINUX.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) public class LinuxSched { // Checkstyle: stop diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Mntent.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Mntent.java index d4342790056f..b05ae665a0fe 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Mntent.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/Mntent.java @@ -24,13 +24,13 @@ */ package com.oracle.svm.core.posix.headers.linux; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.struct.CField; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.word.PointerBase; import com.oracle.svm.core.posix.headers.PosixDirectives; @@ -42,7 +42,7 @@ * Definitions manually translated from the C header file mntent.h. */ @CContext(PosixDirectives.class) -@Platforms(Platform.LINUX.class) +@Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) public class Mntent { @CStruct(addStructKeyword = true) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxJavaNetCloseImpl.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxJavaNetCloseImpl.java index 15eb4d3261e6..c236dbc0582c 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxJavaNetCloseImpl.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxJavaNetCloseImpl.java @@ -25,8 +25,8 @@ package com.oracle.svm.core.posix.linux; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.type.CIntPointer; @@ -50,7 +50,7 @@ * operations. Where the implementations are identical between platforms, the shared code lives in * {@link PosixJavaNetClose}. */ -@Platforms({Platform.LINUX.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) public class LinuxJavaNetCloseImpl extends PosixJavaNetClose { protected LinuxJavaNetCloseImpl() { @@ -222,7 +222,7 @@ public int NET_Timeout0(int s, long timeoutArg, long currentTime) { /* } Allow names with underscores: Checkstyle: resume */ } -@Platforms({Platform.LINUX.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @AutomaticFeature class LinuxJavaNetCloseFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxJavaNetNetworkInterface.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxJavaNetNetworkInterface.java index 8cbb6eea37ed..c5f0dc314f95 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxJavaNetNetworkInterface.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxJavaNetNetworkInterface.java @@ -33,8 +33,8 @@ import java.util.regex.Pattern; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.CContext; @@ -63,7 +63,7 @@ /* { Do not format quoted code: @formatter:off */ /* { Allow non-standard names: Checkstyle: stop */ -@Platforms(Platform.LINUX.class) +@Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @CContext(PosixDirectives.class) public class LinuxJavaNetNetworkInterface { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxNIOSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxNIOSubstitutions.java index 597f726076fd..a0c4e71b9ee7 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxNIOSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxNIOSubstitutions.java @@ -28,13 +28,13 @@ 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.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CIntPointer; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import org.graalvm.word.WordFactory; @@ -51,7 +51,7 @@ import com.oracle.svm.core.posix.headers.Unistd; import com.oracle.svm.core.posix.headers.linux.LinuxEPoll; -@Platforms({Platform.LINUX.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) public final class LinuxNIOSubstitutions { /* Private constructor: No instances. */ @@ -60,7 +60,7 @@ private LinuxNIOSubstitutions() { /* { Do not reformat commented-out code: @formatter:off */ /** Translations of jdk/src/solaris/native/sun/nio/ch/EPoll.c?v=Java_1.8.0_40_b10. */ - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @TargetClass(className = "sun.nio.ch.EPoll") static final class Target_sun_nio_ch_EPoll { @@ -265,7 +265,7 @@ static int wait(int epfd, long address, int numfds, int timeout) throws IOExcept /* { Do not reformat commented-out code: @formatter:off */ /** Translations of jdk/src/solaris/native/sun/nio/ch/EPollArrayWrapper.c?v=Java_1.8.0_40_b10. */ - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @TargetClass(className = "sun.nio.ch.EPollArrayWrapper", onlyWith = JDK8OrEarlier.class) static final class Target_sun_nio_ch_EPollArrayWrapper { @@ -495,7 +495,7 @@ public void duringSetup(DuringSetupAccess access) { /* { Do not reformat commented-out code: @formatter:off */ /** Translations of jdk/src/solaris/native/sun/nio/ch/EPollPort.c?v=Java_1.8.0_40_b10. */ - @Platforms({Platform.LINUX.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class}) @TargetClass(className = "sun.nio.ch.EPollPort") static final class Target_sun_nio_ch_EPollPort { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSubstitutions.java index 9691ef6e16a1..999d267b1a74 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSubstitutions.java @@ -30,10 +30,10 @@ import static org.graalvm.nativeimage.UnmanagedMemory.calloc; import static org.graalvm.nativeimage.UnmanagedMemory.free; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.struct.SizeOf; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; @@ -73,7 +73,7 @@ public static String mapLibraryName(String libname) { } } -@Platforms(Platform.LINUX.class) +@Platforms(DeprecatedPlatform.LINUX_SUBSTITUTION.class) @TargetClass(java.lang.Runtime.class) @SuppressWarnings({"static-method"}) final class Target_java_lang_Runtime { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/headers/Errno.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/headers/Errno.java index 04eab094d85d..cb4b212c65d7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/headers/Errno.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/headers/Errno.java @@ -24,12 +24,12 @@ */ package com.oracle.svm.core.headers; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.UnsignedWord; @@ -102,7 +102,7 @@ public class Errno { /** Block device required. */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENOTBLK(); /** Device or resource busy. */ @@ -147,7 +147,7 @@ public class Errno { /** Text file busy. */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ETXTBSY(); /** File too large. */ @@ -184,7 +184,7 @@ public class Errno { /** Linux has no ENOTSUP error code. */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENOTSUP(); /** Resource deadlock would occur */ @@ -209,213 +209,213 @@ public class Errno { /** Too many symbolic links encountered */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ELOOP(); /** Operation would block */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EWOULDBLOCK(); /** No message of desired type */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENOMSG(); /** Identifier removed */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EIDRM(); /** Protocol error */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EPROTO(); /** Multihop attempted */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EMULTIHOP(); /** Not a data message */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EBADMSG(); /** Value too large for defined data type */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EOVERFLOW(); /** Too many users */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EUSERS(); /** Socket operation on non-socket */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENOTSOCK(); /** Destination address required */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EDESTADDRREQ(); /** Message too long */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EMSGSIZE(); /** Protocol wrong type for socket */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EPROTOTYPE(); /** Protocol not available */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENOPROTOOPT(); /** Protocol not supported */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EPROTONOSUPPORT(); /** Socket type not supported */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ESOCKTNOSUPPORT(); /** Operation not supported on transport endpoint */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EOPNOTSUPP(); /** Protocol family not supported */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EPFNOSUPPORT(); /** Address family not supported by protocol */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EAFNOSUPPORT(); /** Address already in use */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EADDRINUSE(); /** Cannot assign requested address */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EADDRNOTAVAIL(); /** Network is down */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENETDOWN(); /** Network is unreachable */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENETUNREACH(); /** Network dropped connection because of reset */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENETRESET(); /** Software caused connection abort */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ECONNABORTED(); /** Connection reset by peer */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ECONNRESET(); /** No buffer space available */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENOBUFS(); /** Transport endpoint is already connected */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EISCONN(); /** Transport endpoint is not connected */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENOTCONN(); /** Cannot send after transport endpoint shutdown */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ESHUTDOWN(); /** Too many references: cannot splice */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ETOOMANYREFS(); /** Connection timed out */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ETIMEDOUT(); /** Connection refused */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ECONNREFUSED(); /** Host is down */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EHOSTDOWN(); /** No route to host */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EHOSTUNREACH(); /** Operation already in progress */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EALREADY(); /** Operation now in progress */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EINPROGRESS(); /** Stale NFS file handle */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ESTALE(); /** Quota exceeded */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EDQUOT(); /** Operation Canceled */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ECANCELED(); /* for robust mutexes */ /** Owner died */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int EOWNERDEAD(); /** State not recoverable */ @CConstant - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native int ENOTRECOVERABLE(); /* @@ -439,6 +439,6 @@ public class Errno { public static native CCharPointer strerror(int errnum); @CFunction - @Platforms({Platform.LINUX.class, Platform.DARWIN.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) public static native CCharPointer strerror_r(int errnum, CCharPointer buf, UnsignedWord buflen); } 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 4bfda8d92cce..31c9437a2dbc 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 @@ -126,6 +126,7 @@ import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.Feature.OnAnalysisExitAccess; import org.graalvm.nativeimage.impl.CConstantValueSupport; +import org.graalvm.nativeimage.impl.DeprecatedPlatform; import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import org.graalvm.nativeimage.impl.SizeOfSupport; @@ -342,9 +343,9 @@ public static Platform defaultPlatform(ClassLoader classLoader) { boolean isJava8 = JavaVersionUtil.JAVA_SPEC == 8; if (hostedArchitecture instanceof AMD64) { if (currentOs == OS.LINUX) { - return isJava8 ? new InternalPlatform.LINUX_JNI_AMD64() : new Platform.LINUX_AMD64(); + return isJava8 ? new InternalPlatform.LINUX_JNI_AMD64() : new DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64(); } else if (currentOs == OS.DARWIN) { - return isJava8 ? new InternalPlatform.DARWIN_JNI_AMD64() : new Platform.DARWIN_AMD64(); + return isJava8 ? new InternalPlatform.DARWIN_JNI_AMD64() : new DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64(); } else if (currentOs == OS.WINDOWS) { return new Platform.WINDOWS_AMD64(); } else { @@ -352,7 +353,7 @@ public static Platform defaultPlatform(ClassLoader classLoader) { } } else if (hostedArchitecture instanceof AArch64) { if (OS.getCurrent() == OS.LINUX) { - return new Platform.LINUX_AArch64(); + return new DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64(); } else { throw VMError.shouldNotReachHere("Unsupported architecture/operating system: " + hostedArchitecture.getName() + "/" + currentOs.className); } From fd660909e9eb3de64549dd3be3bea11a163e825e Mon Sep 17 00:00:00 2001 From: Christian Wimmer Date: Tue, 8 Oct 2019 17:13:37 -0700 Subject: [PATCH 132/140] Remove JNI suffix from new LINUX and DARWIN platforms --- .../org.graalvm.nativeimage/snapshot.sigtest | 20 ++-- .../src/org/graalvm/nativeimage/Platform.java | 83 ++++++++++++++- .../nativeimage/impl/DeprecatedPlatform.java | 8 +- .../nativeimage/impl/InternalPlatform.java | 100 +----------------- .../svm/core/graal/llvm/LLVMFeature.java | 3 +- .../snippets/PosixAArch64VaListSnippets.java | 4 +- .../snippets/PosixAMD64VaListSnippets.java | 4 +- .../posix/PosixJavaLangSubstitutions.java | 4 +- .../svm/core/posix/PosixLogHandler.java | 2 +- .../core/posix/PosixNativeLibraryFeature.java | 10 +- .../PosixSubstrateOperatingSystemMXBean.java | 4 +- .../posix/PosixSystemPropertiesSupport.java | 2 +- .../com/oracle/svm/core/posix/PosixUtils.java | 2 +- .../posix/PosixVirtualMemoryProvider.java | 2 +- .../core/posix/SegfaultHandlerFeature.java | 4 +- .../svm/core/posix/SunMiscSubstitutions.java | 8 +- .../posix/UnmanagedMemorySupportImpl.java | 2 +- .../amd64/AMD64UContextRegisterDumper.java | 4 +- .../darwin/DarwinCoreFoundationUtils.java | 2 +- .../posix/darwin/DarwinImageHeapProvider.java | 2 +- .../posix/darwin/DarwinPhysicalMemory.java | 2 +- .../DarwinProcessPropertiesSupport.java | 2 +- .../darwin/DarwinStackOverflowSupport.java | 4 +- .../posix/darwin/DarwinSubstitutions.java | 6 +- .../darwin/DarwinSystemPropertiesSupport.java | 4 +- .../darwin/DarwinUContextRegisterDumper.java | 4 +- .../oracle/svm/core/posix/headers/Dlfcn.java | 6 +- .../svm/core/posix/headers/Langinfo.java | 6 +- .../oracle/svm/core/posix/headers/LibC.java | 2 +- .../oracle/svm/core/posix/headers/Paths.java | 2 +- .../core/posix/headers/PosixDirectives.java | 6 +- .../svm/core/posix/headers/Pthread.java | 6 +- .../oracle/svm/core/posix/headers/Sched.java | 6 +- .../oracle/svm/core/posix/headers/Signal.java | 23 ++-- .../oracle/svm/core/posix/headers/Spawn.java | 6 +- .../oracle/svm/core/posix/headers/Unistd.java | 4 +- .../posix/headers/darwin/CoreFoundation.java | 2 +- .../core/posix/headers/darwin/DarwinDyld.java | 2 +- .../posix/headers/darwin/DarwinErrno.java | 2 +- .../posix/headers/darwin/DarwinPthread.java | 2 +- .../posix/headers/darwin/DarwinSysctl.java | 2 +- .../posix/headers/darwin/DarwinSyslimits.java | 2 +- .../core/posix/headers/darwin/DarwinTime.java | 2 +- .../headers/darwin/DarwinVirtualMemory.java | 2 +- .../core/posix/headers/linux/LinuxErrno.java | 2 +- .../posix/headers/linux/LinuxPthread.java | 2 +- .../core/posix/headers/linux/LinuxTime.java | 2 +- .../posix/linux/LinuxImageHeapProvider.java | 2 +- .../core/posix/linux/LinuxPhysicalMemory.java | 2 +- .../linux/LinuxProcessPropertiesSupport.java | 2 +- .../linux/LinuxStackOverflowSupport.java | 4 +- .../core/posix/linux/LinuxSubstitutions.java | 2 +- .../linux/LinuxSystemPropertiesSupport.java | 4 +- .../posix/pthread/PthreadConditionUtils.java | 4 +- .../posix/pthread/PthreadVMLockSupport.java | 2 +- .../core/posix/thread/PosixJavaThreads.java | 4 +- .../svm/core/posix/thread/PosixVMThreads.java | 2 +- .../com/oracle/svm/core/ErrnoDirectives.java | 4 +- .../com/oracle/svm/core/headers/Errno.java | 94 ++++++++-------- .../src/com/oracle/svm/core/os/IsDefined.java | 4 +- .../svm/driver/NativeImageServerHelper.java | 8 +- .../svm/hosted/NativeImageGenerator.java | 5 +- .../hosted/image/NativeBootImageViaCC.java | 2 +- .../svm/hosted/jdk/JNIRegistrationUtil.java | 7 +- .../nfi/posix/PosixTruffleNFIFeature.java | 6 +- ...acle_truffle_nfi_impl_NFIContextPosix.java | 2 +- .../nativeapi/PolyglotNativeAPIFeature.java | 2 +- 67 files changed, 263 insertions(+), 280 deletions(-) diff --git a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest index 194b9b5a45e3..9377272c9aee 100644 --- a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest +++ b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest @@ -232,7 +232,7 @@ CLSS public static org.graalvm.nativeimage.Platform$DARWIN_AMD64 cons public init() intf org.graalvm.nativeimage.Platform$AMD64 intf org.graalvm.nativeimage.Platform$DARWIN -intf org.graalvm.nativeimage.impl.InternalPlatform$DARWIN_AND_JNI +intf org.graalvm.nativeimage.impl.InternalPlatform$DARWIN_JNI_AND_SUBSTITUTIONS supr java.lang.Object CLSS public final static org.graalvm.nativeimage.Platform$HOSTED_ONLY @@ -249,7 +249,7 @@ CLSS public final static org.graalvm.nativeimage.Platform$LINUX_AArch64 cons public init() intf org.graalvm.nativeimage.Platform$AArch64 intf org.graalvm.nativeimage.Platform$LINUX -intf org.graalvm.nativeimage.impl.InternalPlatform$LINUX_AND_JNI +intf org.graalvm.nativeimage.impl.InternalPlatform$LINUX_JNI_AND_SUBSTITUTIONS supr java.lang.Object CLSS public static org.graalvm.nativeimage.Platform$LINUX_AMD64 @@ -257,7 +257,7 @@ CLSS public static org.graalvm.nativeimage.Platform$LINUX_AMD64 cons public init() intf org.graalvm.nativeimage.Platform$AMD64 intf org.graalvm.nativeimage.Platform$LINUX -intf org.graalvm.nativeimage.impl.InternalPlatform$LINUX_AND_JNI +intf org.graalvm.nativeimage.impl.InternalPlatform$LINUX_JNI_AND_SUBSTITUTIONS supr java.lang.Object CLSS public abstract interface static org.graalvm.nativeimage.Platform$WINDOWS @@ -822,18 +822,14 @@ supr java.lang.Object CLSS abstract interface org.graalvm.nativeimage.hosted.package-info CLSS public abstract interface org.graalvm.nativeimage.impl.InternalPlatform -innr public abstract interface static DARWIN_AND_JNI -innr public abstract interface static DARWIN_JNI -innr public abstract interface static LINUX_AND_JNI -innr public abstract interface static LINUX_JNI -innr public static DARWIN_JNI_AMD64 -innr public static LINUX_JNI_AMD64 - -CLSS public abstract interface static org.graalvm.nativeimage.impl.InternalPlatform$DARWIN_AND_JNI +innr public abstract interface static DARWIN_JNI_AND_SUBSTITUTIONS +innr public abstract interface static LINUX_JNI_AND_SUBSTITUTIONS + +CLSS public abstract interface static org.graalvm.nativeimage.impl.InternalPlatform$DARWIN_JNI_AND_SUBSTITUTIONS outer org.graalvm.nativeimage.impl.InternalPlatform intf org.graalvm.nativeimage.Platform -CLSS public abstract interface static org.graalvm.nativeimage.impl.InternalPlatform$LINUX_AND_JNI +CLSS public abstract interface static org.graalvm.nativeimage.impl.InternalPlatform$LINUX_JNI_AND_SUBSTITUTIONS outer org.graalvm.nativeimage.impl.InternalPlatform intf org.graalvm.nativeimage.Platform diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java index dd90b817f05b..f83b350e633a 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java @@ -87,7 +87,6 @@ static boolean includedIn(Class platformGroup) { /* * The standard architectures that are supported. */ - /** * Supported architecture: x86 64-bit. * @@ -109,6 +108,23 @@ interface AArch64 extends Platform { /* * The standard operating systems that are supported. */ + /** + * Supported operating system: Linux. + * + * @since 19.0 + */ + interface LINUX extends InternalPlatform.PLATFORM_JNI { + + } + + /** + * Supported operating system: Darwin (MacOS). + * + * @since 19.0 + */ + interface DARWIN extends InternalPlatform.PLATFORM_JNI { + + } /** * Supported operating system: Windows. @@ -122,6 +138,71 @@ interface WINDOWS extends InternalPlatform.PLATFORM_JNI { /* * The standard leaf platforms, i.e., OS-architecture combinations that we support. */ + /** + * Supported leaf platform: Linux on x86 64-bit. + * + * @since 19.0 + */ + class LINUX_AMD64 implements LINUX, InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS, AMD64 { + + /** + * Instantiates a marker instance of this platform. + * + * @since 19.0 + */ + public LINUX_AMD64() { + } + + } + + /** + * Supported leaf platform: Linux on AArch64 64-bit. + * + * @since 19.0 + */ + final class LINUX_AArch64 implements LINUX, InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS, AArch64 { + + /** + * Instantiates a marker instance of this platform. + * + * @since 19.0 + */ + public LINUX_AArch64() { + } + + } + + /** + * Supported leaf platform: Darwin (MacOS) on x86 64-bit. + * + * @since 19.0 + */ + class DARWIN_AMD64 implements DARWIN, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS, AMD64 { + + /** + * Instantiates a marker instance of this platform. + * + * @since 19.0 + */ + public DARWIN_AMD64() { + } + } + + /** + * Supported leaf platform: Darwin (MacOS) on AArch 64-bit. + * + * @since 2.0 + */ + final class DARWIN_AArch64 implements DARWIN, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS, AArch64 { + + /** + * Instantiates a marker instance of this platform. + * + * @since 2.0 + */ + public DARWIN_AArch64() { + } + } /** * Supported leaf platform: Windows on x86 64-bit. diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/DeprecatedPlatform.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/DeprecatedPlatform.java index a291c6d2830a..96b4d69be70c 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/DeprecatedPlatform.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/DeprecatedPlatform.java @@ -65,7 +65,7 @@ interface DARWIN_SUBSTITUTION extends Platform { * * @since 19.0 */ - class LINUX_SUBSTITUTION_AMD64 implements DeprecatedPlatform.LINUX_SUBSTITUTION, InternalPlatform.LINUX_AND_JNI, Platform.AMD64 { + class LINUX_SUBSTITUTION_AMD64 implements DeprecatedPlatform.LINUX_SUBSTITUTION, InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS, Platform.AMD64 { /** * Instantiates a marker instance of this platform. @@ -81,7 +81,7 @@ public LINUX_SUBSTITUTION_AMD64() { * * @since 19.0 */ - class LINUX_SUBSTITUTION_AArch64 implements DeprecatedPlatform.LINUX_SUBSTITUTION, InternalPlatform.LINUX_AND_JNI, Platform.AArch64 { + class LINUX_SUBSTITUTION_AArch64 implements DeprecatedPlatform.LINUX_SUBSTITUTION, InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS, Platform.AArch64 { /** * Instantiates a marker instance of this platform. @@ -97,7 +97,7 @@ public LINUX_SUBSTITUTION_AArch64() { * * @since 19.0 */ - class DARWIN_SUBSTITUTION_AMD64 implements DeprecatedPlatform.DARWIN_SUBSTITUTION, InternalPlatform.DARWIN_AND_JNI, Platform.AMD64 { + class DARWIN_SUBSTITUTION_AMD64 implements DeprecatedPlatform.DARWIN_SUBSTITUTION, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS, Platform.AMD64 { /** * Instantiates a marker instance of this platform. @@ -113,7 +113,7 @@ public DARWIN_SUBSTITUTION_AMD64() { * * @since 2.0 */ - class DARWIN_SUBSTITUTION_AArch64 implements DeprecatedPlatform.DARWIN_SUBSTITUTION, InternalPlatform.DARWIN_AND_JNI, Platform.AArch64 { + class DARWIN_SUBSTITUTION_AArch64 implements DeprecatedPlatform.DARWIN_SUBSTITUTION, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS, Platform.AArch64 { /** * Instantiates a marker instance of this platform. diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/InternalPlatform.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/InternalPlatform.java index 027c2485766d..5a0df40650d7 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/InternalPlatform.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/InternalPlatform.java @@ -53,112 +53,22 @@ interface PLATFORM_JNI extends Platform { } /** - * Supported operating system: Linux platform that uses JNI based native JDK libraries. + * Temporary platform used to mark classes or methods that are used for LINUX and + * LINUX_SUBSTITUTION platforms. * * @since 19.0 */ - interface LINUX_JNI extends PLATFORM_JNI { - - } - - /** - * Supported operating system: Darwin (MacOS) platform that uses JNI based native JDK libraries. - * - * @since 19.0 - */ - interface DARWIN_JNI extends PLATFORM_JNI { - - } - - /** - * Temporary platform used to mark classes or methods that are used for LINUX and LINUX_JNI - * platforms. - * - * @since 19.0 - */ - interface LINUX_AND_JNI extends Platform { + interface LINUX_JNI_AND_SUBSTITUTIONS extends Platform { } /** * Temporary platform used to mark classes or methods that are used for DARWIN (MacOS) and - * DARWIN_JNI platforms. - * - * @since 19.0 - */ - interface DARWIN_AND_JNI extends Platform { - - } - - /** - * Temporary leaf platform that is used to mark classes or methods that are used for LINUX_JNI - * platforms. - * - * @since 19.0 - */ - class LINUX_JNI_AMD64 implements LINUX_JNI, LINUX_AND_JNI, Platform.AMD64 { - - /** - * Instantiates a marker instance of this platform. - * - * @since 19.0 - */ - public LINUX_JNI_AMD64() { - } - - } - - /** - * Temporary leaf platform that is used to mark classes or methods that are used for DARWIN_JNI - * platforms. + * DARWIN_SUBSTITUTION platforms. * * @since 19.0 */ - class DARWIN_JNI_AMD64 implements DARWIN_JNI, DARWIN_AND_JNI, Platform.AMD64 { - - /** - * Instantiates a marker instance of this platform. - * - * @since 19.0 - */ - public DARWIN_JNI_AMD64() { - } - - } - - /** - * Temporary leaf platform that is used to mark classes or methods that are used for LINUX_JNI - * platforms. - * - * @since 19.1.0 - */ - class LINUX_JNI_AArch64 implements LINUX_JNI, LINUX_AND_JNI, Platform.AArch64 { - - /** - * Instantiates a marker instance of this platform. - * - * @since 19.1.0 - */ - public LINUX_JNI_AArch64() { - } - - } - - /** - * Temporary leaf platform that is used to mark classes or methods that are used for DARWIN_JNI - * platforms. - * - * @since 19.1.0 - */ - class DARWIN_JNI_AArch64 implements DARWIN_JNI, DARWIN_AND_JNI, Platform.AArch64 { - - /** - * Instantiates a marker instance of this platform. - * - * @since 19.1.0 - */ - public DARWIN_JNI_AArch64() { - } + interface DARWIN_JNI_AND_SUBSTITUTIONS extends Platform { } } diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java index 151f481b01fb..a25e61ffb79e 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java @@ -82,7 +82,8 @@ @AutomaticFeature @CLibrary("m") -@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, InternalPlatform.LINUX_AND_JNI.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, + InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) public class LLVMFeature implements Feature, GraalFeature { private static HostedMethod personalityStub; diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAArch64VaListSnippets.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAArch64VaListSnippets.java index a871ddf96c14..480e8a59d920 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAArch64VaListSnippets.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAArch64VaListSnippets.java @@ -39,8 +39,6 @@ import org.graalvm.compiler.replacements.Snippets; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.impl.DeprecatedPlatform; -import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_JNI_AArch64; -import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_JNI_AArch64; import org.graalvm.word.Pointer; import com.oracle.svm.core.annotate.AutomaticFeature; @@ -54,7 +52,7 @@ class PosixAArch64VaListSnippetsFeature implements GraalFeature { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { return Platform.includedIn(DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64.class) || Platform.includedIn(DeprecatedPlatform.DARWIN_SUBSTITUTION_AArch64.class) || - Platform.includedIn(LINUX_JNI_AArch64.class) || Platform.includedIn(DARWIN_JNI_AArch64.class); + Platform.includedIn(Platform.LINUX_AArch64.class) || Platform.includedIn(Platform.DARWIN_AArch64.class); } @Override diff --git a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAMD64VaListSnippets.java b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAMD64VaListSnippets.java index 8439d40056ab..cf034e05b586 100644 --- a/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAMD64VaListSnippets.java +++ b/substratevm/src/com.oracle.svm.core.graal/src/com/oracle/svm/core/graal/snippets/PosixAMD64VaListSnippets.java @@ -39,8 +39,6 @@ import org.graalvm.compiler.replacements.Snippets; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.impl.DeprecatedPlatform; -import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_JNI_AMD64; -import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_JNI_AMD64; import org.graalvm.word.Pointer; import com.oracle.svm.core.annotate.AutomaticFeature; @@ -54,7 +52,7 @@ class PosixAMD64VaListSnippetsFeature implements GraalFeature { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { return Platform.includedIn(DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class) || Platform.includedIn(DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class) || - Platform.includedIn(LINUX_JNI_AMD64.class) || Platform.includedIn(DARWIN_JNI_AMD64.class); + Platform.includedIn(Platform.LINUX_AMD64.class) || Platform.includedIn(Platform.DARWIN_AMD64.class); } @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaLangSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaLangSubstitutions.java index 1657ea58cf11..170dd9e98810 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaLangSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixJavaLangSubstitutions.java @@ -199,7 +199,7 @@ public String apply(TargetClass annotation) { } @TargetClass(classNameProvider = ProcessNameProvider.class) -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) final class Target_java_lang_UNIXProcess { // The reaper thread pool and thread groups (currently) confuse the analysis, so we launch @@ -352,7 +352,7 @@ final class Target_java_lang_ProcessBuilder_NullOutputStream { } @TargetClass(java.lang.System.class) -@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.DARWIN_JNI.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, Platform.LINUX.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.DARWIN.class}) final class Target_java_lang_System { @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)// diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLogHandler.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLogHandler.java index 9a852f0b66ae..f66e2e9782db 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLogHandler.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLogHandler.java @@ -39,7 +39,7 @@ import com.oracle.svm.core.posix.headers.LibC; @AutomaticFeature -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) class PosixLogHandlerFeature implements Feature { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java index 2bf7ae91f50a..f254ed141871 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java @@ -51,7 +51,7 @@ import com.oracle.svm.core.posix.headers.darwin.DarwinSyslimits; @AutomaticFeature -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) class PosixNativeLibraryFeature implements Feature { @Override public void afterRegistration(AfterRegistrationAccess access) { @@ -82,7 +82,7 @@ public boolean initializeBuiltinLibraries() { Resource.rlimit rlp = StackValue.get(Resource.rlimit.class); if (Resource.getrlimit(Resource.RLIMIT_NOFILE(), rlp) == 0) { UnsignedWord newValue = rlp.rlim_max(); - if (Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class)) { + if (Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class)) { // On Darwin, getrlimit may return RLIM_INFINITY for rlim_max, but then OPEN_MAX // must be used for setrlimit or it will fail with errno EINVAL. newValue = WordFactory.unsigned(DarwinSyslimits.OPEN_MAX()); @@ -179,8 +179,8 @@ public boolean load() { private boolean doLoad() { // Make sure the jvm.lib is available for linking // Need a better place to put this. - if (Platform.includedIn(InternalPlatform.LINUX_JNI.class) || - Platform.includedIn(InternalPlatform.DARWIN_JNI.class)) { + if (Platform.includedIn(Platform.LINUX.class) || + Platform.includedIn(Platform.DARWIN.class)) { Jvm.initialize(); } @@ -210,7 +210,7 @@ public PointerBase findSymbol(String name) { } } -@Platforms({InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) +@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) @TargetClass(className = "java.io.UnixFileSystem") final class Target_java_io_UnixFileSystem_JNI { @Alias diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSubstrateOperatingSystemMXBean.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSubstrateOperatingSystemMXBean.java index ca9b149be55f..b1e4560468a2 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSubstrateOperatingSystemMXBean.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSubstrateOperatingSystemMXBean.java @@ -36,7 +36,7 @@ import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.impl.InternalPlatform; -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) class PosixSubstrateOperatingSystemMXBean extends SubstrateOperatingSystemMXBean { /** @@ -62,7 +62,7 @@ public long getProcessCpuTime() { } -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) @AutomaticFeature class PosixSubstrateOperatingSystemMXBeanFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSystemPropertiesSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSystemPropertiesSupport.java index efa9e7c21ca8..6d7720cad1a1 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSystemPropertiesSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixSystemPropertiesSupport.java @@ -38,7 +38,7 @@ import com.oracle.svm.core.posix.headers.Pwd.passwd; import com.oracle.svm.core.posix.headers.Unistd; -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) public abstract class PosixSystemPropertiesSupport extends SystemPropertiesSupport { /* diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java index 1f301b5e4b16..4367042c0c54 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java @@ -72,7 +72,7 @@ import com.oracle.svm.core.posix.headers.Wait; import com.oracle.svm.core.util.VMError; -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) public class PosixUtils { static String setLocale(String category, String locale) { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixVirtualMemoryProvider.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixVirtualMemoryProvider.java index 5ec900432dbc..4db5b8832535 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixVirtualMemoryProvider.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixVirtualMemoryProvider.java @@ -59,7 +59,7 @@ import com.oracle.svm.core.os.VirtualMemoryProvider; @AutomaticFeature -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) class PosixVirtualMemoryProviderFeature implements Feature { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java index ea4d9f613408..6ca9d437a6f3 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/SegfaultHandlerFeature.java @@ -28,6 +28,7 @@ import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.LogHandler; +import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.function.CEntryPoint; @@ -35,7 +36,6 @@ import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.impl.DeprecatedPlatform; -import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.annotate.AutomaticFeature; @@ -56,7 +56,7 @@ import com.oracle.svm.core.posix.headers.Signal.ucontext_t; import com.oracle.svm.core.thread.VMThreads; -@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, Platform.LINUX_AMD64.class, Platform.DARWIN_AMD64.class}) @AutomaticFeature public class SegfaultHandlerFeature implements Feature { 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 9cf959ddf1b5..a4d5c2efa0a7 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 @@ -68,7 +68,7 @@ public String apply(TargetClass annotation) { } } -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) @TargetClass(classNameProvider = Package_jdk_internal_misc.class, className = "Signal") final class Target_jdk_internal_misc_Signal { @@ -107,7 +107,7 @@ private static void raise0(int signalNumber) { } /** Support for Target_sun_misc_Signal. */ -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) final class Util_jdk_internal_misc_Signal { /** A thread to dispatch signals as they are raised. */ @@ -413,7 +413,7 @@ static void handle0(int sig, long f) { } } -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) @AutomaticFeature class IgnoreSIGPIPEFeature implements Feature { @@ -441,7 +441,7 @@ public void run() { } } -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) @TargetClass(className = "jdk.internal.misc.VM", onlyWith = JDK11OrLater.class) final class Target_jdk_internal_misc_VM { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/UnmanagedMemorySupportImpl.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/UnmanagedMemorySupportImpl.java index e0f4665795ab..80299f313c7a 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/UnmanagedMemorySupportImpl.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/UnmanagedMemorySupportImpl.java @@ -64,7 +64,7 @@ public void free(PointerBase ptr) { } @AutomaticFeature -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) class UnmanagedMemoryFeature implements Feature { @Override public void afterRegistration(AfterRegistrationAccess access) { 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 index c16eac7f8f13..8fcaae43e1d8 100644 --- 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 @@ -25,10 +25,10 @@ package com.oracle.svm.core.posix.amd64; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.impl.DeprecatedPlatform; -import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.SubstrateUtil; @@ -39,7 +39,7 @@ import com.oracle.svm.core.posix.headers.Signal.GregsPointer; import com.oracle.svm.core.posix.headers.Signal.ucontext_t; -@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) +@Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, Platform.LINUX_AMD64.class}) @AutomaticFeature class AMD64UContextRegisterDumperFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinCoreFoundationUtils.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinCoreFoundationUtils.java index ffbcc206eebf..505e73222c8f 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinCoreFoundationUtils.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinCoreFoundationUtils.java @@ -32,7 +32,7 @@ import com.oracle.svm.core.posix.headers.darwin.CoreFoundation; -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) public final class DarwinCoreFoundationUtils { private DarwinCoreFoundationUtils() { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinImageHeapProvider.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinImageHeapProvider.java index 2e9cca4ebfcf..5e2b616c91e7 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinImageHeapProvider.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinImageHeapProvider.java @@ -50,7 +50,7 @@ import com.oracle.svm.core.util.UnsignedUtils; @AutomaticFeature -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) class DarwinImageHeapProviderFeature implements Feature { @Override public void duringSetup(DuringSetupAccess access) { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinPhysicalMemory.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinPhysicalMemory.java index 5389f7ef37de..c75267a95f0a 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinPhysicalMemory.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinPhysicalMemory.java @@ -44,7 +44,7 @@ import com.oracle.svm.core.posix.headers.darwin.DarwinSysctl; import com.oracle.svm.core.util.VMError; -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) class DarwinPhysicalMemory extends PhysicalMemory { static class PhysicalMemorySupportImpl implements PhysicalMemorySupport { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinProcessPropertiesSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinProcessPropertiesSupport.java index 99581ebb062a..5cea23c17018 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinProcessPropertiesSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinProcessPropertiesSupport.java @@ -41,7 +41,7 @@ import com.oracle.svm.core.posix.headers.darwin.DarwinDyld; import com.oracle.svm.core.util.VMError; -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) public class DarwinProcessPropertiesSupport extends PosixProcessPropertiesSupport { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinStackOverflowSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinStackOverflowSupport.java index d28cfafacd28..0eebbbee35bb 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinStackOverflowSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinStackOverflowSupport.java @@ -36,7 +36,7 @@ import com.oracle.svm.core.posix.headers.darwin.DarwinPthread; import com.oracle.svm.core.stack.StackOverflowCheck; -@Platforms({InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) class DarwinStackOverflowSupport implements StackOverflowCheck.OSSupport { @Uninterruptible(reason = "Called while thread is being attached to the VM, i.e., when the thread state is not yet set up.") @@ -49,7 +49,7 @@ public UnsignedWord lookupStackEnd() { } } -@Platforms({InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) @AutomaticFeature class DarwinStackOverflowSupportFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSubstitutions.java index 5dea043b0c1e..1c6f9ade134c 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSubstitutions.java @@ -43,7 +43,7 @@ import com.oracle.svm.core.posix.headers.Time.timezone; import com.oracle.svm.core.posix.headers.darwin.DarwinTime.MachTimebaseInfo; -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) @TargetClass(java.lang.System.class) final class Target_java_lang_System { @@ -86,7 +86,7 @@ public static String mapLibraryName(String libname) { } /** Additional static-like fields for {@link Target_java_lang_System}. */ -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) final class Util_java_lang_System { boolean timeBaseValid = false; boolean fastTime = false; @@ -97,7 +97,7 @@ final class Util_java_lang_System { } } -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) @AutomaticFeature class DarwinSubsitutionsFeature implements Feature { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSystemPropertiesSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSystemPropertiesSupport.java index 6fd4f780aab7..cba9f466dc82 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSystemPropertiesSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSystemPropertiesSupport.java @@ -44,7 +44,7 @@ import com.oracle.svm.core.posix.headers.darwin.CoreFoundation; import com.oracle.svm.core.posix.headers.darwin.CoreFoundation.CFStringRef; -@Platforms({InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) public class DarwinSystemPropertiesSupport extends PosixSystemPropertiesSupport { @Override @@ -99,7 +99,7 @@ protected String osVersionValue() { } } -@Platforms({InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) @AutomaticFeature class DarwinSystemPropertiesFeature implements Feature { @Override 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/darwin/DarwinUContextRegisterDumper.java index a3bc8016fc7f..a256fba7a12f 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/darwin/DarwinUContextRegisterDumper.java @@ -25,12 +25,12 @@ package com.oracle.svm.core.posix.darwin; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CLongPointer; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.impl.DeprecatedPlatform; -import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.WordFactory; import com.oracle.svm.core.SubstrateUtil; @@ -40,7 +40,7 @@ import com.oracle.svm.core.posix.headers.Signal; import com.oracle.svm.core.posix.headers.Signal.ucontext_t; -@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) +@Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, Platform.DARWIN_AMD64.class}) @AutomaticFeature class DarwinUContextRegisterDumperFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Dlfcn.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Dlfcn.java index aa8b81c0be3c..04a194fd9081 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Dlfcn.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Dlfcn.java @@ -32,8 +32,8 @@ import org.graalvm.nativeimage.c.struct.CField; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.CCharPointer; -import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_AND_JNI; -import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_AND_JNI; +import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS; +import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS; import org.graalvm.word.Pointer; import org.graalvm.word.PointerBase; import org.graalvm.word.WordBase; @@ -43,7 +43,7 @@ /** * Definitions manually translated from the C header file dlfcn.h. */ -@Platforms({DARWIN_AND_JNI.class, LINUX_AND_JNI.class}) +@Platforms({DARWIN_JNI_AND_SUBSTITUTIONS.class, LINUX_JNI_AND_SUBSTITUTIONS.class}) @CContext(PosixDirectives.class) @CLibrary("dl") public class Dlfcn { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Langinfo.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Langinfo.java index a360fc380661..34d5f0bf291e 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Langinfo.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Langinfo.java @@ -28,11 +28,11 @@ import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.type.CCharPointer; -import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_AND_JNI; -import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_AND_JNI; +import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS; +import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS; /** Definitions hand-translated from . */ -@Platforms({DARWIN_AND_JNI.class, LINUX_AND_JNI.class}) +@Platforms({DARWIN_JNI_AND_SUBSTITUTIONS.class, LINUX_JNI_AND_SUBSTITUTIONS.class}) @CContext(PosixDirectives.class) public class Langinfo { /* Allow non-standard names: Checkstyle: stop */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/LibC.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/LibC.java index 4bd5ccd6cbf3..cd5e5f13ef29 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/LibC.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/LibC.java @@ -40,7 +40,7 @@ /** * Basic functions from the standard C library that we require to be present on all Posix platforms. */ -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) public class LibC { /** diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Paths.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Paths.java index e33699e2b4e5..f325fbdd4994 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Paths.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Paths.java @@ -34,7 +34,7 @@ @CContext(PosixDirectives.class) public class Paths { - @Platforms(InternalPlatform.LINUX_AND_JNI.class) + @Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) @CConstant public static native String _PATH_VARTMP(); } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/PosixDirectives.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/PosixDirectives.java index e3cfd591600c..a951b1d08b76 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/PosixDirectives.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/PosixDirectives.java @@ -104,15 +104,15 @@ public class PosixDirectives implements CContext.Directives { @Override public boolean isInConfiguration() { - return Platform.includedIn(InternalPlatform.LINUX_AND_JNI.class) || Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class); + return Platform.includedIn(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) || Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class); } @Override public List getHeaderFiles() { List result = new ArrayList<>(Arrays.asList(commonLibs)); - if (Platform.includedIn(InternalPlatform.LINUX_AND_JNI.class)) { + if (Platform.includedIn(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class)) { result.addAll(Arrays.asList(linuxLibs)); - } else if (Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class)) { + } else if (Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class)) { result.addAll(Arrays.asList(darwinLibs)); } else { throw VMError.shouldNotReachHere("Unsupported OS"); diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Pthread.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Pthread.java index 060b93eebf7c..313f9e9ca88b 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Pthread.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Pthread.java @@ -33,8 +33,8 @@ import org.graalvm.nativeimage.c.struct.CPointerTo; import org.graalvm.nativeimage.c.struct.CStruct; import org.graalvm.nativeimage.c.type.WordPointer; -import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_AND_JNI; -import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_AND_JNI; +import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS; +import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS; import org.graalvm.word.PointerBase; import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordBase; @@ -50,7 +50,7 @@ * Definitions manually translated from the C header file pthread.h. */ @CContext(PosixDirectives.class) -@Platforms({DARWIN_AND_JNI.class, LINUX_AND_JNI.class}) +@Platforms({DARWIN_JNI_AND_SUBSTITUTIONS.class, LINUX_JNI_AND_SUBSTITUTIONS.class}) @CLibrary("pthread") public class Pthread { 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 9fc4b365da5d..2b67284769dd 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 @@ -27,8 +27,8 @@ import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.function.CFunction; -import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_AND_JNI; -import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_AND_JNI; +import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS; +import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS; //Allow methods with non-standard names: Checkstyle: stop @@ -36,7 +36,7 @@ * The definitions I need, manually translated from the C header file . */ -@Platforms({DARWIN_AND_JNI.class, LINUX_AND_JNI.class}) +@Platforms({DARWIN_JNI_AND_SUBSTITUTIONS.class, LINUX_JNI_AND_SUBSTITUTIONS.class}) @CContext(PosixDirectives.class) public class Sched { 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 06cdb3ba0f20..a0d1361b1083 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 @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.posix.headers; +import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -87,13 +88,13 @@ public interface siginfo_t extends PointerBase { /* Fields unused */ } - @Platforms(InternalPlatform.LINUX_AND_JNI.class) + @Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) @CPointerTo(nameOfCType = "long long int") public interface GregsPointer extends PointerBase { long read(int index); } - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, Platform.LINUX_AMD64.class}) @CEnum @CContext(PosixDirectives.class) public enum GregEnum { @@ -125,7 +126,7 @@ public enum GregEnum { public native int getCValue(); } - @Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) + @Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) @CStruct public interface ucontext_t extends PointerBase { /*- @@ -150,7 +151,7 @@ public interface ucontext_t extends PointerBase { } mcontext_t; */ @CFieldAddress("uc_mcontext.gregs") - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, InternalPlatform.LINUX_JNI_AMD64.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64.class, Platform.LINUX_AMD64.class}) GregsPointer uc_mcontext_gregs(); /*- @@ -176,16 +177,16 @@ public interface ucontext_t extends PointerBase { }; */ @CFieldAddress("uc_mcontext") - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64.class, InternalPlatform.LINUX_JNI_AArch64.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64.class, Platform.LINUX_AArch64.class}) mcontext_t uc_mcontext(); @CField("uc_mcontext") - @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, Platform.DARWIN_AMD64.class}) MContext64 uc_mcontext64(); } - @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, InternalPlatform.DARWIN_JNI_AMD64.class}) + @Platforms({DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64.class, Platform.DARWIN_AMD64.class}) @CStruct(value = "__darwin_mcontext64", addStructKeyword = true) public interface MContext64 extends PointerBase { @@ -245,7 +246,7 @@ public interface MContext64 extends PointerBase { } @CStruct - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64.class, InternalPlatform.LINUX_JNI_AArch64.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION_AArch64.class, Platform.LINUX_AArch64.class}) public interface mcontext_t extends PointerBase { @CField long fault_address(); @@ -270,7 +271,7 @@ public interface AdvancedSignalDispatcher extends CFunctionPointer { void dispatch(int signum, siginfo_t siginfo, WordPointer opaque); } - @Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) + @Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) @CConstant public static native int SA_SIGINFO(); @@ -349,7 +350,7 @@ public enum SignalEnum { public native int getCValue(); } - @Platforms(InternalPlatform.LINUX_AND_JNI.class) + @Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) @CEnum @CContext(PosixDirectives.class) public enum LinuxSignalEnum { @@ -360,7 +361,7 @@ public enum LinuxSignalEnum { public native int getCValue(); } - @Platforms(InternalPlatform.DARWIN_AND_JNI.class) + @Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) @CEnum @CContext(PosixDirectives.class) public enum DarwinSignalEnum { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Spawn.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Spawn.java index b82487db7ad1..51ca54f73746 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Spawn.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Spawn.java @@ -32,12 +32,12 @@ import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CCharPointerPointer; import org.graalvm.nativeimage.c.type.CShortPointer; -import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_AND_JNI; -import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_AND_JNI; +import org.graalvm.nativeimage.impl.InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS; +import org.graalvm.nativeimage.impl.InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS; import org.graalvm.word.PointerBase; /** Definitions hand-translated from . */ -@Platforms({DARWIN_AND_JNI.class, LINUX_AND_JNI.class}) +@Platforms({DARWIN_JNI_AND_SUBSTITUTIONS.class, LINUX_JNI_AND_SUBSTITUTIONS.class}) @CContext(PosixDirectives.class) public class Spawn { /* Allow lower-case type names: Checkstyle: stop. */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Unistd.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Unistd.java index dc85951de03c..447e4b21fca2 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Unistd.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/Unistd.java @@ -150,11 +150,11 @@ public class Unistd { public static native int _SC_NPROCESSORS_ONLN(); @CConstant - @Platforms(InternalPlatform.LINUX_AND_JNI.class) + @Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) public static native int _SC_PHYS_PAGES(); @CConstant - @Platforms(InternalPlatform.DARWIN_AND_JNI.class) + @Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) public static native int _CS_DARWIN_USER_TEMP_DIR(); @CFunction diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/CoreFoundation.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/CoreFoundation.java index 248ff53f8ab4..5566dcc5a7eb 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/CoreFoundation.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/CoreFoundation.java @@ -41,7 +41,7 @@ */ @CContext(PosixDirectives.class) @CLibrary("-framework CoreFoundation") -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) public class CoreFoundation { public interface CFStringRef extends PointerBase { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinDyld.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinDyld.java index fac55e118615..b1313e4d1a3d 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinDyld.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinDyld.java @@ -36,7 +36,7 @@ // { Allow names with underscores: Checkstyle: stop /** Declarations of method from . */ -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) @CContext(PosixDirectives.class) public class DarwinDyld { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinErrno.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinErrno.java index 528e5e043180..8701017df36b 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinErrno.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinErrno.java @@ -36,7 +36,7 @@ //Checkstyle: stop -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) class DarwinErrno { @TargetClass(Errno.class) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinPthread.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinPthread.java index c3ab750190d3..97c0ea606de0 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinPthread.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinPthread.java @@ -38,7 +38,7 @@ import com.oracle.svm.core.posix.headers.Pthread; @CContext(PosixDirectives.class) -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) @CLibrary("pthread") public class DarwinPthread { /* { Allow names with underscores: Checkstyle: stop */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSysctl.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSysctl.java index be4b431b7b9b..5ae2b8adf155 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSysctl.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSysctl.java @@ -32,7 +32,7 @@ import org.graalvm.nativeimage.impl.InternalPlatform; /** Declarations of method from . */ -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) @CContext(PosixDirectives.class) public class DarwinSysctl { // { Allow names with underscores: Checkstyle: stop diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSyslimits.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSyslimits.java index 97351a186ef5..3ba931507019 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSyslimits.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinSyslimits.java @@ -32,7 +32,7 @@ import com.oracle.svm.core.posix.headers.PosixDirectives; /** Declarations of method from . */ -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) @CContext(PosixDirectives.class) public class DarwinSyslimits { // { Allow names with underscores: Checkstyle: stop diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinTime.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinTime.java index 55bbdc128919..e5ed49e50822 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinTime.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinTime.java @@ -37,7 +37,7 @@ //Checkstyle: stop @CContext(PosixDirectives.class) -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) public class DarwinTime { @CStruct("struct mach_timebase_info") diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinVirtualMemory.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinVirtualMemory.java index afac3fcb21cc..f5423a0cf9ac 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinVirtualMemory.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/darwin/DarwinVirtualMemory.java @@ -37,7 +37,7 @@ //Checkstyle: stop @CContext(PosixDirectives.class) -@Platforms(InternalPlatform.DARWIN_AND_JNI.class) +@Platforms(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) public class DarwinVirtualMemory { @CFunction(transition = CFunction.Transition.NO_TRANSITION) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxErrno.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxErrno.java index 04362ea1a0dc..70c3d8d76171 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxErrno.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxErrno.java @@ -36,7 +36,7 @@ //Checkstyle: stop -@Platforms(InternalPlatform.LINUX_AND_JNI.class) +@Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) class LinuxErrno { @TargetClass(Errno.class) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxPthread.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxPthread.java index c7b9704d0eeb..ccb7477be803 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxPthread.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxPthread.java @@ -36,7 +36,7 @@ @CContext(PosixDirectives.class) @CLibrary("pthread") -@Platforms(InternalPlatform.LINUX_AND_JNI.class) +@Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) public class LinuxPthread { /* { Allow names with underscores: Checkstyle: stop */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxTime.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxTime.java index a26dba02bd83..8a740b7eaa55 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxTime.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers/linux/LinuxTime.java @@ -40,7 +40,7 @@ * Definitions manually translated from the C header file sys/time.h. */ @CContext(PosixDirectives.class) -@Platforms(InternalPlatform.LINUX_AND_JNI.class) +@Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) public class LinuxTime extends Time { /** Monotonic system-wide clock. */ diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java index ec0b69319a6c..10cd68e2a9c5 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java @@ -79,7 +79,7 @@ import jdk.vm.ci.code.MemoryBarriers; @AutomaticFeature -@Platforms(InternalPlatform.LINUX_AND_JNI.class) +@Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) class LinuxImageHeapProviderFeature implements Feature { @Override public void duringSetup(DuringSetupAccess access) { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxPhysicalMemory.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxPhysicalMemory.java index 44f2aa7dc161..2727eb8ca233 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxPhysicalMemory.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxPhysicalMemory.java @@ -45,7 +45,7 @@ import com.oracle.svm.core.thread.VMOperation; import com.oracle.svm.core.util.UnsignedUtils; -@Platforms(InternalPlatform.LINUX_AND_JNI.class) +@Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) class LinuxPhysicalMemory extends PhysicalMemory { static class PhysicalMemorySupportImpl implements PhysicalMemorySupport { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxProcessPropertiesSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxProcessPropertiesSupport.java index f55847bedc9d..4d80d70c44a8 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxProcessPropertiesSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxProcessPropertiesSupport.java @@ -33,7 +33,7 @@ import com.oracle.svm.core.annotate.AutomaticFeature; import com.oracle.svm.core.posix.PosixProcessPropertiesSupport; -@Platforms(InternalPlatform.LINUX_AND_JNI.class) +@Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) public class LinuxProcessPropertiesSupport extends PosixProcessPropertiesSupport { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxStackOverflowSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxStackOverflowSupport.java index 8b86d52a322d..17b27c0a4001 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxStackOverflowSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxStackOverflowSupport.java @@ -38,7 +38,7 @@ import com.oracle.svm.core.posix.headers.Pthread; import com.oracle.svm.core.stack.StackOverflowCheck; -@Platforms({InternalPlatform.LINUX_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class}) class LinuxStackOverflowSupport implements StackOverflowCheck.OSSupport { @Uninterruptible(reason = "Called while thread is being attached to the VM, i.e., when the thread state is not yet set up.") @@ -67,7 +67,7 @@ public UnsignedWord lookupStackEnd() { } } -@Platforms({InternalPlatform.LINUX_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class}) @AutomaticFeature class LinuxStackOverflowSupportFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSubstitutions.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSubstitutions.java index 999d267b1a74..f5880ab7e0de 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSubstitutions.java @@ -47,7 +47,7 @@ import com.oracle.svm.core.posix.headers.Unistd; import com.oracle.svm.core.posix.headers.linux.LinuxSched; -@Platforms(InternalPlatform.LINUX_AND_JNI.class) +@Platforms(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) @TargetClass(java.lang.System.class) final class Target_java_lang_System { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSystemPropertiesSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSystemPropertiesSupport.java index 953793dc2858..d11e5cee9cf0 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSystemPropertiesSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSystemPropertiesSupport.java @@ -37,7 +37,7 @@ import com.oracle.svm.core.posix.headers.Utsname; import org.graalvm.nativeimage.impl.InternalPlatform; -@Platforms({InternalPlatform.LINUX_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class}) public class LinuxSystemPropertiesSupport extends PosixSystemPropertiesSupport { @Override @@ -55,7 +55,7 @@ protected String osVersionValue() { } } -@Platforms({InternalPlatform.LINUX_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class}) @AutomaticFeature class LinuxSystemPropertiesFeature implements Feature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadConditionUtils.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadConditionUtils.java index be9cbaf4c86a..352fba55c727 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadConditionUtils.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/pthread/PthreadConditionUtils.java @@ -50,7 +50,7 @@ public static int initCondition(Pthread.pthread_cond_t cond) { return status; } - if (Platform.includedIn(InternalPlatform.LINUX_AND_JNI.class)) { + if (Platform.includedIn(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class)) { /* * On Linux, CLOCK_MONOTONIC is also used in the implementation of System.nanoTime, so * we can safely assume that it is present. @@ -70,7 +70,7 @@ private static void getAbsoluteTimeNanos(timespec result) { * We need the real-time clock to compute absolute deadlines when a conditional wait should * return, but calling System.currentTimeMillis reduces the resolution too much. */ - if (Platform.includedIn(InternalPlatform.LINUX_AND_JNI.class)) { + if (Platform.includedIn(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class)) { /* * Linux is easy, we can just access the clock that we registered as the attribute when * the condition was created. 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 56fe3eff200e..9d9261b59eae 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 @@ -59,7 +59,7 @@ * implemented via pthreads. */ @AutomaticFeature -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) final class PthreadVMLockFeature implements Feature { private final ClassInstanceReplacer mutexReplacer = new ClassInstanceReplacer(VMMutex.class) { 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 7b4dbd3c7cf8..e56bce1964e4 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 @@ -204,7 +204,7 @@ protected void beforeThreadRun(Thread thread) { } @TargetClass(Thread.class) -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) final class Target_java_lang_Thread { @Inject @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)// boolean hasPthreadIdentifier; @@ -361,7 +361,7 @@ public ParkEvent create() { } @AutomaticFeature -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) class PosixThreadsFeature implements Feature { @Override public void afterRegistration(AfterRegistrationAccess access) { 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 d95ad5de1808..5700198f1e50 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 @@ -103,7 +103,7 @@ public void failFatally(int code, CCharPointer message) { } @AutomaticFeature -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) class PosixVMThreadsFeature implements Feature { @Override public void afterRegistration(AfterRegistrationAccess access) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ErrnoDirectives.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ErrnoDirectives.java index 9990fe3078a6..e72f4dcb1030 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ErrnoDirectives.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ErrnoDirectives.java @@ -39,14 +39,14 @@ public class ErrnoDirectives implements CContext.Directives { @Override public boolean isInConfiguration() { - return Platform.includedIn(InternalPlatform.LINUX_AND_JNI.class) || Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class) || + return Platform.includedIn(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) || Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class) || Platform.includedIn(Platform.WINDOWS.class); } @Override public List getHeaderFiles() { List result = new ArrayList<>(); - if (Platform.includedIn(InternalPlatform.LINUX_AND_JNI.class) || Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class)) { + if (Platform.includedIn(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) || Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class)) { result.add(""); } else if (Platform.includedIn(Platform.WINDOWS.class)) { result.add(""); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/headers/Errno.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/headers/Errno.java index cb4b212c65d7..32fe408a3541 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/headers/Errno.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/headers/Errno.java @@ -24,13 +24,13 @@ */ package com.oracle.svm.core.headers; +import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; import org.graalvm.nativeimage.c.function.CFunction; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.impl.DeprecatedPlatform; -import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.word.UnsignedWord; import com.oracle.svm.core.ErrnoDirectives; @@ -102,7 +102,7 @@ public class Errno { /** Block device required. */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENOTBLK(); /** Device or resource busy. */ @@ -147,7 +147,7 @@ public class Errno { /** Text file busy. */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ETXTBSY(); /** File too large. */ @@ -184,7 +184,7 @@ public class Errno { /** Linux has no ENOTSUP error code. */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENOTSUP(); /** Resource deadlock would occur */ @@ -209,213 +209,213 @@ public class Errno { /** Too many symbolic links encountered */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ELOOP(); /** Operation would block */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EWOULDBLOCK(); /** No message of desired type */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENOMSG(); /** Identifier removed */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EIDRM(); /** Protocol error */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EPROTO(); /** Multihop attempted */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EMULTIHOP(); /** Not a data message */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EBADMSG(); /** Value too large for defined data type */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EOVERFLOW(); /** Too many users */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EUSERS(); /** Socket operation on non-socket */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENOTSOCK(); /** Destination address required */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EDESTADDRREQ(); /** Message too long */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EMSGSIZE(); /** Protocol wrong type for socket */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EPROTOTYPE(); /** Protocol not available */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENOPROTOOPT(); /** Protocol not supported */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EPROTONOSUPPORT(); /** Socket type not supported */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ESOCKTNOSUPPORT(); /** Operation not supported on transport endpoint */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EOPNOTSUPP(); /** Protocol family not supported */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EPFNOSUPPORT(); /** Address family not supported by protocol */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EAFNOSUPPORT(); /** Address already in use */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EADDRINUSE(); /** Cannot assign requested address */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EADDRNOTAVAIL(); /** Network is down */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENETDOWN(); /** Network is unreachable */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENETUNREACH(); /** Network dropped connection because of reset */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENETRESET(); /** Software caused connection abort */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ECONNABORTED(); /** Connection reset by peer */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ECONNRESET(); /** No buffer space available */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENOBUFS(); /** Transport endpoint is already connected */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EISCONN(); /** Transport endpoint is not connected */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENOTCONN(); /** Cannot send after transport endpoint shutdown */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ESHUTDOWN(); /** Too many references: cannot splice */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ETOOMANYREFS(); /** Connection timed out */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ETIMEDOUT(); /** Connection refused */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ECONNREFUSED(); /** Host is down */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EHOSTDOWN(); /** No route to host */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EHOSTUNREACH(); /** Operation already in progress */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EALREADY(); /** Operation now in progress */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EINPROGRESS(); /** Stale NFS file handle */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ESTALE(); /** Quota exceeded */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EDQUOT(); /** Operation Canceled */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ECANCELED(); /* for robust mutexes */ /** Owner died */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int EOWNERDEAD(); /** State not recoverable */ @CConstant - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native int ENOTRECOVERABLE(); /* @@ -439,6 +439,6 @@ public class Errno { public static native CCharPointer strerror(int errnum); @CFunction - @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, InternalPlatform.LINUX_JNI.class, InternalPlatform.DARWIN_JNI.class}) + @Platforms({DeprecatedPlatform.LINUX_SUBSTITUTION.class, DeprecatedPlatform.DARWIN_SUBSTITUTION.class, Platform.LINUX.class, Platform.DARWIN.class}) public static native CCharPointer strerror_r(int errnum, CCharPointer buf, UnsignedWord buflen); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/IsDefined.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/IsDefined.java index 341991fe1f38..15066e618767 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/IsDefined.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/IsDefined.java @@ -39,12 +39,12 @@ public class IsDefined { @Fold public static final boolean isDarwin() { - return Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class); + return Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class); } @Fold public static final boolean isLinux() { - return Platform.includedIn(InternalPlatform.LINUX_AND_JNI.class); + return Platform.includedIn(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class); } @Fold diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImageServerHelper.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImageServerHelper.java index 84757c1ecb16..3f0477350503 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImageServerHelper.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImageServerHelper.java @@ -38,13 +38,13 @@ public class NativeImageServerHelper { @Fold public static boolean isInConfiguration() { - return Platform.includedIn(InternalPlatform.LINUX_AND_JNI.class) || Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class); + return Platform.includedIn(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class) || Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class); } /* * Ensures started server keeps running even after native-image completes. */ - @Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) + @Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) static int daemonize(Runnable runnable) { int pid = Unistd.fork(); switch (pid) { @@ -63,7 +63,7 @@ static int daemonize(Runnable runnable) { } } -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) class UnistdDirectives implements CContext.Directives { @Override public boolean isInConfiguration() { @@ -81,7 +81,7 @@ public List getMacroDefinitions() { } } -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) @CContext(UnistdDirectives.class) class Unistd { /** 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 31c9437a2dbc..e40ab1985589 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 @@ -127,7 +127,6 @@ import org.graalvm.nativeimage.hosted.Feature.OnAnalysisExitAccess; import org.graalvm.nativeimage.impl.CConstantValueSupport; import org.graalvm.nativeimage.impl.DeprecatedPlatform; -import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import org.graalvm.nativeimage.impl.SizeOfSupport; import org.graalvm.word.PointerBase; @@ -343,9 +342,9 @@ public static Platform defaultPlatform(ClassLoader classLoader) { boolean isJava8 = JavaVersionUtil.JAVA_SPEC == 8; if (hostedArchitecture instanceof AMD64) { if (currentOs == OS.LINUX) { - return isJava8 ? new InternalPlatform.LINUX_JNI_AMD64() : new DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64(); + return isJava8 ? new Platform.LINUX_AMD64() : new DeprecatedPlatform.LINUX_SUBSTITUTION_AMD64(); } else if (currentOs == OS.DARWIN) { - return isJava8 ? new InternalPlatform.DARWIN_JNI_AMD64() : new DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64(); + return isJava8 ? new Platform.DARWIN_AMD64() : new DeprecatedPlatform.DARWIN_SUBSTITUTION_AMD64(); } else if (currentOs == OS.WINDOWS) { return new Platform.WINDOWS_AMD64(); } else { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeBootImageViaCC.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeBootImageViaCC.java index 4e8c0a5d24ce..74f9fd4e32e5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeBootImageViaCC.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeBootImageViaCC.java @@ -174,7 +174,7 @@ protected void setOutputKind(List cmd) { throw UserError.abort(OS.getCurrent().name() + " does not support building static executable images."); case SHARED_LIBRARY: cmd.add("-shared"); - if (Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class)) { + if (Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class)) { cmd.add("-undefined"); cmd.add("dynamic_lookup"); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationUtil.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationUtil.java index 2bf7ffd666c0..56fe1efa7a81 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationUtil.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationUtil.java @@ -32,7 +32,6 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.hosted.Feature.FeatureAccess; -import org.graalvm.nativeimage.impl.InternalPlatform; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import com.oracle.svm.core.jni.JNIRuntimeAccess; @@ -44,15 +43,15 @@ public class JNIRegistrationUtil { protected static boolean isPosix() { - return Platform.includedIn(InternalPlatform.LINUX_JNI.class) || Platform.includedIn(InternalPlatform.DARWIN_JNI.class); + return Platform.includedIn(Platform.LINUX.class) || Platform.includedIn(Platform.DARWIN.class); } protected static boolean isLinux() { - return Platform.includedIn(InternalPlatform.LINUX_JNI.class); + return Platform.includedIn(Platform.LINUX.class); } protected static boolean isDarwin() { - return Platform.includedIn(InternalPlatform.DARWIN_JNI.class); + return Platform.includedIn(Platform.DARWIN.class); } protected static boolean isWindows() { diff --git a/substratevm/src/com.oracle.svm.truffle.nfi.posix/src/com/oracle/svm/truffle/nfi/posix/PosixTruffleNFIFeature.java b/substratevm/src/com.oracle.svm.truffle.nfi.posix/src/com/oracle/svm/truffle/nfi/posix/PosixTruffleNFIFeature.java index c40637b1a773..4136a31d3870 100644 --- a/substratevm/src/com.oracle.svm.truffle.nfi.posix/src/com/oracle/svm/truffle/nfi/posix/PosixTruffleNFIFeature.java +++ b/substratevm/src/com.oracle.svm.truffle.nfi.posix/src/com/oracle/svm/truffle/nfi/posix/PosixTruffleNFIFeature.java @@ -45,7 +45,7 @@ import org.graalvm.word.WordFactory; @AutomaticFeature -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) public final class PosixTruffleNFIFeature implements Feature { @Override @@ -64,10 +64,10 @@ private PosixTruffleNFISupport() { } private static String getErrnoGetterFunctionName() { - if (Platform.includedIn(InternalPlatform.LINUX_AND_JNI.class)) { + if (Platform.includedIn(InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class)) { return "__errno_location"; } - if (Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class)) { + if (Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class)) { return "__error"; } throw VMError.unsupportedFeature("unsupported platform for TruffleNFIFeature"); diff --git a/substratevm/src/com.oracle.svm.truffle.nfi.posix/src/com/oracle/svm/truffle/nfi/posix/Target_com_oracle_truffle_nfi_impl_NFIContextPosix.java b/substratevm/src/com.oracle.svm.truffle.nfi.posix/src/com/oracle/svm/truffle/nfi/posix/Target_com_oracle_truffle_nfi_impl_NFIContextPosix.java index 558017879860..dc93557029c8 100644 --- a/substratevm/src/com.oracle.svm.truffle.nfi.posix/src/com/oracle/svm/truffle/nfi/posix/Target_com_oracle_truffle_nfi_impl_NFIContextPosix.java +++ b/substratevm/src/com.oracle.svm.truffle.nfi.posix/src/com/oracle/svm/truffle/nfi/posix/Target_com_oracle_truffle_nfi_impl_NFIContextPosix.java @@ -34,7 +34,7 @@ import com.oracle.svm.truffle.nfi.TruffleNFIFeature; @TargetClass(className = "com.oracle.truffle.nfi.impl.NFIContext", onlyWith = TruffleNFIFeature.IsEnabled.class) -@Platforms({InternalPlatform.LINUX_AND_JNI.class, InternalPlatform.DARWIN_AND_JNI.class}) +@Platforms({InternalPlatform.LINUX_JNI_AND_SUBSTITUTIONS.class, InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class}) final class Target_com_oracle_truffle_nfi_impl_NFIContextPosix { // Checkstyle: stop diff --git a/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPIFeature.java b/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPIFeature.java index 62a5bd60d85b..af96b726b771 100644 --- a/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPIFeature.java +++ b/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPIFeature.java @@ -64,7 +64,7 @@ public void afterImageWrite(AfterImageWriteAccess access) { throw new RuntimeException(e); } }); - if (Platform.includedIn(InternalPlatform.DARWIN_AND_JNI.class)) { + if (Platform.includedIn(InternalPlatform.DARWIN_JNI_AND_SUBSTITUTIONS.class)) { // on Darwin, change the `id` install name String id = System.getProperty("org.graalvm.polyglot.install_name_id"); if (id == null) { From c8f1521240be046fdd842d2774685de825f857e0 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 9 Oct 2019 13:20:24 +0200 Subject: [PATCH 133/140] [GR-18108] Fix BCI to rethrow an exception in the interpreter. --- .../phases/common/inlining/info/MultiTypeGuardInlineInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 45b41ec4981b..72332e67e60d 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 @@ -208,7 +208,7 @@ private EconomicSet inlineMultipleMethods(StructuredGraph graph, Providers FixedNode exceptionSux = exceptionEdge.next(); graph.addBeforeFixed(exceptionSux, exceptionMerge); exceptionObjectPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(JavaKind.Object), exceptionMerge)); - exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, JavaKind.Object, new JavaKind[]{JavaKind.Object}, + exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.bci(), true, JavaKind.Object, new JavaKind[]{JavaKind.Object}, new ValueNode[]{exceptionObjectPhi})); } From 4d4fa150e277221f2debd6ecb075b1cdf6ae9689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Wed, 9 Oct 2019 16:04:19 +0200 Subject: [PATCH 134/140] Ensure we have implementations for Thread.{stop0,suspend0,resume0} --- .../svm/core/thread/Target_java_lang_Thread.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java index b65328808295..23d2a0adbba0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java @@ -291,6 +291,21 @@ void interrupt0() { JavaThreads.interruptVMCondVars(); } + @Substitute + private void stop0(Object o) { + VMError.unimplemented(); + } + + @Substitute + private void suspend0() { + VMError.unimplemented(); + } + + @Substitute + private void resume0() { + VMError.unimplemented(); + } + @Substitute private boolean isAlive() { // There are fewer cases that are not-alive. From ea2359cad98999a6adf14d212bf19219d4d880a8 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 9 Oct 2019 16:20:43 +0200 Subject: [PATCH 135/140] Use a simpler duplicateModified() and assert the values are correct --- .../src/org/graalvm/compiler/nodes/FrameState.java | 10 ---------- .../common/inlining/info/MultiTypeGuardInlineInfo.java | 6 ++++-- 2 files changed, 4 insertions(+), 12 deletions(-) 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 e6c0475f7f00..ce8444df329d 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 @@ -349,16 +349,6 @@ public FrameState duplicateModifiedBeforeCall(int newBci, JavaKind popKind, Java return duplicateModified(graph(), newBci, rethrowException, false, popKind, pushedSlotKinds, pushedValues); } - /** - * Creates a copy of this frame state with one stack element of type {@code popKind} popped from - * the stack and the values in {@code pushedValues} pushed on the stack. The - * {@code pushedValues} will be formatted correctly in slot encoding: a long or double will be - * followed by a null slot. - */ - public FrameState duplicateModified(int newBci, boolean newRethrowException, JavaKind popKind, JavaKind[] pushedSlotKinds, ValueNode[] pushedValues) { - return duplicateModified(graph(), newBci, newRethrowException, duringCall, popKind, pushedSlotKinds, pushedValues); - } - public FrameState duplicateModified(int newBci, boolean newRethrowException, boolean newDuringCall, JavaKind popKind, JavaKind[] pushedSlotKinds, ValueNode[] pushedValues) { return duplicateModified(graph(), newBci, newRethrowException, newDuringCall, popKind, pushedSlotKinds, pushedValues); } 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 72332e67e60d..6ba1dace3c0c 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 @@ -208,8 +208,10 @@ private EconomicSet inlineMultipleMethods(StructuredGraph graph, Providers FixedNode exceptionSux = exceptionEdge.next(); graph.addBeforeFixed(exceptionSux, exceptionMerge); exceptionObjectPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(JavaKind.Object), exceptionMerge)); - exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.bci(), true, JavaKind.Object, new JavaKind[]{JavaKind.Object}, - new ValueNode[]{exceptionObjectPhi})); + + assert exceptionEdge.stateAfter().bci == invoke.bci(); + assert exceptionEdge.stateAfter().rethrowException(); + exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(JavaKind.Object, JavaKind.Object, exceptionObjectPhi)); } // create one separate block for each invoked method From 73e30b606442db3bdd7d4489d70abf0ef5260ab6 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 9 Oct 2019 15:58:55 +0200 Subject: [PATCH 136/140] Remove FrameState#duplicate(int newBci) and use the simpler FrameState#duplicate() instead --- .../src/org/graalvm/compiler/nodes/FrameState.java | 9 +-------- .../common/inlining/info/MultiTypeGuardInlineInfo.java | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) 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 ce8444df329d..38b5d02de263 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 @@ -303,18 +303,11 @@ public NodeInputList virtualObjectMappings() { return virtualObjectMappings; } - /** - * Gets a copy of this frame state. - */ - public FrameState duplicate(int newBci) { - return graph().add(new FrameState(outerFrameState(), code, newBci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings)); - } - /** * Gets a copy of this frame state. */ public FrameState duplicate() { - return duplicate(bci); + return graph().add(new FrameState(outerFrameState(), code, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings)); } /** 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 6ba1dace3c0c..407db3863465 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 @@ -398,7 +398,7 @@ private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke i JavaKind kind = invoke.asNode().getStackKind(); if (kind != JavaKind.Void) { FrameState stateAfter = invoke.stateAfter(); - stateAfter = stateAfter.duplicate(stateAfter.bci); + stateAfter = stateAfter.duplicate(); stateAfter.replaceFirstInput(invoke.asNode(), result.asNode()); result.setStateAfter(stateAfter); } From 0e74fd31758ed737d8a58597db12a290c6151a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Wed, 9 Oct 2019 16:40:15 +0200 Subject: [PATCH 137/140] Style fix --- .../com/oracle/svm/core/thread/Target_java_lang_Thread.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java index 23d2a0adbba0..1274cd2810a4 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java @@ -292,16 +292,19 @@ void interrupt0() { } @Substitute + @SuppressWarnings({"static-method"}) private void stop0(Object o) { VMError.unimplemented(); } @Substitute + @SuppressWarnings({"static-method"}) private void suspend0() { VMError.unimplemented(); } @Substitute + @SuppressWarnings({"static-method"}) private void resume0() { VMError.unimplemented(); } From 702ab6a774e75fad1a10a63de3bb259ebc4e75a7 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 9 Oct 2019 16:21:31 +0200 Subject: [PATCH 138/140] Inline helper method only used in the constructor --- .../src/org/graalvm/compiler/java/FrameStateBuilder.java | 3 +-- .../src/org/graalvm/compiler/nodes/FrameState.java | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java index 8583dd975f10..607f9e9d3ac2 100644 --- a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java +++ b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java @@ -328,8 +328,7 @@ public FrameState create(int bci, BytecodeParser parent, boolean duringCall, Jav outerFrameState = parent.getFrameStateBuilder().create(parent.bci(), parent.getNonIntrinsicAncestor(), true, null, null); } if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) { - FrameState newFrameState = outerFrameState.duplicateModified(outerFrameState.bci, true, false, JavaKind.Void, new JavaKind[]{JavaKind.Object}, new ValueNode[]{stack[0]}); - return newFrameState; + return outerFrameState.duplicateModified(graph, outerFrameState.bci, true, false, JavaKind.Void, new JavaKind[]{JavaKind.Object}, new ValueNode[]{stack[0]}); } if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) { throw shouldNotReachHere(); 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 38b5d02de263..7342c0b61bde 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 @@ -342,10 +342,6 @@ public FrameState duplicateModifiedBeforeCall(int newBci, JavaKind popKind, Java return duplicateModified(graph(), newBci, rethrowException, false, popKind, pushedSlotKinds, pushedValues); } - public FrameState duplicateModified(int newBci, boolean newRethrowException, boolean newDuringCall, JavaKind popKind, JavaKind[] pushedSlotKinds, ValueNode[] pushedValues) { - return duplicateModified(graph(), newBci, newRethrowException, newDuringCall, popKind, pushedSlotKinds, pushedValues); - } - /** * Creates a copy of this frame state with the top of stack replaced with with * {@code pushedValue} which must be of type {@code popKind}. From 7ce14befb1e12c9c18bcc7fb831f65bcba279abf Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Wed, 9 Oct 2019 18:08:34 +0200 Subject: [PATCH 139/140] Implement option to force use of conservative context references. --- .../truffle/polyglot/PolyglotEngineImpl.java | 2 ++ .../polyglot/PolyglotEngineOptions.java | 6 ++++++ .../truffle/polyglot/PolyglotLanguage.java | 2 +- .../polyglot/PolyglotLanguageInstance.java | 19 +++++++++++-------- 4 files changed, 20 insertions(+), 9 deletions(-) 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 48a644ca848f..116bbb682123 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 @@ -176,6 +176,7 @@ final class PolyglotEngineImpl extends AbstractPolyglotImpl.AbstractEngineImpl i final CastUnsafe castUnsafe; final int contextLength; private volatile EngineLimits limits; + final boolean conservativeContextReferences; PolyglotEngineImpl(PolyglotImpl impl, DispatchOutputStream out, DispatchOutputStream err, InputStream in, Map options, boolean allowExperimentalOptions, boolean useSystemProperties, ClassLoader contextClassLoader, boolean boundEngine, @@ -248,6 +249,7 @@ private PolyglotEngineImpl(PolyglotImpl impl, DispatchOutputStream out, Dispatch parseOptions(options, useSystemProperties, originalEngineOptions, languagesOptions, instrumentsOptions, logLevels); this.engineOptionValues.putAll(originalEngineOptions, allowExperimentalOptions); + this.conservativeContextReferences = engineOptionValues.get(PolyglotEngineOptions.UseConservativeContextReferences); for (PolyglotLanguage language : languagesOptions.keySet()) { language.getOptionValues().putAll(languagesOptions.get(language), allowExperimentalOptions); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineOptions.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineOptions.java index 99ef948c5369..da05ec208342 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineOptions.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineOptions.java @@ -42,6 +42,7 @@ import org.graalvm.options.OptionCategory; import org.graalvm.options.OptionKey; +import org.graalvm.options.OptionStability; import com.oracle.truffle.api.Option; @@ -59,4 +60,9 @@ final class PolyglotEngineOptions { */ @Option(name = INSTRUMENT_EXCEPTIONS_ARE_THROWN_NAME, category = OptionCategory.INTERNAL, help = "Propagates exceptions thrown by instruments.")// static final OptionKey InstrumentExceptionsAreThrown = new OptionKey<>(false); + + @Option(category = OptionCategory.INTERNAL, stability = OptionStability.EXPERIMENTAL, help = "Enables conservative context references. " + + "This allows invalid sharing between contexts. " + + "For testing purposes only.")// + static final OptionKey UseConservativeContextReferences = new OptionKey<>(false); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java index d644fb134e36..0cd6fa9ece64 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguage.java @@ -289,7 +289,7 @@ void freeInstance(PolyglotLanguageInstance instance) { * Returns a context reference sharable within this engine. */ ContextReference getContextReference() { - if (singleInstance.isValid()) { + if (singleInstance.isValid() && !engine.conservativeContextReferences) { return singleOrMultiContextReference; } else { return multiContextReference; 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 30ad6bd4cedc..9feaca062b90 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 @@ -99,16 +99,19 @@ final class PolyglotLanguageInstance implements VMObject { Assumption useDirectSingleContext = currentExclusive ? null : singleContext; Assumption useInnerContext = mayBeUsedInInnerContext ? language.engine.noInnerContexts : null; - if (useDirectSingleContext == null && useInnerContext == null) { - // no checks can use direct reference - this.directContextSupplier = PolyglotReferences.createAlwaysSingleContext(language, currentExclusive); + if (language.engine.conservativeContextReferences) { + this.directContextSupplier = language.getConservativeContextReference(); } else { - this.directContextSupplier = PolyglotReferences.createAssumeSingleContext(language, - useInnerContext, - useDirectSingleContext, - language.getContextReference(), currentExclusive); + if (useDirectSingleContext == null && useInnerContext == null) { + // no checks can use direct reference + this.directContextSupplier = PolyglotReferences.createAlwaysSingleContext(language, currentExclusive); + } else { + this.directContextSupplier = PolyglotReferences.createAssumeSingleContext(language, + useInnerContext, + useDirectSingleContext, + language.getContextReference(), currentExclusive); + } } - this.directLanguageSupplier = PolyglotReferences.createAlwaysSingleLanguage(language, this); } From 8fa9b349a6c3b08cd11a18e5229b2a85391cc065 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Wed, 9 Oct 2019 17:55:27 -0400 Subject: [PATCH 140/140] Revert "Merge branch 'o2-workaround'" This reverts commit 0c480640cead260dc7639cd098087f07adf19c3c, reversing changes made to f73a7df85026312070877a87b6fa582c86cce143. --- .../truffle/llvm/runtime/nodes/op/LLVMCompareNode.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/LLVMCompareNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/LLVMCompareNode.java index 8c6f39154a93..139c8e3ff1fa 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/LLVMCompareNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/op/LLVMCompareNode.java @@ -29,7 +29,6 @@ */ package com.oracle.truffle.llvm.runtime.nodes.op; -import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; @@ -82,11 +81,6 @@ protected boolean eqPointer(LLVMPointer val1, LLVMPointer val2, protected boolean eq(LLVMIVarBit val1, LLVMIVarBit val2) { return val1.isEqual(val2); } - - @Fallback - protected boolean eq(Object a, Object b) { - return false; - } } public abstract static class LLVMNeNode extends LLVMCompareNode {