Ludovic Courtès schreef op ma 04-07-2022 om 12:09 [+0200]: > I don’t think the optimizer makes any such assumption, except for > literal bytevectors.
It _does_ assume that bytevector lengths don't change: ,use (rnrs bytevectors) ,compile (bytevector-u8-ref some-variable 999) ;;; <unknown-location>: warning: possibly unbound variable `some-variable' Disassembly of <unnamed function> at #xe8: 0 (instrument-entry 254) at (unknown file):4:9 2 (assert-nargs-ee/locals 1 3) ;; 4 slots (0 args) 3 (call-scm<-thread 3 62) at (unknown file):4:28 5 (static-ref 2 187) ;; some-variable 7 (call-scm<-scm-scm 3 3 2 111) 9 (scm-ref/immediate 3 3 1) 10 (make-immediate 2 3998) ;; 999 at (unknown file):4:42 11 (immediate-tag=? 3 7 0) ;; heap-object? at (unknown file):4:9 13 (jne 21) ;; -> L2 14 (heap-tag=? 3 127 77) ;; bytevector? 16 (jne 18) ;; -> L2 17 (word-ref/immediate 1 3 1) 18 (load-s64 0 0 999) 21 (imm-u64<? 1 0) 22 (jnl 10) ;; -> L1 23 (usub/immediate 1 1 0) 24 (u64<? 0 1) 25 (jnl 7) ;; -> L1 26 (pointer-ref/immediate 2 3 2) 27 (u8-ref 3 2 0) 28 (tag-fixnum 3 3) 29 (reset-frame 1) ;; 1 slot 30 (handle-interrupts) 31 (return-values) L1: 32 (throw/value+data 2 188) ;; #(out-of-range "bytevector-u8-ref" "Argument 2 out of range: ~S") L2: 34 (throw/value+data 3 212) ;; #(wrong-type-arg "bytevector-u8-ref" "Wrong type argument in position 1 (ex…") As can be seen in the above output, it first determines the length of the bytevector and then compares it again the index (for the index check) and then actually reads th byte so it assumes that the length doesn't change in-between -- it's not an atomic operation! Even if it didn't, being able to assume bytevector lengths don't change is important for optimising code like (begin (bytevector-ref bv 9000) (bytevector-ref 8999) ...)), to optimise out many range checks, though I don't know if Guile currently does that. Greetings, Maxime.