@@ -1821,9 +1821,61 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
18211821 }
18221822 }
18231823
1824+ // HFieldGet of a final field from an allocator can be replaced with the
1825+ // field's value.
1826+ //
1827+ // Load Elimination is more powerful as it can handle non-final fields, but
1828+ // doing this earlier in the simplifier generates more opportunities for the
1829+ // first GVN pass.
1830+ if (receiver is HCreate && ! node.isAssignable) {
1831+ int index = _indexOfFieldInAllocatorInputs (
1832+ receiver.element,
1833+ node.element,
1834+ );
1835+ if (index >= 0 ) return receiver.inputs[index];
1836+ }
1837+
18241838 return node;
18251839 }
18261840
1841+ int _indexOfFieldInAllocatorInputs (ClassEntity cls, FieldEntity field) {
1842+ final classCache = _indexOfFieldInAllocatorCache ?? = {};
1843+ final fieldCache = classCache[cls] ?? = {};
1844+ final index = fieldCache[field];
1845+ if (index != null ) return index;
1846+
1847+ int argumentIndex = 0 ;
1848+ _closedWorld.elementEnvironment.forEachInstanceField (cls, (
1849+ _,
1850+ FieldEntity member,
1851+ ) {
1852+ FieldAnalysisData fieldData = _closedWorld.fieldAnalysis.getFieldData (
1853+ member,
1854+ );
1855+ int index = (fieldData.isElided || fieldData.isInitializedInAllocator)
1856+ ? - 1
1857+ : argumentIndex++ ;
1858+
1859+ // TODO(https://github.com/dart-lang/sdk/issues/26775): dart2js has a bug
1860+ // with using the same mixin twice, the fields are not separated, so can
1861+ // occur here twice. If we already have an index, one of them is wrong.
1862+ if (fieldCache[member] != null ) index = - 1 ;
1863+
1864+ fieldCache[member] = index;
1865+ });
1866+
1867+ if (fieldCache[field] == null ) {
1868+ // The field should not be missing but it might be possible (1) with
1869+ // unsound optimizations due to 'trusted' checks (-O3), and (2) attempting
1870+ // to compile an abstract class generative constructor (a bit unclear why
1871+ // this happens, see b/422944368).
1872+ return fieldCache[field] = - 1 ;
1873+ }
1874+ return fieldCache[field]! ;
1875+ }
1876+
1877+ Map <ClassEntity , Map <FieldEntity , int >>? _indexOfFieldInAllocatorCache;
1878+
18271879 @override
18281880 HInstruction visitGetLength (HGetLength node) {
18291881 HInstruction receiver = node.receiver;
0 commit comments