ClojureScript

avoid producing unnecessary calls to next in emit-apply-to

Details

  • Type: Enhancement Enhancement
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

A function like

(defn bar [a b c d e f g h i j & more])

currently receives a cljs$lang$applyTo property of the following form:

function (arglist__4466) {
    var a = cljs.core.first(arglist__4466);
    var b = cljs.core.first(cljs.core.next(arglist__4466));
    var c = cljs.core.first(cljs.core.next(cljs.core.next(arglist__4466)));
    var d = cljs.core.first(cljs.core.next(cljs.core.next(cljs.core.next(arglist__4466))));
    var e = cljs.core.first(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(arglist__4466)))));
    var f = cljs.core.first(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(arglist__4466))))));
    var g = cljs.core.first(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(arglist__4466)))))));
    var h = cljs.core.first(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(arglist__4466))))))));
    var i = cljs.core.first(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(arglist__4466)))))))));
    var j = cljs.core.first(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(arglist__4466))))))))));
    var more = cljs.core.rest(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(cljs.core.next(arglist__4466))))))))));
    return bar__delegate(a, b, c, d, e, f, g, h, i, j, more);
}

The forthcoming patch changes that to

function (arglist__4460) {
    var a = cljs.core.first(arglist__4460);
    arglist__4460 = cljs.core.next(arglist__4460);
    var b = cljs.core.first(arglist__4460);
    arglist__4460 = cljs.core.next(arglist__4460);
    var c = cljs.core.first(arglist__4460);
    arglist__4460 = cljs.core.next(arglist__4460);
    var d = cljs.core.first(arglist__4460);
    arglist__4460 = cljs.core.next(arglist__4460);
    var e = cljs.core.first(arglist__4460);
    arglist__4460 = cljs.core.next(arglist__4460);
    var f = cljs.core.first(arglist__4460);
    arglist__4460 = cljs.core.next(arglist__4460);
    var g = cljs.core.first(arglist__4460);
    arglist__4460 = cljs.core.next(arglist__4460);
    var h = cljs.core.first(arglist__4460);
    arglist__4460 = cljs.core.next(arglist__4460);
    var i = cljs.core.first(arglist__4460);
    arglist__4460 = cljs.core.next(arglist__4460);
    var j = cljs.core.first(arglist__4460);
    var more = cljs.core.rest(arglist__4460);
    return bar__delegate(a, b, c, d, e, f, g, h, i, j, more);
}

The included benchmark seems to demonstrate a substantial reduction in {apply} overhead on V8 for a function with 10 positional arguments preceding the rest arg and a less substantial reduction for a function with 2 positional arguments, as one would expect. The other benchmark entries for {apply} remain in the same ballpark ({list} actually produces the same compilation output with or without the patch; {+} is changed, but only slightly).

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: