Skip to content

Commit 8f6807d

Browse files
committed
refactor bytes to copy on write if not unique
1 parent b6195dd commit 8f6807d

File tree

9 files changed

+90
-14
lines changed

9 files changed

+90
-14
lines changed

kklib/include/kklib/bytes.h

+13-5
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,6 @@ static inline int8_t kk_bytes_at(kk_bytes_t p, uint64_t i, kk_context_t* ctx){
162162
return (int8_t)buf[i];
163163
}
164164

165-
static inline void kk_bytes_set(kk_bytes_t p, uint64_t i, int8_t b, kk_context_t* ctx){
166-
uint8_t* buf = (uint8_t*)kk_bytes_buf_borrow(p, NULL, ctx);
167-
buf[i] = (uint8_t)b;
168-
}
169-
170165
/*--------------------------------------------------------------------------------------------------
171166
Length, compare
172167
--------------------------------------------------------------------------------------------------*/
@@ -200,6 +195,19 @@ static inline kk_bytes_t kk_bytes_copy(kk_bytes_t b, kk_context_t* ctx) {
200195
}
201196
}
202197

198+
static inline kk_bytes_t kk_bytes_set(kk_bytes_t bytes, uint64_t i, int8_t b, kk_context_t* ctx){
199+
if (kk_datatype_ptr_is_unique(bytes, ctx)) {
200+
uint8_t* buf = (uint8_t*)kk_bytes_buf_borrow(bytes, NULL, ctx);
201+
buf[i] = (uint8_t)b;
202+
return bytes;
203+
} else {
204+
kk_bytes_t bytes_new = kk_bytes_copy(bytes, ctx);
205+
uint8_t* buf = (uint8_t*)kk_bytes_buf_borrow(bytes_new, NULL, ctx);
206+
buf[i] = (uint8_t)b;
207+
return bytes_new;
208+
}
209+
}
210+
203211
static inline bool kk_bytes_ptr_eq_borrow(kk_bytes_t b1, kk_bytes_t b2) {
204212
return (kk_datatype_eq(b1, b2));
205213
}

lib/std/core.kk

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ pub import std/core/order
2525
pub import std/core/char
2626
pub import std/core/int
2727
pub import std/core/vector
28+
pub import std/core/bytes
29+
pub import std/core/bslice
2830
pub import std/core/string
2931
pub import std/core/sslice
3032
pub import std/core/list

lib/std/data/bslice.kk renamed to lib/std/core/bslice.kk

+24-4
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@
77
---------------------------------------------------------------------------*/
88

99
// Byte slices
10-
module std/data/bslice
11-
import std/data/bytes
10+
module std/core/bslice
11+
import std/core/bytes
12+
import std/core/types
13+
import std/core/int
14+
import std/core/exn
15+
16+
extern import
17+
c file "inline/bslice"
1218

1319
// A byte slice
14-
pub struct bslice
20+
pub value struct bslice
1521
bytes: bytes
1622
start: int
1723
len: int // The length of the slice
@@ -79,4 +85,18 @@ pub fun after(slice: bslice): bslice
7985
pub fun @index( ^b : bslice, i : int ) : exn int8
8086
val Bslice(bts, start, len, _) = b
8187
if i < 0 || i >= len then throw("index out of bounds", ExnRange)
82-
bts.unsafe-index((start + i).ssize_t)
88+
bts.unsafe-index((start + i).ssize_t)
89+
90+
// Assigns the bytes starting at offset `i` to `new-value`, throws if there is not enough space or the index is invalid
91+
pub fun assign( b : bytes, i : int, new-value : bslice ) : exn bytes
92+
val l = b.length.int
93+
val size = new-value.len
94+
if i < 0 || i > l then
95+
throw("index out of bounds", ExnRange)
96+
elif size + i > l then
97+
throw("size overflow", ExnRange)
98+
else
99+
assign(b, i.ssize_t, new-value)
100+
101+
extern slice/assign(b : bytes, i : ssize_t, new-value : bslice ): bytes
102+
c "kk_bslice_assign"

lib/std/data/bytes.kk renamed to lib/std/core/bytes.kk

+7-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
---------------------------------------------------------------------------*/
88

99
// Byte arrays
10-
module std/data/bytes
10+
module std/core/bytes
11+
import std/core/types
12+
import std/core/exn
13+
import std/core/bool
14+
import std/core/int
1115

1216
// Create a new empty array of bytes
1317
pub extern empty(): bytes
@@ -27,7 +31,7 @@ pub extern string( bytes : bytes ) : string
2731
// Gets a view of the string as raw bytes
2832
pub extern string/bytes( s : string ) : bytes
2933
c inline "#1.bytes"
30-
js inline "new TextEncoder().encode(#1)"
34+
js inline "(new TextEncoder()).encode(#1)"
3135

3236
// Gets the length of the byte array
3337
pub extern length( ^b : bytes ) : ssize_t
@@ -51,6 +55,6 @@ pub extern unsafe-index( ^b : bytes, i : ssize_t ) : int8
5155
js inline "#1[#2]"
5256

5357
// Assigns the byte at offset `i` to `new-value`
54-
pub extern byte/assign( ^b : bytes, i : ssize_t, new-value : int8 ) : ()
58+
pub extern byte/assign( b : bytes, i : ssize_t, new-value : int8 ) : bytes
5559
c "kk_bytes_set"
5660
js inline "#1[#2] = #3"

lib/std/core/inline/bslice.c

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
kk_bytes_t kk_bslice_assign( kk_bytes_t bytes, kk_ssize_t i, struct kk_std_core_bslice_Bslice bslice, kk_context_t* ctx ){
2+
kk_ssize_t len;
3+
const uint8_t* bslice_buf = kk_bytes_buf_borrow(bslice.bytes, &len, ctx);
4+
kk_ssize_t slice_len = kk_integer_clamp_ssize_t_borrow(bslice.len, ctx);
5+
kk_ssize_t slice_start = kk_integer_clamp_ssize_t_borrow(bslice.start, ctx);
6+
if (kk_datatype_ptr_is_unique(bytes, ctx)) {
7+
kk_info_message("kk_bslice_assign: unique\n");
8+
uint8_t* buf = (uint8_t*)kk_bytes_buf_borrow(bytes, &len, ctx);
9+
for (kk_ssize_t j = 0; j < slice_len; j++) {
10+
buf[i + j] = bslice_buf[slice_start + j];
11+
}
12+
kk_std_core_bslice__bslice_drop(bslice,ctx);
13+
return bytes;
14+
} else {
15+
kk_info_message("kk_bslice_assign: not unique\n");
16+
kk_bytes_t bytes_new = kk_bytes_copy(bytes, ctx);
17+
uint8_t* buf_new = (uint8_t*)kk_bytes_buf_borrow(bytes_new, NULL, ctx);
18+
for (kk_ssize_t j = 0; j < slice_len; j++) {
19+
buf_new[i + j] = bslice_buf[slice_start + j];
20+
}
21+
kk_std_core_bslice__bslice_drop(bslice,ctx);
22+
return bytes_new;
23+
}
24+
}

lib/std/core/inline/bslice.h

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
/*---------------------------------------------------------------------------
3+
Copyright 2020-2024, Microsoft Research, Daan Leijen. Tim Whiting.
4+
5+
This is free software; you can redistribute it and/or modify it under the
6+
terms of the Apache License, Version 2.0. A copy of the License can be
7+
found in the LICENSE file at the root of this distribution.
8+
---------------------------------------------------------------------------*/
9+
10+
struct kk_std_core_bslice_Bslice;
11+
kk_bytes_t kk_bslice_assign( kk_bytes_t bytes, kk_ssize_t i, struct kk_std_core_bslice_Bslice bslice, kk_context_t* ctx );

src/Backend/C/FromCore.hs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2229,9 +2229,8 @@ genExprExternal tname formats [fieldDoc,argDoc] | getName tname == nameCFieldSet
22292229
-- normal external
22302230
genExprExternal tname formats argDocs0
22312231
= do
2232-
ctarget <- getCTarget
22332232
let name = getName tname
2234-
format = getFormat ctarget tname formats
2233+
format = getFormat tname formats
22352234
argDocs = map (\argDoc -> if (all (\c -> isAlphaNum c || c == '_') (asString argDoc)) then argDoc else parens argDoc) argDocs0
22362235
return $ case map (\fmt -> ppExternalF name fmt argDocs) $ lines format of
22372236
[] -> ([],empty)

test/lib/bytes.kk

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
3+
fun main()
4+
val b1 = "Hello There".bytes
5+
val new = "World".bytes.slice
6+
val b2 = b1.assign(6, new)
7+
println(b2.string)

test/lib/bytes.kk.out

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello World

0 commit comments

Comments
 (0)