Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi value Complex test and robustness refactoring #11525

Merged
merged 15 commits into from
Nov 19, 2024

Conversation

JaroslavTulach
Copy link
Member

@JaroslavTulach JaroslavTulach commented Nov 11, 2024

Pull Request Description

While working on #11482 and enhancing the tests suite with more tests based on type Complex a getRootNode() did not terminate in 100000 iterations problem was discovered. Detailed investigation revealed that the existing ReadArgumentCheckNode infrastructure was able to create a cycle of parent pointers in the Truffle AST.

The problem was in intricate manipulation of the AST while rewriting internals in ReadArgumentCheckNode. This PR avoids such manipulation by refactoring the type checking code. ReadArgumentNode knows nothing about types anymore. When a type check is needed, IrToTruffle adds additional TypeCheckValueNode.wrap around the ReadArgumentNode - that breaks the vicious circle.

All the type checks nodes are moved to its own package. All but one of the classes are made package private. The external API for doing type checking is concentrated into TypeCheckValueNode.

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • All code follows the
    Scala,
    Java,
  • Unit tests have been written where possible.
  • Benchmarks remain fine:

@JaroslavTulach
Copy link
Member Author

New 4387ccf tests are running and are green:

obrazek

@JaroslavTulach
Copy link
Member Author

Interesting failure in all engine tests:

java.lang.AssertionError: getRootNode() did not terminate in 100000 iterations.
 at <java> org.graalvm.truffle/com.oracle.truffle.api.nodes.Node.getRootNodeImpl(Node.java:604)
 at <java> org.graalvm.truffle/com.oracle.truffle.api.nodes.Node.getRootNode(Node.java:583)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals.resolveLayer(PolyglotFastThreadLocals.java:433)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals.resolveEngine(PolyglotFastThreadLocals.java:441)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals.findLanguage(PolyglotFastThreadLocals.java:450)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals.findContextClass(PolyglotFastThreadLocals.java:467)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals$ContextReferenceImpl.get(PolyglotFastThreadLocals.java:513)
 at <java> org.enso.runtime/org.enso.interpreter.runtime.EnsoContext.get(EnsoContext.java:249)
 at <java> org.enso.runtime/org.enso.interpreter.runtime.library.dispatch.TypeOfNode.doLong(TypeOfNode.java:55)
 at <java> org.enso.runtime/org.enso.interpreter.runtime.library.dispatch.TypeOfNodeGen.execute(TypeOfNodeGen.java:161)
 at <java> org.enso.runtime/org.enso.interpreter.node.callable.argument.ReadArgumentCheckNode$TypeCheckNode.findType(ReadArgumentCheckNode.java:439)
 at <java> org.enso.runtime/org.enso.interpreter.node.callable.argument.ReadArgumentCheckNodeFactory$TypeCheckNodeGen.executeCheckOrConversion(ReadArgumentCheckNodeFactory.java:130)

@JaroslavTulach
Copy link
Member Author

Interesting failure in all engine tests:

java.lang.AssertionError: getRootNode() did not terminate in 100000 iterations.
 at <java> org.graalvm.truffle/com.oracle.truffle.api.nodes.Node.getRootNodeImpl(Node.java:604)
 at <java> org.graalvm.truffle/com.oracle.truffle.api.nodes.Node.getRootNode(Node.java:583)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals.resolveLayer(PolyglotFastThreadLocals.java:433)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals.resolveEngine(PolyglotFastThreadLocals.java:441)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals.findLanguage(PolyglotFastThreadLocals.java:450)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals.findContextClass(PolyglotFastThreadLocals.java:467)
 at <java> org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotFastThreadLocals$ContextReferenceImpl.get(PolyglotFastThreadLocals.java:513)
 at <java> org.enso.runtime/org.enso.interpreter.runtime.EnsoContext.get(EnsoContext.java:249)
 at <java> org.enso.runtime/org.enso.interpreter.runtime.library.dispatch.TypeOfNode.doLong(TypeOfNode.java:55)
 at <java> org.enso.runtime/org.enso.interpreter.runtime.library.dispatch.TypeOfNodeGen.execute(TypeOfNodeGen.java:161)
 at <java> org.enso.runtime/org.enso.interpreter.node.callable.argument.ReadArgumentCheckNode$TypeCheckNode.findType(ReadArgumentCheckNode.java:439)
 at <java> org.enso.runtime/org.enso.interpreter.node.callable.argument.ReadArgumentCheckNodeFactory$TypeCheckNodeGen.executeCheckOrConversion(ReadArgumentCheckNodeFactory.java:130)

The failure is caused by creating cycle in the Truffle AST! I guess it is time to rewrite ReadArgumentCheckNode and turn it into proper ExpressionNode.

