tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

externref-boxing-struct.js (2947B)


      1 // Moving a JS value through a wasm externref is a pair of boxing/unboxing
      2 // conversions that leaves the value unchanged.  There are many cases,
      3 // along these axes:
      4 //
      5 //  - global variables, see externref-boxing.js
      6 //  - tables, see externref-boxing.js
      7 //  - function parameters and returns, see externref-boxing.js
      8 //  - struct fields [for the gc feature], this file
      9 //  - WasmGcObject fields when we construct with the externref type; this file
     10 
     11 // Struct fields of externref type can receive their value in these ways:
     12 //
     13 // - the struct.new and struct.set instructions
     14 // - storing into mutable fields from JS
     15 // - from a constructor called from JS
     16 //
     17 // Struct fields can be read in these ways:
     18 //
     19 // - the struct.get instruction
     20 // - reading the field from JS
     21 //
     22 // We're especially interested in two cases: where JS stores a non-object value
     23 // into a field, in this case there should be boxing; and where JS reads a
     24 // non-pointer value from a field, in this case there should be unboxing.
     25 
     26 // Write with struct.new, read with the JS getter
     27 
     28 for (let v of WasmExternrefValues)
     29 {
     30    let ins = wasmEvalText(
     31        `(module
     32           (type $S (struct (field $S.x (mut externref))))
     33           (func (export "make") (param $v externref) (result eqref)
     34             (struct.new $S (local.get $v))))`);
     35    let x = ins.exports.make(v);
     36    assertEq(wasmGcReadField(x, 0), v);
     37 }
     38 
     39 // Try to make sure externrefs are properly traced
     40 
     41 {
     42    let fields = iota(10).map(() => `(field externref)`).join(' ');
     43    let params = iota(10).map((i) => `(param $${i} externref)`).join(' ');
     44    let args = iota(10).map((i) => `(local.get $${i})`).join(' ');
     45    let txt = `(module
     46                 (type $S (struct ${fields}))
     47                 (func (export "make") ${params} (result eqref)
     48                   (struct.new $S ${args})))`;
     49    let ins = wasmEvalText(txt);
     50    let x = ins.exports.make({x:0}, {x:1}, {x:2}, {x:3}, {x:4}, {x:5}, {x:6}, {x:7}, {x:8}, {x:9})
     51    gc('shrinking');
     52    assertEq(typeof wasmGcReadField(x, 0), "object");
     53    assertEq(wasmGcReadField(x, 0).x, 0);
     54    assertEq(typeof wasmGcReadField(x, 1), "object");
     55    assertEq(wasmGcReadField(x, 1).x, 1);
     56    assertEq(typeof wasmGcReadField(x, 2), "object");
     57    assertEq(wasmGcReadField(x, 2).x, 2);
     58    assertEq(typeof wasmGcReadField(x, 3), "object");
     59    assertEq(wasmGcReadField(x, 3).x, 3);
     60    assertEq(typeof wasmGcReadField(x, 4), "object");
     61    assertEq(wasmGcReadField(x, 4).x, 4);
     62    assertEq(typeof wasmGcReadField(x, 5), "object");
     63    assertEq(wasmGcReadField(x, 5).x, 5);
     64    assertEq(typeof wasmGcReadField(x, 6), "object");
     65    assertEq(wasmGcReadField(x, 6).x, 6);
     66    assertEq(typeof wasmGcReadField(x, 7), "object");
     67    assertEq(wasmGcReadField(x, 7).x, 7);
     68    assertEq(typeof wasmGcReadField(x, 8), "object");
     69    assertEq(wasmGcReadField(x, 8).x, 8);
     70    assertEq(typeof wasmGcReadField(x, 9), "object");
     71    assertEq(wasmGcReadField(x, 9).x, 9);
     72 }