Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include "jsi.h"
  2. #include "jscompile.h"
  3. #include "jsvalue.h"
  4. #include "jsrun.h"
  5.  
  6. #include "regexp.h"
  7.  
  8. static void jsG_freeenvironment(js_State *J, js_Environment *env)
  9. {
  10.         js_free(J, env);
  11. }
  12.  
  13. static void jsG_freefunction(js_State *J, js_Function *fun)
  14. {
  15.         js_free(J, fun->funtab);
  16.         js_free(J, fun->numtab);
  17.         js_free(J, fun->strtab);
  18.         js_free(J, fun->vartab);
  19.         js_free(J, fun->code);
  20.         js_free(J, fun);
  21. }
  22.  
  23. static void jsG_freeproperty(js_State *J, js_Property *node)
  24. {
  25.         if (node->left->level) jsG_freeproperty(J, node->left);
  26.         if (node->right->level) jsG_freeproperty(J, node->right);
  27.         js_free(J, node);
  28. }
  29.  
  30. static void jsG_freeiterator(js_State *J, js_Iterator *node)
  31. {
  32.         while (node) {
  33.                 js_Iterator *next = node->next;
  34.                 js_free(J, node);
  35.                 node = next;
  36.         }
  37. }
  38.  
  39. static void jsG_freeobject(js_State *J, js_Object *obj)
  40. {
  41.         if (obj->properties->level)
  42.                 jsG_freeproperty(J, obj->properties);
  43.         if (obj->type == JS_CREGEXP) {
  44.                 js_free(J, obj->u.r.source);
  45.                 js_regfreex(J->alloc, J->actx, obj->u.r.prog);
  46.         }
  47.         if (obj->type == JS_CITERATOR)
  48.                 jsG_freeiterator(J, obj->u.iter.head);
  49.         if (obj->type == JS_CUSERDATA && obj->u.user.finalize)
  50.                 obj->u.user.finalize(J, obj->u.user.data);
  51.         js_free(J, obj);
  52. }
  53.  
  54. /* Mark and add object to scan queue */
  55. static void jsG_markobject(js_State *J, int mark, js_Object *obj)
  56. {
  57.         obj->gcmark = mark;
  58.         obj->gcroot = J->gcroot;
  59.         J->gcroot = obj;
  60. }
  61.  
  62. static void jsG_markfunction(js_State *J, int mark, js_Function *fun)
  63. {
  64.         int i;
  65.         fun->gcmark = mark;
  66.         for (i = 0; i < fun->funlen; ++i)
  67.                 if (fun->funtab[i]->gcmark != mark)
  68.                         jsG_markfunction(J, mark, fun->funtab[i]);
  69. }
  70.  
  71. static void jsG_markenvironment(js_State *J, int mark, js_Environment *env)
  72. {
  73.         do {
  74.                 env->gcmark = mark;
  75.                 if (env->variables->gcmark != mark)
  76.                         jsG_markobject(J, mark, env->variables);
  77.                 env = env->outer;
  78.         } while (env && env->gcmark != mark);
  79. }
  80.  
  81. static void jsG_markproperty(js_State *J, int mark, js_Property *node)
  82. {
  83.         if (node->left->level) jsG_markproperty(J, mark, node->left);
  84.         if (node->right->level) jsG_markproperty(J, mark, node->right);
  85.  
  86.         if (node->value.type == JS_TMEMSTR && node->value.u.memstr->gcmark != mark)
  87.                 node->value.u.memstr->gcmark = mark;
  88.         if (node->value.type == JS_TOBJECT && node->value.u.object->gcmark != mark)
  89.                 jsG_markobject(J, mark, node->value.u.object);
  90.         if (node->getter && node->getter->gcmark != mark)
  91.                 jsG_markobject(J, mark, node->getter);
  92.         if (node->setter && node->setter->gcmark != mark)
  93.                 jsG_markobject(J, mark, node->setter);
  94. }
  95.  
  96. /* Mark everything the object can reach. */
  97. static void jsG_scanobject(js_State *J, int mark, js_Object *obj)
  98. {
  99.         if (obj->properties->level)
  100.                 jsG_markproperty(J, mark, obj->properties);
  101.         if (obj->prototype && obj->prototype->gcmark != mark)
  102.                 jsG_markobject(J, mark, obj->prototype);
  103.         if (obj->type == JS_CITERATOR && obj->u.iter.target->gcmark != mark) {
  104.                 jsG_markobject(J, mark, obj->u.iter.target);
  105.         }
  106.         if (obj->type == JS_CFUNCTION || obj->type == JS_CSCRIPT || obj->type == JS_CEVAL) {
  107.                 if (obj->u.f.scope && obj->u.f.scope->gcmark != mark)
  108.                         jsG_markenvironment(J, mark, obj->u.f.scope);
  109.                 if (obj->u.f.function && obj->u.f.function->gcmark != mark)
  110.                         jsG_markfunction(J, mark, obj->u.f.function);
  111.         }
  112. }
  113.  
  114. static void jsG_markstack(js_State *J, int mark)
  115. {
  116.         js_Value *v = J->stack;
  117.         int n = J->top;
  118.         while (n--) {
  119.                 if (v->type == JS_TMEMSTR && v->u.memstr->gcmark != mark)
  120.                         v->u.memstr->gcmark = mark;
  121.                 if (v->type == JS_TOBJECT && v->u.object->gcmark != mark)
  122.                         jsG_markobject(J, mark, v->u.object);
  123.                 ++v;
  124.         }
  125. }
  126.  
  127. void js_gc(js_State *J, int report)
  128. {
  129.         js_Function *fun, *nextfun, **prevnextfun;
  130.         js_Object *obj, *nextobj, **prevnextobj;
  131.         js_String *str, *nextstr, **prevnextstr;
  132.         js_Environment *env, *nextenv, **prevnextenv;
  133.         unsigned int nenv = 0, nfun = 0, nobj = 0, nstr = 0, nprop = 0;
  134.         unsigned int genv = 0, gfun = 0, gobj = 0, gstr = 0, gprop = 0;
  135.         int mark;
  136.         int i;
  137.  
  138.         if (J->gcpause) {
  139.                 if (report)
  140.                         js_report(J, "garbage collector is paused");
  141.                 return;
  142.         }
  143.  
  144.         mark = J->gcmark = J->gcmark == 1 ? 2 : 1;
  145.  
  146.         /* Add initial roots. */
  147.  
  148.         jsG_markobject(J, mark, J->Object_prototype);
  149.         jsG_markobject(J, mark, J->Array_prototype);
  150.         jsG_markobject(J, mark, J->Function_prototype);
  151.         jsG_markobject(J, mark, J->Boolean_prototype);
  152.         jsG_markobject(J, mark, J->Number_prototype);
  153.         jsG_markobject(J, mark, J->String_prototype);
  154.         jsG_markobject(J, mark, J->RegExp_prototype);
  155.         jsG_markobject(J, mark, J->Date_prototype);
  156.  
  157.         jsG_markobject(J, mark, J->Error_prototype);
  158.         jsG_markobject(J, mark, J->EvalError_prototype);
  159.         jsG_markobject(J, mark, J->RangeError_prototype);
  160.         jsG_markobject(J, mark, J->ReferenceError_prototype);
  161.         jsG_markobject(J, mark, J->SyntaxError_prototype);
  162.         jsG_markobject(J, mark, J->TypeError_prototype);
  163.         jsG_markobject(J, mark, J->URIError_prototype);
  164.  
  165.         jsG_markobject(J, mark, J->R);
  166.         jsG_markobject(J, mark, J->G);
  167.  
  168.         jsG_markstack(J, mark);
  169.  
  170.         jsG_markenvironment(J, mark, J->E);
  171.         jsG_markenvironment(J, mark, J->GE);
  172.         for (i = 0; i < J->envtop; ++i)
  173.                 jsG_markenvironment(J, mark, J->envstack[i]);
  174.  
  175.         /* Scan objects until none remain. */
  176.  
  177.         while ((obj = J->gcroot) != NULL) {
  178.                 J->gcroot = obj->gcroot;
  179.                 obj->gcroot = NULL;
  180.                 jsG_scanobject(J, mark, obj);
  181.         }
  182.  
  183.         /* Free everything not marked. */
  184.  
  185.         prevnextenv = &J->gcenv;
  186.         for (env = J->gcenv; env; env = nextenv) {
  187.                 nextenv = env->gcnext;
  188.                 if (env->gcmark != mark) {
  189.                         *prevnextenv = nextenv;
  190.                         jsG_freeenvironment(J, env);
  191.                         ++genv;
  192.                 } else {
  193.                         prevnextenv = &env->gcnext;
  194.                 }
  195.                 ++nenv;
  196.         }
  197.  
  198.         prevnextfun = &J->gcfun;
  199.         for (fun = J->gcfun; fun; fun = nextfun) {
  200.                 nextfun = fun->gcnext;
  201.                 if (fun->gcmark != mark) {
  202.                         *prevnextfun = nextfun;
  203.                         jsG_freefunction(J, fun);
  204.                         ++gfun;
  205.                 } else {
  206.                         prevnextfun = &fun->gcnext;
  207.                 }
  208.                 ++nfun;
  209.         }
  210.  
  211.         prevnextobj = &J->gcobj;
  212.         for (obj = J->gcobj; obj; obj = nextobj) {
  213.                 nprop += obj->count;
  214.                 nextobj = obj->gcnext;
  215.                 if (obj->gcmark != mark) {
  216.                         gprop += obj->count;
  217.                         *prevnextobj = nextobj;
  218.                         jsG_freeobject(J, obj);
  219.                         ++gobj;
  220.                 } else {
  221.                         prevnextobj = &obj->gcnext;
  222.                 }
  223.                 ++nobj;
  224.         }
  225.  
  226.         prevnextstr = &J->gcstr;
  227.         for (str = J->gcstr; str; str = nextstr) {
  228.                 nextstr = str->gcnext;
  229.                 if (str->gcmark != mark) {
  230.                         *prevnextstr = nextstr;
  231.                         js_free(J, str);
  232.                         ++gstr;
  233.                 } else {
  234.                         prevnextstr = &str->gcnext;
  235.                 }
  236.                 ++nstr;
  237.         }
  238.  
  239.         unsigned int ntot = nenv + nfun + nobj + nstr + nprop;
  240.         unsigned int gtot = genv + gfun + gobj + gstr + gprop;
  241.         unsigned int remaining = ntot - gtot;
  242.  
  243.         J->gccounter = remaining;
  244.         J->gcthresh = remaining * JS_GCFACTOR;
  245.  
  246.         if (report) {
  247.                 char buf[256];
  248.                 snprintf(buf, sizeof buf, "garbage collected (%d%%): %d/%d envs, %d/%d funs, %d/%d objs, %d/%d props, %d/%d strs",
  249.                         100*gtot/ntot, genv, nenv, gfun, nfun, gobj, nobj, gprop, nprop, gstr, nstr);
  250.                 js_report(J, buf);
  251.         }
  252. }
  253.  
  254. void js_freestate(js_State *J)
  255. {
  256.         js_Function *fun, *nextfun;
  257.         js_Object *obj, *nextobj;
  258.         js_Environment *env, *nextenv;
  259.         js_String *str, *nextstr;
  260.  
  261.         if (!J)
  262.                 return;
  263.  
  264.         for (env = J->gcenv; env; env = nextenv)
  265.                 nextenv = env->gcnext, jsG_freeenvironment(J, env);
  266.         for (fun = J->gcfun; fun; fun = nextfun)
  267.                 nextfun = fun->gcnext, jsG_freefunction(J, fun);
  268.         for (obj = J->gcobj; obj; obj = nextobj)
  269.                 nextobj = obj->gcnext, jsG_freeobject(J, obj);
  270.         for (str = J->gcstr; str; str = nextstr)
  271.                 nextstr = str->gcnext, js_free(J, str);
  272.  
  273.         jsS_freestrings(J);
  274.  
  275.         js_free(J, J->lexbuf.text);
  276.         J->alloc(J->actx, J->stack, 0);
  277.         J->alloc(J->actx, J, 0);
  278. }
  279.