Skip to content

WIP: Support for mutable global imports/exports#1644

Closed
jayphelps wants to merge 2 commits intoWebAssembly:masterfrom
jayphelps:mut-global
Closed

WIP: Support for mutable global imports/exports#1644
jayphelps wants to merge 2 commits intoWebAssembly:masterfrom
jayphelps:mut-global

Conversation

@jayphelps
Copy link
Contributor

@jayphelps jayphelps commented Aug 26, 2018

Wanted to open the conversation around adding support for mutable global imports/exports so I made what I think are most of the necessary changes--I'm probably missing some parts in one of the tools.

I'm also ran into some issues with check.py and auto_update_tests.py on MacOS but we can discuss those in #1185


No worries if this PR isn't merged, I mostly did the work to unblock myself for now 🌮

ExternalKind kind;
Name functionType; // for Function imports
Type globalType; // for Global imports
bool mutable_; // for Global imports
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels dirty but seemed like a simple solution without deciding to completely rethink about imports/globals are represented

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable to me. Might be nice to eventually think about a union or other cleaner approach, but Imports are not that common, so I'm not worried about it.

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Good start, everything looks correct to me aside from the one comment below on reading of SetGlobals.

return;
}
throwError("bad set_global");
curr->finalize();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be missing something, but I don't think the code added to this function is needed - the type of SetGlobal is always none, as it does not return a value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're not missing something, I was! You are correct and it actually explains why some codegen around the tests were adding in a drop. Great catch.

@kripken
Copy link
Member

kripken commented Aug 26, 2018

Otherwise, we have a FeatureSet concept at the top of wasm.h, currently with a flag for atomics. Not sure if we intend to add a flag for every new feature, or if mutable global imports in particular - @dschuff, thoughts?

Other things we'll need here eventually:

  • wasm-interpreter.h support.
  • Tests.
  • Fuzzer support.
  • Optimizer support, if we decide it's worth it.

@kripken
Copy link
Member

kripken commented Aug 26, 2018

Oh, and about tests: auto_update_tests.py runs the tests and updates their outputs. So you can add a test input, run that script, and then git add and commit the output. Then check.py will check that output is the same when it is run.

For this feature, we might want to add the spec tests, but we haven't in a while and I'm not sure it's worth the effort. Otherwise, can add test/mutable-global.wast with some code, and then the test suite will convert it to binary and back, so if you run the auto script it will generate an output like test/mutable-global.wast.fromBinary or something like that.

Copy link
Contributor Author

@jayphelps jayphelps left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test, and some fixes that the test revealed, however it also caused some other tests to change to mutable and it's not clear why. I'll continue digging but if you happen to know immediately why lmk.

