Description
This discrepancy comes from a difference in the result of TypeMask.unionOf.
This might be due to our union not being quite symmetrical, or a slightly different type hierarchy (which is the case for mixins).
Both compiled with --disable-type-inference --disable-inlining
.
Old code has one copy of [H.getRuntimeTypeArgument(this, "ListIterable", 0)]
which was moved up from both branches.
toList$1$growable: function(_, growable) {
var t1, result, t2, i;
t1 = [H.getRuntimeTypeArgument(this, "ListIterable", 0)];
if (growable === true) {
result = H.setRuntimeTypeInfo([], t1);
C.JSArray_methods.set$length(result, this.get$length(this));
} else {
t2 = this.get$length(this);
if (typeof t2 !== "number")
return H.iae(t2);
t2 = new Array(t2);
t2.fixed$length = Array;
result = H.setRuntimeTypeInfo(t2, t1);
}
...
New code has two copies:
toList$1$growable: function(_, growable) {
var result, t1, i;
if (growable === true) {
result = H.setRuntimeTypeInfo([], [H.getRuntimeTypeArgument(this, "ListIterable", 0)]);
C.JSArray_methods.set$length(result, this.get$length(this));
} else {
t1 = this.get$length(this);
if (typeof t1 !== "number")
return H.iae(t1);
t1 = new Array(t1);
t1.fixed$length = Array;
result = H.setRuntimeTypeInfo(t1, [H.getRuntimeTypeArgument(this, "ListIterable", 0)]);
}
...
The common subexpression is not pulled out of the 'if' by code motion because of a HTypeKnown in the one branch:
Old SSA block has no HTypeKnown pinning the HTypeInforReadVariable:
B4 |
-- | --
v19 | Interceptor : U1 [subclass=Object]
v20 | InvokeDynamicGetter : v19.length(U1)([subclass=ListIterable]) [null\|subclass=Object] ! ?
n21 | TypeConversion : v20 to [subclass=JSNumber] [subclass=JSNumber]
f22 | ForeignCode : Instance of 'New' (n21) [exact=JSFixedArray]
u23 | ForeignCode : Instance of 'Assignment' (f22) [null]
v24 | TypeInfoReadVariable : U1.ListIterable.E [null\|subclass=Object]
v25 | TypeInfoExpression : INSTANCE List<List.E> (v24) [null\|subclass=Object]
f26 | InvokeStatic : setRuntimeTypeInfo(f22, v25) [exact=JSFixedArray] ! ?
c27 | Goto : (B5) [empty]
New SSA block has a refined receiver after .length which pins the HTypeInfoReadVariable
B4 |
-- | --
v18 | Interceptor : U1 [subclass=Object]
v19 | InvokeDynamicGetter : v18.length(U1)([subclass=ListIterable]) [null\|subclass=Object] ! ?
U52 | TypeKnown : U1 is Union of [[exact=ListQueue], [exact=MappedListIterable], [exact=SubListIterable], [exact=_JsonMapKeyIterable]] witnessed by v19 Union of [[exact=ListQueue], [exact=MappedListIterable], [exact=SubListIterable], [exact=_JsonMapKeyIterable]]
n20 | TypeConversion : v19 to [subclass=JSNumber] [subclass=JSNumber]
f21 | ForeignCode : Instance of 'New' (n20) [exact=JSFixedArray]
u22 | ForeignCode : Instance of 'Assignment' (f21) [null]
v23 | TypeInfoReadVariable : U52.ListIterable.E [null\|subclass=Object]
v24 | TypeInfoExpression : INSTANCE JSArray<JSArray.E> (v23) [null\|subclass=Object]
f25 | InvokeStatic : setRuntimeTypeInfo(f21, v24) [exact=JSFixedArray] ! ?
c26 | Goto : (B5) [empty]
The HTypeKnown is added because the different result iof TypeMask.unionOf looks like the receiver is refined.
A separate issue is that we should still be able to do the code motion. We could selective in our use of the HTypeKnown output and use the unrefined input when the refinement is immaterial to the using instruction.