Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ref-struct.js   Sprache: JAVA

 
// |jit-test| test-also=--gc-zeal=2

// We'll be running some binary-format tests shortly.

load(libdir + "wasm-binary.js");

const v2vSigSection = sigSection([{args:[], ret:VoidCode}]);

function checkInvalid(body, errorMessage) {
    assertErrorMessage(() => new WebAssembly.Module(
        moduleWithSections([v2vSigSection,
                            declSection([0]),
                            bodySection([body])])),
                       WebAssembly.CompileError,
                       errorMessage);
}

// General test case for struct.new, struct.get, and struct.set: binary tree
// manipulation.

{
    let bin = wasmTextToBinary(
        `(module
          (import "" "print_lp" (func $print_lp))
          (import "" "print_rp" (func $print_rp))
          (import "" "print_int" (func $print_int (param i32)))

          (type $wabbit (struct
                         (field $x (mut i32))
                         (field $left (mut (ref null $wabbit)))
                         (field $right (mut (ref null $wabbit)))))

          (global $g (mut (ref null $wabbit)) (ref.null $wabbit))

          (global $k (mut i32) (i32.const 0))

          (func (export "init") (param $n i32)
                (global.set $g (call $make (local.get $n))))

          (func $make (param $n i32) (result (ref null $wabbit))
                (local $tmp i32)
                (local.set $tmp (global.get $k))
                (global.set $k (i32.add (local.get $tmp) (i32.const 1)))
                (if (result (ref null $wabbit)) (i32.le_s (local.get $n) (i32.const 2))
                    (then (struct.new $wabbit (local.get $tmp) (ref.null $wabbit) (ref.null $wabbit)))
                    (else
                      (block (result (ref null $wabbit))
                      (struct.new $wabbit
                                  (local.get $tmp)
                                  (call $make (i32.sub (local.get $n) (i32.const 1)))
                                  (call $make (i32.sub (local.get $n) (i32.const 2))))))))

          (func (export "accumulate") (result i32)
                (call $accum (global.get $g)))

          (func $accum (param $w (ref null $wabbit)) (result i32)
                (if (result i32) (ref.is_null (local.get $w))
                    (then (i32.const 0))
                    (else
                      (i32.add (struct.get $wabbit 0 (local.get $w))
                             (i32.sub (call $accum (struct.get $wabbit 1 (local.get $w)))
                                      (call $accum (struct.get $wabbit 2 (local.get $w))))))))

          (func (export "reverse")
                (call $reverse (global.get $g)))

          (func $reverse (param $w (ref null $wabbit))
                (local $tmp (ref null $wabbit))
                (if (i32.eqz (ref.is_null (local.get $w)))
                    (then
                      (block
                        (struct.set $wabbit 0 (local.get $w) (i32.mul (i32.const 2) (struct.get $wabbit 0 (local.get $w))))
                        (local.set $tmp (struct.get $wabbit 1 (local.get $w)))
                        (struct.set $wabbit 1 (local.get $w) (struct.get $wabbit 2 (local.get $w)))
                        (struct.set $wabbit 2 (local.get $w) (local.get $tmp))
                        (call $reverse (struct.get $wabbit 1 (local.get $w)))
                        (call $reverse (struct.get $wabbit 2 (local.get $w)))))))

          (func (export "print")
                (call $pr (global.get $g)))

          (func $pr (param $w (ref null $wabbit))
                (if (i32.eqz (ref.is_null (local.get $w)))
                    (then 
                      (block
                        (call $print_lp)
                        (call $print_int (struct.get $wabbit 0 (local.get $w)))
                        (call $pr (struct.get $wabbit 1 (local.get $w)))
                        (call $pr (struct.get $wabbit 2 (local.get $w)))
                        (call $print_rp)))))
         )`);

    let s = "";
    function pr_int(k) { s += k + " "; }
    function pr_lp() { s += "(" };
    function pr_rp() { s += ")" }

    let mod = new WebAssembly.Module(bin);
    let ins = new WebAssembly.Instance(mod, {"":{print_int:pr_int,print_lp:pr_lp,print_rp:pr_rp}}).exports;

    ins.init(6);
    s = ""; ins.print(); assertEq(s, "(0 (1 (2 (3 (4 )(5 ))(6 ))(7 (8 )(9 )))(10 (11 (12 )(13 ))(14 )))");
    assertEq(ins.accumulate(), -13);

    ins.reverse();
    s = ""; ins.print(); assertEq(s, "(0 (20 (28 )(22 (26 )(24 )))(2 (14 (18 )(16 ))(4 (12 )(6 (10 )(8 )))))");
    assertEq(ins.accumulate(), 14);

    for (let i=10; i < 22; i++ ) {
        ins.init(i);
        ins.reverse();
        gc();
        ins.reverse();
    }
}

