Commit ed2be895 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Try moving from closures to direct calls. (#7679)

Rumours have it that this is faster now.

Fixes https://github.com/flutter/flutter/issues/5154
parent f1cdf570
...@@ -1095,9 +1095,6 @@ class PipelineOwner { ...@@ -1095,9 +1095,6 @@ class PipelineOwner {
} }
} }
// See _performLayout.
void _doNothing() { }
/// An object in the render tree. /// An object in the render tree.
/// ///
/// The [RenderObject] class hierarchy is the core of the rendering /// The [RenderObject] class hierarchy is the core of the rendering
...@@ -1212,7 +1209,6 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1212,7 +1209,6 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// Initializes internal fields for subclasses. /// Initializes internal fields for subclasses.
RenderObject() { RenderObject() {
_needsCompositing = isRepaintBoundary || alwaysNeedsCompositing; _needsCompositing = isRepaintBoundary || alwaysNeedsCompositing;
_performLayout = performLayout;
} }
/// Cause the entire subtree rooted at the given [RenderObject] to be marked /// Cause the entire subtree rooted at the given [RenderObject] to be marked
...@@ -1227,7 +1223,6 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1227,7 +1223,6 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// ///
/// * [BindingBase.reassembleApplication]. /// * [BindingBase.reassembleApplication].
void reassemble() { void reassemble() {
_performLayout = performLayout;
markNeedsLayout(); markNeedsLayout();
markNeedsCompositingBitsUpdate(); markNeedsCompositingBitsUpdate();
markNeedsPaint(); markNeedsPaint();
...@@ -1608,7 +1603,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1608,7 +1603,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
return true; return true;
}); });
try { try {
_performLayout(); performLayout();
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
} catch (e, stack) { } catch (e, stack) {
_debugReportException('performLayout', e, stack); _debugReportException('performLayout', e, stack);
...@@ -1732,7 +1727,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1732,7 +1727,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
return true; return true;
}); });
try { try {
_performLayout(); performLayout();
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
assert(() { debugAssertDoesMeetConstraints(); return true; }); assert(() { debugAssertDoesMeetConstraints(); return true; });
} catch (e, stack) { } catch (e, stack) {
...@@ -1803,11 +1798,6 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1803,11 +1798,6 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
@protected @protected
void performLayout(); 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 mutations to be made to this object's child list (and any /// Allows mutations to be made to this object's child list (and any
/// descendants) as well as to any other dirty nodes in the render tree owned /// descendants) as well as to any other dirty nodes in the render tree owned
/// by the same [PipelineOwner] as this object. The `callback` argument is /// by the same [PipelineOwner] as this object. The `callback` argument is
......
...@@ -2820,9 +2820,6 @@ typedef Widget WidgetBuilder(BuildContext context); ...@@ -2820,9 +2820,6 @@ typedef Widget WidgetBuilder(BuildContext context);
/// Used by [LazyBlockBuilder.builder]. /// Used by [LazyBlockBuilder.builder].
typedef Widget IndexedWidgetBuilder(BuildContext context, int index); typedef Widget IndexedWidgetBuilder(BuildContext context, int index);
// See ComponentElement._builder.
Widget _buildNothing(BuildContext context) => null;
/// An [Element] that composes other [Element]s. /// An [Element] that composes other [Element]s.
/// ///
/// Rather than creating a [RenderObject] directly, a [ComponentElement] creates /// Rather than creating a [RenderObject] directly, a [ComponentElement] creates
...@@ -2833,10 +2830,6 @@ abstract class ComponentElement extends BuildableElement { ...@@ -2833,10 +2830,6 @@ abstract class ComponentElement extends BuildableElement {
/// Creates an element that uses the given widget as its configuration. /// Creates an element that uses the given widget as its configuration.
ComponentElement(Widget widget) : super(widget); ComponentElement(Widget widget) : super(widget);
// Initializing this field with _buildNothing helps the compiler prove that
// this field always holds a closure.
WidgetBuilder _builder = _buildNothing;
Element _child; Element _child;
@override @override
...@@ -2869,13 +2862,13 @@ abstract class ComponentElement extends BuildableElement { ...@@ -2869,13 +2862,13 @@ abstract class ComponentElement extends BuildableElement {
assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(true)); assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(true));
Widget built; Widget built;
try { try {
built = _builder(this); built = build();
debugWidgetBuilderValue(widget, built); debugWidgetBuilderValue(widget, built);
} catch (e, stack) { } catch (e, stack) {
_debugReportException('building $this', e, stack); _debugReportException('building $this', e, stack);
built = new ErrorWidget(e); built = new ErrorWidget(e);
} finally { } finally {
// We delay marking the element as clean until after calling _builder so // We delay marking the element as clean until after calling build() so
// that attempts to markNeedsBuild() during build() will be ignored. // that attempts to markNeedsBuild() during build() will be ignored.
_dirty = false; _dirty = false;
assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(false)); assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(false));
...@@ -2896,6 +2889,9 @@ abstract class ComponentElement extends BuildableElement { ...@@ -2896,6 +2889,9 @@ abstract class ComponentElement extends BuildableElement {
}); });
} }
@protected
Widget build();
@override @override
void visitChildren(ElementVisitor visitor) { void visitChildren(ElementVisitor visitor) {
if (_child != null) if (_child != null)
...@@ -2912,27 +2908,21 @@ abstract class ComponentElement extends BuildableElement { ...@@ -2912,27 +2908,21 @@ abstract class ComponentElement extends BuildableElement {
/// An [Element] that uses a [StatelessWidget] as its configuration. /// An [Element] that uses a [StatelessWidget] as its configuration.
class StatelessElement extends ComponentElement { class StatelessElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration. /// Creates an element that uses the given widget as its configuration.
StatelessElement(StatelessWidget widget) : super(widget) { StatelessElement(StatelessWidget widget) : super(widget);
_builder = widget.build;
}
@override @override
StatelessWidget get widget => super.widget; StatelessWidget get widget => super.widget;
@override
Widget build() => widget.build(this);
@override @override
void update(StatelessWidget newWidget) { void update(StatelessWidget newWidget) {
super.update(newWidget); super.update(newWidget);
assert(widget == newWidget); assert(widget == newWidget);
_builder = widget.build;
_dirty = true; _dirty = true;
rebuild(); rebuild();
} }
@override
void _reassemble() {
_builder = widget.build;
super._reassemble();
}
} }
/// An [Element] that uses a [StatefulWidget] as its configuration. /// An [Element] that uses a [StatefulWidget] as its configuration.
...@@ -2953,13 +2943,14 @@ class StatefulElement extends ComponentElement { ...@@ -2953,13 +2943,14 @@ class StatefulElement extends ComponentElement {
}); });
assert(_state._element == null); assert(_state._element == null);
_state._element = this; _state._element = this;
assert(_builder == _buildNothing);
_builder = _state.build;
assert(_state._config == null); assert(_state._config == null);
_state._config = widget; _state._config = widget;
assert(_state._debugLifecycleState == _StateLifecycle.created); assert(_state._debugLifecycleState == _StateLifecycle.created);
} }
@override
Widget build() => state.build(this);
/// The [State] instance associated with this location in the tree. /// The [State] instance associated with this location in the tree.
/// ///
/// There is a one-to-one relationship between [State] objects and the /// There is a one-to-one relationship between [State] objects and the
...@@ -2970,7 +2961,6 @@ class StatefulElement extends ComponentElement { ...@@ -2970,7 +2961,6 @@ class StatefulElement extends ComponentElement {
@override @override
void _reassemble() { void _reassemble() {
_builder = state.build;
state.reassemble(); state.reassemble();
super._reassemble(); super._reassemble();
} }
...@@ -3100,20 +3090,13 @@ class StatefulElement extends ComponentElement { ...@@ -3100,20 +3090,13 @@ class StatefulElement extends ComponentElement {
/// An [Element] that uses a [ProxyElement] as its configuration. /// An [Element] that uses a [ProxyElement] as its configuration.
abstract class ProxyElement extends ComponentElement { abstract class ProxyElement extends ComponentElement {
/// Initializes fields for subclasses. /// Initializes fields for subclasses.
ProxyElement(ProxyWidget widget) : super(widget) { ProxyElement(ProxyWidget widget) : super(widget);
_builder = _build;
}
@override @override
ProxyWidget get widget => super.widget; ProxyWidget get widget => super.widget;
Widget _build(BuildContext context) => widget.child;
@override @override
void _reassemble() { Widget build() => widget.child;
_builder = _build;
super._reassemble();
}
@override @override
void update(ProxyWidget newWidget) { void update(ProxyWidget newWidget) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment