@@ -68,9 +68,11 @@ struct MultiMemoryLowering : public Pass {
6868 // properties will be set
6969 Name module ;
7070 Name base;
71- // The initial page size of the combined memory
71+ // The page size of the combined memory
72+ uint8_t pageSizeLog2;
73+ // The initial page count of the combined memory
7274 Address totalInitialPages;
73- // The max page size of the combined memory
75+ // The max page count of the combined memory
7476 Address totalMaxPages;
7577 // There is no offset for the first memory, so offsetGlobalNames will always
7678 // have a size that is one less than the count of memories at the time this
@@ -435,6 +437,7 @@ struct MultiMemoryLowering : public Pass {
435437 : Builder::MemoryInfo::Memory64;
436438 isShared = getFirstMemory ().shared ;
437439 isImported = getFirstMemory ().imported ();
440+ pageSizeLog2 = Memory::kDefaultPageSizeLog2 ;
438441 for (auto & memory : wasm->memories ) {
439442 // We are assuming that each memory is configured the same as the first
440443 // and assert if any of the memories does not match this configuration
@@ -446,18 +449,21 @@ struct MultiMemoryLowering : public Pass {
446449 Fatal () << " MultiMemoryLowering: only the first memory can be imported" ;
447450 }
448451
452+ // Calculating the page size of the combined memory.
453+ // This corresponds to the smaller granularity among combined memories
454+ pageSizeLog2 = std::min (pageSizeLog2,memory->pageSizeLog2 );
455+
449456 // Calculating the total initial and max page size for the combined memory
450457 // by totaling the initial and max page sizes for the memories in the
451458 // module
452- totalInitialPages = totalInitialPages + memory->initial ;
459+ totalInitialPages = totalInitialPages + ( memory->initial << (memory-> pageSizeLog2 - pageSizeLog2)) ;
453460 if (memory->hasMax ()) {
454- totalMaxPages = totalMaxPages + memory->max ;
461+ totalMaxPages = totalMaxPages + ( memory->max << (memory-> pageSizeLog2 - pageSizeLog2)) ;
455462 }
456463 }
457464 // Ensuring valid initial and max page sizes that do not exceed the number
458465 // of pages addressable by the pointerType
459- Address maxSize =
460- pointerType == Type::i32 ? Memory::kMaxSize32 : Memory::kMaxSize64 ;
466+ Address maxSize = pointerType == Type::i32 ? 1ull <<(32 -pageSizeLog2) : 1ull <<(64 -pageSizeLog2);
461467 if (totalMaxPages > maxSize || totalMaxPages == 0 ) {
462468 totalMaxPages = Memory::kUnlimitedSize ;
463469 }
@@ -504,9 +510,9 @@ struct MultiMemoryLowering : public Pass {
504510 Name name = Names::getValidGlobalName (
505511 *wasm, memory->name .toString () + " _byte_offset" );
506512 offsetGlobalNames.push_back (std::move (name));
507- addGlobal (name, offsetRunningTotal * Memory:: kPageSize );
513+ addGlobal (name, offsetRunningTotal << pageSizeLog2 );
508514 }
509- offsetRunningTotal += memory->initial ;
515+ offsetRunningTotal += memory->initial << (memory-> pageSizeLog2 - pageSizeLog2) ;
510516 }
511517 }
512518
@@ -554,10 +560,10 @@ struct MultiMemoryLowering : public Pass {
554560 functionName, Signature (pointerType, pointerType), {});
555561 function->setLocalName (0 , " page_delta" );
556562 auto pageSizeConst = [&]() {
557- return builder.makeConst (Literal (Memory:: kPageSize ));
563+ return builder.makeConst (Literal (wasm-> memories [memIdx]-> pageSizeLog2 ));
558564 };
559565 auto getOffsetDelta = [&]() {
560- return builder.makeBinary (Abstract::getBinary (pointerType, Abstract::Mul ),
566+ return builder.makeBinary (Abstract::getBinary (pointerType, Abstract::Shl ),
561567 builder.makeLocalGet (0 , pointerType),
562568 pageSizeConst ());
563569 };
@@ -588,7 +594,8 @@ struct MultiMemoryLowering : public Pass {
588594 builder.makeBinary (
589595 EqInt32,
590596 builder.makeMemoryGrow (
591- builder.makeLocalGet (0 , pointerType), combinedMemory, memoryInfo),
597+ builder.makeBinary ( Abstract::getBinary (pointerType, Abstract::Shl),
598+ builder.makeLocalGet (0 , pointerType), builder.makeConst (Literal (wasm->memories [memIdx]->pageSizeLog2 - pageSizeLog2))) , combinedMemory, memoryInfo),
592599 builder.makeConst (-1 )),
593600 builder.makeReturn (builder.makeConst (-1 ))));
594601
@@ -609,7 +616,7 @@ struct MultiMemoryLowering : public Pass {
609616 // size
610617 builder.makeBinary (
611618 Abstract::getBinary (pointerType, Abstract::Sub),
612- builder.makeBinary (Abstract::getBinary (pointerType, Abstract::Mul ),
619+ builder.makeBinary (Abstract::getBinary (pointerType, Abstract::Shl ),
613620 builder.makeLocalGet (sizeLocal, pointerType),
614621 pageSizeConst ()),
615622 getMoveSource (offsetGlobalName)),
@@ -646,11 +653,11 @@ struct MultiMemoryLowering : public Pass {
646653 functionName, Signature (Type::none, pointerType), {});
647654 Expression* functionBody;
648655 auto pageSizeConst = [&]() {
649- return builder.makeConst (Literal (Memory:: kPageSize ));
656+ return builder.makeConst (Literal (pageSizeLog2 ));
650657 };
651658 auto getOffsetInPageUnits = [&](Name global) {
652659 return builder.makeBinary (
653- Abstract::getBinary (pointerType, Abstract::DivU ),
660+ Abstract::getBinary (pointerType, Abstract::ShrU ),
654661 builder.makeGlobalGet (global, pointerType),
655662 pageSizeConst ());
656663 };
@@ -697,6 +704,7 @@ struct MultiMemoryLowering : public Pass {
697704 memory->base = base;
698705 memory->module = module ;
699706 }
707+ memory->pageSizeLog2 = pageSizeLog2;
700708 wasm->addMemory (std::move (memory));
701709 }
702710
0 commit comments