Skip to content

Commit 6e4ff0c

Browse files
authored
Safer array primitives (#1220)
- [x] Review resizable array (what is the intended semantics even) - [x] Change names of vm primitives. - [x] Check allocateZeros and allocateNones on JS - [x] Measure performance cost
1 parent a708f99 commit 6e4ff0c

29 files changed

+289
-290
lines changed

effekt/shared/src/main/scala/effekt/core/vm/Builtin.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,31 +248,31 @@ lazy val chars: Builtins = Map(
248248
)
249249

250250
lazy val arrays: Builtins = Map(
251-
builtin("array::allocate(Int)") {
251+
builtin("array::unsafeAllocate(Int)") {
252252
case As.Int(x) :: Nil => Value.Array(scala.Array.ofDim(x.toInt))
253253
},
254254
builtin("array::size[T](Array[T])") {
255255
case As.Array(arr) :: Nil => Value.Int(arr.length.toLong)
256256
},
257-
builtin("array::unsafeGet[T](Array[T], Int)") {
257+
builtin("array::get[T](Array[T], Int)") {
258258
case As.Array(arr) :: As.Int(index) :: Nil => arr(index.toInt)
259259
},
260-
builtin("array::unsafeSet[T](Array[T], Int, T)") {
260+
builtin("array::set[T](Array[T], Int, T)") {
261261
case As.Array(arr) :: As.Int(index) :: value :: Nil => arr.update(index.toInt, value); Value.Unit()
262262
},
263263
)
264264

265265
lazy val bytearrays: Builtins = Map(
266-
builtin("bytearray::allocate(Int)") {
266+
builtin("bytearray::unsafeAllocate(Int)") {
267267
case As.Int(x) :: Nil => Value.ByteArray(scala.Array.ofDim(x.toInt))
268268
},
269269
builtin("bytearray::size(ByteArray)") {
270270
case As.ByteArray(arr) :: Nil => Value.Int(arr.length.toLong)
271271
},
272-
builtin("bytearray::unsafeGet(ByteArray, Int)") {
272+
builtin("bytearray::get(ByteArray, Int)") {
273273
case As.ByteArray(arr) :: As.Int(index) :: Nil => Value.Byte(arr(index.toInt))
274274
},
275-
builtin("bytearray::unsafeSet(ByteArray, Int, Byte)") {
275+
builtin("bytearray::set(ByteArray, Int, Byte)") {
276276
case As.ByteArray(arr) :: As.Int(index) :: As.Byte(value) :: Nil => arr.update(index.toInt, value); Value.Unit()
277277
},
278278
builtin("bytearray::compare(ByteArray, ByteArray)") {

examples/benchmarks/are_we_fast_yet/bounce.effekt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def run(n: Int) = {
6969

7070
each(0, n) { i =>
7171
each(0, ballCount) { i =>
72-
val ball = balls.unsafeGet(i);
72+
val ball = balls.get(i);
7373
val didBounce = ball.bounce();
7474
if (didBounce)
7575
bounces = bounces + 1;

examples/benchmarks/are_we_fast_yet/nbody.effekt

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,13 @@ def run(n: Int) = {
7171
val sun = makeBody(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)
7272

7373
def createBodies(): Array[Body] = {
74-
val bodies = allocate[Body](5)
74+
val bodies = unsafeAllocate[Body](5)
7575

76-
bodies.unsafeSet(0, sun);
77-
bodies.unsafeSet(1, jupiter);
78-
bodies.unsafeSet(2, saturn);
79-
bodies.unsafeSet(3, uranus);
80-
bodies.unsafeSet(4, neptune);
76+
bodies.set(0, sun);
77+
bodies.set(1, jupiter);
78+
bodies.set(2, saturn);
79+
bodies.set(3, uranus);
80+
bodies.set(4, neptune);
8181

8282
var px = 0.0;
8383
var py = 0.0;
@@ -97,16 +97,16 @@ def run(n: Int) = {
9797
0.0 - (pz / SOLAR_MASS),
9898
body.mass)
9999

100-
bodies.unsafeSet(0, sun.offsetMomentum(px, py, pz))
100+
bodies.set(0, sun.offsetMomentum(px, py, pz))
101101

102102
bodies
103103
}
104104

105105
def advance(bodies: Array[Body], dt: Double) = {
106106
each(0, bodies.size) { i =>
107107
each(i + 1, bodies.size) { j =>
108-
val iBody = bodies.unsafeGet(i);
109-
val jBody = bodies.unsafeGet(j);
108+
val iBody = bodies.get(i);
109+
val jBody = bodies.get(j);
110110

111111
val dx = iBody.x - jBody.x;
112112
val dy = iBody.y - jBody.y;
@@ -116,15 +116,15 @@ def run(n: Int) = {
116116
val distance = sqrt(dSquared);
117117
val mag = dt / (dSquared * distance);
118118

119-
bodies.unsafeSet(i, Body(
119+
bodies.set(i, Body(
120120
iBody.x, iBody.y, iBody.z,
121121
iBody.vx - dx * jBody.mass * mag,
122122
iBody.vy - dy * jBody.mass * mag,
123123
iBody.vz - dz * jBody.mass * mag,
124124
iBody.mass
125125
));
126126

127-
bodies.unsafeSet(j, Body(
127+
bodies.set(j, Body(
128128
jBody.x, jBody.y, jBody.z,
129129
jBody.vx + dx * iBody.mass * mag,
130130
jBody.vy + dy * iBody.mass * mag,
@@ -135,8 +135,8 @@ def run(n: Int) = {
135135
}
136136

137137
each(0, bodies.size) { i =>
138-
val body = bodies.unsafeGet(i);
139-
bodies.unsafeSet(i, Body(
138+
val body = bodies.get(i);
139+
bodies.set(i, Body(
140140
body.x + dt * body.vx,
141141
body.y + dt * body.vy,
142142
body.z + dt * body.vz,
@@ -151,11 +151,11 @@ def run(n: Int) = {
151151
def energy(bodies: Array[Body]): Double = {
152152
var e = 0.0;
153153
each(0, bodies.size()){ i =>
154-
val iBody = bodies.unsafeGet(i);
154+
val iBody = bodies.get(i);
155155
e = e + 0.5 * iBody.mass * (iBody.vx * iBody.vx + iBody.vy * iBody.vy + iBody.vz * iBody.vz);
156156

157157
each(i + 1, bodies.size){ j =>
158-
val jBody = bodies.unsafeGet(j);
158+
val jBody = bodies.get(j);
159159
val dx = iBody.x - jBody.x;
160160
val dy = iBody.y - jBody.y;
161161
val dz = iBody.z - jBody.z;

examples/benchmarks/are_we_fast_yet/permute.effekt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import ref
44
import array
55

66
def swap(arr: Array[Int], i: Int, j: Int) = {
7-
val tmp = arr.unsafeGet(i);
8-
arr.unsafeSet(i, arr.unsafeGet(j));
9-
arr.unsafeSet(j, tmp)
7+
val tmp = arr.get(i);
8+
arr.set(i, arr.get(j));
9+
arr.set(j, tmp)
1010
}
1111

1212
def run(n: Int) = {

examples/benchmarks/are_we_fast_yet/queens.effekt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@ def run(n: Int) = {
1414
val queenRows: Array[Int] = array(n, -1);
1515

1616
def getRowColumn(r: Int, c: Int): Bool =
17-
freeRows.unsafeGet(r) && freeMaxs.unsafeGet(c + r) && freeMins.unsafeGet(c - r + (n - 1))
17+
freeRows.get(r) && freeMaxs.get(c + r) && freeMins.get(c - r + (n - 1))
1818

1919
def setRowColumn(r: Int, c: Int, v: Bool) = {
20-
freeRows.unsafeSet(r, v);
21-
freeMaxs.unsafeSet(c + r, v);
22-
freeMins.unsafeSet(c - r + (n - 1), v)
20+
freeRows.set(r, v);
21+
freeMaxs.set(c + r, v);
22+
freeMins.set(c - r + (n - 1), v)
2323
}
2424

2525
def placeQueen(c: Int): Bool =
2626
try {
2727
each(0, n) { r =>
2828
if (getRowColumn(r, c)) {
29-
queenRows.unsafeSet(r, c);
29+
queenRows.set(r, c);
3030
setRowColumn(r, c, false);
3131

3232
if (c == (n - 1)) {

examples/benchmarks/are_we_fast_yet/sieve.effekt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ def run(size: Int) = {
66
var primeCount: Int = 0;
77
val flags: Array[Bool] = array(size, true);
88
each(2, size) { i =>
9-
if (flags.unsafeGet(i - 1)) {
9+
if (flags.get(i - 1)) {
1010
primeCount = primeCount + 1;
1111
var k = i + i;
1212
while (k <= size) {
13-
flags.unsafeSet(k - 1, false);
13+
flags.set(k - 1, false);
1414
k = k + i;
1515
}
1616
}

examples/benchmarks/are_we_fast_yet/storage.effekt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def run(n: Int) = {
3131
def buildTreeDepth(depth: Int) { rand: Random }: Tree = {
3232
count.set(count.get + 1);
3333
if (depth == 1) {
34-
Leaf(allocate(mod(rand.next, 10) + 1))
34+
Leaf(array::allocateZeros(mod(rand.next, 10) + 1))
3535
} else {
3636
Node(
3737
buildTreeDepth(depth - 1){ rand },

examples/benchmarks/are_we_fast_yet/towers.effekt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,25 @@ def run(n: Int) = {
1313
var towers: Towers = array(3, Nil());
1414

1515
def pushDisk(newTopDiskOnPile: Disk, pileIdx: Int): Unit = {
16-
val pile: Pile = towers.unsafeGet(pileIdx);
16+
val pile: Pile = towers.get(pileIdx);
1717
pile match {
1818
case Cons(topDiskOnStack, _) =>
1919
if (newTopDiskOnPile >= topDiskOnStack) {
2020
panic("Cannot put a big disk onto a smaller one");
2121
}
2222
case Nil() => ()
2323
}
24-
towers.unsafeSet(pileIdx, Cons(newTopDiskOnPile, pile));
24+
towers.set(pileIdx, Cons(newTopDiskOnPile, pile));
2525
}
2626

2727
def popDisk(pileIdx: Int): Disk = {
28-
val pile = towers.unsafeGet(pileIdx);
28+
val pile = towers.get(pileIdx);
2929

3030
pile match {
3131
case Nil() =>
3232
panic("Attempting to remove a disk from an empty pile");
3333
case Cons(disk, next) =>
34-
towers.unsafeSet(pileIdx, next)
34+
towers.set(pileIdx, next)
3535
disk
3636
}
3737
}

examples/benchmarks/input_output/large_file.effekt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def run(n: Int) = {
1616
panic("failed open for writing")
1717
}
1818
val outputBuffer = bytearray(size, 33.toByte)
19-
outputBuffer.unsafeSet(999, 10.toByte)
19+
outputBuffer.set(999, 10.toByte)
2020
repeat(n) {
2121
val m = internal::write(file, outputBuffer, 0, size, -1)
2222
if (m < outputBuffer.size) {

examples/pos/array/list_conversion.effekt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def main() = {
5050
listToArrayAndBack(list)
5151

5252
println("empty array")
53-
val emptyArray = array::allocate[Int](0)
53+
val emptyArray = array[Int](0, 0)
5454
arrayToListAndBack(emptyArray)
5555

5656
println("nonempty array")

0 commit comments

Comments
 (0)