Fix make-array transforms.
[sbcl.git] / src / compiler / generic / objdef.lisp
index b3839eb..ad0b2c9 100644 (file)
@@ -14,9 +14,6 @@
 ;;;; KLUDGE: The primitive objects here may look like self-contained
 ;;;; definitions, but in general they're not. In particular, if you
 ;;;; try to add a slot to them, beware of the following:
-;;;;   * (mysterious crashes which occur after changing the length
-;;;;     of SIMPLE-FUN, just adding a new slot not even doing anything
-;;;;     with it, still dunno why)
 ;;;;   * The GC scavenging code (and for all I know other GC code too)
 ;;;;     is not automatically generated from these layouts, but instead
 ;;;;     was hand-written to correspond to them. The offsets are
 \f
 ;;;; the primitive objects themselves
 
-(define-primitive-object (cons :lowtag list-pointer-lowtag
+(define-primitive-object (cons :type cons
+                               :lowtag list-pointer-lowtag
                                :alloc-trans cons)
-  (car :ref-trans car :set-trans sb!c::%rplaca :init :arg)
-  (cdr :ref-trans cdr :set-trans sb!c::%rplacd :init :arg))
+  (car :ref-trans car :set-trans sb!c::%rplaca :init :arg
+       :cas-trans %compare-and-swap-car)
+  (cdr :ref-trans cdr :set-trans sb!c::%rplacd :init :arg
+       :cas-trans %compare-and-swap-cdr))
 
 (define-primitive-object (instance :lowtag instance-pointer-lowtag
                                    :widetag instance-header-widetag
@@ -51,7 +51,7 @@
 (define-primitive-object (bignum :lowtag other-pointer-lowtag
                                  :widetag bignum-widetag
                                  :alloc-trans sb!bignum::%allocate-bignum)
-  (digits :rest-p t :c-type #!-alpha "long" #!+alpha "u32"))
+  (digits :rest-p t :c-type #!-alpha "sword_t" #!+alpha "u32"))
 
 (define-primitive-object (ratio :type ratio
                                 :lowtag other-pointer-lowtag
                 :ref-trans %array-fill-pointer
                 :ref-known (flushable foldable)
                 :set-trans (setf %array-fill-pointer)
-                :set-known (unsafe))
+                :set-known ())
   (fill-pointer-p :type (member t nil)
                   :ref-trans %array-fill-pointer-p
                   :ref-known (flushable foldable)
                   :set-trans (setf %array-fill-pointer-p)
-                  :set-known (unsafe))
+                  :set-known ())
   (elements :type index
             :ref-trans %array-available-elements
             :ref-known (flushable foldable)
             :set-trans (setf %array-available-elements)
-            :set-known (unsafe))
+            :set-known ())
   (data :type array
         :ref-trans %array-data-vector
         :ref-known (flushable foldable)
         :set-trans (setf %array-data-vector)
-        :set-known (unsafe))
+        :set-known ())
   (displacement :type (or index null)
                 :ref-trans %array-displacement
                 :ref-known (flushable foldable)
                 :set-trans (setf %array-displacement)
-                :set-known (unsafe))
-  (displaced-p :type (member t nil)
+                :set-known ())
+  (displaced-p :type t
                :ref-trans %array-displaced-p
                :ref-known (flushable foldable)
                :set-trans (setf %array-displaced-p)
-               :set-known (unsafe))
+               :set-known ())
+  (displaced-from :type list
+                  :ref-trans %array-displaced-from
+                  :ref-known (flushable)
+                  :set-trans (setf %array-displaced-from)
+                  :set-known ())
   (dimensions :rest-p t))
 
 (define-primitive-object (vector :type vector
   ;; VECTOR -- see SHRINK-VECTOR.
   (length :ref-trans sb!c::vector-length
           :type index)
-  (data :rest-p t :c-type #!-alpha "unsigned long" #!+alpha "u32"))
+  (data :rest-p t :c-type #!-alpha "uword_t" #!+alpha "u32"))
 
 (define-primitive-object (code :type code-component
                                :lowtag other-pointer-lowtag
   (entry-points :type (or function null)
                 :ref-known (flushable)
                 :ref-trans %code-entry-points
-                :set-known (unsafe)
+                :set-known ()
                 :set-trans (setf %code-entry-points))
   (debug-info :type t
               :ref-known (flushable)
               :ref-trans %code-debug-info
-              :set-known (unsafe)
+              :set-known ()
               :set-trans (setf %code-debug-info))
   (trace-table-offset)
   (constants :rest-p t))
   (next :type (or function null)
         :ref-known (flushable)
         :ref-trans %simple-fun-next
-        :set-known (unsafe)
+        :set-known ()
         :set-trans (setf %simple-fun-next))
   (name :ref-known (flushable)
         :ref-trans %simple-fun-name
-        :set-known (unsafe)
+        :set-known ()
         :set-trans (setf %simple-fun-name))
   (arglist :type list
            :ref-known (flushable)
            :ref-trans %simple-fun-arglist
-           :set-known (unsafe)
+           :set-known ()
            :set-trans (setf %simple-fun-arglist))
   (type :ref-known (flushable)
         :ref-trans %simple-fun-type
-        :set-known (unsafe)
+        :set-known ()
         :set-trans (setf %simple-fun-type))
+  ;; NIL for empty, STRING for a docstring, SIMPLE-VECTOR for XREFS, and (CONS
+  ;; STRING SIMPLE-VECTOR) for both.
+  (info :init :null
+        :ref-trans %simple-fun-info
+        :ref-known (flushable)
+        :set-trans (setf %simple-fun-info)
+        :set-known ())
   ;; the SB!C::DEBUG-FUN object corresponding to this object, or NIL for none
   #+nil ; FIXME: doesn't work (gotcha, lowly maintenoid!) See notes on bug 137.
   (debug-fun :ref-known (flushable)
              :ref-trans %simple-fun-debug-fun
-             :set-known (unsafe)
+             :set-known ()
              :set-trans (setf %simple-fun-debug-fun))
   (code :rest-p t :c-type "unsigned char"))
 
 (define-primitive-object (closure :lowtag fun-pointer-lowtag
                                   :widetag closure-header-widetag)
   (fun :init :arg :ref-trans %closure-fun)
-  ;; This SELF slot needs explanation.
-  ;;
-  ;; Ordinary closures did not need this slot before version 0.9.3.xx,
-  ;; as the closure object was already in some dedicated register --
-  ;; EAX/RAX on x86(-64), reg_LEXENV on register-rich platforms -- and
-  ;; consequently setting up the environment (from the INFO slot,
-  ;; below) was easy.
-  ;;
-  ;; However, it is not easy to support calling FUNCALLABLE-INSTANCEs
-  ;; in the same way; in a FUNCALLABLE-INSTANCE, there are
-  ;; conceptually two variable-length data areas: the closure
-  ;; environment, if any, and the slots of the instance.
-  ;;
-  ;; Until sbcl-0.9.3.xx, it was required that closures to be set as a
-  ;; FUNCALLABLE-INSTANCE-FUNCTION be defined using the magical
-  ;; keyword SB-KERNEL:INSTANCE-LAMBDA, rather than ordinary LAMBDA;
-  ;; this caused an extra indirection to be compiled into the closure
-  ;; code to load the closure from the FUNCALLABLE-INSTANCE-LEXENV
-  ;; slot before setting up the environment for the function body.
-  ;; Failure to obey this protocol yielded confusing error messages as
-  ;; either INSTANCE-LAMBDAs tried to dereference environments that
-  ;; weren't there, or ordinary LAMBDAs got hold of the LAYOUT and
-  ;; LEXENV slots of a FUNCALLABLE-INSTANCE.
-  ;;
-  ;; By adding this SELF slot, which is at the same offset in a
-  ;; regular CLOSURE as the LEXENV slot is in a FUNCALLABLE-INSTANCE,
-  ;; we enable the extra indirection (VOP FUNCALLABLE-INSTANCE-LEXENV,
-  ;; in src/compiler/ir2tran.lisp) to be compiled unconditionally
-  ;; (provided that we set this slot to the closure object itself).
-  ;; Relative to the code before, this adds a word to the space
-  ;; requirements of a closure, and one instruction (a memory fetch)
-  ;; to the body of a closure function.
-  ;;
-  ;; There are potentially other implementation strategies which would
-  ;; remove the need for this extra indirection in regular closures,
-  ;; such as setting up a trampoline for funcallable instances (though
-  ;; it was not clear to me that there are enough registers free in
-  ;; the x86 backend to permit this).  This indirection should not be
-  ;; too disastrous, given that for regular closures the fetch is from
-  ;; memory which is known to be active.
-  ;;
-  ;; CSR, 2005-08-05
-  (self) ; KLUDGE (see above comment)
   (info :rest-p t))
 
 (define-primitive-object (funcallable-instance
                           :lowtag fun-pointer-lowtag
                           :widetag funcallable-instance-header-widetag
                           :alloc-trans %make-funcallable-instance)
-  #!-(or x86 x86-64)
-  (fun
-   :ref-known (flushable) :ref-trans %funcallable-instance-fun
-   :set-known (unsafe) :set-trans (setf %funcallable-instance-fun))
-  #!+(or x86 x86-64)
-  (fun
-   :ref-known (flushable) :ref-trans %funcallable-instance-fun
-   ;; KLUDGE: There's no :SET-KNOWN or :SET-TRANS in this case.
-   ;; Instead, later in compiler/x86/system.lisp there's a separate
-   ;; DEFKNOWN for (SETF %FUNCALLABLE-INSTANCE-FUN), and a weird
-   ;; unexplained DEFTRANSFORM from (SETF %SIMPLE-FUN-INSTANCE-FUN)
-   ;; into (SETF %SIMPLE-FUN-SELF). The #!+X86 wrapped around this case
-   ;; is a literal translation of the old CMU CL implementation into
-   ;; the new world of sbcl-0.6.12.63, where multiple DEFKNOWNs for
-   ;; the same operator cause an error (instead of silently deleting
-   ;; all information associated with the old DEFKNOWN, as before).
-   ;; It's definitely not very clean, with too many #!+ conditionals and
-   ;; too little documentation, but I have more urgent things to
-   ;; clean up right now, so I've just left it as a literal
-   ;; translation without trying to fix it. -- WHN 2001-08-02
-   )
-  (lexenv :ref-known (flushable) :ref-trans %funcallable-instance-lexenv
-          :set-known (unsafe) :set-trans (setf %funcallable-instance-lexenv))
+  (trampoline :init :funcallable-instance-tramp)
+  (function :ref-known (flushable) :ref-trans %funcallable-instance-function
+            :set-known () :set-trans (setf %funcallable-instance-function))
   (info :rest-p t))
 
 (define-primitive-object (value-cell :lowtag other-pointer-lowtag
                                      :widetag value-cell-header-widetag
+                                     ;; FIXME: We also have an explicit VOP
+                                     ;; for this. Is this needed as well?
                                      :alloc-trans make-value-cell)
   (value :set-trans value-cell-set
-         :set-known (unsafe)
+         :set-known ()
          :ref-trans value-cell-ref
          :ref-known (flushable)
          :init :arg))
 
 (define-primitive-object (binding)
   value
-  symbol)
+  symbol) ;; on sb-thread, this is actually a tls-index
 
 (define-primitive-object (unwind-block)
   (current-uwp :c-type #!-alpha "struct unwind_block *" #!+alpha "u32")
   (current-cont :c-type #!-alpha "lispobj *" #!+alpha "u32")
   #!-(or x86 x86-64) current-code
-  entry-pc)
+  entry-pc
+  #!+win32 next-seh-frame
+  #!+win32 seh-frame-handler)
 
 (define-primitive-object (catch-block)
   (current-uwp :c-type #!-alpha "struct unwind_block *" #!+alpha "u32")
   (current-cont :c-type #!-alpha "lispobj *" #!+alpha "u32")
   #!-(or x86 x86-64) current-code
   entry-pc
+  #!+(and win32 x86) next-seh-frame
+  #!+(and win32 x86) seh-frame-handler
   tag
-  (previous-catch :c-type #!-alpha "struct catch_block *" #!+alpha "u32")
-  size)
+  (previous-catch :c-type #!-alpha "struct catch_block *" #!+alpha "u32"))
 
 ;;; (For an explanation of this, see the comments at the definition of
 ;;; KLUDGE-NONDETERMINISTIC-CATCH-BLOCK-SIZE.)
 
 (define-primitive-object (symbol :lowtag other-pointer-lowtag
                                  :widetag symbol-header-widetag
-                                 :alloc-trans %make-symbol)
+                                 :alloc-trans %make-symbol
+                                 :type symbol)
 
   ;; Beware when changing this definition.  NIL-the-symbol is defined
   ;; using this layout, and NIL-the-end-of-list-marker is the cons
   ;; first data slot, and if you subtract 7 you get a symbol header.
 
   ;; also the CAR of NIL-as-end-of-list
-  (value :init :unbound :ref-known (flushable) :ref-trans symbol-global-value)
+  (value :init :unbound
+         :set-trans %set-symbol-global-value
+         :set-known ())
   ;; also the CDR of NIL-as-end-of-list.  Its reffer needs special
   ;; care for this reason, as hash values must be fixnums.
   (hash :set-trans %set-symbol-hash)
 
   (plist :ref-trans symbol-plist
          :set-trans %set-symbol-plist
+         :cas-trans %compare-and-swap-symbol-plist
+         :type list
          :init :null)
   (name :ref-trans symbol-name :init :arg)
   (package :ref-trans symbol-package
            :set-trans %set-symbol-package
            :init :null)
-  #!+sb-thread (tls-index :ref-known (flushable) :ref-trans symbol-tls-index))
+  ;; 0 tls-index means no tls-index is allocated
+  #!+sb-thread
+  (tls-index :ref-known (flushable) :ref-trans symbol-tls-index))
 
 (define-primitive-object (complex-single-float
                           :lowtag other-pointer-lowtag
                           :widetag complex-single-float-widetag)
+  #!+x86-64
+  (data :c-type "struct { float data[2]; } ")
+  #!-x86-64
   (real :c-type "float")
+  #!-x86-64
   (imag :c-type "float"))
 
 (define-primitive-object (complex-double-float
                           :lowtag other-pointer-lowtag
                           :widetag complex-double-float-widetag)
-  #!-x86-64 (filler)
+  (filler)
   (real :c-type "double" :length #!-x86-64 2 #!+x86-64 1)
   (imag :c-type "double" :length #!-x86-64 2 #!+x86-64 1))
 
-#!+sb-lutex
-(define-primitive-object (lutex
+#!+sb-simd-pack
+(define-primitive-object (simd-pack
                           :lowtag other-pointer-lowtag
-                          :widetag lutex-widetag
-                          :alloc-trans %make-lutex)
-  (gen :c-type "long" :length 1)
-  (live :c-type "long" :length 1)
-  (next :c-type "struct lutex *" :length 1)
-  (prev :c-type "struct lutex *" :length 1)
-  (mutex :c-type "pthread_mutex_t *"
-         :length 1)
-  (condition-variable :c-type "pthread_cond_t *"
-                      :length 1))
+                          :widetag simd-pack-widetag)
+  (tag :ref-trans %simd-pack-tag
+       :attributes (movable flushable)
+       :type fixnum)
+  (lo-value :c-type "long" :type (unsigned-byte 64))
+  (hi-value :c-type "long" :type (unsigned-byte 64)))
 
 ;;; this isn't actually a lisp object at all, it's a c structure that lives
 ;;; in c-land.  However, we need sight of so many parts of it from Lisp that
 ;;; it makes sense to define it here anyway, so that the GENESIS machinery
 ;;; can take care of maintaining Lisp and C versions.
-;;; Hence the even-fixnum lowtag just so we don't get odd(sic) numbers
-;;; added to the slot offsets
-(define-primitive-object (thread :lowtag even-fixnum-lowtag)
+(define-primitive-object (thread)
   ;; no_tls_value_marker is borrowed very briefly at thread startup to
   ;; pass the address of initial-function into new_thread_trampoline.
   ;; tls[0] = NO_TLS_VALUE_MARKER_WIDETAG because a the tls index slot
   ;; of a symbol is initialized to zero
   (no-tls-value-marker)
-  (os-thread :c-type "volatile os_thread_t")
+  (os-thread :c-type "os_thread_t")
+  ;; This is the original address at which the memory was allocated,
+  ;; which may have different alignment then what we prefer to use.
+  ;; Kept here so that when the thread dies we can release the whole
+  ;; memory we reserved.
+  (os-address :c-type "void *" :length #!+alpha 2 #!-alpha 1)
+  ;; Keep these next four slots close to the beginning of the structure.
+  ;; Doing so reduces code size for x86-64 allocation sequences and
+  ;; special variable manipulations.
+  #!+gencgc (alloc-region :c-type "struct alloc_region" :length 5)
+  #!+(or x86 x86-64 sb-thread) (pseudo-atomic-bits)
   (binding-stack-start :c-type "lispobj *" :length #!+alpha 2 #!-alpha 1)
   (binding-stack-pointer :c-type "lispobj *" :length #!+alpha 2 #!-alpha 1)
+  #!+sb-thread
+  (os-attr :c-type "pthread_attr_t *" :length #!+alpha 2 #!-alpha 1)
+  #!+sb-thread
+  (state-sem :c-type "os_sem_t *" :length #!+alpha 2 #!-alpha 1)
+  #!+sb-thread
+  (state-not-running-sem :c-type "os_sem_t *" :length #!+alpha 2 #!-alpha 1)
+  #!+sb-thread
+  (state-not-running-waitcount :c-type "int" :length 1)
+  #!+sb-thread
+  (state-not-stopped-sem :c-type "os_sem_t *" :length #!+alpha 2 #!-alpha 1)
+  #!+sb-thread
+  (state-not-stopped-waitcount :c-type "int" :length 1)
   (control-stack-start :c-type "lispobj *" :length #!+alpha 2 #!-alpha 1)
   (control-stack-end :c-type "lispobj *" :length #!+alpha 2 #!-alpha 1)
+  (control-stack-guard-page-protected)
   (alien-stack-start :c-type "lispobj *" :length #!+alpha 2 #!-alpha 1)
   (alien-stack-pointer :c-type "lispobj *" :length #!+alpha 2 #!-alpha 1)
-  #!+gencgc (alloc-region :c-type "struct alloc_region" :length 5)
+  #!+win32 (private-events :c-type "struct private_events" :length 2)
   (this :c-type "struct thread *" :length #!+alpha 2 #!-alpha 1)
   (prev :c-type "struct thread *" :length #!+alpha 2 #!-alpha 1)
   (next :c-type "struct thread *" :length #!+alpha 2 #!-alpha 1)
   ;; starting, running, suspended, dead
-  (state :c-type "volatile lispobj")
+  (state :c-type "lispobj")
   (tls-cookie)                          ;  on x86, the LDT index
-  #!+(or x86 x86-64) (pseudo-atomic-atomic)
-  #!+(or x86 x86-64) (pseudo-atomic-interrupted)
   (interrupt-data :c-type "struct interrupt_data *"
                   :length #!+alpha 2 #!-alpha 1)
+  (stepping)
+  ;; For various reasons related to pseudo-atomic and interrupt
+  ;; handling, we need to know if the machine context is in Lisp code
+  ;; or not.  On non-threaded targets, this is a global variable in
+  ;; the runtime, but it's clearly a per-thread value.
+  #!+sb-thread
+  (foreign-function-call-active :c-type "boolean")
+  ;; Same as above for the location of the current control stack frame.
+  #!+(and sb-thread (not (or x86 x86-64)))
+  (control-frame-pointer :c-type "lispobj *")
+  ;; Same as above for the location of the current control stack
+  ;; pointer.  This is also used on threaded x86oids to allow LDB to
+  ;; print an approximation of the CSP as needed.
+  #!+sb-thread
+  (control-stack-pointer :c-type "lispobj *")
+  #!+mach-exception-handler
+  (mach-port-name :c-type "mach_port_name_t")
+  (nonpointer-data :c-type "struct nonpointer_thread_data *" :length #!+alpha 2 #!-alpha 1)
+  #!+(and sb-safepoint x86) (selfptr :c-type "struct thread *")
+  ;; Context base pointer for running on top of system libraries built using
+  ;; -fomit-frame-pointer.  Currently truly required and implemented only
+  ;; for (and win32 x86-64), but could be generalized to other platforms if
+  ;; needed:
+  #!+win32 (carried-base-pointer :c-type "os_context_register_t")
+  #!+sb-safepoint (csp-around-foreign-call :c-type "lispobj *")
+  #!+sb-safepoint (pc-around-foreign-call :c-type "lispobj *")
+  #!+win32 (synchronous-io-handle-and-flag :c-type "HANDLE" :length 1)
+  #!+(and sb-safepoint-strictly (not win32))
+  (sprof-alloc-region :c-type "struct alloc_region" :length 5)
+  ;; KLUDGE: On alpha, until STEPPING we have been lucky and the 32
+  ;; bit slots came in pairs. However the C compiler will align
+  ;; interrupt_contexts on a double word boundary. This logic should
+  ;; be handled by DEFINE-PRIMITIVE-OBJECT.
+  #!+alpha
+  (padding)
   (interrupt-contexts :c-type "os_context_t *" :rest-p t))