Spaces:
Running
Running
public | |
addMethodsForPrimitives: classAndSelectorList | |
| sel aClass source verbose meth primInstVars sharedInstVars assignedInstVars | | |
classAndSelectorList do:[:classAndSelector | | |
aClass := Smalltalk at: (classAndSelector at: 1) ifAbsent:[nil]. | |
aClass ifNotNil:[ | |
self addAllClassVarsFor: aClass. | |
"TPR - should pool vars also be added here?" | |
"find the method in either the class or the metaclass" | |
sel := classAndSelector at: 2. | |
(aClass includesSelector: sel) | |
ifTrue: [source := aClass sourceCodeAt: sel ifAbsent:[nil]] | |
ifFalse: [source := aClass class sourceCodeAt: sel ifAbsent:[nil]]. | |
]. | |
source ifNil:[ | |
Transcript cr; show: 'WARNING: Compiled primitive ', classAndSelector first, '>>', classAndSelector last, ' not present'. | |
] ifNotNil:[ | |
"compile the method source and convert to a suitable translation | |
method " | |
meth := (Compiler new | |
parse: source | |
in: aClass | |
notifying: nil) | |
asTranslationMethodOfClass: self translationMethodClass. | |
(aClass includesSelector: sel) | |
ifTrue: [meth definingClass: aClass] | |
ifFalse: [meth definingClass: aClass class]. | |
meth primitive > 0 ifTrue:[meth preparePrimitiveName]. | |
"for old-style array accessing: | |
meth covertToZeroBasedArrayReferences." | |
meth replaceSizeMessages. | |
self addMethod: meth. | |
]. | |
]. | |
"method preparation" | |
verbose := false. | |
self prepareMethods. | |
verbose | |
ifTrue: | |
[self printUnboundCallWarnings. | |
self printUnboundVariableReferenceWarnings. | |
Transcript cr]. | |
"code generation" | |
"self doInlining: false" | |
primInstVars := Set new. "inst vars used in primitives" | |
sharedInstVars := Set new. "inst vars used in non-primitives" | |
assignedInstVars := Set new. "inst vars modified in non-primitives" | |
methods do:[:m| | |
m primitive > 0 ifTrue: [ | |
primInstVars addAll: m freeVariableReferences. | |
] ifFalse: [ | |
sharedInstVars addAll: m freeVariableReferences. | |
assignedInstVars addAll: m variablesAssignedTo. | |
]. | |
]. | |
methods do:[:m| | |
"if this method is supposed to be a primitive (rather than a helper | |
routine), add assorted prolog and epilog items" | |
m primitive > 0 ifTrue: [ | |
m preparePrimitivePrologueShared: sharedInstVars assigned: assignedInstVars ]. | |
"check for one-based array access" | |
m oneBasedArrays ifNotNil: [self oneBasedArrays: true]. | |
]. | |
"Add declarations for inst vars used in both prims and non-prims as global" | |
((primInstVars intersection: sharedInstVars) difference: variables) do: [:var | | |
methods do:[:m| | |
m declarations at: var ifPresent: [:decl | | |
variableDeclarations at: var | |
ifPresent: [:existing | | |
decl = existing ifFalse: [self error: 'decls do not match']] | |
ifAbsent: [variableDeclarations at: var put: decl]]]. | |
variables add: var]. | |
"Add non-shared inst vars as local" | |
methods do:[:m| | |
m locals addAll: (m freeVariableReferences difference: sharedInstVars)]. | |