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

[wasm] optional legacy JS interop #79622

Closed

Conversation

pavelsavara
Copy link
Member

@pavelsavara pavelsavara commented Dec 13, 2022

currently only build time switch, not workload switch

  • removes runtime\net6-legacy\* from dotnet.js
    • release size 338118 -> 304870 = 33248
  • removes relevant C code in driver.c from dotnet.wasm
    • release size 2409118 -> 2407787 = 1331
  • removes legacy stuff from System.Runtime.InteropServices.JavaScript.dll
    • release size 32256 -> 24064 = 8192

@ghost
Copy link

ghost commented Dec 13, 2022

Tagging subscribers to 'arch-wasm': @lewing
See info in area-owners.md if you want to be subscribed.

Issue Details

currently only build time switch, not workload switch

  • removes runtime\net6-legacy\* from dotnet.js
    • release size 338118 -> 304870
  • removes relevant C code in driver.c from dotnet.wasm
    • release size 2409118 -> 2407787
  • removes legacy stuff from System.Runtime.InteropServices.JavaScript.dll
    • release size 32256 -> 24064
Author: pavelsavara
Assignees: pavelsavara
Labels:

arch-wasm, area-System.Runtime.InteropServices.JavaScript

Milestone: 8.0.0

@pavelsavara
Copy link
Member Author

We should make decision on how to proceed with this

  1. merge close to what it is and set MonoWasmLegacyJsInterop to false
  • for the threaded binaries as the legacy interop doesn't work well anyway there
  • possibly for new binary flavor (or mixed with EH, SIMD)
  1. invest more effort and make this workload linker flag
  • we would have to split the C methods into separate binary object
  • we would have to somehow explain the flag to trimmer on dev machine for IL stuff.
    • There is [DynamicDependecy] which need to be configurable.
  • we would need to make the JS part separate ES6 module
    • because we don't have rollup on the dev machine
  • and then deal with SDK impact of the new files
  1. is easier
  2. same pattern could be also applied to Jitterpretter too

thoughts ? @kg @lewing @lambdageek

@kg
Copy link
Contributor

kg commented Dec 14, 2022

I think we should start with 1 (merge close to what it is now, only disable for threading and for new scenarios going forward) and then prepare 2 as a separate PR

Comment on lines 267 to 268
<EmscriptenEnvVars Include="MonoWasmLegacyJsInterop=$(MonoWasmLegacyJsInterop)"/>
<EmscriptenEnvVars Include="MonoWasmThreads=$(MonoWasmThreads)"/>
Copy link
Member

Choose a reason for hiding this comment

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

Should these be set only when they have value?

Copy link
Member Author

Choose a reason for hiding this comment

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

They must have value even if we just default it to false or true.

The env variable is the way how to evaluate it in dotnet.es6.lib.js while linking.
But when this code would be running on user dev machine, I don't know how to get the value which was previously used to compile this runtime flavor in our CI.

There was USE_PTHREADS which is pre-processor directive, but it works only for existing emcc settings. Whatever could be passed with -s XXX. Benefit is, that emcc-link.rsp would have that value stored for the runtime flavor.

But here I want to add something which emcc doesn't know about and so I went with env variables. But those are not in emcc-link.rsp. As I write this comment now I rememebred that there is emcc-props.json which could carry that value for me. That would work.

But is that wasted effort if we go for 2) as next step ?

src/mono/wasm/runtime/cwraps.ts Show resolved Hide resolved
src/mono/wasm/runtime/exports-linker.ts Outdated Show resolved Hide resolved
src/mono/wasm/runtime/startup.ts Show resolved Hide resolved
src/mono/wasm/build/WasmApp.Native.targets Outdated Show resolved Hide resolved
pavelsavara and others added 4 commits December 16, 2022 13:39
# Conflicts:
#	src/mono/wasm/runtime/cwraps.ts
Co-authored-by: Ankit Jain <radical@gmail.com>
Co-authored-by: Ankit Jain <radical@gmail.com>
Co-authored-by: Ankit Jain <radical@gmail.com>
@lewing
Copy link
Member

