Speeding up Ordering_Comparator (#10593)

This commit is contained in:
Jaroslav Tulach 2024-07-19 04:08:53 +02:00 committed by GitHub
parent 451d7cb452
commit c0f5759e07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 61 additions and 26 deletions

View File

@ -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
## PRIVATE
type Positive_Integer_Comparator
@ -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

View File

@ -155,9 +155,8 @@ final class BinaryOperatorNode extends ExpressionNode {
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;
}

View File

@ -179,9 +179,10 @@ public abstract class InvokeConversionNode extends BaseNode {
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),

View File

@ -294,10 +294,11 @@ public abstract class InvokeMethodNode extends BaseNode {
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;

View File

@ -287,6 +287,7 @@ public abstract class ReadArgumentCheckNode extends Node {
@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);
@ -354,7 +355,11 @@ public abstract class ReadArgumentCheckNode extends Node {
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;
}

View File

@ -2,7 +2,11 @@ package org.enso.interpreter.runtime.data;
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;
@ -12,6 +16,7 @@ import com.oracle.truffle.api.interop.UnsupportedTypeException;
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;
@ -413,19 +418,40 @@ public final class EnsoMultiValue implements EnsoObject {
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;
}
/**