mirror of
https://github.com/byteworksinc/ORCA-C.git
synced 2024-12-26 03:32:45 +00:00
Maintain a pool of empty symbol tables that can be reused.
The motivation for this is that allocating and clearing symbol tables is a common operation, especially with C99+, where a construct like "if (...) { ... }" involves three levels of scope with their own symbol tables. In some tests, it could take an appreciable fraction of total execution time (sometimes ~10%). This patch allows symbol tables that have already been allocated and cleared to be reused for a subsequent scope, as long as they are still empty. It does this by maintaining a pool of empty symbol tables and taking one from there rather than allocating a new one when possible. We impose a somewhat arbitrary limit of MaxBlock/150000 on the number of symbol tables we keep, to avoid filling up memory with them. It would probably be better to use purgeable handles here, but that would be a little more work, and this should be good enough for now.
This commit is contained in:
parent
705c9d36a2
commit
09fbfb1905
@ -74,6 +74,7 @@ interface
|
||||
const
|
||||
{hashsize appears in CCOMMON.ASM}
|
||||
hashSize = 876; {# hash buckets - 1}
|
||||
{NOTE: hashsize2 is used in Symbol.asm}
|
||||
hashSize2 = 1753; {# hash buckets * 2 - 1}
|
||||
maxLine = 255; {max length of a line}
|
||||
maxPath = 255; {max length of a path name}
|
||||
|
@ -9,11 +9,12 @@
|
||||
****************************************************************
|
||||
*
|
||||
ClearTable private cc
|
||||
tableSize equ 7026 sizeof(symbolTable)
|
||||
hashSize2 equ 1753 # hash buckets * 2 - 1
|
||||
sizeofBuckets equ 4*(hashSize2+1) sizeof(symbolTable.buckets)
|
||||
|
||||
subroutine (4:table),0
|
||||
|
||||
ldy #tableSize-2
|
||||
ldy #sizeofBuckets-2
|
||||
lda #0
|
||||
lb1 sta [table],Y
|
||||
dey
|
||||
|
61
Symbol.pas
61
Symbol.pas
@ -75,6 +75,7 @@ type
|
||||
buckets: array[0..hashSize2] of identPtr; {hash buckets}
|
||||
next: symbolTablePtr; {next symbol table}
|
||||
staticNum: packed array[1..6] of char; {staticNum at start of table}
|
||||
isEmpty: boolean; {is the pool empty (nothing in buckets)?}
|
||||
end;
|
||||
|
||||
var
|
||||
@ -310,6 +311,9 @@ type
|
||||
|
||||
var
|
||||
staticNum: packed array[1..6] of char; {static variable number}
|
||||
tablePool: symbolTablePtr; {pool of reusable empty symbol tables}
|
||||
tablePoolSize: 0..maxint; {number of tables in pool}
|
||||
tablePoolMaxSize: 0..maxint; {max number of tables in pool}
|
||||
|
||||
{- Imported from expression.pas --------------------------------}
|
||||
|
||||
@ -414,6 +418,10 @@ procedure Purge; extern;
|
||||
|
||||
{ write any constant bytes to the output buffer }
|
||||
|
||||
{- Imported from IIGS Memory Manager ---------------------------}
|
||||
|
||||
function MaxBlock: longint; tool ($02, $1C);
|
||||
|
||||
{---------------------------------------------------------------}
|
||||
|
||||
procedure ClearTable (table: symbolTable); extern;
|
||||
@ -698,6 +706,22 @@ procedure DoGlobals;
|
||||
{ declare the ~globals and ~arrays segments }
|
||||
|
||||
|
||||
procedure FreeTablePool;
|
||||
|
||||
{ free the symbol table pool }
|
||||
|
||||
var
|
||||
tPtr: symbolTablePtr;
|
||||
|
||||
begin {FreeTablePool}
|
||||
while tablePool <> nil do begin
|
||||
tPtr := tablePool;
|
||||
tablePool := tPtr^.next;
|
||||
dispose(tPtr);
|
||||
end;
|
||||
end; {FreeTablePool}
|
||||
|
||||
|
||||
procedure StaticInit (variable: identPtr);
|
||||
|
||||
{ statically initialize a variable }
|
||||
@ -1053,6 +1077,8 @@ begin {DoGlobals}
|
||||
{if printSymbols then {debug}
|
||||
{ PrintTable(globalTable); {debug}
|
||||
|
||||
FreeTablePool; {dispose of unneeded symbol tables}
|
||||
|
||||
{declare the ~globals segment, which holds non-array data types}
|
||||
if smallMemoryModel then
|
||||
currentSegment := ' '
|
||||
@ -1677,8 +1703,12 @@ var
|
||||
begin {InitSymbol}
|
||||
staticNum := '~0000'; {no functions processed}
|
||||
table := nil; {initialize the global symbol table}
|
||||
tablePool := nil; {table pool is initially empty}
|
||||
tablePoolSize := 0;
|
||||
tablePoolMaxSize := ord(MaxBlock div 150000); {limit size of pool based on RAM}
|
||||
PushTable;
|
||||
globalTable := table;
|
||||
globalTable^.isEmpty := false; {global table is never treated as empty}
|
||||
functionTable := nil;
|
||||
{declare base types}
|
||||
new(sCharPtr); {signed char}
|
||||
@ -2348,12 +2378,13 @@ if needSymbol then begin
|
||||
{p^.used := false;} {unused for now}
|
||||
if space <> fieldListSpace then {insert the symbol in the hash bucket}
|
||||
begin
|
||||
if itype = nil then
|
||||
hashPtr := pointer(ord4(table)+Hash(name))
|
||||
else if isGlobal then
|
||||
hashPtr := pointer(ord4(globalTable)+Hash(name))
|
||||
else
|
||||
if (itype = nil) or not isGlobal then begin
|
||||
hashPtr := pointer(ord4(table)+Hash(name));
|
||||
table^.isEmpty := false;
|
||||
end {if}
|
||||
else begin
|
||||
hashPtr := pointer(ord4(globalTable)+Hash(name));
|
||||
end; {else}
|
||||
if space = tagSpace then
|
||||
hashPtr := pointer(ord4(hashPtr) + 4*(hashSize+1));
|
||||
p^.next := hashPtr^;
|
||||
@ -2452,7 +2483,13 @@ if (lint & lintUnused) <> 0 then
|
||||
CheckUnused(tPtr);
|
||||
if tPtr^.next <> nil then begin
|
||||
table := table^.next;
|
||||
dispose(tPtr);
|
||||
if not tPtr^.isEmpty or (tablePoolSize = tablePoolMaxSize) then
|
||||
dispose(tPtr)
|
||||
else begin
|
||||
tPtr^.next := tablePool;
|
||||
tablePool := tPtr;
|
||||
tablePoolSize := tablePoolSize + 1;
|
||||
end; {else}
|
||||
end; {if}
|
||||
end; {PopTable}
|
||||
|
||||
@ -2480,8 +2517,16 @@ repeat
|
||||
done := i = 1;
|
||||
end; {if}
|
||||
until done;
|
||||
new(tPtr); {create a new symbol table}
|
||||
ClearTable(tPtr^);
|
||||
if tablePool <> nil then begin {use existing empty table if available}
|
||||
tPtr := tablePool;
|
||||
tablePool := tPtr^.next;
|
||||
tablePoolSize := tablePoolSize - 1;
|
||||
end {if}
|
||||
else begin
|
||||
new(tPtr); {...or create a new symbol table}
|
||||
ClearTable(tPtr^);
|
||||
tPtr^.isEmpty := true;
|
||||
end; {else}
|
||||
tPtr^.next := table;
|
||||
table := tPtr;
|
||||
tPtr^.staticNum := staticNum; {record the static symbol table number}
|
||||
|
Loading…
Reference in New Issue
Block a user