tor-browser

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

casting.js (5927B)


      1 // Test all possible casting combinations of the following graph:
      2 //
      3 //  A1       A2
      4 //  |        |
      5 //  B1       B2
      6 //  | \      |
      7 //  C1  C2   C3
      8 //  | \      |
      9 //  D1  D2   D3
     10 //  | \      |
     11 //  E1  E2   E3
     12 //  | \      |
     13 //  F1  F2   F3
     14 //  | \      |
     15 //  G1  G2   G3
     16 //  | \      |
     17 //  H1  H2   H3
     18 //  | \      |
     19 //  I1  I2   I3
     20 //  | \      |
     21 //  J1  J2   J3
     22 //
     23 // NOTE: this object needs to be ordered such that parent definitions come
     24 // before children.  Note also, to be properly effective, these trees need to
     25 // have a depth of at least MinSuperTypeVectorLength as defined in
     26 // wasm/WasmCodegenConstants.h; keep it in sync with that.
     27 const TYPES = {
     28  'A1': { super: null },
     29  'A2': { super: null },
     30  'B1': { super: 'A1' },
     31  'B2': { super: 'A2' },
     32  'C1': { super: 'B1' },
     33  'C2': { super: 'B1', final: true },
     34  'C3': { super: 'B2' },
     35  'D1': { super: 'C1' },
     36  'D2': { super: 'C1', final: true },
     37  'D3': { super: 'C3' },
     38  'E1': { super: 'D1' },
     39  'E2': { super: 'D1', final: true },
     40  'E3': { super: 'D3' },
     41  'F1': { super: 'E1' },
     42  'F2': { super: 'E1', final: true },
     43  'F3': { super: 'E3' },
     44  'G1': { super: 'F1' },
     45  'G2': { super: 'F1', final: true },
     46  'G3': { super: 'F3' },
     47  'H1': { super: 'G1' },
     48  'H2': { super: 'G1', final: true },
     49  'H3': { super: 'G3' },
     50  'I1': { super: 'H1' },
     51  'I2': { super: 'H1', final: true },
     52  'I3': { super: 'H3' },
     53  'J1': { super: 'I1' },
     54  'J2': { super: 'I1', final: true },
     55  'J3': { super: 'I3' },
     56 };
     57 
     58 // The oracle method for testing the declared subtype relationship.
     59 function manualIsSubtype(types, subType, superType) {
     60  while (subType !== superType && subType.super !== null) {
     61    subType = types[subType.super];
     62  }
     63  return subType === superType;
     64 }
     65 
     66 function makeAnyModule(types) {
     67  let typeSection = ``;
     68  let funcSection = ``;
     69  for (let name in types) {
     70    let type = types[name];
     71    typeSection += `(type \$${name} (sub ${type.final ? "final" : ""} ${type.super ? "$" + type.super : ""} (struct)))\n`;
     72    funcSection += `(func (export "new${name}") (result externref)
     73      struct.new_default \$${name}
     74      extern.convert_any
     75    )\n`;
     76    funcSection += `(func (export "is${name}") (param externref) (result i32)
     77      local.get 0
     78      any.convert_extern
     79      ref.test (ref \$${name})
     80    )\n`;
     81  }
     82  // NOTE: we place all types in a single recursion group to prevent
     83  // canonicalization from combining them into a single type.
     84  return `(module
     85    (rec ${typeSection})
     86    ${funcSection}
     87  )`;
     88 }
     89 
     90 function makeFuncModule(types) {
     91  let typeSection = ``;
     92  let funcSection = ``;
     93  for (let name in types) {
     94    let type = types[name];
     95    typeSection += `(type \$${name} (sub ${type.final ? "final" : ""} ${type.super ? "$" + type.super : ""} (func)))\n`;
     96    funcSection += `(func \$f${name} (type \$${name}))\n`;
     97    funcSection += `(func (export "new${name}") (result funcref)
     98      ref.func \$f${name}
     99    )\n`;
    100    funcSection += `(func (export "is${name}") (param funcref) (result i32)
    101      local.get 0
    102      ref.test (ref \$${name})
    103    )\n`;
    104  }
    105 
    106  const elemSection = `(elem declare func ${Object.keys(types).map(name => `\$f${name}`).join(" ")})`;
    107 
    108  // NOTE: we place all types in a single recursion group to prevent
    109  // canonicalization from combining them into a single type.
    110  return `(module
    111    (rec ${typeSection})
    112    ${elemSection}
    113    ${funcSection}
    114  )`;
    115 }
    116 
    117 function testAllCasts(types, moduleText) {
    118  // Instantiate the module and acquire the testing methods
    119  let exports = wasmEvalText(moduleText).exports;
    120  for (let name in types) {
    121    let type = types[name];
    122    type['new'] = exports[`new${name}`];
    123    type['is'] = exports[`is${name}`];
    124  }
    125 
    126  // Test every combination of types, comparing the oracle method against the
    127  // JIT'ed method.
    128  for (let subTypeName in types) {
    129    let subType = types[subTypeName];
    130    for (let superTypeName in types) {
    131      let superType = types[superTypeName];
    132      assertEq(
    133        manualIsSubtype(types, subType, superType) ? 1 : 0,
    134        superType['is'](subType['new']()));
    135    }
    136  }
    137 }
    138 testAllCasts(TYPES, makeAnyModule(TYPES));
    139 testAllCasts(TYPES, makeFuncModule(TYPES));
    140 
    141 // Test that combinations of ref.test and ref.cast compile correctly.
    142 // (These can be optimized together.)
    143 {
    144  const { make, test1, test2, test3, test4 } = wasmEvalText(`(module
    145    (type $a (array i32))
    146    (func (export "make") (param i32) (result anyref)
    147      local.get 0
    148      local.get 0
    149      array.new_fixed $a 2
    150    )
    151    (func (export "test1") (param anyref) (result i32)
    152      (if (ref.test (ref $a) (local.get 0))
    153        (then
    154          (ref.cast (ref $a) (local.get 0))
    155          (array.get $a (i32.const 0))
    156          return
    157        )
    158      )
    159      i32.const -1
    160    )
    161    (func (export "test2") (param anyref) (result i32)
    162      (if (ref.test (ref $a) (local.get 0))
    163        (then)
    164        (else
    165          (ref.cast (ref $a) (local.get 0))
    166          (array.get $a (i32.const 0))
    167          return
    168        )
    169      )
    170      i32.const -1
    171    )
    172    (func (export "test3") (param anyref) (result i32)
    173      (if (ref.test (ref $a) (local.get 0))
    174        (then
    175          (if (ref.test (ref $a) (local.get 0))
    176            (then)
    177            (else
    178              (ref.cast (ref $a) (local.get 0))
    179              (array.get $a (i32.const 0))
    180              return
    181            )
    182          )
    183        )
    184      )
    185      i32.const -1
    186    )
    187    (func (export "test4") (param anyref) (result i32)
    188      (if (ref.test (ref $a) (local.get 0))
    189        (then
    190          (if (ref.test (ref $a) (local.get 0))
    191            (then
    192              local.get 0
    193              ref.cast (ref $a)
    194              ref.cast (ref $a)
    195              (array.get $a (i32.const 0))
    196              return
    197            )
    198          )
    199        )
    200      )
    201      i32.const -1
    202    )
    203  )`).exports;
    204  assertEq(test1(make(99)), 99);
    205  assertEq(test2(make(99)), -1);
    206  assertEq(test3(make(99)), -1);
    207  assertEq(test4(make(99)), 99);
    208 }