o << "(mut " << printType(curr->globalType) << ")";
} else {
o << printType(curr->globalType) << ' ';
o << printType(curr->globalType);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test revealed that I had incorrectly added spaces here

im->kind = ExternalKind::Global;
im->globalType = type;
if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
im->mutable_ = mutable_;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testing revealed I missed adding the support to this file.

(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kripken It's not clear why all these changed to mutable. Perhaps this is revealing a bug I introduced?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! Is it because those asmjs globals were actually mutable but previously we couldn’t represent that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting - I think that's a coincidence actually, but a good one here as it pointed out something useful :) What I think is going on is that we forgot an initial value for bool mutable_; (unlike the other fields near it, it doesn't have a default value) - we should set that to bool mutable_ = false;.

It's also a good question what we should do for asm.js imports. Yeah, in asm.js they are mutable, and to work around that in wasm we created a mutable global with the initial value of the import, then we just use that global from then on. In theory we could simplify that to use a mutable import, however, I think it would be more complicated than it would be worth since we do want the old form supported too (and also a mutable import may have perf overhead).

@jayphelps
Copy link
Contributor Author

jayphelps commented Aug 29, 2018

Fixed bool mutable_ = false; default, rebuilt tests, however I needed to update the testsuite/spec files to pick up mutual global support and in doing so it opened a big old can of worms with incompatibilities 😱. I also couldn't find an intermediate commit we can use to ship this. I've been digging through them for a while now, so far biggest ones are the renaming of memory instructions (e.g. grow_memory -> memory.grow) and numerous tests now mix stack/sexprs which binaryen doesn't support. Gonna see how far I get. If I'm not back in a few days send help ☠️🏳️

@binji
Copy link
Member

binji commented Aug 29, 2018

and numerous tests now mix stack/sexprs which binaryen doesn't support.

You could use wat-desugar --fold to convert from flat format to folded format, if the flat format is not essential to the test. It would be a bit tedious, since it currently only works on individual modules, however.

@jayphelps
Copy link
Contributor Author

jayphelps commented Aug 29, 2018

@binji thanks for the tip--I really do appreciate it. Unfortunately wat-desugar strips comments and also removes some extraneous code that are part of the test (like deeply nested blocks). But lmk if I'm misunderstanding!

@binji
Copy link
Member

binji commented Aug 29, 2018

Yes, it will remove comments (it'd be nice if the wabt parser kept them around for tools like this). It shouldn't remove blocks though; if you have a repro case I'd like to fix that.

But yeah, you can't just run it directly, but you could use it to help fold code rather than doing it by hand.

@jayphelps
Copy link
Contributor Author

if you have a repro case I'd like to fix that

turns out I was looking at the git diff incorrectly. What actually happened is that it put the export outside instead of inline--my eye saw the export "deep" and thought the code was removed. Sorry about that!

(func (export "deep") (result i32)
    (block (result i32) (block (result i32)

        (; etc...I removed the rest for comment readability ;)

                                        (block (result i32) (block (result i32)
                                          (call $dummy) (i32.const 150)
                                        ))
                                      ))
                                    ))
                                  ))
                                ))
                              ))
                            ))
                          ))
                        ))
                      ))
                    ))
                  ))
                ))
              ))
            ))
          ))
        ))
      ))
    ))
  )
(func (;5;) (result i32)
    (block (result i32)  ;; label = @1
      (block (result i32)  ;; label = @2

        (; etc...I removed the rest for comment readability ;)

                                                                            (block (result i32)  ;; label = @37
                                                                              (block (result i32)  ;; label = @38
                                                                                (call $dummy)
                                                                                (i32.const 150))))))))))))))))))))))))))))))))))))))))
  (export "deep" (func 5))

@binji
Copy link
Member

binji commented Aug 29, 2018

What actually happened is that it put the export outside instead of inline

Oh, there should be an option for that, but it looks like it's only in wasm2wat and not wat-desugar. 😅

@kripken
Copy link
Member

kripken commented Aug 29, 2018

however I needed to update the testsuite/spec files to pick up mutual global support and in doing so it opened a big old can of worms with incompatibilities

Ah yes, I was worried about that. It might not be worth the effort - I think it would be reasonable instead to just get the relevant mutable global tests directly. Specifically, we can replace the git submodule with just checked-in files (since we've diverged from upstream anyhow) of the current state, then add that one file (assuming it's in a new file).

@sbc100
Copy link
Member

sbc100 commented Nov 29, 2018

Do you still want to land this?

I'd would like to see mutable global support in binaryen.

sbc100 added a commit that referenced this pull request Nov 29, 2018
This picks up from #1644 and indeed borrows the test case from there.
sbc100 added a commit that referenced this pull request Nov 30, 2018
This picks up from #1644 and indeed borrows the test case from there.
sbc100 added a commit that referenced this pull request Nov 30, 2018
This picks up from #1644 and indeed borrows the test case from there.
@sbc100
Copy link
Member

sbc100 commented Nov 30, 2018

I think this should be covered now by #1785 and

@sbc100 sbc100 closed this Nov 30, 2018
@jayphelps
Copy link
Contributor Author

Thanks @sbc100! I had ran into a blocker with the spec test suite but if it passed for you it must have since been resolved. Woot woot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants