Skip to content

Memory bug on Windows x64 #52

Closed

Description

@kg

On my x64 Windows 10 box memory.wasm fails mysteriously:

-- Assert invoking...
Result: 42. : f64
Expect: 42. : f64
-- Error:
test/memory.wasm:151.1-151.45: assertion failed

Not sure what's going on here, don't know ocaml well enough to debug.

Activity

  1. lukewagner commented on Sep 8, 2015

    @lukewagner
    Member

    I'm guessing that, though the text strings are identical, the float bits don't line up. I think you can confirm by changing the float case of values.ml:string_of_value to return Int64.to_string (Int64.of_float z).

  2. kg commented on Sep 8, 2015

    @kg
    ContributorAuthor

    Int64.to_string (Int64.of_float z) just prints '42'.

  3. lukewagner commented on Sep 8, 2015

    @lukewagner
    Member

    Oops, I meant Int64.bits_of_float, not Int64.of_float.

  4. kg commented on Sep 8, 2015

    @kg
    ContributorAuthor

    Yeah, that's the problem:

    Result: 4631107791820423180 : f64
    Expect: 4631107791820423168 : f64
    

    I'm not sure what to do about this. Does this indicate that our implementation is actually incorrect, at least on this os/arch combination?

  5. kg commented on Sep 8, 2015

    @kg
    ContributorAuthor

    Also fails:

    (assert_eq (invoke "cast") (f64.convert_s/i32 (i32.const 42)))
    
  6. pjuftring commented on Sep 14, 2015

    @pjuftring
    Contributor

    I compared the disassembled code of the windows-version of main.native with the linux-version and noticed, that windows only makes use of fpu commands, while linux uses SSE-like commands. Could this make the difference?

  7. kg commented on Sep 14, 2015

    @kg
    ContributorAuthor

    x87 vs SSE was my guess as well. I guess wasm on windows is doing 80-bit arithmetic and truncating, then?

  8. sunfishcode commented on Sep 14, 2015

    @sunfishcode
    Member

    There are ways that using x87 (fpu) instructions instead of SSE instructions can causes differences, but in the testcase here, all the values are small whole integers, so we ought to get the same answer regardless of which floating point unit is used.

  9. sunfishcode commented on Sep 15, 2015

    @sunfishcode
    Member

    @kg Would you mind trying a few more experiments:

    • modify the cast function to replace the last two stores with a single store of 4631107791820423168 to address 9 directly
    • change the store and subsequent load to use an aligned address instead of address 9
    • change the return value of the cast function to (f64.const 42.0) instead of doing a load
    • change the return value of the cast function to (f64.convert_s/i32 (i32.const 42))
  10. kg commented on Sep 15, 2015

    @kg
    ContributorAuthor

    Sure thing, I'll try all that the next time I'm at home.

  11. AndrewScheidecker commented on Sep 22, 2015

    @AndrewScheidecker
    Contributor

    I'm running the 32-bit ocaml build on Windows that the ml-prototype README recommends. Before this change, I see the same thing as @kg. With that change, I get a segfault running either the unaligned or cast assert_eqs in memory.wasm. I narrowed it down to something triggered by using the result of a f64.load. Some testing shows that it can evaluate this without crashing:

        (i32.store (i32.const 8) (i32.const 0))
        (i64.store (i32.const 8) (i64.const 0))
        (f32.store (i32.const 8) (f32.const 0))
        (f64.store (i32.const 8) (f64.const 0))
        (i32.load (i32.const 8))
        (i64.load (i32.const 8))
        (f32.load (i32.const 8))
        (f64.load (i32.const 8))
        (i32.eq (i32.load (i32.const 8)) (i32.const 0))
        (i64.eq (i64.load (i32.const 8)) (i64.const 0))
        (f32.eq (f32.load (i32.const 8)) (f32.const 0))
    

    But either of these operations will cause a segfault:

        (f64.eq (f64.load (i32.const 8)) (f64.const 0))
        (f64.add (f64.load (i32.const 8)) (f64.const 0))
    

    I am highly suspicious of the Obj.magic in the memory module.

  12. maurer commented on Sep 22, 2015

    @maurer

    It may be possible to use Genarray.map_file to produce differently typed views of the same memory without using Obj.magic.

    I would expect this would prevent the unusual segfault behavior that people are seeing.

  13. added a commit that references this issue on Sep 18, 2019
  14. added a commit that references this issue on Mar 2, 2023
  15. added a commit that references this issue on Nov 6, 2024
  16. added a commit that references this issue on Nov 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions