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