@@ -117,6 +117,8 @@ class StringConstantTracker {
117
117
return escape (str);
118
118
}
119
119
120
+ std::vector<Address> segmentOffsets; // segment index => address offset
121
+
120
122
private:
121
123
void calcSegmentOffsets () {
122
124
std::unordered_map<Index, Address> passiveOffsets;
@@ -185,7 +187,6 @@ class StringConstantTracker {
185
187
}
186
188
187
189
Module& wasm;
188
- std::vector<Address> segmentOffsets; // segment index => address offset
189
190
};
190
191
191
192
enum class Proxying {
@@ -380,6 +381,7 @@ struct EmJsWalker : public PostWalker<EmJsWalker> {
380
381
std::vector<Export> toRemove;
381
382
382
383
std::map<std::string, std::string> codeByName;
384
+ std::map<Address, size_t > codeAddresses; // map from address to string len
383
385
384
386
EmJsWalker (Module& _wasm) : wasm(_wasm), stringTracker(_wasm) {}
385
387
@@ -404,9 +406,34 @@ struct EmJsWalker : public PostWalker<EmJsWalker> {
404
406
int64_t address = addrConst->value .getInteger ();
405
407
auto code = stringTracker.codeForConstAddr (address);
406
408
codeByName[funcName] = code;
409
+ codeAddresses[address] = code.size () + 1 ;
407
410
}
408
411
};
409
412
413
+ struct SegmentRemover : WalkerPass<PostWalker<SegmentRemover>> {
414
+ SegmentRemover (Index segment) : segment(segment) {}
415
+
416
+ bool isFunctionParallel () override { return true ; }
417
+
418
+ Pass* create () override { return new SegmentRemover (segment); }
419
+
420
+ void visitMemoryInit (MemoryInit* curr) {
421
+ if (segment == curr->segment ) {
422
+ Builder builder (*getModule ());
423
+ replaceCurrent (builder.makeNop ());
424
+ }
425
+ }
426
+
427
+ void visitDataDrop (DataDrop* curr) {
428
+ if (segment == curr->segment ) {
429
+ Builder builder (*getModule ());
430
+ replaceCurrent (builder.makeNop ());
431
+ }
432
+ }
433
+
434
+ Index segment;
435
+ };
436
+
410
437
EmJsWalker fixEmJsFuncsAndReturnWalker (Module& wasm) {
411
438
EmJsWalker walker (wasm);
412
439
walker.walkModule (&wasm);
@@ -415,6 +442,31 @@ EmJsWalker fixEmJsFuncsAndReturnWalker(Module& wasm) {
415
442
wasm.removeExport (exp .name );
416
443
wasm.removeFunction (exp .value );
417
444
}
445
+
446
+
447
+ for (Index i = 0 ; i < wasm.memory .segments .size (); i++) {
448
+ Address start = walker.stringTracker .segmentOffsets [0 ];
449
+ Address cur = start;
450
+
451
+ // With newer versions of emscripten/llvm we pack all EM_JS strings into
452
+ // single segment.
453
+ // We can detect this by checking if the strings found cover the entire
454
+ // segment
455
+ while (cur < start + wasm.memory .segments [i].data .size ()) {
456
+ if (walker.codeAddresses .count (cur) == 0 )
457
+ break ;
458
+ cur.addr += walker.codeAddresses [cur];
459
+ }
460
+
461
+ if (cur == start + wasm.memory .segments [i].data .size ()) {
462
+ PassRunner runner (&wasm);
463
+ SegmentRemover (i).run (&runner, &wasm);
464
+ // Resize the segment to zero. In theory we should completely remove it
465
+ // but that would mean re-numbering the segments that follow which would
466
+ // mean renumbering.
467
+ wasm.memory .segments [i].data .resize (0 );
468
+ }
469
+ }
418
470
return walker;
419
471
}
420
472
0 commit comments