|
1 | 1 | (in-package :cl-binary-store) |
2 | 2 |
|
3 | 3 | (defun restore-array (storage restore-object) |
4 | | - ;; This is somewhat complex because we cannot build the array |
5 | | - ;; if it is displaced to another array until we restore what the array |
6 | | - ;; is displaced to. So we need to use a fix-up scenario. |
7 | | - (declare (type function restore-object)) |
| 4 | + (declare (type function restore-object) (optimize (speed 3) (safety 1))) |
8 | 5 | (let* ((has-fill-pointer (funcall restore-object)) |
9 | | - (fill-pointer (when has-fill-pointer (funcall restore-object))) |
| 6 | + (fill-pointer (when has-fill-pointer (restore-tagged-unsigned-fixnum storage))) |
10 | 7 | (adjustable (funcall restore-object)) |
11 | 8 | (array-rank (the (unsigned-byte 8) (restore-ub8 storage))) |
12 | | - ;; restore tagged integers |
13 | | - (dimensions (loop repeat array-rank collect (funcall restore-object))) |
14 | | - (displaced (funcall restore-object))) |
15 | | - (if displaced |
16 | | - (let ((element-type (funcall restore-object)) |
17 | | - (offset (funcall restore-object)) |
18 | | - (displaced-to (funcall restore-object))) |
19 | | - (make-array dimensions :element-type element-type :adjustable adjustable |
20 | | - :fill-pointer fill-pointer :displaced-to displaced-to |
21 | | - :displaced-index-offset offset)) |
22 | | - (let ((array |
23 | | - (let* ((element-type (funcall restore-object))) |
24 | | - (make-array dimensions :element-type element-type :adjustable adjustable |
25 | | - :fill-pointer fill-pointer)))) |
26 | | - (loop for idx fixnum from 0 below (array-total-size array) |
27 | | - do (restore-object-to (row-major-aref array idx) restore-object)) |
28 | | - array)))) |
| 9 | + (dimensions (loop repeat array-rank |
| 10 | + collect (restore-tagged-unsigned-fixnum storage))) |
| 11 | + (displaced (funcall restore-object)) |
| 12 | + (array-total-size (if dimensions (reduce #'* dimensions) 0))) |
| 13 | + (unless (and (typep array-total-size 'fixnum) (>= array-total-size 0)) |
| 14 | + (unexpected-data "Array total size is too large")) |
| 15 | + (check-if-too-much-data (read-storage-max-to-read storage) array-total-size) |
| 16 | + (labels ((check-fill-pointer (dimensions) |
| 17 | + (when has-fill-pointer |
| 18 | + (unless (= array-rank 1) |
| 19 | + (unexpected-data "found fill-pointer for a non-vector")) |
| 20 | + (unless (<= fill-pointer (first dimensions)) |
| 21 | + (unexpected-data "fill-pointer > vector length"))) |
| 22 | + (values))) |
| 23 | + (if displaced |
| 24 | + (let ((element-type (funcall restore-object)) |
| 25 | + (offset (restore-tagged-unsigned-fixnum storage)) |
| 26 | + (displaced-to (funcall restore-object))) |
| 27 | + (unless (typep displaced-to 'array) |
| 28 | + (unexpected-data "displaced to a non array?!")) |
| 29 | + (unless (typep (array-element-type displaced-to) element-type) |
| 30 | + (unexpected-data "array displaced to array of different element-type")) |
| 31 | + (unless (< offset (array-total-size displaced-to)) |
| 32 | + (unexpected-data "array displaced to too small array")) |
| 33 | + (when has-fill-pointer (check-fill-pointer dimensions)) |
| 34 | + (make-array dimensions :element-type element-type :adjustable adjustable |
| 35 | + :fill-pointer fill-pointer :displaced-to displaced-to |
| 36 | + :displaced-index-offset offset)) |
| 37 | + (progn |
| 38 | + (when has-fill-pointer (check-fill-pointer dimensions)) |
| 39 | + (let ((array |
| 40 | + (let* ((element-type (funcall restore-object))) |
| 41 | + (make-array dimensions :element-type element-type :adjustable adjustable |
| 42 | + :fill-pointer fill-pointer)))) |
| 43 | + ;; We need to make our array first in case any of the array elements refer to it! |
| 44 | + ;; If we are ever referred to, then there will already be a fixup in place for |
| 45 | + ;; our array handled by `restore-new-reference-indicator'. |
| 46 | + (loop for idx fixnum from 0 below array-total-size |
| 47 | + do (restore-object-to (row-major-aref array idx) restore-object)) |
| 48 | + array)))))) |
29 | 49 |
|
30 | 50 | (defun store-array (array storage eq-refs store-object assign-new-reference-id) |
31 | 51 | (declare (optimize speed safety) (type array array) (type function store-object)) |
|
0 commit comments