mirror of
https://github.com/byteworksinc/ORCA-C.git
synced 2025-01-13 16: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
|
const
|
||||||
{hashsize appears in CCOMMON.ASM}
|
{hashsize appears in CCOMMON.ASM}
|
||||||
hashSize = 876; {# hash buckets - 1}
|
hashSize = 876; {# hash buckets - 1}
|
||||||
|
{NOTE: hashsize2 is used in Symbol.asm}
|
||||||
hashSize2 = 1753; {# hash buckets * 2 - 1}
|
hashSize2 = 1753; {# hash buckets * 2 - 1}
|
||||||
maxLine = 255; {max length of a line}
|
maxLine = 255; {max length of a line}
|
||||||
maxPath = 255; {max length of a path name}
|
maxPath = 255; {max length of a path name}
|
||||||
|
@ -9,11 +9,12 @@
|
|||||||
****************************************************************
|
****************************************************************
|
||||||
*
|
*
|
||||||
ClearTable private cc
|
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
|
subroutine (4:table),0
|
||||||
|
|
||||||
ldy #tableSize-2
|
ldy #sizeofBuckets-2
|
||||||
lda #0
|
lda #0
|
||||||
lb1 sta [table],Y
|
lb1 sta [table],Y
|
||||||
dey
|
dey
|
||||||
|
61
Symbol.pas
61
Symbol.pas
@ -75,6 +75,7 @@ type
|
|||||||
buckets: array[0..hashSize2] of identPtr; {hash buckets}
|
buckets: array[0..hashSize2] of identPtr; {hash buckets}
|
||||||
next: symbolTablePtr; {next symbol table}
|
next: symbolTablePtr; {next symbol table}
|
||||||
staticNum: packed array[1..6] of char; {staticNum at start of table}
|
staticNum: packed array[1..6] of char; {staticNum at start of table}
|
||||||
|
isEmpty: boolean; {is the pool empty (nothing in buckets)?}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
@ -310,6 +311,9 @@ type
|
|||||||
|
|
||||||
var
|
var
|
||||||
staticNum: packed array[1..6] of char; {static variable number}
|
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 --------------------------------}
|
{- Imported from expression.pas --------------------------------}
|
||||||
|
|
||||||
@ -414,6 +418,10 @@ procedure Purge; extern;
|
|||||||
|
|
||||||
{ write any constant bytes to the output buffer }
|
{ write any constant bytes to the output buffer }
|
||||||
|
|
||||||
|
{- Imported from IIGS Memory Manager ---------------------------}
|
||||||
|
|
||||||
|
function MaxBlock: longint; tool ($02, $1C);
|
||||||
|
|
||||||
{---------------------------------------------------------------}
|
{---------------------------------------------------------------}
|
||||||
|
|
||||||
procedure ClearTable (table: symbolTable); extern;
|
procedure ClearTable (table: symbolTable); extern;
|
||||||
@ -698,6 +706,22 @@ procedure DoGlobals;
|
|||||||
{ declare the ~globals and ~arrays segments }
|
{ 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);
|
procedure StaticInit (variable: identPtr);
|
||||||
|
|
||||||
{ statically initialize a variable }
|
{ statically initialize a variable }
|
||||||
@ -1053,6 +1077,8 @@ begin {DoGlobals}
|
|||||||
{if printSymbols then {debug}
|
{if printSymbols then {debug}
|
||||||
{ PrintTable(globalTable); {debug}
|
{ PrintTable(globalTable); {debug}
|
||||||
|
|
||||||
|
FreeTablePool; {dispose of unneeded symbol tables}
|
||||||
|
|
||||||
{declare the ~globals segment, which holds non-array data types}
|
{declare the ~globals segment, which holds non-array data types}
|
||||||
if smallMemoryModel then
|
if smallMemoryModel then
|
||||||
currentSegment := ' '
|
currentSegment := ' '
|
||||||
@ -1677,8 +1703,12 @@ var
|
|||||||
begin {InitSymbol}
|
begin {InitSymbol}
|
||||||
staticNum := '~0000'; {no functions processed}
|
staticNum := '~0000'; {no functions processed}
|
||||||
table := nil; {initialize the global symbol table}
|
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;
|
PushTable;
|
||||||
globalTable := table;
|
globalTable := table;
|
||||||
|
globalTable^.isEmpty := false; {global table is never treated as empty}
|
||||||
functionTable := nil;
|
functionTable := nil;
|
||||||
{declare base types}
|
{declare base types}
|
||||||
new(sCharPtr); {signed char}
|
new(sCharPtr); {signed char}
|
||||||
@ -2348,12 +2378,13 @@ if needSymbol then begin
|
|||||||
{p^.used := false;} {unused for now}
|
{p^.used := false;} {unused for now}
|
||||||
if space <> fieldListSpace then {insert the symbol in the hash bucket}
|
if space <> fieldListSpace then {insert the symbol in the hash bucket}
|
||||||
begin
|
begin
|
||||||
if itype = nil then
|
if (itype = nil) or not isGlobal then begin
|
||||||
hashPtr := pointer(ord4(table)+Hash(name))
|
|
||||||
else if isGlobal then
|
|
||||||
hashPtr := pointer(ord4(globalTable)+Hash(name))
|
|
||||||
else
|
|
||||||
hashPtr := pointer(ord4(table)+Hash(name));
|
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
|
if space = tagSpace then
|
||||||
hashPtr := pointer(ord4(hashPtr) + 4*(hashSize+1));
|
hashPtr := pointer(ord4(hashPtr) + 4*(hashSize+1));
|
||||||
p^.next := hashPtr^;
|
p^.next := hashPtr^;
|
||||||
@ -2452,7 +2483,13 @@ if (lint & lintUnused) <> 0 then
|
|||||||
CheckUnused(tPtr);
|
CheckUnused(tPtr);
|
||||||
if tPtr^.next <> nil then begin
|
if tPtr^.next <> nil then begin
|
||||||
table := table^.next;
|
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; {if}
|
||||||
end; {PopTable}
|
end; {PopTable}
|
||||||
|
|
||||||
@ -2480,8 +2517,16 @@ repeat
|
|||||||
done := i = 1;
|
done := i = 1;
|
||||||
end; {if}
|
end; {if}
|
||||||
until done;
|
until done;
|
||||||
new(tPtr); {create a new symbol table}
|
if tablePool <> nil then begin {use existing empty table if available}
|
||||||
ClearTable(tPtr^);
|
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;
|
tPtr^.next := table;
|
||||||
table := tPtr;
|
table := tPtr;
|
||||||
tPtr^.staticNum := staticNum; {record the static symbol table number}
|
tPtr^.staticNum := staticNum; {record the static symbol table number}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user