summaryrefslogtreecommitdiff
path: root/module/ice-9
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2017-03-09 17:22:08 +0100
committerAndy Wingo <wingo@pobox.com>2017-03-09 17:24:06 +0100
commitc525aa6d95a9e19b260d6b99dbf6d73939d76585 (patch)
tree579660b1a34b147b3b132b2c64f1e6807dbe3dd5 /module/ice-9
parentf71c2c12609abfac9af7d38ea99f89a1f51b6992 (diff)
VM support for string-set!; slimmer read-string
* doc/ref/vm.texi (Inlined Scheme Instructions): Add string-set!. * libguile/vm-engine.c (string-set!): New opcode. * module/ice-9/rdelim.scm (read-string): Reimplement in terms of a geometrically growing list of strings, to reduce total heap usage when reading big files. * module/language/cps/compile-bytecode.scm (compile-function): Add string-set! support. * module/language/cps/types.scm (string-set!): Update for &u64 index. * module/language/tree-il/compile-cps.scm (convert): Unbox index to string-set!. * module/system/vm/assembler.scm (system): Export string-set!.
Diffstat (limited to 'module/ice-9')
-rw-r--r--module/ice-9/rdelim.scm19
1 files changed, 13 insertions, 6 deletions
diff --git a/module/ice-9/rdelim.scm b/module/ice-9/rdelim.scm
index a406f4e55..d2cd081d7 100644
--- a/module/ice-9/rdelim.scm
+++ b/module/ice-9/rdelim.scm
@@ -156,13 +156,20 @@ If the COUNT argument is present, treat it as a limit to the number of
characters to read. By default, there is no limit."
((#:optional (port (current-input-port)))
;; Fast path.
- ;; This creates more garbage than using 'string-set!' as in
- ;; 'read-string!', but currently that is faster nonetheless.
- (let loop ((chars '()))
+ (let loop ((head (make-string 30)) (pos 0) (tail '()))
(let ((char (read-char port)))
- (if (eof-object? char)
- (list->string (reverse! chars))
- (loop (cons char chars))))))
+ (cond
+ ((eof-object? char)
+ (let ((head (substring head 0 pos)))
+ (if (null? tail)
+ (substring head 0 pos)
+ (string-concatenate-reverse tail head pos))))
+ (else
+ (string-set! head pos char)
+ (if (< (1+ pos) (string-length head))
+ (loop head (1+ pos) tail)
+ (loop (make-string (* (string-length head) 2)) 0
+ (cons head tail))))))))
((port count)
;; Slower path.
(let loop ((chars '())