Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove unnecessary restrictions around RTTI from wire.h #10914

Merged
merged 12 commits into from
Aug 24, 2020

Conversation

dnfield
Copy link
Contributor

@dnfield dnfield commented Apr 14, 2020

Fixes #6551

Removes the static_asserts that check if the type for a LightTypeID is_polymorphic. AFAICT, LightTypeID works fine with polymorphic types, and provides the same identity guarantees as when RTTI is enabled. Adds a test asserting such code compiles and runs correctly.

I'm still not clear why this restriction was in place - it may have been necessary in previous impelmentations, or perhaps with previous versions of LLVM/Clang. However, as far as I can tell, it's not necessary now and only limits options around doing non-RTTI builds with emscripten.

/cc @kjlubick, @yjbanov - this would help building CanvasKit with -fno-rtti, in part.

@welcome
Copy link

welcome bot commented Apr 14, 2020

Thank you for submitting a pull request! If this is your first PR, make sure to add yourself to AUTHORS.

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! This looks good to me, but like you, I'm not sure why this existed.

@chadaustin do you remember?

Also @jgravelle-google may have insights.

@@ -7121,7 +7121,7 @@ class std_string {
std::cout << txtTestString.data() << std::endl;
return 0;
}
''', '''std_string(const char* s)
''', '''std_string(const char* s)
Copy link
Member

Choose a reason for hiding this comment

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

the test failure may be due to this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahh whups, my editor was set to trim whitespace at EOL. Reverted that line.

@dnfield
Copy link
Contributor Author

dnfield commented Apr 14, 2020

@chinmaygarde knows lots more about C++ than I do, he might have some insight on this. Or maybe @jason-simmons

@abigailbunyan
Copy link
Contributor

This changes the behaviour in subtle ways, and I think it's potentially incorrect. Consider:

struct Base { virtual ~Base() {} };
struct Derived : Base { ~Derived(); };

TYPEID f() {
    Derived d;
    Base& b = d;
    const auto id = getLightTypeID(b);
};

Previously, f would return the TYPEID of Derived, now it returns the TYPEID of Base. This getLightTypeID function then becomes the getActualType function of the registered class, which looks like it would cause problems down the line.

@dnfield
Copy link
Contributor Author

dnfield commented Apr 16, 2020

@abigailbunyan is that just fine as long as you provide a factory constructor to embind?

Can you think of a sample program that would fail with this change? If nothing else, we should add it as a test to this repo.

@chadaustin
Copy link
Collaborator

I had a big comment written about how I didn't recall the context behind the check... but I think it's come back to me. :)

getLightTypeID returns the actual type ID of a potentially-polymorphic value. You can see its use in bind.h's _embind_register_class, which passes an instantiation of getActualType into JavaScript.

I don't know precisely what effect this change would have, but I think it might break code where a polymorphic base class pointer is passed to JavaScript, and JavaScript calls a derived class's bound methods on it.

If you can show that 1) we have tests for that scenario and 2) said tests pass with -fno-rtti, I'd support relaxing this constraint, even though I don't understand how it would work. :)

I seem to recall the cost of RTTI in our use of embind at IMVU not being high when everything was statically linked: only the referenced RTTI tables were include in the binary.

@dnfield
Copy link
Contributor Author

dnfield commented Apr 19, 2020

I'll see if I can make a test case for that. @chadaustin - this change allows Skia CanvasKit to compile as-is with -fno-rtti, which saves ~100kb on the WASM blob. I'm fairly confident there's no actual need for RTTI in that case, but it would still help to prove out the case you're describing.

@dnfield
Copy link
Contributor Author

dnfield commented Apr 19, 2020

@chadaustin - I'm having trouble constructing a case where this causes problems that don't already exist with RTTI. For example:

#include <emscripten/bind.h>
#include <memory>

#include <string>

class Poly {
public:
  virtual ~Poly() {}
  virtual std::string message() = 0;
  virtual Poly *get() = 0;
};

class PolyHi : public Poly {
public:
  std::string message() override { return std::string("Hi"); }
  Poly *get() override { return static_cast<Poly *>(this); }
  std::string nonVirtual() { return std::string("nonVirtual"); }
};

std::shared_ptr<Poly> MakePoly() { return std::make_shared<PolyHi>(); }
std::shared_ptr<PolyHi> MakePolyHi() { return std::make_shared<PolyHi>(); }

