Skip to content

Commit f57e1fa

Browse files
committed
optimize some bytevector functions
refactor some sequence-related functions
1 parent e92a6ed commit f57e1fa

20 files changed

+471
-335
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ containers.o: containers/containers.c containers/containers.h eval.h
6666
eval.o: eval.c eval.h
6767
$(CC) -o $@ -c $< $(CFLAGS) -I"$(CHEZ_SCHEME_DIR)"
6868

69-
posix.o: posix/posix.c posix/posix.h eval.h
69+
posix.o: posix/posix.c posix/posix.h posix/signal.h eval.h
7070
$(CC) -o $@ -c $< $(CFLAGS) -I"$(CHEZ_SCHEME_DIR)"
7171

7272
shell.o: shell/shell.c shell/shell.h containers/containers.h eval.h posix/posix.h

bootstrap/bootstrap.ss

+9-4
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,15 @@
130130
(syntax-case stx ()
131131
((_ caller (proc args ...))
132132
(with-syntax (((targs ...) (generate-pretty-temporaries #'(args ...))))
133-
#`(let ((tproc proc) (targs args) ...)
134-
(if (tproc targs ...)
135-
(void)
136-
(raise-assert* caller #,form targs ...)))))
133+
(if (symbol? (syntax->datum #'proc))
134+
#`(let ((targs args) ...) ;; proc is a symbol, no need to save its value into a local variable
135+
(if (proc targs ...)
136+
(void)
137+
(raise-assert* caller #,form targs ...)))
138+
#`(let ((tproc proc) (targs args) ...)
139+
(if (tproc targs ...)
140+
(void)
141+
(raise-assert* caller #,form targs ...))))))
137142
((_ caller expr)
138143
#`(let ((texpr expr))
139144
(if texpr

containers/bytespan.ss

+15-13
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
(only (chezscheme) bytevector-truncate! fx1+ fx1- record-writer void)
3030
(only (schemesh bootstrap) assert* assert-not*)
3131
(only (schemesh containers list) list-iterate)
32-
(schemesh containers misc))
32+
(schemesh containers bytevector))
3333

3434
(define-record-type
3535
(%bytespan %make-bytespan bytespan?)
@@ -112,7 +112,8 @@
112112
(bytespan-end sp) u8))
113113

114114
(define (bytespan-fill-range! sp start end u8)
115-
(assert* 'bytespan-fill-range! (fx<=? 0 start end (bytespan-length sp)))
115+
(assert* 'bytespan-fill-range! (fx<=? 0 start end))
116+
(assert* 'bytespan-fill-range! (fx<=? end (bytespan-length sp)))
116117
(let ((offset (bytespan-beg sp)))
117118
(bytevector-fill-range! (bytespan-vec sp) (fx+ start offset) (fx+ end offset) u8)))
118119

@@ -124,8 +125,11 @@
124125
dst))
125126

126127
(define (bytespan-copy! src src-start dst dst-start n)
127-
(assert* 'bytespan-copy! (fx<=? 0 src-start (fx+ src-start n) (bytespan-length src)))
128-
(assert* 'bytespan-copy! (fx<=? 0 dst-start (fx+ dst-start n) (bytespan-length dst)))
128+
;; assert* allocates if too many arguments
129+
(assert* 'bytespan-copy! (fx<=? 0 src-start (fx+ src-start n)))
130+
(assert* 'bytespan-copy! (fx<=? 0 dst-start (fx+ dst-start n)))
131+
(assert* 'bytespan-copy! (fx<=? (fx+ src-start n) (bytespan-length src)))
132+
(assert* 'bytespan-copy! (fx<=? (fx+ dst-start n) (bytespan-length dst)))
129133
(bytevector-copy! (bytespan-vec src) (fx+ src-start (bytespan-beg src))
130134
(bytespan-vec dst) (fx+ dst-start (bytespan-beg dst)) n))
131135

@@ -285,8 +289,10 @@
285289
(define bytespan-insert-right/bspan!
286290
(case-lambda
287291
((sp-dst sp-src src-start src-end)
292+
;; assert* allocates if too many arguments
288293
(assert-not* 'bytespan-insert-right/bspan! (eq? sp-dst sp-src))
289-
(assert* 'bytespan-insert-right/bspan! (fx<=? 0 src-start src-end (bytespan-length sp-src)))
294+
(assert* 'bytespan-insert-right/bspan! (fx<=? 0 src-start src-end))
295+
(assert* 'bytespan-insert-right/bspan! (fx<=? src-end (bytespan-length sp-src)))
290296
(when (fx<? src-start src-end)
291297
;; check for (not (eq? src dst)) only if dst is non-empty,
292298
;; because reusing the empty bytevector is a common optimization of Scheme compilers
@@ -329,20 +335,16 @@
329335
(define in-bytespan
330336
(case-lambda
331337
((sp start end step)
332-
(assert* 'in-bytespan (fx<=? 0 start end (bytespan-length sp)))
338+
(assert* 'in-bytespan (fx<=? 0 start end))
339+
(assert* 'in-bytespan (fx<=? end (bytespan-length sp)))
333340
(assert* 'in-bytespan (fx>=? step 0))
334-
(lambda ()
335-
(if (fx<? start end)
336-
(let ((elem (bytespan-ref/u8 sp start)))
337-
(set! start (fx+ start step))
338-
(values elem #t))
339-
(values 0 #f))))
341+
(let ((offset (bytespan-beg sp)))
342+
(in-bytevector (bytespan-vec sp) (fx+ start offset) (fx+ end offset) step)))
340343
((sp start end)
341344
(in-bytespan sp start end 1))
342345
((sp)
343346
(in-bytespan sp 0 (bytespan-length sp) 1))))
344347

345-
346348
;; (bytespan-iterate l proc) iterates on all elements of given bytespan sp,
347349
;; and calls (proc index elem) on each element. stops iterating if (proc ...) returns #f
348350
;;

containers/bytevector.ss

+70-26
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,78 @@
99
;; this file should be included only by file containers/misc.ss
1010

1111

12+
(library (schemesh containers bytevector (0 8 1))
13+
(export
14+
in-bytevector list->bytevector subbytevector
15+
bytevector-fill-range! bytevector-index bytevector-compare
16+
bytevector<=? bytevector<? bytevector>=? bytevector>? bytevector-iterate)
17+
(import
18+
(rnrs)
19+
(rnrs mutable-pairs)
20+
(only (chezscheme) bytevector foreign-procedure fx1+ logbit? procedure-arity-mask)
21+
(only (schemesh bootstrap) assert*))
22+
23+
24+
;; each element in list l must be a fixnum in the range [-128, 255]
1225
(define (list->bytevector l)
1326
(apply bytevector l))
1427

1528

1629
;; return a copy of bytevector bvec containing only elements
1730
;; from start (inclusive) to end (exclusive)
1831
(define (subbytevector bvec start end)
19-
(assert* 'subbytevector (fx<=? 0 start end (bytevector-length bvec)))
32+
(assert* 'subbytevector (fx<=? 0 start end))
33+
(assert* 'subbytevector (fx<=? end (bytevector-length bvec)))
2034
(let* ((n (fx- end start))
2135
(dst (make-bytevector n)))
2236
(bytevector-copy! bvec start dst 0 n)
2337
dst))
2438

25-
(define (bytevector-fill-range! bvec start end val)
26-
(assert* 'bytevector-fill-range! (fx<=? 0 start end (bytevector-length bvec)))
27-
(do ((i start (fx1+ i)))
28-
((fx>=? i end))
29-
(bytevector-u8-set! bvec i val)))
30-
31-
32-
;; search bytevector range [start, end) and return index of first byte equal to b.
39+
(define bytevector-fill-range!
40+
(let ((c-bytevector-fill-range (foreign-procedure "c_bytevector_fill_range" (ptr int int int) void)))
41+
(lambda (bvec start end val)
42+
;; assert* allocates if too many arguments
43+
(assert* 'bytevector-fill-range! (fx<=? 0 start end))
44+
(assert* 'bytevector-fill-range! (fx<=? end (bytevector-length bvec)))
45+
(assert* 'bytevector-fill-range! (fx<=? -128 val 255))
46+
(let ((val (fxand val 255))
47+
(n (fx- end start)))
48+
(if (fx<? n 3)
49+
(unless (fxzero? n)
50+
(bytevector-u8-set! bvec start val)
51+
(when (fx>? n 1)
52+
(bytevector-u8-set! bvec (fx1+ start) val)))
53+
(c-bytevector-fill-range bvec start end val))))))
54+
55+
56+
;; search bytevector range [start, end) and return index of first byte equal to u8 or that satisfies pred.
3357
;; returned numerical index will be in the range [start, end).
3458
;; return #f if no such byte is found in range.
35-
(define bytevector-index/u8
36-
(case-lambda
37-
((bvec start end b)
38-
(assert* 'bytevector-index/u8 (bytevector? bvec))
39-
(assert* 'bytevector-index/u8 (fx<=? 0 start end (bytevector-length bvec)))
40-
(assert* 'bytevector-index/u8 (fx<=? 0 b 255))
41-
(do ((i start (fx1+ i)))
42-
((or (fx>=? i end) (fx=? b (bytevector-u8-ref bvec i)))
43-
(if (fx>=? i end) #f i))))
44-
((bvec b)
45-
(bytevector-index/u8 bvec 0 (bytevector-length bvec) b))))
59+
(define bytevector-index
60+
(let ((c-bytevector-index-u8 (foreign-procedure "c_bytevector_index_u8" (ptr int int int) ptr)))
61+
(case-lambda
62+
((bvec start end byte-or-pred)
63+
;; assert* allocates if too many arguments
64+
(assert* 'bytevector-index (bytevector? bvec))
65+
(assert* 'bytevector-index (fx<=? 0 start end))
66+
(assert* 'bytevector-index (fx<=? end (bytevector-length bvec)))
67+
(if (fixnum? byte-or-pred)
68+
(begin
69+
(assert* 'bytevector-index (fx<=? -128 byte-or-pred 255))
70+
(let ((u8 (fxand byte-or-pred 255)))
71+
(if (fx<? (fx- end start) 4)
72+
(do ((i start (fx1+ i)))
73+
((or (fx>=? i end) (fx=? u8 (bytevector-u8-ref bvec i)))
74+
(if (fx<? i end) i #f)))
75+
(c-bytevector-index-u8 bvec start end u8))))
76+
(begin
77+
(assert* 'bytevector-index (logbit? 1 (procedure-arity-mask byte-or-pred)))
78+
(let ((pred byte-or-pred))
79+
(do ((i start (fx1+ i)))
80+
((or (fx>=? i end) (pred (bytevector-u8-ref bvec i)))
81+
(if (fx<? i end) i #f)))))))
82+
((bvec byte-or-pred)
83+
(bytevector-index bvec 0 (bytevector-length bvec) byte-or-pred)))))
4684

4785

4886

@@ -56,12 +94,14 @@
5694
((sp start end step)
5795
(assert* 'in-bytevector (fx<=? 0 start end (bytevector-length sp)))
5896
(assert* 'in-bytevector (fx>=? step 0))
59-
(lambda ()
60-
(if (fx<? start end)
61-
(let ((elem (bytevector-u8-ref sp start)))
62-
(set! start (fx+ start step))
63-
(values elem #t)))
64-
(values 0 #f)))
97+
(let ((%in-bytevector ; name shown when displaying the closure
98+
(lambda ()
99+
(if (fx<? start end)
100+
(let ((elem (bytevector-u8-ref sp start)))
101+
(set! start (fx+ start step))
102+
(values elem #t)))
103+
(values 0 #f))))
104+
%in-bytevector))
65105
((sp start end)
66106
(in-bytevector sp start end 1))
67107
((sp)
@@ -80,6 +120,7 @@
80120
((or (fx>=? i n) (not (proc i (bytevector-u8-ref bvec i))))
81121
(fx>=? i n))))
82122

123+
83124
;; compare the two bytevectors bvec1 and bvec2.
84125
;; return -1 if bvec1 is lexicographically lesser than bvec2,
85126
;; return 0 if they are equal,
@@ -93,6 +134,7 @@
93134
(or (eq? bvec1 bvec2)
94135
(c-bytevector-compare bvec1 bvec2)))))
95136

137+
96138
(define (bytevector<=? bvec1 bvec2)
97139
(fx<=? (bytevector-compare bvec1 bvec2) 0))
98140

@@ -104,3 +146,5 @@
104146

105147
(define (bytevector>? bvec1 bvec2)
106148
(fx>? (bytevector-compare bvec1 bvec2) 0))
149+
150+
) ; close library

containers/chargbuffer.ss

+8-6
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,14 @@
221221
((gb start end step)
222222
(assert* 'in-chargbuffer (fx<=? 0 start end (chargbuffer-length gb)))
223223
(assert* 'in-chargbuffer (fx>=? step 0))
224-
(lambda ()
225-
(if (fx<? start end)
226-
(let ((elem (chargbuffer-ref gb start)))
227-
(set! start (fx+ start step))
228-
(values elem #t))
229-
(values #\nul #f))))
224+
(let ((%in-chargbuffer ; name shown when displaying the closure
225+
(lambda ()
226+
(if (fx<? start end)
227+
(let ((elem (chargbuffer-ref gb start)))
228+
(set! start (fx+ start step))
229+
(values elem #t))
230+
(values #\nul #f)))))
231+
%in-chargbuffer))
230232
((gb start end)
231233
(in-chargbuffer gb start end 1))
232234
((gb)

containers/charline.ss

+8-6
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,14 @@
264264
((line start end step)
265265
(assert* 'in-charline (fx<=? 0 start end (charline-length line)))
266266
(assert* 'in-charline (fx>=? step 0))
267-
(lambda ()
268-
(if (fx<? start end)
269-
(let ((elem (charline-ref line start)))
270-
(set! start (fx+ start step))
271-
(values elem #t))
272-
(values #\nul #f))))
267+
(let ((%in-charline ; name shown when displaying the closure
268+
(lambda ()
269+
(if (fx<? start end)
270+
(let ((elem (charline-ref line start)))
271+
(set! start (fx+ start step))
272+
(values elem #t))
273+
(values #\nul #f)))))
274+
%in-charline))
273275
((line start end)
274276
(in-charline line start end 1))
275277
((line)

containers/charlines.ss

+8-6
Original file line numberDiff line numberDiff line change
@@ -366,12 +366,14 @@
366366
((lines start end step)
367367
(assert* 'in-charlines (fx<=? 0 start end (charlines-length lines)))
368368
(assert* 'in-charlines (fx>=? step 0))
369-
(lambda ()
370-
(if (fx<? start end)
371-
(let ((elem (charlines-ref lines start)))
372-
(set! start (fx+ start step))
373-
(values elem #t))
374-
(values #f #f))))
369+
(let ((%in-charlines ; name shown when displaying the closure
370+
(lambda ()
371+
(if (fx<? start end)
372+
(let ((elem (charlines-ref lines start)))
373+
(set! start (fx+ start step))
374+
(values elem #t))
375+
(values #f #f)))))
376+
%in-charlines))
375377
((lines start end)
376378
(in-charlines lines start end 1))
377379
((lines)

containers/charspan.ss

+8-6
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,14 @@
406406
((sp start end step)
407407
(assert* 'in-charspan (fx<=? 0 start end (charspan-length sp)))
408408
(assert* 'in-charspan (fx>=? step 0))
409-
(lambda ()
410-
(if (fx<? start end)
411-
(let ((elem (charspan-ref sp start)))
412-
(set! start (fx+ start step))
413-
(values elem #t))
414-
(values #\nul #f))))
409+
(let ((%in-charspan ; name shown when displaying the closure
410+
(lambda ()
411+
(if (fx<? start end)
412+
(let ((elem (charspan-ref sp start)))
413+
(set! start (fx+ start step))
414+
(values elem #t))
415+
(values #\nul #f)))))
416+
%in-charspan))
415417
((sp start end)
416418
(in-charspan sp start end 1))
417419
((sp)

containers/containers.c

+28-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,29 @@ static signed char c_bytevector_compare(ptr left, ptr right) {
5151
}
5252
}
5353

54+
/** fill with value a bytevector range */
55+
static void c_bytevector_fill_range(ptr bvec, iptr start, iptr end, int value) {
56+
if (Sbytevectorp(bvec) && 0 <= start && start < end && end <= Sbytevector_length(bvec)) {
57+
memset(Sbytevector_data(bvec) + start, value & 0xFF, (size_t)end - (size_t)start);
58+
}
59+
}
60+
61+
/**
62+
* find first byte equal to value in bytevector range,
63+
* and return its position in the range [start, end)
64+
* return #f if no such byte was found.
65+
*/
66+
static ptr c_bytevector_index_u8(ptr bvec, iptr start, iptr end, int value) {
67+
if (Sbytevectorp(bvec) && 0 <= start && start < end && end <= Sbytevector_length(bvec)) {
68+
const octet* data = Sbytevector_data(bvec) + start;
69+
const octet* match = (const octet*)memchr(data, value & 0xFF, (size_t)end - (size_t)start);
70+
if (match) {
71+
return Sfixnum((size_t)(match - data));
72+
}
73+
}
74+
return Sfalse;
75+
}
76+
5477
/**
5578
* INTENTIONALLY fills string with Unicode codepoints in the surrogate range 0xDC80..0xDCFF,
5679
* which cannot be created with (integer->char).
@@ -366,6 +389,7 @@ static size_t c_bytes_utf8b_to_string_length(const octet* bytes, size_t len) {
366389
return ret;
367390
}
368391

392+
#if 0
369393
/**
370394
* convert the range [start, end) of UTF-8b bytevector to UTF-32 string.
371395
* and return ONLY the length of converted string i.e. the number of Unicode codepoints.
@@ -390,6 +414,7 @@ static iptr c_bytevector_utf8b_to_string_length(ptr bvec, iptr start, iptr end)
390414
}
391415
return 0;
392416
}
417+
#endif /* 0 */
393418

394419
static sizepair c_sizepair(const size_t byte_n, const size_t char_n) {
395420
sizepair ret;
@@ -511,12 +536,14 @@ ptr schemesh_Sbytevector(const char chars[], const size_t len) {
511536

512537
void schemesh_register_c_functions_containers(void) {
513538
Sregister_symbol("c_bytevector_compare", &c_bytevector_compare);
539+
Sregister_symbol("c_bytevector_fill_range", &c_bytevector_fill_range);
540+
Sregister_symbol("c_bytevector_index_u8", &c_bytevector_index_u8);
514541
Sregister_symbol("c_string_fill_utf8b_surrogate_chars", &c_string_fill_utf8b_surrogate_chars);
515542
Sregister_symbol("c_string_to_utf8b_length", &c_string_to_utf8b_length);
516543
Sregister_symbol("c_string_to_utf8b_append", &c_string_to_utf8b_append);
517544
#if 0
518545
Sregister_symbol("c_string_to_utf8b", &c_string_to_utf8b);
519-
#endif /* 0 */
520546
Sregister_symbol("c_bytevector_utf8b_to_string_length", &c_bytevector_utf8b_to_string_length);
547+
#endif /* 0 */
521548
Sregister_symbol("c_bytevector_utf8b_to_string_append", &c_bytevector_utf8b_to_string_append);
522549
}

0 commit comments

Comments
 (0)