Directly allocate warnings asVectorEnsoObjects (#10143)

This commit is contained in:
Jaroslav Tulach 2024-06-01 06:23:49 +02:00 committed by GitHub
parent af4177e61f
commit 9632f04e9b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 129 additions and 86 deletions

View File

@ -382,7 +382,7 @@ type Array
`Map_Error`.
- No_Wrap: The first error is thrown, and is not wrapped in
`Map_Error`.
- Report_Warning: The result for that element is `Nothing`,
- Report_Warning: The result for that element is `Nothing`,
the error is attached as a warning. Currently unimplemented.
- Ignore: The result is `Nothing`, and the error is
ignored.
@ -421,7 +421,7 @@ type Array
`Map_Error`.
- No_Wrap: The first error is thrown, and is not wrapped in
`Map_Error`.
- Report_Warning: The result for that element is `Nothing`,
- Report_Warning: The result for that element is `Nothing`,
the error is attached as a warning. Currently unimplemented.
- Ignore: The result is `Nothing`, and the error is
ignored.
@ -668,7 +668,7 @@ type Array
`Map_Error`.
- No_Wrap: The first error is thrown, and is not wrapped in
`Map_Error`.
- Report_Warning: The result for that element is `Nothing`,
- Report_Warning: The result for that element is `Nothing`,
the error is attached as a warning. Currently unimplemented.
- Ignore: The result is `Nothing`, and the error is
ignored.
@ -891,7 +891,7 @@ type Array
`Map_Error`.
- No_Wrap: The first error is thrown, and is not wrapped in
`Map_Error`.
- Report_Warning: The result for that element is `Nothing`,
- Report_Warning: The result for that element is `Nothing`,
the error is attached as a warning. Currently unimplemented.
- Ignore: The result is `Nothing`, and the error is
ignored.

View File

@ -679,7 +679,7 @@ type Vector a
`Map_Error`.
- No_Wrap: The first error is thrown, and is not wrapped in
`Map_Error`.
- Report_Warning: The result for that element is `Nothing`,
- Report_Warning: The result for that element is `Nothing`,
the error is attached as a warning. Currently unimplemented.
- Ignore: The result is `Nothing`, and the error is
ignored.
@ -718,7 +718,7 @@ type Vector a
`Map_Error`.
- No_Wrap: The first error is thrown, and is not wrapped in
`Map_Error`.
- Report_Warning: The result for that element is `Nothing`,
- Report_Warning: The result for that element is `Nothing`,
the error is attached as a warning. Currently unimplemented.
- Ignore: The result is `Nothing`, and the error is
ignored.
@ -772,7 +772,7 @@ type Vector a
`Map_Error`.
- No_Wrap: The first error is thrown, and is not wrapped in
`Map_Error`.
- Report_Warning: The result for that element is `Nothing`,
- Report_Warning: The result for that element is `Nothing`,
the error is attached as a warning. Currently unimplemented.
- Ignore: The result is `Nothing`, and the error is
ignored.
@ -1014,7 +1014,7 @@ type Vector a
`Map_Error`.
- No_Wrap: The first error is thrown, and is not wrapped in
`Map_Error`.
- Report_Warning: The result for that element is `Nothing`,
- Report_Warning: The result for that element is `Nothing`,
the error is attached as a warning. Currently unimplemented.
- Ignore: The result is `Nothing`, and the error is
ignored.
@ -1507,17 +1507,16 @@ type Builder
## GROUP Conversions
ICON convert
Clones the builder into a Vector.
to_vector : Vector Any
to_vector self =
to_vector self -> Vector =
## This creates a fresh copy of the builders storage, so any future
changes to the builder will not affect the returned vector.
This also reattaches any warnings that were attached to the added
values. It attaches them to the whole array, not the individual
values.
warnings_vector = Vector.from_polyglot_array self.warnings_java_builder.toArray
warnings_vector = self.warnings_java_builder.toArray
Warning.attach_multiple warnings_vector <|
Vector.from_polyglot_array self.elements_java_builder.toArray
self.elements_java_builder.toArray
## PRIVATE
Describes an error attached to a value within a `Vector`. The `index` field

View File

@ -74,7 +74,7 @@ type Warning
- wrap_errors: If true, warnings attached to elements in array-likes are
wrapped in Map_Error.
get_all : Any -> Boolean -> Vector Warning
get_all value wrap_errors:Boolean=False = Vector.from_polyglot_array (get_all_array value wrap_errors)
get_all value wrap_errors:Boolean=False = get_all_vector value wrap_errors
## PRIVATE
ADVANCED
@ -306,8 +306,8 @@ attach_with_stacktrace value warning origin = @Builtin_Method "Warning.attach_wi
## PRIVATE
Builtin function that gets all the warnings attached to the given value.
get_all_array : Any -> Boolean -> Array Warning
get_all_array value should_wrap = @Builtin_Method "Warning.get_all_array"
get_all_vector : Any -> Boolean -> Vector Warning
get_all_vector value should_wrap = @Builtin_Method "Warning.get_all_vector"
## PRIVATE

View File

@ -38,10 +38,15 @@ public class VectorBenchmarks {
import Standard.Base.Data.Vector.Builder
import Standard.Base.Data.Vector.Vector
import Standard.Base.Data.Array_Proxy.Array_Proxy
from Standard.Base.Data.Boolean import False
avg arr =
sum acc i = if i == arr.length then acc else
@Tail_Call sum (acc + arr.at i) i+1
sum acc i =
stop = i == arr.length
if stop then acc else
value = arr.at i
both = acc + value
@Tail_Call sum both i+1
(sum 0 0) / arr.length
fibarr size modulo =

View File

@ -490,7 +490,11 @@ public final class Builtins {
if (atomNodes == null) {
return Optional.empty();
}
LoadedBuiltinMethod builtin = atomNodes.get(methodName).get();
var supply = atomNodes.get(methodName);
if (supply == null) {
return Optional.empty();
}
LoadedBuiltinMethod builtin = supply.get();
if (builtin == null) {
return Optional.empty();
}

View File

@ -12,17 +12,20 @@ import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.nodes.Node;
import java.util.Arrays;
import org.enso.interpreter.runtime.data.EnsoObject;
import org.enso.interpreter.runtime.error.WarningsLibrary;
@ExportLibrary(InteropLibrary.class)
final class ArrayBuilder implements EnsoObject {
private static final String[] MEMBERS =
new String[] {"isEmpty", "add", "appendTo", "get", "getSize", "toArray"};
private static final Object[] EMPTY_ARRAY = new Object[0];
private final int initialCapacity;
private int size;
private Object primitiveArray;
private Object[] objectArray;
/** becomes {@code true} when a non trivial value is being added to the builder */
private boolean nonTrivialEnsoValue;
private ArrayBuilder(int initialCapacity) {
this.initialCapacity = Math.max(1, initialCapacity);
}
@ -41,14 +44,21 @@ final class ArrayBuilder implements EnsoObject {
* Adds an element to the builder
*
* @param e the element to add
* @param warnings library to check for values with warnings
*/
void add(Object e) {
if (objectArray != null) {
if (size == objectArray.length) {
CompilerDirectives.transferToInterpreter();
objectArray = Arrays.copyOf(objectArray, size * 2);
void add(Object e, WarningsLibrary warnings) {
if (!nonTrivialEnsoValue) {
if (warnings.hasWarnings(e)) {
nonTrivialEnsoValue = true;
} else {
var isEnsoValue = e instanceof EnsoObject || e instanceof Long || e instanceof Double;
if (!isEnsoValue) {
nonTrivialEnsoValue = true;
}
}
objectArray[size++] = e;
}
if (objectArray != null) {
addToObjectArray(e);
} else if (primitiveArray instanceof long[] longArray) {
if (e instanceof Long l) {
if (size == longArray.length) {
@ -63,7 +73,7 @@ final class ArrayBuilder implements EnsoObject {
objectArray[i] = longArray[i];
}
primitiveArray = null;
add(e);
addToObjectArray(e);
}
} else if (primitiveArray instanceof double[] doubleArray) {
if (e instanceof Double d) {
@ -79,29 +89,41 @@ final class ArrayBuilder implements EnsoObject {
objectArray[i] = doubleArray[i];
}
primitiveArray = null;
add(e);
addToObjectArray(e);
}
} else {
assert objectArray == null;
assert primitiveArray == null;
assert size == 0;
if (e instanceof Long l) {
var arr = new long[initialCapacity];
arr[0] = l;
primitiveArray = arr;
} else if (e instanceof Double d) {
var arr = new double[initialCapacity];
arr[0] = d;
primitiveArray = arr;
} else {
var arr = new Object[initialCapacity];
arr[0] = e;
objectArray = arr;
switch (e) {
case Long l -> {
var arr = new long[initialCapacity];
arr[0] = l;
primitiveArray = arr;
}
case Double d -> {
var arr = new double[initialCapacity];
arr[0] = d;
primitiveArray = arr;
}
default -> {
var arr = new Object[initialCapacity];
arr[0] = e;
objectArray = arr;
}
}
size = 1;
}
}
private void addToObjectArray(Object e) {
if (size == objectArray.length) {
CompilerDirectives.transferToInterpreter();
objectArray = Arrays.copyOf(objectArray, size * 2);
}
objectArray[size++] = e;
}
/** Obtains an element from the builder */
private Object get(int index, Node node) {
try {
@ -121,7 +143,7 @@ final class ArrayBuilder implements EnsoObject {
}
/** Returns the current array of the builder. */
Object toArray() {
private Object toArray() {
if (objectArray != null) {
return objectArray.length == size ? objectArray : Arrays.copyOf(objectArray, size);
} else if (primitiveArray instanceof long[] longArray) {
@ -129,7 +151,7 @@ final class ArrayBuilder implements EnsoObject {
} else if (primitiveArray instanceof double[] doubleArray) {
return doubleArray.length == size ? doubleArray : Arrays.copyOf(doubleArray, size);
} else {
return EMPTY_ARRAY;
return null;
}
}
@ -138,12 +160,16 @@ final class ArrayBuilder implements EnsoObject {
}
@ExportMessage
Object invokeMember(String name, Object[] args, @CachedLibrary(limit = "3") InteropLibrary iop)
Object invokeMember(
String name,
Object[] args,
@CachedLibrary(limit = "3") InteropLibrary iop,
@CachedLibrary(limit = "3") WarningsLibrary warnings)
throws UnknownIdentifierException, UnsupportedTypeException, UnsupportedMessageException {
return switch (name) {
case "isEmpty" -> isEmpty();
case "add" -> {
add(args[0]);
add(args[0], warnings);
yield this;
}
case "appendTo" -> {
@ -151,7 +177,7 @@ final class ArrayBuilder implements EnsoObject {
for (var i = 0; i < len; i++) {
try {
var e = iop.readArrayElement(args[0], i);
add(e);
add(e, warnings);
} catch (InvalidArrayIndexException ex) {
throw UnsupportedTypeException.create(args);
}
@ -169,16 +195,7 @@ final class ArrayBuilder implements EnsoObject {
yield get(index, iop);
}
case "getSize" -> getSize();
case "toArray" -> {
var arr = toArray();
if (arr instanceof long[] longs) {
yield Vector.fromLongArray(longs);
}
if (arr instanceof double[] doubles) {
yield Vector.fromDoubleArray(doubles);
}
yield Vector.fromInteropArray(Array.wrap((Object[]) arr));
}
case "toArray" -> asVector();
default -> throw UnknownIdentifierException.create(name);
};
}
@ -207,4 +224,19 @@ final class ArrayBuilder implements EnsoObject {
String toDisplayString(boolean ignore) {
return "Array_Builder";
}
Object asVector() {
var res = toArray();
if (res instanceof long[] longs) {
return Vector.fromLongArray(longs);
}
if (res instanceof double[] doubles) {
return Vector.fromDoubleArray(doubles);
}
if (nonTrivialEnsoValue) {
return Vector.fromInteropArray(Array.wrap((Object[]) res));
} else {
return Vector.fromEnsoOnlyArray((Object[]) res);
}
}
}

View File

@ -90,35 +90,14 @@ public final class ArrayLikeHelpers {
@CachedLibrary(limit = "3") WarningsLibrary warnings) {
var len = Math.toIntExact(length);
var target = ArrayBuilder.newBuilder(len);
boolean nonTrivialEnsoValue = false;
for (int i = 0; i < len; i++) {
var value = invokeFunctionNode.execute(fun, frame, state, new Long[] {(long) i});
if (value instanceof DataflowError) {
return value;
}
if (warnings.hasWarnings(value)) {
nonTrivialEnsoValue = true;
} else {
var isEnsoValue =
value instanceof EnsoObject || value instanceof Long || value instanceof Double;
if (!isEnsoValue) {
nonTrivialEnsoValue = true;
}
}
target.add(value);
}
var res = target.toArray();
if (res instanceof long[] longs) {
return Vector.fromLongArray(longs);
}
if (res instanceof double[] doubles) {
return Vector.fromDoubleArray(doubles);
}
if (nonTrivialEnsoValue) {
return Vector.fromInteropArray(Array.wrap((Object[]) res));
} else {
return Vector.fromEnsoOnlyArray((Object[]) res);
target.add(value, warnings);
}
return target.asVector();
}
@Builtin.Method(
@ -166,4 +145,12 @@ public final class ArrayLikeHelpers {
public static EnsoObject asVectorFromArray(Object storage) {
return Vector.fromInteropArray(storage);
}
public static EnsoObject asVectorEnsoObjects(EnsoObject... arr) {
return Vector.fromEnsoOnlyArray(arr);
}
public static EnsoObject asVectorEmpty() {
return Vector.fromEnsoOnlyArray(null);
}
}

View File

@ -24,6 +24,10 @@ import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
@ExportLibrary(TypesLibrary.class)
@Builtin(pkg = "immutable", stdlibName = "Standard.Base.Data.Vector.Vector")
abstract class Vector implements EnsoObject {
private static final Vector EMPTY_LONG = new Long(new long[0]);
private static final Vector EMPTY_DOUBLE = new Double(new double[0]);
private static final Vector EMPTY_VECTOR = new EnsoOnly(new Object[0]);
@ExportMessage
boolean hasArrayElements() {
return true;
@ -112,15 +116,27 @@ abstract class Vector implements EnsoObject {
}
static Vector fromLongArray(long[] arr) {
return new Long(arr);
if (arr == null || arr.length == 0) {
return EMPTY_LONG;
} else {
return new Long(arr);
}
}
static Vector fromDoubleArray(double[] arr) {
return new Double(arr);
if (arr == null || arr.length == 0) {
return EMPTY_DOUBLE;
} else {
return new Double(arr);
}
}
static Object fromEnsoOnlyArray(Object[] arr) {
return new EnsoOnly(arr);
static Vector fromEnsoOnlyArray(Object[] arr) {
if (arr == null || arr.length == 0) {
return EMPTY_VECTOR;
} else {
return new EnsoOnly(arr);
}
}
@ExportLibrary(InteropLibrary.class)

View File

@ -88,7 +88,7 @@ public final class Warning implements EnsoObject {
}
@Builtin.Method(
name = "get_all_array",
name = "get_all_vector",
description = "Gets all the warnings associated with the value.",
autoRegister = false)
@Builtin.Specialize
@ -97,11 +97,11 @@ public final class Warning implements EnsoObject {
WithWarnings value, boolean shouldWrap, WarningsLibrary warningsLib) {
Warning[] warnings = value.getWarningsArray(warningsLib, shouldWrap);
sortArray(warnings);
return ArrayLikeHelpers.wrapEnsoObjects(warnings);
return ArrayLikeHelpers.asVectorEnsoObjects(warnings);
}
@Builtin.Method(
name = "get_all_array",
name = "get_all_vector",
description = "Gets all the warnings associated with the value.",
autoRegister = false)
@Builtin.Specialize(fallback = true)
@ -110,12 +110,12 @@ public final class Warning implements EnsoObject {
try {
Warning[] warnings = warningsLib.getWarnings(value, null, shouldWrap);
sortArray(warnings);
return ArrayLikeHelpers.wrapEnsoObjects(warnings);
return ArrayLikeHelpers.asVectorEnsoObjects(warnings);
} catch (UnsupportedMessageException e) {
throw EnsoContext.get(warningsLib).raiseAssertionPanic(warningsLib, null, e);
}
} else {
return ArrayLikeHelpers.empty();
return ArrayLikeHelpers.asVectorEmpty();
}
}