Prepack: Should Prepack remove 'dead' code?

Created on 10 May 2017  路  3Comments  路  Source: facebook/prepack

RE nodejs/node#12938

I thought this might have been something Prepack would take care of but not sure it does.

Expected Prepack to remove unreachable / dead code. c is always false, therefore the console.logs _should_ be killed but they are not.

Input

const c = false;
var n = 0;
var start  = Date.now();
function f( ) {
for (let i = 0; i < 1000000; i++) {
    if (c) {
        console.log('Yes');
    }
    if (c) {
        console.log('Yes');
    }
    if (c) {
        console.log('Yes');
    }
    if (c) {
        console.log('Yes');
    }
    if (c) {
        console.log('Yes');
    }
    if (c) {
        console.log('Yes');
    }
}
console.log( "time:", Date.now() - start );
start = Date.now();
if( n++ < 1000 )
    setTimeout( f, 0 );
}

Expected

var f, start, n;
(function () {
    var _$1 = this;

    function _0() {
        for (let i = 0; i < 1000000; i++) {
        }

        _$1.console.log("time:", _$1.Date.now() - _$1.start);

        _$1.start = _$1.Date.now();
        if (_$1.n++ < 1000) _$1.setTimeout(_$1.f, 0);
    }

    let _1 = false;
    f = _0;
    start = undefined;
    n = undefined;
    n = 0;

    var _$0 = Date.now();

    if (typeof _$0 !== "number") {
        throw new Error("Prepack model invariant violation: " + _$0);
    }

    start = _$0;
}).call(this);

Actual

var f, start, n;
(function () {
    var _$1 = this;

    function _0() {
        for (let i = 0; i < 1000000; i++) {
            if (_1) {
                _$1.console.log('Yes');
            }

            if (_1) {
                _$1.console.log('Yes');
            }

            if (_1) {
                _$1.console.log('Yes');
            }

            if (_1) {
                _$1.console.log('Yes');
            }

            if (_1) {
                _$1.console.log('Yes');
            }

            if (_1) {
                _$1.console.log('Yes');
            }
        }

        _$1.console.log("time:", _$1.Date.now() - _$1.start);

        _$1.start = _$1.Date.now();
        if (_$1.n++ < 1000) _$1.setTimeout(_$1.f, 0);
    }

    let _1 = false;
    f = _0;
    start = undefined;
    n = undefined;
    n = 0;

    var _$0 = Date.now();

    if (typeof _$0 !== "number") {
        throw new Error("Prepack model invariant violation: " + _$0);
    }

    start = _$0;
}).call(this);
question

All 3 comments

Here's what's going on: Prepack only optimizes code that gets _executed_ along the global code path - that's what we consider the _initialization phase_. Residual functions such as f just get carried over into the prepacked code (with some tweaks to properly resolve captured variables). As f doesn't get invoked here, it doesn't get optimized. Small wrinkle: If you would invoke f, I'd expect that you get an internal TODO telling you that setTimeout is not yet supported.

I think that this is more of a case of lack of constant folding. The constant c is false and so the inner functions don't get eliminated.

Prepack currently doesn't do constant folding since that's a task that most minifiers will do for you. We recommend that you use a minifier after Prepacking which will take care of that.

Right. This keeps coming up. I created a dedicated issue for this that describes in some more detail what's going on, and what needs to happen: #632

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cblappert picture cblappert  路  7Comments

phpnode picture phpnode  路  3Comments

simon-yxl picture simon-yxl  路  3Comments

jtenner picture jtenner  路  5Comments

NTillmann picture NTillmann  路  8Comments