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 ].! |
Free forum by Nabble | Edit this page |