changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate lisp/lib/io/static-vector.lisp

changeset 695: 2bad47888dbf
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 16:14:44 -0400
permissions: -rw-r--r--
description: add static-vector
695
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1
 ;;; static-vector.lisp --- Static Vectors
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3
 ;; Vectors allocated in static memory. Useful for things like IO buffers
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
4
 ;; created from Lisp and shared with C code.
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
5
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
6
 ;;; Commentary:
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
7
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
8
 ;; The source here is pulled directly from the STATIC-VECTORS package on
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
9
 ;; Quicklisp: https://github.com/sionescu/static-vectors
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
10
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
11
 ;;; Code:
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
12
 (in-package :io/static-vector)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
13
 ;;; --- Checking for compile-time constants and evaluating such forms
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
14
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
15
 (defun quotedp (form)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
16
   (and (listp form)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
17
        (= 2 (length form))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
18
        (eql 'quote (car form))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
19
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
20
 (defun constantp (form &optional env)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
21
   (let ((form (if (symbolp form)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
22
                   (macroexpand form env)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
23
                   form)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
24
     (or (quotedp form)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
25
         (cl:constantp form))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
26
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
27
 (defun eval-constant (form &optional env)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
28
   (declare (ignorable env))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
29
   (cond
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
30
     ((quotedp form)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
31
      (second form))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
32
     (t
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
33
      #+clozure
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
34
      (ccl::eval-constant form)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
35
      #+sbcl
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
36
      (sb-int:constant-form-value form env)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
37
      #-(or clozure sbcl)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
38
      (eval form))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
39
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
40
 (defun canonicalize-args (env element-type length)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
41
   (let* ((eltype-spec (or (and (constantp element-type)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
42
                                (ignore-errors
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
43
                                 (upgraded-array-element-type
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
44
                                  (eval-constant element-type))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
45
                           '*))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
46
          (length-spec (if (constantp length env)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
47
                           `,(eval-constant length env)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
48
                           '*))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
49
          (type-decl (if (eql '* eltype-spec)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
50
                         'simple-array
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
51
                         `(simple-array ,eltype-spec (,length-spec)))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
52
     (values (if (eql '* eltype-spec)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
53
                 element-type
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
54
                 `(quote ,eltype-spec))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
55
             (if (eql '* length-spec)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
56
                 length
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
57
                 length-spec)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
58
             type-decl)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
59
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
60
 ;;; --- SBCL implementation
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
61
 (declaim (inline fill-foreign-memory))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
62
 (defun fill-foreign-memory (pointer length value)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
63
   "Fill LENGTH octets in foreign memory area POINTER with VALUE."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
64
   (std/alien:memset pointer value length)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
65
   pointer)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
66
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
67
 (declaim (inline replace-foreign-memory))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
68
 (defun replace-foreign-memory (dst-ptr src-ptr length)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
69
   "Copy LENGTH octets from foreign memory area SRC-PTR to DST-PTR."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
70
   (std/alien:memcpy dst-ptr src-ptr length)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
71
   dst-ptr)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
72
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
73
 ;;; We have to handle all the low-level bits including setting the array header
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
74
 ;;; and keeping around the info about the original pointer returned by the
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
75
 ;;; foreign allocator.
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
76
 ;;;
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
77
 ;;; It goes like this:
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
78
 ;;;
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
79
 ;;; 1. Compute the data size for the Lisp-visible memory (that means an extra #\Nul
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
80
 ;;;    at the end for strings)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
81
 ;;; 2. Sum the data size, the SBCL header size, and our extra header size to get
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
82
 ;;;    the total foreign size required
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
83
 ;;; 3. Adjust the total foreign size to the required alignment, compute the header offset
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
84
 ;;;    and write the headers.
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
85
 ;;;
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
86
 ;;; Array layout:
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
87
 ;;;
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
88
 ;;;    +-------------------+
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
89
 ;;;    | Allocated address | <-- Original pointer
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
90
 ;;;    +-------------------+
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
91
 ;;;    | Start gap ...     | <-- For large alignments, there's a gap between
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
92
 ;;;    |                   |     the data block and the headers.
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
93
 ;;;    +-------------------+
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
94
 ;;;    | SV header         | <-- The offset from the original pointer (DWORD)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
95
 ;;;    +-------------------+
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
96
 ;;;    | Lisp array header | <-- Array element-type and size (DWORD)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
97
 ;;;    +-------------------+
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
98
 ;;;    | Lisp array data   | <-- Lisp-visible data
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
99
 ;;;    +-------------------+
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
100
 ;;;
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
101
 ;;; There's no end gap because when a alignment is requested,
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
102
 ;;; the requested size must also be a multiple of the alignment.
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
103
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
104
 (defconstant +array-header-size+
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
105
   (* sb-vm:vector-data-offset sb-vm:n-word-bytes))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
106
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
107
 (declaim (inline vector-widetag-and-n-bytes))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
108
 (defun vector-widetag-and-n-bytes (type)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
109
   "Returns the widetag and octet size of the upgraded array element type
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
110
 for a given type specifier."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
111
   (let ((upgraded-type (upgraded-array-element-type type)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
112
     (case upgraded-type
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
113
       ((nil t) (error "~A is not a specializable array element type" type))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
114
       (t
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
115
        #+#.(cl:if (cl:find-symbol "%VECTOR-WIDETAG-AND-N-BITS" "SB-IMPL")
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
116
                   '(and) '(or))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
117
        (sb-impl::%vector-widetag-and-n-bits type)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
118
        #+#.(cl:if (cl:find-symbol "%VECTOR-WIDETAG-AND-N-BITS-SHIFT" "SB-IMPL")
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
119
                   '(and) '(or))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
120
        (multiple-value-bind (widetag shift)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
121
            (sb-impl::%vector-widetag-and-n-bits-shift type)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
122
          (values widetag (expt 2 (- shift 3))))))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
123
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
124
 (declaim (inline align))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
125
 (defun align (size boundary)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
126
   (* boundary
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
127
      (ceiling size boundary)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
128
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
129
 (declaim (inline %memalign))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
130
 (defun %memalign (size alignment)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
131
   (with-alien ((box (* t)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
132
     (let ((errno (std/alien:posix-memalign box alignment size)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
133
       (when (not (zerop errno))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
134
         (error "posix_memalign() returned error ~A" errno))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
135
       ;; (mem-ref box :pointer)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
136
       (deref box))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
137
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
138
 (defun %allocate-static-vector (length element-type alignment)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
139
   (declare (type (unsigned-byte 16) alignment))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
140
   (flet ((allocation-sizes (length widetag n-bytes)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
141
            (values
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
142
             ;; We're allocating two headers: one for SBCL and
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
143
             ;; the other one for our bookkeeping.
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
144
             (align (* 2 +array-header-size+) alignment)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
145
             ;; Align data size.
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
146
             (align
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
147
              (* (if (= widetag sb-vm:simple-character-string-widetag)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
148
                     (1+ length)         ; for the final #\Nul
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
149
                     length)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
150
                 n-bytes)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
151
              alignment))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
152
     (multiple-value-bind (widetag n-bytes)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
153
         (vector-widetag-and-n-bytes element-type)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
154
       (multiple-value-bind (header-size data-size)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
155
           (allocation-sizes length widetag n-bytes)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
156
         (let* ((total-size (+ header-size data-size))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
157
                (foreign-block (%memalign total-size alignment))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
158
                (data-offset header-size )
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
159
                (lisp-header-offset
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
160
                  (- data-offset +array-header-size+))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
161
                (lisp-header-pointer
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
162
                  (sb-sys:sap+ foreign-block lisp-header-offset))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
163
                (extra-header-offset
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
164
                  (- data-offset (* 2 +array-header-size+)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
165
                (extra-header-pointer
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
166
                  (sb-sys:sap+ foreign-block extra-header-offset)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
167
           ;; Write Lisp header: tag and length
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
168
           (setf (sb-sys:sap-ref-word lisp-header-pointer 0) widetag)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
169
           (setf (sb-sys:sap-ref-word lisp-header-pointer sb-vm:n-word-bytes)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
170
                 (sb-vm:fixnumize length))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
171
           ;; Save the relative position from the start of the foreign block
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
172
           (setf (sb-sys:sap-ref-word extra-header-pointer 0)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
173
                 (- data-offset (* 2 +array-header-size+)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
174
           ;; Instantiate Lisp object
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
175
           (sb-kernel:%make-lisp-obj (logior (sb-sys:sap-int lisp-header-pointer)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
176
                                             sb-vm:other-pointer-lowtag)))))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
177
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
178
 (declaim (inline static-vector-address))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
179
 (defun static-vector-address (vector)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
180
   "Return a foreign pointer to start of the Lisp VECTOR(including its header).
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
181
 VECTOR must be a vector created by MAKE-STATIC-VECTOR."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
182
   (logandc2 (sb-kernel:get-lisp-obj-address vector)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
183
             sb-vm:lowtag-mask))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
184
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
185
 (declaim (inline static-vector-pointer))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
186
 (defun static-vector-pointer (vector &key (offset 0))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
187
   "Return a foreign pointer to the beginning of VECTOR + OFFSET octets.
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
188
 VECTOR must be a vector created by MAKE-STATIC-VECTOR."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
189
   (check-type offset unsigned-byte)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
190
   (sb-sys:int-sap (+ (static-vector-address vector)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
191
                    +array-header-size+
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
192
                    offset)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
193
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
194
 (declaim (inline free-static-vector))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
195
 (defun free-static-vector (vector)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
196
   "Free VECTOR, which must be a vector created by MAKE-STATIC-VECTOR."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
197
   (declare (sb-ext:muffle-conditions sb-ext:compiler-note))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
198
   (let* ((extra-header-pointer
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
199
            (sb-sys:int-sap (- (static-vector-address vector) +array-header-size+)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
200
          (start-offset
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
201
            (sb-sys:sap-ref-word extra-header-pointer 0)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
202
     (free-alien (sap-alien (sb-sys:sap+ extra-header-pointer (- start-offset)) (* (unsigned 8)))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
203
   (values))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
204
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
205
 (defmacro with-static-vector ((var length &rest args
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
206
                                &key (element-type ''(unsigned-byte 8))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
207
                                  initial-contents initial-element)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
208
                               &body body &environment env)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
209
   "Bind PTR-VAR to a static vector of length LENGTH and execute BODY
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
210
 within its dynamic extent. The vector is freed upon exit."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
211
   (declare (ignorable element-type initial-contents initial-element))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
212
   (multiple-value-bind (real-element-type length type-spec)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
213
       (canonicalize-args env element-type length)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
214
     (let ((args (copy-list args)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
215
       (remf args :element-type)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
216
       `(sb-sys:without-interrupts
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
217
          (let ((,var (make-static-vector ,length ,@args
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
218
                                          :element-type ,real-element-type)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
219
            (declare (type ,type-spec ,var))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
220
            (unwind-protect
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
221
                 (sb-sys:with-local-interrupts ,@body)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
222
              (when ,var (free-static-vector ,var))))))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
223
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
224
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
225
 ;;; --- MAKE-STATIC-VECTOR
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
226
 (declaim (inline check-initial-element))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
227
 (defun check-initial-element (element-type initial-element)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
228
   (when (not (typep initial-element element-type))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
229
     ;; FIXME: signal SUBTYPE-ERROR
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
230
     (error "MAKE-STATIC-VECTOR: The type of :INITIAL-ELEMENT ~S is not a subtype ~
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
231
 of the array's :ELEMENT-TYPE ~S"
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
232
            initial-element element-type)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
233
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
234
 (declaim (inline check-initial-contents))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
235
 (defun check-initial-contents (length initial-contents)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
236
   (let ((initial-contents-length (length initial-contents)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
237
     (when (/= length initial-contents-length)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
238
       ;; FIXME: signal TYPE-ERROR
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
239
       (error "MAKE-STATIC-VECTOR: There are ~A elements in the :INITIAL-CONTENTS, ~
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
240
 but requested vector length is ~A."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
241
              initial-contents-length length))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
242
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
243
 (declaim (inline check-initialization-arguments))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
244
 (defun check-initialization-arguments (initial-element-p initial-contents-p)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
245
   (when (and initial-element-p initial-contents-p)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
246
     ;; FIXME: signal ARGUMENT-LIST-ERROR
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
247
     (error "MAKE-STATIC-VECTOR: You must not specify both ~
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
248
 :INITIAL-ELEMENT and :INITIAL-CONTENTS")))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
249
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
250
 (defun check-arguments (length element-type
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
251
                         initial-element initial-element-p
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
252
                         initial-contents initial-contents-p)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
253
   (check-initialization-arguments initial-element-p initial-contents-p)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
254
   (check-type length non-negative-fixnum)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
255
   (when initial-element-p
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
256
     (check-initial-element element-type initial-element))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
257
   (when initial-contents-p
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
258
     (check-initial-contents length initial-contents)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
259
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
260
 (defconstant +default-alignment+ 16)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
261
 (defconstant +max-alignment+ 4096)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
262
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
263
 (declaim (inline make-static-vector))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
264
 (defun make-static-vector (length &key (element-type '(unsigned-byte 8))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
265
                            (initial-element nil initial-element-p)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
266
                            (initial-contents nil initial-contents-p)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
267
                            (alignment nil alignp))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
268
   "Create a simple vector of length LENGTH and type ELEMENT-TYPE which will
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
269
 not be moved by the garbage collector. The vector might be allocated in
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
270
 foreign memory so you must always call FREE-STATIC-VECTOR to free it."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
271
   (declare #+sbcl (sb-ext:muffle-conditions sb-ext:compiler-note)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
272
            (optimize speed))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
273
   (check-arguments length element-type initial-element initial-element-p
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
274
                    initial-contents initial-contents-p)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
275
   (when alignp
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
276
     ;; Check that the alignment is a power of 2 beteeen 16 and 4096.
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
277
     #+(and sbcl unix)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
278
     (assert (and (<= +default-alignment+ alignment +max-alignment+)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
279
                  (= 1 (logcount alignment))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
280
     #-(and sbcl unix)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
281
     (error "Allocation alignment not supported on this implementation."))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
282
   ;; TODO: fix %allocate-static-vector for all implementations
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
283
   (let ((vector
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
284
           (%allocate-static-vector length element-type
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
285
                                    #+sbcl
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
286
                                    (or alignment +default-alignment+))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
287
     (if initial-element-p
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
288
         (fill vector initial-element)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
289
         (replace vector initial-contents))))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
290
 
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
291
 (defmacro with-static-vectors (((var length &rest args) &rest more-clauses)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
292
                                &body body)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
293
   "Allocate multiple static vectors at once."
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
294
   `(with-static-vector (,var ,length ,@args)
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
295
      ,@(if more-clauses
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
296
            `((with-static-vectors ,more-clauses
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
297
                ,@body))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
298
            body)))
2bad47888dbf add static-vector
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
299