tc39 / ecmascript_simd

SIMD numeric type for EcmaScript
Other
540 stars 71 forks source link

Anything compiled via emscripten with SIMD=1 fails in Microsoft Edge #321

Closed GordoRank closed 8 years ago

GordoRank commented 8 years ago

I have compiled several projects with Emscripten and in all of them have found a significant speed boost by enabling auto-vectoring via SIMD=1, which results in the simd.js polyfill being bundled. The resulting code works perfectly in Chrome/Firefox.

However, anything including this polyfill completely fails in the latest build of Microsoft Edge. I am using Windows 10 Insider build 1427, so it is quite possible that MS introduced a bug very recently, but I am unable to test an older version.

The error I get when the simd.js polyfill is run is:

Unable to get property 'hasOwnProperty' of undefined or null reference.

Here's some more information i got from looking through the polyfill javascript as it gets spat out by emscripten.

The error occurs here, in the first section // Install each prototype function on each SIMD prototype. on the if(!proto.hasOwnProperty(name)) line:

  allTypes.forEach(function(type) {
            // Install each prototype function on each SIMD prototype.
            var simdFn = type.fn;
            var proto = simdFn.prototype;
            for (var name in prototypeFns) {
                if (!proto.hasOwnProperty(name))
                    proto[name] = prototypeFns[name](type);
            }
            // Install regular functions.
            type.fns.forEach(function(name) {
                if (typeof simdFn[name] === "undefined")
                    simdFn[name] = simdFns[name](type);
            });
            // Install 'fromTIMD' functions.
            if (type.from) {
                type.from.forEach(function(fromType) {
                    var name = "from" + fromType.name;
                    var toType = type;  // pull type into closure.
                    if (typeof type.fn[name] === "undefined") {
                        type.fn[name] =
                            function(a) { return simdFrom(toType, fromType, a); }
                    }
                });
            }
            // Install 'fromTIMDBits' functions.
            if (type.fromBits) {
                type.fromBits.forEach(function(fromType) {
                    var name = "from" + fromType.name + "Bits";
                    var toType = type;  // pull type into closure.
                    if (typeof type.fn[name] === "undefined") {
                        type.fn[name] =
                            function(a) { return simdFromBits(toType, fromType, a); }
                    }
                });
            }
        });

To clarify, in MS Edge, var proto = simdFn.prototype; never appears to be defined.

nmostafa commented 8 years ago

@GordoRank, The issue here is that Chakra doesn't support SIMD prototype functions yet (coming very soon), and it seems you are running with SIMD.js ON in the browser. Currently, we don't set the prototype of SIMD constructors, and the polyfill doesn't have a check if the prototype exists when it is attempting to polyfill the prototype functions. As a workaround for now, I suggest you add a check in the bundled polyfill per below.

allTypes.forEach(function(type) {
            // Install each prototype function on each SIMD prototype.
            var simdFn = type.fn;
            var proto;
            if (simdFn.prototype === undefined)
            { simdFn.prototype = {}; }
            proto = simdFn.prototype;

            { simdFn.prototype = {} };
            for (var name in prototypeFns) {
                if (!proto.hasOwnProperty(name))
                    proto[name] = prototypeFns[name](type);
            }
PeterJensen commented 8 years ago

Use:

if (typeof simdFn.prototype === "undefined")

instead, just in case someone decides to redefine undefined :)

GordoRank commented 8 years ago

Fantastic thanks guys.