home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ppcsmalleiffel / lib_se / gc_handler.e < prev    next >
Encoding:
Text File  |  1998-01-16  |  12.2 KB  |  547 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  4. --                       http://www.loria.fr/SmallEiffel
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it 
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later 
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License 
  11. -- for  more  details.  You  should  have  received a copy of the GNU General 
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class GC_HANDLER
  17.    -- 
  18.    -- GARBAGE_COLLECTOR_HANDLER
  19.    --
  20.  
  21. inherit GLOBALS;
  22.  
  23. creation make
  24.  
  25. feature
  26.  
  27.    is_on: BOOLEAN;
  28.      -- True when the Garbage Collector is produced.
  29.  
  30.    info_flag: BOOLEAN;
  31.      -- True when the Garbage Collector Info need to be printed.
  32.    
  33. feature {NONE}
  34.  
  35.    make is
  36.       do
  37.       end;
  38.  
  39. feature
  40.  
  41.    enable is
  42.       do
  43.      is_on := true;
  44.       end;
  45.    
  46.    set_info_flag is
  47.       do
  48.      is_on := true;
  49.      info_flag := true;
  50.       end;
  51.    
  52. feature {SMALL_EIFFEL}
  53.  
  54.    define1 is
  55.       require
  56.      is_on
  57.       local
  58.      i, j: INTEGER;
  59.       do
  60.      cpp.swap_on_h;
  61.      echo.put_string("Adding Garbage Collector.%N");
  62.      cpp.put_string(
  63.         "#define GCFLAG_UNMARKED 1%N%
  64.         %#define GCFLAG_MARKED 2%N%
  65.         %typedef union u_gcfsh gcfsh;%N%
  66.         %union u_gcfsh {gcfsh*next;int flag;};%N%
  67.         %typedef struct s_gcnah gcnah;%N%
  68.         %struct s_gcnah{int size;%N%
  69.         %void(*mfp)(gcnah*);%N%
  70.         %union {gcnah*next;int flag;double padding;}header;%N%
  71.         %};%N%
  72.         %extern gcnah*nafl[];%N");
  73.      cpp.put_extern5("void**gc_root_main",fz_null);
  74.      cpp.put_extern5("void**gcmt_fs1",fz_null);
  75.      cpp.put_extern5("void**gcmt_fs2",fz_null);
  76.      cpp.put_extern5("void(**gcmt_fsf)(void*,void*)",fz_null);
  77.      cpp.put_extern5("int gcmt_fs_max","1023");
  78.      cpp.put_extern2("int gcmt_fs_used",'0');
  79.      cpp.put_extern5("gcnah**gcmt_na",fz_null);
  80.      cpp.put_extern5("int gcmt_na_max","1023");
  81.      cpp.put_extern2("int gcmt_na_used",'0');
  82.      cpp.swap_on_c;
  83.      from
  84.         cpp.put_string("gcnah*nafl[");
  85.         cpp.put_integer(nafl_size);
  86.         cpp.put_string("]={%NNULL,");
  87.         i := nafl_size - 2;
  88.         j := 7;
  89.      until
  90.         i = 0
  91.      loop
  92.         if j = 0 then
  93.            cpp.put_character('%N');
  94.            j := 7;
  95.         else
  96.            j := j - 1;
  97.         end;
  98.         cpp.put_string(fz_null);
  99.         cpp.put_character(',');
  100.         i := i - 1;
  101.      end;
  102.      cpp.put_string(fz_null);
  103.      cpp.put_character('}');
  104.      cpp.put_character(';');
  105.      cpp.put_character('%N');
  106.      cpp.swap_on_h;
  107.      if info_flag then
  108.         cpp.put_extern2("int gc_start_count",'0');
  109.      end;
  110.       end;
  111.  
  112.    define2 is
  113.       require
  114.      is_on
  115.       local
  116.      i: INTEGER;
  117.      rc: RUN_CLASS;
  118.      rcd: DICTIONARY[RUN_CLASS,STRING];
  119.       do
  120.      rcd := small_eiffel.run_class_dictionary;
  121.      cpp.put_c_function("void gc_mark_na(void*p)",
  122.         "gcnah*n=((gcnah*)p-1);%N%
  123.         %if(gcmt_na_used==0)return;%N%
  124.         %if(n<*gcmt_na)return;%N%
  125.         %if(gcmt_na[gcmt_na_used-1]<n)return;%N%
  126.         %{int i1=0;%N%
  127.         %int i2=gcmt_na_used-1;%N%
  128.         %int m=i2>>1;%N%
  129.         %for(;i1<i2;m=((i1+i2)>>1)){%N%
  130.         %if(gcmt_na[m]<n)i1=m+1;%N%
  131.         %else i2=m;}%N%
  132.         %if(n==gcmt_na[i2])(*(n->mfp))(n);%N%
  133.         %}");
  134.      cpp.put_c_function("void gc_mark(void*p)",
  135.         "if(p<=*gcmt_fs1){%N%
  136.         %gc_mark_na(p);%Nreturn;%N}%N%
  137.         %if(gcmt_fs2[gcmt_fs_used-1]<p){%N%
  138.         %gc_mark_na(p);%Nreturn;%N}%N%
  139.         %{int i1=0; int m;%N%
  140.             %int i2=gcmt_fs_used-1;%N%
  141.             %for(;i1<i2;){%N%
  142.             %m=((i1+i2)>>1);%N%
  143.             %if(gcmt_fs1[m]<=p)%Ni1=m+1;%Nelse%Ni2=m;%N}%N%
  144.         %if(p<gcmt_fs1[i2])%Ni2--;%N%
  145.             %if(gcmt_fs2[i2]<p){%N%
  146.         %gc_mark_na(p);%Nreturn;%N}%N%
  147.         %if(p==gcmt_fs1[i2])return;%N%
  148.         %(*gcmt_fsf[i2])(p,gcmt_fs1[i2]);%N%
  149.         %}");
  150.      cpp.put_c_function("void gc_start(void)",
  151.         "jmp_buf env;%N%
  152.             %(void)setjmp(env);%N%
  153.             %gc_start_aux(((void**)&env));");
  154.      body.clear;
  155.      body.append( 
  156.             "if(sp>gc_root_main){%N%
  157.             %for(sp+=(sizeof(jmp_buf)/sizeof(void*));sp>=gc_root_main;sp--)%N%
  158.             %gc_mark(*sp);}%N%
  159.             %else {%N%
  160.             %for(sp-=(sizeof(jmp_buf)/sizeof(void*));sp<=gc_root_main;sp++)%N%
  161.             %gc_mark(*sp);}%N");
  162.      if info_flag then
  163.         body.append("gc_start_count++;%N");
  164.      end;
  165.      manifest_string_pool.gc_mark_in(body);
  166.      once_routine_pool.gc_mark_in(body);
  167.      call_gc_sweep(rcd);
  168.      body.append(
  169.             "{int h;%N%
  170.         %gcnah**p=gcmt_na+gcmt_na_used-1;%N%
  171.         %gcnah*n;%N%
  172.         %for(;p>=gcmt_na;p--){%N%
  173.         %n=*p;%N%
  174.         %switch(n->header.flag){%N%
  175.         %case GCFLAG_MARKED:n->header.flag=GCFLAG_UNMARKED;%N%
  176.         %break;%N%
  177.         %case GCFLAG_UNMARKED:h=n->size&");
  178.      (nafl_size - 1).append_in(body);
  179.      body.append(
  180.         ";%N%
  181.         %n->header.next=nafl[h];%N%
  182.         %nafl[h]=n;%N%
  183.         %break;%N%
  184.         %}}}");
  185.      cpp.put_c_function("void gc_start_aux(void**sp)",body);
  186.      cpp.swap_on_h;
  187.      from   
  188.         i := 1;
  189.      until
  190.         i > rcd.count
  191.      loop
  192.         rc := rcd.item(i);
  193.         rc.gc_define1;
  194.         i := i + 1;
  195.      end;
  196.      cpp.swap_on_c;
  197.      from   
  198.         i := 1;
  199.      until
  200.         i > rcd.count
  201.      loop
  202.         rc := rcd.item(i);
  203.         rc.gc_define2;
  204.         i := i + 1;
  205.      end;
  206.      from   
  207.         i := run_class_list.upper;
  208.      until
  209.         i < 0
  210.      loop
  211.         switch_for(run_class_list.item(i));
  212.         i := i - 1;
  213.      end;
  214.      if info_flag then
  215.         define_gc_info(rcd);
  216.      end;
  217.       end;
  218.  
  219. feature {TYPE}
  220.  
  221.    threshold_start(id: INTEGER): INTEGER is
  222.       local
  223.      nb: INTEGER;
  224.      log2_nb: DOUBLE;
  225.       do
  226.      Result := 9;
  227.      inspect
  228.         id
  229.      when 7,9 then
  230.         nb := manifest_string_pool.count;
  231.         if nb > 0 then
  232.            log2_nb := nb.log / (2).log;
  233.            nb := log2_nb.rounded + 2;
  234.            if nb > Result then
  235.           Result := nb;
  236.            end;
  237.         end;
  238.      else
  239.      end;
  240.       end;
  241.  
  242. feature {TYPE_NATIVE_ARRAY}
  243.  
  244.    nafl_size: INTEGER is 2048;
  245.  
  246. feature {C_PRETTY_PRINTER}
  247.  
  248.    initialize is
  249.      -- Initializing inside main function.
  250.       require
  251.      gc_handler.is_on
  252.       local
  253.      i: INTEGER;
  254.      rc: RUN_CLASS;
  255.      rcd: DICTIONARY[RUN_CLASS,STRING];
  256.       do
  257.      body.copy(
  258.         "gcmt_fs1=malloc((gcmt_fs_max+1)*sizeof(void*));%N%
  259.         %gcmt_fs2=malloc((gcmt_fs_max+1)*sizeof(void*));%N%
  260.         %gcmt_fsf=malloc((gcmt_fs_max+1)*sizeof(void*));%N%
  261.         %gcmt_na=malloc((gcmt_na_max+1)*sizeof(void*));%N");
  262.      cpp.put_string(body);
  263.      rcd := small_eiffel.run_class_dictionary;
  264.      from   
  265.         i := 1;
  266.      until
  267.         i > rcd.count
  268.      loop
  269.         rc := rcd.item(i);
  270.         rc.gc_initialize;
  271.         i := i + 1;
  272.      end;
  273.       end;
  274.  
  275. feature {CREATION_CALL,C_PRETTY_PRINTER}   
  276.    
  277.    put_new(rc: RUN_CLASS) is
  278.      -- Basic allocation of in new temporary `n' local.
  279.       require
  280.      rc.at_run_time;
  281.      rc.current_type.is_reference;
  282.      cpp.on_c
  283.       local
  284.      ct: TYPE;
  285.      id: INTEGER;
  286.       do
  287.      ct := rc.current_type;
  288.      id := rc.id;
  289.      body.clear;
  290.      body.extend('T');
  291.      id.append_in(body);
  292.      body.extend('*');
  293.      body.extend('n');
  294.      body.extend('=');
  295.      if is_on then
  296.         body.append(fz_new);
  297.         id.append_in(body);
  298.         body.extend('(');
  299.         body.extend(')');
  300.      elseif ct.need_c_struct then
  301.         body.append(us_malloc);
  302.         body.extend('(');
  303.         body.append(fz_sizeof);
  304.         body.extend('(');
  305.         body.extend('*');
  306.         body.extend('n');
  307.         body.extend(')');
  308.         body.extend(')');
  309.         body.append(fz_00);
  310.         body.extend('*');
  311.         body.extend('n');
  312.         body.extend('=');
  313.         body.extend('M');
  314.         id.append_in(body);
  315.      else
  316.         -- Object has no attributes :
  317.         body.append(us_malloc);
  318.         body.extend('(');
  319.         body.extend('1');
  320.         body.extend(')');
  321.      end;
  322.      body.append(fz_00);
  323.      cpp.put_string(body);
  324.       end;
  325.  
  326. feature {RUN_CLASS}
  327.  
  328.    call_gc_mark(str: STRING; rf2: RUN_FEATURE_2) is
  329.       require
  330.      str /= Void;
  331.      rf2.result_type.run_class.at_run_time
  332.       local
  333.      rc: RUN_CLASS;
  334.      ct: TYPE;
  335.      field: STRING;
  336.      r: ARRAY[RUN_CLASS];
  337.       do
  338.      ct := rf2.result_type;
  339.      if ct.need_gc_mark_function then
  340.         field := rf2.name.to_string;
  341.         if ct.is_expanded then
  342.            if ct.is_user_expanded then
  343.           str.append("RUN_CLASS : GARGGLLL");
  344.            else
  345.           str.append(fz_c_if_neq_null);
  346.           str.append("(o->_");
  347.           str.append(field);
  348.           str.append(fz_13);
  349.           ct.gc_mark_in(str);
  350.           str.append("(((gcnah*)(o->_");
  351.           str.append(field);
  352.           str.append("))-1);%N");
  353.            end;
  354.         else
  355.            rc := ct.run_class;
  356.            r := rc.running;
  357.            check
  358.           r.count >= 1
  359.            end;
  360.            str.append("if(NULL!=(o->_");
  361.            str.append(field);
  362.            str.append("))");
  363.            if r.count > 1 then
  364.           if not run_class_list.fast_has(rc) then
  365.              run_class_list.add_last(rc);
  366.           end;
  367.           str.extend('X');
  368.           ct.gc_mark_in(str);
  369.            else
  370.           r.first.current_type.gc_mark_in(str);
  371.            end;
  372.            str.append("(((void*)(o->_");
  373.            str.append(field);
  374.            str.append(")));%N");
  375.         end;
  376.      end;
  377.       end;
  378.  
  379. feature {TYPE_NATIVE_ARRAY}
  380.  
  381.    native_array_mark(str: STRING; rc: RUN_CLASS) is
  382.       local
  383.      ct: TYPE;
  384.      r: ARRAY[RUN_CLASS];
  385.       do
  386.      ct := rc.current_type;
  387.      if ct.is_reference then
  388.         str.append("if(NULL!=o)")
  389.      end;
  390.      r := rc.running;
  391.      check
  392.         r.count >= 1;
  393.      end;
  394.      if r.count > 1 then
  395.         if not run_class_list.fast_has(rc) then
  396.            run_class_list.add_last(rc);
  397.         end;
  398.         str.extend('X');
  399.         ct.gc_mark_in(str);
  400.      else
  401.         r.first.current_type.gc_mark_in(str);
  402.      end;
  403.      str.extend('(');
  404.      if ct.is_expanded then
  405.         str.extend('&');
  406.      else
  407.         str.append(fz_cast_void_star);
  408.      end;
  409.      str.extend('o');
  410.      str.extend(')');
  411.      str.append(fz_00);
  412.       end;
  413.    
  414. feature {NONE}
  415.  
  416.    run_class_list: FIXED_ARRAY[RUN_CLASS] is
  417.       once
  418.      !!Result.with_capacity(32);
  419.       end;
  420.  
  421. feature {NONE}
  422.  
  423.    switch_for(rc: RUN_CLASS) is
  424.       local
  425.      ct: TYPE;
  426.      r: ARRAY[RUN_CLASS];
  427.       do
  428.      header.clear;
  429.      header.append(fz_void);
  430.      header.extend(' ');
  431.      header.extend('X');
  432.      ct := rc.current_type;
  433.      ct.gc_mark_in(header);
  434.      header.extend('(');
  435.      header.append(fz_t0_star);
  436.      header.extend('o');
  437.      header.extend(')');
  438.      body.clear;
  439.      r := rc.running;
  440.      sort_running(r);
  441.      body.append("{int i=o->id;%N");
  442.      c_dicho(r,1,r.upper);
  443.      body.extend('}');
  444.      cpp.put_c_function(header,body);
  445.       end;
  446.  
  447. feature {NONE}
  448.  
  449.    c_dicho(r: ARRAY[RUN_CLASS]; bi, bs: INTEGER) is
  450.      -- Produce dichotomic inspection code for Current id.
  451.       require
  452.      bi <= bs
  453.       local
  454.      m: INTEGER;
  455.      rc: RUN_CLASS;
  456.       do
  457.      if bi = bs then
  458.         rc := r.item(bi);
  459.         rc.current_type.gc_mark_in(body);
  460.         body.extend('(');
  461.         body.extend('(');
  462.         body.extend('T');
  463.         rc.id.append_in(body);
  464.         body.extend('*');
  465.         body.extend(')');
  466.         body.extend('o');
  467.         body.extend(')');
  468.         body.append(fz_00);
  469.      else        
  470.         m := (bi + bs) // 2;
  471.         rc := r.item(m);
  472.         body.append("if (i <= ");
  473.         rc.id.append_in(body);
  474.         body.append(") {%N");
  475.         c_dicho(r,bi,m);
  476.         body.append("} else {%N");
  477.         c_dicho(r,m + 1,bs);
  478.         body.extend('}');
  479.      end;
  480.       end;
  481.  
  482. feature {NONE}
  483.  
  484.    call_gc_sweep(rcd: DICTIONARY[RUN_CLASS,STRING]) is
  485.       require
  486.      is_on
  487.       local
  488.      i: INTEGER;
  489.      rc: RUN_CLASS;
  490.       do
  491.      from   
  492.         i := 1;
  493.      until
  494.         i > rcd.count
  495.      loop
  496.         rc := rcd.item(i);
  497.         rc.call_gc_sweep_in(body);
  498.         i := i + 1;
  499.      end;
  500.       end;
  501.  
  502. feature {NONE}
  503.  
  504.    define_gc_info(rcd: DICTIONARY[RUN_CLASS,STRING]) is
  505.       local
  506.      i: INTEGER;
  507.      rc: RUN_CLASS;
  508.       do
  509.      header.clear;
  510.      header.append(fz_void);
  511.      header.extend(' ');
  512.      header.append(fz_gc_info);
  513.      header.append(fz_c_void_args);
  514.      body.clear;
  515.      from   
  516.         i := 1;
  517.      until
  518.         i > rcd.count
  519.      loop
  520.         rc := rcd.item(i);
  521.         rc.gc_info_in(body);
  522.         i := i + 1;
  523.      end;
  524.      body.append(
  525.            "printf(%"gcmt_fs_used = %%d\n%",gcmt_fs_used);%N%
  526.        %printf(%"gcmt_fs_max = %%d\n%",gcmt_fs_max);%N%
  527.            %printf(%"gcmt_na_used = %%d\n%",gcmt_na_used);%N%
  528.        %printf(%"gcmt_na_max = %%d\n%",gcmt_na_max);%N%
  529.        %printf(%"GC called %%d time(s)\n%",gc_start_count);%N");
  530.      cpp.put_c_function(header,body);
  531.       end;
  532.  
  533. feature {NONE}
  534.  
  535.    header: STRING is
  536.       once
  537.      !!Result.make(64);
  538.       end;
  539.  
  540.    body: STRING is
  541.       once
  542.      !!Result.make(512);
  543.       end;
  544.  
  545. end -- GC_HANDLER
  546.  
  547.