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