From: cuz Date: Thu, 5 Jun 2003 16:50:01 +0000 (+0000) Subject: More stringpool use / memory savings X-Git-Tag: V2.12.0~1519 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=eb5637b6e4f49aaae32d442de10cee7062714483;p=cc65 More stringpool use / memory savings git-svn-id: svn://svn.cc65.org/cc65/trunk@2199 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/ld65/exports.c b/src/ld65/exports.c index 7520a1c9b..7aafb72b3 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -75,8 +75,12 @@ static unsigned ImpOpen = 0; /* Count of open imports */ static unsigned ExpCount = 0; /* Export count */ static Export** ExpPool = 0; /* Exports array */ +/* Defines for the flags in Import */ +#define IMP_INLIST 0x0001U /* Import is in exports list */ + /* Defines for the flags in Export */ -#define EXP_USERMARK 0x0001 +#define EXP_INLIST 0x0001U /* Export is in exports list */ +#define EXP_USERMARK 0x0002U /* User setable flag */ @@ -102,6 +106,7 @@ static Import* NewImport (unsigned char Type, ObjData* Obj) I->Obj = Obj; I->Exp = 0; I->Name = INVALID_STRING_ID; + I->Flags = 0; I->Type = Type; /* Return the new structure */ @@ -157,6 +162,24 @@ void InsertImport (Import* I) /* This is a dummy export */ ++ImpOpen; } + + /* Mark the import so we know it's in the list */ + I->Flags |= IMP_INLIST; +} + + + +void FreeImport (Import* I) +/* Free an import. NOTE: This won't remove the import from the exports table, + * so it may only be called for unused imports (imports from modules that + * aren't referenced). + */ +{ + /* Safety */ + PRECONDITION ((I->Flags & IMP_INLIST) == 0); + + /* Free the struct */ + xfree (I); } @@ -217,6 +240,24 @@ static Export* NewExport (unsigned char Type, unsigned Name, ObjData* Obj) +void FreeExport (Export* E) +/* Free an export. NOTE: This won't remove the export from the exports table, + * so it may only be called for unused exports (exports from modules that + * aren't referenced). + */ +{ + /* Safety */ + PRECONDITION ((E->Flags & EXP_INLIST) == 0); + + /* Free the export expression */ + FreeExpr (E->Expr); + + /* Free the struct */ + xfree (E); +} + + + void InsertExport (Export* E) /* Insert an exported identifier and check if it's already in the list */ { @@ -225,6 +266,9 @@ void InsertExport (Export* E) Import* Imp; unsigned Hash; + /* Mark the export as inserted */ + E->Flags |= EXP_INLIST; + /* Insert the export into any condes tables if needed */ if (IS_EXP_CONDES (E->Type)) { ConDesAddExport (E); @@ -243,35 +287,37 @@ void InsertExport (Export* E) Last = 0; L = HashTab[Hash]; do { - if (L->Name == E->Name) { + if (L->Name == E->Name) { /* This may be an unresolved external */ if (L->Expr == 0) { - /* This *is* an unresolved external */ + /* This *is* an unresolved external. Use the actual export + * in E instead of the dummy one in L. + */ E->Next = L->Next; E->ImpCount = L->ImpCount; E->ImpList = L->ImpList; - if (Last) { - Last->Next = E; - } else { + if (Last) { + Last->Next = E; + } else { HashTab[Hash] = E; - } + } ImpOpen -= E->ImpCount; /* Decrease open imports now */ - xfree (L); - /* We must run through the import list and change the + xfree (L); + /* We must run through the import list and change the * export pointer now. - */ - Imp = E->ImpList; - while (Imp) { - Imp->Exp = E; - Imp = Imp->Next; - } - } else { - /* Duplicate entry, ignore it */ - Warning ("Duplicate external identifier: `%s'", + */ + Imp = E->ImpList; + while (Imp) { + Imp->Exp = E; + Imp = Imp->Next; + } + } else { + /* Duplicate entry, ignore it */ + Warning ("Duplicate external identifier: `%s'", GetString (L->Name)); - } - return; + } + return; } Last = L; L = L->Next; @@ -491,15 +537,15 @@ static void CheckSymType (const Export* E) /* User defined export */ Warning ("Type mismatch for `%s', export in " "%s(%lu), import in %s(%lu)", - GetString (E->Name), + GetString (E->Name), GetSourceFileName (E->Obj, Imp->Pos.Name), - E->Pos.Line, + E->Pos.Line, GetSourceFileName (Imp->Obj, Imp->Pos.Name), Imp->Pos.Line); } else { /* Export created by the linker */ Warning ("Type mismatch for `%s', imported from %s(%lu)", - GetString (E->Name), + GetString (E->Name), GetSourceFileName (Imp->Obj, Imp->Pos.Name), Imp->Pos.Line); } @@ -557,7 +603,7 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data) static int CmpExpName (const void* K1, const void* K2) /* Compare function for qsort */ { - return strcmp (GetString ((*(Export**)K1)->Name), + return strcmp (GetString ((*(Export**)K1)->Name), GetString ((*(Export**)K2)->Name)); } @@ -728,11 +774,11 @@ void CircularRefError (const Export* E) /* Print an error about a circular reference using to define the given export */ { Error ("Circular reference for symbol `%s', %s(%lu)", - GetString (E->Name), + GetString (E->Name), GetSourceFileName (E->Obj, E->Pos.Name), E->Pos.Line); } - + diff --git a/src/ld65/exports.h b/src/ld65/exports.h index c28d49ed4..97a6eea63 100644 --- a/src/ld65/exports.h +++ b/src/ld65/exports.h @@ -65,6 +65,7 @@ struct Import { FilePos Pos; /* File position of reference */ struct Export* Exp; /* Matching export for this import */ unsigned Name; /* Name if not in table */ + unsigned char Flags; /* Generic flags */ unsigned char Type; /* Type of import */ }; @@ -103,12 +104,24 @@ typedef int (*ExpCheckFunc) (unsigned Name, void* Data); +void FreeImport (Import* I); +/* Free an import. NOTE: This won't remove the import from the exports table, + * so it may only be called for unused imports (imports from modules that + * aren't referenced). + */ + Import* ReadImport (FILE* F, ObjData* Obj); /* Read an import from a file and insert it into the table */ void InsertImport (Import* I); /* Insert an import into the table */ +void FreeExport (Export* E); +/* Free an export. NOTE: This won't remove the export from the exports table, + * so it may only be called for unused exports (exports from modules that + * aren't referenced). + */ + Export* ReadExport (FILE* F, ObjData* Obj); /* Read an export from a file */ diff --git a/src/ld65/library.c b/src/ld65/library.c index 8b3c868a5..327c142d9 100644 --- a/src/ld65/library.c +++ b/src/ld65/library.c @@ -49,9 +49,10 @@ #include "error.h" #include "exports.h" #include "fileio.h" +#include "library.h" #include "objdata.h" #include "objfile.h" -#include "library.h" +#include "spool.h" @@ -63,19 +64,18 @@ /* Library data */ static FILE* Lib = 0; -static char* LibName = 0; static unsigned ModuleCount = 0; static ObjData** Index = 0; /*****************************************************************************/ -/* Reading file data structures */ +/* Reading file data structures */ /*****************************************************************************/ -static void LibReadObjHeader (ObjData* O) +static void LibReadObjHeader (ObjData* O, const char* LibName) /* Read the header of the object file checking the signature */ { O->Header.Magic = Read32 (Lib); @@ -117,10 +117,14 @@ static ObjData* ReadIndexEntry (void) /* Create a new entry and insert it into the list */ ObjData* O = NewObjData (); - /* Module name/flags/MTime/Start/Size */ - O->Name = ReadStr (Lib); + /* Module name */ + char* Name = ReadStr (Lib); + O->Name = GetStringId (Name); + xfree (Name); + + /* Module flags/MTime/Start/Size */ O->Flags = Read16 (Lib); - Read32 (Lib); /* Skip MTime */ + O->MTime = Read32 (Lib); O->Start = Read32 (Lib); Read32 (Lib); /* Skip Size */ @@ -208,13 +212,14 @@ void LibAdd (FILE* F, const char* Name) * be satisfied. */ { - int Add; + unsigned LibName; + int HaveAdditions; unsigned I; LibHeader Header; /* Store the parameters, so they're visible for other routines */ Lib = F; - LibName = xstrdup (Name); + LibName = GetStringId (Name); /* Read the remaining header fields (magic is already read) */ Header.Magic = LIB_MAGIC; @@ -235,27 +240,31 @@ void LibAdd (FILE* F, const char* Name) * were added. */ do { - Add = 0; - for (I = 0; I < ModuleCount; ++I) { - ObjData* O = Index [I]; - if ((O->Flags & OBJ_REF) == 0) { - LibCheckExports (O); - if (O->Flags & OBJ_REF) { - /* The routine added the file */ - Add = 1; - } - } - } - } while (Add); + HaveAdditions = 0; + for (I = 0; I < ModuleCount; ++I) { + ObjData* O = Index [I]; + if ((O->Flags & OBJ_REF) == 0) { + LibCheckExports (O); + if (O->Flags & OBJ_REF) { + /* The routine added the file */ + HaveAdditions = 1; + } + } + } + } while (HaveAdditions); /* Add the files list and sections for all requested modules */ for (I = 0; I < ModuleCount; ++I) { + + /* Get the object data */ ObjData* O = Index [I]; + + /* Is this object file referenced? */ if (O->Flags & OBJ_REF) { /* Seek to the start of the object file and read the header */ fseek (Lib, O->Start, SEEK_SET); - LibReadObjHeader (O); + LibReadObjHeader (O, Name); /* Seek to the start of the files list and read the files list */ fseek (Lib, O->Start + O->Header.FileOffs, SEEK_SET); @@ -276,24 +285,29 @@ void LibAdd (FILE* F, const char* Name) fseek (Lib, O->Start + O->Header.SegOffs, SEEK_SET); ObjReadSections (Lib, O); - /* We have the data now */ - O->Flags |= OBJ_HAVEDATA; - } + /* Add a pointer to the library name */ + O->LibName = LibName; + + /* All references to strings are now resolved, so we can delete + * the module string pool. + */ + FreeObjStrings (O); + + /* Insert the object into the list of all used object files */ + InsertObjData (O); + + } else { - /* All references to strings are now resolved, so we can delete - * the module string pool. - */ - FreeObjStrings (O); + /* Unreferenced object file, remove it */ + FreeObjData (O); - /* Add a pointer to the library name */ - O->LibName = LibName; + } } /* Done. Close the file, release allocated memory */ fclose (F); xfree (Index); Lib = 0; - LibName = 0; ModuleCount = 0; Index = 0; } diff --git a/src/ld65/mapfile.c b/src/ld65/mapfile.c index 7a8eab44e..af4ad2191 100644 --- a/src/ld65/mapfile.c +++ b/src/ld65/mapfile.c @@ -60,7 +60,6 @@ void CreateMapFile (void) /* Create a map file */ { - ObjData* O; unsigned I; /* Open the map file */ @@ -72,28 +71,30 @@ void CreateMapFile (void) /* Write a modules list */ fprintf (F, "Modules list:\n" "-------------\n"); - O = ObjRoot; - while (O) { - if (O->Flags & OBJ_HAVEDATA) { - /* We've linked this module */ - if (O->LibName) { - /* The file is from a library */ - fprintf (F, "%s(%s):\n", O->LibName, GetObjFileName (O)); - } else { - fprintf (F, "%s:\n", GetObjFileName (O)); - } - for (I = 0; I < O->SectionCount; ++I) { - const Section* S = O->Sections [I]; - /* Don't include zero sized sections if not explicitly - * requested - */ - if (VerboseMap || S->Size > 0) { - fprintf (F, " %-15s Offs = %06lX Size = %06lX\n", - GetString (S->Seg->Name), S->Offs, S->Size); - } - } - } - O = O->Next; + for (I = 0; I < CollCount (&ObjDataList); ++I) { + + unsigned J; + + /* Get the object file */ + const ObjData* O = CollConstAt (&ObjDataList, I); + + /* Output the data */ + if (O->LibName != INVALID_STRING_ID) { + /* The file is from a library */ + fprintf (F, "%s(%s):\n", GetString (O->LibName), GetObjFileName (O)); + } else { + fprintf (F, "%s:\n", GetObjFileName (O)); + } + for (J = 0; J < O->SectionCount; ++J) { + const Section* S = O->Sections [J]; + /* Don't include zero sized sections if not explicitly + * requested + */ + if (VerboseMap || S->Size > 0) { + fprintf (F, " %-15s Offs = %06lX Size = %06lX\n", + GetString (S->Seg->Name), S->Offs, S->Size); + } + } } /* Write the segment list */ @@ -125,7 +126,7 @@ void CreateMapFile (void) void CreateLabelFile (void) /* Create a label file */ { - ObjData* O; + unsigned I; /* Open the label file */ FILE* F = fopen (LabelFileName, "w"); @@ -136,15 +137,14 @@ void CreateLabelFile (void) /* Print the labels for the export symbols */ PrintExportLabels (F); - /* Print debug symbols from all modules we have linked into the output file */ - O = ObjRoot; - while (O) { - if (O->Flags & OBJ_HAVEDATA) { - /* We've linked this module */ - PrintDbgSymLabels (O, F); + /* Create labels from all modules we have linked into the output file */ + for (I = 0; I < CollCount (&ObjDataList); ++I) { + + /* Get the object file */ + ObjData* O = CollAtUnchecked (&ObjDataList, I); - } - O = O->Next; + /* Output the labels */ + PrintDbgSymLabels (O, F); } /* If we should mark write protected areas as such, do it */ @@ -174,7 +174,7 @@ void CreateLabelFile (void) void CreateDbgFile (void) /* Create a debug info file */ { - ObjData* O; + unsigned I; /* Open the debug info file */ FILE* F = fopen (DbgFileName, "w"); @@ -183,14 +183,13 @@ void CreateDbgFile (void) } /* Print line infos from all modules we have linked into the output file */ - O = ObjRoot; - while (O) { - if (O->Flags & OBJ_HAVEDATA) { - /* We've linked this module */ - PrintDbgInfo (O, F); - - } - O = O->Next; + for (I = 0; I < CollCount (&ObjDataList); ++I) { + + /* Get the object file */ + ObjData* O = CollAtUnchecked (&ObjDataList, I); + + /* Output debug info */ + PrintDbgInfo (O, F); } /* Close the file */ diff --git a/src/ld65/objdata.c b/src/ld65/objdata.c index 484c5431f..6da81965c 100644 --- a/src/ld65/objdata.c +++ b/src/ld65/objdata.c @@ -41,6 +41,7 @@ /* ld65 */ #include "error.h" +#include "exports.h" #include "fileinfo.h" #include "objdata.h" #include "spool.h" @@ -53,11 +54,8 @@ -/* Object data list management */ -unsigned ObjCount = 0; /* Count of object files in the list */ -ObjData* ObjRoot = 0; /* List of object files */ -ObjData* ObjLast = 0; /* Last entry in list */ -ObjData** ObjPool = 0; /* Object files as array */ +/* Collection containing used ObjData objects */ +Collection ObjDataList = STATIC_COLLECTION_INITIALIZER; @@ -75,8 +73,9 @@ ObjData* NewObjData (void) /* Initialize the data */ O->Next = 0; - O->Name = 0; - O->LibName = 0; + O->Name = INVALID_STRING_ID; + O->LibName = INVALID_STRING_ID; + O->MTime = 0; O->Flags = 0; O->Start = 0; O->ExportCount = 0; @@ -90,24 +89,33 @@ ObjData* NewObjData (void) O->StringCount = 0; O->Strings = 0; - /* Link it into the list */ - if (ObjLast) { - ObjLast->Next = O; - ObjLast = O; - } else { - /* First entry */ - ObjRoot = ObjLast = O; - } - - /* One object file more now */ - ++ObjCount; - /* Return the new entry */ return O; } +void FreeObjData (ObjData* O) +/* Free an ObjData object. NOTE: This function works only for unused object + * data, that is, ObjData objects that aren't used because they aren't + * referenced. + */ +{ + /* Unused ObjData do only have the string pool, Exports and Imports. */ + while (O->ExportCount) { + FreeExport (O->Exports[--O->ExportCount]); + } + xfree (O->Exports); + while (O->ImportCount) { + FreeImport (O->Imports[--O->ImportCount]); + } + xfree (O->Imports); + FreeObjStrings (O); + xfree (O); +} + + + void FreeObjStrings (ObjData* O) /* Free the module string data. Used once the object file is loaded completely * when all strings are converted to global strings. @@ -122,6 +130,14 @@ void FreeObjStrings (ObjData* O) +void InsertObjData (ObjData* O) +/* Insert the ObjData object into the collection of used ObjData objects. */ +{ + CollAppend (&ObjDataList, O); +} + + + const char* GetObjString (const ObjData* O, unsigned Index) /* Get a string from the object file string table. Abort if the string index * is invalid. @@ -153,7 +169,7 @@ const char* GetObjFileName (const ObjData* O) * file is NULL. */ { - return O? O->Name : "[linker generated]"; + return O? GetString (O->Name) : "[linker generated]"; } diff --git a/src/ld65/objdata.h b/src/ld65/objdata.h index 8da6fc080..0174b733d 100644 --- a/src/ld65/objdata.h +++ b/src/ld65/objdata.h @@ -39,6 +39,7 @@ /* common */ +#include "coll.h" #include "objdefs.h" @@ -51,16 +52,14 @@ /* Values for the Flags field */ #define OBJ_REF 0x0001 /* We have a reference to this file */ -#define OBJ_HAVEDATA 0x0002 /* We have this object file already */ -#define OBJ_MARKED 0x0004 /* Generic marker bit */ - /* Internal structure holding object file data */ typedef struct ObjData ObjData; struct ObjData { - ObjData* Next; /* Linked list of all objects */ - char* Name; /* Module name */ - char* LibName; /* Name of library */ + ObjData* Next; /* Linked list of all objects */ + unsigned Name; /* Module name */ + unsigned LibName; /* Name of library */ + unsigned long MTime; /* Time of last modification */ ObjHeader Header; /* Header of file */ unsigned long Start; /* Start offset of data in library */ unsigned Flags; @@ -82,15 +81,13 @@ struct ObjData { -/* Object data list management */ -extern unsigned ObjCount; /* Count of files in the list */ -extern ObjData* ObjRoot; /* List of object files */ -extern ObjData* ObjLast; /* Last entry in list */ +/* Collection containing used ObjData objects */ +extern Collection ObjDataList; /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -98,11 +95,20 @@ extern ObjData* ObjLast; /* Last entry in list */ ObjData* NewObjData (void); /* Allocate a new structure on the heap, insert it into the list, return it */ +void FreeObjData (ObjData* O); +/* Free an ObjData object. NOTE: This function works only for unused object + * data, that is, ObjData objects that aren't used because they aren't + * referenced. + */ + void FreeObjStrings (ObjData* O); /* Free the module string data. Used once the object file is loaded completely * when all strings are converted to global strings. */ +void InsertObjData (ObjData* O); +/* Insert the ObjData object into the collection of used ObjData objects. */ + const char* GetObjString (const ObjData* O, unsigned Index); /* Get a string from the object file string table. Abort if the string index * is invalid. diff --git a/src/ld65/objfile.c b/src/ld65/objfile.c index ff9a14b57..7404b2cac 100644 --- a/src/ld65/objfile.c +++ b/src/ld65/objfile.c @@ -51,8 +51,9 @@ #include "fileio.h" #include "lineinfo.h" #include "objdata.h" -#include "segments.h" #include "objfile.h" +#include "segments.h" +#include "spool.h" @@ -62,15 +63,15 @@ -static const char* GetModule (const char* Name) -/* Get a module name from the file name */ +static unsigned GetModule (const char* Name) +/* Get a module name index from the file name */ { /* Make a module name from the file name */ const char* Module = FindName (Name); if (*Module == 0) { Error ("Cannot make module name from `%s'", Name); } - return Module; + return GetStringId (Module); } @@ -216,8 +217,7 @@ void ObjAdd (FILE* Obj, const char* Name) ObjReadHeader (Obj, &O->Header, Name); /* Initialize the object module data structure */ - O->Name = xstrdup (GetModule (Name)); - O->Flags = OBJ_HAVEDATA; + O->Name = GetModule (Name); /* Read the string pool from the object file */ fseek (Obj, O->Header.StrPoolOffs, SEEK_SET); @@ -251,7 +251,7 @@ void ObjAdd (FILE* Obj, const char* Name) ObjReadSections (Obj, O); /* Mark this object file as needed */ - O->Flags |= OBJ_REF | OBJ_HAVEDATA; + O->Flags |= OBJ_REF; /* Done, close the file (we read it only, so no error check) */ fclose (Obj); @@ -260,6 +260,9 @@ void ObjAdd (FILE* Obj, const char* Name) * string pool. */ FreeObjStrings (O); + + /* Insert the object into the list of all used object files */ + InsertObjData (O); }