unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Finding objects on C stack - alternate GCPRO
@ 2011-11-16 10:07 Dmitry Antipov
  2011-11-16 10:18 ` Helmut Eller
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Dmitry Antipov @ 2011-11-16 10:07 UTC (permalink / raw)
  To: emacs-devel

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

Everyone agrees that GGPROs are ugly and painful. On the other side,
current C stack marking code introduces substantial overhead by
maintaining red-black tree. And, since C stack marking is
conservative, it becomes very tricky to implement GC that may
relocate live objects (copying or compacting approach).

But there is another method to implement GCPROs. It looks not very
portable beyond GNU C since it uses __attribute__ ((cleanup (function)))
and compound statement expressions C extensions. But it doesn't
require UNGCPRO and dumbs like 'struct gcpro gcpro1, struct gcpro2, ...'.
And I believe it should work across longjmps.

This idea is briefly illustrated by an attached example. As for the
Emacs, it would be enough to declare every local Lisp_Object which
should survive the GC with the stuff like FOOPTR from this example,
and we're ready for exact C stack marking with (hopefully) very small
overhead.

Dmitry

[-- Attachment #2: cleanup.c --]
[-- Type: text/plain, Size: 1906 bytes --]

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  int x;
  int y;
} foo_t;

typedef struct gcpro {
  void *addr;
  struct gcpro *next;
} gcpro_t;

gcpro_t *foo_root;

static foo_t * foo_add (gcpro_t *fl, void *fooaddr)
{
  /* printf ("New local var at %p\n", fooaddr); */
  fl->addr = fooaddr;
  fl->next = foo_root;
  foo_root = fl;
  return NULL;
}

static void foo_remove (void *fooaddr)
{
  /* printf ("Drop local var at %p\n", fooaddr); */
  if (fooaddr != foo_root->addr)
    abort ();
  foo_root = foo_root->next;
}

#define FOOPTR(name) \
  foo_t __attribute__ ((cleanup (foo_remove))) *name = \
    ({ gcpro_t *fl = alloca (sizeof (gcpro_t)); foo_add (fl, &name); })

void gc (int locals)
{
  gcpro_t *fl;

  /* We should print addresses of all live
     locals defined with FOOPTR. */
  printf ("In GC, expect %d locals at:\n", locals);
  for (fl = foo_root; fl; fl = fl->next)
    printf ("  %p\n", fl->addr);
  printf ("GC end\n");
}

int foofun (foo_t *f1, foo_t *f2)
{
  FOOPTR (fooptr3);
  int ret;

  printf ("In foofun, local var at %p\n", &fooptr3);

  fooptr3 = malloc (sizeof *fooptr3);
  fooptr3->x = f1->x + f2->x;
  fooptr3->y = f1->y - f2->y;

  if (fooptr3->x > 0)
    {
      FOOPTR (fooptr4);

      printf ("In foofun, inner local var at %p\n", &fooptr4);
      gc (4); /* Here we expect 4 fooptrs on C stack. */
    }

  ret = fooptr3->x + fooptr3->y;
  free (fooptr3);
  return ret;
}

int main (int argc, char *argv[])
{
  FOOPTR (fooptr1);
  FOOPTR (fooptr2);
  int val;

  printf ("In main, local vars at %p and %p\n", &fooptr1, &fooptr2);
  
  fooptr1 = malloc (sizeof *fooptr1);
  fooptr1->x = argc;
  fooptr1->y = argc + 1;

  fooptr2 = malloc (sizeof *fooptr2);
  fooptr2->x = argc * 2;
  fooptr2->y = argc * 2 + 1;

  val = foofun (fooptr1, fooptr2);
  free (fooptr1);
  free (fooptr2);
  
  gc (2); /* Here we expect 2 fooptrs on C stack. */
  return val;
}

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

end of thread, other threads:[~2011-11-17 19:12 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-16 10:07 Finding objects on C stack - alternate GCPRO Dmitry Antipov
2011-11-16 10:18 ` Helmut Eller
2011-11-16 10:33   ` Dmitry Antipov
2011-11-16 23:27   ` Richard Stallman
2011-11-17  4:17     ` Stephen J. Turnbull
2011-11-17 19:12       ` Richard Stallman
2011-11-16 11:06 ` Eli Zaretskii
2011-11-17 12:50   ` Stephen Berman
2011-11-17 16:50     ` Eli Zaretskii
2011-11-16 14:41 ` Stefan Monnier
2011-11-16 18:19 ` Tom Tromey
2011-11-16 21:07 ` Ken Raeburn

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).