-
Notifications
You must be signed in to change notification settings - Fork 863
MemoryPacking: Optimize trampled data instead of giving up #8834
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2193,41 +2193,136 @@ | |
| (data.drop 0) | ||
| ) | ||
| ) | ||
|
|
||
| (module | ||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| ;; the zero tramples the "x", so the final memory contents are all zeros, and | ||
| ;; both segments can be removed entirely | ||
| (data (i32.const 1024) "x") | ||
| (data (i32.const 1024) "\00") ;; this tramples the "x", and so must be kept. | ||
| (data (i32.const 1024) "\00") | ||
| ) | ||
| ;; CHECK: (data $0 (i32.const 1024) "x") | ||
|
|
||
| ;; CHECK: (data $1 (i32.const 1024) "\00") | ||
| (module | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please leave a blank line between each module to help readability.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done — added blank lines between the modules here and in memory-packing_zero-filled-memory.wast (2738c38). |
||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| (data (i32.const 1024) "x") | ||
| (data (i32.const 1025) "\00") | ||
| ) | ||
|
|
||
| ;; CHECK: (data $0 (i32.const 1024) "x") | ||
| (module | ||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| (data (i32.const 1024) "x") | ||
| (data (i32.const 1023) "\00") | ||
| ) | ||
|
|
||
| ;; CHECK: (data $0 (i32.const 1024) "x") | ||
| (module | ||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| ;; trampling in one place does not prevent optimizing elsewhere: everything | ||
| ;; here is zeros in the final memory contents, and can be removed | ||
| (data (i32.const 1024) "x") | ||
| (data (i32.const 1024) "\00") ;; when we see one bad thing, we give up | ||
| (data (i32.const 1024) "\00") | ||
| (data (i32.const 4096) "\00") | ||
| ) | ||
| ;; CHECK: (data $0 (i32.const 1024) "x") | ||
|
|
||
| ;; CHECK: (data $1 (i32.const 1024) "\00") | ||
| (module | ||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| ;; the "y" fully tramples the "x", so only the "y" remains | ||
| (data (i32.const 1024) "x") | ||
| (data (i32.const 1024) "y") | ||
| ) | ||
|
|
||
| ;; CHECK: (data $1 (i32.const 1024) "y") | ||
| (module | ||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| ;; partial trampling: the "A" overwrites the "y" in the middle of "xyz". the | ||
| ;; trampled byte is zeroed out, and as the segments are applied in order, the | ||
| ;; final memory contents are "x", "A", "z" | ||
| (data (i32.const 1024) "xyz") | ||
| (data (i32.const 1025) "A") | ||
| ) | ||
|
|
||
| ;; CHECK: (data $0 (i32.const 1024) "x\00z") | ||
|
|
||
| ;; CHECK: (data $1 (i32.const 1025) "A") | ||
| (module | ||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| ;; chained trampling, where the tramplers are themselves trampled: the final | ||
| ;; memory contents are "f", "e", "c" | ||
| (data (i32.const 1024) "abc") | ||
| (data (i32.const 1024) "de") | ||
| (data (i32.const 1024) "f") | ||
| ) | ||
|
|
||
| ;; CHECK: (data $0 (i32.const 1026) "c") | ||
|
|
||
| ;; CHECK: (data $1 (i32.const 1025) "e") | ||
|
|
||
| ;; CHECK: (data $2 (i32.const 1024) "f") | ||
| (module | ||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| ;; one segment tramples multiple earlier ones: "WXYZ" covers all of "ab" and | ||
| ;; the "c" of "cd", so only "WXYZ" and the "d" remain | ||
| (data (i32.const 1024) "ab") | ||
| (data (i32.const 1026) "cd") | ||
| (data (i32.const 1023) "WXYZ") | ||
| ) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's also add a test that depends on the merging of the covered regions. For example, with segments covering the following intervals: When we visit segment A (after visiting C and B), if we didn't correctly merge the covering information for B into the covering information for C, then we would fail to detect the overlap between C and A because the map lookup would find B instead.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea — added in 2738c38, with segments "abcde"@1027, "B"@1025, "fghij"@1024 matching your A: [3, 8), B: [1, 2), C: [0, 5) shape. Without the merge, the lookup when visiting "abcde" would find the "B" region and miss the overlap with "fghij". The output checks confirm the trampled "ab" is dropped ("cde" remains at 1029). |
||
|
|
||
| ;; CHECK: (data $1 (i32.const 1027) "d") | ||
|
|
||
| ;; CHECK: (data $2 (i32.const 1023) "WXYZ") | ||
| (module | ||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| ;; the regions covered by later segments must be merged as they accumulate: | ||
| ;; walking the segments in reverse we see "fghij" [1024, 1029), then "B" | ||
| ;; [1025, 1026), then "abcde" [1027, 1032). if the region for "B" were not | ||
| ;; merged into the one for "fghij", then looking up the region covering | ||
| ;; "abcde" would find "B" and miss that "fghij" tramples the "ab" | ||
| (data (i32.const 1027) "abcde") | ||
| (data (i32.const 1025) "B") | ||
| (data (i32.const 1024) "fghij") | ||
| ) | ||
|
|
||
| ;; CHECK: (data $0 (i32.const 1029) "cde") | ||
|
|
||
| ;; CHECK: (data $2 (i32.const 1024) "fghij") | ||
| (module | ||
| ;; CHECK: (type $0 (func)) | ||
|
|
||
| ;; CHECK: (memory $0 1 1) | ||
| (memory $0 1 1) | ||
| ;; a passive segment is not applied at instantiation, so it neither tramples | ||
| ;; nor is trampled: the active segments cancel out as usual, and the passive | ||
| ;; segment is untouched | ||
| (data (i32.const 1024) "x") | ||
| ;; CHECK: (data $passive "ppp") | ||
| (data $passive "ppp") | ||
| (data (i32.const 1024) "\00") | ||
| ;; CHECK: (func $init (type $0) | ||
| ;; CHECK-NEXT: (memory.init $passive | ||
| ;; CHECK-NEXT: (i32.const 0) | ||
| ;; CHECK-NEXT: (i32.const 0) | ||
| ;; CHECK-NEXT: (i32.const 3) | ||
| ;; CHECK-NEXT: ) | ||
| ;; CHECK-NEXT: ) | ||
| (func $init | ||
| (memory.init $passive | ||
| (i32.const 0) | ||
| (i32.const 0) | ||
| (i32.const 3) | ||
| ) | ||
| ) | ||
| ) | ||
|
|
||
| ;; CHECK: (data $2 (i32.const 4096) "\00") | ||
| (module | ||
| ;; CHECK: (import "env" "memoryBase" (global $memoryBase i32)) | ||
| (import "env" "memoryBase" (global $memoryBase i32)) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe worth adding a TODO about optimizing anyway if we can check that all the segments after the trampled segment up to and including the trampling segment will be in-bounds for the imported memory.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done — added the TODO in 2738c38.