Services.prefs.setBoolPref("javascript.options.wasm_tail_calls", true);
registerCleanupFunction(() => {
  Services.prefs.clearUserPref("javascript.options.wasm_tail_calls");
});

// The tests runs code in tight loop with the profiler enabled. It is testing
// behavoir of MacroAssembler::wasmCollapseFrameXXXX methods.
// It is not guarantee 100% hit since the profiler probes stacks every 1ms,
// but it will happen often enough.
add_task(async () => {
  await Services.profiler.StartProfiler(10, 1, ["js"], ["GeckoMain"]);
  Assert.ok(Services.profiler.IsActive());

/* Wasm module that is tested:
(module
    (func $f (param i64 i64 i64 i64 i64 i64 i64 i64 i64)
        local.get 0
        i64.eqz
        br_if 0
        local.get 0
        return_call $g
    )
    (func $g (param i64)
        local.get 0
        i64.const 1
        i64.sub
        i64.const 2
        i64.const 6
        i64.const 3
        i64.const 4
        i64.const 1
        i64.const 2
        i64.const 6
        i64.const 3
        return_call $f
    )
    (func (export "run")
        i64.const 0x100000
        call $g
    )
)
*/

  const b = new Uint8Array([
    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x14, 0x03, 0x60,
    0x09, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x60,
    0x01, 0x7e, 0x00, 0x60, 0x00, 0x00, 0x03, 0x04, 0x03, 0x00, 0x01, 0x02,
    0x07, 0x07, 0x01, 0x03, 0x72, 0x75, 0x6e, 0x00, 0x02, 0x0a, 0x31, 0x03,
    0x0b, 0x00, 0x20, 0x00, 0x50, 0x0d, 0x00, 0x20, 0x00, 0x12, 0x01, 0x0b,
    0x19, 0x00, 0x20, 0x00, 0x42, 0x01, 0x7d, 0x42, 0x02, 0x42, 0x06, 0x42,
    0x03, 0x42, 0x04, 0x42, 0x01, 0x42, 0x02, 0x42, 0x06, 0x42, 0x03, 0x12,
    0x00, 0x0b, 0x09, 0x00, 0x42, 0x80, 0x80, 0xc0, 0x00, 0x10, 0x01, 0x0b
  ]);
  const ins = new WebAssembly.Instance(new WebAssembly.Module(b));
  for (var i = 0; i < 100; i++) {
    ins.exports.run();
  }
  
  Assert.ok(true, "Done");
  await Services.profiler.StopProfiler();
});

add_task(async () => {
  await Services.profiler.StartProfiler(10, 1, ["js"], ["GeckoMain"]);
  Assert.ok(Services.profiler.IsActive());

/* Wasm modules that are tested:
(module (func (export "t")))

(module
    (import "" "t" (func $g))
    (table $t 1 1 funcref)

    (func $f (return_call_indirect $t (i32.const 0)))  
    (func (export "run") (param i64)
     loop
       local.get 0
       i64.eqz
       br_if 1
       call $f
       local.get 0
       i64.const 1
       i64.sub
       local.set 0
       br 0
     end
    )
    (elem (i32.const 0) $g)
)
*/
  const b0 = new Uint8Array([
    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60,
    0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x07, 0x05, 0x01, 0x01, 0x74, 0x00,
    0x00, 0x0a, 0x04, 0x01, 0x02, 0x00, 0x0b  
  ]);
  const ins0 = new WebAssembly.Instance(new WebAssembly.Module(b0));
  const b = new Uint8Array([
    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x60,
    0x00, 0x00, 0x60, 0x01, 0x7e, 0x00, 0x02, 0x06, 0x01, 0x00, 0x01, 0x74,
    0x00, 0x00, 0x03, 0x03, 0x02, 0x00, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01,
    0x01, 0x01, 0x07, 0x07, 0x01, 0x03, 0x72, 0x75, 0x6e, 0x00, 0x02, 0x09,
    0x07, 0x01, 0x00, 0x41, 0x00, 0x0b, 0x01, 0x00, 0x0a, 0x1f, 0x02, 0x07,
    0x00, 0x41, 0x00, 0x13, 0x00, 0x00, 0x0b, 0x15, 0x00, 0x03, 0x40, 0x20,
    0x00, 0x50, 0x0d, 0x01, 0x10, 0x01, 0x20, 0x00, 0x42, 0x01, 0x7d, 0x21,
    0x00, 0x0c, 0x00, 0x0b, 0x0b
  ]);
  const ins = new WebAssembly.Instance(new WebAssembly.Module(b), {"": {t: ins0.exports.t,},});
  for (var i = 0; i < 100; i++) {
    ins.exports.run(0x100000n);
  }

  Assert.ok(true, "Done");
  await Services.profiler.StopProfiler();
});

/**
 * All the tests are implemented with add_task, this starts them automatically.
 */
function run_test() {
  do_get_profile();
  run_next_test();
}
