-
Notifications
You must be signed in to change notification settings - Fork 317
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
Make suspended atom fields work for boxed atoms #8712
Conversation
OK, now we have two test failures that need to be fixed. |
engine/runtime/src/main/java/org/enso/interpreter/runtime/data/atom/AtomConstructor.java
Outdated
Show resolved
Hide resolved
e2dbd65
to
7ff995e
Compare
32d36d7
to
580c3d8
Compare
engine/runtime/src/main/java/org/enso/interpreter/runtime/EnsoContext.java
Show resolved
Hide resolved
After a28daff we only expose four essential classes from the "atom" package: |
…f AtomConstructors
Running engine benchmarks with 08df824 fixes that optimize fields extraction in |
@@ -739,6 +738,10 @@ public static FunctionPointer fromAtomConstructor(AtomConstructor atomConstructo | |||
} | |||
|
|||
public static FunctionPointer fromFunction(Function function) { | |||
var cons = AtomConstructor.accessorFor(function); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Introducing the accessorFor
method allows us to make QualifiedAccessorNode
package private, @4e6.
if (profile.profile(matcher == target.getConstructor())) { | ||
accept(frame, state, structs.getFields(target)); | ||
var arr = toArrayNode.executeFields(target); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -29,6 +30,6 @@ protected void postInitialize() { | |||
} | |||
|
|||
public final Atom newInstance(Object... params) { | |||
return uniqueConstructor.newInstance(params); | |||
return AtomNewInstanceNode.getUncached().newInstance(uniqueConstructor, params); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to hide AtomConstructor.newInstance
as package private and expose AtomNewInstanceNode.getUncached()
instead. It was not clear that AtomConstructor.newInstance
was slow (and only allocating BoxedAtom
!). Now, when we follow standard Truffle conventions, it is clear getUncached()
is the slow path version of AtomNewInstanceNode.create()
. Functionally they are identical as AtomConstructorTest
demonstrates.
EnsoObject doStruct(Atom atom, @CachedLibrary(limit = "2") StructsLibrary structs) { | ||
return ArrayLikeHelpers.wrapObjectsWithCheckAt(structs.getFields(atom)); | ||
@TruffleBoundary | ||
final EnsoObject doOther(Atom atom) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question of Truffle experts: If I do just the first @Specialization(limit = LIMIT, guards = {"atom.getConstructor() == cons"})
then the execute
method yields UnsupportedSpecializationException
when we send there more than LIMIT
of different atom constructors.
I thought @Fallback
would be appropriate, but DSL processor refuses it. So I ended up with @Specialization
without any guards behind @TruffleBoundary
calling the first specialization @TruffleBoundary
. Can we do better? Should the second specialization replace the first one?
new GetFieldNode(language, field.getPosition(), this, field.getName())); | ||
}); | ||
} | ||
var roots = AtomConstructor.collectFieldAccessors(language, this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Introduction of collectFieldAccessors
function allows us to hide GetFieldWithMatchNode
and GetFieldNode
and make them package private.
if (Layout.isAritySupported(args.length)) { | ||
boxedLayout = Layout.create(args.length, 0, args); | ||
} | ||
boxedLayout = Layout.createBoxed(args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The major change that fixes #8710:
- each
AtomConstructor
is associated withboxedLayout
- we always use
StructsLibrary
(and thus layouts) to access the atom values - as such the
SuspendedFieldGetterNode
is used forBoxingAtom
as well asUnboxingAtom
@@ -33,7 +36,51 @@ private SuspendedFieldGetterNode( | |||
this.set = set; | |||
} | |||
|
|||
static UnboxingAtom.FieldGetterNode build( | |||
static NodeFactory<? extends UnboxingAtom.FieldGetterNode> factory( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrapping of FieldGetterNode
now happens on the level of factories. As such it should be more consistent and the suspended wrapper shall be used everywhere.
assertAtomFactory("AtomNewInstanceNode.create", factory); | ||
assertLessArguments("AtomNewInstanceNode.create", factory); | ||
|
||
assertAtomFactory("AtomConstructor.newInstance with priming", factory); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two tests. First one verifies the behavior of getUncached()
in isolation. The second one checks whether both cached and uncached variants co-operate well.
} | ||
|
||
@Test | ||
public void fiveAtomIntFields() throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the test that simulates #8710 - fourXYZ
tests were always passing. fiveXYZ
tests were failing prior to this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor questions about the (need for) TruffleBoundary annotations
private Text doComplexAtom(Atom atom, Object[] fields) { | ||
Text res = Text.create("(", consName(atom.getConstructor())); | ||
private Text doComplexAtom(Atom atom) { | ||
var structs = StructsLibrary.getUncached(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not keep on using a cached StructsLibrary
in doAtom
and passing it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will it make anything better if doComplexAtom
is inlined into PE mode? Do we really need to run this code at assembly speed? Please note that there are showObject
calls that are annotated with @TruffleBoundary
anyway.
Pull Request Description
Fixes #8710 by making sure suspended atom fields support works also for "normal"
Atom
instances without any specialLayout
. Moves all atom related classes into single package and hides as much of classes as possible by making them package private.Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,
style guides.