// Sanity check for struct.set: we /can/ store a (ref null T) into a (ref null U) field
// with struct.set if T <: U; this should fall out of normal coercion but good
// to test.

wasmEvalText(
    `(module
      (type $node (sub (struct (field (mut (ref null $node))))))
      (type $nix (sub $node (struct (field (mut (ref null $node))) (field i32))))
      (func $f (param $p (ref null $node)) (param $q (ref null $nix))
       (struct.set $node 0 (local.get $p) (local.get $q))))`);

// ref.cast: if the downcast succeeds we get the original pointer

assertEq(wasmEvalText(
  `(module
    (type $node (sub (struct (field i32))))
    (type $node2 (sub $node (struct (field i32) (field f32))))
    (func $f (param $p (ref null $node)) (result (ref null $node2))
     (ref.cast (ref null $node2) (local.get $p)))
    (func (export "test") (result i32)
     (local $n (ref null $node))
     (local.set $n (struct.new $node2 (i32.const 0) (f32.const 12)))
     (ref.eq (call $f (local.get $n)) (local.get $n))))`).exports.test(),
       1);

// ref.cast: if the pointer is null we trap

assertErrorMessage(() => wasmEvalText(
    `(module
      (type $node (struct (field i32)))
      (type $node2 (struct (field i32) (field f32)))
      (func $f (param $p (ref null $node)) (result (ref null $node2))
       (ref.cast (ref $node2) (local.get $p)))
      (func (export "test") (result eqref)
       (call $f (ref.null $node))))`).exports.test(),
    WebAssembly.RuntimeError,
    /bad cast/,
);

// ref.cast null: if the pointer is null we do not trap

wasmEvalText(
  `(module
    (type $node (struct (field i32)))
    (type $node2 (struct (field i32) (field f32)))
    (func $f (param $p (ref null $node)) (result (ref null $node2))
     (ref.cast (ref null $node2) (local.get $p)))
    (func (export "test") (result eqref)
     (call $f (ref.null $node))))`).exports.test();


// And once more with mutable fields

assertEq(wasmEvalText(
    `(module
      (type $node (sub (struct (field (mut i32)))))
      (type $node2 (sub $node (struct (field (mut i32)) (field f32))))
      (func $f (param $p (ref null $node)) (result (ref null $node2))
       (ref.cast (ref null $node2) (local.get $p)))
      (func (export "test") (result i32)
       (local $n (ref null $node))
       (local.set $n (struct.new $node2 (i32.const 0) (f32.const 12)))
       (ref.eq (call $f (local.get $n)) (local.get $n))))`).exports.test(),
         1);

// ref.cast: eqref -> struct when the eqref is the right struct;
// special case since eqref requires unboxing

assertEq(wasmEvalText(
    `(module
      (type $node (struct (field i32)))
      (func $f (param $p eqref) (result (ref null $node))
       (ref.cast (ref null $node) (local.get $p)))
      (func (export "test") (result i32)
       (local $n (ref null $node))
       (local.set $n (struct.new $node (i32.const 0)))
       (ref.eq (call $f (local.get $n)) (local.get $n))))`).exports.test(),
         1);

// Can default initialize a struct which zero initializes

