Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speeding up Ordering_Comparator #10593

Merged
merged 6 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,16 @@ assert_same_comparators this that ~action =
False -> Error.throw (Incomparable_Values.Error this that)

compare_with_comparators this that -> Ordering ! Incomparable_Values =
any_result = Panic.catch Type_Error handler=identity <|
yield_an_error _ = Error.throw (Incomparable_Values.Error this that)
Panic.catch Type_Error handler=yield_an_error <|
comp_this = Comparable.from this
comp_that = Comparable.from that

if Meta.is_same_object comp_this.comparator comp_that.comparator then
any_result = if Meta.is_same_object comp_this.comparator comp_that.comparator then
comp_this.comparator.compare comp_this.value comp_that.value

case any_result of
result:Ordering -> result
_ -> Error.throw (Incomparable_Values.Error this that)
result = any_result:Ordering
result
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved

## PRIVATE
type Positive_Integer_Comparator
Expand All @@ -92,7 +92,10 @@ type Positive_Integer_Comparator
## PRIVATE
type Ordering_Comparator
## PRIVATE
compare x:Ordering y:Ordering = Ordering.compare x.to_sign y.to_sign
compare x:Ordering y:Ordering = if Meta.is_same_object x y then Ordering.Equal else
if Meta.is_same_object x Ordering.Equal . not then x else
if Meta.is_same_object y Ordering.Less then Ordering.Greater else
Ordering.Less

## PRIVATE
hash x:Ordering = x.to_sign
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,8 @@ final Object doThatConversionUncached(
for (var thatType : multi.allTypes()) {
var fn = findSymbol(symbol, thatType);
if (fn != null) {
var result =
doDispatch(
frame, self, multi.castTo(thatType), thatType, fn, convertNode, invokeNode);
var thatCasted = EnsoMultiValue.CastToNode.getUncached().executeCast(thatType, multi);
var result = doDispatch(frame, self, thatCasted, thatType, fn, convertNode, invokeNode);
if (result != null) {
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,10 @@ Object doMultiValue(
UnresolvedConversion conversion,
Object self,
EnsoMultiValue that,
Object[] arguments) {
Object[] arguments,
@Cached EnsoMultiValue.CastToNode castTo) {
var type = extractType(self);
var result = that.castTo(type);
var result = castTo.executeCast(type, that);
if (result == null) {
throw new PanicException(
EnsoContext.get(this).getBuiltins().error().makeNoSuchConversion(type, self, conversion),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,11 @@ Object doMultiValue(
UnresolvedSymbol symbol,
EnsoMultiValue self,
Object[] arguments,
@Shared("methodResolverNode") @Cached MethodResolverNode methodResolverNode) {
@Shared("methodResolverNode") @Cached MethodResolverNode methodResolverNode,
@Cached EnsoMultiValue.CastToNode castTo) {
var fnAndType = self.resolveSymbol(methodResolverNode, symbol);
if (fnAndType != null) {
var unwrapSelf = self.castTo(fnAndType.getRight());
var unwrapSelf = castTo.executeCast(fnAndType.getRight(), self);
if (unwrapSelf != null) {
assert arguments[0] == self;
arguments[0] = unwrapSelf;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ abstract static class TypeCheckNode extends ReadArgumentCheckNode {
@Child IsValueOfTypeNode checkType;
@CompilerDirectives.CompilationFinal private String expectedTypeMessage;
@CompilerDirectives.CompilationFinal private LazyCheckRootNode lazyCheck;
@Child private EnsoMultiValue.CastToNode castTo;

TypeCheckNode(String name, Type expectedType) {
super(name);
Expand Down Expand Up @@ -354,7 +355,11 @@ final Object findDirectMatch(VirtualFrame frame, Object v) {
return lazyCheckFn;
}
if (v instanceof EnsoMultiValue mv) {
var result = mv.castTo(expectedType);
if (castTo == null) {
CompilerDirectives.transferToInterpreter();
castTo = insert(EnsoMultiValue.CastToNode.create());
}
var result = castTo.executeCast(expectedType, mv);
if (result != null) {
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Cached.Shared;
import com.oracle.truffle.api.dsl.GenerateUncached;
import com.oracle.truffle.api.dsl.NeverDefault;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.ArityException;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
Expand All @@ -12,6 +16,7 @@
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.nodes.Node;
import java.math.BigInteger;
import java.time.Duration;
import java.time.LocalDate;
Expand Down Expand Up @@ -413,19 +418,40 @@ public String toString() {
return Arrays.stream(types).map(t -> t.getName()).collect(Collectors.joining(" & "));
}

/**
* Casts value in this multi value into specific t.
*
* @param type the requested t
* @return instance of the {@code t} or {@code null} if no suitable value was found
*/
public final Object castTo(Type type) {
for (var i = 0; i < types.length; i++) {
if (types[i] == type) {
return values[i];
/** Casts {@link EnsoMultiValue} to requested type effectively. */
@GenerateUncached
public abstract static class CastToNode extends Node {
/**
* Casts value in a multi value into specific type.
*
* @param type the requested t
* @param mv a multi value
* @return instance of the {@code t} or {@code null} if no suitable value was found
*/
public abstract Object executeCast(Type type, EnsoMultiValue mv);

@NeverDefault
public static CastToNode create() {
return EnsoMultiValueFactory.CastToNodeGen.create();
}

@NeverDefault
public static CastToNode getUncached() {
return EnsoMultiValueFactory.CastToNodeGen.getUncached();
}

@Specialization
Object castsToAType(
Type type,
EnsoMultiValue mv,
@Cached(value = "type", allowUncached = true, neverDefault = true) Type cachedType) {
for (var i = 0; i < mv.types.length; i++) {
if (mv.types[i] == cachedType) {
return mv.values[i];
}
}
return null;
}
return null;
}

/**
Expand Down
Loading