From 8e08a3b6343d4961d368f4c9cd8e4beb474c75ae Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 25 Apr 2023 12:02:51 +0200 Subject: [PATCH] Improve inlining of `<|` on (GraalVM EE) (#6384) --- .../lib/Standard/Base/0.0.0-dev/src/Any.enso | 45 ------------------ .../Standard/Base/0.0.0-dev/src/Function.enso | 46 +++++++++++++++++++ .../semantic/IfVsCaseBenchmarks.java | 19 ++++++++ .../node/callable/InvokeMethodNode.java | 4 +- .../expression/builtin/BuiltinRootNode.java | 4 +- 5 files changed, 70 insertions(+), 48 deletions(-) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Any.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Any.enso index 87d4e7204d3d..96d826ef9cf1 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Any.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Any.enso @@ -371,25 +371,6 @@ type Any Nothing -> Nothing a -> f a - ## Applies the function `self` to the provided argument. - - Arguments: - - argument: The argument to apply `self` to. - - ? Piping Blocks to Functions - This construction is particularly useful for passing a block as an argument - to a function. This means that you can compute more sophisticated values - in-line, as shown in the example below. - - > Example - Applying a function to a block. - - (x -> x + 1) <| - y = 1 ^ 3 - 3 + y - <| : Any -> Any - <| self ~argument = self argument - ## Applies the function on the right hand side to the argument on the left. Arguments @@ -411,32 +392,6 @@ type Any |> : (Any -> Any) -> Any |> self ~function = function self - ## Composes two functions together, for `f << g` creating the function - composition `f ∘ g` (equivalent to `x -> f (g x)`). - - Arguments: - - that: The function to compose with `self`. - - > Example - Multiply by 2 and then add 1 as a function applied to 2. - - (+1 << *2) 2 - << : (Any -> Any) -> (Any -> Any) - << self ~that = x -> self (that x) - - ## Composes two functions together in the forward direction, for `f >> g` - creating the function composition `g ∘ f` (equivalent to `x -> g (f (x))`). - - Arguments: - - that: The function to compose with `self`. - - > Example - Add one and then multiply by two as a function applied to 2. - - (+1 >> *2) 2 - >> : (Any -> Any) -> (Any -> Any) - >> self ~that = x -> that (self x) - ## Checks if any warnings (either all or of a specified type) are attached to the value. Arguments: diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Function.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Function.enso index 5a3ba1587846..de090ec357fe 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Function.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Function.enso @@ -8,6 +8,52 @@ import project.Data.Vector.Vector @Builtin_Type type Function + ## Applies the function `self` to the provided argument. + + Arguments: + - argument: The argument to apply `self` to. + + ? Piping Blocks to Functions + This construction is particularly useful for passing a block as an argument + to a function. This means that you can compute more sophisticated values + in-line, as shown in the example below. + + > Example + Applying a function to a block. + + (x -> x + 1) <| + y = 1 ^ 3 + 3 + y + <| : Any -> Any + <| self ~argument = @Builtin_Method "Function.<|" + + ## Composes two functions together, for `f << g` creating the function + composition `f ∘ g` (equivalent to `x -> f (g x)`). + + Arguments: + - that: The function to compose with `self`. + + > Example + Multiply by 2 and then add 1 as a function applied to 2. + + (+1 << *2) 2 + << : (Any -> Any) -> (Any -> Any) + << self ~that = x -> self (that x) + + ## Composes two functions together in the forward direction, for `f >> g` + creating the function composition `g ∘ f` (equivalent to `x -> g (f (x))`). + + Arguments: + - that: The function to compose with `self`. + + > Example + Add one and then multiply by two as a function applied to 2. + + (+1 >> *2) 2 + >> : (Any -> Any) -> (Any -> Any) + >> self ~that = x -> that (self x) + + ## An identity function which returns the provided argument. Arguments: diff --git a/engine/runtime/src/bench/java/org/enso/interpreter/bench/benchmarks/semantic/IfVsCaseBenchmarks.java b/engine/runtime/src/bench/java/org/enso/interpreter/bench/benchmarks/semantic/IfVsCaseBenchmarks.java index 37a69a779151..c1848d13b87b 100644 --- a/engine/runtime/src/bench/java/org/enso/interpreter/bench/benchmarks/semantic/IfVsCaseBenchmarks.java +++ b/engine/runtime/src/bench/java/org/enso/interpreter/bench/benchmarks/semantic/IfVsCaseBenchmarks.java @@ -40,6 +40,7 @@ public class IfVsCaseBenchmarks extends TestBase { private Value ifBench3; private Value caseBench3; private Value ifBench6; + private Value ifBench6In; private Value caseBench6; private Value createVec; private Value inputVec; @@ -98,6 +99,17 @@ public void initializeBench(BenchmarkParams params) throws IOException { if curr.f6.not then acc else acc + 1 + if_bench_6_in : Vector My_Type -> Integer + if_bench_6_in vec = + vec.fold 0 acc-> curr-> + curr.f1.not.if_then_else acc <| + curr.f2.not.if_then_else acc <| + curr.f3.not.if_then_else acc <| + curr.f4.not.if_then_else acc <| + curr.f5.not.if_then_else acc <| + curr.f6.not.if_then_else acc <| + acc + 1 + case_bench_6 : Vector My_Type -> Integer case_bench_6 vec = vec.fold 0 acc-> curr-> @@ -130,6 +142,7 @@ public void initializeBench(BenchmarkParams params) throws IOException { ifBench3 = Objects.requireNonNull(module.invokeMember(Module.EVAL_EXPRESSION, "if_bench_3")); caseBench3 = Objects.requireNonNull(module.invokeMember(Module.EVAL_EXPRESSION, "case_bench_3")); ifBench6 = Objects.requireNonNull(module.invokeMember(Module.EVAL_EXPRESSION, "if_bench_6")); + ifBench6In = Objects.requireNonNull(module.invokeMember(Module.EVAL_EXPRESSION, "if_bench_6_in")); caseBench6 = Objects.requireNonNull(module.invokeMember(Module.EVAL_EXPRESSION, "case_bench_6")); createVec = Objects.requireNonNull(module.invokeMember(Module.EVAL_EXPRESSION, "create_vec")); // So far, input is a vector of My_Type.Value with all fields set to True @@ -156,6 +169,12 @@ public void ifBench6() { checkResult(res); } + @Benchmark + public void ifBench6In() { + Value res = ifBench6In.execute(inputVec); + checkResult(res); + } + @Benchmark public void caseBench3() { Value res = caseBench3.execute(inputVec); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeMethodNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeMethodNode.java index 0ccd30812095..74a672bd9fa8 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeMethodNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeMethodNode.java @@ -620,9 +620,9 @@ Object doFallback( @CachedLibrary(limit = "10") TypesLibrary methods, @CachedLibrary(limit = "10") InteropLibrary interop, @CachedLibrary(limit = "10") WarningsLibrary warnings, - @Cached MethodResolverNode anyResolverNode) { + @Cached MethodResolverNode resolverNode) { var ctx = EnsoContext.get(this); - Function function = anyResolverNode.expectNonNull(self, ctx.getBuiltins().any(), symbol); + Function function = resolverNode.expectNonNull(self, ctx.getBuiltins().function(), symbol); return invokeFunctionNode.execute(function, frame, state, arguments); } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinRootNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinRootNode.java index 8d67dd59bb7c..52d8b83d01c5 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinRootNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinRootNode.java @@ -42,7 +42,9 @@ protected BuiltinRootNode(EnsoLanguage language) { * @return new node to use to call this builtin */ public DirectCallNode createDirectCallNode() { - return DirectCallNode.create(getCallTarget()); + var callNode = DirectCallNode.create(cloneUninitialized().getCallTarget()); + callNode.forceInlining(); + return callNode; } /**