0.8.3.11
authorDaniel Barlow <dan@telent.net>
Thu, 29 Jul 2004 22:41:26 +0000 (22:41 +0000)
committerDaniel Barlow <dan@telent.net>
Thu, 29 Jul 2004 22:41:26 +0000 (22:41 +0000)
 Inline allocation for GENCGC ...

 ... add allocation-inline, which does direct access to
 allocation region fields based on %fs (for threads)
 or &boxed_region (unithread), falling through to
 assembler routines and eventual call to alloc()
 if we've run out of space in the region

 ... relevant assembler glue, partly borrowed from CMUCL
 but with changes to do thread-local access when appropriate

 ... patch alloc() to use boxed_region instead of
 all_threads->region on unithread builds

 ... clean up cut/pasted code in allocation-notinline

doc/internals-notes/threading-specials
src/compiler/x86/macros.lisp
src/runtime/gencgc.c
src/runtime/x86-arch.h
src/runtime/x86-assem.S
src/runtime/x86-linux-os.c
version.lisp-expr

index adfe42c..4f346d9 100644 (file)
@@ -27,7 +27,7 @@ The goals are
         spots.  Global state in closures, etc etc
            
        (4) suggest strategies (e.g. rewrites of affected code, suitable
-       locks and lock acquitision/release places) to fix the issues
+       locks and lock acquisition/release places) to fix the issues
        revealed in (2) and (3)
        
        (5) implement same
@@ -599,6 +599,10 @@ Note that the compiler and fasloader are strongly believed not to be
 thread-safe, so there is currently a big lock (*big-compiler-lock*)
 around all calls to the compiler or fasloader
 
+Note that INFO functions use a shared cache for the globaldb, and
+don't lock for cache invalidation. This will need fixing when BCL is
+removed.
+
 *COMPILE-FILE-PATHNAME*  
 *COMPILE-FILE-TRUENAME* 
 *COMPILE-PRINT* 
index 28a35ea..137a0e8 100644 (file)
 ;;; eventually invoke the C alloc() function.  Once upon a time
 ;;; (before threads) allocation within an alloc_region could also be
 ;;; done inline, with the aid of two C symbols storing the current
-;;; allocation region boundaries; however, C cymbols are global.
+;;; allocation region boundaries; however, C symbols are global.
 
 ;;; C calls for allocation don't /seem/ to make an awful lot of
 ;;; difference to speed.  Guessing from historical context, it looks
 ;;; no need for that overhead.  Still, inline alloc would be a neat
 ;;; addition someday
 
-(defvar *maybe-use-inline-allocation* t) ; FIXME unused
-
-;;; Emit code to allocate an object with a size in bytes given by
-;;; SIZE. The size may be an integer of a TN. If Inline is a VOP
-;;; node-var then it is used to make an appropriate speed vs size
-;;; decision.
-
 (defun allocation-dynamic-extent (alloc-tn size)
   (inst sub esp-tn size)
   ;; FIXME: SIZE _should_ be double-word aligned (suggested but
   (values))
 
 (defun allocation-notinline (alloc-tn size)
-  (flet ((load-size (dst-tn size)
-          (unless (and (tn-p size) (location= alloc-tn size))
-            (inst mov dst-tn size))))
-    (let ((alloc-tn-offset (tn-offset alloc-tn)))
-         ;; C call to allocate via dispatch routines. Each
-         ;; destination has a special entry point. The size may be a
-         ;; register or a constant.
-         (ecase alloc-tn-offset
-           (#.eax-offset
-            (case size
-              (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_eax")
-                                        :foreign)))
-              (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_eax")
-                                         :foreign)))
-              (t
-               (load-size eax-tn size)
-               (inst call (make-fixup (extern-alien-name "alloc_to_eax")
-                                      :foreign)))))
-           (#.ecx-offset
-            (case size
-              (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_ecx")
-                                        :foreign)))
-              (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_ecx")
-                                         :foreign)))
-              (t
-               (load-size ecx-tn size)
-               (inst call (make-fixup (extern-alien-name "alloc_to_ecx")
-                                      :foreign)))))
-           (#.edx-offset
-            (case size
-              (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_edx")
-                                        :foreign)))
-              (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_edx")
-                                         :foreign)))
-              (t
-               (load-size edx-tn size)
-               (inst call (make-fixup (extern-alien-name "alloc_to_edx")
-                                      :foreign)))))
-           (#.ebx-offset
-            (case size
-              (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_ebx")
-                                        :foreign)))
-              (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_ebx")
-                                         :foreign)))
-              (t
-               (load-size ebx-tn size)
-               (inst call (make-fixup (extern-alien-name "alloc_to_ebx")
-                                      :foreign)))))
-           (#.esi-offset
-            (case size
-              (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_esi")
-                                        :foreign)))
-              (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_esi")
-                                         :foreign)))
-              (t
-               (load-size esi-tn size)
-               (inst call (make-fixup (extern-alien-name "alloc_to_esi")
-                                      :foreign)))))
-           (#.edi-offset
-            (case size
-              (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_edi")
-                                        :foreign)))
-              (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_edi")
-                                         :foreign)))
-              (t
-               (load-size edi-tn size)
-               (inst call (make-fixup (extern-alien-name "alloc_to_edi")
-                                  :foreign)))))))))
-  
-;;; This macro should only be used inside a pseudo-atomic section,
-;;; which should also cover subsequent initialization of the object.
+  (let* ((alloc-tn-offset (tn-offset alloc-tn))
+        ;; C call to allocate via dispatch routines. Each
+        ;; destination has a special entry point. The size may be a
+        ;; register or a constant.
+        (tn-text (ecase alloc-tn-offset
+                   (#.eax-offset "eax")
+                   (#.ecx-offset "ecx")
+                   (#.edx-offset "edx")
+                   (#.ebx-offset "ebx")
+                   (#.esi-offset "esi")
+                   (#.edi-offset "edi")))
+        (size-text (case size (8 "8_") (16 "16_") (t ""))))
+    (unless (or (eql size 8) (eql size 16))
+      (unless (and (tn-p size) (location= alloc-tn size))
+       (inst mov alloc-tn size)))
+    (inst call (make-fixup (extern-alien-name 
+                           (concatenate 'string
+                                        "alloc_" size-text
+                                        "to_" tn-text))
+                          :foreign))))
+
+(defun allocation-inline (alloc-tn size)
+  (let ((ok (gen-label))
+       (free-pointer
+        (make-ea :dword :disp 
+                 #!+sb-thread (* n-word-bytes thread-alloc-region-slot)
+                 #!-sb-thread (make-fixup (extern-alien-name "boxed_region")
+                                           :foreign)
+                 :scale 1)) ; thread->alloc_region.free_pointer
+       (end-addr 
+        (make-ea :dword :disp
+                 #!+sb-thread (* n-word-bytes (1+ thread-alloc-region-slot))
+                 #!-sb-thread (make-fixup (extern-alien-name "boxed_region")
+                                          :foreign 4)
+                 :scale 1)))   ; thread->alloc_region.end_addr
+    (unless (and (tn-p size) (location= alloc-tn size))
+      (inst mov alloc-tn size))
+    #!+sb-thread (inst fs-segment-prefix)
+    (inst add alloc-tn free-pointer)
+    #!+sb-thread (inst fs-segment-prefix)
+    (inst cmp alloc-tn end-addr)
+    (inst jmp :be OK)
+    (let ((dst (ecase (tn-offset alloc-tn)
+                (#.eax-offset "alloc_overflow_eax")
+                (#.ecx-offset "alloc_overflow_ecx")
+                (#.edx-offset "alloc_overflow_edx")
+                (#.ebx-offset "alloc_overflow_ebx")
+                (#.esi-offset "alloc_overflow_esi")
+                (#.edi-offset "alloc_overflow_edi"))))
+      (inst call (make-fixup (extern-alien-name dst) :foreign)))
+    (emit-label ok)
+    #!+sb-thread (inst fs-segment-prefix)
+    (inst xchg free-pointer alloc-tn))
+  (values))
+
+
+;;; Emit code to allocate an object with a size in bytes given by
+;;; SIZE.  The size may be an integer or a TN. If Inline is a VOP
+;;; node-var then it is used to make an appropriate speed vs size
+;;; decision.
+
+;;; Allocation should only be used inside a pseudo-atomic section, which
+;;; should also cover subsequent initialization of the object.
+
 ;;; (FIXME: so why aren't we asserting this?)
+
 (defun allocation (alloc-tn size &optional inline dynamic-extent)
-  ;; FIXME: since it appears that inline allocation is gone, we should
-  ;; remove the INLINE parameter and *MAYBE-USE-INLINE-ALLOCATION*
-  (declare (ignore inline))  
   (cond
     (dynamic-extent (allocation-dynamic-extent alloc-tn size))
+    ((or (null inline) (policy inline (>= speed space)))
+     (allocation-inline alloc-tn size))
     (t (allocation-notinline alloc-tn size)))
   (values))
 
index ea90e34..bdf74f3 100644 (file)
@@ -4008,8 +4008,12 @@ char *
 alloc(int nbytes)
 {
     struct thread *th=arch_os_get_current_thread();
-    struct alloc_region *region= 
+    struct alloc_region *region=
+#ifdef LISP_FEATURE_SB_THREAD
        th ? &(th->alloc_region) : &boxed_region; 
+#else
+        &boxed_region; 
+#endif
     void *new_obj;
     void *new_free_pointer;
 
index eea03a4..3bd1e5c 100644 (file)
@@ -8,6 +8,10 @@
 #error genesis/config.h (or sbcl.h) must be incuded before this file
 #endif
 
+#ifndef SBCL_GENESIS_CONFIG
+#error genesis/config.h (or sbcl.h) must be incuded before this file
+#endif
+
 #define ARCH_HAS_STACK_POINTER
 
 /* FIXME: Do we also want
index 1170bba..c145d53 100644 (file)
@@ -658,7 +658,139 @@ GNAME(alloc_16_to_edi):
        popl    %eax
        ret
        .size   GNAME(alloc_16_to_edi),.-GNAME(alloc_16_to_edi)
+
+       
+/* Called from lisp when an inline allocation overflows.
+   Every register except the result needs to be preserved.
+   We depend on C to preserve ebx, esi, edi, and ebp.
+   But where necessary must save eax, ecx, edx. */
+
+#ifdef LISP_FEATURE_SB_THREAD
+#define START_REGION %fs:THREAD_ALLOC_REGION_OFFSET
+#define DISPLACEMENT $7
+#else
+#define START_REGION boxed_region
+#define DISPLACEMENT $6
+#endif
                
+/* This routine handles an overflow with eax=crfp+size. So the
+   size=eax-crfp. */
+        .align  align_4byte
+        .globl  GNAME(alloc_overflow_eax)
+        .type   GNAME(alloc_overflow_eax),@function
+GNAME(alloc_overflow_eax):
+        pushl   %ecx            # Save ecx
+        pushl   %edx            # Save edx
+        /* Calculate the size for the allocation. */
+        subl    START_REGION,%eax
+        pushl   %eax            # Push the size
+        call    GNAME(alloc)
+        addl    $4,%esp # pop the size arg.
+        popl    %edx    # Restore edx.
+        popl    %ecx    # Restore ecx.
+       addl    DISPLACEMENT,(%esp) # Adjust the return address to skip the next inst.
+        ret
+        .size    GNAME(alloc_overflow_eax),.-GNAME(alloc_overflow_eax)
+
+        .align  align_4byte
+        .globl  GNAME(alloc_overflow_ecx)
+        .type   GNAME(alloc_overflow_ecx),@function
+GNAME(alloc_overflow_ecx):
+        pushl   %eax            # Save eax
+        pushl   %edx            # Save edx
+        /* Calculate the size for the allocation. */
+        subl    START_REGION,%ecx
+        pushl   %ecx            # Push the size
+        call    GNAME(alloc)
+        addl    $4,%esp # pop the size arg.
+        movl    %eax,%ecx       # setup the destination.
+        popl    %edx    # Restore edx.
+        popl    %eax    # Restore eax.
+       addl    DISPLACEMENT,(%esp) # Adjust the return address to skip the next inst.
+        ret
+        .size    GNAME(alloc_overflow_ecx),.-GNAME(alloc_overflow_ecx)
+
+        .align  align_4byte
+        .globl  GNAME(alloc_overflow_edx)
+        .type   GNAME(alloc_overflow_edx),@function
+GNAME(alloc_overflow_edx):
+        pushl   %eax            # Save eax
+        pushl   %ecx            # Save ecx
+        /* Calculate the size for the allocation. */
+        subl    START_REGION,%edx
+        pushl   %edx            # Push the size
+        call    GNAME(alloc)
+        addl    $4,%esp # pop the size arg.
+        movl    %eax,%edx       # setup the destination.
+        popl    %ecx    # Restore ecx.
+        popl    %eax    # Restore eax.
+       addl    DISPLACEMENT,(%esp) # Adjust the return address to skip the next inst.
+        ret
+        .size    GNAME(alloc_overflow_edx),.-GNAME(alloc_overflow_edx)
+
+/* This routine handles an overflow with ebx=crfp+size. So the
+   size=ebx-crfp. */
+        .align  align_4byte
+        .globl  GNAME(alloc_overflow_ebx)
+        .type   GNAME(alloc_overflow_ebx),@function
+GNAME(alloc_overflow_ebx):
+        pushl   %eax            # Save eax
+        pushl   %ecx            # Save ecx
+        pushl   %edx            # Save edx
+        /* Calculate the size for the allocation. */
+        subl    START_REGION,%ebx
+        pushl   %ebx            # Push the size
+        call    GNAME(alloc)
+        addl    $4,%esp # pop the size arg.
+        movl    %eax,%ebx       # setup the destination.
+        popl    %edx    # Restore edx.
+        popl    %ecx    # Restore ecx.
+        popl    %eax    # Restore eax.
+       addl    DISPLACEMENT,(%esp) # Adjust the return address to skip the next inst.
+        ret
+        .size    GNAME(alloc_overflow_ebx),.-GNAME(alloc_overflow_ebx)
+
+/* This routine handles an overflow with esi=crfp+size. So the
+   size=esi-crfp. */
+        .align  align_4byte
+        .globl  GNAME(alloc_overflow_esi)
+        .type   GNAME(alloc_overflow_esi),@function
+GNAME(alloc_overflow_esi):
+        pushl   %eax            # Save eax
+        pushl   %ecx            # Save ecx
+        pushl   %edx            # Save edx
+        /* Calculate the size for the allocation. */
+        subl    START_REGION,%esi
+        pushl   %esi            # Push the size
+        call    GNAME(alloc)
+        addl    $4,%esp # pop the size arg.
+        movl    %eax,%esi       # setup the destination.
+        popl    %edx    # Restore edx.
+        popl    %ecx    # Restore ecx.
+        popl    %eax    # Restore eax.
+       addl    DISPLACEMENT,(%esp) # Adjust the return address to skip the next inst.
+        ret
+        .size    GNAME(alloc_overflow_esi),.-GNAME(alloc_overflow_esi)
+
+        .align  align_4byte
+        .globl  GNAME(alloc_overflow_edi)
+        .type   GNAME(alloc_overflow_edi),@function
+GNAME(alloc_overflow_edi):
+        pushl   %eax            # Save eax
+        pushl   %ecx            # Save ecx
+        pushl   %edx            # Save edx
+        /* Calculate the size for the allocation. */
+        subl    START_REGION,%edi
+        pushl   %edi            # Push the size
+        call    GNAME(alloc)
+        addl    $4,%esp # pop the size arg.
+        movl    %eax,%edi       # setup the destination.
+        popl    %edx    # Restore edx.
+        popl    %ecx    # Restore ecx.
+        popl    %eax    # Restore eax.
+       addl    DISPLACEMENT,(%esp) # Adjust the return address to skip the next inst.
+        ret
+        .size    GNAME(alloc_overflow_edi),.-GNAME(alloc_overflow_edi)
 
        .align  align_4byte,0x90
        .globl  GNAME(post_signal_tramp)
@@ -674,139 +806,4 @@ GNAME(post_signal_tramp):
        .size GNAME(post_signal_tramp),.-GNAME(post_signal_tramp)
 
        
-\f
-#ifdef GENCGC_INLINE_ALLOC /* LISP_FEATURE_GENCGC */
-
-/* These routines are called from Lisp when an inline allocation 
- * overflows. Every register except the result needs to be preserved.
- * We depend on C to preserve ebx, esi, edi, and ebp.
- * But where necessary must save eax, ecx, edx. */
-
-/* This routine handles an overflow with eax=crfp+size. So the
- * size=eax-crfp. */
-       .align  align_4byte
-       .globl  GNAME(alloc_overflow_eax)
-       .type   GNAME(alloc_overflow_eax),@function
-GNAME(alloc_overflow_eax):
-       pushl   %ecx            # Save ecx
-       pushl   %edx            # Save edx
-       /* Calculate the size for the allocation. */
-       subl    GNAME(current_region_free_pointer),%eax
-       pushl   %eax            # Push the size
-       call    GNAME(alloc)
-       addl    $4,%esp # pop the size arg.
-       popl    %edx    # Restore edx.
-       popl    %ecx    # Restore ecx.
-       addl    $6,(%esp) # Adjust the return address to skip the next inst.
-       ret
-       .size    GNAME(alloc_overflow_eax),.-GNAME(alloc_overflow_eax)
-
-/* This routine handles an overflow with ecx=crfp+size. So the
- * size=ecx-crfp. */
-       .align  align_4byte
-       .globl  GNAME(alloc_overflow_ecx)
-       .type   GNAME(alloc_overflow_ecx),@function
-GNAME(alloc_overflow_ecx):
-       pushl   %eax            # Save eax
-       pushl   %edx            # Save edx
-       /* Calculate the size for the allocation. */
-       subl    GNAME(current_region_free_pointer),%ecx
-       pushl   %ecx            # Push the size
-       call    GNAME(alloc)
-       addl    $4,%esp # pop the size arg.
-       movl    %eax,%ecx       # setup the destination.
-       popl    %edx    # Restore edx.
-       popl    %eax    # Restore eax.
-       addl    $6,(%esp) # Adjust the return address to skip the next inst.
-       ret
-       .size    GNAME(alloc_overflow_ecx),.-GNAME(alloc_overflow_ecx)
-
-/* This routine handles an overflow with edx=crfp+size. So the
- * size=edx-crfp. */
-       .align  align_4byte
-       .globl  GNAME(alloc_overflow_edx)
-       .type   GNAME(alloc_overflow_edx),@function
-GNAME(alloc_overflow_edx):
-       pushl   %eax            # Save eax
-       pushl   %ecx            # Save ecx
-       /* Calculate the size for the allocation. */
-       subl    GNAME(current_region_free_pointer),%edx
-       pushl   %edx            # Push the size
-       call    GNAME(alloc)
-       addl    $4,%esp # pop the size arg.
-       movl    %eax,%edx       # setup the destination.
-       popl    %ecx    # Restore ecx.
-       popl    %eax    # Restore eax.
-       addl    $6,(%esp) # Adjust the return address to skip the next inst.
-       ret
-       .size    GNAME(alloc_overflow_edx),.-GNAME(alloc_overflow_edx)
-
-/* This routine handles an overflow with ebx=crfp+size. So the
- * size=ebx-crfp. */
-       .align  align_4byte
-       .globl  GNAME(alloc_overflow_ebx)
-       .type   GNAME(alloc_overflow_ebx),@function
-GNAME(alloc_overflow_ebx):
-       pushl   %eax            # Save eax
-       pushl   %ecx            # Save ecx
-       pushl   %edx            # Save edx
-       /* Calculate the size for the allocation. */
-       subl    GNAME(current_region_free_pointer),%ebx
-       pushl   %ebx            # Push the size
-       call    GNAME(alloc)
-       addl    $4,%esp # pop the size arg.
-       movl    %eax,%ebx       # setup the destination.
-       popl    %edx    # Restore edx.
-       popl    %ecx    # Restore ecx.
-       popl    %eax    # Restore eax.
-       addl    $6,(%esp) # Adjust the return address to skip the next inst.
-       ret
-       .size    GNAME(alloc_overflow_ebx),.-GNAME(alloc_overflow_ebx)
-
-/* This routine handles an overflow with esi=crfp+size. So the
- * size=esi-crfp. */
-       .align  align_4byte
-       .globl  GNAME(alloc_overflow_esi)
-       .type   GNAME(alloc_overflow_esi),@function
-GNAME(alloc_overflow_esi):
-       pushl   %eax            # Save eax
-       pushl   %ecx            # Save ecx
-       pushl   %edx            # Save edx
-       /* Calculate the size for the allocation. */
-       subl    GNAME(current_region_free_pointer),%esi
-       pushl   %esi            # Push the size
-       call    GNAME(alloc)
-       addl    $4,%esp # pop the size arg.
-       movl    %eax,%esi       # setup the destination.
-       popl    %edx    # Restore edx.
-       popl    %ecx    # Restore ecx.
-       popl    %eax    # Restore eax.
-       addl    $6,(%esp) # Adjust the return address to skip the next inst.
-       ret
-       .size    GNAME(alloc_overflow_esi),.-GNAME(alloc_overflow_esi)
-
-/* This routine handles an overflow with edi=crfp+size. So the
- * size=edi-crfp. */
-       .align  align_4byte
-       .globl  GNAME(alloc_overflow_edi)
-       .type   GNAME(alloc_overflow_edi),@function
-GNAME(alloc_overflow_edi):
-       pushl   %eax            # Save eax
-       pushl   %ecx            # Save ecx
-       pushl   %edx            # Save edx
-       /* Calculate the size for the allocation. */
-       subl    GNAME(current_region_free_pointer),%edi
-       pushl   %edi            # Push the size
-       call    GNAME(alloc)
-       addl    $4,%esp # pop the size arg.
-       movl    %eax,%edi       # setup the destination.
-       popl    %edx    # Restore edx.
-       popl    %ecx    # Restore ecx.
-       popl    %eax    # Restore eax.
-       addl    $6,(%esp) # Adjust the return address to skip the next inst.
-       ret
-       .size    GNAME(alloc_overflow_edi),.-GNAME(alloc_overflow_edi)
-
-#endif
-
        .end
index 25d9cd7..15eb762 100644 (file)
@@ -70,8 +70,8 @@ volatile lispobj modify_ldt_lock;     /* protect all calls to modify_ldt */
 int arch_os_thread_init(struct thread *thread) {
     stack_t sigstack;
 #ifdef LISP_FEATURE_SB_THREAD
-    /* this must be called from a function that has an exclusive lock
-     * on all_threads
+    /* FIXME Lock ordering rules: all_threads_lock must usually be
+     * held when getting modify_ldt_lock
      */
     struct user_desc ldt_entry = {
        1, 0, 0, /* index, address, length filled in later */
index 8eebb8e..1836c0c 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.13.10"
+"0.8.13.11"