Skip to content

Commit

Permalink
Add TruffleStrings.
Browse files Browse the repository at this point in the history
  • Loading branch information
djoooooe committed Jan 13, 2022
1 parent 24f135b commit 5d52020
Show file tree
Hide file tree
Showing 210 changed files with 31,355 additions and 521 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.List;
import java.util.concurrent.Callable;

import com.oracle.truffle.sl.runtime.SLStrings;
import org.graalvm.compiler.truffle.runtime.OptimizedBlockNode;
import org.graalvm.compiler.truffle.runtime.OptimizedBlockNode.PartialBlocks;
import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget;
Expand Down Expand Up @@ -631,7 +632,7 @@ private static OptimizedCallTarget generateSLFunction(Context context, String na
context.getBindings("sl").getMember(name).execute();
context.enter();
try {
OptimizedCallTarget target = ((OptimizedCallTarget) SLContext.get(null).getFunctionRegistry().getFunction(name).getCallTarget());
OptimizedCallTarget target = ((OptimizedCallTarget) SLContext.get(null).getFunctionRegistry().getFunction(SLStrings.fromJavaString(name)).getCallTarget());
// we invalidate to make sure the call counts are updated.
target.invalidate("invalidate for test");
return target;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package org.graalvm.compiler.truffle.test;

import com.oracle.truffle.sl.runtime.SLStrings;
import org.graalvm.compiler.truffle.options.PolyglotCompilerOptions;
import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget;
import org.graalvm.options.OptionDescriptor;
Expand Down Expand Up @@ -99,7 +100,7 @@ private void testCompilationThreshold(int iterations, String compilationThreshol
Context ctx = setupContext(compilationThresholdOption == null ? new String[]{"engine.MultiTier", "false"}
: new String[]{"engine.SingleTierCompilationThreshold", compilationThresholdOption, "engine.MultiTier", "false"});
ctx.eval("sl", "function test() {}");
SLFunction test = SLContext.get(null).getFunctionRegistry().getFunction("test");
SLFunction test = SLContext.get(null).getFunctionRegistry().getFunction(SLStrings.fromJavaString("test"));

Assert.assertFalse(isExecuteCompiled(test));
for (int i = 0; i < iterations - 1; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
package org.graalvm.compiler.truffle.test.builtins;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.strings.TruffleString;
import com.oracle.truffle.sl.builtins.SLBuiltinNode;
import com.oracle.truffle.sl.runtime.SLNull;

Expand All @@ -38,17 +40,18 @@
public abstract class SLAssertFalseBuiltin extends SLBuiltinNode {

@Specialization
public boolean doAssert(boolean value, String message) {
public boolean doAssert(boolean value, TruffleString message,
@Cached TruffleString.ToJavaStringNode toJavaStringNode) {
if (value) {
CompilerDirectives.transferToInterpreter();
throw new SLAssertionError(message == null ? "" : message, this);
throw new SLAssertionError(message == null ? "" : toJavaStringNode.execute(message), this);
}
return value;
}

@Specialization
public boolean doAssertNull(boolean value, @SuppressWarnings("unused") SLNull message) {
return doAssert(value, null);
return doAssert(value, null, null);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
package org.graalvm.compiler.truffle.test.builtins;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.strings.TruffleString;
import com.oracle.truffle.sl.builtins.SLBuiltinNode;
import com.oracle.truffle.sl.runtime.SLNull;

Expand All @@ -38,17 +40,18 @@
public abstract class SLAssertTrueBuiltin extends SLBuiltinNode {

@Specialization
public boolean doAssert(boolean value, String message) {
public boolean doAssert(boolean value, TruffleString message,
@Cached TruffleString.ToJavaStringNode toJavaStringNode) {
if (!value) {
CompilerDirectives.transferToInterpreter();
throw new SLAssertionError(message == null ? "" : message, this);
throw new SLAssertionError(message == null ? "" : toJavaStringNode.execute(message), this);
}
return value;
}

@Specialization
public boolean doAssertNull(boolean value, @SuppressWarnings("unused") SLNull message) {
return doAssert(value, null);
return doAssert(value, null, null);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@
package org.graalvm.compiler.truffle.test.builtins;

import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.strings.TruffleString;
import com.oracle.truffle.sl.SLLanguage;
import com.oracle.truffle.sl.runtime.SLContext;
import com.oracle.truffle.sl.runtime.SLFunction;
import com.oracle.truffle.sl.runtime.SLNull;
Expand All @@ -43,10 +46,13 @@ public abstract class SLCallFunctionsWithBuiltin extends SLGraalRuntimeBuiltin {
@Child private IndirectCallNode indirectCall = Truffle.getRuntime().createIndirectCallNode();

@Specialization
public SLNull runTests(String startsWith, SLFunction harness) {
public SLNull runTests(TruffleString startsWith, SLFunction harness,
@Cached TruffleString.RegionEqualByteIndexNode regionEqualNode) {
boolean found = false;
for (SLFunction function : SLContext.get(this).getFunctionRegistry().getFunctions()) {
if (function.getName().startsWith(startsWith) && getSource(function) == getSource(harness) && getSource(function) != null) {
int length = startsWith.byteLength(SLLanguage.STRING_ENCODING);
if (function.getName().byteLength(SLLanguage.STRING_ENCODING) >= length && regionEqualNode.execute(function.getName(), 0, startsWith, 0, length, SLLanguage.STRING_ENCODING) &&
getSource(function) == getSource(harness) && getSource(function) != null) {
indirectCall.call(harness.getCallTarget(), new Object[]{function});
found = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@
*/
package org.graalvm.compiler.truffle.test.builtins;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.NodeInfo;
import org.graalvm.compiler.truffle.options.PolyglotCompilerOptions;
import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget;
import org.graalvm.options.OptionDescriptor;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.strings.TruffleString;

/**
* Looks up the value of an option in {@link PolyglotCompilerOptions}. In the future this builtin
* might be extended to lookup other options as well.
Expand All @@ -40,8 +43,9 @@ public abstract class SLGetOptionBuiltin extends SLGraalRuntimeBuiltin {

@Specialization
@TruffleBoundary
public Object getOption(String name) {
final OptionDescriptor option = PolyglotCompilerOptions.getDescriptors().get(name);
public Object getOption(TruffleString name,
@Cached TruffleString.ToJavaStringNode toJavaStringNode) {
final OptionDescriptor option = PolyglotCompilerOptions.getDescriptors().get(toJavaStringNode.execute(name));
if (option == null) {
throw new SLAssertionError("No such option named \"" + name + "\" found in " + PolyglotCompilerOptions.class.getName(), this);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or
* data (collectively the "Software"), free of charge and under any and all
* copyright rights in the Software, and any and all patent rights owned or
* freely licensable by each licensor hereunder covering either (i) the
* unmodified Software as contributed to or provided by such licensor, or (ii)
* the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or at a
* minimum a reference to the UPL must be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.oracle.truffle.regex.jmh;

import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;

import com.oracle.truffle.regex.tregex.test.TRegexTestDummyLanguage;

@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class DFAGenBenchmark extends BenchmarkBase {

@State(Scope.Benchmark)
public static class BenchState {
String reURL = "(((\\w+):\\/\\/)([^\\/:]*)(:(\\d+))?)?([^#?]*)(\\?([^#]*))?(#(.*))?";
String input = "https://lafo.ssw.uni-linz.ac.at/?computer=15";
Pattern javaPattern = Pattern.compile(reURL);
Context context;
Value tregexPattern;

public BenchState() {
context = Context.newBuilder().build();
context.enter();
tregexPattern = context.eval(TRegexTestDummyLanguage.ID, '/' + reURL + '/');
}

@TearDown
public void tearDown() {
context.leave();
context.close();
}
}

@Benchmark
public boolean javaPattern(BenchState state) {
return state.javaPattern.matcher(state.input).find();
}

@Benchmark
public boolean tregex(BenchState state) {
return state.tregexPattern.invokeMember("exec", state.input, 0).getMember("isMatch").asBoolean();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import com.oracle.truffle.api.nodes.ExecutableNode;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.regex.tregex.string.Encodings;

@GenerateWrapper
public abstract class RegexBodyNode extends ExecutableNode implements InstrumentableNode {
Expand Down Expand Up @@ -77,6 +78,10 @@ public RegexLanguage getRegexLanguage() {
return language;
}

public Encodings.Encoding getEncoding() {
return source.getEncoding();
}

@TruffleBoundary
@Override
public SourceSection getSourceSection() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public RegexExecNode(RegexLanguage language, RegexSource source, boolean mustChe
public final RegexResult execute(VirtualFrame frame) {
Object[] args = frame.getArguments();
assert args.length == 2;
return executeDirect(args[0], (int) args[1]);
return adjustIndexAndRun(args[0], (int) args[1]);
}

private int adjustFromIndex(int fromIndex, Object input) {
Expand All @@ -78,18 +78,18 @@ public int inputLength(Object input) {
CompilerDirectives.transferToInterpreterAndInvalidate();
lengthNode = insert(InputLengthNode.create());
}
return lengthNode.execute(input);
return lengthNode.execute(input, getEncoding());
}

public int inputRead(Object input, int i) {
if (charAtNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
charAtNode = insert(InputReadNode.create());
}
return charAtNode.execute(input, i);
return charAtNode.execute(input, i, getEncoding());
}

public RegexResult executeDirect(Object input, int fromIndex) {
private RegexResult adjustIndexAndRun(Object input, int fromIndex) {
if (fromIndex < 0 || fromIndex > inputLength(input)) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new IllegalArgumentException(String.format("got illegal fromIndex value: %d. fromIndex must be >= 0 and <= input length (%d)", fromIndex, inputLength(input)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import com.oracle.truffle.regex.runtime.nodes.ToLongNode;
import com.oracle.truffle.regex.tregex.parser.flavors.PythonFlags;
import com.oracle.truffle.regex.tregex.parser.flavors.RubyFlags;
import com.oracle.truffle.regex.tregex.string.Encodings;
import com.oracle.truffle.regex.util.TruffleNull;
import com.oracle.truffle.regex.util.TruffleReadOnlyKeysArray;
import com.oracle.truffle.regex.util.TruffleReadOnlyMap;
Expand Down Expand Up @@ -251,38 +252,38 @@ Object invokeMember(String member, Object[] args,
if (fromIndex > Integer.MAX_VALUE) {
return RegexResult.getNoMatchInstance();
}
return invokeCache.execute(member, getExecCallTarget(), input, (int) fromIndex);
return invokeCache.execute(member, getExecCallTarget(), input, (int) fromIndex, source.getEncoding());
}

@ImportStatic(RegexObject.class)
@GenerateUncached
abstract static class InvokeCacheNode extends Node {

abstract Object execute(String symbol, CallTarget receiver, Object input, int fromIndex)
abstract Object execute(String symbol, CallTarget receiver, Object input, int fromIndex, Encodings.Encoding encoding)
throws UnsupportedMessageException, ArityException, UnsupportedTypeException, UnknownIdentifierException;

@SuppressWarnings("unused")
@Specialization(guards = {"symbol == cachedSymbol", "cachedSymbol.equals(PROP_EXEC)"}, limit = N_METHODS)
Object execIdentity(String symbol, CallTarget receiver, Object input, int fromIndex,
Object execIdentity(String symbol, CallTarget receiver, Object input, int fromIndex, Encodings.Encoding encoding,
@Cached("symbol") String cachedSymbol,
@Cached ExpectStringOrTruffleObjectNode expectStringOrTruffleObjectNode,
@Cached ExecCompiledRegexNode execNode) throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
return execNode.execute(receiver, expectStringOrTruffleObjectNode.execute(input), fromIndex);
return execNode.execute(receiver, expectStringOrTruffleObjectNode.execute(input, encoding), fromIndex);
}

@SuppressWarnings("unused")
@Specialization(guards = {"symbol.equals(cachedSymbol)", "cachedSymbol.equals(PROP_EXEC)"}, limit = N_METHODS, replaces = "execIdentity")
Object execEquals(String symbol, CallTarget receiver, Object input, int fromIndex,
Object execEquals(String symbol, CallTarget receiver, Object input, int fromIndex, Encodings.Encoding encoding,
@Cached("symbol") String cachedSymbol,
@Cached ExpectStringOrTruffleObjectNode expectStringOrTruffleObjectNode,
@Cached ExecCompiledRegexNode execNode) throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
return execNode.execute(receiver, expectStringOrTruffleObjectNode.execute(input), fromIndex);
return execNode.execute(receiver, expectStringOrTruffleObjectNode.execute(input, encoding), fromIndex);
}

// EXPERIMENTAL
@SuppressWarnings("unused")
@Specialization(guards = {"symbol == cachedSymbol", "cachedSymbol.equals(PROP_EXEC_BYTES)"}, limit = N_METHODS)
Object execBytesIdentity(String symbol, CallTarget receiver, Object input, int fromIndex,
Object execBytesIdentity(String symbol, CallTarget receiver, Object input, int fromIndex, @SuppressWarnings("unused") Encodings.Encoding encoding,
@Cached("symbol") String cachedSymbol,
@Cached ExpectByteArrayHostObjectNode expectByteArrayHostObjectNode,
@Cached ExecCompiledRegexNode execNode) throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
Expand All @@ -292,7 +293,7 @@ Object execBytesIdentity(String symbol, CallTarget receiver, Object input, int f
// EXPERIMENTAL
@SuppressWarnings("unused")
@Specialization(guards = {"symbol.equals(cachedSymbol)", "cachedSymbol.equals(PROP_EXEC_BYTES)"}, limit = N_METHODS, replaces = "execBytesIdentity")
Object execBytesEquals(String symbol, CallTarget receiver, Object input, int fromIndex,
Object execBytesEquals(String symbol, CallTarget receiver, Object input, int fromIndex, @SuppressWarnings("unused") Encodings.Encoding encoding,
@Cached("symbol") String cachedSymbol,
@Cached ExpectByteArrayHostObjectNode expectByteArrayHostObjectNode,
@Cached ExecCompiledRegexNode execNode) throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
Expand All @@ -301,13 +302,13 @@ Object execBytesEquals(String symbol, CallTarget receiver, Object input, int fro

@ReportPolymorphism.Megamorphic
@Specialization(replaces = {"execEquals", "execBytesEquals"})
static Object invokeGeneric(String symbol, CallTarget receiver, Object input, int fromIndex,
static Object invokeGeneric(String symbol, CallTarget receiver, Object input, int fromIndex, Encodings.Encoding encoding,
@Cached ExpectStringOrTruffleObjectNode expectStringOrTruffleObjectNode,
@Cached ExpectByteArrayHostObjectNode expectByteArrayHostObjectNode,
@Cached ExecCompiledRegexNode execNode) throws UnsupportedMessageException, ArityException, UnsupportedTypeException, UnknownIdentifierException {
switch (symbol) {
case PROP_EXEC:
return execNode.execute(receiver, expectStringOrTruffleObjectNode.execute(input), fromIndex);
return execNode.execute(receiver, expectStringOrTruffleObjectNode.execute(input, encoding), fromIndex);
case PROP_EXEC_BYTES:
return execNode.execute(receiver, expectByteArrayHostObjectNode.execute(input), fromIndex);
default:
Expand Down Expand Up @@ -345,7 +346,7 @@ Object execute(Object[] args,
CompilerDirectives.transferToInterpreterAndInvalidate();
throw ArityException.create(2, 2, args.length);
}
Object input = expectStringOrTruffleObjectNode.execute(args[0]);
Object input = expectStringOrTruffleObjectNode.execute(args[0], regex.source.getEncoding());
long fromIndex = toLongNode.execute(args[1]);
if (fromIndex > Integer.MAX_VALUE) {
return RegexResult.getNoMatchInstance();
Expand Down
Loading

0 comments on commit 5d52020

Please sign in to comment.