Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

With jumps #12

Open
wants to merge 79 commits into
base: testCompilationObservable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
c76fe58
Removed unused variables
guillep Sep 14, 2021
bef15af
Forbid variable localization in the intepreter loop if it creates con…
guillep Sep 14, 2021
1749752
Cleanups in localization
guillep Sep 14, 2021
3b81239
Remove reporting
guillep Sep 14, 2021
22a8dc8
Adding case of localizing after and before inlining
guillep Sep 14, 2021
751363d
Adding first iteration on automatic localization of variables:
guillep Sep 14, 2021
1c75b7f
Wrap sends with externalizations/externalizations
guillep Sep 14, 2021
76c1b6a
Simplify tests and make them more robust
guillep Sep 14, 2021
0d9e99f
Rename args=>arguments
guillep Sep 21, 2021
d9efe62
Adding external send node
guillep Sep 24, 2021
c72650c
Merge 7fd4f7c3a55f46fe85b49e993ba9090c3fb71976
guillep Sep 24, 2021
9ab71f2
Finish Merge
guillep Sep 24, 2021
7b856e3
Handling linearization of calls, name conflicts when extracting argum…
guillep Sep 24, 2021
c2b9f28
Fixing iteration of the children of external send nodes
guillep Sep 24, 2021
45a044f
Experimental:
guillep Oct 1, 2021
650f6da
Add tests for automatic localization.
LABSARI Oct 7, 2021
3a271a4
Adding first iteration on automatic localization of variables:
LABSARI Oct 7, 2021
063b06a
Merge pull request #1 from LABSARI/feat/autoLocalization
guillep Oct 26, 2021
1d3c701
Correct autolocalization transpilation errors.
LABSARI Oct 26, 2021
b9c2cf2
Reformatting due to automatic deprecation of args->arguments
guillep Oct 26, 2021
83d5677
Merge branch 'feat/automatic-localization' into feat/autoLocalization3
guillep Oct 26, 2021
b5c916b
Merge pull request #2 from LABSARI/feat/autoLocalization3
guillep Oct 26, 2021
8f8484e
Fixing tests
guillep Oct 26, 2021
50e24fc
Fix test after bad merge
guillep Oct 26, 2021
a46b891
Trying auto localisation of instructionPointer
guillep Oct 26, 2021
38e6a73
Simplifying manual localFP by => framePointer to make later automatic…
guillep Oct 26, 2021
35530b1
Remove manual localSP optimisation
guillep Oct 26, 2021
601dbb1
Replace internalPop => pop
guillep Oct 26, 2021
1ade953
removing internal* versions
guillep Oct 26, 2021
daedc40
Cleanups with automatic rewrites
guillep Oct 26, 2021
baa4c6e
Remove automatic localization hint
guillep Dec 21, 2021
d4b6e37
Replace cmacro by a normal perform
guillep Dec 21, 2021
96c0130
Adding support for linearization of expressions
guillep Dec 21, 2021
188f2ba
Renames of isStmtNode
guillep Dec 21, 2021
7d785fd
Added visiting methods to the TAST and MLVMVariableAccessCollector to…
guillep Dec 22, 2021
246d497
Introducing node parents to be able to do O(1) replacement
guillep Dec 28, 2021
7eb8483
Extending visitor to switch
guillep Dec 28, 2021
56ae36c
Cleanups in StatementList instantiation
guillep Dec 28, 2021
058941c
More cleanups in statement list instantiation
guillep Dec 28, 2021
7f5afca
Extending isSameAs: for more types
guillep Dec 28, 2021
89f0f97
Using replaceBy: to replace without the need of iterating
guillep Dec 28, 2021
e36c902
Hoist new variables during linearization
guillep Dec 28, 2021
e5edcff
Making tests green for now
guillep Dec 29, 2021
768c97c
Correct node replacement
guillep Dec 29, 2021
bbde1bc
Fix wrong rename
guillep Dec 29, 2021
dc0c853
Fix automatic deprecations
guillep Dec 29, 2021
e0f5687
Rename setExpression: -> expression:
guillep Dec 30, 2021
c4c0961
Making locals belong to statement list instead of method
guillep Jan 3, 2022
75b7ff6
Extracting common methods
guillep Jan 3, 2022
24afe96
Add missing method
guillep Jan 3, 2022
cd555ee
Avoid creating unused variables
guillep Jan 3, 2022
26440de
Making tests pass
guillep Jan 3, 2022
1a5d843
add locals
guillep Jan 3, 2022
620005c
Adding declarations on C code
guillep Jan 3, 2022
5f23c47
Using declared types when output
guillep Jan 3, 2022
dcbf9e0
Adding iterator variable locally
guillep Jan 3, 2022
8c6874a
Do not linearize assertions
guillep Jan 3, 2022
1b252ba
Update tabbing
guillep Jan 3, 2022
5e84cb9
only write locals
guillep Jan 3, 2022
e44a871
Do not linearize blocks in expressions (and, iftrue...) for now, nor …
guillep Jan 3, 2022
513b674
Fixing back tabbing
guillep Jan 3, 2022
33dcd74
Deprecating args
guillep Jan 3, 2022
07e57e6
Hoisting closure arguments as method locals
guillep Jan 3, 2022
b503e9b
Hoisting closure arguments as method locals
guillep Jan 3, 2022
2fbdf9b
Make tests green
guillep Jan 4, 2022
afb8a29
Fix gnufication tabbing
guillep Jan 4, 2022
f95f92c
Only linearise if needed
guillep Jan 4, 2022
15df79b
Fixing tabbing (again)
guillep Jan 5, 2022
f9855ac
Fix double declaration
guillep Jan 5, 2022
9214ffb
Reducing tabs even more
guillep Jan 5, 2022
66abdc1
Cleaning usedVariable cache
guillep Jan 5, 2022
64f9a0b
Note variables used in statement lists
guillep Jan 5, 2022
ae25b0c
Do not look for variables inside noteVariableUsageInString:
guillep Jan 5, 2022
56b3393
Fix doWhile translation with temporaries
guillep Jan 5, 2022
2bea188
Making locals without declarations work too
guillep Jan 5, 2022
068bce0
Do not lose cascade declarations
guillep Jan 5, 2022
03edefd
Recovering method level locals
guillep Jan 5, 2022
4ed32bc
externalize/localise on dynamic calls
guillep Jan 6, 2022
ae1982f
Avoid shadowing and redefinition of global struct macro
guillep Jan 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 92 additions & 78 deletions smalltalksrc/Melchor/MLAccessorDepthCalculator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ MLAccessorDepthCalculator class >> forCodeGenerator: aCodeGenerator [

{ #category : #'spur primitive compilation' }
MLAccessorDepthCalculator >> accessorChainsForMethod: method interpreterClass: interpreterClass [

"Answer a set of access paths from arguments through objects, in the method, assuming
it is a primitive. This is in support of Spur's lazy become. A primitive may fail because it
may encounter a forwarder. The primitive failure code needs to know to what depth it
Expand All @@ -31,53 +32,61 @@ MLAccessorDepthCalculator >> accessorChainsForMethod: method interpreterClass: i
has depth 2, since field is accessed, and field is an element of obj."

| accessors assignments roots chains extendedChains extended lastPass |
self accessorsAndAssignmentsForMethod: method
self
accessorsAndAssignmentsForMethod: method
actuals: (self actualsForMethod: method)
depth: 0
interpreterClass: interpreterClass
into: [:theRoots :theAccessors :theAssignments|
into: [ :theRoots :theAccessors :theAssignments |
roots := theRoots.
accessors := theAccessors.
assignments := theAssignments].
assignments := theAssignments ].
"Compute the transitive closure of assignments of accessor sends or variables to variables from the roots.
Start from the stack accesses (the roots).
On the last pass look only for accessors of the targets of the tip assignments."
chains := OrderedCollection new.
roots do: [:root| chains addAll: (assignments
select: [:assignment| assignment expression = root]
thenCollect: [:assignment| OrderedCollection with: assignment])].
roots do: [ :root |
chains addAll: (assignments
select: [ :assignment | assignment expression = root ]
thenCollect: [ :assignment | OrderedCollection with: assignment ]) ].
lastPass := false.
[extended := false.
extendedChains := OrderedCollection new: chains size * 2.
chains do:
[:chain| | tip refs accessorRefs variableRefs |
[
extended := false.
extendedChains := OrderedCollection new: chains size * 2.
chains do: [ :chain |
| tip refs accessorRefs variableRefs |
tip := chain last variable.
refs := accessors select: [:send| send args anySatisfy: [:arg| tip isSameAs: arg]].
lastPass ifFalse:
[accessorRefs := refs collect: [:send|
assignments
detect: [:assignment|
assignment expression = send
and: [(chain includes: assignment) not]]
ifNone: []]
thenSelect: [:assignmentOrNil| assignmentOrNil notNil].
variableRefs := assignments select:
[:assignment|
(tip isSameAs: assignment expression)
and: [(tip isSameAs: assignment variable) not
and: [(chain includes: assignment) not]]].
refs := (Set withAll: accessorRefs) addAll: variableRefs; yourself].
refs := accessors select: [ :send |
send arguments anySatisfy: [ :arg | tip isSameAs: arg ] ].
lastPass ifFalse: [
accessorRefs := refs
collect: [ :send |
assignments
detect: [ :assignment |
assignment expression = send and: [
(chain includes: assignment) not ] ]
ifNone: [ ] ]
thenSelect: [ :assignmentOrNil |
assignmentOrNil notNil ].
variableRefs := assignments select: [ :assignment |
(tip isSameAs: assignment expression) and: [
(tip isSameAs: assignment variable) not and: [
(chain includes: assignment) not ] ] ].
refs := (Set withAll: accessorRefs)
addAll: variableRefs;
yourself ].
refs isEmpty
ifTrue:
[extendedChains add: chain]
ifFalse:
[lastPass ifFalse: [extended := true].
self assert: (refs noneSatisfy: [:assignment| chain includes: assignment]).
extendedChains addAll: (refs collect: [:assignment| chain, {assignment}])]].
extended or: [lastPass not]] whileTrue:
[chains := extendedChains.
extended ifFalse: [lastPass := true]].
^chains
ifTrue: [ extendedChains add: chain ]
ifFalse: [
lastPass ifFalse: [ extended := true ].
self assert:
(refs noneSatisfy: [ :assignment | chain includes: assignment ]).
extendedChains addAll:
(refs collect: [ :assignment | chain , { assignment } ]) ] ].
extended or: [ lastPass not ] ] whileTrue: [
chains := extendedChains.
extended ifFalse: [ lastPass := true ] ].
^ chains
]

{ #category : #'spur primitive compilation' }
Expand Down Expand Up @@ -135,55 +144,60 @@ MLAccessorDepthCalculator >> accessorDepthForSelector: selector [

{ #category : #'spur primitive compilation' }
MLAccessorDepthCalculator >> accessorsAndAssignmentsForMethod: method actuals: actualParameters depth: depth interpreterClass: interpreterClass into: aTrinaryBlock [

"Evaluate aTrinaryBlock with the root accessor sends, accessor sends and assignments in the method."

| accessors assignments roots |
accessors := Set new.
assignments := Set new.
roots := Set new.
actualParameters with: method args do:
[:actual :argName|
(actual isVariable or: [actual isSend]) ifTrue:
[(actual isSend and: [self isStackAccessor: actual selector given: interpreterClass]) ifTrue:
[roots add: actual].
actualParameters with: method args do: [ :actual :argName |
(actual isVariable or: [ actual isSend ]) ifTrue: [
(actual isSend and: [
self isStackAccessor: actual selector given: interpreterClass ])
ifTrue: [ roots add: actual ].
assignments add: (TAssignmentNode new
setVariable: (TVariableNode new setName: argName)
expression: actual)]].
method parseTree nodesDo:
[:node|
node isSend ifTrue:
[(self isStackAccessor: node selector given: interpreterClass) ifTrue:
[roots add: node].
(self isObjectAccessor: node selector given: interpreterClass) ifTrue:
[accessors add: node].
(self accessorDepthDeterminationFollowsSelfSends
and: [node receiver isVariable
and: [node receiver name = 'self'
and: [roots isEmpty
or: [node args anySatisfy:
[:arg|
(roots includes: arg)
or: [(accessors includes: arg)
or: [assignments anySatisfy: [:assignment| assignment variable isSameAs: arg]]]]]]]]) ifTrue:
[self accessorsAndAssignmentsForSubMethodNamed: node selector
actuals: node args
depth: depth + 1
interpreterClass: interpreterClass
into: [:subRoots :subAccessors :subAssignments|
(subRoots isEmpty and: [subAccessors isEmpty and: [subAssignments isEmpty]]) ifFalse:
[roots addAll: subRoots.
accessors add: node.
accessors addAll: subAccessors.
assignments addAll: subAssignments]]]].
(node isAssignment
and: [(node expression isSend and: [codeGenerator vmmakerConfiguration baseObjectMemoryManagerClass isTerminalObjectAccessor: node expression selector]) not
and: [(roots includes: node expression)
or: [(accessors includes: node expression)
or: [node expression isVariable and: [node expression name ~= 'nil']]]]]) ifTrue:
[assignments add: node]].
^aTrinaryBlock
value: roots
value: accessors
value: assignments
setVariable: (TVariableNode new setName: argName)
expression: actual) ] ].
method parseTree nodesDo: [ :node |
node isSend ifTrue: [
(self isStackAccessor: node selector given: interpreterClass)
ifTrue: [ roots add: node ].
(self isObjectAccessor: node selector given: interpreterClass)
ifTrue: [ accessors add: node ].
(self accessorDepthDeterminationFollowsSelfSends and: [
node receiver isVariable and: [
node receiver name = 'self' and: [
roots isEmpty or: [
node arguments anySatisfy: [ :arg |
(roots includes: arg) or: [
(accessors includes: arg) or: [
assignments anySatisfy: [ :assignment |
assignment variable isSameAs: arg ] ] ] ] ] ] ] ])
ifTrue: [
self
accessorsAndAssignmentsForSubMethodNamed: node selector
actuals: node arguments
depth: depth + 1
interpreterClass: interpreterClass
into: [ :subRoots :subAccessors :subAssignments |
(subRoots isEmpty and: [
subAccessors isEmpty and: [ subAssignments isEmpty ] ])
ifFalse: [
roots addAll: subRoots.
accessors add: node.
accessors addAll: subAccessors.
assignments addAll: subAssignments ] ] ] ].
(node isAssignment and: [
(node expression isSend and: [
codeGenerator vmmakerConfiguration baseObjectMemoryManagerClass
isTerminalObjectAccessor: node expression selector ]) not and: [
(roots includes: node expression) or: [
(accessors includes: node expression) or: [
node expression isVariable and: [
node expression name ~= 'nil' ] ] ] ] ]) ifTrue: [
assignments add: node ] ].
^ aTrinaryBlock value: roots value: accessors value: assignments
]

{ #category : #'spur primitive compilation' }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ MLPluginAccessorDepthCalculator >> accessorsAndAssignmentsForSubMethodNamed: sel
[^nil].
map := Dictionary new.
method args do: [:var| map at: var put: depth asString, var].
method locals do: [:var| map at: var put: depth asString, var].
method allLocals do: [:var| map at: var put: depth asString, var].
^self accessorsAndAssignmentsForMethod: (method copy renameVariablesUsing: map)
actuals: actualParameters
depth: depth + 1
Expand Down
74 changes: 12 additions & 62 deletions smalltalksrc/Melchor/MLVMCCodeGenerator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,15 @@ MLVMCCodeGenerator >> doInlining: inlineFlagOrSymbol [
"Inline the bodies of all methods that are suitable for inlining."
"Modified slightly for the core VM translator, since the first level of inlining for the interpret loop must be performed in order that the instruction implementations can easily discover their addresses. Remember to inline the bytecode routines as well"

| removed |
| interpretMethod |
inlineFlagOrSymbol isSymbol ifTrue:
[self inlineDispatchesInMethodNamed: #interpret localizingVars: #().
[self inlineDispatchesInMethodNamed: #interpret.
self doBasicInlining: inlineFlagOrSymbol.
self pruneUnreachableMethods.
^self].

inlineFlagOrSymbol ifFalse:
[self inlineDispatchesInMethodNamed: #interpret localizingVars: #().
[self inlineDispatchesInMethodNamed: #interpret.
self pruneUnreachableMethods.
^self].

Expand All @@ -134,17 +134,14 @@ MLVMCCodeGenerator >> doInlining: inlineFlagOrSymbol [
displayProgress: 'Inlining bytecodes'
from: 1 to: 2
during: [:bar |
self inlineDispatchesInMethodNamed: #interpret
localizingVars: self vmClass namesOfVariablesToLocalize.
bar value: 1.
removed := self removeMethodsReferingToGlobals: self vmClass namesOfVariablesToLocalize
except: #interpret.
bar value: 2].

"only prune when generating the interpreter itself"
self pruneUnreachableMethods.
self inlineDispatchesInMethodNamed: #interpret.
bar value: 1 ].

self reportShouldNotBeRemoved: removed varList: self vmClass namesOfVariablesToLocalize
self pruneUnreachableMethods.
interpretMethod := self methodNamed: #interpret.
self
localizeVariables: self vmClass namesOfVariablesToLocalize
inMethod: interpretMethod
]

{ #category : #'C code generator' }
Expand Down Expand Up @@ -452,54 +449,6 @@ MLVMCCodeGenerator >> removeVariable: aName [
newLine]]
]

{ #category : #'C translation support' }
MLVMCCodeGenerator >> reportShouldNotBeRemoved: removed varList: varList [
"Report whether any of the removed methods are still used."
| varListAsStrings shouldNotBeRemoved |
varListAsStrings := varList collect: [ :sym | sym asString ].
shouldNotBeRemoved := Set new.
removed do:
[:m|
m isAPIMethod ifTrue:
[shouldNotBeRemoved add: m selector]].
methods do:
[:m|
(m selector = #interpret
or: [removed includes: m selector]) ifFalse:
[m allCalls do:
[:sel|
(removed includesKey: sel) ifTrue:
[shouldNotBeRemoved add: sel]]]].
self vmClass additionalSelectorTables do:
[:selectorTable|
selectorTable do:
[:selOrInteger|
selOrInteger isInteger ifFalse:
[(removed includesKey: selOrInteger) ifTrue:
[shouldNotBeRemoved add: selOrInteger]]]].
shouldNotBeRemoved do:
[:sel| | str |
str := String streamContents:
[:strm| | them |
strm
nextPutAll: 'Removed ';
nextPutAll: sel;
nextPutAll: ' because it refers to the local variable'.
them := (removed at: sel) freeVariableReferences asSet intersection: varListAsStrings.
them size > 1 ifTrue:
[strm nextPut: $s.
them := self sortStrings: them].
them do: [:var| strm space; nextPutAll: var].

strm
nextPutAll: ' of interpret.';
newLine;
nextPutAll: 'But it is either used outside of interpret or exported!!';
newLine].
logger newLine; show: str.
self inform: str]
]

{ #category : #'C code generator' }
MLVMCCodeGenerator >> returnTypeForSend: sendNode in: aTMethod boundTo: aCalledMethod typeIfNil: typeIfNil [
"Answer the return type for a send. Unbound sends default to typeIfNil.
Expand Down Expand Up @@ -574,8 +523,9 @@ MLVMCCodeGenerator >> unusedConstants [

{ #category : #'C code generator' }
MLVMCCodeGenerator >> validateCppIf: nodeOrNil withValue: value [

(self vmClass notNil and: [
nodeOrNil args first isConstant and: [
nodeOrNil arguments first isConstant and: [
value isSymbol and: [
(self vmClass defineAtCompileTime: value) not and: [
(self vmClass bindingOf: value) notNil ] ] ] ]) ifTrue: [
Expand Down
6 changes: 3 additions & 3 deletions smalltalksrc/Melchor/VMPluginCodeGenerator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,9 @@ VMPluginCodeGenerator >> generateCASTRemapOopIn: aTSendNode [
]

{ #category : #'CAST translation' }
VMPluginCodeGenerator >> generateCASTSpurRemapOopIn: aTSendNode [
VMPluginCodeGenerator >> generateCASTSpurRemapOopIn: aTSendNode [

^ aTSendNode args second asCASTIn: self
^ aTSendNode arguments second asCASTIn: self
]

{ #category : #'C translation' }
Expand Down Expand Up @@ -578,7 +578,7 @@ VMPluginCodeGenerator >> structTargetKindForDeclaration: decl [ "<String>"
VMPluginCodeGenerator >> typeFor: aNode in: aTMethod [
"Override to provide the type for InterpreterProxy's implicit stack variable."
aNode isVariable ifTrue:
[^(aTMethod typeFor: aNode in: self) ifNil:
[^(aTMethod typeFor: aNode name in: self) ifNil:
[aNode name = 'stack'
ifTrue: [#'sqInt *']
ifFalse: [#sqInt]]].
Expand Down
Loading