Branch: Tag:

2000-06-11

2000-06-11 11:59:47 by Martin Stjernholm <mast@lysator.liu.se>

More gc fixes and more tests.

Rev: src/gc.c:1.90
Rev: src/gc.h:1.46
Rev: src/testsuite.in:1.299

1: - test_true([["$Id: testsuite.in,v 1.298 2000/06/09 22:17:28 mast Exp $"]]); + test_true([["$Id: testsuite.in,v 1.299 2000/06/11 11:59:47 mast Exp $"]]);      cond([[all_constants()->_verify_internals]],   [[
1893:    }    ");    add_constant ("Live", Live); -  program Nested = compile_string (#" +  program LiveNested = compile_string (#"    inherit Live; -  string id = \"nested[0]\"; +  string id = \"live_nested[0]\";    void create() {}    void check_live_0 (mapping(object:int) checked) {check_live (checked);} -  class Nested1 +  class LiveNested1    {    inherit Live; -  string id = \"nested[1]\"; +  string id = \"live_nested[1]\";    void create() {}    void check_live (mapping(object:int) checked) {    checked[this_object()] = 1;
1910:    else ::check_live (checked);    }    void check_live_1 (mapping(object:int) checked) {check_live (checked);} -  class Nested2 +  class LiveNested2    {    inherit Live; -  string id = \"nested[2]\"; +  string id = \"live_nested[2]\";    void create() {}    void check_live (mapping(object:int) checked) {    checked[this_object()] = 1;
1922:    else ::check_live (checked);    }    } -  class Nested3 +  class LiveNested3    {    inherit Live; -  string id = \"nested[3]\"; +  string id = \"live_nested[3]\";    void create() {}    void check_live (mapping(object:int) checked) {    checked[this_object()] = 1;
1936:    }    }    "); +  program DeadNested = compile_string (#" +  inherit Dead; +  string id = \"dead_nested[0]\"; +  void create() {} +  void check_live_0 (mapping(object:int) checked) {check_live (checked);} +  class DeadNested1 +  { +  inherit Dead; +  string id = \"dead_nested[1]\"; +  void create() {} +  void check_live (mapping(object:int) checked) { +  checked[this_object()] = 1; +  if (catch (check_live_0 (checked))) +  my_error (\"Parent for %s got destructed too early.\\n\", id); +  else ::check_live (checked); +  } +  void check_live_1 (mapping(object:int) checked) {check_live (checked);} +  class DeadNested2 +  { +  inherit Dead; +  string id = \"dead_nested[2]\"; +  void create() {} +  void check_live (mapping(object:int) checked) { +  checked[this_object()] = 1; +  if (catch (check_live_1 (checked))) +  my_error (\"Parent for %s got destructed too early.\\n\", id); +  else ::check_live (checked); +  } +  } +  class DeadNested3 +  { +  inherit Dead; +  string id = \"dead_nested[3]\"; +  void create() {} +  void check_live (mapping(object:int) checked) { +  checked[this_object()] = 1; +  if (catch (check_live_1 (checked))) +  my_error (\"Parent for %s got destructed too early.\\n\", id); +  else ::check_live (checked); +  } +  } +  } +  ");    add_constant ("destructing");    add_constant ("my_error");    add_constant ("Dead");    add_constant ("Live");    -  array(object) live, dead, nested; +  array(object) live, dead, live_nested, dead_nested;    array(array) destruct_order_tests = ({    ({3, // Wanted number of live objects.    0, // Wanted number of dead objects. -  0, // Wanted nested objects. +  0, // Wanted live nested objects. +  0, // Wanted dead nested objects.    lambda() { // Function to connect them.    live[0]->x = live[1], live[0]->a = live[2];    live[1]->x = live[0];    }}), -  ({2, 2, 0, lambda() { // 1 +  ({2, 2, 0, 0, lambda() { // 1    live[0]->x = live[1], live[0]->a = dead[0];    live[1]->x = live[0];    dead[0]->a = dead[1];    dead[1]->a = dead[0];    }}), -  ({1, 2, 0, lambda() { // 2 +  ({1, 2, 0, 0, lambda() { // 2    live[0]->a = live[0], live[0]->b = dead[0];    dead[0]->a = dead[1];    dead[1]->a = dead[0];    }}), -  ({0, 3, 0, lambda() { // 3 +  ({0, 3, 0, 0, lambda() { // 3    dead[0]->a = dead[1];    dead[1]->a = dead[0];    dead[2]->a = dead[0], dead[2]->b = dead[2];    }}), -  ({3, 0, 0, lambda() { // 4 +  ({3, 0, 0, 0, lambda() { // 4    live[0]->a = live[0], live[0]->b = live[1];    live[1]->a = live[2];    }}), -  ({1, 2, 0, lambda() { // 5 +  ({1, 2, 0, 0, lambda() { // 5    live[0]->a = live[0], live[0]->b = dead[0];    dead[0]->a = dead[1];    }}), -  ({1, 2, 0, lambda() { // 6 +  ({1, 2, 0, 0, lambda() { // 6    live[0]->a = live[0], live[0]->b = dead[1];    dead[0]->a = dead[0], dead[0]->b = dead[1];    dead[1]->a = dead[1];    }}), -  ({2, 2, 0, lambda() { // 7 +  ({2, 2, 0, 0, lambda() { // 7    live[0]->a = live[0], live[0]->b = live[1];    dead[0]->a = dead[0];    dead[0]->b = live[1];    live[1]->a = dead[1];    dead[1]->a = dead[1];    }}), -  ({1, 3, 0, lambda() { // 8 +  ({1, 3, 0, 0, lambda() { // 8    live[0]->a = live[0], live[0]->b = dead[2];    dead[0]->a = dead[0];    dead[0]->b = dead[2];    dead[2]->a = dead[1];    dead[1]->a = dead[1];    }}), -  ({3, 1, 0, lambda() { // 9 +  ({3, 1, 0, 0, lambda() { // 9    live[0]->a = live[0], live[0]->b = live[1];    dead[0]->a = dead[0], dead[0]->b = live[1];    live[1]->a = live[2];    }}), -  ({1, 3, 0, lambda() { // 10 +  ({1, 3, 0, 0, lambda() { // 10    live[0]->a = live[0], live[0]->b = dead[1];    dead[0]->a = dead[0], dead[0]->b = dead[1];    dead[1]->a = dead[2];    }}), -  ({1, 3, 0, lambda() { // 11 +  ({1, 3, 0, 0, lambda() { // 11    live[0]->a = live[0], live[0]->b = dead[1];    dead[0]->a = dead[0], dead[0]->b = dead[1];    dead[1]->a = dead[1], dead[1]->b = dead[2];    dead[2]->a = dead[2];    }}), -  ({5, 0, 0, lambda() { // 12 +  ({5, 0, 0, 0, lambda() { // 12    live[0]->x = live[1];    live[1]->x = live[0], live[1]->a = live[2];    live[2]->x = live[3];    live[3]->x = live[2], live[3]->a = live[4];    live[4]->a = live[4];    }}), -  ({3, 0, 0, lambda() { // 13 +  ({3, 0, 0, 0, lambda() { // 13    live[0]->x = live[1], live[0]->y = live[2];    live[1]->x = live[2];    live[2]->x = live[0];    }}), -  ({2, 0, 0, lambda() { // 14 +  ({2, 0, 0, 0, lambda() { // 14    live[0]->a = live[1], live[0]->b = live[0];    live[1]->w[0] = live[0];    }}), -  ({2, 0, 0, lambda() { // 15 +  ({2, 0, 0, 0, lambda() { // 15    live[0]->a = live[0], live[0]->b = live[1];    live[1]->w[0] = live[0];    }}), -  ({2, 0, 0, lambda() { // 16 +  ({2, 0, 0, 0, lambda() { // 16    live[0]->a = live[0], live[0]->w[0] = live[1];    live[1]->x = live[0];    }}), -  ({3, 0, 0, lambda() { // 17 +  ({3, 0, 0, 0, lambda() { // 17    live[0]->a = live[0], live[0]->b = live[1];    live[1]->w[0] = live[2];    live[2]->a = live[2], live[2]->b = live[1];    }}), -  ({3, 0, 0, lambda() { // 18 +  ({3, 0, 0, 0, lambda() { // 18    live[0]->a = live[1], live[0]->x = live[2];    live[1]->w[0] = live[2];    live[2]->x = live[0];    }}), -  ({4, 0, 0, lambda() { // 19 +  ({4, 0, 0, 0, lambda() { // 19    live[0]->x = live[0], live[0]->a = live[1], live[0]->b = live[2];    live[1]->a = live[3];    live[2]->a = live[3];    live[3]->w[0] = live[0];    }}), -  ({3, 0, 0, lambda() { // 20 +  ({3, 0, 0, 0, lambda() { // 20    live[0]->x = live[1];    live[1]->x = live[0], live[1]->a = live[2];    live[2]->w[0] = live[1];    }}), -  ({4, 0, 0, lambda() { // 21 +  ({4, 0, 0, 0, lambda() { // 21    live[0]->w[0] = live[1], live[0]->a = live[3];    live[1]->w[0] = live[2];    live[2]->a = live[0], live[2]->b = live[3], live[2]->x = live[2];    live[3]->a = live[1];    }}), -  ({2, 1, 0, lambda() { // 22 +  ({2, 1, 0, 0, lambda() { // 22    live[0]->a = dead[0], live[0]->x = live[1];    live[1]->x = live[0];    dead[0]->w[0] = live[1];    }}), -  ({2, 1, 0, lambda() { // 23 +  ({2, 1, 0, 0, lambda() { // 23    live[0]->a = live[1], live[0]->b = dead[0];    live[1]->w[0] = dead[0];    dead[0]->x = live[0];    }}), -  ({3, 0, 0, lambda() { // 24 +  ({3, 0, 0, 0, lambda() { // 24    live[0]->x = live[0], live[0]->a = live[1], live[0]->b = live[2];    live[1]->w[0] = live[0], live[1]->w[1] = live[2];    live[2]->a = live[1];    }}), -  ({3, 0, 0, lambda() { // 25 +  ({3, 0, 0, 0, lambda() { // 25    live[0]->a = live[1];    live[1]->w[0] = live[2];    live[2]->x = live[2], live[2]->a = live[0], live[2]->b = live[1];    }}), -  ({3, 0, 0, lambda() { // 26 +  ({3, 0, 0, 0, lambda() { // 26    live[0]->w[0] = live[1], live[0]->a = live[2];    live[1]->x = live[1], live[1]->a = live[0], live[1]->b = live[2];    live[2]->w[0] = live[1];    }}), -  ({3, 0, 0, lambda() { // 27 +  ({3, 0, 0, 0, lambda() { // 27    live[0]->w[0] = live[1];    live[1]->x = live[1], live[1]->a = live[0], live[1]->b = live[2];    live[2]->a = live[0];    }}), -  ({3, 0, 0, lambda() { // 28 +  ({3, 0, 0, 0, lambda() { // 28    live[0]->a = live[0], live[0]->v[0] = live[1];    live[1]->a = live[1], live[1]->v[0] = live[2];    live[2]->a = live[2];    }}), -  ({2, 2, 0, lambda() { // 29 +  ({2, 2, 0, 0, lambda() { // 29    live[0]->x = live[1], live[0]->v[0] = dead[0];    live[1]->x = live[0];    dead[0]->a = dead[1];    dead[1]->a = dead[0];    }}), -  ({4, 0, 0, lambda() { // 30 +  ({4, 0, 0, 0, lambda() { // 30    live[0]->a = live[1], live[0]->b = live[2], live[0]->v[0] = live[3];    live[1]->w[0] = live[0];    live[2]->a = live[3];    live[3]->w[0] = live[2];    }}), -  ({2, 1, 0, lambda() { // 31 +  ({2, 1, 0, 0, lambda() { // 31    live[0]->a = dead[0];    dead[0]->a = live[0], dead[0]->b = live[1];    live[1]->a = live[1];    }}), -  ({2, 1, 0, lambda() { // 32 +  ({2, 1, 0, 0, lambda() { // 32    live[0]->a = live[0], live[0]->b = dead[0];    live[1]->a = dead[0];    dead[0]->a = live[1];    }}), -  ({2, 1, 0, lambda() { // 33 +  ({2, 1, 0, 0, lambda() { // 33    dead[0]->a = live[0];    live[0]->a = dead[0], live[0]->b = live[1];    live[1]->a = live[1];    }}), -  ({2, 1, 0, lambda() { // 34 +  ({2, 1, 0, 0, lambda() { // 34    live[0]->a = dead[0];    dead[0]->b = live[0], dead[0]->a = live[1];    live[1]->a = live[1];    }}), -  ({2, 1, 0, lambda() { // 35 +  ({2, 1, 0, 0, lambda() { // 35    live[0]->b = live[0], live[0]->a = dead[0];    live[1]->a = dead[0];    dead[0]->a = live[1];    }}), -  ({2, 1, 0, lambda() { // 36 +  ({2, 1, 0, 0, lambda() { // 36    dead[0]->a = live[0];    live[0]->b = dead[0], live[0]->a = live[1];    live[1]->a = live[1];    }}), -  ({3, 0, 0, lambda() { // 37 +  ({3, 0, 0, 0, lambda() { // 37    live[0]->a = live[0], live[0]->v[0] = live[1];    live[0]->checkfn = lambda (object o) {    return o->v[0]->w[0];
2145:    live[1]->w[0] = live[2];    live[2]->a = live[1], live[2]->b = live[2];    }}), -  ({4, 0, 0, lambda() { // 38 +  ({4, 0, 0, 0, lambda() { // 38    live[0]->x = live[1];    live[1]->x = live[2];    live[2]->x = live[0], live[2]->w[0] = live[3];    live[3]->a = live[1], live[3]->b = live[3];    }}), -  ({0, 2, 2, lambda() { // 39 -  dead[0]->x = dead[0], dead[0]->a = nested[0]; -  dead[1]->x = dead[1], dead[1]->a = nested[1]; -  nested[0]->x = nested[1]; +  ({0, 2, 2, 0, lambda() { // 39 +  dead[0]->x = dead[0], dead[0]->a = live_nested[0]; +  dead[1]->x = dead[1], dead[1]->a = live_nested[1]; +  live_nested[0]->x = live_nested[1];    }}), -  ({0, 2, 2, lambda() { // 40 -  dead[0]->x = dead[0], dead[0]->a = nested[0]; -  dead[1]->x = dead[1], dead[1]->a = nested[1]; -  nested[0]->w[0] = nested[1]; +  ({0, 2, 2, 0, lambda() { // 40 +  dead[0]->x = dead[0], dead[0]->a = live_nested[0]; +  dead[1]->x = dead[1], dead[1]->a = live_nested[1]; +  live_nested[0]->w[0] = live_nested[1];    }}), -  ({3, 0, 3, lambda() { // 41 -  live[0]->x = live[0], live[0]->a = nested[0]; -  live[1]->x = live[1], live[1]->a = nested[2]; -  live[2]->x = live[2], live[2]->a = nested[1]; -  nested[0]->x = nested[2]; +  ({3, 0, 3, 0, lambda() { // 41 +  live[0]->x = live[0], live[0]->a = live_nested[0]; +  live[1]->x = live[1], live[1]->a = live_nested[2]; +  live[2]->x = live[2], live[2]->a = live_nested[1]; +  live_nested[0]->x = live_nested[2];    }}), -  ({4, 0, 4, lambda() { // 42 -  live[0]->x = live[0], live[0]->a = nested[0]; -  live[1]->x = live[1], live[1]->a = nested[1]; -  live[2]->x = live[2], live[2]->a = nested[2]; -  live[3]->x = live[3], live[3]->a = nested[3]; -  nested[0]->x = nested[3]; +  ({4, 0, 4, 0, lambda() { // 42 +  live[0]->x = live[0], live[0]->a = live_nested[0]; +  live[1]->x = live[1], live[1]->a = live_nested[1]; +  live[2]->x = live[2], live[2]->a = live_nested[2]; +  live[3]->x = live[3], live[3]->a = live_nested[3]; +  live_nested[0]->x = live_nested[3];    }}), -  ({3, 0, 2, lambda() { // 43 -  live[0]->x = live[0], live[0]->a = nested[0]; -  live[1]->x = live[1], live[1]->a = nested[1]; -  nested[0]->a = live[2]; -  live[2]->x = nested[1]; +  ({3, 0, 2, 0, lambda() { // 43 +  live[0]->x = live[0], live[0]->a = live_nested[0]; +  live[1]->x = live[1], live[1]->a = live_nested[1]; +  live_nested[0]->a = live[2]; +  live[2]->x = live_nested[1];    }}), -  ({3, 0, 3, lambda() { // 44 -  live[0]->x = live[0], live[0]->a = nested[0]; -  live[1]->x = live[1], live[1]->a = nested[2]; -  live[2]->x = live[2], live[2]->a = nested[1]; -  nested[0]->x = nested[2]; -  nested[1]->a = live[0]; +  ({3, 0, 3, 0, lambda() { // 44 +  live[0]->x = live[0], live[0]->a = live_nested[0]; +  live[1]->x = live[1], live[1]->a = live_nested[2]; +  live[2]->x = live[2], live[2]->a = live_nested[1]; +  live_nested[0]->x = live_nested[2]; +  live_nested[1]->a = live[0];    }}), - // ({3, 0, 0, lambda() { // Not possible without weak refs directly in objects. +  ({0, 2, 0, 2, lambda() { // 45 +  dead[0]->x = dead[0], dead[0]->a = dead_nested[0]; +  dead[1]->x = dead[1], dead[1]->a = dead_nested[1]; +  dead_nested[0]->x = dead_nested[1]; +  }}), +  ({0, 2, 0, 2, lambda() { // 46 +  dead[0]->x = dead[0], dead[0]->a = dead_nested[0]; +  dead[1]->x = dead[1], dead[1]->a = dead_nested[1]; +  dead_nested[0]->w[0] = dead_nested[1]; +  }}), +  ({3, 0, 0, 3, lambda() { // 47 +  live[0]->x = live[0], live[0]->a = dead_nested[0]; +  live[1]->x = live[1], live[1]->a = dead_nested[2]; +  live[2]->x = live[2], live[2]->a = dead_nested[1]; +  dead_nested[0]->x = dead_nested[2]; +  }}), +  ({4, 0, 0, 4, lambda() { // 48 +  live[0]->x = live[0], live[0]->a = dead_nested[0]; +  live[1]->x = live[1], live[1]->a = dead_nested[1]; +  live[2]->x = live[2], live[2]->a = dead_nested[2]; +  live[3]->x = live[3], live[3]->a = dead_nested[3]; +  dead_nested[0]->x = dead_nested[3]; +  }}), +  ({3, 0, 0, 2, lambda() { // 49 +  live[0]->x = live[0], live[0]->a = dead_nested[0]; +  live[1]->x = live[1], live[1]->a = dead_nested[1]; +  dead_nested[0]->a = live[2]; +  live[2]->x = dead_nested[1]; +  }}), +  ({3, 0, 0, 3, lambda() { // 50 +  live[0]->x = live[0], live[0]->a = dead_nested[0]; +  live[1]->x = live[1], live[1]->a = dead_nested[2]; +  live[2]->x = live[2], live[2]->a = dead_nested[1]; +  dead_nested[0]->x = dead_nested[2]; +  dead_nested[1]->a = live[0]; +  }}), +  ({0, 4, 2, 2, lambda() { // 51 +  dead[0]->x = dead[0], dead[0]->a = live_nested[0]; +  dead[1]->x = dead[1], dead[1]->a = live_nested[1]; +  dead[2]->x = dead[2], dead[2]->a = dead_nested[0]; +  dead[3]->x = dead[3], dead[3]->a = dead_nested[1]; +  live_nested[0]->x = dead_nested[1]; +  dead_nested[0]->x = live_nested[1]; +  }}), +  // ({3, 0, 0, 0, lambda() { // Not possible without weak refs directly in objects.   // live[0]->x = live[0], live[0]->v[0] = live[1];   // live[1]->x = live[1], live[1]->w[0] = live[2];   // live[2]->x = live[2], live[2]->a = live[0];
2196:       int test_failed = 0;    for (int test = 0; test < sizeof (destruct_order_tests); test++) { -  [int nlive, int ndead, int nnested, function(void:void) setup] = +  [int nlive, int ndead, int nlnested, int ndnested, function(void:void) setup] =    destruct_order_tests[test];    int objs = nlive + ndead;    array(int) idx = indices (allocate (objs));
2208:    array(int) create_order = ({});    live = allocate (nlive);    dead = allocate (ndead); -  if (nnested >= 1) { +  if (nlnested >= 1) {    // Creating these before the Dead and Live objects below assumes    // that the gc will start with the last created object first, so    // the order can be controlled with those objects. -  nested = ({Nested()}); -  if (nnested >= 2) nested += ({nested[0]->Nested1()}); -  if (nnested >= 3) nested += ({nested[1]->Nested2()}); -  if (nnested >= 4) nested += ({nested[1]->Nested3()}); +  live_nested = ({LiveNested()}); +  if (nlnested >= 2) live_nested += ({live_nested[0]->LiveNested1()}); +  if (nlnested >= 3) live_nested += ({live_nested[1]->LiveNested2()}); +  if (nlnested >= 4) live_nested += ({live_nested[1]->LiveNested3()});    } -  +  if (ndnested >= 1) { +  dead_nested = ({DeadNested()}); +  if (ndnested >= 2) dead_nested += ({dead_nested[0]->DeadNested1()}); +  if (ndnested >= 3) dead_nested += ({dead_nested[1]->DeadNested2()}); +  if (ndnested >= 4) dead_nested += ({dead_nested[1]->DeadNested3()}); +  }    for (int i = 0; i < objs; i++) {    int p = alloc_order[i];    if (p < nlive) live[p] = Live (p), create_order += ({p});
2224:    }    destruct_order = ({""}); // Using ({}) would alloc a new array in destructing().    setup(); -  live = dead = nested = 0; +  live = dead = live_nested = dead_nested = 0;    int garbed = gc() + gc(); // Second gc to garb live object leftovers.    destruct_order = destruct_order[1..]; -  if (!got_error && (got_error = sizeof (destruct_order) != nlive + nnested)) +  if (!got_error && (got_error = sizeof (destruct_order) != nlive + nlnested))    werror ("\nGC should garb %d live objects, " -  "but took %d.\n", nlive + nnested, sizeof (destruct_order)); -  if (!got_error && (got_error = garbed < 3 * (objs + nnested))) +  "but took %d.\n", nlive + nlnested, sizeof (destruct_order)); +  if (!got_error && (got_error = garbed < 3 * (objs + nlnested + ndnested)))    werror ("\nGC should garb at least %d things, " -  "but took only %d.\n", 3 * (objs + nnested), garbed); +  "but took only %d.\n", 3 * (objs + nlnested + ndnested), garbed);    if (got_error) {    werror ("Create order was: " +    map (create_order, lambda (int i) {
2242:    "Destruct order was: " + destruct_order * ", " + "\n");    test_failed = 1;    got_error = 0; -  error(""); +     break;    }    }