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
Add method inlining to inline constructors filter #9599
Conversation
I've added a few tests. |
tclass * | ||
Type.tparams * | ||
tclass_field * | ||
bool (* Wether the inline constructor is forced or not. Cancelling a forced constructor should produce an error *) |
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 recommend using a record type instead of a tuple type here, in my experience that's easier to work with and also easier to modify.
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've committed this change.
I found a bug (fix is committed with tests) The bug should only happen in weird dynamic casts: class InlineClass {
public var a : Int;
public inline function new() {};
public inline function method() return a;
}
// ...
var a : {function method(arg:String) : Int; } = cast new InlineClass();
// InlineClass.method doesn't take any arguments.
// This should definitely cancel the inlining.
a.method("hello"); My fix uses type_iseq_strict to compare This is probably overly conservative, I think that checking if it unifies and that the efield type is not Dynamic would be better. I'm going to try that next. |
Please update to the latest development |
…ing inline objects if the parent inline object is cancelled.
This can only happen when dynamic casts are involved. This is probably over-conservative, instead of type_eq_strict it would be better to check if it unifies.
…pe instead. Also check that the field expression is a function to avoid the Dynamic case.
I've rebased on latest development |
Normally inline constructors would immediately cancel if a field that is not a member variable is accessed.
For example:
With this PR the inline constructor filter will not give up so easily.
When the filter finds an expression of the form
ethis.method(args)
ifethis
references an inline object andmethod
is an inline method in the inline object then it will be inlined on demand by the filter.This achieves the goals mentioned in #9432
It also probably solves #3147 (requires implementing proper inlineable iterator for map types and fixing the TFor issue I discussed with simn in slack)
I tested using the IntMap iterator from #8806 and this code:
Compiled into js:
Explanations about some of the changes
Identifying inline objects
Previously inline objects were being identified by the order in which they appeared in the code. While it sounds nice in theory, nested inline objects inside inlined constructors make this very problematic. It requires keeping track of the start and end id of every inlined constructor to be able to reproduce the same id's in the final_pass phase.
In this PR the expressions are now mapped with a function called
mark_ctors
which will wrap anyTNew
TArrayDecl
orTObjectDecl
with @:inlineObject(curr_io_id++). This makes identifying inline objects in final_map a lot simpler, but it's a bit less efficient (Type.map_expr vs Type.iter).handle_field_case
In
analyse_aliases
, the functionhandle_field_case
is used to handle analysis of TField and TArray. It used to return either None or Some inline variable that represents a field of an inline object.handle_field_case
now has a third possible return value IOFInlineMethod.In the cases of TArray and TField this third value is ignored and causes cancellation of the inline object (Keeping the same behaviour it used to have).
IOFInlineMethod is only accepted without cancelling the inline object in the new
TCall({eexpr=TField(ethis,fa)},ca)
case ofanalyze_aliases
.