EMSCRIPTEN_BINDINGS(interface_tests) {
  emscripten::class_<Poly>("Poly")
      .smart_ptr_constructor("Poly", &MakePoly)
      .function("message", &Poly::message)
      .function("get", &Poly::get, emscripten::allow_raw_pointers());
  emscripten::class_<PolyHi>("PolyHi")
      .smart_ptr_constructor("PolyHi", &MakePolyHi)
      .function("message", &PolyHi::message)
      .function("get", &PolyHi::get, emscripten::allow_raw_pointers())
      .function("nonVirtual", &PolyHi::nonVirtual);
};

nonVirtual is not available on the object returned from get (in JavaScript) with or without RTTI. What am I missing?

@luigi-rosso
Copy link

Another 👍 for this PR. We ran into similar problems with this restriction when trying to compile with -fno-rtti. Using @dnfield's fork fixed the issue (compiles and no runtime issues). We have a bunch of abstract classes with pure virtual methods implemented in JS and no need for RTTI. We don't call any virtual methods from JS as @chadaustin was expressing concern over, however.

@kripken kripken added the embind label Jul 27, 2020
@kripken
Copy link
Member

kripken commented Aug 18, 2020

I haven't understood all the details here, so sorry if this is not helpful, but could we land this change guarded by #if !__has_feature(cxx_rtti)? That is, to change nothing when rtti is enabled, but if the user disabled it, to do what this PR does?

@dnfield
Copy link
Contributor Author

dnfield commented Aug 19, 2020

@kripken - I'm not quite sure I follow what you're suggesting.

This PR removes case where we assert if rtti is disabled. I have not been able to come up with a test that would fail with this change, although if there is one we should add it and could make a decision then about whether to reject this.

I can try to fix up the merge conflict if we want to move forward with this. It would be beneficial to Flutter users though.

@kripken
Copy link
Member

kripken commented Aug 20, 2020

@dnfield Oh, right, I had that backwards... yes, ignore my suggestion.

Rereading this, it looks like your attempted testcase should answer the question @chadaustin posed. It would be better to understand this more deeply (which I don't) but I think we have enough to move forward here.

In the worst case, if we did miss something here, and someone files a bug later, we can revert it (and we'd have a testcase). Let's add a mention in the Changelog for this, so that it will be easier to find in case there is such a report.

@dnfield
Copy link
Contributor Author

dnfield commented Aug 20, 2020

I think I fixed the merge conflict, hopefully I did it right :)

@dnfield
Copy link
Contributor Author

dnfield commented Aug 20, 2020

Updated the changelog, tests should all be good now.

};
'''
self.emcc_args += ['--bind', '-fno-rtti', '-DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0']
self.do_run(src, 'Hello, world.\nfoo.test() returned: 42\n')
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you put this code into test/core/test_embind_polymorphic_class_no_rtti.cpp and the expected output in test/core/test_embind_polymorphic_class_no_rtti.out
and then run with self.do_run_in_out_file_test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@kripken kripken merged commit e5663b9 into emscripten-core:master Aug 24, 2020
sbc100 added a commit to sbc100/emscripten that referenced this pull request Mar 26, 2024
Automatic downcasting of polymorphic types in embind has been broken
without rtti since emscripten-core#10914 landed.

This test update confirms this brokenness rather than fixing it since
this as has been the behavior since 2020.

Fixes: emscripten-core#21619
sbc100 added a commit to sbc100/emscripten that referenced this pull request Mar 26, 2024
Automatic downcasting of polymorphic types in embind has been broken
without rtti since emscripten-core#10914 landed.

This test update confirms this brokenness rather than fixing it since
this has been the behavior since 2020.

Fixes: emscripten-core#21619
sbc100 added a commit to sbc100/emscripten that referenced this pull request Mar 27, 2024
Automatic downcasting of polymorphic types in embind has been broken
without rtti since emscripten-core#10914 landed.

This test update confirms this brokenness rather than fixing it since
this has been the behavior since 2020.

Fixes: emscripten-core#21619
sbc100 added a commit to sbc100/emscripten that referenced this pull request Mar 27, 2024
Automatic downcasting of polymorphic types in embind has been broken
without rtti since emscripten-core#10914 landed.

This test update confirms this brokenness rather than fixing it since
this has been the behavior since 2020.

Fixes: emscripten-core#21619
sbc100 added a commit to sbc100/emscripten that referenced this pull request Mar 27, 2024
Automatic downcasting of polymorphic types in embind has been broken
without rtti since emscripten-core#10914 landed.

This test update confirms this brokenness rather than fixing it since
this has been the behavior since 2020.

Fixes: emscripten-core#21619
sbc100 added a commit that referenced this pull request Mar 27, 2024
Automatic downcasting of polymorphic types in embind has been broken
without rtti since #10914 landed.

This test update confirms this brokenness rather than fixing it since
this has been the behavior since 2020.

Fixes: #21619
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

embind: Make working without RTTI
6 participants