summaryrefslogtreecommitdiff
path: root/src/js/post.js
blob: a4a80ddd165d23507ae8f1d496ccf016823155e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

function integrateWasmJS(Module) {
  if (typeof WASM === 'object') {
    // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate
    // the wasm module at that time, and it receives imports and provides exports and so forth, the app
    // doesn't need to care that it is wasm and not asm.
    Module['asm'] = function(global, env, providedBuffer) {
      // Load the binary wasm module
      var filename = Module['wasmCodeFile'];
      var binary;
      if (typeof read === 'function') {
        // spidermonkey or v8 shells
        if (typeof readbuffer === 'function') {
          binary = new Uint8Array(readbuffer(filename));
        } else {
          binary = read(f, 'binary');
        }
      } else if (typeof process === 'object' && typeof require === 'function') {
        // node.js
        binary = require('fs')['readFileSync'](filename);
        if (!binary.buffer) { // handle older node.js not returning a proper typed array
          binary = new Uint8Array(ret);
        }
      } else {
        throw 'TODO: binary loading in other platforms';
      }
      assert(binary.buffer);
      // Create an instance of the module using native support in the JS engine.
      var instance = WASM.instantiateModule(binary, {
        "global.Math": global.Math,
        "env": env
      });
      // The wasm instance creates its memory. But static init code might have written to
      // buffer already, and we must copy it over.
      // TODO: avoid this copy, by avoiding such static init writes
      // TODO: in shorter term, just copy up to the last static init write
      var oldBuffer = Module['buffer'];
      var newBuffer = instance.memory;
      assert(newBuffer.byteLength >= oldBuffer.byteLength, 'we might fail if we allocated more than TOTAL_MEMORY');
      (new Int8Array(newBuffer)).set(new Int8Array(oldBuffer));
      updateGlobalBuffer(newBuffer);
      updateGlobalBufferViews();
      Module['reallocBuffer'] = function(size) {
        abort('no memory growth quite yet, but easy to add');
      };
      return instance;
    };
    return;
  }

  // Use wasm.js to polyfill and execute code in a wasm interpreter.
  var wasmJS = WasmJS({});

  // XXX don't be confused. Module here is in the outside program. wasmJS is the inner wasm-js.cpp.
  wasmJS['outside'] = Module; // Inside wasm-js.cpp, Module['outside'] reaches the outside module.

  // Information for the instance of the module.
  var info = wasmJS['info'] = {
    global: null,
    env: null,
    asm2wasm: { // special asm2wasm imports
      "f64-rem": function(x, y) {
        return x % y;
      },
      "f64-to-int": function(x) {
        return x | 0;
      },
      "debugger": function() {
        debugger;
      },
    },
    parent: Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program.
  };

  wasmJS['lookupImport'] = function(mod, base) {
    var lookup = info;
    if (mod.indexOf('.') < 0) {
      lookup = (lookup || {})[mod];
    } else {
      var parts = mod.split('.');
      lookup = (lookup || {})[parts[0]];
      lookup = (lookup || {})[parts[1]];
    }
    lookup = (lookup || {})[base];
    if (lookup === undefined) {
      abort('bad lookupImport to (' + mod + ').' + base);
    }
    return lookup;
  }

  // The asm.js function, called to "link" the asm.js module. At that time, we are provided imports
  // and respond with exports, and so forth.
  Module['asm'] = function(global, env, providedBuffer) {
    assert(providedBuffer === Module['buffer']); // we should not even need to pass it as a 3rd arg for wasm, but that's the asm.js way.

    // Generate a module instance of the asm.js converted into wasm.
    var code;
    if (typeof read === 'function') {
      // spidermonkey or v8 shells
      code = read(Module['asmjsCodeFile']);
    } else if (typeof process === 'object' && typeof require === 'function') {
      // node.js
      code = require('fs')['readFileSync'](Module['asmjsCodeFile']).toString();
    } else {
      throw 'TODO: loading in other platforms';
    }

    // wasm code would create its own buffer, at this time. But static init code might have
    // written to the buffer already, and we must copy it over. We could just avoid
    // this copy in wasm.js polyfilling, but to be as close as possible to real wasm,
    // we do what wasm would do.
    // TODO: avoid this copy, by avoiding such static init writes
    // TODO: in shorter term, just copy up to the last static init write
    var oldBuffer = Module['buffer'];
    var newBuffer = ArrayBuffer(oldBuffer.byteLength);
    (new Int8Array(newBuffer)).set(new Int8Array(oldBuffer));
    updateGlobalBuffer(newBuffer);
    updateGlobalBufferViews();
    wasmJS['providedTotalMemory'] = Module['buffer'].byteLength;

    Module['reallocBuffer'] = function(size) {
      var old = Module['buffer'];
      wasmJS['asmExports']['__growWasmMemory'](size); // tiny wasm method that just does grow_memory
      return Module['buffer'] !== old ? Module['buffer'] : null; // if it was reallocated, it changed
    };

    var temp = wasmJS['_malloc'](code.length + 1);
    wasmJS['writeAsciiToMemory'](code, temp);
    wasmJS['_load_asm'](temp);
    wasmJS['_free'](temp);

    // write the provided data to a location the wasm instance can get at it.
    info.global = global;
    info.env = env;
    wasmJS['_load_mapped_globals'](); // now that we have global and env, we can ready the provided imported globals, copying them to their mapped locations.
    return wasmJS['asmExports'];
  };
}