diff --git a/src/js/hntrie.js b/src/js/hntrie.js index 3afe60ad1..7ba879c37 100644 --- a/src/js/hntrie.js +++ b/src/js/hntrie.js @@ -475,3 +475,126 @@ HNTrieBuilder.prototype.HNTrie32.prototype.matches = function(needle) { } } }; + +/******************************************************************************* + + Experimenting: WebAssembly version. + Developed using this simple online tool: https://wasdk.github.io/WasmFiddle/ + + >>> start of C code + unsigned short buffer[0]; + int matches(int id, int cclen) + { + unsigned short* cc0 = &buffer[0]; + unsigned short* cc = cc0 + cclen; + unsigned short* cell0 = &buffer[512+id]; + unsigned short* cell = cell0; + unsigned short* ww; + int c1, c2, ccnt; + for (;;) { + c1 = cc <= cc0 ? 0 : *--cc; + for (;;) { + c2 = cell[2]; + if ( c2 == c1 ) { break; } + if ( c2 == 0 && c1 == 0x2E ) { return 1; } + if ( cell[0] == 0 ) { return 0; } + cell = cell0 + cell[0]; + } + if ( c1 == 0 ) { return 1; } + ccnt = cell[3]; + if ( ccnt != 0 ) { + if ( cc - ccnt < cc0 ) { return 0; } + ww = cell + 4; + while ( ccnt-- ) { + if ( *--cc != *ww++ ) { return 0; } + } + } + if ( cell[1] == 0 ) { + if ( cc == cc0 ) { return 1; } + if ( *--cc == 0x2E ) { return 1; } + return 0; + } + cell = cell0 + cell[1]; + } + } + int getLinearMemoryOffset() { + return (int)&buffer[0]; + } + <<< end of C code + + Observations: + - When growing memory, we must re-create the typed array js-side. The content + of the array is preserved by grow(). + - It's slower than the javascript version... Possible explanations: + - Call overhead: https://github.com/WebAssembly/design/issues/1120 + - Having to copy whole input string in buffer before call. + +var HNTrie16wasm = (function() { + var module; + var instance; + var memory; + var memoryOrigin = 0; + var memoryUsed = 1024; + var cbuffer; + var tbuffer; + var tbufferSize = 0; + var matchesFn; + + var init = function() { + module = new WebAssembly.Module(new Uint8Array([0,97,115,109,1,0,0,0,1,139,128,128,128,0,2,96,2,127,127,1,127,96,0,1,127,3,131,128,128,128,0,2,0,1,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,172,128,128,128,0,3,6,109,101,109,111,114,121,2,0,7,109,97,116,99,104,101,115,0,0,21,103,101,116,76,105,110,101,97,114,77,101,109,111,114,121,79,102,102,115,101,116,0,1,10,217,130,128,128,0,2,202,130,128,128,0,1,5,127,32,1,65,1,116,65,12,106,33,3,32,0,65,1,116,65,140,8,106,34,2,33,0,2,64,2,64,2,64,2,64,2,64,2,64,3,64,65,0,33,5,2,64,32,3,65,12,77,13,0,32,3,65,126,106,34,3,47,1,0,33,5,11,2,64,32,5,32,0,47,1,4,34,1,70,13,0,2,64,32,5,65,46,71,13,0,3,64,32,1,65,255,255,3,113,69,13,5,32,0,47,1,0,34,1,69,13,6,32,2,32,1,65,1,116,106,34,0,47,1,4,34,1,65,46,71,13,0,12,2,11,11,3,64,32,0,47,1,0,34,1,69,13,3,32,5,32,2,32,1,65,1,116,106,34,0,47,1,4,71,13,0,11,11,65,1,33,6,32,5,69,13,5,2,64,2,64,32,0,47,1,6,34,1,69,13,0,32,3,32,1,65,1,116,107,65,12,73,13,8,32,1,65,127,115,33,5,32,0,65,8,106,33,1,3,64,32,5,65,1,106,34,5,69,13,1,32,1,47,1,0,33,4,32,1,65,2,106,33,1,32,4,32,3,65,126,106,34,3,47,1,0,70,13,0,12,2,11,11,32,0,47,1,2,34,1,69,13,5,32,2,32,1,65,1,116,106,33,0,12,1,11,11,65,0,15,11,65,0,15,11,65,1,15,11,65,0,15,11,32,3,65,12,70,13,0,32,3,65,126,106,47,1,0,65,46,70,33,6,11,32,6,15,11,65,0,11,132,128,128,128,0,0,65,12,11])); + instance = new WebAssembly.Instance(module); + memory = instance.exports.memory; + memoryOrigin = instance.exports.getLinearMemoryOffset(); + cbuffer = new Uint16Array(memory.buffer, memoryOrigin, 512); + tbuffer = new Uint16Array(memory.buffer, memoryOrigin + 1024); + memoryUsed = memoryOrigin + 1024; + matchesFn = instance.exports.matches; + }; + + return { + create: function(data) { + if ( module === undefined ) { init(); } + var bytesNeeded = memoryUsed + ((data.length * 2 + 3) & ~3); + if ( bytesNeeded > memory.buffer.byteLength ) { + memory.grow((bytesNeeded - memory.buffer.byteLength + 65535) >>> 16); + cbuffer = new Uint16Array(memory.buffer, memoryOrigin, 512); + tbuffer = new Uint16Array(memory.buffer, memoryOrigin + 1024); + } + for ( var i = 0, j = tbufferSize; i < data.length; i++, j++ ) { + tbuffer[j] = data[i]; + } + var id = tbufferSize; + tbufferSize += data.length; + if ( tbufferSize & 1 ) { tbufferSize += 1; } + memoryUsed += tbufferSize * 2; + return id; + }, + reset: function() { + module = undefined; + instance = undefined; + memory = undefined; + memory.grow(1); + memoryUsed = 1024; + cbuffer = undefined; + tbuffer = undefined; + tbufferSize = 0; + }, + matches: function(id, hn) { + var len = hn.length; + if ( len > 512 ) { + hn = hn.slice(-512); + var pos = hn.indexOf('.'); + if ( pos !== 0 ) { + hn = hn.slice(pos + 1); + } + len = hn.length; + } + var needle = cbuffer, i = len; + while ( i-- ) { + needle[i] = hn.charCodeAt(i); + } + return matchesFn(id, len) === 1; + } + }; +})(); +*/