Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into topic/GR-6405
Browse files Browse the repository at this point in the history
  • Loading branch information
ansalond committed Dec 10, 2018
2 parents 4919e9c + c4d2ccc commit 7665a06
Show file tree
Hide file tree
Showing 95 changed files with 1,462 additions and 814 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,6 @@ public CheckGraalIntrinsics() {
"java/lang/Math.fma(DDD)D",
// HotSpot MacroAssembler-based intrinsic
"java/lang/Math.fma(FFF)F",
// Emit pause instruction if os::is_MP()
"java/lang/Thread.onSpinWait()V",
// Just check if the argument is a compile time constant
"java/lang/invoke/MethodHandleImpl.isCompileConstant(Ljava/lang/Object;)Z",
// Some logic and a runtime call
Expand Down Expand Up @@ -419,6 +417,7 @@ public CheckGraalIntrinsics() {
"jdk/internal/misc/Unsafe.getAndSet" + oopName + "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;");
}
add(toBeInvestigated,
"java/lang/Thread.onSpinWait()V",
"jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C",
"jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I",
"jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool.RoundingMode;
import org.graalvm.compiler.nodes.PauseNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
Expand Down Expand Up @@ -75,6 +76,7 @@ public static void register(Plugins plugins, BytecodeProvider replacementsByteco
invocationPlugins.defer(new Runnable() {
@Override
public void run() {
registerThreadPlugins(invocationPlugins, arch);
registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, JavaKind.Int, arch, replacementsBytecodeProvider);
registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, JavaKind.Long, arch, replacementsBytecodeProvider);
registerPlatformSpecificUnsafePlugins(invocationPlugins, replacementsBytecodeProvider, explicitUnsafeNullChecks,
Expand All @@ -89,6 +91,22 @@ public void run() {
});
}

private static void registerThreadPlugins(InvocationPlugins plugins, AMD64 arch) {
if (!Java8OrEarlier) {
// Pause instruction introduced with SSE2
if (arch.getFeatures().contains(AMD64.CPUFeature.SSE2)) {
Registration r = new Registration(plugins, Thread.class);
r.register0("onSpinWait", new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.append(new PauseNode());
return true;
}
});
}
}
}

