mirror of
https://github.com/enso-org/enso.git
synced 2024-11-24 00:27:16 +03:00
Standardization of Vector.sort array access (#7697)
Inspired by #6361 - let's use `ArrayLikeXyzNode` instead of `InteropLibrary`.
This commit is contained in:
parent
1437a671e1
commit
6deaf80a87
@ -1,17 +1,5 @@
|
||||
package org.enso.interpreter.node.expression.builtin.ordering;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
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.Specialization;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -26,7 +14,6 @@ import org.enso.interpreter.dsl.AcceptsError;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.callable.dispatch.CallOptimiserNode;
|
||||
import org.enso.interpreter.node.callable.resolver.MethodResolverNode;
|
||||
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
|
||||
import org.enso.interpreter.node.expression.builtin.meta.EqualsNode;
|
||||
import org.enso.interpreter.node.expression.builtin.meta.TypeOfNode;
|
||||
import org.enso.interpreter.node.expression.builtin.text.AnyToTextNode;
|
||||
@ -36,7 +23,9 @@ import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.data.Type;
|
||||
import org.enso.interpreter.runtime.data.text.Text;
|
||||
import org.enso.interpreter.runtime.data.vector.ArrayLikeAtNode;
|
||||
import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers;
|
||||
import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.error.Warning;
|
||||
@ -45,6 +34,18 @@ import org.enso.interpreter.runtime.error.WithWarnings;
|
||||
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
|
||||
import org.enso.interpreter.runtime.state.State;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
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.Specialization;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
|
||||
/**
|
||||
* Sorts a vector with elements that have only Default_Comparator, thus, only elements with a
|
||||
* builtin type, which is the most common scenario for sorting.
|
||||
@ -97,7 +98,7 @@ public abstract class SortVectorNode extends Node {
|
||||
@Specialization(
|
||||
guards = {
|
||||
"interop.hasArrayElements(self)",
|
||||
"areAllDefaultComparators(interop, hostValueToEnsoNode, comparators)",
|
||||
"areAllDefaultComparators(lengthNode, atNode, comparators)",
|
||||
"interop.isNull(byFunc)",
|
||||
"interop.isNull(onFunc)"
|
||||
}, limit = "3")
|
||||
@ -112,32 +113,23 @@ public abstract class SortVectorNode extends Node {
|
||||
long problemBehavior,
|
||||
@Shared("lessThanNode") @Cached LessThanNode lessThanNode,
|
||||
@Shared("equalsNode") @Cached EqualsNode equalsNode,
|
||||
@Cached HostValueToEnsoNode hostValueToEnsoNode,
|
||||
@Shared("lengthNode") @Cached ArrayLikeLengthNode lengthNode,
|
||||
@Shared("atNode") @Cached ArrayLikeAtNode atNode,
|
||||
@Shared("typeOfNode") @Cached TypeOfNode typeOfNode,
|
||||
@Shared("anyToTextNode") @Cached AnyToTextNode toTextNode,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop) {
|
||||
EnsoContext ctx = EnsoContext.get(this);
|
||||
Object[] elems;
|
||||
long longSize = 0L;
|
||||
try {
|
||||
long size = interop.getArraySize(self);
|
||||
assert size < Integer.MAX_VALUE;
|
||||
elems = new Object[(int) size];
|
||||
longSize = lengthNode.executeLength(self);
|
||||
int size = Math.toIntExact(longSize);
|
||||
elems = new Object[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (interop.isArrayElementReadable(self, i)) {
|
||||
elems[i] = hostValueToEnsoNode.execute(interop.readArrayElement(self, i));
|
||||
} else {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
throw new PanicException(
|
||||
ctx.getBuiltins()
|
||||
.error()
|
||||
.makeUnsupportedArgumentsError(
|
||||
new Object[] {self},
|
||||
"Cannot read array element at index " + i + " of " + self),
|
||||
this);
|
||||
elems[i] = atNode.executeAt(self, i);
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedMessageException | InvalidArrayIndexException e) {
|
||||
throw new IllegalStateException("Should not reach here", e);
|
||||
} catch (ArithmeticException | InvalidArrayIndexException e) {
|
||||
throw invalidArrayIndexException(e, longSize);
|
||||
}
|
||||
var javaComparator =
|
||||
createDefaultComparator(
|
||||
@ -189,17 +181,18 @@ public abstract class SortVectorNode extends Node {
|
||||
@Shared("lessThanNode") @Cached LessThanNode lessThanNode,
|
||||
@Shared("equalsNode") @Cached EqualsNode equalsNode,
|
||||
@Shared("typeOfNode") @Cached TypeOfNode typeOfNode,
|
||||
@Shared("lengthNode") @Cached ArrayLikeLengthNode lengthNode,
|
||||
@Shared("atNode") @Cached ArrayLikeAtNode atNode,
|
||||
@Shared("anyToTextNode") @Cached AnyToTextNode toTextNode,
|
||||
@Cached MethodResolverNode methodResolverNode,
|
||||
@Cached(value = "build()", uncached = "build()") HostValueToEnsoNode hostValueToEnsoNode,
|
||||
@Cached(value = "build()", uncached = "build()") CallOptimiserNode callNode) {
|
||||
var problemBehavior = ProblemBehavior.fromInt((int) problemBehaviorNum);
|
||||
// Split into groups
|
||||
List<Object> elems = readInteropArray(interop, hostValueToEnsoNode, warningsLib, self);
|
||||
List<Object> elems = readInteropArray(lengthNode, atNode, warningsLib, self);
|
||||
List<Type> comparators =
|
||||
readInteropArray(interop, hostValueToEnsoNode, warningsLib, comparatorsArray);
|
||||
readInteropArray(lengthNode, atNode, warningsLib, comparatorsArray);
|
||||
List<Function> compareFuncs =
|
||||
readInteropArray(interop, hostValueToEnsoNode, warningsLib, compareFuncsArray);
|
||||
readInteropArray(lengthNode, atNode, warningsLib, compareFuncsArray);
|
||||
List<Group> groups = splitByComparators(elems, comparators, compareFuncs);
|
||||
|
||||
// Prepare input for DefaultSortComparator and GenericSortComparator and sort the elements
|
||||
@ -388,15 +381,17 @@ public abstract class SortVectorNode extends Node {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> List<T> readInteropArray(
|
||||
InteropLibrary interop,
|
||||
HostValueToEnsoNode hostValueToEnsoNode,
|
||||
ArrayLikeLengthNode lengthNode,
|
||||
ArrayLikeAtNode atNode,
|
||||
WarningsLibrary warningsLib,
|
||||
Object vector) {
|
||||
var longSize = 0L;
|
||||
try {
|
||||
int size = (int) interop.getArraySize(vector);
|
||||
longSize = lengthNode.executeLength(vector);
|
||||
int size = Math.toIntExact(longSize);
|
||||
List<T> res = new ArrayList<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
Object elem = hostValueToEnsoNode.execute(interop.readArrayElement(vector, i));
|
||||
Object elem = atNode.executeAt(vector, i);
|
||||
if (warningsLib.hasWarnings(elem)) {
|
||||
elem = warningsLib.removeWarnings(elem);
|
||||
}
|
||||
@ -404,7 +399,7 @@ public abstract class SortVectorNode extends Node {
|
||||
}
|
||||
return res;
|
||||
} catch (UnsupportedMessageException | InvalidArrayIndexException | ClassCastException e) {
|
||||
throw new IllegalStateException("Should not be reachable", e);
|
||||
throw invalidArrayIndexException(e, longSize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,20 +449,21 @@ public abstract class SortVectorNode extends Node {
|
||||
|
||||
/** Returns true iff the given array of comparators is all Default_Comparator */
|
||||
boolean areAllDefaultComparators(
|
||||
InteropLibrary interop, HostValueToEnsoNode hostValueToEnsoNode, Object comparators) {
|
||||
assert interop.hasArrayElements(comparators);
|
||||
ArrayLikeLengthNode lengthNode, ArrayLikeAtNode atNode, Object comparators
|
||||
) {
|
||||
var ctx = EnsoContext.get(this);
|
||||
var longSize = 0L;
|
||||
try {
|
||||
int compSize = (int) interop.getArraySize(comparators);
|
||||
longSize = lengthNode.executeLength(comparators);
|
||||
int compSize = (int) longSize;
|
||||
for (int i = 0; i < compSize; i++) {
|
||||
assert interop.isArrayElementReadable(comparators, i);
|
||||
Object comparator = hostValueToEnsoNode.execute(interop.readArrayElement(comparators, i));
|
||||
Object comparator = atNode.executeAt(comparators, i);
|
||||
if (!isDefaultComparator(comparator, ctx)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedMessageException | InvalidArrayIndexException e) {
|
||||
throw new IllegalStateException("Should not be reachable", e);
|
||||
} catch (ArithmeticException | InvalidArrayIndexException e) {
|
||||
throw invalidArrayIndexException(e, longSize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -480,6 +476,13 @@ public abstract class SortVectorNode extends Node {
|
||||
return object instanceof Double dbl && dbl.isNaN();
|
||||
}
|
||||
|
||||
private PanicException invalidArrayIndexException(Exception e, long size) {
|
||||
var index = e instanceof InvalidArrayIndexException ex ? ex.getInvalidIndex() : 0L;
|
||||
var ctx = EnsoContext.get(this);
|
||||
var payload = ctx.getBuiltins().error().makeInvalidArrayIndex(index, size);
|
||||
throw new PanicException(payload, this);
|
||||
}
|
||||
|
||||
private enum ProblemBehavior {
|
||||
IGNORE,
|
||||
REPORT_WARNING,
|
||||
@ -618,7 +621,7 @@ public abstract class SortVectorNode extends Node {
|
||||
} else if (isPrimitiveValue(y)) {
|
||||
return ascending ? 1 : -1;
|
||||
} else {
|
||||
throw new IllegalStateException("Should not be reachable");
|
||||
throw CompilerDirectives.shouldNotReachHere();
|
||||
}
|
||||
} else {
|
||||
// Values other than primitives are compared just by their type's FQN.
|
||||
|
@ -19,6 +19,11 @@ public abstract class ArrayLikeAtNode extends Node {
|
||||
return ArrayLikeAtNodeGen.create();
|
||||
}
|
||||
|
||||
@NeverDefault
|
||||
public static ArrayLikeAtNode getUncached() {
|
||||
return ArrayLikeAtNodeGen.getUncached();
|
||||
}
|
||||
|
||||
//
|
||||
// implementation
|
||||
//
|
||||
|
@ -17,6 +17,11 @@ public abstract class ArrayLikeLengthNode extends Node {
|
||||
return ArrayLikeLengthNodeGen.create();
|
||||
}
|
||||
|
||||
@NeverDefault
|
||||
public static ArrayLikeLengthNode getUncached() {
|
||||
return ArrayLikeLengthNodeGen.getUncached();
|
||||
}
|
||||
|
||||
//
|
||||
// implementation
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user