lewing commented Dec 21, 2022

I love the idea here perhaps we can gate the actual managed bits on a linker flag like the latest simd settings and keep most of the size improvement that way? I'd love a better way to solve the unmanage<->managed linking problem but we don't always need a general solution.

Comment on lines +145 to +147
#if FEATURE_LEGACY_JS_INTEROP
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, "System.Runtime.InteropServices.JavaScript.LegacyExports", "System.Runtime.InteropServices.JavaScript")]
#endif
Copy link
Contributor

Choose a reason for hiding this comment

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

This does not let us to remove LegacyExports because it's a library compile time setting. We could remove this DynamicDependency and use XML descriptor with System.Runtime.InteropServices.JavaScript.LegacyExports and pass it to linker only when legacy interop is enabled.

Copy link
Member Author

Choose a reason for hiding this comment

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

That XML would become embedded resource, right ? How do I tell the linker to ignore it or not in WasmApp.Native.targets ?

Copy link
Contributor

Choose a reason for hiding this comment

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

It would be additional file passed conditionally to the linker (we run it all the time to this should work).

Copy link
Member Author

Choose a reason for hiding this comment

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

For threaded runtime flavor everything would be already trimmed away.

For normal runtime flavor we would keep the code with DynamicDependency above.
User would be able to opt in for trimming on customer's dev machine.

I can follow example of WasmEnableSIMD and ILLink.Substitutions.WasmIntrinsics.xml.
Except I need ILLink.LinkAttributes.xml which could remove the attribute ?

Copy link
Contributor

Choose a reason for hiding this comment

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

That won't work DynamicDependency is always processed and it only removed later. The attribute cannot be visible to linker in this case to work as expected.

Copy link
Member

Choose a reason for hiding this comment

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

We should discuss the mechanisms we need in the regular build to pass additional linker files based on options as part of the bunder/sdk changes

# Conflicts:
#	src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs
# Conflicts:
#	src/mono/wasm/runtime/startup.ts
@pavelsavara
Copy link
Member Author

pavelsavara commented Jan 3, 2023

Today I tried to separate the net6-legacy/*.ts into separate rollup->IIFE. If we are able to do that we could
A) download it as separate ES6 module
B) or we could let the emcc linker to merge it into final dotnet.js

I was able to draft detaching the runtime->legacy dependency into small surface of few initialization functions which would the runtime all on the legacy module to connect it.

But, there are many dependencies in the opposite direction. Legacy interop uses almost all internal infrastructure of the runtime. JS code we have. We could export internal "API" for this purpose. It means that all the internal function names would have to be protected from minification.

I'm scratching my head what to do about it conceptually, so that we could use the same approach for jiterpreter code and possibly also for MT infrastructure.

  1. make our runtime.iffe less opaque and trust emcc/closure that it could propagate constants and eliminate dead code.
  2. include rollupJS in the wasm workload
  3. expose internal API between our modules with A) B)
  4. give up JS modularization / trimming features (on dev machine)

@build-analysis build-analysis bot mentioned this pull request Jan 3, 2023
@pavelsavara
Copy link
Member Author

pavelsavara commented Jan 3, 2023

re 1)

@pavelsavara
Copy link
Member Author

pavelsavara commented Jan 18, 2023

note to self mono_wasm_new_roots and set_root is unused ?

@pavelsavara
Copy link
Member Author

The closure compiler (and the trimming side effects) could be only run without -g that is with WasmNativeStrip==true

@ghost ghost closed this Feb 18, 2023
@ghost
Copy link

ghost commented Feb 18, 2023

Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it.

@ghost ghost locked as resolved and limited conversation to collaborators Apr 1, 2023
@pavelsavara pavelsavara deleted the wasm_optional_legacy_interop branch September 2, 2024 15:29
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants