Skip to content

Commit

Permalink
fix(stdlib): Ensure references are retained in unsafe stdlib functions (
Browse files Browse the repository at this point in the history
  • Loading branch information
ospencer committed Jul 28, 2024
1 parent eea321f commit 639856f
Show file tree
Hide file tree
Showing 7 changed files with 382 additions and 179 deletions.
2 changes: 2 additions & 0 deletions stdlib/array.gr
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ provide let make = (length: Number, item: a) => {
_ARRAY_START_OFFSET
)
}
ignore(item)
WasmI32.toGrain(array): Array<a>
}

Expand Down Expand Up @@ -988,6 +989,7 @@ provide let join = (separator: String, items: Array<String>) => {
if (i != arrLen) Memory.copy(offset, sepPtr, sepSize)
offset += sepSize
}
ignore(separator)
WasmI32.toGrain(newString): String
}

Expand Down
45 changes: 38 additions & 7 deletions stdlib/bytes.gr
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ provide let fromString = (string: String) => {
let size = getSize(src)
let dst = allocateBytes(size)
Memory.copy(dst + _VALUE_OFFSET, src + _VALUE_OFFSET, size)
ignore(string)
WasmI32.toGrain(dst): Bytes
}

Expand All @@ -134,6 +135,7 @@ provide let toString = (bytes: Bytes) => {
let size = getSize(src)
let dst = allocateString(size)
Memory.copy(dst + _VALUE_OFFSET, src + _VALUE_OFFSET, size)
ignore(bytes)
WasmI32.toGrain(dst): String
}

Expand All @@ -151,7 +153,9 @@ provide let toString = (bytes: Bytes) => {
@unsafe
provide let length = (bytes: Bytes) => {
let b = WasmI32.fromGrain(bytes)
Conv.wasmI32ToNumber(getSize(b))
let result = Conv.wasmI32ToNumber(getSize(b))
ignore(bytes)
result
}

/**
Expand All @@ -171,6 +175,7 @@ provide let copy = (bytes: Bytes) => {
let size = getSize(src)
let dst = allocateBytes(size)
Memory.copy(dst + _VALUE_OFFSET, src + _VALUE_OFFSET, size)
ignore(bytes)
WasmI32.toGrain(dst): Bytes
}

Expand Down Expand Up @@ -208,6 +213,7 @@ provide let slice = (start: Number, length: Number, bytes: Bytes) => {
let dst = allocateBytes(length)
let offset = start
Memory.copy(dst + _VALUE_OFFSET, src + _VALUE_OFFSET + start, length)
ignore(bytes)
WasmI32.toGrain(dst): Bytes
}

Expand Down Expand Up @@ -263,6 +269,7 @@ provide let resize = (left: Number, right: Number, bytes: Bytes) => {
len
)
}
ignore(bytes)
WasmI32.toGrain(dst): Bytes
}

Expand Down Expand Up @@ -298,11 +305,11 @@ provide let move = (
let srcIndexOrig = srcIndex
let dstIndexOrig = dstIndex
let lenthOrig = length
let src = WasmI32.fromGrain(src)
let srcSize = getSize(src)
let srcPtr = WasmI32.fromGrain(src)
let srcSize = getSize(srcPtr)
let srcIndex = coerceNumberToWasmI32(srcIndex)
let dst = WasmI32.fromGrain(dst)
let dstSize = getSize(dst)
let dstPtr = WasmI32.fromGrain(dst)
let dstSize = getSize(dstPtr)
let dstIndex = coerceNumberToWasmI32(dstIndex)
let length = coerceNumberToWasmI32(length)
if (srcIndex + length > srcSize) {
Expand All @@ -313,10 +320,12 @@ provide let move = (
}
let end = srcIndex + length
Memory.copy(
dst + _VALUE_OFFSET + dstIndex,
src + _VALUE_OFFSET + srcIndex,
dstPtr + _VALUE_OFFSET + dstIndex,
srcPtr + _VALUE_OFFSET + srcIndex,
length
)
ignore(src)
ignore(dst)
}

/**
Expand Down Expand Up @@ -362,6 +371,7 @@ provide let fill = (value: Uint8, bytes: Bytes) => {
let size = getSize(src)
let v = untagUint8(value)
Memory.fill(src + _VALUE_OFFSET, v, size)
ignore(bytes)
}

/**
Expand All @@ -383,6 +393,7 @@ provide let clear = (bytes: Bytes) => {
let src = WasmI32.fromGrain(bytes)
let size = getSize(src)
Memory.fill(src + _VALUE_OFFSET, 0n, size)
ignore(bytes)
}

/**
Expand Down Expand Up @@ -411,6 +422,7 @@ provide let getInt8 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT8_BYTE_SIZE, size)
let n = WasmI32.load8S(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
tagInt8(n)
}

Expand Down Expand Up @@ -440,6 +452,7 @@ provide let setInt8 = (index: Number, value: Int8, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT8_BYTE_SIZE, size)
let v = untagInt8(value)
ignore(bytes)
WasmI32.store8(ptr + offset, v, _VALUE_OFFSET)
}

Expand Down Expand Up @@ -469,6 +482,7 @@ provide let getUint8 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT8_BYTE_SIZE, size)
let n = WasmI32.load8U(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
tagUint8(n)
}

Expand Down Expand Up @@ -498,6 +512,7 @@ provide let setUint8 = (index: Number, value: Uint8, bytes: Bytes) => {
checkIndexIsInBounds(offset, _INT8_BYTE_SIZE, size)
let v = untagUint8(value)
WasmI32.store8(ptr + offset, v, _VALUE_OFFSET)
ignore(bytes)
}

/**
Expand Down Expand Up @@ -526,6 +541,7 @@ provide let getInt16 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT16_BYTE_SIZE, size)
let n = WasmI32.load16S(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
tagInt16(n)
}

Expand Down Expand Up @@ -556,6 +572,7 @@ provide let setInt16 = (index: Number, value: Int16, bytes: Bytes) => {
checkIndexIsInBounds(offset, _INT16_BYTE_SIZE, size)
let v = untagInt16(value)
WasmI32.store16(ptr + offset, v, _VALUE_OFFSET)
ignore(bytes)
}

/**
Expand Down Expand Up @@ -584,6 +601,7 @@ provide let getUint16 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT16_BYTE_SIZE, size)
let n = WasmI32.load16U(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
tagUint16(n)
}

Expand Down Expand Up @@ -613,6 +631,7 @@ provide let setUint16 = (index: Number, value: Uint16, bytes: Bytes) => {
checkIndexIsInBounds(offset, _INT16_BYTE_SIZE, size)
let v = untagUint16(value)
WasmI32.store16(ptr + offset, v, _VALUE_OFFSET)
ignore(bytes)
}

/**
Expand Down Expand Up @@ -640,6 +659,7 @@ provide let getInt32 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT32_BYTE_SIZE, size)
let n = WasmI32.load(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
Conv.toInt32(n)
}

Expand Down Expand Up @@ -669,6 +689,7 @@ provide let setInt32 = (index: Number, value: Int32, bytes: Bytes) => {
checkIndexIsInBounds(offset, _INT32_BYTE_SIZE, size)
let v = Conv.fromInt32(value)
WasmI32.store(ptr + offset, v, _VALUE_OFFSET)
ignore(bytes)
}

/**
Expand Down Expand Up @@ -696,6 +717,7 @@ provide let getUint32 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT32_BYTE_SIZE, size)
let n = WasmI32.load(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
Conv.toUint32(n)
}

Expand Down Expand Up @@ -725,6 +747,7 @@ provide let setUint32 = (index: Number, value: Uint32, bytes: Bytes) => {
checkIndexIsInBounds(offset, _INT32_BYTE_SIZE, size)
let v = Conv.fromUint32(value)
WasmI32.store(ptr + offset, v, _VALUE_OFFSET)
ignore(bytes)
}

/**
Expand Down Expand Up @@ -752,6 +775,7 @@ provide let getFloat32 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT32_BYTE_SIZE, size)
let n = WasmF32.load(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
Conv.toFloat32(n)
}

Expand Down Expand Up @@ -781,6 +805,7 @@ provide let setFloat32 = (index: Number, value: Float32, bytes: Bytes) => {
checkIndexIsInBounds(offset, _INT32_BYTE_SIZE, size)
let v = Conv.fromFloat32(value)
WasmF32.store(ptr + offset, v, _VALUE_OFFSET)
ignore(bytes)
}

/**
Expand Down Expand Up @@ -808,6 +833,7 @@ provide let getInt64 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT64_BYTE_SIZE, size)
let n = WasmI64.load(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
Conv.toInt64(n)
}

Expand Down Expand Up @@ -837,6 +863,7 @@ provide let setInt64 = (index: Number, value: Int64, bytes: Bytes) => {
checkIndexIsInBounds(offset, _INT64_BYTE_SIZE, size)
let v = Conv.fromInt64(value)
WasmI64.store(ptr + offset, v, _VALUE_OFFSET)
ignore(bytes)
}

/**
Expand Down Expand Up @@ -864,6 +891,7 @@ provide let getUint64 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _INT64_BYTE_SIZE, size)
let n = WasmI64.load(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
Conv.toUint64(n)
}

Expand Down Expand Up @@ -893,6 +921,7 @@ provide let setUint64 = (index: Number, value: Uint64, bytes: Bytes) => {
checkIndexIsInBounds(offset, _INT64_BYTE_SIZE, size)
let v = Conv.fromUint64(value)
WasmI64.store(ptr + offset, v, _VALUE_OFFSET)
ignore(bytes)
}

/**
Expand Down Expand Up @@ -920,6 +949,7 @@ provide let getFloat64 = (index: Number, bytes: Bytes) => {
let offset = coerceNumberToWasmI32(index)
checkIndexIsInBounds(offset, _FLOAT64_BYTE_SIZE, size)
let n = WasmF64.load(ptr + offset, _VALUE_OFFSET)
ignore(bytes)
Conv.toFloat64(n)
}

Expand Down Expand Up @@ -949,4 +979,5 @@ provide let setFloat64 = (index: Number, value: Float64, bytes: Bytes) => {
checkIndexIsInBounds(offset, _FLOAT64_BYTE_SIZE, size)
let v = Conv.fromFloat64(value)
WasmF64.store(ptr + offset, v, _VALUE_OFFSET)
ignore(bytes)
}
2 changes: 2 additions & 0 deletions stdlib/hash.gr
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ provide let hash = anything => {
}

hashOne(WasmI32.fromGrain(anything), 0n)
ignore(anything)

finalize(0n)

// Tag the number on the way out.
Expand Down
5 changes: 3 additions & 2 deletions stdlib/map.gr
Original file line number Diff line number Diff line change
Expand Up @@ -436,13 +436,14 @@ provide let toArray = (map: Map<a, b>) => {
use WasmI32.{ (+) as addWasmI32 }
// Assign the values into the array.
// We store them directly to prevent GC on uninitialized array data.
let array = WasmI32.fromGrain(array)
let arrayPtr = WasmI32.fromGrain(array)
let item = (key, value)
WasmI32.store(
addWasmI32(array, untagSimpleNumber(i) * 4n),
addWasmI32(arrayPtr, untagSimpleNumber(i) * 4n),
Memory.incRef(WasmI32.fromGrain(item)),
8n
)
ignore(array)
i + 1
}
reduce(reducer, 0, map)
Expand Down
Loading

0 comments on commit 639856f

Please sign in to comment.