Replace each use by a constructor with a more specific name.
Full analysis:
* Use of MAKE-EQ-HASH-TABLE in MIT Scheme, 2009-12-21 -*- outline -*-
In MIT Scheme, MAKE-EQ-HASH-TABLE yields a hash table whose keys are
held only weakly, so that they will be garbage-collected if there are
no strong references to them. To make a similar hash table whose keys
are held strongly, one must use MAKE-STRONG-EQ-HASH-TABLE explicitly.
Of the sixty-two uses of MAKE-EQ-HASH-TABLE throughout the MIT Scheme
source code, only four appear to need weak references to their keys,
and for only two more is there an obvious reason to use weak
references. This list categorizes most uses of MAKE-EQ-HASH-TABLE.
Each entry is marked by the decision that was made for it of whether
it should be strong or weak.
** Hash table must be key-weak
*** [weak] edwin/curren.scm, screen-buffer-layouts
*** [weak] edwin/eystep.scm, stepper-buffers
*** [weak] edwin/xterm.scm, display/cached-atoms-table
*** [weak] edwin/xterm.scm, display/selection-records
** Hash table should be key-weak, but will work as key-strong
*** [weak] edwin/comman.scm, permanent-local-variables
As long as Edwin variables are strongly interned, it is safe to use a
key-strong hash table for properties on Edwin variables such as the
permanent-local property, but if Edwin variables were weakly interned
then this would be a space leak.
*** [strong] sos/class.scm, built-in-class-table
Dispatch tags that are garbage-collected shouldn't accumulate space
here. These might arise, for instance, from re-evaluating
DEFINE-RECORD-TYPE forms causing the old record type's dispatch tags
to be garbage-collected. That requires key- and datum-weak hash
tables, though. Using MAKE-WEAK-EQ-HASH-TABLE here breaks the
bootstrap from the
20090107 snapshot, which doesn't have a binding for
that name. So just use a strong eq hash table for now.
** Hash table should be key-strong, but will work as key-weak
*** [strong] compiler/machines/i386/lapopt.scm, *rules*
If the compiler never generates instructions with certain symbols in
them, and hence the compiler's code has no strong references to those
symbols, then the rules for those symbols may as well be discarded.
But that's pretty sketchy.
*** [strong] compiler/machines/svm/assembler-runtime.scm, symbolic-operators
*** [strong] compiler/machines/svm/assembler-runtime.scm, pvar-type-table
*** [strong] compiler/machines/svm/lapopt.scm, *rules* (not really used)
*** [strong] compiler/machines/x86-64/lapopt.scm, *rules* (not really used)
*** [strong] edwin/nntp.scm, equivalences in build-equivalence-classes
The only reason that this works as a key-weak hash table is that every
key is also strongly referenced by the hash table's data.
*** [strong] edwin/nntp.scm, tables in convert-header-graphs-to-trees
In the only caller of CONVERT-HEADER-GRAPHS-TO-TREES, the (strong)
list of headers is still strongly referenced, so the keys of the two
hash tables in TABLES will not be garbage-collected.
*** [strong] edwin/xterm.scm, built-in-atoms-table
If the binding for BUILT-IN-ATOMS were collected while that for
BUILT-IN-ATOMS-TABLE were not, then the latter would be in trouble.
This generally doesn't happen currently.
*** [strong] microcode/os2pm.scm, type-abbreviations
*** [strong] microcode/os2pm.scm, id-external-roots
This code is probably defunct, but if it weren't, and if the
presentation manager procedure abstraction were used outside this
file, it would probably be necessary to make these two hash tables
key-strong. Another hash table, PM-PROCEDURES, is incorrectly
key-weak.
*** [strong] runtime/genio.scm, {en,de}coder/sizer/{,de}normalizer maps
Since there are maps in both directions, each hash table's keys also
have strong references in the data positions of the other hash table.
But this is pretty fragile, and in any case there is no need to use
key-weak hash tables.
*** [strong] runtime/syntax-output.scm, unmappings
*** [strong] runtime/syntax-output.scm, rename-databases' mapping-tables
*** [strong] runtime/syntax-output.scm, rename-databases' id-tables
*** [weak] ssp/xmlrpc.scm, methods in get-xmlrpc-method-handler
Since the hash table is used only in one place, and only one key is
fetched out of it, that key will be strongly referenced until it is
fetched, and the other keys don't matter. (For that matter, why use a
hash table at all?)
*** [strong] xml/turtle.scm, table in write-prefixes
** Hash table must be key-strong
*** [strong] compiler/machines/svm/assembler-runtime.scm, symbol tables
These are probably meant to be treated like the symbol tables
implemented in compiler/back/symtab.scm.
*** [strong] imail/imail-file.scm, file-folder-types
*** [strong] imail/imail-mime.scm, mime-encodings
*** [strong] microcode/os2pm.scm, pm-procedures
*** [strong] runtime/http-syntax.scm, header-value-defns
*** [strong] ssp/mod-lisp.scm, mime-handlers
*** [strong] ssp/xhtml-expander.scm, *sabbr-table*
The processing instructions are processed incrementally as the file is
parsed, so keys in the sabbr table may be garbage-collected and then
re-interned, between which times the associations would be destroyed.
*** [strong] star-parser/matcher.scm, matcher-preprocessors
*** [strong] star-parser/matcher.scm, matcher-compilers
*** [strong] star-parser/parser.scm, parser-preprocessors
*** [strong] star-parser/parser.scm, parser-compilers
*** [strong] star-parser/shared.scm, make-parser-macros
*** [strong] star-parser/shared.scm, *global-parser-macros*
*** [strong] xdoc/validate-xdoc.scm, element-checkers
*** [strong] xdoc/xdoc.scm, html-generators
*** [strong] xdoc/xdoc.scm, when-conditions
*** [strong] xdoc/xdoc.scm, xdoc-content-types
*** [strong] xdoc/xdoc.scm, xdoc-element-types
*** [strong] xdoc/xdoc.scm, xdoc-input-canonicalizers
*** [strong] xdoc/xdoc.scm, xdoc-output-definitions
*** [strong] xml/xhtml.scm, element-context-map
** Other
*** [strong] compiler/machines/C/stackify.scm, stackify count tables
It is not immediately clear to me whether these need to be strong, but
they probably should be.
*** [strong] compiler/rtlbase/rtlobj.scm, label->object maps
It's not immediately obvious to me whether LABEL->OBJECT will ever be
used after the last references to the keys of the hash tables involved
(which cause strong references to those keys to be dropped, if
COMPILER:PRESERVE-DATA-STRUCTURES? is false). A little further
analysis is required. A conservative guess would be that these should
to be strong.
*** [weak] edwin/eystep.scm, ynode-regions
What are the keys to these hash tables? I don't know how long they
persist.
Chris's answer: The keys are stepper nodes; they are stored in a text
property and consequently will be held appropriately. This should be
a weak table.
*** [weak] edwin/prompt.scm, prompt-histories
Making this key-strong is not likely to be a space leak, but if a
command is garbage-collected, then so may the symbol for its history
be garbage-collected, and its history is presumably no longer needed.
*** [strong-eqv] edwin/win32.scm, event-handlers
The keys in EVENT-HANDLERS are integers. I think this should be a
key-strong eqv hash table rather than a key-weak eq hash table.
*** [strong] edwin/xterm.scm, selection->record table in display/selection-records
I'm not sure what the domain of possible keys to this hash table is --
it may be just the symbols PRIMARY and CLIPBOARD, which will probably
be strongly referenced by the rest of the Edwin code, but on the other
hand I think this should probably be a key-strong hash table.
*** [strong] edwin/xterm.scm, symbol->x-atom table in display/cached-atoms-table
Whether this should be key-strong or key-weak depends on whether the
set of atoms that it will map is arbitrarily large.
*** [weak] imail/imail-core.scm, memoized-resources
As long as URLs are interned strongly, it doesn't matter whether
MEMOIZED-RESOURCES is key-weak or key-strong. This requires further
analysis, but leaving it weak for now (i.e. not changing it) is safe
until internment of URLs changes.
*** [strong with comment] runtime/sfile.scm, interned-mime-types
This should really be a key-strong, datum-weak hash table, which the
hash table abstraction does not presently support. (The same goes for
UNUSUAL-INTERNED-MIME-TYPES.) Barring that, INTERNED-MIME-TYPES
should be key-strong, although it happens to work as a key-weak hash
table because its data have strong references to its keys anyway.
*** [weak] xdoc/xdoc.scm, *xdoc-element-properties*
*** [weak] xdoc/xdoc.scm, *xdoc-inputs*
*** [weak] xdoc/xdoc.scm, *xdoc-outputs*
As maps from XML elements by identity to properties, these three
should probably be key-weak, but since new ones are created for each
xdoc expansion, they could probably safely be key-strong without
badly leaking memory.
*** [strong] xdoc/xdoc.scm, *xdoc-id-map*
This should be key-strong, although it doesn't matter until XML names
become weakly interned.
*** [strong-eqv] xml/xhtml-entities.scm, table in html-char->name-map
The keys in the table inside HTML-CHAR->NAME-MAP is keyed by
characters. Should this be a key-strong eqv hash table rather than a
key-weak eq hash table?
*** [strong with comment] xml/xml-names.scm
If we had datum-weak hash tables, then EXPANDED-NAMES should be
key-weak and the other two should be datum-weak. But we don't, so
instead all three should be strong, since in each one the data all
have strong references to their corresponding keys.
;; This version uses an eq hash table
(define-integrable (stackify/make-table)
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define-integrable (stackify/table/lookup key)
(hash-table/get *stackify/table* key #f))
predicate ; (lambda (dict) ...) -> bool
constructor) ; (lambda (dict) ...) -> lap
-(define *rules* (make-eq-hash-table))
+(define *rules* (make-strong-eq-hash-table))
\f
;; Rules are indexed by the last opcode in the pattern.
(value symbol-binding-value))
(define (make-symbol-table)
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (define-symbol name type value symbol-table)
(hash-table/get symbol-table name (make-symbol-binding name type value)))
(error:bad-range-argument name #f)))
(define symbolic-operators
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define-integrable (se-integer? object)
(exact-integer? object))
(hash-table/datum-list pvar-type-table))
(define pvar-type-table
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (define-pvt name abbreviation sb-type predicate encoder decoder)
(hash-table/put! pvar-type-table
constructor) ; (lambda (dict) ...) -> lap
(define *rules*
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
\f
;; Rules are indexed by the last opcode in the pattern.
predicate ; (lambda (dict) ...) -> bool
constructor) ; (lambda (dict) ...) -> lap
-(define *rules* (make-eq-hash-table))
+(define *rules* (make-strong-eq-hash-table))
\f
;; Rules are indexed by the last opcode in the pattern.
\f
(define (make/label->object expression procedures continuations)
(let ((hash-table
- (make-eq-hash-table
+ (make-strong-eq-hash-table
(+ (if expression 1 0)
(length procedures)
(length continuations)))))
(hash-table/get permanent-local-variables variable #f))
(define permanent-local-variables
- (make-eq-hash-table))
\ No newline at end of file
+ (make-weak-eq-hash-table))
\ No newline at end of file
(add-event-receiver! editor-initializations
(lambda ()
- (set! screen-buffer-layouts (make-eq-hash-table))
+ (set! screen-buffer-layouts (make-weak-eq-hash-table))
unspecific))
\f
;;;; Point
(get-stepper-buffer state)))
(define stepper-buffers
- (make-eq-hash-table))
+ (make-weak-eq-hash-table))
(define (current-stepper-state)
(buffer->stepper-state (current-buffer)))
(define (get-buffer-ynode-regions buffer)
(or (buffer-get buffer 'YNODE-REGIONS)
- (let ((table (make-eq-hash-table)))
+ (let ((table (make-weak-eq-hash-table)))
(buffer-put! buffer 'YNODE-REGIONS table)
table)))
;;; redundant paths to the ancestors of a header.
(define (convert-header-graphs-to-trees headers)
- (let ((tables (cons (make-eq-hash-table) (make-eq-hash-table))))
+ (let ((tables
+ (cons (make-strong-eq-hash-table) (make-strong-eq-hash-table))))
(for-each (lambda (header)
(if (eq? (hash-table/get (car tables) header 'NONE) 'NONE)
(eliminate-redundant-relatives tables header)))
;;; common references.
(define (build-equivalence-classes threads subject-alist)
- (let ((equivalences (make-eq-hash-table)))
+ (let ((equivalences (make-strong-eq-hash-table)))
(for-each (lambda (thread)
(hash-table/put! equivalences
thread
(set! typein-saved-windows '())
(set! map-name/internal->external identity-procedure)
(set! map-name/external->internal identity-procedure)
- (set! prompt-histories (make-eq-hash-table))
+ (set! prompt-histories (make-weak-eq-hash-table))
unspecific))
(define (make-typein-buffer-name depth)
(handler screen event))))
(define event-handlers
- (make-eq-hash-table))
+ (make-strong-eqv-hash-table))
(define (define-event-handler event-type handler)
(hash-table/put! event-handlers event-type handler))
(define built-in-atoms-table
(let ((n (vector-length built-in-atoms)))
- (let ((table (make-eq-hash-table n)))
+ (let ((table (make-strong-eq-hash-table n)))
(do ((i 0 (fix:+ i 1)))
((fix:= i n))
(hash-table/put! table (vector-ref built-in-atoms i) i))
table)))
(define display/cached-atoms-tables
- (let ((table (make-eq-hash-table)))
+ (let ((table (make-weak-eq-hash-table)))
(lambda (display)
(or (hash-table/get table display #f)
- (let ((result (cons (make-eq-hash-table) (make-eqv-hash-table))))
+ (let ((result
+ (cons (make-strong-eq-hash-table)
+ (make-strong-eqv-hash-table))))
(hash-table/put! table display result)
result)))))
\f
#t)))
(define display/selection-records
- (let ((table (make-eq-hash-table)))
+ (let ((table (make-weak-eq-hash-table)))
(lambda (display)
(or (hash-table/get table display #f)
- (let ((result (make-eq-hash-table)))
+ (let ((result (make-strong-eq-hash-table)))
(hash-table/put! table display result)
result)))))
(hash-table/remove! memoized-resources url))
(define memoized-resources
- (make-eq-hash-table))
+ (make-weak-eq-hash-table))
\f
;;;; Folder operations
name predicate)))
(define file-folder-types
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (prompt-for-file-folder-type url)
(imail-ui:prompt-for-alist-value
(define-guarantee mime-encoding "MIME codec")
(define mime-encodings
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (define-mime-encoding name
encode:initialize encode:finalize encode:update
(hash-table/put! type-abbreviations name type))
(define type-abbreviations
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define-type-abbreviation 'boolean 'int)
(define-type-abbreviation 'uchar '(unsigned char))
(hash-table/get id-external-roots (id-type-name type) #f))
(define id-external-roots
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (id-external-type type)
(list (id-external-root type) "_t"))
;;;; PM Procedures
(define pm-procedures
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define-structure pmp
(root-name #f read-only #t)
(define (install-profile-hash-table)
-;;;(set! make-profile-hash-table make-eq-hash-table); weakly held
+;;;(set! make-profile-hash-table make-weak-eq-hash-table); weakly held
;;;(set! profile-hash-table-car weak-car)
;;;(set! profile-hash-table-cdr weak-cdr)
(define (initialize-name-maps!)
(let ((convert-reverse
(lambda (alist)
- (let ((table (make-eq-hash-table)))
+ (let ((table (make-strong-eq-hash-table)))
(for-each (lambda (n.d)
(hash-table/put! table (cdr n.d) (car n.d)))
alist)
table)))
(convert-forward
(lambda (alist)
- (let ((table (make-eq-hash-table)))
+ (let ((table (make-strong-eq-hash-table)))
(for-each (lambda (n.d)
(hash-table/put! table (car n.d) (cdr n.d)))
alist)
(hash-table-ref/default header-value-defns name #f))
(define-deferred header-value-defns
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define-structure hvdefn
(name #f read-only #t)
(define (initialize-package!)
(set! interned-mime-types
- (vector-map (lambda (token) token (make-eq-hash-table))
+ ;; We really want each of these hash tables to be a
+ ;; datum-weak hash table, but the hash table abstraction
+ ;; doesn't support that. Using a key-weak hash table does no
+ ;; good because each datum has a strong reference to its key.
+ (vector-map (lambda (token) token (make-strong-eq-hash-table))
top-level-mime-types))
(set! unusual-interned-mime-types (make-equal-hash-table))
(set! char-set:mime-token
(alpha-substitute (unmapping->substitution unmapping) expression)))
(define (empty-unmapping)
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (store-unmapping-entry! identifier unmapped-identifier unmapping)
(hash-table/put! unmapping identifier unmapped-identifier))
(conc-name rename-database/))
(frame-number 0)
(mapping-table (make-equal-hash-table) read-only #t)
- (unmapping-table (make-eq-hash-table) read-only #t)
- (id-table (make-eq-hash-table) read-only #t))
+ (unmapping-table (make-strong-eq-hash-table) read-only #t)
+ (id-table (make-strong-eq-hash-table) read-only #t))
(define (make-rename-id)
(delay
(else
(error:wrong-type-argument type "MIME type" 'DEFINE-MIME-HANDLER))))
-(define mime-handlers (make-eq-hash-table))
+(define mime-handlers (make-strong-eq-hash-table))
(define mime-extensions (make-string-hash-table))
(define (html-content-type)
(lambda ()
(with-load-environment environment
(lambda ()
- (fluid-let ((*sabbr-table* (make-eq-hash-table)))
+ (fluid-let ((*sabbr-table* (make-strong-eq-hash-table)))
(read-xml-file pathname
`((scheme ,(pi-expander environment))
(svar ,svar-expander)
(apply handler params)))))))))))
(define (get-xmlrpc-method-handler pathname name)
- (let ((methods (make-eq-hash-table)))
+ (let ((methods (make-weak-eq-hash-table)))
(let ((environment (make-expansion-environment pathname)))
(environment-define environment 'define-xmlrpc-method
(lambda (name handler)
(hash-table/get matcher-preprocessors name #f)))
(define matcher-preprocessors
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
\f
(define-*matcher-expander '+
(lambda (expression)
keyword)
(define matcher-compilers
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
\f
(define-syntax define-atomic-matcher
(rsc-macro-transformer
(hash-table/get parser-preprocessors name #f)))
(define parser-preprocessors
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
\f
(define-*parser-expander '+
(lambda (expression)
keyword)
(define parser-compilers
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
\f
(define-parser (match expression)
(call-with-pointer pointer
(define (make-parser-macros parent)
(if parent (guarantee-parser-macros parent 'MAKE-PARSER-MACROS))
(%make-parser-macros (or parent *global-parser-macros*)
- (make-eq-hash-table)
- (make-eq-hash-table)))
+ (make-strong-eq-hash-table)
+ (make-strong-eq-hash-table)))
(define *global-parser-macros*
- (%make-parser-macros #f (make-eq-hash-table) (make-eq-hash-table)))
+ (%make-parser-macros #f
+ (make-strong-eq-hash-table)
+ (make-strong-eq-hash-table)))
(define (guarantee-parser-macros object procedure)
(if (not (parser-macros? object))
(vector valid-attrs? type valid-local? procedure))))
(define element-checkers
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (vx:standard-attrs elt)
(vx:optional-attr 'class elt vx:nmtokens)
(*xdoc-environment* environment)
(*xdoc-root*)
(*xdoc-late?*)
- (*xdoc-element-properties* (make-eq-hash-table))
- (*xdoc-id-map* (make-eq-hash-table))
- (*xdoc-inputs* (make-eq-hash-table))
- (*xdoc-outputs* (make-eq-hash-table)))
+ (*xdoc-element-properties* (make-weak-eq-hash-table))
+ (*xdoc-id-map* (make-strong-eq-hash-table))
+ (*xdoc-inputs* (make-weak-eq-hash-table))
+ (*xdoc-outputs* (make-weak-eq-hash-table)))
(let ((document (read/expand-xml-file pathname environment)))
(set! *xdoc-root* (xml-document-root document))
(set! *xdoc-late?* (due-date-in-past?))
(hash-table/get html-generators (xdoc-element-name item) #f))
(define html-generators
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (generate-container-items items extra-content?)
(generate-container-groups
value)))))
(define xdoc-input-canonicalizers
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define-xdoc-input 'text
string-trim
(error:bad-range-argument elt 'xdoc-output-definition)))
(define xdoc-output-definitions
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
\f
(define-unary-xdoc-output 'check-input #t
(lambda (elt)
(hash-table/put! when-conditions name procedure))
(define when-conditions
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define-when-condition 'submitted
(lambda (elt)
(error "Unknown XDOC element name:" local)))))
(define xdoc-content-types
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (xdoc-element-type elt)
(let ((local (xdoc-element-name elt)))
(error "Unknown XDOC element name:" local)))))
(define xdoc-element-types
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (xdoc-container? elt)
(let ((type (xdoc-element-type elt)))
(newline port)))
(define (write-prefixes graph port)
- (let ((table (make-eq-hash-table)))
+ (let ((table (make-strong-eq-hash-table)))
(define (check-graph g)
(for-each check-triple (rdf-graph-triples g)))
html-entity-alist))
(define html-char->name-map
- (let ((table (make-eq-hash-table)))
+ (let ((table (make-strong-eqv-hash-table)))
(for-each (lambda (b) (hash-table/put! table (cadr b) (car b)))
html-entity-alist)
(lambda (char)
(hash-table/key-list element-context-map))
(define element-context-map
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define-html-element a inline)
(define-html-element abbr inline)
(error:bad-range-argument uri 'MAKE-XML-NAME))
(%make-xml-name name-symbol uri)))))
+;;; EXPANDED-NAMES should be a key-weak hash table, but that has an
+;;; effect only if the other two hash tables are datum-weak, because
+;;; there is a strong reference from each datum to its associated key
+;;; in all three hash tables involved. And since we don't have datum-
+;;; weak hash tables, for now these will all be key-strong, since
+;;; there's some overhead and no value to using key-weak hash tables.
+
(define (%make-xml-name qname uri)
(let ((uname
(let ((local (xml-qname-local qname)))
- (hash-table/intern! (hash-table/intern! expanded-names
- uri
- make-eq-hash-table)
- local
- (lambda ()
- (make-expanded-name uri
- local
- (make-eq-hash-table)))))))
- (hash-table/intern! (expanded-name-combos uname)
- qname
- (lambda () (make-combo-name qname uname)))))
+ (hash-table/intern! (hash-table/intern! expanded-names uri
+ make-strong-eq-hash-table)
+ local
+ (lambda ()
+ (make-expanded-name uri local (make-strong-eq-hash-table)))))))
+ (hash-table/intern! (expanded-name-combos uname) qname
+ (lambda ()
+ (make-combo-name qname uname)))))
(define expanded-names
- (make-eq-hash-table))
+ (make-strong-eq-hash-table))
(define (xml-name? object)
(or (xml-name-symbol? object)