You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've done an analysis of the WebAssembly code generated by the JIT for GetGCStaticBase, and I've identified a number of issues that reduce its performance.
Current state of the function ...
(func$S_P_CoreLib_System_Runtime_CompilerServices_StaticsHelpers__GetGCStaticBase (type58) (parami32i32i32) (resulti32)
(locali32i32i32)
local.get0i32.const32;; Allocate 32bytes on stacki32.sublocal.tee0global.get2i32.const16141i32.addi32.storealign=1;; Set initial Function pointer into stack frameblock;; label = @1block;; label = @2local.get0i32.const1i32.storeoffset=4align=1;; Store relative ip of 1 into stack framelocal.get0local.get1i32.const24i32.addlocal.tee5local.get5i32.const1023i32.le_ubr_if1(;@1;);; Null check on read of MethodTableAuxiliaryData pointer (pointer less than 1024)i32.loadalign=1;; Load MethodTableAuxiliaryData from MethodTable pointeri32.storeoffset=20align=1;; Store pointer to MethodTableAuxiliaryData at offset 20.local.get0local.get0i32.loadoffset=20align=1;; Load pointer to MethodTableAuxiliaryData from offset 20.i32.const-12i32.addlocal.tee5local.get5i32.const1023i32.le_ubr_if1(;@1;);; Null check on read of gcStaticBasei32.loadalign=1;; read gcStaticBase from location relative to MethodTableAuxiliaryDatai32.storeoffset=24align=1;; Store gcStaticBase value to memory locallocal.get0i32.loadoffset=24align=1;; Load gcStaticBase value from memory locallocal.tee3;; Save gcStaticBase to WASM local, and leave on stack (Not sure why this is here. We don't read the local ever)i32.const1i32.andi32.const0i32.nebr_if0(;@2;);; Check gcStaticBase against having the low bit set Fallback to GetGCStaticBaseSlow.local.get0i32.loadoffset=24align=1;; load gcStaticBase from memory localreturnendlocal.get0local.get1global.get1i32.loadoffset=1026044align=1local.tee4local.get4i32.loadalign=1call_indirect (type58) ;; Call GetGCStaticBase slowreturnendlocal.get0i32.const1i32.storeoffset=4align=1;; Set VirtualIP offset to 1local.get0local.get0global.get1i32.loadoffset=968744align=1;; Load address of null throw helperi32.storeoffset=28align=1;; Stash PEP in memory locallocal.get0i32.loadoffset=28align=1;; load PEP from local for null throw helper for PEP argumentlocal.get0i32.loadoffset=28align=1;; load PEP from local for null throw helper for function index loadi32.loadalign=1;; load target function indexcall_indirect (type8)
unreachable)
In there I identified a number of issues we could fix, and measured the overall improvement to a small application which used static access very often.
For this function in particular, if the ByRef's it reads from are null, we could consider it to be a runtime crash, since that should never happen. So, we could remove the null checks.
We have a number of cases where we stored a temporary byref to the stack, but we didn't actually need to do so, since we didn't actually cross a GC point when the locals were logically live. Instead we could use WASM locals to hold the data.
Also noticed... the call to the null throw helper is using dispatch through a PEP, but for some reason it was stashing some temps into a memory based local. (The call to GetGCStaticBaseSlow was using the more efficient wasm local). Not sure what's happening there.
My hand-adjusted code looks like:
(func$S_P_CoreLib_System_Runtime_CompilerServices_StaticsHelpers__GetGCStaticBase (type58) (parami32i32i32) (resulti32)
(locali32i32i32)
block;; label = @2local.get1i32.const24i32.addi32.load;; Load MethodTableAuxiliaryData from MethodTable pointeri32.const-12i32.addi32.load;; read gcStaticBase from location relative to MethodTableAuxiliaryDatalocal.tee5;; Store gcStaticBase pointer to WASM locali32.const1i32.andi32.const0i32.nebr_if0(;@1;);; Check gcStaticBase against having the low bit set Fallback to GetGCStaticBaseSlow.local.get5;; Load gcStaticBasereturnendlocal.get0local.get1global.get1i32.loadoffset=1026044align=1local.tee4local.get4i32.loadalign=1call_indirect (type58)
return)
Configuration
Browser wasm R2R
Regression?
No
Data
With the above changes, a small test app which was spending about 10% of the application in this helper went from
Description
I've done an analysis of the WebAssembly code generated by the JIT for GetGCStaticBase, and I've identified a number of issues that reduce its performance.
Current state of the function ...
In there I identified a number of issues we could fix, and measured the overall improvement to a small application which used static access very often.
My hand-adjusted code looks like:
Configuration
Browser wasm R2R
Regression?
No
Data
With the above changes, a small test app which was spending about 10% of the application in this helper went from