DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T f

⟦cf7822b4b⟧ TextFile

    Length: 14774 (0x39b6)
    Types: TextFile
    Names: »fasdump.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/gnu-31mar87/scheme/microcode/fasdump.c« 

TextFile

/*          Hey EMACS, this is -*- C -*- code!                 */

/****************************************************************
*                                                               *
*                         Copyright (c) 1985                    *
*               Massachusetts Institute of Technology           *
*                                                               *
* This material was developed by the Scheme project at the      *
* Massachusetts Institute of Technology, Department of          *
* Electrical Engineering and Computer Science.  Permission to   *
* copy this software, to redistribute it, and to use it for any *
* purpose is granted, subject to the following restrictions and *
* understandings.                                               *
*                                                               *
* 1. Any copy made of this software must include this copyright *
* notice in full.                                               *
*                                                               *
* 2. Users of this software agree to make their best efforts (a)*
* to return to the MIT Scheme project any improvements or       *
* extensions that they make, so that these may be included in   *
* future releases; and (b) to inform MIT of noteworthy uses of  *
* this software.                                                *
*                                                               *
* 3.  All materials developed as a consequence of the use of    *
* this software shall duly acknowledge such use, in accordance  *
* with the usual standards of acknowledging credit in academic  *
* research.                                                     *
*                                                               *
* 4. MIT has made no warrantee or representation that the       *
* operation of this software will be error-free, and MIT is     *
* under no obligation to provide any services, by way of        *
* maintenance, update, or otherwise.                            *
*                                                               *
* 5.  In conjunction with products arising from the use of this *
* material, there shall be no use of the name of the            *
* Massachusetts Institute of Technology nor of any adaptation   *
* thereof in any advertising, promotional, or sales literature  *
* without prior written consent from MIT in each case.          *
*                                                               *
****************************************************************/

/* File: FASDUMP.C
   This file contains code for FASDUMP, BAND_DUMP, and BAND_LOAD.
*/

#include "scheme.h"
#include "primitive.h"
#include "dump.c"
\f


/* Some statics used freely in this file */
Pointer *NewFree, *NewMemTop, *Fixup, *Orig_New_Free;

/* (BAND_DUMP PROCEDURE FILE-NAME)
      [Primitive number 0xB7]
      Saves all of the heap and pure space on FILE-NAME.  When the
      file is loaded back using BAND_LOAD, PROCEDURE is called with an
      argument of NIL.
*/
Built_In_Primitive(Prim_Band_Dump, 2, "BAND-DUMP")
{ Pointer Combination, Ext_Prims;
  long Arg1Type;
  Primitive_2_Args();

  Band_Dump_Permitted();
  Arg1Type = Type_Code(Arg1);
  if ((Arg1Type != TC_CONTROL_POINT) &&
      (Arg1Type != TC_PRIMITIVE) &&
      (Arg1Type != TC_PRIMITIVE_EXTERNAL) &&
      (Arg1Type != TC_EXTENDED_PROCEDURE)) Arg_1_Type(TC_PROCEDURE);
  Arg_2_Type(TC_CHARACTER_STRING);
  if (!Open_Dump_File(Arg2, WRITE_FLAG))
    Primitive_Error(ERR_ARG_2_BAD_RANGE);
  /* Free cannot be saved around this code since Make_Prim_Exts will
     intern the undefined externals and potentially allocate space.
   */
  Ext_Prims = Make_Prim_Exts();
  Combination = Make_Pointer(TC_COMBINATION_1, Free);
  Free[COMB_1_FN] = Arg1;
  Free[COMB_1_ARG_1] = NIL;
  Free += 2;
  *Free++ = Combination;
  *Free++ = Ext_Prims;
  Write_File(Free-Heap_Bottom, Heap_Bottom, Free-2,
             Free_Constant-Constant_Space, Constant_Space, Free-1);
  fclose(File_Handle);
  return NIL;
}
\f


/* FASDUMP:
  
   Hideous and ugly ... in order to dump an object it must be traced
   (as in a garbage collection), but with some awful differences.
   First, the copy must have (a) the global value cell of symbols set
   to UNBOUND; (b) the danger bits cleared in all objects; and (c)
   variables uncompiled.  Second, and worse, all the broken hearts
   created during the process must be restored to their original
   values.  This last is done by growing the copy of the object in the
   bottom of spare heap, keeping track of the locations of broken
   hearts and original contents at the top of the spare heap.

   FASDUMP is called with three arguments:
   Argument 1: Base of spare heap
   Argument 2: Top of spare heap
   Argument 3: Hunk 3, #<Object to dump | File name | Flag>
               where the flag is #!true for a dump into constant
               space at reload time, () for a dump into heap.

   As with Purify, dumping an object for reloading into constant space
   requires dividing it into pure and constant parts and building a
   standard Pure/Constant block.
*/
\f


/* Copy of GCLoop, except (a) copies out of constant space into the
   object to be dumped; (b) changes symbols and variables as
   described; (c) clears danger bits as described; (d) keeps track of
   broken hearts and their original contents (e) End_Pointer and
   To_Pointer are now NewFree.
*/

#define	NORMAL_DUMP	0
#define PURE_COPY	1
#define CONSTANT_COPY	2

Boolean DumpLoop(Scan, Dump_Mode)
fast Pointer *Scan;
int Dump_Mode;
{ fast Pointer *Old;
  fast int Type_For_GC;
  Pointer New_Address, *Starting_Address;

  Starting_Address = Scan;
  if (Dump_Debug) printf( "Starting scan at %x\n", Scan);

/* DumpLoop continues on next page */
\f


/* DumpLoop, continued */

  for ( ; Scan < NewFree; Scan++)
  { *Scan &= ~DANGER_BIT;
    Type_For_GC = GC_Type(*Scan);
    if (Dump_Debug && *Scan != NIL)
      printf( "0x%x: %x|%x ... ",
              Scan, Type_Code(*Scan), Get_Integer(*Scan));
    if ((Type_For_GC == GC_Non_Pointer) ||
        ((Dump_Mode == PURE_COPY) &&
         ((Type_Code(*Scan) == TC_ENVIRONMENT) ||
          (Type_Code(*Scan) == TC_INTERNED_SYMBOL) ||
          (Type_Code(*Scan) == TC_UNINTERNED_SYMBOL) ||
          (Type_Code(*Scan) == TC_VARIABLE))))
    { Type_For_GC = Safe_Type_Code(*Scan);
      if (Consistency_Check)
	if ((Type_For_GC == TC_BROKEN_HEART) &&
            Address(*Scan) != 0)
        { printf("Broken heart in scan.\n");
          Microcode_Termination(TERM_EXIT);
        }
      if ((Type_For_GC == TC_MANIFEST_NM_VECTOR) ||
	  (Type_For_GC == TC_MANIFEST_SPECIAL_NM_VECTOR))
		/* Special headers meaning following block
		   contains no relocatable pointers */
      { if (Dump_Debug)
          printf( "skipping %d cells.",
                  Get_Integer(*Scan));
        Scan += Get_Integer(*Scan);
      }
      else if (Dump_Debug && *Scan != NIL)
             printf( "not a pointer.");
    }

/* DumpLoop continues on the next page */
\f


/* DumpLoop, continued */

    else /* A pointer object */
    { Old = Get_Pointer(*Scan);
      if ((Dump_Mode == CONSTANT_COPY) &&
          (Old > Starting_Address) && (Old < NewFree))
      { if (Dump_Debug) printf( "Skipping 0x%x", *Scan);
        continue;		/* Loop on ... */
      }
      if (Dump_Debug) printf( "From 0x%x", Old);
      if (Safe_Type_Code(*Old) == TC_BROKEN_HEART)
      { Store_Address(*Scan, Address(*Old));
        if (Dump_Debug) printf( ", To (BH) 0x%x",
                                Address(*Old));
      }
      else		/* Otherwise, it must be copied */
      { if (Dump_Debug) printf( ", To 0x%x", NewFree);
	New_Address = BROKEN_HEART_0 + C_To_Scheme(NewFree);
        { fast long i, Length;
          switch (Type_For_GC)
          { case GC_Non_Pointer:
              printf( "Non_Pointer copy?\n");
              Microcode_Termination(TERM_EXIT);

            case GC_Vector: Length = Vector_Length(*Scan)+1; break;

/* DumpLoop continues on the next page */
\f


/* DumpLoop, continued */

            case GC_Triple:  
              if (Safe_Type_Code(*Scan)==TC_VARIABLE)
              { *NewFree++ = *Old;
                *NewFree++ = UNCOMPILED_VARIABLE;
                *NewFree++ = NIL;
                Length = 0;
              }
              else Length = 3;
              break;

            default:        
              if (Safe_Type_Code(*Scan)==TC_UNINTERNED_SYMBOL)
	      { *NewFree++ = *Old;
                *NewFree++ = UNBOUND_OBJECT;
                Length = 0;
              }
              else if (Safe_Type_Code(*Scan)==TC_INTERNED_SYMBOL)
              { *NewFree++ = *Old;
		*NewFree++ = Make_Non_Pointer(TC_BROKEN_HEART, 0);
                Length = 0;
              }
	      else Length = 2;
              break;
          }
          if ((NewFree+Length+5) >= Fixup) return false;
          for (i=0; i < Length; i++) *NewFree++ = *Old++;
          if (Dump_Debug) printf( " copied %d words", Length);
        }
        *--Fixup = * Get_Pointer(*Scan);                   /* What it was.*/
        *--Fixup = Make_New_Pointer(TC_ADDRESS, *Scan);    /* Where it goes.*/
        *Get_Pointer(*Scan) = New_Address;
        Store_Address(*Scan, Address(New_Address));
      } /* End of else for ... == TC_BROKEN_HEART */
    } /* End of else for ... == GC_Type_Code */
    if (Dump_Debug && *Scan != NIL) printf( "\n");
  } /* End of FOR loop */
  return true;
} /* End of DumpLoop */
\f


/* (PRIMITIVE_FASDUMP Object-to-Dump File-Name Flag)
      [Primitive number 0x56]
      Dump an object into a file so that it can be loaded using
      PRIMITIVE_BINARY_FASLOAD.  A spare heap is required for this
      operation.  The first argument is the object to be dumped.  The
      second is the filename and the third a flag.  The flag, if
      #!TRUE, means that the object is to be dumped for reloading into
      constant space.  This is currently disabled. If the flag is NIL,
      it means that it will be reloaded into the heap.  The primitive
      returns #!TRUE or NIL indicating whether it successfully dumped
      the object (it can fail on an object that is too large).
*/
Built_In_Primitive(Prim_Prim_Fasdump, 3, "PRIMITIVE-FASDUMP")
{ Pointer Object, File_Name, Flag, *New_Object,
          *Addr_Of_New_Object, Prim_Exts;
  long Pure_Length, Length;
  Boolean To_Constant_Space;
  Primitive_3_Args();

  Object = Arg1;
  File_Name = Arg2;
  Flag = Arg3;
  if (Type_Code(File_Name) != TC_CHARACTER_STRING)
    Primitive_Error(ERR_ARG_2_WRONG_TYPE);
  if (!Open_Dump_File(File_Name, WRITE_FLAG))
    Primitive_Error(ERR_ARG_2_BAD_RANGE);
#ifdef CAN_DUMP_PURE
  if ((Flag != NIL) && (Flag != TRUTH))
#else
  if (Flag != NIL)
#endif
    Primitive_Error(ERR_ARG_3_WRONG_TYPE);

  Fasdump_Free_Calc(NewFree, NewMemTop, Orig_New_Free);
  Fixup = NewMemTop;
  Prim_Exts = Make_Prim_Exts();
  New_Object = NewFree;
  *NewFree++ = Object;
  *NewFree++ = Prim_Exts;

/* Prim_Primitive_Fasdump continues on next page */
\f


/* Prim_Primitive_Fasdump, continued */

#ifdef CAN_DUMP_PURE
  if (Flag==TRUTH)
  { if (!DumpLoop(New_Object, PURE_COPY))
    { fclose(File_Handle);
      Fasdump_Exit_Hook();
      return NIL;
    }
    Pure_Length = (NewFree-New_Object) + 1;
    *NewFree++ = Make_Non_Pointer(TC_MANIFEST_SPECIAL_NM_VECTOR, 1);
    *NewFree++ = Make_Non_Pointer(CONSTANT_PART, Pure_Length);
    if (!DumpLoop(New_Object, CONSTANT_COPY))
    { fclose(File_Handle);
      Fasdump_Exit_Hook();
      return NIL;
    }
    Length =  NewFree-New_Object+2;
    *NewFree++ = Make_Non_Pointer(TC_MANIFEST_SPECIAL_NM_VECTOR, 1);
    *NewFree++ = Make_Non_Pointer(END_OF_BLOCK, Length-1);
    Addr_Of_New_Object = Get_Pointer(New_Object[0]);
    Prim_Exts = New_Object[1];
    New_Object[0] = Make_Non_Pointer(TC_MANIFEST_SPECIAL_NM_VECTOR,
                                     Pure_Length);
    New_Object[1] = Make_Non_Pointer(PURE_PART, Length-1);
    Write_File(0, 0x000000, Addr_Of_New_Object,
               Length, New_Object, Prim_Exts);
    fclose(File_Handle);
  }

/* Fasdump continues on the next page */
\f


/* Fasdump, continued */

  else		/* Dumping for reload into heap */
#endif
  { if (!DumpLoop(New_Object, NORMAL_DUMP))
    { fclose(File_Handle);
      Fasdump_Exit_Hook();
      return NIL;
    }
    Length = NewFree-New_Object;
    Write_File(Length, New_Object, New_Object,
               0, ADDRESS_MASK, New_Object+1);
    fclose(File_Handle);
  }
  while (Fixup != NewMemTop)
  { Pointer *Fix_Address;
    Fix_Address = Get_Pointer(*Fixup++); /* Where it goes. */
    *Fix_Address = *Fixup++;             /* Put it there. */
  }
  Fasdump_Exit_Hook();
  return TRUTH;
}
\f


/* (BAND_LOAD FILE-NAME)
      [Primitive number 0xB9]
      Restores the heap and pure space from the contents of FILE-NAME,
      which is typically a file created by BAND_DUMP.  The file can,
      however, be any file which can be loaded with BINARY_FASLOAD.
*/
Built_In_Primitive(Prim_Band_Load, 1, "BAND-LOAD")
{ Pointer Save_FO, *Save_Free, *Save_Free_Constant, Save_Undefined,
          *Save_Stack_Pointer, *Save_Stack_Guard, Result;
  long Jump_Value;
  jmp_buf  Swapped_Buf, *Saved_Buf;
  Primitive_1_Arg();

  Save_Fixed_Obj(Save_FO);
  Save_Undefined = Undefined_Externals;
  Undefined_Externals = NIL;
  Save_Free = Free;
  Free = Heap_Bottom;
  Save_Free_Constant = Free_Constant;
  Free_Constant = Constant_Space;
  Save_Stack_Pointer = Stack_Pointer;
  Stack_Pointer = Stack_Top;
  Save_Stack_Guard = Stack_Guard;
  Set_Stack_Guard(Stack_Pointer - STACK_GUARD_SIZE);

/* Prim_Band_Load continues on next page */
\f


/* Prim_Band_Load, continued */

  /* There is some jiggery-pokery going on here to make sure
     that all returns from Fasload (including error exits) return to
     the clean-up code before returning on up the C call stack.
  */
  Saved_Buf = Back_To_Eval;
  Jump_Value = setjmp(Swapped_Buf);
  if (Jump_Value == 0)
  { Back_To_Eval = (jmp_buf *) Swapped_Buf;
    Result = Fasload(Arg1, false);
    Back_To_Eval = Saved_Buf;
    History = Make_Dummy_History();
    Store_Return(RC_END_OF_COMPUTATION);
    Store_Expression(NIL);
    Save_Cont();
    Store_Expression(Result);
    Store_Env(Make_Non_Pointer(GLOBAL_ENV, GO_TO_GLOBAL));
    Band_Load_Hook();
    longjmp(*Back_To_Eval, PRIM_DO_EXPRESSION);
  }
  else
  { Back_To_Eval = Saved_Buf;
    Free = Save_Free;
    Free_Constant = Save_Free_Constant;
    Stack_Pointer = Save_Stack_Pointer;
    Set_Stack_Guard(Save_Stack_Guard);
    Undefined_Externals = Save_Undefined;
    Restore_Fixed_Obj(Save_FO);
    if (Jump_Value == PRIM_INTERRUPT)
    { printf("\nFile too large for memory.\n");
      Jump_Value = ERR_FASL_FILE_BAD_DATA;
    }
    Primitive_Error(Jump_Value);
  }
}