@@ -1873,37 +1873,71 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
18731873
18741874 state.nrOpUpdates ++;
18751875
1876- if (v1.attrs ()->size () == 0 ) {
1876+ const Bindings & bindings1 = *v1.attrs ();
1877+ if (bindings1.empty ()) {
18771878 v = v2;
18781879 return ;
18791880 }
1880- if (v2.attrs ()->size () == 0 ) {
1881+
1882+ const Bindings & bindings2 = *v2.attrs ();
1883+ if (bindings2.empty ()) {
18811884 v = v1;
18821885 return ;
18831886 }
18841887
1885- auto attrs = state.buildBindings (v1.attrs ()->size () + v2.attrs ()->size ());
1888+ /* Simple heuristic for determining whether attrs2 should be "layered" on top of
1889+ attrs1 instead of copying to a new Bindings. */
1890+ bool shouldLayer = [&]() -> bool {
1891+ if (bindings1.isLayerListFull ())
1892+ return false ;
1893+
1894+ if (bindings2.size () > state.settings .bindingsUpdateLayerRhsSizeThreshold )
1895+ return false ;
1896+
1897+ return true ;
1898+ }();
1899+
1900+ if (shouldLayer) {
1901+ auto attrs = state.buildBindings (bindings2.size ());
1902+ attrs.layerOnTopOf (bindings1);
1903+
1904+ std::ranges::copy (bindings2, std::back_inserter (attrs));
1905+ v.mkAttrs (attrs.alreadySorted ());
1906+
1907+ state.nrOpUpdateValuesCopied += bindings2.size ();
1908+ return ;
1909+ }
1910+
1911+ auto attrs = state.buildBindings (bindings1.size () + bindings2.size ());
18861912
18871913 /* Merge the sets, preferring values from the second set. Make
18881914 sure to keep the resulting vector in sorted order. */
1889- auto i = v1. attrs ()-> begin ();
1890- auto j = v2. attrs ()-> begin ();
1915+ auto i = bindings1. begin ();
1916+ auto j = bindings2. begin ();
18911917
1892- while (i != v1. attrs ()-> end () && j != v2. attrs ()-> end ()) {
1918+ while (i != bindings1. end () && j != bindings2. end ()) {
18931919 if (i->name == j->name ) {
18941920 attrs.insert (*j);
18951921 ++i;
18961922 ++j;
1897- } else if (i->name < j->name )
1898- attrs.insert (*i++);
1899- else
1900- attrs.insert (*j++);
1923+ } else if (i->name < j->name ) {
1924+ attrs.insert (*i);
1925+ ++i;
1926+ } else {
1927+ attrs.insert (*j);
1928+ ++j;
1929+ }
19011930 }
19021931
1903- while (i != v1.attrs ()->end ())
1904- attrs.insert (*i++);
1905- while (j != v2.attrs ()->end ())
1906- attrs.insert (*j++);
1932+ while (i != bindings1.end ()) {
1933+ attrs.insert (*i);
1934+ ++i;
1935+ }
1936+
1937+ while (j != bindings2.end ()) {
1938+ attrs.insert (*j);
1939+ ++j;
1940+ }
19071941
19081942 v.mkAttrs (attrs.alreadySorted ());
19091943
0 commit comments