From 7b6d3641f6cc4469c84efb78fe78374080c85503 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Fri, 20 Dec 2024 08:28:52 +0100 Subject: [PATCH] Use EnsoMultiValue.NewNode to allocate new instances of EnsoMultiValue --- .../meta/TypeOfNodeMultiValueTest.java | 10 ++- .../builtin/meta/TypeOfNodeValueTest.java | 4 +- .../node/typecheck/TypeCheckValueTest.java | 9 +-- .../test/EnsoMultiValueInteropTest.java | 4 +- .../test/EqualsMultiValueTest.java | 30 +++++---- .../node/typecheck/AllOfTypesCheckNode.java | 2 +- .../runtime/data/EnsoMultiValue.java | 67 +++++++++++++------ 7 files changed, 83 insertions(+), 43 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/expression/builtin/meta/TypeOfNodeMultiValueTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/expression/builtin/meta/TypeOfNodeMultiValueTest.java index 835c24f62f24..3adc0c0aeaa2 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/expression/builtin/meta/TypeOfNodeMultiValueTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/expression/builtin/meta/TypeOfNodeMultiValueTest.java @@ -90,15 +90,19 @@ private static void registerValue( var rawValue = ContextUtils.unwrapValue(ctx(), polyValue); var rawType = ContextUtils.unwrapValue(ctx(), t); if (rawType instanceof Type type) { - var singleMultiValue = EnsoMultiValue.create(new Type[] {type}, 1, new Object[] {rawValue}); + var singleMultiValue = + EnsoMultiValue.NewNode.getUncached() + .newValue(new Type[] {type}, 1, new Object[] {rawValue}); var n = t.getMetaSimpleName(); data.add(new Object[] {singleMultiValue, n, 0}); var rawInt = (Type) ContextUtils.unwrapValue(ctx(), g.typeInteger()); var secondMultiValue = - EnsoMultiValue.create(new Type[] {rawInt, type}, 2, new Object[] {5L, rawValue}); + EnsoMultiValue.NewNode.getUncached() + .newValue(new Type[] {rawInt, type}, 2, new Object[] {5L, rawValue}); data.add(new Object[] {secondMultiValue, n, 1}); var firstMultiValue = - EnsoMultiValue.create(new Type[] {type, rawInt}, 2, new Object[] {rawValue, 6L}); + EnsoMultiValue.NewNode.getUncached() + .newValue(new Type[] {type, rawInt}, 2, new Object[] {rawValue, 6L}); data.add(new Object[] {firstMultiValue, n, 0}); } else { if (!t.isHostObject()) { diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/expression/builtin/meta/TypeOfNodeValueTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/expression/builtin/meta/TypeOfNodeValueTest.java index 3c22ef041617..128d2993f16a 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/expression/builtin/meta/TypeOfNodeValueTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/expression/builtin/meta/TypeOfNodeValueTest.java @@ -93,7 +93,9 @@ public void multiValueWithHiddenType() { new Type[] { ensoCtx.getBuiltins().number().getInteger(), ensoCtx.getBuiltins().text() }; - var multi = EnsoMultiValue.create(types, 1, new Object[] {42L, "Meaning"}); + var multi = + EnsoMultiValue.NewNode.getUncached() + .newValue(types, 1, new Object[] {42L, "Meaning"}); var arr = (Object[]) testTypesCall.call(multi, true); var allTypes = (Type[]) arr[1]; assertEquals("Two types", 2, allTypes.length); diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/typecheck/TypeCheckValueTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/typecheck/TypeCheckValueTest.java index 7a4fbdd1e028..e732d1dcbcd0 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/typecheck/TypeCheckValueTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/node/typecheck/TypeCheckValueTest.java @@ -39,10 +39,11 @@ public void avoidDoubleWrappingOfEnsoMultiValue() { () -> { var builtins = ContextUtils.leakContext(ctx).getBuiltins(); var m1 = - EnsoMultiValue.create( - new Type[] {builtins.text(), builtins.number().getInteger()}, - 2, - new Object[] {"Hi", 42}); + EnsoMultiValue.NewNode.getUncached() + .newValue( + new Type[] {builtins.text(), builtins.number().getInteger()}, + 2, + new Object[] {"Hi", 42}); assertEquals("Text & Integer", m1.toDisplayString(true)); var res = convert.call(m1); diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/EnsoMultiValueInteropTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/EnsoMultiValueInteropTest.java index dad3a6100481..d945732ee0e4 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/EnsoMultiValueInteropTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/EnsoMultiValueInteropTest.java @@ -58,7 +58,9 @@ private static void registerValue( if (rawT1 instanceof Type typ1 && rawT2 instanceof Type typ2) { var r1 = ContextUtils.unwrapValue(ctx, v1); var r2 = ContextUtils.unwrapValue(ctx, v2); - var both = EnsoMultiValue.create(new Type[] {typ1, typ2}, 2, new Object[] {r1, r2}); + var both = + EnsoMultiValue.NewNode.getUncached() + .newValue(new Type[] {typ1, typ2}, 2, new Object[] {r1, r2}); data.add(new Object[] {both}); } } diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/EqualsMultiValueTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/EqualsMultiValueTest.java index 57d60662bb43..0bd801be4c28 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/EqualsMultiValueTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/EqualsMultiValueTest.java @@ -55,8 +55,9 @@ public void testEqualityIntegerAndMultiValue() { var intType = builtins.number().getInteger(); var textText = builtins.text(); var fourExtraText = - EnsoMultiValue.create( - new Type[] {intType, textText}, 1, new Object[] {4L, Text.create("Hi")}); + EnsoMultiValue.NewNode.getUncached() + .newValue( + new Type[] {intType, textText}, 1, new Object[] {4L, Text.create("Hi")}); assertTrue("4 == 4t", equalityCheck(4L, fourExtraText)); assertFalse("5 != 4t", equalityCheck(5L, fourExtraText)); @@ -85,7 +86,7 @@ public void testEqualityTextAndExtraIntegerMultiValue() { // x = _ : (Text & Integer) : Text // e.g. multi value with Text and Integer, casted to Text only // - var multiV = EnsoMultiValue.create(bothTypes, 1, text, integer); + var multiV = EnsoMultiValue.NewNode.getUncached().newValue(bothTypes, 1, text, integer); assertTrue("'Hi' == multiV", equalityCheck(text, multiV)); assertFalse("'Ahoj' != multiV", equalityCheck(ahoj, multiV)); @@ -112,7 +113,8 @@ public void testEqualityIntegerAndMultiValueWithBoth() { var textText = builtins.text(); var hi = Text.create("Hi"); var fourExtraText = - EnsoMultiValue.create(new Type[] {textText, intType}, 2, new Object[] {hi, 4L}); + EnsoMultiValue.NewNode.getUncached() + .newValue(new Type[] {textText, intType}, 2, new Object[] {hi, 4L}); assertTrue("4 == 4t", equalityCheck(4L, fourExtraText)); assertFalse("5 != 4t", equalityCheck(5L, fourExtraText)); @@ -134,8 +136,9 @@ public void testEqualityIntegerAndMultiValueWithIntText() { var intType = builtins.number().getInteger(); var textText = builtins.text(); var fourExtraText = - EnsoMultiValue.create( - new Type[] {intType, textText}, 2, new Object[] {4L, Text.create("Hi")}); + EnsoMultiValue.NewNode.getUncached() + .newValue( + new Type[] {intType, textText}, 2, new Object[] {4L, Text.create("Hi")}); assertTrue("4 == 4t", equalityCheck(4L, fourExtraText)); assertFalse("5 != 4t", equalityCheck(5L, fourExtraText)); @@ -155,14 +158,17 @@ public void twoMultiValues() { var intType = builtins.number().getInteger(); var textText = builtins.text(); var fourExtraText = - EnsoMultiValue.create( - new Type[] {intType, textText}, 1, new Object[] {4L, Text.create("Hi")}); + EnsoMultiValue.NewNode.getUncached() + .newValue( + new Type[] {intType, textText}, 1, new Object[] {4L, Text.create("Hi")}); var fourExtraText2 = - EnsoMultiValue.create( - new Type[] {intType, textText}, 1, new Object[] {4L, Text.create("Hi")}); + EnsoMultiValue.NewNode.getUncached() + .newValue( + new Type[] {intType, textText}, 1, new Object[] {4L, Text.create("Hi")}); var fiveExtraText = - EnsoMultiValue.create( - new Type[] {intType, textText}, 1, new Object[] {5L, Text.create("Hi")}); + EnsoMultiValue.NewNode.getUncached() + .newValue( + new Type[] {intType, textText}, 1, new Object[] {5L, Text.create("Hi")}); assertFalse("!= for sure #1", equalityCheck(fiveExtraText, fourExtraText)); assertFalse("!= for sure #2", equalityCheck(fourExtraText, fiveExtraText)); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/typecheck/AllOfTypesCheckNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/typecheck/AllOfTypesCheckNode.java index 5b23be5dbe06..14514b8781ef 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/typecheck/AllOfTypesCheckNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/typecheck/AllOfTypesCheckNode.java @@ -52,7 +52,7 @@ Object executeCheckOrConversion(VirtualFrame frame, Object value, ExpressionNode values[at] = result; at++; } - return EnsoMultiValue.create(valueTypes, valueTypes.length, values); + return EnsoMultiValue.NewNode.getUncached().newValue(valueTypes, valueTypes.length, values); } @Override diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java index 9428144d7f4c..4abc261ecfcb 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java @@ -50,26 +50,51 @@ private EnsoMultiValue(MultiType dispatch, MultiType extra, Object[] values) { this.values = values; } - /** - * Creates new instance of EnsoMultiValue from provided information. - * - * @param types all the types this value can be {@link CastToNode cast to} - * @param dispatchTypes the (subset of) types that the value is cast to currently - bigger than - * {@code 0} and at most {@code type.length} - * @param values value of each of the provided {@code types} - * @return non-{@code null} multi value instance - */ - @NeverDefault - public static EnsoMultiValue create( - @NeverDefault Type[] types, @NeverDefault int dispatchTypes, @NeverDefault Object... values) { - assert dispatchTypes > 0; - assert dispatchTypes <= types.length; - assert types.length == values.length; - assert !Stream.of(values).anyMatch(v -> v instanceof EnsoMultiValue) - : "Avoid double wrapping " + Arrays.toString(values); - var dt = MultiType.create(types, 0, dispatchTypes); - var et = MultiType.create(types, dispatchTypes, types.length); - return new EnsoMultiValue(dt, et, values); + /** Creates new instance of EnsoMultiValue from provided information. */ + @GenerateUncached + public abstract static class NewNode extends Node { + private static final String INLINE_CACHE_LIMIT = "5"; + + @NeverDefault + public static NewNode create() { + return EnsoMultiValueFactory.NewNodeGen.create(); + } + + @NeverDefault + public static NewNode getUncached() { + return EnsoMultiValueFactory.NewNodeGen.getUncached(); + } + + /** + * Creates new multi value from provided information. + * + * @param types all the types this value can be {@link CastToNode cast to} + * @param dispatchTypes the (subset of) types that the value is cast to currently - bigger than + * {@code 0} and at most {@code type.length} + * @param values value of each of the provided {@code types} + * @return non-{@code null} multi value instance + */ + @NeverDefault + public EnsoMultiValue newValue( + @NeverDefault Type[] types, + @NeverDefault int dispatchTypes, + @NeverDefault Object... values) { + assert dispatchTypes > 0; + assert dispatchTypes <= types.length; + assert types.length == values.length; + assert !Stream.of(values).anyMatch(v -> v instanceof EnsoMultiValue) + : "Avoid double wrapping " + Arrays.toString(values); + var dt = executeTypes(types, 0, dispatchTypes); + var et = executeTypes(types, dispatchTypes, types.length); + return new EnsoMultiValue(dt, et, values); + } + + abstract MultiType executeTypes(Type[] types, int from, int to); + + @Specialization + final MultiType createMultiType(Type[] types, int from, int to) { + return MultiType.create(types, from, to); + } } @ExportMessage @@ -460,7 +485,7 @@ public final Object findTypeOrNull( copyValues[0] = copyValues[i]; copyTypes[i] = mv.dispatch.types[0]; copyValues[i] = mv.values[0]; - return EnsoMultiValue.create(copyTypes, 1, copyValues); + return EnsoMultiValue.NewNode.getUncached().newValue(copyTypes, 1, copyValues); } else { return mv.values[i]; }