diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index e0e912d688..90b4d0f019 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -777,6 +777,9 @@ class PipelineOwner { } +// See _performLayout. +void _doNothing() { } + /// An object in the render tree. /// /// The [RenderObject] class hierarchy is the core of the rendering @@ -804,6 +807,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { RenderObject() { _needsCompositing = isRepaintBoundary || alwaysNeedsCompositing; + _performLayout = performLayout; } // LAYOUT @@ -1073,7 +1077,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { return true; }); try { - performLayout(); + _performLayout(); markNeedsSemanticsUpdate(); } catch (e, stack) { _debugReportException('performLayout', e, stack); @@ -1168,7 +1172,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { return true; }); try { - performLayout(); + _performLayout(); markNeedsSemanticsUpdate(); assert(() { debugAssertDoesMeetConstraints(); return true; }); } catch (e, stack) { @@ -1235,6 +1239,11 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// information without informing this render object. void performLayout(); + // We cache a closure to performLayout so that the callsite is monomorphic. + // Initializing this field with _buildNothing helps the compiler prove that + // this field always holds a closure. + VoidCallback _performLayout = _doNothing; + /// Allows this render object to mutate its child list during layout and /// invokes callback. void invokeLayoutCallback(LayoutCallback callback) { diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index 37497a1a95..61ff0acaa2 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -1351,12 +1351,18 @@ abstract class BuildableElement extends Element { typedef Widget WidgetBuilder(BuildContext context); +// See _builder. +Widget _buildNothing(BuildContext context) => null; + /// Base class for the instantiation of [StatelessWidget], [StatefulWidget], /// and [_ProxyWidget] widgets. abstract class ComponentElement extends BuildableElement { ComponentElement(Widget widget) : super(widget); - WidgetBuilder _builder; + // Initializing this field with _buildNothing helps the compiler prove that + // this field always holds a closure. + WidgetBuilder _builder = _buildNothing; + Element _child; @override @@ -1456,7 +1462,7 @@ class StatefulElement extends ComponentElement { assert(_state._debugTypesAreRight(widget)); assert(_state._element == null); _state._element = this; - assert(_builder == null); + assert(_builder == _buildNothing); _builder = _state.build; assert(_state._config == null); _state._config = widget;