home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_se / gc_handler.e < prev    next >
Text File  |  1999-06-05  |  17KB  |  571 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://SmallEiffel.loria.fr
  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_off: BOOLEAN;
  28.          -- True when the Garbage Collector is not produced.
  29.  
  30.    info_flag: BOOLEAN;
  31.          -- True when Garbage Collector Information need to be printed.
  32.  
  33. feature {NONE}
  34.  
  35.    make is
  36.       do
  37.       end;
  38.  
  39. feature {COMPILE_TO_C}
  40.  
  41.    no_gc is
  42.       do
  43.          is_off := true;
  44.          info_flag := false;
  45.       ensure
  46.          is_off;
  47.          not info_flag
  48.       end;
  49.  
  50.    set_info_flag is
  51.       do
  52.          is_off := false;
  53.          info_flag := true;
  54.       ensure
  55.          not is_off;
  56.          info_flag
  57.       end;
  58.  
  59. feature {NONE}
  60.  
  61.    compute_ceils is
  62.       local
  63.          fsoc_count_ceil, rsoc_count_ceil, i: INTEGER;
  64.          rcd: DICTIONARY[RUN_CLASS,STRING];
  65.          rc: RUN_CLASS;
  66.          kb_count: INTEGER;
  67.       do
  68.          rcd := small_eiffel.run_class_dictionary;
  69.          from
  70.             i := 1;
  71.          until
  72.             i > rcd.count
  73.          loop
  74.             rc := rcd.item(i);
  75.             if rc.at_run_time then
  76.                if rc.current_type.is_native_array then
  77.                   rsoc_count_ceil := rsoc_count_ceil + 1;
  78.                else
  79.                   fsoc_count_ceil := fsoc_count_ceil + 1;
  80.                end;
  81.             end;
  82.             i := i + 1;
  83.          end;
  84.          fsoc_count_ceil := 4 * fsoc_count_ceil;
  85.          kb_count := fsoc_count_ceil * (fsoc_size // 1024);
  86.          if kb_count < 256 then
  87.             fsoc_count_ceil := 256 // (fsoc_size // 1024);
  88.          end;
  89.          rsoc_count_ceil := 3 * rsoc_count_ceil;
  90.          kb_count := rsoc_count_ceil * (rsoc_size // 1024);
  91.          if kb_count < 256 then
  92.             rsoc_count_ceil := 256 // (rsoc_size // 1024);
  93.          end;
  94.          cpp.put_extern6("unsigned int fsoc_count_ceil",fsoc_count_ceil);
  95.          cpp.put_extern6("unsigned int rsoc_count_ceil",rsoc_count_ceil);
  96.       end;
  97.  
  98. feature {TYPE}
  99.  
  100.    memory_dispose(code: STRING; o: STRING; run_class: RUN_CLASS) is
  101.          -- Append in `code' the extra C code for MEMORY.dispose if
  102.          -- any.
  103.       require
  104.          not run_class.current_type.is_expanded;
  105.          not run_class.current_type.is_native_array
  106.       local
  107.          rf3: RUN_FEATURE_3;
  108.          no_check: BOOLEAN;
  109.       do
  110.          rf3 := run_class.get_memory_dispose;
  111.          if rf3 /= Void then
  112.             code.append("if((");
  113.             code.append(o);
  114.             code.append("->header.flag)==FSOH_UNMARKED){");
  115.             no_check := run_control.no_check;
  116.             if no_check then
  117.                code.append(
  118.                "{se_frame_descriptor gcd={%"Garbage Collector at work.\n%
  119.                 %dispose called (during sweep phase)%",0,0,%"%",1};%N%
  120.                 %se_dump_stack ds = {NULL,NULL,0,0,0,NULL,NULL};%N%
  121.                 %ds.fd=&gcd;%N%
  122.                 %ds.caller=se_dst;%N%
  123.                 %se_dst=&ds;/*link*/%N");
  124.             end;
  125.             code.extend('r');
  126.             run_class.id.append_in(code);
  127.             rf3.name.mapping_c_in(code);
  128.             code.extend('(');
  129.             if no_check then
  130.                code.append("&ds,");
  131.             end;
  132.             if no_check or else rf3.use_current then
  133.                code.extend('(');
  134.                run_class.current_type.c_type_for_target_in(code);
  135.                code.extend(')');
  136.                code.append(o);
  137.             end;
  138.             code.append(fz_14);
  139.             if no_check then
  140.                code.append("se_dst=ds.caller;/*unlink*/%N}");
  141.             end;
  142.             code.extend('}');
  143.          end;
  144.       end;
  145.  
  146. feature {SMALL_EIFFEL}
  147.  
  148.    define1 is
  149.       require
  150.          not is_off
  151.       do
  152.          echo.put_string("Adding Garbage Collector.%N");
  153.          cpp.macro_def("FSOC_SIZE",fsoc_size);
  154.          cpp.macro_def("RSOC_SIZE",rsoc_size);
  155.          cpp.sys_runtime_h(fz_gc_lib);
  156.          compute_ceils;
  157.          cpp.sys_runtime_c(fz_gc_lib);
  158.          --
  159.          cpp.swap_on_h;
  160.          cpp.put_extern2("unsigned int gc_start_count",'0');
  161.       end;
  162.  
  163.    define2 is
  164.       require
  165.          not is_off
  166.       local
  167.          i: INTEGER;
  168.          rc: RUN_CLASS;
  169.          rcd: DICTIONARY[RUN_CLASS,STRING];
  170.          root_type: TYPE;
  171.       do
  172.          rcd := small_eiffel.run_class_dictionary;
  173.          root_type := small_eiffel.root_procedure.current_type;
  174.          manifest_string_pool.define_manifest_string_mark;
  175.          body.clear;
  176.          once_routine_pool.gc_mark_in(body);
  177.          cpp.put_c_function("void once_function_mark(void)",body);
  178.          system_tools.put_mark_stack_and_registers;
  179.          define_gc_start(root_type,rcd);
  180.          cpp.swap_on_h;
  181.          from
  182.             i := 1;
  183.          until
  184.             i > rcd.count
  185.          loop
  186.             rc := rcd.item(i);
  187.             rc.gc_define1;
  188.             i := i + 1;
  189.          end;
  190.          cpp.swap_on_c;
  191.          from
  192.             i := 1;
  193.          until
  194.             i > rcd.count
  195.          loop
  196.             rc := rcd.item(i);
  197.             rc.gc_define2;
  198.             i := i + 1;
  199.          end;
  200.          from
  201.             i := run_class_list.upper;
  202.          until
  203.             i < 0
  204.          loop
  205.             switch_for(run_class_list.item(i));
  206.             i := i - 1;
  207.          end;
  208.          if info_flag then
  209.             define_gc_info(rcd);
  210.          end;
  211.       ensure
  212.          small_eiffel.magic_count = old small_eiffel.magic_count
  213.       end;
  214.  
  215. feature {RUN_CLASS}
  216.  
  217.    falling_down(run_class: RUN_CLASS) is
  218.       local
  219.          rf3: RUN_FEATURE_3;
  220.       do
  221.          if not is_off then
  222.             rf3 := run_class.get_memory_dispose;
  223.             if rf3 /= Void then
  224.                dispose_flag := true;
  225.             end;
  226.          end;
  227.       end;
  228.  
  229.  
  230. feature {C_PRETTY_PRINTER}
  231.  
  232.    initialize_runtime is
  233.       do
  234.          if not is_off then
  235.             cpp.put_string("gcmt=malloc((gcmt_max+1)*sizeof(void*));%N%
  236.                            %stack_bottom=((void*)(&argc));%N");
  237.          end;
  238.       end;
  239.  
  240. feature {CREATION_CALL,C_PRETTY_PRINTER,TYPE_BIT_REF}
  241.  
  242.    allocation(rc: RUN_CLASS) is
  243.          -- Basic allocation of in new temporary `n' local.
  244.       require
  245.          rc.at_run_time;
  246.          rc.current_type.is_reference;
  247.          cpp.on_c
  248.       do
  249.          body.clear;
  250.          body.extend('T');
  251.          rc.id.append_in(body);
  252.          body.extend('*');
  253.          cpp.put_string(body);
  254.          allocation_of("n",rc);
  255.       end;
  256.  
  257. feature {C_PRETTY_PRINTER}
  258.  
  259.    allocation_of(var: STRING; rc: RUN_CLASS) is
  260.          -- Basic allocation in C variable `var' of object of `rc'.
  261.       require
  262.          var /= Void;
  263.          rc.at_run_time;
  264.          rc.current_type.is_reference;
  265.          cpp.on_c
  266.       local
  267.          ct: TYPE;
  268.          id: INTEGER;
  269.       do
  270.          ct := rc.current_type;
  271.          id := rc.id;
  272.          body.copy(var);
  273.          body.extend('=');
  274.          if is_off then
  275.             if ct.need_c_struct then
  276.                body.append("malloc(sizeof(*");
  277.                body.append(var);
  278.                body.append("));%N*");
  279.                body.append(var);
  280.                body.append("=M");
  281.                id.append_in(body);
  282.             else
  283.                -- Object has no attributes :
  284.                body.append("malloc(1)");
  285.             end;
  286.          elseif var = fz_eiffel_root_object then
  287.             body.append("malloc(sizeof(double)+sizeof(*eiffel_root_object));%N%
  288.                         %*eiffel_root_object=M");
  289.             id.append_in(body);
  290.          else
  291.             body.append(fz_new);
  292.             id.append_in(body);
  293.             body.append(fz_c_no_args_function);
  294.          end;
  295.          body.append(fz_00);
  296.          cpp.put_string(body);
  297.       end;
  298.  
  299. feature {MANIFEST_STRING_POOL}
  300.  
  301.    new_manifest_string_in(c_code: STRING; string_at_run_time: BOOLEAN) is
  302.       do
  303.          if is_off or else not string_at_run_time then
  304.             c_code.append("malloc(sizeof(T7));%N");
  305.          else
  306.             c_code.append("malloc(sizeof(gc7));%N%
  307.                           %((gc7*)s)->header.flag=FSOH_MARKED;%N");
  308.          end;
  309.          if string_at_run_time and then type_string.run_class.is_tagged then
  310.             c_code.append("s->id=7;%N");
  311.          end;
  312.       end;
  313.  
  314.    new_native9_in(c_code: STRING; string_at_run_time: BOOLEAN) is
  315.       do
  316.          if is_off or else not string_at_run_time then
  317.             c_code.append(as_malloc);
  318.          else
  319.             c_code.append(fz_new);
  320.             c_code.extend('9');
  321.          end;
  322.       end;
  323.  
  324. feature
  325.  
  326.    mark_for(c_code: STRING; entity: STRING; rc: RUN_CLASS) is
  327.          -- Add `c_code' to mark `entity' of class `rc'.
  328.       require
  329.          not is_off;
  330.          rc.current_type.need_gc_mark_function
  331.       local
  332.          ct: TYPE;
  333.          r: ARRAY[RUN_CLASS];
  334.       do
  335.          r := rc.running;
  336.          if r /= Void then
  337.             ct := rc.current_type;
  338.             if ct.is_reference or else ct.is_native_array then
  339.                c_code.append("if(NULL!=");
  340.                c_code.append(entity);
  341.                c_code.extend(')');
  342.             end;
  343.             if r.count > 1 then
  344.                cpp.incr_switch_count;
  345.                if not run_class_list.fast_has(rc) then
  346.                   run_class_list.add_last(rc);
  347.                end;
  348.                c_code.extend('X');
  349.                ct.gc_mark_in(c_code);
  350.             else
  351.                cpp.incr_direct_call_count;
  352.                r.first.current_type.gc_mark_in(c_code);
  353.             end;
  354.             c_code.extend('(');
  355.             if ct.is_expanded then
  356.                if ct.is_user_expanded then
  357.                   c_code.extend('&');
  358.                end;
  359.             else
  360.                c_code.append(fz_cast_void_star);
  361.             end;
  362.             c_code.extend('(');
  363.             c_code.append(entity);
  364.             c_code.append(fz_16);
  365.          end;
  366.       end;
  367.  
  368. feature {C_PRETTY_PRINTER}
  369.  
  370.    gc_info_before_exit is
  371.       require
  372.          cpp.on_c
  373.       do
  374.          if is_off then
  375.          elseif info_flag then
  376.             cpp.put_string("printf(%"==== Last GC before exit ====\n%");%N%
  377.                            %gc_start();%N");
  378.          end;
  379.          if not is_off and then dispose_flag then
  380.             cpp.put_string("gc_dispose_before_exit();%N");
  381.          end;
  382.       end;
  383.  
  384. feature {NONE}
  385.  
  386.    run_class_list: FIXED_ARRAY[RUN_CLASS] is
  387.       once
  388.          !!Result.with_capacity(32);
  389.       end;
  390.  
  391.    switch_for(rc: RUN_CLASS) is
  392.       local
  393.          ct: TYPE;
  394.          r: ARRAY[RUN_CLASS];
  395.       do
  396.          header.clear;
  397.          header.append(fz_void);
  398.          header.extend(' ');
  399.          header.extend('X');
  400.          ct := rc.current_type;
  401.          ct.gc_mark_in(header);
  402.          header.extend('(');
  403.          header.append(fz_t0_star);
  404.          header.extend('o');
  405.          header.extend(')');
  406.          body.clear;
  407.          r := rc.running;
  408.          sort_running(r);
  409.          body.append("{int i=o->id;%N");
  410.          c_dicho(r,1,r.upper);
  411.          body.extend('}');
  412.          cpp.put_c_function(header,body);
  413.       end;
  414.  
  415.    c_dicho(r: ARRAY[RUN_CLASS]; bi, bs: INTEGER) is
  416.          -- Produce dichotomic inspection code for Current id.
  417.       require
  418.          bi <= bs
  419.       local
  420.          m: INTEGER;
  421.          rc: RUN_CLASS;
  422.       do
  423.          if bi = bs then
  424.             rc := r.item(bi);
  425.             rc.current_type.gc_mark_in(body);
  426.             body.extend('(');
  427.             body.extend('(');
  428.             body.extend('T');
  429.             rc.id.append_in(body);
  430.             body.extend('*');
  431.             body.extend(')');
  432.             body.extend('o');
  433.             body.extend(')');
  434.             body.append(fz_00);
  435.          else
  436.             m := (bi + bs) // 2;
  437.             rc := r.item(m);
  438.             body.append("if (i <= ");
  439.             rc.id.append_in(body);
  440.             body.append(") {%N");
  441.             c_dicho(r,bi,m);
  442.             body.append("} else {%N");
  443.             c_dicho(r,m + 1,bs);
  444.             body.extend('}');
  445.          end;
  446.       end;
  447.  
  448.   just_before_mark(rcd: DICTIONARY[RUN_CLASS,STRING]) is
  449.       require
  450.          not is_off
  451.       local
  452.          i: INTEGER;
  453.          rc: RUN_CLASS;
  454.       do
  455.          from
  456.             i := 1;
  457.          until
  458.             i > rcd.count
  459.          loop
  460.             rc := rcd.item(i);
  461.             rc.just_before_gc_mark_in(body);
  462.             i := i + 1;
  463.          end;
  464.       end;
  465.  
  466.    define_gc_info(rcd: DICTIONARY[RUN_CLASS,STRING]) is
  467.       require
  468.          info_flag
  469.       local
  470.          i: INTEGER;
  471.          rc: RUN_CLASS;
  472.       do
  473.          header.clear;
  474.          header.append(fz_void);
  475.          header.extend(' ');
  476.          header.append(fz_gc_info);
  477.          header.append(fz_c_void_args);
  478.          body.clear;
  479.          body.append("printf(%"--------------------\n%");%N");
  480.          from
  481.             i := 1;
  482.          until
  483.             i > rcd.count
  484.          loop
  485.             rc := rcd.item(i);
  486.             rc.gc_info_in(body);
  487.             i := i + 1;
  488.          end;
  489.          body.append(
  490.            "printf(%"Stack size = %%d\n%",gc_stack_size());%N%
  491.            %printf(%"GC Main Table:\n%");%N%
  492.            %printf(%" gcmt_used = %%d\n%",gcmt_used);%N%
  493.            %printf(%" gcmt_max = %%d\n%",gcmt_max);%N%
  494.            %printf(%"Fixed Size Chunk(s):\n%");%N%
  495.            %printf(%" fsocfl = %%d\n%",fsocfl_count());%N%
  496.            %printf(%" fsoc_count = %%d\n%",fsoc_count);%N%
  497.            %printf(%" fsoc_count_ceil = %%d\n%",fsoc_count_ceil);%N%
  498.            %printf(%"Native Array(s):\n%");%N%
  499.            %printf(%" rsoc_count = %%d\n%",rsoc_count);%N%
  500.            %printf(%" rsoc_count_ceil = %%d\n%",rsoc_count_ceil);%N%
  501.            %rsocfl_info();%N%
  502.            %printf(%"GC called %%d time(s)\n%",gc_start_count);%N%
  503.            %printf(%"--------------------\n%");%N");
  504.          cpp.put_c_function(header,body);
  505.       end;
  506.  
  507.    define_gc_start(root_type: TYPE; rcd: DICTIONARY[RUN_CLASS,STRING]) is
  508.       do
  509.          body.clear;
  510.          body.append("if(gc_is_off)return;%N%
  511.                    %if(garbage_delayed())return;%N");
  512.          if info_flag then
  513.             body.append("printf(%"==== Before  GC ====\n%");%N%
  514.                         %gc_info();%N");
  515.          end
  516.          body.append(
  517.             "gcmt_tail_addr=(((char*)(gcmt[gcmt_used-1]))+%
  518.             %(gcmt[gcmt_used-1])->size);%N%
  519.             %((gc");
  520.          root_type.id.append_in(body);
  521.          body.append("*)eiffel_root_object)->header.flag=FSOH_UNMARKED;%N");
  522.          just_before_mark(rcd);
  523.          body.append(fz_gc_mark);
  524.          root_type.id.append_in(body);
  525.          body.append("(eiffel_root_object);%N%
  526.                      %manifest_string_mark1();%N%
  527.                      %once_function_mark();%N");
  528.          if run_control.generator_used then
  529.             body.append("{int i=SE_MAXID-1;%N%
  530.                         %while(i>=0){%N%
  531.                         %if(g[i]!=NULL)gc_mark9((g[i])->_storage);%N%
  532.                         %i--;}%N}%N");
  533.          end;
  534.          if run_control.generating_type_used then
  535.             body.append("{int i=SE_MAXID-1;%N%
  536.                         %while(i>=0){%N%
  537.                         %if(t[i]!=NULL)gc_mark9((t[i])->_storage);%N%
  538.                         %i--;}%N}%N");
  539.          end;
  540.          body.append("mark_stack_and_registers();%N%
  541.                      %gc_sweep();%N%
  542.                      %gc_start_count++;%N");
  543.          if info_flag then
  544.             body.append("gc_info();");
  545.          end
  546.          cpp.put_c_function("void gc_start(void)",body);
  547.       end;
  548.  
  549.    header: STRING is
  550.       once
  551.          !!Result.make(64);
  552.       end;
  553.  
  554.    body: STRING is
  555.       once
  556.          !!Result.make(512);
  557.       end
  558.  
  559.    fsoc_size: INTEGER is 8192; -- Fixed Size Objects Chunks Size.
  560.  
  561.    rsoc_size: INTEGER is 32768; -- ReSizable Objects Chunks Size.
  562.  
  563.    dispose_flag: BOOLEAN;
  564.  
  565. invariant
  566.  
  567.    info_flag implies not is_off
  568.  
  569. end -- GC_HANDLER
  570.  
  571.