{
  let {makeA, makeB, makeC} = wasmEvalText(`
  (module
   (type $a (struct))
   (type $b (struct (field i32) (field f32)))
   (type $c (struct (field eqref)))

   (func (export "makeA") (result eqref)
     struct.new_default $a
   )
   (func (export "makeB") (result eqref)
     struct.new_default $b
   )
   (func (export "makeC") (result eqref)
     struct.new_default $c
   )
  )`).exports;
  let a = makeA();

  let b = makeB();
  assertEq(wasmGcReadField(b, 0), 0);
  assertEq(wasmGcReadField(b, 1), 0);

  let c = makeC();
  assertEq(wasmGcReadField(c, 0), null);
}

// struct.new_default: valid if all struct fields are defaultable

wasmFailValidateText(`(module
  (type $a (struct (field (ref $a))))
  (func
    struct.new_default $a
  )
)`, /defaultable/);

wasmFailValidateText(`(module
  (type $a (struct (field i32) (field i32) (field (ref $a))))
  (func
    struct.new_default $a
  )
)`, /defaultable/);

// Negative tests

// Attempting to mutate immutable field with struct.set

assertErrorMessage(() => wasmEvalText(
    `(module
      (type $node (struct (field i32)))
      (func $f (param $p (ref null $node))
       (struct.set $node 0 (local.get $p) (i32.const 37))))`),
                   WebAssembly.CompileError,
                   /field is not mutable/);

// Attempting to store incompatible value in mutable field with struct.set

assertErrorMessage(() => wasmEvalText(
    `(module
      (type $node (struct (field (mut i32))))
      (func $f (param $p (ref null $node))
       (struct.set $node 0 (local.get $p) (f32.const 37))))`),
                   WebAssembly.CompileError,
                   /expression has type f32 but expected i32/);

// Out-of-bounds reference for struct.get

assertErrorMessage(() => wasmEvalText(
    `(module
      (type $node (struct (field i32)))
      (func $f (param $p (ref null $node)) (result i32)
       (struct.get $node 1 (local.get $p))))`),
                   WebAssembly.CompileError,
                   /field index out of range/);

// Out-of-bounds reference for struct.set

assertErrorMessage(() => wasmEvalText(
    `(module
      (type $node (struct (field (mut i32))))
      (func $f (param $p (ref null $node))
       (struct.set $node 1 (local.get $p) (i32.const 37))))`),
                   WebAssembly.CompileError,
                   /field index out of range/);

// Base pointer is of unrelated type to stated type in struct.get

assertErrorMessage(() => wasmEvalText(
    `(module
      (type $node (struct (field i32)))
      (type $snort (struct (field f64)))
      (func $f (param $p (ref null $snort)) (result i32)
       (struct.get $node 0 (local.get $p))))`),
                   WebAssembly.CompileError,
                   /expression has type.*but expected.*/);

// Base pointer is of unrelated type to stated type in struct.set

assertErrorMessage(() => wasmEvalText(
    `(module
      (type $node (struct (field (mut i32))))
      (type $snort (struct (field f64)))
      (func $f (param $p (ref null $snort)) (result i32)
       (struct.set $node 0 (local.get $p) (i32.const 0))))`),
                   WebAssembly.CompileError,
                   /expression has type.*but expected.*/);

// Null pointer dereference in struct.get

assertErrorMessage(function() {
    let ins = wasmEvalText(
        `(module
          (type $node (struct (field i32)))
          (func (export "test")
           (drop (call $f (ref.null $node))))
          (func $f (param $p (ref null $node)) (result i32)
           (struct.get $node 0 (local.get $p))))`);
    ins.exports.test();
},
                   WebAssembly.RuntimeError,
                   /dereferencing null pointer/);

// Null pointer dereference in struct.set

assertErrorMessage(function() {
    let ins = wasmEvalText(
        `(module
          (type $node (struct (field (mut i32))))
          (func (export "test")
           (call $f (ref.null $node)))
          (func $f (param $p (ref null $node))
           (struct.set $node 0 (local.get $p) (i32.const 0))))`);
    ins.exports.test();
},
                   WebAssembly.RuntimeError,
                   /dereferencing null pointer/);

Messung V0.5
C=92 H=97 G=94

¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge