Question about WebAssembly

Dukc ajieskola at gmail.com
Thu Oct 3 16:28:43 UTC 2019


On Thursday, 3 October 2019 at 15:33:54 UTC, Max Haughton wrote:
> Is there still a barrier on having syscalls to use, e.g. being 
> able to implement malloc/free? Assuming it's technically 
> possible I would like to work on this but probably in 2020 :(

Why would you need syscalls to implement malloc/free? Just 
allocate out of a static buffer. It is not even that hard to do, 
versions I use myself (feel free to use for any purpose, but bad 
code quality and high probability of bugs as it's fairly little 
used):

```
@nogc:

/+
0x0000_0000 = varaamaton
0x0000_0001 = varattu, yksi 4kt lohko
0x0000_0002 = varattu, yli 4kt
0x0000_0003 = varattu, osa varausta aikaisemmalla sivulla
0x0000_0004 = puoliksi varattu, yksi 2kt lohko
0x0000_0005 = kokonaan varattu, 2 kt lohkoissa
0x0000_0007 = jälkimmäinen 2kt puolisko varattu
0x0000_0010 = varattu, yksi 1kt lohko
0x0000_0011 = varattu, 2*1kt
0x0000_0013 = varattu kokonaan, 1kt lohkoissa
0x0000_0015 = varattu 2*1kt joista jompi kumpi vapautettu
0x0000_001B = varattu 4*1kt, kaksi vapautettu
0x0000_001F = varattu 4*1kt, kolme vapautettu
0x0000_004X = varattu 512t lohkoissa
0x0000_01XX = varattu 256t lohkoissa
0x0000_040X = varattu 128t lohkoissa
0x0000_1XXX = varattu 64t lohkoissa
0x0000_4XXX = varattu 32t lohkoissa
0x0001_XXXX = varattu 16t lohkoissa
0x0004_XXXX = varattu 8t lohkoissa
0x01XX_XXXX = varattu 1t lohkoissa
+/

enum memPageAmount = 0x200u;
enum memSizeClasses = 13u;
enum pageSize = 1u << memSizeClasses-1;
__gshared ushort[memSizeClasses] lastMemoryPages;
__gshared uint[memPageAmount] heapMap;
__gshared void[pageSize][memPageAmount] heap = void;

export extern(C) void* malloc(size_t amount)
{   if (amount == 0) return null;
     foreach(allocSize; memSizeClasses.iota)
         if (amount <= (1u << allocSize))
         foreach(pageI; 
lastMemoryPages[allocSize].iota(lastMemoryPages[allocSize] + 
memPageAmount).map!(i => cast(short)i))
     {   pageI %= memPageAmount;

         void* result;
         if
         (   heapMap[pageI] >= 0x0100_0000u >>> allocSize * 2
             &&  heapMap[pageI] <  0x0300_0000u >>> allocSize * 2
             && ~heapMap[pageI] &  0x0000_0FFFu >>> allocSize
         )
         {   result = &heap[pageI][0] + ((heapMap[pageI] & 0xFFF 
 >>> allocSize) + 1) * (1u << allocSize);
             //merkitsee muistikarttaan lohkon käyttöönoton.
             heapMap[pageI]++;
         } else if (heapMap[pageI] == 0)
         // varaamaton sivu. Eiköhän oteta käyttöön.
         {   heapMap[pageI] = 0x0100_0000u >>> allocSize * 2;
             result = heap[pageI].ptr;
         }
         else continue;

         assert(result >= heap.ptr && result < heap.ptr + 
memPageAmount);
         lastMemoryPages[allocSize] = pageI;
         assert(heapMap[pageI] != 0);
         return result;
     }

     //yli muistisivun kokoisen alueen varaus
     auto pagesNeeded = (amount - 1) / pageSize + 1;
     size_t result = 0;
     foreach (canditate; heapMap[].slide(pagesNeeded))
     {   if (canditate.all!(page => page == 0u)) goto foundArea;
         result++;
     }
     //muisti loppu
     return null;

     foundArea:
     heapMap[result] = 2u;
     foreach(ref pageMark; heapMap[].drop(result + 
1).takeExactly(pagesNeeded-1))
     {   pageMark = 3u;
     }

     return heap[result].ptr;
}

export extern(C) void free(const(void)* cAllocation)
{   //Oletettavasti tälle funktiolle välitetty osoitin dumpataan 
jorpakkoon heti jälkeenpäin,
     //joten tämä tyyppimuunnos ei luultavasti aiheuta ongelmia.
     auto allocation = cast(void*) cAllocation;
     if (allocation == null) return;
     assert(allocation >= heap.ptr && allocation < heap.ptr + 
memPageAmount, "free() ei osoita kekoon!");

     ptrdiff_t allocAddr = allocation - &heap[0][0];
     size_t pageI = allocAddr / pageSize;
     size_t pageOffset = allocAddr % pageSize;

     assert (heapMap[pageI] != 0, "Yritetään vapauttaa jo 
valmiiksi varaamatonta muistia");
     assert (heapMap[pageI] != 3, "Muistin vapautus ei osoita 
varatun pätkän alkuun");

     foreach(allocSize; memSizeClasses.iota) if
     (   heapMap[pageI] >= 0x0100_0000u >>> allocSize * 2
         &&  heapMap[pageI] <  0x0300_0000u >>> allocSize * 2
     )
     {   /+assert
         (   heapMap[pageI] >= cast(ulong)pageOffset * pageSize + 
0x0100_0000u >>> allocSize * 2,
             "Yritetään vapauttaa jo valmiiksi varaamatonta 
muistia"
         );+/
         assert (pageOffset % 1u << allocSize == 0, "Muistin 
vapautus ei osoita varatun pätkän alkuun");

         //kirjoitetaan muistiin: yksi vapautettu.
         heapMap[pageI] += pageSize >>> allocSize;
         if (heapMap[pageI] > 0x0200_0000u >>> allocSize * 2) 
heapMap[pageI] = 0;
         return;
     }

     assert (heapMap[pageI] == 2u);
     heapMap[pageI] = 0;
     foreach(ref pageMark; heapMap[pageI+1 .. $].until!(a => 
a!=3u)) pageMark = 0;
}
```


More information about the Digitalmars-d mailing list