home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / dev / lang / umbscheme / src / architecture.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-30  |  13.9 KB  |  651 lines

  1. /* architecture.c -- UMB Scheme, symbol table, stacks and heap.
  2.  
  3. UMB Scheme Interpreter                  $Revision: 2.12 $
  4. Copyright (C) 1988, 1991 William R Campbell
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. UMB Scheme was written by Bill Campbell with help from Karl Berry,
  21. Barbara Dixey, Ira Gerstein, Mary Glaser, Kathy Hargreaves, Bill McCabe,
  22. Long Nguyen, Susan Quina, Jeyashree Sivasubram, Bela Sohoni and Thang Quoc Tran.
  23.  
  24. For additional information about UMB Scheme, contact the author:
  25.  
  26.     Bill Campbell
  27.     Department of Mathematics and Computer Science
  28.     University of Massachusetts at Boston
  29.     Harbor Campus
  30.     Boston, MA 02125
  31.  
  32.     Telephone: 617-287-6449        Internet: bill@cs.umb.edu
  33.  
  34. */
  35.  
  36. #include <signal.h>
  37. #include "portable.h"
  38. #include "io.h"
  39. #include "eval.h"
  40. #include "object.h"
  41. #include "architecture.h"
  42. #include "steering.h"
  43. #include "debug.h"
  44. #include "primitive.h"
  45. #include "number.h"
  46.  
  47. Public Object     Expression_Register, Value_Register, Environment_Register, 
  48.         Function_Register, Arguments_Register, State_Register;
  49.  
  50. Public ELabel    PC_Register;
  51.  
  52. Public    Object    Value_Debugged, State_Debugged;
  53.  
  54. Public    ELabel    PC_Debugged;
  55.  
  56. Public    Integer Arg_Stack_Ptr = 0;
  57. Public    Integer    Debugged_Ptr  = 0;
  58. Public    Object    Arg_Stack[ARG_STACK_SIZE];
  59.  
  60. /* Garbage collector declarations. */
  61.  
  62. Public    Boolean    Allocating = FALSE;
  63. Public    Boolean Show_GC_Messages = TRUE;
  64.  
  65. Private Integer Free = 0;        /* First free location. */
  66. Private Integer Working = 0;        /* Space allocations come from this. */
  67. Private Integer Fallow = 1;        /* The half currently not in use. */
  68. Private Byte * Heap[2] = { NULL,NULL};    /* Two spaces. */
  69.  
  70. #define INITIAL_HEAPSIZE     200000
  71. #define MAX_HEAPSIZE          800000
  72. #define    ENLARGEMENT_FACTOR    2
  73. #define DESIRED_RECLAIMATION    0.2
  74.  
  75. Private Integer Heapsize = INITIAL_HEAPSIZE;
  76. Private    Boolean    Enable_Heap_Enlargement = TRUE;
  77. Private    Integer    Next_Heapsize = INITIAL_HEAPSIZE;
  78.  
  79.  
  80. typedef struct entry_structure
  81. {
  82.     Object Symbol;
  83.     struct entry_structure *Next;
  84. } Entry;
  85.  
  86.  
  87. Private Entry * Make_Entry();
  88.  
  89. Private    void Init_Heap(size)
  90.  
  91. Integer size;
  92.  
  93. {
  94.     if (Heap[0] == NULL && Heap[1] == NULL )
  95.     {
  96.         Heap[0] = (Byte *)malloc( (unsigned) (size+ALIGNMENT));
  97.         Heap[1] = (Byte *)malloc( (unsigned) (size+ALIGNMENT));
  98.     }
  99.  
  100.     if ( Heap[0] == NULL || Heap[1] == NULL )
  101.     {
  102.         Output( "\nPANIC: Not enough memory for the heap.\n" );
  103.         exit(1);
  104.     }
  105.  
  106.     Free = 0;
  107.     Working = 0;
  108.     Fallow = 1;
  109. }
  110.  
  111. /* Get the current size of the heap. */
  112.  
  113. Public void Get_Heap_Size()
  114. {
  115.     Integer_To_Number(Heapsize - Free);
  116. }
  117.  
  118. Public void Get_Arg_Stack_Ptr()
  119. {
  120.     Integer_To_Number( Arg_Stack_Ptr );
  121. }
  122.  
  123.  
  124.  
  125. /* Allocate some memory from the working space. */
  126.  
  127. Public Object Allocate(size)
  128.  
  129.     Integer size;
  130.  
  131. {
  132.     Object    new;
  133.     void    Garbage_Collect();
  134.  
  135.     Allocating = TRUE;
  136.  
  137.     if (Free + size >= Heapsize)
  138.     {
  139.         /* Not enough space. */
  140.         Garbage_Collect();
  141.     }
  142.  
  143.     if (Free + size < Heapsize)
  144.     {
  145.         /* Enough space now, or was before. */
  146.         new = (Object)&Heap[Working][Free];
  147. #if (ALIGNMENT-1)
  148.         /* Alignment (if not 1; defined in portable.h) */
  149.  
  150.         Free += ((size+ALIGNMENT-1)/ALIGNMENT)*ALIGNMENT;
  151. #else
  152.         Free += size;
  153. #endif
  154.     }
  155.     else
  156.     {
  157.         Panic( "Memory Exhausted" );
  158.         new =  Nil; 
  159.     }
  160.  
  161.     if ( Control_C )
  162.     {
  163.         Control_C = FALSE;
  164.         Allocating = FALSE;
  165.         Handler( SIGINT );
  166.     }
  167.     Allocating = FALSE;
  168.  
  169.     return new;
  170. }
  171.  
  172.  
  173. Public void Garbage_Collect()
  174. {
  175.     Integer this_argument;
  176.     Integer orig_free = Free;
  177.     Byte    *new_heap[2] ;
  178.     Character temp_string[120];
  179.     
  180.     if ( Show_GC_Messages )
  181.     {
  182.         Output( "GCing... " );
  183.     }
  184.  
  185.     if ( Next_Heapsize > Heapsize )
  186.     {
  187.         /* Allocate a new, larger, heap */
  188.  
  189.         new_heap[0] = NULL;
  190.         new_heap[1] = NULL;
  191.         new_heap[0] = (Byte *) malloc((unsigned) Next_Heapsize);
  192.         new_heap[1] = (Byte *) malloc((unsigned) Next_Heapsize);
  193.  
  194.         if ( new_heap[0] == NULL || new_heap[1] == NULL )
  195.         {
  196.             /* Reallocation has failed  -- Disable enlargement */
  197.  
  198.             if ( new_heap[0] != NULL ) free( new_heap[0] );
  199.             if ( new_heap[1] != NULL ) free( new_heap[1] );
  200.             Enable_Heap_Enlargement = FALSE;
  201.             Next_Heapsize = Heapsize;
  202.         }
  203.         else
  204.         {
  205.             /* Enlarge the current fallow (next working) heap. */
  206.             free( Heap[Fallow] );
  207.             Heap[Fallow] = new_heap[Fallow];
  208.         }
  209.     }
  210.  
  211.     /* Exchange spaces. */
  212.     Working = 1 - Working;
  213.     Fallow = 1 - Fallow;
  214.  
  215.     /* Nothing's allocated yet in the new space. */
  216.     Free = 0;
  217.  
  218.     /* Garbage collect the (object) registers. */
  219.     Relocate(&Expression_Register);
  220.     Relocate(&Value_Register);
  221.     Relocate(&Environment_Register);
  222.     Relocate(&Function_Register);
  223.     Relocate(&Arguments_Register);
  224.     Relocate(&State_Register);
  225.  
  226.     /* Garbage collect the (object) debugged registers */
  227.  
  228.     Relocate(&Value_Debugged);
  229.     Relocate(&State_Debugged);
  230.  
  231.     /* And the special objects. */
  232.     Relocate(&Nil);
  233.     Relocate(&The_Global_Environment);
  234.     Relocate(&The_True_Object);
  235.     Relocate(&The_False_Object);
  236.     Relocate(&The_Eof_Object);
  237.     Relocate(&Current_Input_Port);
  238.     Relocate(&Current_Output_Port);
  239.     Relocate(&The_Transcript_Port);
  240.     Relocate(&The_Dot_Object);
  241.     Relocate(&The_Rparen_Object);
  242.  
  243.     /* Debugger Registers */
  244.     Relocate(&Traced_Procedures);
  245.  
  246.     /* And the special symbols. */
  247.     Relocate(&The_Undefined_Symbol);
  248.     Relocate(&The_Syntactic_Keyword);
  249.     Relocate(&An_Argument);
  250.     Relocate("E_Symbol);
  251.     Relocate(&DEFINE_Symbol);
  252.     Relocate(&SET_Symbol);
  253.     Relocate(&IF_Symbol);
  254.     Relocate(&MACRO_Symbol);
  255.     Relocate(&BEGIN_Symbol);
  256.     Relocate(&DELAY_Symbol);
  257.     Relocate(&LAMBDA_Symbol);
  258.  
  259.     /* Now gc the stack... */
  260.     for (this_argument = 0; this_argument < Arg_Stack_Ptr; 
  261.                 this_argument++)
  262.     {
  263.         Relocate(&Arg_Stack[this_argument]);
  264.     }
  265.  
  266.     /* ...and the symbols. */
  267.     Symbol_Hash_Iterate(Relocate);
  268.  
  269.     if ( Next_Heapsize != Heapsize )
  270.     {
  271.         /* Enlarge the current fallow (previous working) heap. */
  272.         free( Heap[Fallow] );
  273.         Heap[Fallow] = new_heap[Fallow];
  274.         Heapsize = Next_Heapsize;
  275.     }
  276.  
  277.     if ( Show_GC_Messages )
  278.     {
  279.         sprintf( temp_string,
  280.          "%d bytes collected, %d bytes used, heapsize %d bytes.\n", 
  281.          orig_free-Free, Free, Heapsize );
  282.             Output(temp_string);
  283.     }
  284.  
  285.     if ( Enable_Heap_Enlargement && Heapsize < MAX_HEAPSIZE )
  286.     {
  287.         /* Decide whether to enlarge heap at next garbage collection */
  288.  
  289.         if ( (float) Free / (float) Heapsize > DESIRED_RECLAIMATION )
  290.         {
  291.             Next_Heapsize = Heapsize * ENLARGEMENT_FACTOR;
  292.             if ( Next_Heapsize > MAX_HEAPSIZE )
  293.             {
  294.                 Next_Heapsize = MAX_HEAPSIZE;
  295.                 if ( Show_GC_Messages )
  296.                  Output("Disabling enlargement due to size.\n");
  297.             }
  298.         }
  299.     }
  300. }
  301.  
  302.  
  303. Public void Relocate( old )
  304.  
  305.     Object * old;
  306. {
  307.     if ( *old != NULL )
  308.     {
  309.         if (Is_Forwarded(*old))
  310.         {
  311.             *old = Get_Forwarding_Address(*old);
  312.         }
  313.         else
  314.         {
  315.             *old = GC_Object(*old);
  316.         }
  317.     }
  318. }
  319.  
  320.  
  321.  
  322. Public Object Move_Object(old_object, size)
  323.  
  324.     Object old_object;
  325.     Integer size;
  326. {
  327.     Byte *new, *old;
  328.     Object new_object;
  329.  
  330.     new_object = Allocate(size); /* GC never called during GC */
  331.     old = (Byte *) old_object;
  332.     new = (Byte *) new_object;
  333.  
  334.     for (; size > 0; size--)
  335.     {
  336.         *new++ = *old++;
  337.     }
  338.  
  339.     Set_Forwarding_Address(old_object,new_object);
  340.     return( new_object );
  341. }
  342.  
  343. /* Symbol table/environment handling stuff. */
  344.  
  345. Public void Assign(var, value, env)
  346.     
  347.     Object var, value, env;
  348. {
  349.     Object*    location;
  350.     Object* how;
  351.     Integer    frame;
  352.  
  353.     if ( Is_Local_Variable( var ) )
  354.     {
  355.         for ( frame = 0;
  356.               frame < Get_Variable_Frame_Number( var );
  357.                   frame++ ) env = Get_Environment_Frame_Previous( env );
  358.         location = &Get_Environment_Frame_Binding_Value( env ,
  359.                 Get_Variable_Displacement( var ) );
  360.         how = &Get_Environment_Frame_Binding_How( env ,
  361.                 Get_Variable_Displacement( var ) );
  362.     }
  363.     else
  364.     {
  365.         location = &Get_Global_Binding(Get_Variable_Symbol( var ) );
  366.         how = &Get_Symbol_How(Get_Variable_Symbol( var ) );
  367.     }
  368.  
  369.     if (*location == The_Undefined_Symbol)
  370.     {
  371.         Error1("`%s' is undefined; you can't assign to it", 
  372.                 Get_Symbol_Name(Get_Variable_Symbol(var)));
  373.     } 
  374.  
  375.     *location = value;
  376.     *how = Expression_Register;
  377.     Value_Register = value;
  378. }
  379.  
  380. Public void Define(var, value, env)
  381.  
  382.     Object var, value, env;
  383. {
  384.     Object*    location;
  385.     Object* how;
  386.  
  387.     if ( Is_Local_Variable( var )  )
  388.     {
  389.         /* We know it's frame 0 (the most recent);
  390.            otherwise, compile_form() would have caught it */
  391.  
  392.         location = &Get_Environment_Frame_Binding_Value( env ,
  393.                 Get_Variable_Displacement( var ) );
  394.         how = &Get_Environment_Frame_Binding_How( env ,
  395.                 Get_Variable_Displacement( var ) );
  396.  
  397.         if (*location != The_Undefined_Symbol)
  398.         {
  399.             Error1("`%s' cannot be defined twice in the same scope",
  400.                 Get_Symbol_Name(Get_Variable_Symbol( var)));
  401.         } 
  402.     
  403.     }
  404.     else
  405.     {
  406.         location = &Get_Global_Binding(Get_Variable_Symbol( var ) );
  407.         how = &Get_Symbol_How(Get_Variable_Symbol( var ) );
  408.         Get_Symbol_User_Defined(Get_Variable_Symbol( var )) = 
  409.             Prelude_Complete;
  410.     }
  411.  
  412.     *location = value;
  413.     *how = Expression_Register;
  414.     Value_Register = Get_Variable_Symbol( var );
  415.  
  416.     if ( Is_Procedure( value ) )
  417.     {
  418.         Get_Procedure_Name( value ) = Get_Symbol_Name( Value_Register );
  419.     }
  420. }
  421.  
  422. /* Extend_Environment makes a new environment to be added to the top of 
  423. the environment stack. */
  424.  
  425. Public void Extend_Environment(actual_count)
  426.  
  427.     Integer actual_count;
  428. {
  429.     Object old_frame = Get_Procedure_Frame(Function_Register);
  430.     Integer formal_count = Get_Procedure_Numargs(Function_Register);
  431.     Boolean has_rest = Get_Procedure_Has_Rest(Function_Register);
  432.  
  433.     if (has_rest && actual_count < formal_count)
  434.     {
  435.         Display_Error(
  436.         "Not enough actuals in the following procedure call", 
  437.         Expression_Register);
  438.     } 
  439.     else if (! has_rest && actual_count != formal_count)
  440.     {
  441.         Display_Error(
  442.         "Wrong number of actuals in the following procedure call", 
  443.                    Expression_Register);
  444.     }
  445.  
  446.     Environment_Register =
  447.         Copy_Object( old_frame, 
  448.              (Integer) Environment_Frame_Size( 
  449.                             Get_Environment_Frame_Size(old_frame)));
  450.  
  451.     Get_Environment_Frame_Previous(Environment_Register) =
  452.         Get_Procedure_Environment(Function_Register);
  453.  
  454.     if (has_rest)
  455.     {
  456.         Integer rest_count = actual_count - formal_count;
  457.  
  458.         /* Construct the list for the rest argument. */
  459.         Push(Nil);   /* The end of our list. */
  460.         while (rest_count--)
  461.         {
  462.             Make_Pair();
  463.             Push(Value_Register);
  464.         }
  465.         Get_Environment_Frame_Binding_Value(Environment_Register,
  466.                           formal_count) = Top(1);
  467.         Pop(1);
  468.     }
  469.  
  470.     actual_count = formal_count;
  471.     while (formal_count--)
  472.     {
  473.         Get_Environment_Frame_Binding_Value(Environment_Register, 
  474.                  formal_count) = Top(actual_count-formal_count);
  475.     }
  476.     Pop(actual_count);
  477. }
  478.  
  479.  
  480. Public Object Copy_Object(old_object, size)
  481.  
  482.     Object old_object;
  483.     Integer size;
  484. {
  485.     Byte *new, *old;
  486.     Object new_object;
  487.  
  488.     Push( old_object );    /* Save from GC */
  489.     new_object = Allocate(size);
  490.     old = (Byte *) Top(1);
  491.     Pop( 1 );
  492.     new = (Byte *) new_object;
  493.  
  494.     for (; size > 0; size--)
  495.     {
  496.         *new++ = *old++;
  497.     }
  498.  
  499.     return( new_object );
  500. }
  501.  
  502.  
  503. #define HASH_TABLE_SIZE 1009
  504.  
  505. Private Entry * Symbol_Hash_Table[HASH_TABLE_SIZE];
  506.  
  507.  
  508. Private Integer Hash(s)
  509.  
  510.     String s;
  511. {
  512.     /* From Aho, Sethi and Ullman */
  513.  
  514.     String p;
  515.     unsigned h = 0, g;
  516.     for ( p = s ; *p != '\0' ; p++ )
  517.     {
  518.         h = (h << 4) + (*p);
  519.         if ((g = (h & 0xf0000000)))
  520.         {
  521.             h = h ^ (g >> 24);
  522.             h = h ^ g;
  523.         }
  524.     }
  525.     return( h % HASH_TABLE_SIZE );
  526. }
  527.  
  528. Private void Init_Hash_Table()
  529. {
  530.     Integer this_entry;
  531.  
  532.     for (this_entry = 0; this_entry < HASH_TABLE_SIZE; this_entry++)
  533.         Symbol_Hash_Table[this_entry] = NULL;
  534. }
  535.  
  536. #define hash_entry Symbol_Hash_Table[hash_value]
  537.  
  538. Public Object Intern_Name(name)
  539.  
  540.     String name;
  541. {
  542.     Integer hash_value = Hash(name);
  543.  
  544.     if (hash_entry == NULL)
  545.     {
  546.         hash_entry = Make_Entry(name);
  547.         return hash_entry->Symbol;
  548.     }
  549.     else
  550.     {
  551.         Boolean at_end = FALSE;
  552.         Entry * this_entry = hash_entry;
  553.  
  554.         while (strcmp(name, Get_Symbol_Name(this_entry->Symbol)) != 0
  555.             && !(at_end = (this_entry->Next == NULL)))
  556.         {
  557.             this_entry = this_entry->Next;
  558.         }
  559.  
  560.         /* If at end of chain, add the entry. */
  561.         if (at_end)
  562.         {
  563.             this_entry->Next = Make_Entry(name);
  564.             return this_entry->Next->Symbol;
  565.         } 
  566.         else 
  567.         {
  568.             return this_entry->Symbol;
  569.         }
  570.     }
  571. }
  572.  
  573. /* Go through the hash table calling the operation on all its elements. */
  574.  
  575. Public    void Symbol_Hash_Iterate(operation)
  576.  
  577. void (*operation)();            /* Takes an &object. */
  578. {
  579.     Integer this_bucket;
  580.     Entry * this_entry;
  581.  
  582.     for (this_bucket = 0; this_bucket < HASH_TABLE_SIZE; this_bucket++)
  583.     {
  584.         for (this_entry = Symbol_Hash_Table[this_bucket];
  585.             this_entry != NULL;
  586.             this_entry = this_entry->Next )
  587.         {
  588.             (*operation)(&(this_entry->Symbol));
  589.         }
  590.     }
  591. }
  592.  
  593.  
  594. Private Entry * Make_Entry(name)
  595.  
  596.     String name;
  597. {
  598.     Entry * new = (Entry *) malloc(sizeof(Entry));
  599.  
  600.     if ( new == NULL )
  601.     {
  602.         Panic( "Out of space in making hash entry" );
  603.     }
  604.  
  605.     Make_Symbol(name);
  606.     new->Symbol = Value_Register;
  607.     new->Next = NULL;
  608.  
  609.     return new;
  610. }
  611.  
  612.  
  613. /* Push and pop State Frames. */
  614.  
  615. Public void Save()
  616. {
  617.     Make_State_Frame();
  618.  
  619.     Get_State_Frame_Expression(Value_Register) = Expression_Register;
  620.     Get_State_Frame_Environment(Value_Register) = Environment_Register;
  621.     Get_State_Frame_Function(Value_Register) = Function_Register;
  622.     Get_State_Frame_Arguments(Value_Register) = Arguments_Register;
  623.     Get_State_Frame_PC(Value_Register) = PC_Register;
  624.     Get_State_Frame_State(Value_Register) = State_Register;
  625.     Get_State_Frame_Top(Value_Register) = Arg_Stack_Ptr;
  626.  
  627.  
  628.     State_Register = Value_Register;
  629. }
  630.  
  631.  
  632. Public void Restore()
  633. {
  634.         /* Note this does not mess with the Value_Register. */
  635.  
  636.     Expression_Register = Get_State_Frame_Expression(State_Register);
  637.     Environment_Register = Get_State_Frame_Environment(State_Register);
  638.     Function_Register = Get_State_Frame_Function(State_Register);
  639.     Arguments_Register = Get_State_Frame_Arguments(State_Register);
  640.     PC_Register = Get_State_Frame_PC(State_Register);
  641.     Arg_Stack_Ptr = Get_State_Frame_Top(State_Register);
  642.     State_Register = Get_State_Frame_State(State_Register);
  643. }
  644.  
  645.  
  646. Public void Initialize_Architecture()
  647. {
  648.     Init_Heap(Heapsize);
  649.     Init_Hash_Table();
  650. }
  651.