unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Dmitry Antipov <dmantipov@yandex.ru>
To: emacs-devel@gnu.org
Subject: Finding objects on C stack - alternate GCPRO
Date: Wed, 16 Nov 2011 14:07:46 +0400	[thread overview]
Message-ID: <4EC38B72.1000101@yandex.ru> (raw)

[-- 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;
}

             reply	other threads:[~2011-11-16 10:07 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-16 10:07 Dmitry Antipov [this message]
2011-11-16 10:18 ` Finding objects on C stack - alternate GCPRO 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4EC38B72.1000101@yandex.ru \
    --to=dmantipov@yandex.ru \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).