private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class<?> substituteDeclaringClass, JavaKind kind, AMD64 arch, BytecodeProvider bytecodeProvider) {
Class<?> declaringClass = kind.toBoxedJavaClass();
Class<?> type = kind.toJavaClass();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ protected void initSubstitution(ResolvedJavaMethod theRealMethod,
needCheckNode = false;
} else {
List<String> vmArgs = GraalServices.getInputArguments();
Assume.assumeTrue(vmArgs != null);
for (String vmArg : vmArgs) {
if (vmArg.equals(DISABLE_COMPACTSTRINGS_FLAG)) {
needCheckNode = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,10 +419,18 @@ protected class PEAppendGraphBuilderContext extends PENonAppendGraphBuilderConte
protected FixedWithNextNode lastInstr;
protected ValueNode pushedNode;
protected boolean invokeConsumed;
protected final InvokeKind invokeKind;
protected final JavaType invokeReturnType;

public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr) {
this(inlineScope, lastInstr, null, null);
}

public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr, InvokeKind invokeKind, JavaType invokeReturnType) {
super(inlineScope, inlineScope.invokeData != null ? inlineScope.invokeData.invoke : null);
this.lastInstr = lastInstr;
this.invokeKind = invokeKind;
this.invokeReturnType = invokeReturnType;
}

@Override
Expand Down Expand Up @@ -482,6 +490,22 @@ private <T extends ValueNode> void updateLastInstruction(T v) {
}
}

@Override
public InvokeKind getInvokeKind() {
if (invokeKind != null) {
return invokeKind;
}
return super.getInvokeKind();
}

@Override
public JavaType getInvokeReturnType() {
if (invokeReturnType != null) {
return invokeReturnType;
}
return super.getInvokeReturnType();
}

@Override
public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
if (invokeConsumed) {
Expand Down Expand Up @@ -727,7 +751,9 @@ protected boolean tryInvocationPlugin(PEMethodScope methodScope, LoopScope loopS
invoke.asNode().replaceAtPredecessor(null);

PEMethodScope inlineScope = new PEMethodScope(graph, methodScope, loopScope, null, targetMethod, invokeData, methodScope.inliningDepth + 1, loopExplosionPlugin, arguments);
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor);

JavaType returnType = targetMethod.getSignature().getReturnType(methodScope.method.getDeclaringClass());
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor, callTarget.invokeKind(), returnType);
InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(graphBuilderContext);

if (invocationPlugin.execute(graphBuilderContext, targetMethod, invocationPluginReceiver.init(targetMethod, arguments), arguments)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
*/
package com.oracle.truffle.regex.tregex;

import static com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import static com.oracle.truffle.regex.tregex.util.DebugUtil.LOG_AUTOMATON_SIZES;
import static com.oracle.truffle.regex.tregex.util.DebugUtil.LOG_BAILOUT_MESSAGES;
import static com.oracle.truffle.regex.tregex.util.DebugUtil.LOG_PHASES;
import static com.oracle.truffle.regex.tregex.util.DebugUtil.LOG_TREGEX_COMPILATIONS;

import java.util.logging.Level;

import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.FrameSlotKind;
Expand Down Expand Up @@ -59,14 +67,6 @@
import com.oracle.truffle.regex.tregex.util.NFAExport;
import com.oracle.truffle.regex.tregex.util.json.Json;

import java.util.logging.Level;

import static com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import static com.oracle.truffle.regex.tregex.util.DebugUtil.LOG_AUTOMATON_SIZES;
import static com.oracle.truffle.regex.tregex.util.DebugUtil.LOG_BAILOUT_MESSAGES;
import static com.oracle.truffle.regex.tregex.util.DebugUtil.LOG_PHASES;
import static com.oracle.truffle.regex.tregex.util.DebugUtil.LOG_TREGEX_COMPILATIONS;

/**
* This class is responsible for compiling a single regex pattern. The compilation process is
* designed to be single-threaded, but multiple {@link TRegexCompilationRequest}s can be compiled in
Expand Down Expand Up @@ -245,7 +245,6 @@ private TRegexDFAExecutorProperties createExecutorProperties(NFA nfaArg, boolean
FrameSlot captureGroupResultFS = frameDescriptor.addFrameSlot("captureGroupResult", FrameSlotKind.Object);
FrameSlot lastTransitionFS = frameDescriptor.addFrameSlot("lastTransition", FrameSlotKind.Int);
FrameSlot cgDataFS = frameDescriptor.addFrameSlot("cgData", FrameSlotKind.Object);
FrameSlot inputIsCompactStringFS = frameDescriptor.addFrameSlot("inputIsCompactString", FrameSlotKind.Boolean);
return new TRegexDFAExecutorProperties(
frameDescriptor,
inputFS,
Expand All @@ -258,7 +257,6 @@ private TRegexDFAExecutorProperties createExecutorProperties(NFA nfaArg, boolean
captureGroupResultFS,
lastTransitionFS,
cgDataFS,
inputIsCompactStringFS,
forward,
searching,
trackCaptureGroups,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@

package com.oracle.truffle.regex.tregex.dfa;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.regex.RegexLanguageOptions;
import com.oracle.truffle.regex.RegexOptions;
Expand Down Expand Up @@ -62,15 +71,6 @@
import com.oracle.truffle.regex.tregex.util.json.JsonConvertible;
import com.oracle.truffle.regex.tregex.util.json.JsonValue;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public final class DFAGenerator implements JsonConvertible {

private static final DFAStateTransitionBuilder[] EMPTY_TRANSITIONS_ARRAY = new DFAStateTransitionBuilder[0];
Expand Down Expand Up @@ -504,22 +504,18 @@ private DFAAbstractStateNode[] createDFAExecutorStates() {
}
estimatedTransitionsCost += matchers[i].estimatedCost();
}
if (matchers.length == 1 && matchers[0] == AnyMatcher.INSTANCE) {
matchers = AnyMatcher.INSTANCE_ARRAY;
}

// Very conservative heuristic for whether we should use AllTransitionsInOneTreeMatcher.
// TODO: Potential benefits of this should be further explored.
AllTransitionsInOneTreeMatcher allTransitionsInOneTreeMatcher = null;
boolean useTreeTransitionMatcher = nCheckingTransitions > 1 && MathUtil.log2ceil(nRanges + 2) * 8 < estimatedTransitionsCost;
if (useTreeTransitionMatcher) {
if (getOptions().isRegressionTestMode()) {
// in regression test mode, we compare results of regular matchers and the
if (!getOptions().isRegressionTestMode()) {
// in regression test mode, we compare results of regular matchers and
// AllTransitionsInOneTreeMatcher
matchers = Arrays.copyOf(matchers, matchers.length + 1);
matchers[matchers.length - 1] = createAllTransitionsInOneTreeMatcher(s);
} else {
matchers = new CharMatcher[]{createAllTransitionsInOneTreeMatcher(s)};
matchers = null;
}
allTransitionsInOneTreeMatcher = createAllTransitionsInOneTreeMatcher(s);
}

short[] successors = s.getNumberOfSuccessors() > 0 ? new short[s.getNumberOfSuccessors()] : EMPTY_SHORT_ARRAY;
Expand Down Expand Up @@ -563,16 +559,16 @@ private DFAAbstractStateNode[] createDFAExecutorStates() {
}
DFAStateNode stateNode;
if (trackCaptureGroups) {
stateNode = new CGTrackingDFAStateNode(s.getId(), flags, loopOptimizationNode, successors, matchers, cgTransitions, cgPrecedingTransitions,
stateNode = new CGTrackingDFAStateNode(s.getId(), flags, loopOptimizationNode, successors, matchers, allTransitionsInOneTreeMatcher, cgTransitions, cgPrecedingTransitions,
createCGFinalTransition(s.getAnchoredFinalStateTransition()),
createCGFinalTransition(s.getUnAnchoredFinalStateTransition()));
} else if (nfa.isTraceFinderNFA()) {
stateNode = new TraceFinderDFAStateNode(s.getId(), flags, loopOptimizationNode, successors, matchers,
s.getPreCalculatedUnAnchoredResult(), s.getPreCalculatedAnchoredResult());
allTransitionsInOneTreeMatcher, s.getPreCalculatedUnAnchoredResult(), s.getPreCalculatedAnchoredResult());
} else if (forward) {
stateNode = new DFAStateNode(s.getId(), flags, loopOptimizationNode, successors, matchers);
stateNode = new DFAStateNode(s.getId(), flags, loopOptimizationNode, successors, matchers, allTransitionsInOneTreeMatcher);
} else {
stateNode = new BackwardDFAStateNode(s.getId(), flags, loopOptimizationNode, successors, matchers);
stateNode = new BackwardDFAStateNode(s.getId(), flags, loopOptimizationNode, successors, matchers, allTransitionsInOneTreeMatcher);
}
ret[s.getId()] = stateNode;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,24 @@
*/
package com.oracle.truffle.regex.tregex.matchers;

import com.oracle.truffle.api.dsl.Specialization;

/**
* A character matcher that always matches.
*/
public final class AnyMatcher implements CharMatcher {

private AnyMatcher() {
}

public static final AnyMatcher INSTANCE = new AnyMatcher();

public static final CharMatcher[] INSTANCE_ARRAY = new CharMatcher[]{INSTANCE};
public abstract class AnyMatcher extends CharMatcher {

public static CharMatcher create() {
return INSTANCE;
return AnyMatcherNodeGen.create();
}

public static CharMatcher create(boolean invert) {
return invert ? EmptyMatcher.create() : create();
}

@Override
public boolean match(char c) {
@Specialization
@SuppressWarnings("unused")
boolean match(char c, boolean compactString) {
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package com.oracle.truffle.regex.tregex.matchers;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.regex.tregex.util.DebugUtil;
import com.oracle.truffle.regex.util.CompilationFinalBitSet;

Expand All @@ -34,13 +35,14 @@
* are matched by this high byte and a bit set that matches {@code 0x10}, {@code 0x20} and
* {@code 0x30}.
*/
public final class BitSetMatcher extends InvertibleCharMatcher {
public abstract class BitSetMatcher extends InvertibleCharMatcher {

private final int highByte;
private final CompilationFinalBitSet bitSet;

private BitSetMatcher(boolean invert, int highByte, CompilationFinalBitSet bitSet) {
BitSetMatcher(boolean invert, int highByte, CompilationFinalBitSet bitSet) {
super(invert);
assert highByte != 0 : "use NullHighByteBitSetMatcher instead!";
this.highByte = highByte;
this.bitSet = bitSet;
}
Expand All @@ -55,18 +57,18 @@ private BitSetMatcher(boolean invert, int highByte, CompilationFinalBitSet bitSe
*/
public static InvertibleCharMatcher create(boolean invert, int highByte, CompilationFinalBitSet bitSet) {
if (highByte == 0) {
return new NullHighByteBitSetMatcher(invert, bitSet);
return NullHighByteBitSetMatcher.create(invert, bitSet);
}
return new BitSetMatcher(invert, highByte, bitSet);
return BitSetMatcherNodeGen.create(invert, highByte, bitSet);
}

public CompilationFinalBitSet getBitSet() {
return bitSet;
}

@Override
public boolean matchChar(char c) {
return highByte(c) == highByte && bitSet.get(lowByte(c));
@Specialization
public boolean match(char c, boolean compactString) {
return result(!compactString && highByte(c) == highByte && bitSet.get(lowByte(c)));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,30 @@
*/
package com.oracle.truffle.regex.tregex.matchers;

public interface CharMatcher {
import com.oracle.truffle.api.nodes.Node;

CharMatcher[] EMPTY = {};
public abstract class CharMatcher extends Node {

public static final CharMatcher[] EMPTY = {};

/**
* Check if a given character matches this {@link CharMatcher}.
*
* @param c any character.
* @param compactString {@code true} if {@code c} was read from a compact string and can
* therefore be treated as a {@code byte}. This parameter must always be partial
* evaluation constant!
* @return {@code true} if the character matches.
* @see com.oracle.truffle.api.CompilerDirectives#isPartialEvaluationConstant(Object)
*/
boolean match(char c);
public abstract boolean execute(char c, boolean compactString);

/**
* Conservatively estimate the equivalent number of integer comparisons of calling
* {@link #match(char)}.
* {@link #execute(char, boolean)}.
*
* @return the number of integer comparisons one call to {@link #match(char)} is roughly
* equivalent to. Array loads are treated as two comparisons.
* @return the number of integer comparisons one call to {@link #execute(char, boolean)} is
* roughly equivalent to. Array loads are treated as two comparisons.
*/
int estimatedCost();
public abstract int estimatedCost();
}
Loading

0 comments on commit 7665a06

Please sign in to comment.