[Vm-dev] VM Maker Inbox: VMMaker.oscog-eem.2765.mcz
Rolandas Guobys
rolandasguobys at gmail.com
Fri Jul 9 16:31:40 UTC 2021
please don't send me more letters !!!
> On 2020-06-24, at 04:41, commits at source.squeak.org wrote:
>
>
> Eliot Miranda uploaded a new version of VMMaker to project VM Maker Inbox:
> http://source.squeak.org/VMMakerInbox/VMMaker.oscog-eem.2765.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-eem.2765
> Author: eem
> Time: 23 June 2020, 6:41:19.556484 pm
> UUID: 91b9976e-60b9-4b5c-a2f8-b621dd454a07
> Ancestors: VMMaker.oscog-eem.2764
>
> Spur: Rewrite the revised followForwardedObjectFields:toDepth: soi it can be correctly inlined.
>
> Slang: Change the order of application of ensureConditionalAssignmentsAreTransformedIn: so it is always the last thing done in tryToInlineMethodsIn:.
>
> Straight-forward optimization of bindVariablesIn: in the common case of methods being inlined swith unchanged parameters.
>
> =============== Diff against VMMaker.oscog-eem.2764 ===============
>
> Item was changed:
> ----- Method: Spur32BitCoMemoryManager>>followForwardedObjectFields:toDepth: (in category 'as yet unclassified') -----
> followForwardedObjectFields: objOop toDepth: depth
> "Follow pointers in the object to depth.
> Answer if any forwarders were found.
> How to avoid cyclic structures?? A temporary mark bit? eem 6/22/2020 no need since depth is always finite."
> <api>
> <inline: false>
> + | found fmt limit |
> - | oop found fmt |
> found := false.
> self assert: ((self isPointers: objOop) or: [self isOopCompiledMethod: objOop]).
> fmt := self formatOf: objOop.
> + limit := (self numPointerSlotsOf: objOop format: fmt) - 1.
> "It is essential to skip the first field of a method because it may be a
> reference to a Cog method in the method zone, not a real object at all."
> ((self isCompiledMethodFormat: fmt)
> ifTrue: [1]
> ifFalse: [0])
> + to: limit
> + do: [:i| | oop |
> - to: (self numPointerSlotsOf: objOop format: fmt) - 1
> - do: [:i|
> oop := self fetchPointer: i ofObject: objOop.
> (self isNonImmediate: oop) ifTrue:
> [(self isForwarded: oop) ifTrue:
> [found := true.
> oop := self followForwarded: oop.
> self storePointer: i ofObject: objOop withValue: oop].
> (depth > 0
> and: [(self hasPointerFields: oop)
> and: [self followForwardedObjectFields: oop toDepth: depth - 1]]) ifTrue:
> [found := true]]].
> ^found!
>
> Item was changed:
> ----- Method: Spur64BitCoMemoryManager>>followForwardedObjectFields:toDepth: (in category 'forwarding') -----
> followForwardedObjectFields: objOop toDepth: depth
> "Follow pointers in the object to depth.
> Answer if any forwarders were found.
> How to avoid cyclic structures?? A temporary mark bit? eem 6/22/2020 no need since depth is always finite."
> <api>
> <inline: false>
> + | found fmt limit |
> - | oop found fmt |
> found := false.
> self assert: ((self isPointers: objOop) or: [self isOopCompiledMethod: objOop]).
> fmt := self formatOf: objOop.
> + limit := (self numPointerSlotsOf: objOop format: fmt) - 1.
> "It is essential to skip the first field of a method because it may be a
> reference to a Cog method in the method zone, not a real object at all."
> ((self isCompiledMethodFormat: fmt)
> ifTrue: [1]
> ifFalse: [0])
> + to: limit
> + do: [:i| | oop |
> - to: (self numPointerSlotsOf: objOop format: fmt) - 1
> - do: [:i|
> oop := self fetchPointer: i ofObject: objOop.
> (self isNonImmediate: oop) ifTrue:
> [(self isForwarded: oop) ifTrue:
> [found := true.
> oop := self followForwarded: oop.
> self storePointer: i ofObject: objOop withValue: oop].
> (depth > 0
> and: [(self hasPointerFields: oop)
> and: [self followForwardedObjectFields: oop toDepth: depth - 1]]) ifTrue:
> [found := true]]].
> ^found!
>
> Item was changed:
> ----- Method: TMethod>>exitVar:label:in: (in category 'inlining') -----
> exitVar: exitVar label: exitLabel in: aCodeGen
> "Replace each return statement in this method with an assignment to the
> exit variable followed by either a return or a goto to the given label.
> Answer if a goto was generated."
> "Optimization: If exitVar is nil, the return value of the inlined method is not being used, so don't add the assignment statement."
>
> | labelUsed map elisions eliminateReturnSelfs |
> labelUsed := false.
> map := Dictionary new.
> elisions := Set new.
> "Conceivably one might ^self from a struct class and mean it. In most cases though
> ^self means `get me outta here, fast'. So unless this method is from a VMStruct class,
> elide any ^self's"
> eliminateReturnSelfs := ((definingClass inheritsFrom: VMClass) and: [definingClass isStructClass]) not
> and: [returnType = #void or: [returnType = #sqInt]].
> parseTree nodesDo:
> [:node | | replacement |
> node isReturn ifTrue:
> [self transformReturnSubExpression: node
> toAssignmentOf: exitVar
> andGoto: exitLabel
> unless: eliminateReturnSelfs
> into: [:rep :labelWasUsed|
> replacement := rep.
> labelWasUsed ifTrue: [labelUsed := true]]
> in: aCodeGen.
> "replaceNodesIn: is strictly top-down, so any replacement for ^expr ifTrue: [...^fu...] ifFalse: [...^bar...]
> will prevent replacement of either ^fu or ^bar. The corollary is that ^expr ifTrue: [foo] ifFalse: [^bar]
> must be transformed into expr ifTrue: [^foo] ifFalse: [^bar]"
> (node expression isConditionalSend
> and: [node expression hasExplicitReturn])
> ifTrue:
> [elisions add: node.
> (node expression args reject: [:arg| arg endsWithReturn]) do:
> [:nodeNeedingReturn|
> self transformReturnSubExpression: nodeNeedingReturn statements last
> toAssignmentOf: exitVar
> andGoto: exitLabel
> unless: eliminateReturnSelfs
> into: [:rep :labelWasUsed|
> replacement := rep.
> + labelWasUsed ifTrue: [labelUsed := true]]
> + in: aCodeGen.
> - labelWasUsed ifTrue: [labelUsed := true]].
> map
> at: nodeNeedingReturn statements last
> put: replacement]]
> ifFalse:
> [map
> at: node
> put: (replacement ifNil:
> [TLabeledCommentNode new setComment: 'return ', node expression printString])]]].
> map isEmpty ifTrue:
> [self deny: labelUsed.
> ^false].
> "Now do a top-down replacement for all returns that should be mapped to assignments and gotos"
> parseTree replaceNodesIn: map.
> "Now it is safe to eliminate the returning ifs..."
> elisions isEmpty ifFalse:
> [| elisionMap |
> elisionMap := Dictionary new.
> elisions do: [:returnNode| elisionMap at: returnNode put: returnNode expression].
> parseTree replaceNodesIn: elisionMap].
> "Now flatten any new statement lists..."
> parseTree nodesDo:
> [:node| | list |
> (node isStmtList
> and: [node statements notEmpty
> and: [node statements last isStmtList]]) ifTrue:
> [list := node statements last statements.
> node statements removeLast; addAllLast: list]].
> ^labelUsed!
>
> Item was changed:
> ----- Method: TMethod>>inlineFunctionCall:in: (in category 'inlining') -----
> inlineFunctionCall: aSendNode in: aCodeGen
> "Answer the body of the called function, substituting the actual
> parameters for the formal argument variables in the method body.
> Assume caller has established that:
> 1. the method arguments are all substitutable nodes, and
> 2. the method to be inlined contains no additional embedded returns."
>
> | sel meth doNotRename argsForInlining substitutionDict |
> + aCodeGen maybeBreakForInlineOf: aSendNode in: self.
> sel := aSendNode selector.
> meth := (aCodeGen methodNamed: sel) copy.
> meth ifNil:
> [^self inlineBuiltin: aSendNode in: aCodeGen].
> doNotRename := Set withAll: args.
> argsForInlining := aSendNode argumentsForInliningCodeGenerator: aCodeGen.
> meth args with: argsForInlining do:
> [ :argName :exprNode |
> exprNode isLeaf ifTrue:
> [doNotRename add: argName]].
> (meth statements size = 2
> and: [meth statements first isSend
> and: [meth statements first selector == #flag:]]) ifTrue:
> [meth statements removeFirst].
> meth renameVarsForInliningInto: self except: doNotRename in: aCodeGen.
> meth renameLabelsForInliningInto: self.
> self addVarsDeclarationsAndLabelsOf: meth except: doNotRename.
> substitutionDict := Dictionary new: meth args size * 2.
> meth args with: argsForInlining do:
> [ :argName :exprNode |
> + (exprNode isVariable and: [exprNode name = argName]) ifFalse:
> + [substitutionDict at: argName put: exprNode].
> - substitutionDict at: argName put: exprNode.
> (doNotRename includes: argName) ifFalse:
> [locals remove: argName]].
> meth parseTree bindVariablesIn: substitutionDict.
> ^meth parseTree endsWithReturn
> ifTrue: [meth parseTree copyWithoutReturn]
> ifFalse: [meth parseTree]!
>
> Item was changed:
> ----- Method: TMethod>>tryToInlineMethodsIn: (in category 'inlining') -----
> tryToInlineMethodsIn: aCodeGen
> "Expand any (complete) inline methods sent by this method.
> Set the complete flag when all inlining has been done.
> Answer if something was inlined."
>
> | didSomething statementLists |
> "complete ifTrue:
> [^false]."
>
> self definedAsMacro ifTrue:
> [complete ifTrue:
> [^false].
> ^complete := true].
>
> - self ensureConditionalAssignmentsAreTransformedIn: aCodeGen.
> didSomething := self tryToInlineMethodStatementsIn: aCodeGen statementListsInto: [:stmtLists| statementLists := stmtLists].
> didSomething := (self tryToInlineMethodExpressionsIn: aCodeGen) or: [didSomething].
> + self ensureConditionalAssignmentsAreTransformedIn: aCodeGen.
>
> didSomething ifTrue:
> [writtenToGlobalVarsCache := nil].
>
> complete ifFalse:
> [self checkForCompletenessIn: aCodeGen.
> complete ifTrue: [didSomething := true]]. "marking a method complete is progress"
> ^didSomething!
>
> Item was changed:
> ----- Method: TStmtListNode>>bindVariablesIn: (in category 'transformations') -----
> bindVariablesIn: aDictionary
>
> + aDictionary notEmpty ifTrue:
> + [statements := statements collect: [:s| s bindVariablesIn: aDictionary]]!
> - statements := statements collect: [ :s | s bindVariablesIn: aDictionary ].!
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20210709/7825a6a9/attachment-0001.html>
More information about the Vm-dev
mailing list