@JaroslavTulach JaroslavTulach changed the title Multi value casts tests and implementation changes Multi value casts tests and robustness changes Nov 15, 2024
@JaroslavTulach
Copy link
Member Author

JaroslavTulach commented Nov 15, 2024

With 04d3835 we can finally try to address #11482 and specify the return type of the Complex.new method:

diff --git test/Base_Tests/src/Data/Complex.enso test/Base_Tests/src/Data/Complex.enso
index 9a0c98590b..41dd0c5567 100644
--- test/Base_Tests/src/Data/Complex.enso
+++ test/Base_Tests/src/Data/Complex.enso
@@ -10,7 +10,7 @@ import project.Data.Complex_Helpers.Complex_Comparator
 type Complex
     private Value re:Float im:Float
 
-    new re=0:Float im=0:Float =
+    new re=0:Float im=0:Float -> Complex =
         c = Complex.Value re im
         if im != 0 then c:Complex else
             c.as_complex_and_float

with this change the test/Base_Tests fail "the right way" - only then we can address the needs of #11482. However I leave such a work for another PR. Let's dedicate this PR to fixing the getRootNode() did not terminate in 100000 iterations problem.

@JaroslavTulach JaroslavTulach added CI: No changelog needed Do not require a changelog entry for this PR. CI: Clean build required CI runners will be cleaned before and after this PR is built. labels Nov 15, 2024
@JaroslavTulach JaroslavTulach changed the title Multi value casts tests and robustness changes Multi value Complex test and robustness refactoring Nov 15, 2024
@JaroslavTulach JaroslavTulach marked this pull request as ready for review November 15, 2024 08:55

## explicit "conversion" of `Complex` to `Float` in a private module
used in `as_complex_and_float`
Float.from (that:Complex) =
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Info for library guys (@jdunkerley, @radeusgd, @GregoryTravis, etc.). You can implement values with mutiple roles even right now. Steps:

  • define a type Complex in one file
  • create another private helper module with explicit conversion
  • define extension method on Complex that creates the mixed in value - e.g. as_complex_and_float
  • when you want to "mix" multiple types into Complex - call such extension method

Your review is welcomed.

@JaroslavTulach JaroslavTulach requested a review from 4e6 November 15, 2024 15:04
Copy link
Member

@Akirathan Akirathan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not entirelly sure what is going on in the code. But it is definitely better than adding all type checking under ReadArgumentNode.Before integrating, please ensure that all benchmarks seems OK.

test/Base_Tests/src/Semantic/Multi_Value_Spec.enso Outdated Show resolved Hide resolved
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.callable.function.FunctionSchema;

final class LazyCheckRootNode extends RootNode {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this class does not extend EnsoRootNode? By extending it, we would have functionality like source section and associated scopes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably because it represents internal function only:

  Function wrapThunk(Function thunk) {
    return new Function(getCallTarget(), thunk.getScope(), SCHEMA, new Object[] {thunk}, null);
  }

In any case, I am not aware of any missing source sections or scopes.

Copy link
Member

@jdunkerley jdunkerley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to correct the typo @Akirathan spotted.

Copy link
Member

@radeusgd radeusgd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@JaroslavTulach JaroslavTulach added CI: Ready to merge This PR is eligible for automatic merge CI: Keep up to date Automatically update this PR to the latest develop. labels Nov 18, 2024
@JaroslavTulach JaroslavTulach added CI: Keep up to date Automatically update this PR to the latest develop. and removed CI: Keep up to date Automatically update this PR to the latest develop. labels Nov 19, 2024
@mergify mergify bot merged commit 3d8a0e1 into develop Nov 19, 2024
44 checks passed
@mergify mergify bot deleted the wip/jtulach/MultiValueCasts11482 branch November 19, 2024 17:04
somebody1234 pushed a commit that referenced this pull request Nov 21, 2024
While working on #11482 and enhancing the tests suite with more tests based on `type Complex` a [getRootNode() did not terminate in 100000 iterations](#11525 (comment)) problem was discovered. Detailed investigation revealed that the existing `ReadArgumentCheckNode` infrastructure was able to create a **cycle** of parent pointers in the Truffle AST.

The problem was in intricate manipulation of the AST while rewriting internals in `ReadArgumentCheckNode`. This PR avoids such manipulation by _refactoring the type checking code_. `ReadArgumentNode` knows nothing about types anymore. When a type check is needed, `IrToTruffle` adds additional `TypeCheckValueNode.wrap` around the `ReadArgumentNode` - that breaks the **vicious circle**.

All the _type checks_ nodes are moved to its own package. All but one of the classes are made package private. The external API for doing _type checking_ is concentrated into `TypeCheckValueNode`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: Clean build required CI runners will be cleaned before and after this PR is built. CI: No changelog needed Do not require a changelog entry for this PR. CI: Ready to merge This PR is eligible for automatic merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants