unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
       [not found] <E1SwCK8-0001PC-3m@vcs.savannah.gnu.org>
@ 2012-08-01 10:33 ` Stefan Monnier
  2012-08-01 12:04   ` Dmitry Antipov
  0 siblings, 1 reply; 43+ messages in thread
From: Stefan Monnier @ 2012-08-01 10:33 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

>   * src/frame.h (FVAR): New macro.

Is it really necessary?  To me this just obfuscates the code.
If/when it turns out to be needed, it'll be easy enough to introduce.


        Stefan



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 10:33 ` [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames Stefan Monnier
@ 2012-08-01 12:04   ` Dmitry Antipov
  2012-08-01 14:58     ` Paul Eggert
                       ` (2 more replies)
  0 siblings, 3 replies; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-01 12:04 UTC (permalink / raw)
  To: emacs-devel

On 08/01/2012 02:33 PM, Stefan Monnier wrote:

>>    * src/frame.h (FVAR): New macro.
>
> Is it really necessary?  To me this just obfuscates the code.
> If/when it turns out to be needed, it'll be easy enough to introduce.

I have no ideas why BVAR and KVAR was introduced, but my motivation is:

http://lists.gnu.org/archive/html/emacs-devel/2012-07/msg00667.html
http://lists.gnu.org/archive/html/emacs-devel/2012-07/msg00669.html
http://lists.gnu.org/archive/html/emacs-devel/2012-08/msg00001.html

I'm really trying to design some GC bits on top of this.

Dmitry




^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 12:04   ` Dmitry Antipov
@ 2012-08-01 14:58     ` Paul Eggert
  2012-08-01 16:52       ` Dmitry Antipov
  2012-08-01 17:38       ` Tom Tromey
  2012-08-01 15:01     ` Eli Zaretskii
  2012-08-01 23:52     ` Stefan Monnier
  2 siblings, 2 replies; 43+ messages in thread
From: Paul Eggert @ 2012-08-01 14:58 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

On 08/01/2012 05:04 AM, Dmitry Antipov wrote:
> I'm really trying to design some GC bits on top of this.

OK, but why bother to do the hugely overestimated
write barrier that FVAR implies?  Surely that is not
what is wanted here, for the garbage collector.  As I
understand it, what's really wanted for the GC is SET_FVAR.
FVAR itself might be useful in that it can be forced
to be an rvalue so that code doesn't use FVAR (...) = VAL
by mistake, but surely that is secondary.

Stefan's point also, is that it'll be easy enough to
introduce SET_FVAR when the GC bits are ready,
and that there's no pressing need to introduce it now.

While we're on the topic, the code is currently sloppy
about using ASET; sometimes it uses 'AREF (a, b) = c'
rather than 'ASET (a, b, c)'.  I suppose this will
need fixing too.  It probably should be fixed regardless
of any GC changes.




^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 12:04   ` Dmitry Antipov
  2012-08-01 14:58     ` Paul Eggert
@ 2012-08-01 15:01     ` Eli Zaretskii
  2012-08-01 18:02       ` Dmitry Antipov
  2012-08-01 23:52     ` Stefan Monnier
  2 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-08-01 15:01 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

> Date: Wed, 01 Aug 2012 16:04:36 +0400
> From: Dmitry Antipov <dmantipov@yandex.ru>
> 
> On 08/01/2012 02:33 PM, Stefan Monnier wrote:
> 
> >>    * src/frame.h (FVAR): New macro.
> >
> > Is it really necessary?  To me this just obfuscates the code.
> > If/when it turns out to be needed, it'll be easy enough to introduce.
> 
> I have no ideas why BVAR and KVAR was introduced

For multithreading branch.  See

  http://lists.gnu.org/archive/html/emacs-devel/2011-01/msg01019.html

and the rest of the longish thread (which continues into the next
month).

> I'm really trying to design some GC bits on top of this.

May I suggest to post some kind of design notes, with some details
about the above?  I think such preliminary discussions help get all
the interested parties up to speed, raise some important issues that
are best discovered sooner rather than later, and generally avoid
surprises, pleasant or otherwise.

I did something like that while I was working on bidi display, and my
experience with this was very positive, even though much less people
are interested in that subject than in GC.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 14:58     ` Paul Eggert
@ 2012-08-01 16:52       ` Dmitry Antipov
  2012-08-01 17:38       ` Tom Tromey
  1 sibling, 0 replies; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-01 16:52 UTC (permalink / raw)
  To: Paul Eggert; +Cc: emacs-devel

On 08/01/2012 06:58 PM, Paul Eggert wrote:

> OK, but why bother to do the hugely overestimated
> write barrier that FVAR implies?  Surely that is not
> what is wanted here, for the garbage collector.  As I
> understand it, what's really wanted for the GC is SET_FVAR.
> FVAR itself might be useful in that it can be forced
> to be an rvalue so that code doesn't use FVAR (...) = VAL
> by mistake, but surely that is secondary.

I agree, but see http://lists.gnu.org/archive/html/emacs-devel/2012-08/msg00001.html.

> Stefan's point also, is that it'll be easy enough to
> introduce SET_FVAR when the GC bits are ready,
> and that there's no pressing need to introduce it now.

I'm considering this much like a kind of chicken-egg problem:
it's very hard to design GC bits without supporting infrastructure
implemented, and no one wants to deal with obfuscated internal
things in the absence of visible advantages provided by new GC :-).

> While we're on the topic, the code is currently sloppy
> about using ASET; sometimes it uses 'AREF (a, b) = c'
> rather than 'ASET (a, b, c)'.  I suppose this will
> need fixing too.  It probably should be fixed regardless
> of any GC changes.

Yes. BTW, there are few other things which are bad from GC's point of view:
X = &AREF (obj, idx), memcpy and memmove directly between FOO->contents
of struct Lisp_Vector, etc.

Dmitry




^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 14:58     ` Paul Eggert
  2012-08-01 16:52       ` Dmitry Antipov
@ 2012-08-01 17:38       ` Tom Tromey
  2012-08-01 21:04         ` Paul Eggert
  2012-08-02  5:28         ` Stephen J. Turnbull
  1 sibling, 2 replies; 43+ messages in thread
From: Tom Tromey @ 2012-08-01 17:38 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Dmitry Antipov, emacs-devel

>>>>> "Paul" == Paul Eggert <eggert@cs.ucla.edu> writes:

Paul> While we're on the topic, the code is currently sloppy
Paul> about using ASET; sometimes it uses 'AREF (a, b) = c'
Paul> rather than 'ASET (a, b, c)'.  I suppose this will
Paul> need fixing too.  It probably should be fixed regardless
Paul> of any GC changes.

It isn't just ASET but many accessors of many objects.
Also, when I looked into this, there were places that take the address
of a field of a Lisp_Object and pass that around... more stuff to fix if
you want a software write barrier.

FWIW I think it is an interesting project, and the problems are all
surmountable.

Tom



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 15:01     ` Eli Zaretskii
@ 2012-08-01 18:02       ` Dmitry Antipov
  2012-08-02 15:28         ` Eli Zaretskii
  0 siblings, 1 reply; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-01 18:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2841 bytes --]

On 08/01/2012 07:01 PM, Eli Zaretskii wrote:

>> I'm really trying to design some GC bits on top of this.
>
> May I suggest to post some kind of design notes, with some details
> about the above?  I think such preliminary discussions help get all
> the interested parties up to speed, raise some important issues that
> are best discovered sooner rather than later, and generally avoid
> surprises, pleasant or otherwise.

OK. There are some ideas to share now.

1. Be realistic. It's practically impossible to throw away current GC and
redesign everything from scratch. In general, GC theory says that the collector
which is able to move objects should have advantages against non-moving
collector; we can think about compaction methods, but switching to (mostly)
copying collector is not a subject for discussions now. So, let's preserve
basic mark and sweep approach.

2. Do not (re)invent the bicycle. The most common ways to improve simple
mark and sweep collector is to make it generational and/or incremental.
Both approaches usually relies on the ability to trap pointer writes,
which is needed to maintain collector invariants; that's why I'm looking
for the lowest-effort methods to implement write barriers on top of
the existing infrastructure. Next, generational and incremental approaches
may be investigated and designed in parallel.

3. Premature optimization is the root of all evil. For the beginning,
I'm trying to implement a hugely overestimated write barrier (e.g. a lot
of pointer writes are really pointer reads). Of course, it will be notoriously
slow. Next, it should be possible to shrink an overestimation by separating
reads from writes, thus improving the collector speed.

4. Let's group them. Advanced GC usually requires additional information stored
in objects. This may be tricky for some objects (consider struct Lisp_Cons as
an example). But the most of objects are allocated from blocks (that's why I
spent some time to design block-based vector allocator :-), so we can try to
investigate using per-block special fields rather than per-object ones. (Large
vectors and buffers are special). For example, the only XSETCAR (X, Y) "invalidates"
the whole block where X is allocated, thus making this block a subject to
mark and sweep procedure at the next partial collection. LOL? Hold your horses
and re-read 3).

5. Just do it. Now I'm trying to trap each X = Y (remember about it's hugely
overestimated), where both X and Y are Lisp_Objects (not integers, not pure),
mark block contains X as target to mark at next partial collection, and mark
block contains _previous_ value of X (which was in effect before assignment)
as target to sweep at next partial collection. Next, I'm trying to estimate
how much allocated blocks needs marking and sweeping. Attached patch illustrates
this idea.

Dmitry







[-- Attachment #2: gc_write_barrier_approach_1.patch --]
[-- Type: text/plain, Size: 16677 bytes --]

=== modified file 'configure.ac'
--- configure.ac	2012-08-01 07:20:52 +0000
+++ configure.ac	2012-08-01 10:03:56 +0000
@@ -607,6 +607,15 @@
    fi
 fi)
 
+AC_ARG_ENABLE(experimental-gc,
+[AS_HELP_STRING([--enable-experimental-gc],
+                [build emacs with experimental garbage collector.
+                 This is not really implemented yet.
+                 Expect bootstrap failures, slowdown and crashes.])],
+if test "${enableval}" = "yes"; then
+  AC_DEFINE(EXPERIMENTAL_GC, 1, [Define to try experimental GC.])
+fi)
+
 # gl_GCC_VERSION_IFELSE([major], [minor], [run-if-found], [run-if-not-found])
 # ------------------------------------------------
 # If $CPP is gcc-MAJOR.MINOR or newer, then run RUN-IF-FOUND.

=== modified file 'src/alloc.c'
--- src/alloc.c	2012-08-01 08:49:28 +0000
+++ src/alloc.c	2012-08-01 16:41:39 +0000
@@ -1443,8 +1443,18 @@
 #endif /* not SYNC_INPUT */
 #endif /* not SYSTEM_MALLOC */
 
-
-\f
+#ifdef EXPERIMENTAL_GC
+
+#define GC_EXTRA sizeof (struct blockdata)
+
+static void set_sweep (Lisp_Object);
+
+#else /* not EXPERIMENTAL_GC */
+
+#define GC_EXTRA (0)
+
+#endif /* EXPERIMENTAL_GC */
+
 /***********************************************************************
 			 Interval Allocation
  ***********************************************************************/
@@ -2639,7 +2649,7 @@
    any new cons cells from the latest cons_block.  */
 
 #define CONS_BLOCK_SIZE						\
-  (((BLOCK_BYTES - sizeof (struct cons_block *)			\
+  (((BLOCK_BYTES - GC_EXTRA - sizeof (struct cons_block *)	\
      /* The compiler might add padding at the end.  */		\
      - (sizeof (struct Lisp_Cons) - sizeof (int))) * CHAR_BIT)	\
    / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1))
@@ -2655,6 +2665,9 @@
   /* Place `conses' at the beginning, to ease up CONS_INDEX's job.  */
   struct Lisp_Cons conses[CONS_BLOCK_SIZE];
   int gcmarkbits[1 + CONS_BLOCK_SIZE / (sizeof (int) * CHAR_BIT)];
+#ifdef EXPERIMENTAL_GC
+  struct blockdata bd;
+#endif
   struct cons_block *next;
 };
 
@@ -2693,6 +2706,34 @@
   total_free_conses++;
 }
 
+#ifdef EXPERIMENTAL_GC
+
+void
+xsetcar (Lisp_Object cell, Lisp_Object car)
+{
+  struct Lisp_Cons *c = XCONS (cell);
+  
+  if (!PURE_POINTER_P (c))
+    CONS_BLOCK (c)->bd.mark = 1;
+
+  set_sweep (CVAR (c, car));
+  CVAR (c, car) = car;
+}
+
+void
+xsetcdr (Lisp_Object cell, Lisp_Object cdr)
+{
+  struct Lisp_Cons *c = XCONS (cell);
+
+  if (!PURE_POINTER_P (c))
+    CONS_BLOCK (c)->bd.mark = 1;
+
+  set_sweep (CVAR (c, u.cdr));
+  CVAR (c, u.cdr) = cdr;
+}
+
+#endif /* EXPERIMENTAL_GC */
+
 DEFUN ("cons", Fcons, Scons, 2, 2, 0,
        doc: /* Create a new cons, give it CAR and CDR as components, and return it.  */)
   (Lisp_Object car, Lisp_Object cdr)
@@ -2718,6 +2759,10 @@
 	    = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
 	  memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
 	  new->next = cons_block;
+#ifdef EXPERIMENTAL_GC
+	  new->bd.mark = 1;
+	  new->bd.sweep = 0;
+#endif
 	  cons_block = new;
 	  cons_block_index = 0;
 	  total_free_conses += CONS_BLOCK_SIZE;
@@ -2728,8 +2773,10 @@
 
   MALLOC_UNBLOCK_INPUT;
 
-  XSETCAR (val, car);
-  XSETCDR (val, cdr);
+  /* Do not use XSETxxx here.  */
+  CVAR (XCONS (val), car) = car;
+  CVAR (XCONS (val), u.cdr) = cdr;
+
   eassert (!CONS_MARKED_P (XCONS (val)));
   consing_since_gc += sizeof (struct Lisp_Cons);
   total_free_conses--;
@@ -2914,7 +2961,8 @@
 
 /* Rounding helps to maintain alignment constraints if USE_LSB_TAG.  */
 
-#define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup (sizeof (void *)))
+#define VECTOR_BLOCK_BYTES \
+  (VECTOR_BLOCK_SIZE - vroundup (sizeof (void *) + GC_EXTRA))
 
 /* Size of the minimal vector allocated from block.  */
 
@@ -2952,9 +3000,19 @@
     total_free_vector_slots += (nbytes) / word_size;		\
   } while (0)
 
+#ifdef EXPERIMENTAL_GC
+
+#define VECTOR_BLOCK(vptr) \
+  ((struct vector_block *) ((uintptr_t) (vptr) & ~(VECTOR_BLOCK_SIZE - 1)))
+
+#endif /* EXPERIMENTAL_GC */
+
 struct vector_block
 {
   char data[VECTOR_BLOCK_BYTES];
+#ifdef EXPERIMENTAL_GC
+  struct blockdata bd;
+#endif
   struct vector_block *next;
 };
 
@@ -2988,7 +3046,17 @@
 static struct vector_block *
 allocate_vector_block (void)
 {
-  struct vector_block *block = xmalloc (sizeof *block);
+  struct vector_block *block;
+
+#ifdef EXPERIMENTAL_GC
+  if (posix_memalign
+      ((void **) &block, VECTOR_BLOCK_SIZE, VECTOR_BLOCK_SIZE))
+    abort ();
+  block->bd.mark = 1;
+  block->bd.sweep = 0;
+#else
+  block = xmalloc (sizeof *block);
+#endif
 
 #if GC_MARK_STACK && !defined GC_MALLOC_CHECK
   mem_insert (block->data, block->data + VECTOR_BLOCK_BYTES,
@@ -3096,6 +3164,9 @@
 {
   struct vector_block *block = vector_blocks, **bprev = &vector_blocks;
   struct Lisp_Vector *vector, *next, **vprev = &large_vectors;
+#ifdef EXPERIMENTAL_GC
+    int num_blocks = 0, num_unchanged_blocks = 0;
+#endif
 
   total_vectors = total_vector_slots = total_free_vector_slots = 0;
   memset (vector_free_lists, 0, sizeof (vector_free_lists));
@@ -3159,9 +3230,21 @@
 	  xfree (block);
 	}
       else
-	bprev = &block->next;
+	{
+	  bprev = &block->next;
+#ifdef EXPERIMENTAL_GC
+	  num_blocks++;
+	  num_unchanged_blocks += !block->bd.mark;
+	  block->bd.mark = 0;
+#endif
+	}
     }
 
+#ifdef EXPERIMENTAL_GC
+  fprintf (stderr, "GC%ld: %d of %d vector blocks are unchanged\n",
+	   gcs_done, num_unchanged_blocks, num_blocks);
+#endif
+
   /* Sweep large vectors.  */
 
   for (vector = large_vectors; vector; vector = *vprev)
@@ -3197,6 +3280,53 @@
     }
 }
 
+#ifdef EXPERIMENTAL_GC
+
+/* Return non-zero if V is allocated from block.  */
+
+static inline int
+block_vector (struct Lisp_Vector *v)
+{
+  ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG;
+
+  if (size & PSEUDOVECTOR_FLAG)
+    {
+      ptrdiff_t pvectype = ((v->header.size & PVEC_TYPE_MASK)
+			    >> PSEUDOVECTOR_SIZE_BITS);
+
+      if (pvectype == PVEC_BUFFER || pvectype == PVEC_SUBR)
+	return 0;
+      else if (pvectype == PVEC_BOOL_VECTOR)
+	{
+	  struct Lisp_Bool_Vector *b = (struct Lisp_Bool_Vector *) v;
+
+	  return (((b->size + CHAR_BIT - 1) / CHAR_BIT)
+		  + bool_header_size) <= VBLOCK_BYTES_MAX;
+	}
+      else
+	return 1;
+    }
+  return header_size + size * word_size <= VBLOCK_BYTES_MAX;
+}
+
+struct Lisp_Vector *
+vector_write_barrier (struct Lisp_Vector *v)
+{
+  if (!PURE_POINTER_P (v) && block_vector (v))
+    {
+      ptrdiff_t i, size = v->header.size & ~ARRAY_MARK_FLAG;
+
+      if (size & PSEUDOVECTOR_FLAG)
+	size &= PSEUDOVECTOR_SIZE_MASK;
+      VECTOR_BLOCK (v)->bd.mark = 1;
+      for (i = 0; i < size; i++)
+	set_sweep (v->contents[i]);
+    }
+  return v;
+}
+
+#endif /* EXPERIMENTAL_GC */
+
 /* Value is a pointer to a newly allocated Lisp_Vector structure
    with room for LEN Lisp_Objects.  */
 
@@ -3279,6 +3409,35 @@
   return v;
 }
 
+#ifdef EXPERIMENTAL_GC
+
+static void
+setup_buffer (struct buffer *b)
+{
+  ptrdiff_t i, size 
+    = (b->header.size & ~ARRAY_MARK_FLAG) & PSEUDOVECTOR_SIZE_MASK;
+  struct Lisp_Vector *v = (struct Lisp_Vector *) b;
+
+  for (i = 0; i < size; i++)
+    v->contents[i] = Qnil;
+}
+
+struct buffer *
+buffer_write_barrier (struct buffer *b)
+{
+  ptrdiff_t i, size 
+    = (b->header.size & ~ARRAY_MARK_FLAG) & PSEUDOVECTOR_SIZE_MASK;
+  struct Lisp_Vector *v = (struct Lisp_Vector *) b;
+
+  b->bd.mark = 1;
+  for (i = 0; i < size; i++)
+    set_sweep (v->contents[i]);
+
+  return b;
+}
+
+#endif /* EXPERIMENTAL_GC */
+
 struct buffer *
 allocate_buffer (void)
 {
@@ -3286,7 +3445,13 @@
 
   XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text)
 				     - header_size) / word_size);
+#ifdef EXPERIMENTAL_GC
+  b->bd.mark = 1;
+  b->bd.sweep = 0;
+  setup_buffer (b);
+#else
   /* Note that the fields of B are not initialized.  */
+#endif
   return b;
 }
 
@@ -3461,16 +3626,27 @@
    really allocates in units of powers of two and uses 4 bytes for its
    own overhead.  */
 
-#define SYMBOL_BLOCK_SIZE \
-  ((1020 - sizeof (struct symbol_block *)) / sizeof (union aligned_Lisp_Symbol))
+#define SYMBOL_BLOCK_SIZE				\
+  ((1020 - GC_EXTRA - sizeof (struct symbol_block *))	\
+   / sizeof (union aligned_Lisp_Symbol))
 
 struct symbol_block
 {
   /* Place `symbols' first, to preserve alignment.  */
   union aligned_Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE];
+#ifdef EXPERIMENTAL_GC
+  struct blockdata bd;
+#endif
   struct symbol_block *next;
 };
 
+#ifdef EXPERIMENTAL_GC
+
+#define SYMBOL_BLOCK(sptr) \
+  ((struct symbol_block *) ((uintptr_t) (sptr) & ~(BLOCK_ALIGN - 1)))
+
+#endif
+
 /* Current symbol block and index of first unused Lisp_Symbol
    structure in it.  */
 
@@ -3481,6 +3657,27 @@
 
 static struct Lisp_Symbol *symbol_free_list;
 
+#ifdef EXPERIMENTAL_GC
+
+struct Lisp_Symbol *
+symbol_write_barrier (struct Lisp_Symbol *sym) 
+{
+  if (!PURE_POINTER_P (sym))
+    SYMBOL_BLOCK (sym)->bd.mark = 1;
+
+  /* Do not use SVAR, you don't want to go
+     through the barrier recursively.  */
+  set_sweep (sym->INTERNAL_FIELD (xname));
+  if (sym->redirect == 0)
+    set_sweep (sym->INTERNAL_FIELD (val.value));
+  set_sweep (sym->INTERNAL_FIELD (function));
+  set_sweep (sym->INTERNAL_FIELD (plist));
+
+  return sym;
+}
+
+#endif /* EXPERIMENTAL_GC */
+
 DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
        doc: /* Return a newly allocated uninterned symbol whose name is NAME.
 Its value and function definition are void, and its property list is nil.  */)
@@ -3504,8 +3701,18 @@
     {
       if (symbol_block_index == SYMBOL_BLOCK_SIZE)
 	{
-	  struct symbol_block *new
-	    = lisp_malloc (sizeof *new, MEM_TYPE_SYMBOL);
+	  struct symbol_block *new;
+#ifdef EXPERIMENTAL_GC
+	  if (posix_memalign ((void **) &new, BLOCK_ALIGN, sizeof *new))
+	    abort ();
+	  mem_insert ((char *) new->symbols,
+		      (char *) new->symbols + sizeof (new->symbols),
+		      MEM_TYPE_SYMBOL);
+          new->bd.mark = 1;
+	  new->bd.sweep = 0;
+#else
+	  new = lisp_malloc (sizeof *new, MEM_TYPE_SYMBOL);
+#endif
 	  new->next = symbol_block;
 	  symbol_block = new;
 	  symbol_block_index = 0;
@@ -3518,11 +3725,11 @@
   MALLOC_UNBLOCK_INPUT;
 
   p = XSYMBOL (val);
-  SVAR (p, xname) = name;
-  SVAR (p, plist) = Qnil;
+  p->INTERNAL_FIELD (xname) = name;
+  p->INTERNAL_FIELD (plist) = Qnil;
   p->redirect = SYMBOL_PLAINVAL;
-  SET_SYMBOL_VAL (p, Qunbound);
-  SVAR (p, function) = Qunbound;
+  p->INTERNAL_FIELD (val.value) = Qunbound;
+  p->INTERNAL_FIELD (function) = Qunbound;
   p->next = NULL;
   p->gcmarkbit = 0;
   p->interned = SYMBOL_UNINTERNED;
@@ -5867,6 +6074,36 @@
     mark_buffer (buffer->base_buffer);
 }
 
+#ifdef EXPERIMENTAL_GC
+
+/* Mark OBJ's block as candidate to sweep.  */
+
+static void
+set_sweep (Lisp_Object obj)
+{
+  if (!INTEGERP (obj) && !PURE_POINTER_P (XPNTR (obj)))
+    switch (XTYPE (obj))
+      {
+        case Lisp_Cons:
+	  CONS_BLOCK (XCONS (obj))->bd.sweep = 1;
+	  break;
+
+        case Lisp_Symbol:
+	  SYMBOL_BLOCK (XSYMBOL (obj))->bd.sweep = 1;
+	  break;
+
+        case Lisp_Vectorlike:
+	  if (block_vector (XVECTOR (obj)))
+	    VECTOR_BLOCK (XVECTOR (obj))->bd.sweep = 1;
+	  break;
+
+        default:
+	  break;
+      }
+}
+
+#endif /* EXPERIMENTAL_GC */
+
 /* Determine type of generic Lisp_Object and mark it accordingly.  */
 
 void
@@ -6287,7 +6524,9 @@
     struct cons_block **cprev = &cons_block;
     register int lim = cons_block_index;
     EMACS_INT num_free = 0, num_used = 0;
-
+#ifdef EXPERIMENTAL_GC
+    int num_blocks = 0, num_unchanged_blocks = 0;
+#endif
     cons_free_list = 0;
 
     for (cblk = cons_block; cblk; cblk = *cprev)
@@ -6352,10 +6591,19 @@
 	  {
 	    num_free += this_free;
 	    cprev = &cblk->next;
+#ifdef EXPERIMENTAL_GC
+	    num_blocks++;
+	    num_unchanged_blocks += !cblk->bd.mark;
+	    cblk->bd.mark = 0;
+#endif
 	  }
       }
     total_conses = num_used;
     total_free_conses = num_free;
+#ifdef EXPERIMENTAL_GC
+    fprintf (stderr, "GC%ld: %d of %d cons blocks are unchanged\n",
+             gcs_done, num_unchanged_blocks, num_blocks);
+#endif
   }
 
   /* Put all unmarked floats on free list */
@@ -6459,6 +6707,9 @@
     struct symbol_block **sprev = &symbol_block;
     register int lim = symbol_block_index;
     EMACS_INT num_free = 0, num_used = 0;
+#ifdef EXPERIMENTAL_GC
+    int num_blocks = 0, num_unchanged_blocks = 0;
+#endif
 
     symbol_free_list = NULL;
 
@@ -6510,10 +6761,19 @@
 	  {
 	    num_free += this_free;
 	    sprev = &sblk->next;
+#ifdef EXPERIMENTAL_GC
+	    num_blocks++;
+	    num_unchanged_blocks += !sblk->bd.mark;
+	    sblk->bd.mark = 0;
+#endif
 	  }
       }
     total_symbols = num_used;
     total_free_symbols = num_free;
+#ifdef EXPERIMENTAL_GC
+    fprintf (stderr, "GC%ld: %d of %d symbol blocks are unchanged\n",
+             gcs_done, num_unchanged_blocks, num_blocks);
+#endif
   }
 
   /* Put all unmarked misc's on free list.
@@ -6576,7 +6836,9 @@
   /* Free all unmarked buffers */
   {
     register struct buffer *buffer = all_buffers, *prev = 0, *next;
-
+#ifdef EXPERIMENTAL_GC
+    int unchanged_buffers = 0;
+#endif
     total_buffers = 0;
     while (buffer)
       if (!VECTOR_MARKED_P (buffer))
@@ -6594,8 +6856,16 @@
 	  VECTOR_UNMARK (buffer);
 	  UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer));
 	  total_buffers++;
+#ifdef EXPERIMENTAL_GC
+	  unchanged_buffers += !buffer->bd.mark;
+	  buffer->bd.mark = 0;
+#endif
 	  prev = buffer, buffer = buffer->header.next.buffer;
 	}
+#ifdef EXPERIMENTAL_GC
+    fprintf (stderr, "GC%ld: %d of %ld buffers are unchanged\n",
+	     gcs_done, unchanged_buffers, total_buffers);
+#endif    
   }
 
   sweep_vectors ();

=== modified file 'src/buffer.h'
--- src/buffer.h	2012-08-01 08:49:28 +0000
+++ src/buffer.h	2012-08-01 14:52:03 +0000
@@ -474,8 +474,18 @@
 
 /* Most code should use this macro to access Lisp fields in struct buffer.  */
 
+#ifdef EXPERIMENTAL_GC
+
+extern struct buffer * buffer_write_barrier (struct buffer *);
+
+#define BVAR(buf, field) (buffer_write_barrier (buf)->INTERNAL_FIELD (field))
+
+#else
+
 #define BVAR(buf, field) ((buf)->INTERNAL_FIELD (field))
 
+#endif /* EXPERIMENTAL_GC */
+
 /* This is the structure that the buffer Lisp object points to.  */
 
 struct buffer
@@ -851,6 +861,10 @@
   /* Position where the overlay lists are centered.  */
   ptrdiff_t overlay_center;
 
+#ifdef EXPERIMENTAL_GC
+  struct blockdata bd;
+#endif
+
   /* Changes in the buffer are recorded here for undo, and t means
      don't record anything.  This information belongs to the base
      buffer of an indirect buffer.  But we can't store it in the

=== modified file 'src/lisp.h'
--- src/lisp.h	2012-08-01 08:49:28 +0000
+++ src/lisp.h	2012-08-01 14:49:35 +0000
@@ -592,7 +592,28 @@
 
 /* Convenience macros for dealing with Lisp arrays.  */
 
+#ifdef EXPERIMENTAL_GC
+
+struct blockdata
+{
+  /* Non-zero if objects in this block are subject to mark.  */
+  unsigned mark : 1;
+
+  /* Non-zero if objects in this block are subject to sweep.  */
+  unsigned sweep : 1;
+};
+
+struct Lisp_Vector;
+extern struct Lisp_Vector * vector_write_barrier (struct Lisp_Vector *);
+
+#define AREF(ARRAY, IDX) vector_write_barrier (XVECTOR (ARRAY))->contents[IDX]
+
+#else
+
 #define AREF(ARRAY, IDX)	XVECTOR ((ARRAY))->contents[IDX]
+
+#endif /* EXPERIMENTAL_GC */
+
 #define ASIZE(ARRAY)		XVECTOR ((ARRAY))->header.size
 /* The IDX==IDX tries to detect when the macro argument is side-effecting.  */
 #define ASET(ARRAY, IDX, VAL)	\
@@ -671,6 +692,16 @@
 #define XCAR(c)	LISP_MAKE_RVALUE (XCAR_AS_LVALUE (c))
 #define XCDR(c) LISP_MAKE_RVALUE (XCDR_AS_LVALUE (c))
 
+#ifdef EXPERIMENTAL_GC
+
+extern void xsetcar (Lisp_Object, Lisp_Object);
+extern void xsetcdr (Lisp_Object, Lisp_Object);
+
+#define XSETCAR(c,n) xsetcar ((c), (n))
+#define XSETCDR(c,n) xsetcdr ((c), (n))
+
+#else /* not EXPERIMENTAL_GC */
+
 /* Use these to set the fields of a cons cell.
 
    Note that both arguments may refer to the same object, so 'n'
@@ -680,6 +711,8 @@
 #define XSETCAR(c,n) (XCAR_AS_LVALUE (c) = (n))
 #define XSETCDR(c,n) (XCDR_AS_LVALUE (c) = (n))
 
+#endif /* EXPERIMENTAL_GC */
+
 /* Take the car or cdr of something whose type is not known.  */
 #define CAR(c)					\
  (CONSP ((c)) ? XCAR ((c))			\
@@ -1047,8 +1080,18 @@
 /* Most code should use this macro to access
    Lisp fields in struct Lisp_Symbol.  */
 
+#ifdef EXPERIMENTAL_GC
+
+extern struct Lisp_Symbol * symbol_write_barrier (struct Lisp_Symbol *);
+
+#define SVAR(sym, field) (symbol_write_barrier (sym)->INTERNAL_FIELD (field))
+
+#else
+
 #define SVAR(sym, field) ((sym)->INTERNAL_FIELD (field))
 
+#endif /* not EXPERIMENTAL_GC */
+
 struct Lisp_Symbol
 {
   unsigned gcmarkbit : 1;


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 17:38       ` Tom Tromey
@ 2012-08-01 21:04         ` Paul Eggert
  2012-08-02  5:28         ` Stephen J. Turnbull
  1 sibling, 0 replies; 43+ messages in thread
From: Paul Eggert @ 2012-08-01 21:04 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Dmitry Antipov, emacs-devel

On 08/01/2012 10:38 AM, Tom Tromey wrote:
> FWIW I think it is an interesting project, and the problems are all
> surmountable.

The first step, which is relatively easy and should be done anyway,
is to use ASET (a, i, v) instead of AREF (a, i) = v when setting vectors,
as that's how ASET and AREF are supposed to be used.
I did that as trunk bzr 109381.  I created a new function aref_addr (a, i)
to substitute for "& AREF (a, i)" -- presumably the (rare)
calls to aref_addr will need special attention if write barriers
are implemented.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 12:04   ` Dmitry Antipov
  2012-08-01 14:58     ` Paul Eggert
  2012-08-01 15:01     ` Eli Zaretskii
@ 2012-08-01 23:52     ` Stefan Monnier
  2012-08-02  4:12       ` Dmitry Antipov
  2 siblings, 1 reply; 43+ messages in thread
From: Stefan Monnier @ 2012-08-01 23:52 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

>>> * src/frame.h (FVAR): New macro.
>> Is it really necessary?  To me this just obfuscates the code.
>> If/when it turns out to be needed, it'll be easy enough to introduce.
> I have no ideas why BVAR and KVAR was introduced, but my motivation is:

Then, please undo your changes.  The INTERNAL_FIELD part is fine, but
the new FVAR, WVAR, ... are not.  Maybe it can be useful as an
intermediate step on some separate generational-gc branch, but it
doesn't have its place in trunk: I can't think of any way to make such
macros give realistic performance with anything but a write-barrier, so
such macros will only ever be needed for write accesses and never for
read-accesses.
So you're obfuscating the read-accesses (i.e. the most common case) for
no good reason.
I'm OK with introducing such macros to *set* such fields (i.e. for write
barriers), but not to read them (at least not until there's a really
good case for them).


        Stefan



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 23:52     ` Stefan Monnier
@ 2012-08-02  4:12       ` Dmitry Antipov
  2012-08-02  5:56         ` Stephen J. Turnbull
                           ` (2 more replies)
  0 siblings, 3 replies; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-02  4:12 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On 08/02/2012 03:52 AM, Stefan Monnier wrote:

> Then, please undo your changes.  The INTERNAL_FIELD part is fine, but
> the new FVAR, WVAR, ... are not.  Maybe it can be useful as an
> intermediate step on some separate generational-gc branch, but it
> doesn't have its place in trunk:

Look at concurrency branch. Everyone agrees that this is an interesting
and useful feature, but no one wants to handle an endless merging efforts.
If we had the same amount of developers as involved in Linux kernel, it's
the only possible practice to maintain 100 branches or even separate
trees for each major feature; for us, everything which is not in trunk
is the candidate to throw and forget, and large amount of code increases
the probability of such an inglorious end.

> I can't think of any way to make such
> macros give realistic performance with anything but a write-barrier, so
> such macros will only ever be needed for write accesses and never for
> read-accesses.
> So you're obfuscating the read-accesses (i.e. the most common case) for
> no good reason.
> I'm OK with introducing such macros to *set* such fields (i.e. for write
> barriers), but not to read them (at least not until there's a really
> good case for them).

Really good case comes very quickly when you start the real debugging.
Things like FVAR are very helpful to trace _all_ accesses to Lisp_Object
members; when FVARs will be converted to rvalues and SETFVARs will be
used appropriately, this guarantees that no pointer stores bypasses
the barrier (just one such a store is fatal for the collector). Next,
when we will know that the collector invariant is never broken, it's
possible to replace these obfuscated FVAR (x, y) back to x->y.

Again, this is a kind of chicken-egg problem: it's very hard to design
GC bits without supporting infrastructure implemented, and no one wants
to deal with obfuscated internal things in the absence of visible
advantages provided by new GC. IMHO the only solution is to suffer
some obfuscation until it becomes really useful.

Dmitry



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 17:38       ` Tom Tromey
  2012-08-01 21:04         ` Paul Eggert
@ 2012-08-02  5:28         ` Stephen J. Turnbull
  1 sibling, 0 replies; 43+ messages in thread
From: Stephen J. Turnbull @ 2012-08-02  5:28 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Paul Eggert, Dmitry Antipov, emacs-devel

Tom Tromey writes:

 > FWIW I think it is an interesting project, and the problems are all
 > surmountable.

Surmounted, in XEmacs.  Ask Marcus Crestani <crestani@xemacs.org> for
details.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02  4:12       ` Dmitry Antipov
@ 2012-08-02  5:56         ` Stephen J. Turnbull
  2012-08-02  7:47           ` Dmitry Antipov
                             ` (2 more replies)
  2012-08-02 15:34         ` Eli Zaretskii
  2012-08-03  7:42         ` Stefan Monnier
  2 siblings, 3 replies; 43+ messages in thread
From: Stephen J. Turnbull @ 2012-08-02  5:56 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Stefan Monnier, emacs-devel

Dmitry Antipov writes:

 > Look at concurrency branch. Everyone agrees that this is an
 > interesting and useful feature,

I don't think that's true.  Emacs needs concurrency, it's true.  It's
not obvious that Emacs Lisp does.  Dynamic scope + concurrency =
nightmare.  You're not going to get RMS (or most Emacs developers) to
give up the former, so the latter is going to need to be seriously
restricted (eg, a GIL).  You're welcome to have a different opinion,
and obviously several people disagree with my assessment.  I'm not
going to argue that point.  But I suggest to you that one reason why
many people who might otherwise be interested in the concurrency
branch don't bother with it is that they agree with me, not you.

 > but no one wants to handle an endless merging efforts.  If we had
 > the same amount of developers as involved in Linux kernel,

It's not the number of developers, it's the customary discipline in
the community.  SXEmacs has a far smaller number of developers than
GNU Emacs does, but they branch like crazy and seem to love it.  Many
projects do.

Merging really isn't that bad if your architecture is designed for it
and your workflow adapted to it.  It's annoying, true, but far less so
than writing tests, or even documentation.

Not to say I don't understand your pain, just that Emacs *can* have an
effective branching-based workflow if Emacs wants it.  bzr is
certainly adequate for such a workflow.  However, bzr was selected
partly because certain folks with veto power didn't want that kind of
workflow for themselves, so making a change is going to take a while.

For you personally, why don't you talk to Miles (aka Mr. Lexbind) and
Eli (aka Mr. BIDI) and see if they have some hints for maintaining
one's own enthusiasm for working on a long-lived branch?  After all,
they did it successfully!  And talk to Eric Ludlam and friends and see
if CEDET has support for the kind of refactoring that you may need to
do, and the Bazaar develoeprs to see how they handle what git calls
re-re-re.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02  5:56         ` Stephen J. Turnbull
@ 2012-08-02  7:47           ` Dmitry Antipov
  2012-08-02  9:30             ` Juanma Barranquero
  2012-08-02 16:07             ` Eli Zaretskii
  2012-08-02 15:45           ` Eli Zaretskii
  2012-08-02 23:38           ` Richard Stallman
  2 siblings, 2 replies; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-02  7:47 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: Stefan Monnier, emacs-devel

On 08/02/2012 09:56 AM, Stephen J. Turnbull wrote:

>   > Look at concurrency branch. Everyone agrees that this is an
>   > interesting and useful feature,
>
> I don't think that's true.  Emacs needs concurrency, it's true.  It's
> not obvious that Emacs Lisp does.

Hm, I mean not only Lisp-level threads, but also implicit concurrency
like one thread per frame or similar things.

>   > but no one wants to handle an endless merging efforts.  If we had
>   > the same amount of developers as involved in Linux kernel,
>
> It's not the number of developers, it's the customary discipline in
> the community.  SXEmacs has a far smaller number of developers than
> GNU Emacs does, but they branch like crazy and seem to love it.  Many
> projects do.

I agree, but only when the feature is more or less isolated (like
BIDI, IIUC). Most probably new GC will introduce new limitations on
how the Lisp_Objects may be used, and, unfortunately, these limitations
should be enforced through the whole project _before_ new GC becomes
alive for the first time. For the particular write barriers case, just
one bypass is most likely to crash everything; so, barriers should be
designed and implemented first, and all developers should be encouraged
to remember about them and obey new limitations when writing new code
or fixing an old bugs. The only reliable way to do it is to have barriers
in the trunk (defined to zero-overhead no-ops in the default configuration,
of course).

> Merging really isn't that bad if your architecture is designed for it
> and your workflow adapted to it.

This is not the matter or _my_ architecture; current code base provides
very poor opportunities for any GC designer, and this should be changed
_before_ any useful GC improvements may be implemented. Everyone wants
a new house, but nobody wants to suffer the temporary inconveniences
connected with building; but (if the house is large enough) it's
practically impossible to build the house somewhere else and then
transport it to the final destination.

Dmitry




^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02  7:47           ` Dmitry Antipov
@ 2012-08-02  9:30             ` Juanma Barranquero
  2012-08-02 16:07             ` Eli Zaretskii
  1 sibling, 0 replies; 43+ messages in thread
From: Juanma Barranquero @ 2012-08-02  9:30 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Stephen J. Turnbull, Stefan Monnier, emacs-devel

On Thu, Aug 2, 2012 at 9:47 AM, Dmitry Antipov <dmantipov@yandex.ru> wrote:

> I agree, but only when the feature is more or less isolated (like
> BIDI, IIUC).

The unicode change was pervasive, and it was developed in parallel and
then merged. The merge was somewhat painful, but that pain would
likely not have been eased by developing the unicode stuff in the
trunk.

    Juanma



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-01 18:02       ` Dmitry Antipov
@ 2012-08-02 15:28         ` Eli Zaretskii
  0 siblings, 0 replies; 43+ messages in thread
From: Eli Zaretskii @ 2012-08-02 15:28 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

> Date: Wed, 01 Aug 2012 22:02:27 +0400
> From: Dmitry Antipov <dmantipov@yandex.ru>
> CC: emacs-devel@gnu.org
> 
> > May I suggest to post some kind of design notes, with some details
> > about the above?  I think such preliminary discussions help get all
> > the interested parties up to speed, raise some important issues that
> > are best discovered sooner rather than later, and generally avoid
> > surprises, pleasant or otherwise.
> 
> OK. There are some ideas to share now.

Thanks.

> 3. Premature optimization is the root of all evil. For the beginning,
> I'm trying to implement a hugely overestimated write barrier (e.g. a lot
> of pointer writes are really pointer reads). Of course, it will be notoriously
> slow.

If "notoriously slow" means slow to the degree that it would annoy
people, my suggestion is either do not commit that to the trunk, or
make it switchable (by an #ifdef or by a variable, preferably the
latter).  Otherwise, people will get annoyed and will bombard you with
bug reports, making development harder.

Having the new code switchable at run time is better because it lets
you easily check whether some bug is due to the new code or not.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02  4:12       ` Dmitry Antipov
  2012-08-02  5:56         ` Stephen J. Turnbull
@ 2012-08-02 15:34         ` Eli Zaretskii
  2012-08-03  7:42         ` Stefan Monnier
  2 siblings, 0 replies; 43+ messages in thread
From: Eli Zaretskii @ 2012-08-02 15:34 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: monnier, emacs-devel

> Date: Thu, 02 Aug 2012 08:12:29 +0400
> From: Dmitry Antipov <dmantipov@yandex.ru>
> Cc: emacs-devel@gnu.org
> 
> On 08/02/2012 03:52 AM, Stefan Monnier wrote:
> 
> > Then, please undo your changes.  The INTERNAL_FIELD part is fine, but
> > the new FVAR, WVAR, ... are not.  Maybe it can be useful as an
> > intermediate step on some separate generational-gc branch, but it
> > doesn't have its place in trunk:
> 
> Look at concurrency branch. Everyone agrees that this is an interesting
> and useful feature, but no one wants to handle an endless merging efforts.

I cannot speak for Tom and the concurrency branch, but in my
experience the merging is almost a non-issue.

> Again, this is a kind of chicken-egg problem: it's very hard to design
> GC bits without supporting infrastructure implemented, and no one wants
> to deal with obfuscated internal things in the absence of visible
> advantages provided by new GC. IMHO the only solution is to suffer
> some obfuscation until it becomes really useful.

In general, at least in this project, if a feature needs to be
developed incrementally over a significant time period, then it is
better to do it on a branch, and then merge it onto the trunk when it
is more or less ready and stable.  Experience taught me that this
paradigm minimizes friction with people who just want to track the
latest code, but not be alpha-testers for unstable new features in the
core that cannot be easily turned off.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02  5:56         ` Stephen J. Turnbull
  2012-08-02  7:47           ` Dmitry Antipov
@ 2012-08-02 15:45           ` Eli Zaretskii
  2012-08-02 21:28             ` Paul Eggert
  2012-08-02 23:38           ` Richard Stallman
  2 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-08-02 15:45 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: dmantipov, monnier, emacs-devel

> From: "Stephen J. Turnbull" <stephen@xemacs.org>
> Date: Thu, 02 Aug 2012 14:56:16 +0900
> Cc: Stefan Monnier <monnier@IRO.UMontreal.CA>, emacs-devel@gnu.org
> 
> For you personally, why don't you talk to Miles (aka Mr. Lexbind) and
> Eli (aka Mr. BIDI) and see if they have some hints for maintaining
> one's own enthusiasm for working on a long-lived branch?

My experience with this is that merging is not a problem at all.  I
just grepp'ed my .bzr.log files for the 2 years I developed bidi on a
branch, and found only 11 conflicts there.  Given that I was merging
from the trunk once a week, this number is all but negligible.

To be fair, I was mainly hacking a single source file (and another one
that didn't exist on the trunk, so it doesn't count).  But the same is
probably true for GC-related work: it mainly affects alloc.c, and
that's it.

So, all in all, I don't understand what's all the fuss about merging
nightmare.  For me, one of the main advantages of bzr (which is common
to all modern dVCSes) is the much smarter merging, with the result
that conflicts are almost non-existent.  I used to be petrified by
merges and branches when I used CVS; now I don't think twice when I
need to make a branch and work on it for a while.

Just try it.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02  7:47           ` Dmitry Antipov
  2012-08-02  9:30             ` Juanma Barranquero
@ 2012-08-02 16:07             ` Eli Zaretskii
  1 sibling, 0 replies; 43+ messages in thread
From: Eli Zaretskii @ 2012-08-02 16:07 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: stephen, monnier, emacs-devel

> Date: Thu, 02 Aug 2012 11:47:05 +0400
> From: Dmitry Antipov <dmantipov@yandex.ru>
> Cc: Stefan Monnier <monnier@IRO.UMontreal.CA>, emacs-devel@gnu.org
> 
> I agree, but only when the feature is more or less isolated (like
> BIDI, IIUC).

How can you consider "isolated" a feature that invades every little
corner of the Emacs display engine?  Can you imagine an Emacs with
broken redisplay being used by someone?

xdisp.c, the main source file that implements the display engine,
weighs in at almost 30K lines.  Given that size, the probability of
someone else fixing a bug in the same file is not negligible.  I just
counted several dozens of changes made in xdisp.c while I was working
on a branch.  And still the amount of clashes was small, see my other
mail.

> Most probably new GC will introduce new limitations on
> how the Lisp_Objects may be used, and, unfortunately, these limitations
> should be enforced through the whole project _before_ new GC becomes
> alive for the first time.

Once you make the initial pass over the sources and replace direct
access with getters and setters, the merges that will bring you code
that uses direct access will be few and far apart, since the bulk of
Emacs code doesn't change.  Moreover, the compiler will flag those
places right away.  So fixing the few build failures introduced by
merges should be simple and fast.  A few minutes devoted to that every
week or so is not a high price to pay.

> For the particular write barriers case, just
> one bypass is most likely to crash everything; so, barriers should be
> designed and implemented first, and all developers should be encouraged
> to remember about them and obey new limitations when writing new code
> or fixing an old bugs. The only reliable way to do it is to have barriers
> in the trunk (defined to zero-overhead no-ops in the default configuration,
> of course).

I don't think this will work, not in Emacs, anyway.  We don't have
here enough discipline or omniscient team leaders to enforce this kind
of order.  People _will_ do what you don't want them to, and they
_will_ bump into bugs, and then will blame you.

The trick I used to spare users from potentially unstable code (when I
merged the bidi branch onto the trunk, after 1.5 years of working
aside) was to have a variable, whose default was OFF, that allowed me
to switch the new code on or off.  After a while, a few well-meaning
people started running with that variable ON and reported the problems
they saw; but the vast majority of people who track the development
were never exposed to the bidi code, until I considered it stable
enough to be used by default.

This way (or something similar) will allow you to avoid annoying
people by unstable code.  So you could develop the entire thing on a
branch, until all of its main pieces are in place, then merge to the
trunk (perhaps after some peer review, to make sure the overall design
and implementation are good enough), and continue development and
debugging on the trunk, having the new code switched off by default
until it's deemed ready for prime time.

> This is not the matter or _my_ architecture; current code base provides
> very poor opportunities for any GC designer, and this should be changed
> _before_ any useful GC improvements may be implemented.

Then make these changes on a branch, one by one, until everything is
in place.

> Everyone wants a new house, but nobody wants to suffer the temporary
> inconveniences connected with building; but (if the house is large
> enough) it's practically impossible to build the house somewhere
> else and then transport it to the final destination.

What is impossible with houses, is fortunately possible with a dVCS ;-)



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02 15:45           ` Eli Zaretskii
@ 2012-08-02 21:28             ` Paul Eggert
  2012-08-03  6:27               ` Eli Zaretskii
  0 siblings, 1 reply; 43+ messages in thread
From: Paul Eggert @ 2012-08-02 21:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Stephen J. Turnbull, dmantipov, monnier, emacs-devel

On 08/02/2012 08:45 AM, Eli Zaretskii wrote:
> the same is
> probably true for GC-related work: it mainly affects alloc.c

I'm afraid not.  Dmitry is right: GC affects lots of files,
basically, anything that touches a data structure that might
be garbage-collected.

My experience with merging is closer to Dmitry's, I'm afraid.
It's no fun merging, say, the FVAR/WVAR/etc patches with the
inline-function patches that I have pending for post-24.2
<http://bugs.gnu.org/11935>.

It's not that it can't be done -- of course it can -- but it's
tedious and error-prone.  The FVAR/etc patches and the inline
patches are both pervasive, and so have many opportunities
to collide with each other.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02  5:56         ` Stephen J. Turnbull
  2012-08-02  7:47           ` Dmitry Antipov
  2012-08-02 15:45           ` Eli Zaretskii
@ 2012-08-02 23:38           ` Richard Stallman
  2 siblings, 0 replies; 43+ messages in thread
From: Richard Stallman @ 2012-08-02 23:38 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: dmantipov, monnier, emacs-devel

      Dynamic scope + concurrency = nightmare.

No it isn't.  The Lisp machine had dynamic scope and multiple threads.
You just have to swap stacks of bindings.

--
Dr Richard Stallman
President, Free Software Foundation
51 Franklin St
Boston MA 02110
USA
www.fsf.org  www.gnu.org
Skype: No way! That's nonfree (freedom-denying) software.
  Use Ekiga or an ordinary phone call



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02 21:28             ` Paul Eggert
@ 2012-08-03  6:27               ` Eli Zaretskii
  2012-08-03  6:52                 ` Paul Eggert
  0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-08-03  6:27 UTC (permalink / raw)
  To: Paul Eggert; +Cc: stephen, dmantipov, monnier, emacs-devel

> Date: Thu, 02 Aug 2012 14:28:43 -0700
> From: Paul Eggert <eggert@cs.ucla.edu>
> CC: "Stephen J. Turnbull" <stephen@xemacs.org>, dmantipov@yandex.ru, 
>  monnier@IRO.UMontreal.CA, emacs-devel@gnu.org
> 
> On 08/02/2012 08:45 AM, Eli Zaretskii wrote:
> > the same is
> > probably true for GC-related work: it mainly affects alloc.c
> 
> I'm afraid not.  Dmitry is right: GC affects lots of files,
> basically, anything that touches a data structure that might
> be garbage-collected.
> 
> My experience with merging is closer to Dmitry's, I'm afraid.
> It's no fun merging, say, the FVAR/WVAR/etc patches with the
> inline-function patches that I have pending for post-24.2
> <http://bugs.gnu.org/11935>.

Mega changes such as FVAR/WVAR/etc should be treated as outliers in
this statistics.  (One more reason to avoid them if at all possible,
btw.)

> It's not that it can't be done -- of course it can -- but it's
> tedious and error-prone.  The FVAR/etc patches and the inline
> patches are both pervasive, and so have many opportunities
> to collide with each other.

Again, let's not build card towers from a single extreme case.

Anyway, I gave numbers for my experience.  It would be good to see
yours, or someone else's.  It's all there in your ~/.bzr.log file, so
just grep it and tell how many conflicts you had in your merges, and
not just for the last FVAR/etc incident.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-03  6:27               ` Eli Zaretskii
@ 2012-08-03  6:52                 ` Paul Eggert
  0 siblings, 0 replies; 43+ messages in thread
From: Paul Eggert @ 2012-08-03  6:52 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: stephen, dmantipov, monnier, emacs-devel

On 08/02/2012 11:27 PM, Eli Zaretskii wrote:
> It's all there in your ~/.bzr.log file, so
> just grep it and tell how many conflicts you had in your merges

OK, here are my bzr conflict statistics for yesterday
(all were Emacs conflicts):

.bzr.log:13553:[ 7812] 2012-08-01 14:11:26.630 INFO: 5 conflicts encountered.   
.bzr.log:14918:[ 8983] 2012-08-01 15:28:13.254 INFO: 2 conflicts encountered.   
.bzr.log:15448:[16729] 2012-08-01 16:14:31.362 INFO: 1 conflicts encountered.   
.bzr.log:15644:[16751] 2012-08-01 16:16:06.115 INFO: 11 conflicts encountered.  
.bzr.log:15873:[16776] 2012-08-01 16:18:16.765 INFO: 5 conflicts encountered.   
.bzr.log:16824:[ 6817] 2012-08-01 19:08:41.422 INFO: 1 conflicts encountered.   
.bzr.log:17425:[30769] 2012-08-01 21:15:16.737 INFO: 1 conflicts encountered.   
.bzr.log:17811:[24363] 2012-08-01 23:23:15.386 INFO: 4 conflicts encountered.   
.bzr.log:17875:[24505] 2012-08-01 23:24:07.525 INFO: 5 conflicts encountered.   
.bzr.log:18569:[25094] 2012-08-01 23:52:10.131 INFO: 2 conflicts encountered.   

The worst one was a conflict that bzr didn't catch, and which
caused Emacs to crash afterwards.

Yesterday was high -- a more typical day I'll get five or ten conflicts.
But clearly our experiences differ, if you're getting only five
conflicts per year.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-02  4:12       ` Dmitry Antipov
  2012-08-02  5:56         ` Stephen J. Turnbull
  2012-08-02 15:34         ` Eli Zaretskii
@ 2012-08-03  7:42         ` Stefan Monnier
  2012-08-03  8:31           ` Dmitry Antipov
  2012-08-08  3:39           ` Chong Yidong
  2 siblings, 2 replies; 43+ messages in thread
From: Stefan Monnier @ 2012-08-03  7:42 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

> the barrier (just one such a store is fatal for the collector). Next,
> when we will know that the collector invariant is never broken, it's
> possible to replace these obfuscated FVAR (x, y) back to x->y.

You can use coccinelle to automatically turn the x->y into an rvalue
FVAR (x,y) while debugging.  And such a script should be kept around and
run every once in a while to check that new code follows the
SETFVAR convention.

But I don't want the trunk's code obfuscated just for some temporary
debugging needs.


        Stefan



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-03  7:42         ` Stefan Monnier
@ 2012-08-03  8:31           ` Dmitry Antipov
  2012-08-03 18:58             ` Paul Eggert
  2012-08-03 22:50             ` Stefan Monnier
  2012-08-08  3:39           ` Chong Yidong
  1 sibling, 2 replies; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-03  8:31 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On 08/03/2012 11:42 AM, Stefan Monnier wrote:

>> the barrier (just one such a store is fatal for the collector). Next,
>> when we will know that the collector invariant is never broken, it's
>> possible to replace these obfuscated FVAR (x, y) back to x->y.
>
> You can use coccinelle to automatically turn the x->y into an rvalue
> FVAR (x,y) while debugging.  And such a script should be kept around and
> run every once in a while to check that new code follows the
> SETFVAR convention.
>
> But I don't want the trunk's code obfuscated just for some temporary
> debugging needs.

Have you tried to use coccinelle? As I have said, it's not a silver bullet
(yet), and it's just impossible to handle such a stuff in fully automated
mode. There are special cases that should be handled manually, and doing
them over and over again is much worse than even an endless merging.

And I still don't see an answer to the simplest possible question: why
(F|W)VARs are so bad but (B|K)VARs are OK?

Dmitry




^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-03  8:31           ` Dmitry Antipov
@ 2012-08-03 18:58             ` Paul Eggert
  2012-08-03 22:52               ` Stefan Monnier
  2012-08-05 14:59               ` Dmitry Antipov
  2012-08-03 22:50             ` Stefan Monnier
  1 sibling, 2 replies; 43+ messages in thread
From: Paul Eggert @ 2012-08-03 18:58 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Stefan Monnier, emacs-devel

On 08/03/2012 01:31 AM, Dmitry Antipov wrote:
> why (F|W)VARs are so bad but (B|K)VARs are OK?

The short answer is they're all bad.  :-)

FVAR is bad partly because it has the syntax of a C function,
but not the semantics; it cannot be implemented as a function.
How about if we compromise by switching to functional notation?
That should be easier to read.  That is, instead of this:

  return XFRAME (frame)->buffer_list;

or this:

  return FVAR (XFRAME (frame), buffer_list);

we write this:

  return frame_buffer_list (XFRAME (frame));

Also, instead instead of this:

  f->buffer_list = Fcons (buf, Qnil);

or this:

  FVAR (f, buffer_list) = Fcons (buf, Qnil);

we write this:

  set_frame_buffer_list (f, Fcons (buf, Qnil));

We needn't use capital letters for the functions, since they
can be implemented as true functions (inline, so that the
code is just as fast as before).  This will help readability
too.

Doing this will give us the opportunity to instrument all accesses
to the buffer_list member of frames.  It's a bit more complicated
in the .h file, but it makes the rest of the code easier to read
than FVAR does.

Similarly for WVAR, etc.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-03  8:31           ` Dmitry Antipov
  2012-08-03 18:58             ` Paul Eggert
@ 2012-08-03 22:50             ` Stefan Monnier
  2012-08-03 23:11               ` Wojciech Meyer
  1 sibling, 1 reply; 43+ messages in thread
From: Stefan Monnier @ 2012-08-03 22:50 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

>>> the barrier (just one such a store is fatal for the collector). Next,
>>> when we will know that the collector invariant is never broken, it's
>>> possible to replace these obfuscated FVAR (x, y) back to x->y.
>> You can use coccinelle to automatically turn the x->y into an rvalue
>> FVAR (x,y) while debugging.  And such a script should be kept around and
>> run every once in a while to check that new code follows the
>> SETFVAR convention.
>> But I don't want the trunk's code obfuscated just for some temporary
>> debugging needs.
> Have you tried to use coccinelle? As I have said, it's not a silver bullet
> (yet), and it's just impossible to handle such a stuff in fully automated
> mode.  There are special cases that should be handled manually, and doing
> them over and over again is much worse than even an endless merging.

If we want to use "foo->bar" in the end code, then we will need to solve
this problem anyway (since, as mentioned, we'll need to check every once
in a while that "foo->bar" is only used for rvalues).

> And I still don't see an answer to the simplest possible question: why
> (F|W)VARs are so bad but (B|K)VARs are OK?

I don't actually think that BVAR/KVAR are OK either.


        Stefan



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-03 18:58             ` Paul Eggert
@ 2012-08-03 22:52               ` Stefan Monnier
  2012-08-04 16:31                 ` Paul Eggert
  2012-08-05 14:59               ` Dmitry Antipov
  1 sibling, 1 reply; 43+ messages in thread
From: Stefan Monnier @ 2012-08-03 22:52 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Dmitry Antipov, emacs-devel

>   return frame_buffer_list (XFRAME (frame));

And then we have to remember that it's a "trivial" function that
can't GC?  No, I don't like that at all.
"foo->buffer_list" is clear, concise and does just what we want.


        Stefan



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-03 22:50             ` Stefan Monnier
@ 2012-08-03 23:11               ` Wojciech Meyer
  0 siblings, 0 replies; 43+ messages in thread
From: Wojciech Meyer @ 2012-08-03 23:11 UTC (permalink / raw)
  To: emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

>>>> the barrier (just one such a store is fatal for the collector). Next,
>>>> when we will know that the collector invariant is never broken, it's
>>>> possible to replace these obfuscated FVAR (x, y) back to x->y.
>>> You can use coccinelle to automatically turn the x->y into an rvalue
>>> FVAR (x,y) while debugging.  And such a script should be kept around and
>>> run every once in a while to check that new code follows the
>>> SETFVAR convention.
>>> But I don't want the trunk's code obfuscated just for some temporary
>>> debugging needs.
>> Have you tried to use coccinelle? As I have said, it's not a silver bullet
>> (yet), and it's just impossible to handle such a stuff in fully automated
>> mode.  There are special cases that should be handled manually, and doing
>> them over and over again is much worse than even an endless merging.
>
> If we want to use "foo->bar" in the end code, then we will need to solve
> this problem anyway (since, as mentioned, we'll need to check every once
> in a while that "foo->bar" is only used for rvalues).

How about using MELT or Clang to rewrite the relevant AST patterns into
something you want at the compile time? Alternatively you could use some
other frontend like CIL, or just do the source to source transformation
similarly to what you have done already with coccinelle.

--
Wojciech




^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-03 22:52               ` Stefan Monnier
@ 2012-08-04 16:31                 ` Paul Eggert
  2012-08-05 15:03                   ` Dmitry Antipov
  0 siblings, 1 reply; 43+ messages in thread
From: Paul Eggert @ 2012-08-04 16:31 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Dmitry Antipov, emacs-devel

On 08/03/2012 03:52 PM, Stefan Monnier wrote:
>>   return frame_buffer_list (XFRAME (frame));
> And then we have to remember that it's a "trivial" function that
> can't GC? 

I can see disliking "frame_buffer_list (FOO)" (as opposed
to "FOO->buffer_list") on length grounds, but I don't understand
disliking it on GC grounds.  The Emacs internals have
lots of functions that don't call the GC; having some
more shouldn't make that much difference one way or another.

If there's a need to more easily distinguish between functions
that call the GC, and functions that don't, there are good
ways to do that -- perhaps Emacs could be taught to highlight
one set of functions and not the other, or we could even institute
a naming convention.  But surely it goes too far to suppress
functional notation merely because some functions call the garbage
collector and others don't.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-03 18:58             ` Paul Eggert
  2012-08-03 22:52               ` Stefan Monnier
@ 2012-08-05 14:59               ` Dmitry Antipov
  2012-08-05 15:23                 ` Paul Eggert
  1 sibling, 1 reply; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-05 14:59 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Stefan Monnier, emacs-devel

On 08/03/2012 10:58 PM, Paul Eggert wrote:

>> why (F|W)VARs are so bad but (B|K)VARs are OK?
>
> The short answer is they're all bad.  :-)
>
> FVAR is bad partly because it has the syntax of a C function,
> but not the semantics; it cannot be implemented as a function.

Why this is a problem ever? OK, maybe AREF and ASET are better;
but the only way to implement FVARs as functions is to have
array of Lisp_Objects in struct frame and meaningful indexes
for the particular slots, i.e.

enum frame_slots
   {
     NAME,
     ICON_NAME,
     TITLE
     ...
   };

I don't like this, and most probably others will not like it too.

> How about if we compromise by switching to functional notation?
> That should be easier to read.  That is, instead of this:
>
>    return XFRAME (frame)->buffer_list;
>
> or this:
>
>    return FVAR (XFRAME (frame), buffer_list);
>
> we write this:
>
>    return frame_buffer_list (XFRAME (frame));
>
> Also, instead instead of this:
>
>    f->buffer_list = Fcons (buf, Qnil);
>
> or this:
>
>    FVAR (f, buffer_list) = Fcons (buf, Qnil);
>
> we write this:
>
>    set_frame_buffer_list (f, Fcons (buf, Qnil));

IMHO this is just a poor copy of C++ class :-(:
if you have a huge class with 50 private members, you're
enforced to have 50 get_xxx and 50 set_xxx member functions.
Most of them are inline and fast, but, (IMHO again) they
do not improve readability and makes sense only if you have
a huge class hierarchies where the fine-granted member access
control is very important for some another reason.

Dmitry



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-04 16:31                 ` Paul Eggert
@ 2012-08-05 15:03                   ` Dmitry Antipov
  2012-08-06 10:54                     ` Stefan Monnier
  0 siblings, 1 reply; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-05 15:03 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Stefan Monnier, emacs-devel

On 08/04/2012 08:31 PM, Paul Eggert wrote:

> On 08/03/2012 03:52 PM, Stefan Monnier wrote:
>>>    return frame_buffer_list (XFRAME (frame));
>> And then we have to remember that it's a "trivial" function that
>> can't GC?
>
> I can see disliking "frame_buffer_list (FOO)" (as opposed
> to "FOO->buffer_list") on length grounds, but I don't understand
> disliking it on GC grounds.  The Emacs internals have
> lots of functions that don't call the GC; having some
> more shouldn't make that much difference one way or another.

I believe that one of the goals for new GC should be the possibility
to run from almost any context, with a few exceptions like signal handlers.

Dmitry




^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-05 14:59               ` Dmitry Antipov
@ 2012-08-05 15:23                 ` Paul Eggert
  2012-08-05 20:29                   ` Miles Bader
  0 siblings, 1 reply; 43+ messages in thread
From: Paul Eggert @ 2012-08-05 15:23 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Stefan Monnier, emacs-devel

On 08/05/2012 06:59 AM, Dmitry Antipov wrote:
> if you have a huge class with 50 private members, you're
> enforced to have 50 get_xxx and 50 set_xxx member functions.
> Most of them are inline and fast,
They're *all* inline and fast, unless we put
hooks in them that make them slow.

The creation of the getter and setter methods
is mechanical and can be automated if need be,
so that's not really an obstacle.  The important
thing here is the readability of the use of these
constructs; their definition is secondary.

The main issue is readability.  I find it more
readable when the notation "f (x)" in ordinary C code
means that F is a function, instead of some other
construct that cannot possibly be a function.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-05 15:23                 ` Paul Eggert
@ 2012-08-05 20:29                   ` Miles Bader
  0 siblings, 0 replies; 43+ messages in thread
From: Miles Bader @ 2012-08-05 20:29 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Dmitry Antipov, Stefan Monnier, emacs-devel

Paul Eggert <eggert@cs.ucla.edu> writes:
> The main issue is readability.  I find it more
> readable when the notation "f (x)" in ordinary C code
> means that F is a function, instead of some other
> construct that cannot possibly be a function.

The convention that an UPPERCASE name means "macro with possibly
non-function-like semantics" is a very well established idiom in C
tho...

-miles

-- 
Cynic, n. A blackguard whose faulty vision sees things as they are, not as
they ought to be. Hence the custom among the Scythians of plucking out a
cynic's eyes to improve his vision.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-05 15:03                   ` Dmitry Antipov
@ 2012-08-06 10:54                     ` Stefan Monnier
  2012-08-06 11:44                       ` Dmitry Antipov
  0 siblings, 1 reply; 43+ messages in thread
From: Stefan Monnier @ 2012-08-06 10:54 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Paul Eggert, emacs-devel

> I believe that one of the goals for new GC should be the possibility
> to run from almost any context, with a few exceptions like signal handlers.

I want the C part of Emacs to look like C code.  So, if the
structure-field access does not require extra machinery (i.e. no read
barrier), I want to write it "foo->bar".

If we want to make sure that the write-barrier is used everywhere where
it's needed, than we need to find a way to check this with some tool.
Such a tool might require some extra annotations in the source code, and
I'm willing to accept some such things, but I'd much rather avoid
"FVAR (foo, bar)" if at all possible.

If tools like coccinelle have trouble finding the right "foo->bar", then
maybe we can try to find some coding convention that helps coccinelle
find the right spots.  Or find some other tool that can do those checks
for us.

E.g. maybe using "foo->_bar" would let us use as simple a tool as "sed"
to rewrite "foo->_bar" into "RVALUE_FIELD (foo, bar)" when we need/want
to run those static checks.


        Stefan



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-06 10:54                     ` Stefan Monnier
@ 2012-08-06 11:44                       ` Dmitry Antipov
  2012-08-06 16:31                         ` Stefan Monnier
  2012-08-08  7:22                         ` Chong Yidong
  0 siblings, 2 replies; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-06 11:44 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Paul Eggert, emacs-devel

On 08/06/2012 02:54 PM, Stefan Monnier wrote:

> I want the C part of Emacs to look like C code.  So, if the
> structure-field access does not require extra machinery (i.e. no read
> barrier), I want to write it "foo->bar".

I (and I hope all others) too. But we do AREF and ASET for vectors,
thinking about that vector implementation may be changed so direct access
to 'contents' becomes invalid or nonsense. So, I think that xGET and xSET
for complex structures fits this approach and don't add too much obfuscation.

Moreover, C itself is not designed to provide GC, and GC-aware system is
"unusual" C program. So, I don't see a problem if such a program contains
some "unusual" constructs which aren't quite similar to a core language.
Оn the contrary, this sets a good point for a newcomer: "look at these
strange things, they're implemented in a such unusual way because they're
really important, you should understand it before you write something".

> If we want to make sure that the write-barrier is used everywhere where
> it's needed, than we need to find a way to check this with some tool.
> Such a tool might require some extra annotations in the source code, and
> I'm willing to accept some such things, but I'd much rather avoid
> "FVAR (foo, bar)" if at all possible.
>
> If tools like coccinelle have trouble finding the right "foo->bar", then
> maybe we can try to find some coding convention that helps coccinelle
> find the right spots.  Or find some other tool that can do those checks
> for us.

Development (and politics) is the art of the possible, and we have those
tools which are. I investigated this area, and I believe that coccinelle
is good enough to be used in our work; finally, I don't see the practical
reasons to wait until someone develops a wunderwaffe like GCC plugin
for automatic barrier insertion on any critical pointer stores.

Dmitry





^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-06 11:44                       ` Dmitry Antipov
@ 2012-08-06 16:31                         ` Stefan Monnier
  2012-08-06 17:43                           ` Stefan Monnier
  2012-08-08  7:22                         ` Chong Yidong
  1 sibling, 1 reply; 43+ messages in thread
From: Stefan Monnier @ 2012-08-06 16:31 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Paul Eggert, emacs-devel

>> I want the C part of Emacs to look like C code.  So, if the
>> structure-field access does not require extra machinery (i.e. no read
>> barrier), I want to write it "foo->bar".
> I (and I hope all others) too. But we do AREF and ASET for vectors,
> thinking about that vector implementation may be changed so direct access
> to 'contents' becomes invalid or nonsense.

No, AREF is just convenience a macro (from where I stand), like
XCAR/XCDR.

> Development (and politics) is the art of the possible, and we have those
> tools which are. I investigated this area, and I believe that coccinelle
> is good enough to be used in our work; finally, I don't see the practical
> reasons to wait until someone develops a wunderwaffe like GCC plugin
> for automatic barrier insertion on any critical pointer stores.

I'm not sure whether you're saying that Coccinelle is good enough to
solve the problem I want solved (i.e. like me write "foo->bar" and turn
it into "RVALUE_FIELD (foo, bar)" when I need to check correct insertion
of write barriers).
If it is, that's great.


        Stefan



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-06 16:31                         ` Stefan Monnier
@ 2012-08-06 17:43                           ` Stefan Monnier
  0 siblings, 0 replies; 43+ messages in thread
From: Stefan Monnier @ 2012-08-06 17:43 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Paul Eggert, emacs-devel

> No, AREF is just convenience a macro (from where I stand), like
> XCAR/XCDR.

E.g. notice how they don't take a struct-field-name as argument.


        Stefan



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-03  7:42         ` Stefan Monnier
  2012-08-03  8:31           ` Dmitry Antipov
@ 2012-08-08  3:39           ` Chong Yidong
  2012-08-08  7:14             ` Dmitry Antipov
  2012-08-08 12:41             ` Stefan Monnier
  1 sibling, 2 replies; 43+ messages in thread
From: Chong Yidong @ 2012-08-08  3:39 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Dmitry Antipov, emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

> You can use coccinelle to automatically turn the x->y into an rvalue
> FVAR (x,y) while debugging.  And such a script should be kept around and
> run every once in a while to check that new code follows the
> SETFVAR convention.
>
> But I don't want the trunk's code obfuscated just for some temporary
> debugging needs.

Another problem, which I haven't seen mentioned in this thread, is that
when you see C code which does FVAR (x, y) the natural assumption is
that x and y are C variables.  So these macros hurt code readability.

The introduction of BVAR also violated this principle, and I'm not eager
to see the problem compounded.

I think FSET/WSET/PSET/PGET/etc should be removed from the trunk, at
least for now.  I recommend moving the generational GC work to a branch.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-08  3:39           ` Chong Yidong
@ 2012-08-08  7:14             ` Dmitry Antipov
  2012-08-08  7:46               ` Chong Yidong
  2012-08-08 12:41             ` Stefan Monnier
  1 sibling, 1 reply; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-08  7:14 UTC (permalink / raw)
  To: Chong Yidong; +Cc: Stefan Monnier, emacs-devel

On 08/08/2012 07:39 AM, Chong Yidong wrote:

> Another problem, which I haven't seen mentioned in this thread, is that
> when you see C code which does FVAR (x, y) the natural assumption is
> that x and y are C variables.  So these macros hurt code readability.
>
> The introduction of BVAR also violated this principle, and I'm not eager
> to see the problem compounded.

It looks like we should think about how to redesign BVARs and KVARs so
that it should be suitable both for GC and concurrency development.

> I think FSET/WSET/PSET/PGET/etc should be removed from the trunk, at
> least for now.  I recommend moving the generational GC work to a branch.

Look at the size of changes I did just for a few days. This is just a
preliminary changes needed to implement write barriers on top of them.
Each pointer store is a subject to handle; most probably each source
file will be affected. I suppose that new GC tree will look so different
so the final merge will be a tremendous task on a few weeks. So I'm
thinking about 2-stage approach: preliminary work is in trunk (where
it might be used for concurrency branch and other development), and
new GC (barriers and core GC bits) is in branch.

Dmitry




^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-06 11:44                       ` Dmitry Antipov
  2012-08-06 16:31                         ` Stefan Monnier
@ 2012-08-08  7:22                         ` Chong Yidong
  1 sibling, 0 replies; 43+ messages in thread
From: Chong Yidong @ 2012-08-08  7:22 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Paul Eggert, Stefan Monnier, emacs-devel

Dmitry Antipov <dmantipov@yandex.ru> writes:

> Development (and politics) is the art of the possible, and we have those
> tools which are. I investigated this area, and I believe that coccinelle
> is good enough to be used in our work; finally, I don't see the practical
> reasons to wait until someone develops a wunderwaffe like GCC plugin
> for automatic barrier insertion on any critical pointer stores.

Absolutely, but that does not mean this has to be done in the
development trunk for what is supposed to go into Emacs 24.2.  Yes,
we've stated that the trunk is open for new features, but there's no
conceivable universe in which a generational GC will be ready for 24.2.
So even if these macros ultimately prove necessary, right now it's doing
nothing but introducing lots of code churn that does nothing but hamper
bugfixing by making it difficult to compare 24.1 and 24.2 code.

I see that you got rid of FGET, PGET and WGET, presumably in response
due to Stefan's concerns (with which I agree).  I think the FSET, WSET
etc. macros are similarly inappropriate, and should also be reverted.
Will you do so?

This work is best done in a branch.  After all, the *GET/*SET macros are
straightforward to apply again once we need them.  Working in a branch
will also let you get more quickly to the problem of the GC itself,
which is presumably the non-trivial part.



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-08  7:14             ` Dmitry Antipov
@ 2012-08-08  7:46               ` Chong Yidong
  2012-08-08 10:18                 ` Dmitry Antipov
  0 siblings, 1 reply; 43+ messages in thread
From: Chong Yidong @ 2012-08-08  7:46 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Stefan Monnier, emacs-devel

Dmitry Antipov <dmantipov@yandex.ru> writes:

>> I think FSET/WSET/PSET/PGET/etc should be removed from the trunk, at
>> least for now.  I recommend moving the generational GC work to a branch.
>
> Look at the size of changes I did just for a few days. This is just a
> preliminary changes needed to implement write barriers on top of them.
> Each pointer store is a subject to handle; most probably each source
> file will be affected. I suppose that new GC tree will look so different
> so the final merge will be a tremendous task on a few weeks. So I'm
> thinking about 2-stage approach: preliminary work is in trunk (where
> it might be used for concurrency branch and other development), and
> new GC (barriers and core GC bits) is in branch.

Isn't the point of Coccinelle to make it possible to transform the code
with minimal manual intervention?  With the Coccinelle scripts you've
written and committed, it shouldn't matter *when* we pull the trigger to
transform the direct accesses into *VAR macros.  This will mitigate the
problem that "new GC tree will look so different so the final merge will
be a tremendous task".  If the new GC tree starts out with the same code
transformations, the merge would involve running Coccinelle on the old
tree, then doing a diff between the result and the GC branch.

Obviously, you've been the one doing all the heavy lifting on this task,
so maybe this is an over-simplification.  But if running the Coccinelle
scripts is straightforward enough, I really think it would be better to
postphone implementing its changes on the actual code in the trunk.

By the way, would you eventually need a macro for the common Vfoo = bar
case?



^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-08  7:46               ` Chong Yidong
@ 2012-08-08 10:18                 ` Dmitry Antipov
  0 siblings, 0 replies; 43+ messages in thread
From: Dmitry Antipov @ 2012-08-08 10:18 UTC (permalink / raw)
  To: Chong Yidong; +Cc: Stefan Monnier, emacs-devel

On 08/08/2012 11:46 AM, Chong Yidong wrote:

> Isn't the point of Coccinelle to make it possible to transform the code
> with minimal manual intervention?

YMMV - now it just refuses to parse the whole xdisp.c :-(.

> With the Coccinelle scripts you've
> written and committed, it shouldn't matter *when* we pull the trigger to
> transform the direct accesses into *VAR macros.

A lot of other pointers should be considered because not all pointers
to collectable objects are represented by Lisp_Objects.

> This will mitigate the
> problem that "new GC tree will look so different so the final merge will
> be a tremendous task".  If the new GC tree starts out with the same code
> transformations, the merge would involve running Coccinelle on the old
> tree, then doing a diff between the result and the GC branch.

Will look at further development of coccinelle; I don't believe that
this is possible just now.

> By the way, would you eventually need a macro for the common Vfoo = bar
> case?

Will see; I started from large objects with complex layout to hit all
possible difficulties at the very beginning.

Dmitry





^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames.
  2012-08-08  3:39           ` Chong Yidong
  2012-08-08  7:14             ` Dmitry Antipov
@ 2012-08-08 12:41             ` Stefan Monnier
  1 sibling, 0 replies; 43+ messages in thread
From: Stefan Monnier @ 2012-08-08 12:41 UTC (permalink / raw)
  To: Chong Yidong; +Cc: Dmitry Antipov, emacs-devel

> Another problem, which I haven't seen mentioned in this thread, is that
> when you see C code which does FVAR (x, y) the natural assumption is
> that x and y are C variables.  So these macros hurt code readability.

> The introduction of BVAR also violated this principle, and I'm not eager
> to see the problem compounded.

Yes, we should see about fixing this problem.

> I think FSET/WSET/PSET/PGET/etc should be removed from the trunk, at
> least for now.  I recommend moving the generational GC work to a branch.

I'm OK with keeping macros for the assignments.  But I'd like to hear
suggestions to reduce/eliminate the problem you mention (of field names
looking like variables).
Depending on the write-barrier, "FSET (foo->bar, val)" can be used, but
most write-barriers want to access other parts of "foo" rather than only
"foo->bar".
Maybe SET_FIELD (foo, bar, val) would be slightly better: "bar" still
looks like a variable, but at least the macro name hints at the fact
that there's a field somewhere in there.

> Isn't the point of Coccinelle to make it possible to transform the code
> with minimal manual intervention?

IIUC Coccinelle helps the work, but there is still a fair bit of manual
intervention needed afterwards, so it's not quite that simple.


        Setfan



^ permalink raw reply	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2012-08-08 12:41 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <E1SwCK8-0001PC-3m@vcs.savannah.gnu.org>
2012-08-01 10:33 ` [Emacs-diffs] /srv/bzr/emacs/trunk r109327: Generalize INTERNAL_FIELD between buffers, keyboards and frames Stefan Monnier
2012-08-01 12:04   ` Dmitry Antipov
2012-08-01 14:58     ` Paul Eggert
2012-08-01 16:52       ` Dmitry Antipov
2012-08-01 17:38       ` Tom Tromey
2012-08-01 21:04         ` Paul Eggert
2012-08-02  5:28         ` Stephen J. Turnbull
2012-08-01 15:01     ` Eli Zaretskii
2012-08-01 18:02       ` Dmitry Antipov
2012-08-02 15:28         ` Eli Zaretskii
2012-08-01 23:52     ` Stefan Monnier
2012-08-02  4:12       ` Dmitry Antipov
2012-08-02  5:56         ` Stephen J. Turnbull
2012-08-02  7:47           ` Dmitry Antipov
2012-08-02  9:30             ` Juanma Barranquero
2012-08-02 16:07             ` Eli Zaretskii
2012-08-02 15:45           ` Eli Zaretskii
2012-08-02 21:28             ` Paul Eggert
2012-08-03  6:27               ` Eli Zaretskii
2012-08-03  6:52                 ` Paul Eggert
2012-08-02 23:38           ` Richard Stallman
2012-08-02 15:34         ` Eli Zaretskii
2012-08-03  7:42         ` Stefan Monnier
2012-08-03  8:31           ` Dmitry Antipov
2012-08-03 18:58             ` Paul Eggert
2012-08-03 22:52               ` Stefan Monnier
2012-08-04 16:31                 ` Paul Eggert
2012-08-05 15:03                   ` Dmitry Antipov
2012-08-06 10:54                     ` Stefan Monnier
2012-08-06 11:44                       ` Dmitry Antipov
2012-08-06 16:31                         ` Stefan Monnier
2012-08-06 17:43                           ` Stefan Monnier
2012-08-08  7:22                         ` Chong Yidong
2012-08-05 14:59               ` Dmitry Antipov
2012-08-05 15:23                 ` Paul Eggert
2012-08-05 20:29                   ` Miles Bader
2012-08-03 22:50             ` Stefan Monnier
2012-08-03 23:11               ` Wojciech Meyer
2012-08-08  3:39           ` Chong Yidong
2012-08-08  7:14             ` Dmitry Antipov
2012-08-08  7:46               ` Chong Yidong
2012-08-08 10:18                 ` Dmitry Antipov
2012-08-08 12:41             ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).