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