Marcel Taeumel uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-mt.1244.mcz
==================== Summary ====================
Name: Kernel-mt.1244 Author: mt Time: 12 July 2019, 9:59:41.866568 am UUID: d585f898-09cc-094b-98ed-a74204c82019 Ancestors: Kernel-mt.1243
Refactoring of #literalsDo: - Step 2 of 3.
For more information, see http://forum.world.st/Please-Review-Refactoring-for-literalsDo-etc-tp5099756....
=============== Diff against Kernel-mt.1243 ===============
Item was removed: - ----- Method: AdditionalMethodState>>hasLiteralSuchThat: (in category 'testing') ----- - hasLiteralSuchThat: aBlock - "Answer true if litBlock returns true for any literal in this array, even if embedded in further array structure. - This method is only intended for private use by CompiledMethod hasLiteralSuchThat:" - 1 to: self basicSize do: [:i | - | propertyOrPragma "<Association|Pragma>" | - propertyOrPragma := self basicAt: i. - (propertyOrPragma isVariableBinding - ifTrue: [(aBlock value: propertyOrPragma key) - or: [(aBlock value: propertyOrPragma value) - or: [propertyOrPragma value isArray - and: [propertyOrPragma value hasLiteralSuchThat: aBlock]]]] - ifFalse: [propertyOrPragma hasLiteralSuchThat: aBlock]) ifTrue: - [^true]]. - ^false!
Item was removed: - ----- Method: CompiledBlock>>allLiterals (in category 'literals') ----- - allLiterals - ^self homeMethod allLiterals!
Item was removed: - ----- Method: CompiledBlock>>allSubLiterals (in category 'literals') ----- - allSubLiterals - | literalsExceptOuter unfoldedSubLiterals | - literalsExceptOuter := self literals allButLast. - unfoldedSubLiterals := literalsExceptOuter - select: [:lit| lit isCompiledCode] - thenCollect: [:blockMethod| blockMethod allSubLiterals]. - unfoldedSubLiterals ifEmpty: - [^literalsExceptOuter]. - ^literalsExceptOuter, (unfoldedSubLiterals fold: [:a :b| a, b])!
Item was added: + ----- Method: CompiledBlock>>codeLiteralsDo: (in category 'literals') ----- + codeLiteralsDo: aBlock + "Overwritten to not cause infinite loop." + + aBlock value: self. + + self literalsDo: [:literal | + (literal isCompiledCode and: [literal ~~ self outerCode]) ifTrue: [ + literal codeLiteralsDo: aBlock]].!
Item was removed: - ----- Method: CompiledBlock>>hasLiteral: (in category 'literals') ----- - hasLiteral: literal - "Answer whether the receiver references the argument, literal." - 2 to: self numLiterals do: "exclude outerCode" - [:index | | lit | - lit := self objectAt: index. - (lit literalEqual: literal) ifTrue: - [^true]. - (lit isCompiledCode and: [lit hasLiteral: literal]) ifTrue: - [^true]]. - ^false!
Item was removed: - ----- Method: CompiledBlock>>hasLiteralSuchThat: (in category 'literals') ----- - hasLiteralSuchThat: litBlock - "Answer true if litBlock returns true for any literal in this method, even if embedded in array structure." - 2 to: self numLiterals do: "exclude outerCode" - [:index | | lit | - lit := self objectAt: index. - ((litBlock value: lit) - or: [(lit isArray or: [lit isCompiledCode]) and: [lit hasLiteralSuchThat: litBlock]]) ifTrue: - [^true]]. - ^false!
Item was changed: ----- Method: CompiledCode>>allLiterals (in category 'literals') ----- allLiterals + "Skip compiled-code objects. Keep literal arrays, bindings, etc." + + ^ Array streamContents: [:result | + self allLiteralsDo: [:literal | result nextPut: literal]]! - self subclassResponsibility!
Item was added: + ----- Method: CompiledCode>>allLiteralsDo: (in category 'literals') ----- + allLiteralsDo: aBlock + "Enumerate all literals thoroughly. Follow nested instances of CompiledCode. Do not treat compiled code as literals here." + + self codeLiteralsDo: [:compiledCode | compiledCode literalsDo: [:literal | + literal isCompiledCode ifFalse: [literal allLiteralsDo: aBlock] ]]. + + "Enumerate special selectors." + self flag: #todo. + + "Enumerate special literals such as true and false." + self flag: #todo.!
Item was added: + ----- Method: CompiledCode>>codeLiterals (in category 'literals') ----- + codeLiterals + + ^ Array streamContents: [:stream | + self codeLiteralsDo: [:compiledCode | stream nextPut: compiledCode]]!
Item was added: + ----- Method: CompiledCode>>codeLiteralsDo: (in category 'literals') ----- + codeLiteralsDo: aBlock + "Enumerate all literals that represent instances of CompiledCode. This is especially required for SistaV1." + + aBlock value: self. + + self literalsDo: [:literal | literal isCompiledCode ifTrue: [ + literal codeLiteralsDo: aBlock]].!
Item was added: + ----- Method: CompiledCode>>hasLiteral: (in category 'literals') ----- + hasLiteral: aLiteral + "Since we cannot enumerate this code's special literals, we have to overwrite this method to invoke the encoder scanner explicitely." + + | scanBlock | + (super hasLiteral: aLiteral) ifTrue: [^ true]. + + scanBlock := self class + scanBlocksForLiteral: aLiteral + do: [:primaryScanner :secondaryScanner | + "E.g., scanner for SistaV1 or scanner for V3PlusClosures" + self signFlag ifTrue: [secondaryScanner] ifFalse: [primaryScanner]]. + + self codeLiteralsDo: [:compiledCode | + (compiledCode scanFor: scanBlock) ifTrue: [^ true]]. + + ^ false!
Item was added: + ----- Method: CompiledCode>>hasMethodReturn (in category 'testing') ----- + hasMethodReturn + "Answer whether the receiver has a method-return ('^') in its code." + + | scanner | + self codeLiteralsDo: [:compiledCode | + scanner := InstructionStream on: compiledCode. + (scanner scanFor: [:x | (scanner willReturn + and: [scanner willBlockReturn not]) + "and: [scanner willReturnTopFromMethod not]" "-> Not supported in EncoderForSistaV1"]) + ifTrue: [^ true]]. + ^ false!
Item was added: + ----- Method: CompiledCode>>isQuick (in category 'testing') ----- + isQuick + + self subclassResponsibility.!
Item was changed: ----- Method: CompiledCode>>literals (in category 'literals') ----- literals + + ^ Array streamContents: [:result | + self literalsDo: [:lit | result nextPut: lit]]! - "Answer an Array of the literals referenced by the receiver." - | literals numberLiterals | - literals := Array new: (numberLiterals := self numLiterals). - 1 to: numberLiterals do: - [:index | - literals at: index put: (self objectAt: index + 1)]. - ^literals!
Item was added: + ----- Method: CompiledCode>>literalsDo: (in category 'literals') ----- + literalsDo: aBlock + "Evaluate aBlock for each of the literals referenced by the receiver. Note that this (raw) enumeration addresses *all* objects stored *after* the method header and *before* the first byte code. If you require a deep and meaningful enumeration of literals use #allLiteralsDo: or #codeLiteralsDo:." + + 1 to: self numLiterals do: [:index | + aBlock value: (self literalAt: index)].!
Item was changed: ----- Method: CompiledCode>>messages (in category 'scanning') ----- messages "Answer a Set of all the message selectors sent by this method."
+ | result | + result := Set new. + self messagesDo: [:selector | result add: selector]. + ^ result! - | encoderClass scanner aSet | - encoderClass := self encoderClass. - aSet := Set new. - scanner := InstructionStream on: self. - scanner scanFor: [ :x | - | selector | - (selector := encoderClass selectorToSendOrItselfFor: scanner in: self at: scanner pc) == scanner - ifFalse: - [aSet add: selector] - ifTrue: - [(encoderClass blockMethodOrNilFor: scanner in: self at: scanner pc) ifNotNil: - [:blockMethod| aSet addAll: blockMethod messages]]. - false "keep scanning" ]. - ^aSet!
Item was added: + ----- Method: CompiledCode>>messagesDo: (in category 'scanning') ----- + messagesDo: workBlock + "Evaluate aBlock with all the message selectors sent by me. Duplicate sends possible." + + | scanner selector | + self isQuick ifTrue: [^ self]. + + self codeLiteralsDo: [:compiledCode | + scanner := InstructionStream on: compiledCode. + scanner scanFor: [ :x | + (selector := scanner selectorToSendOrSelf) == scanner + ifFalse: [workBlock value: selector]. + false "keep scanning" ] ].!
Item was removed: - ----- Method: CompiledCode>>messagesDo:encoderClass:visitedSet: (in category 'private') ----- - messagesDo: aBlock encoderClass: encoderClass visitedSet: visitedSet - "The inner engine for messagesDo:" - - | scanner | - scanner := InstructionStream on: self. - scanner scanFor: [ :x | - | selector | - (selector := encoderClass selectorToSendOrItselfFor: scanner in: self at: scanner pc) == scanner - ifFalse: - [(visitedSet ifAbsentAdd: selector) ifTrue: - [aBlock value: selector]] - ifTrue: - [(encoderClass blockMethodOrNilFor: scanner in: self at: scanner pc) ifNotNil: - [:blockMethod| - blockMethod messagesDo: aBlock encoderClass: encoderClass visitedSet: visitedSet]]. - false "keep scanning" ]!
Item was removed: - ----- Method: CompiledCode>>refersTo:bytecodeScanner:thorough: (in category 'literals') ----- - refersTo: literal bytecodeScanner: scanBlockOrNil thorough: thorough - "Answer if the receiver refers to the literal. If the scan block is non-nil, then - use it to find the literal in bytecode. If thorough is true, dive down into - literal arrays and method properties to locate references to the literal there-in." - 2 to: (self isCompiledBlock - ifTrue: [self numLiterals] "exclude outerCode or methodClass" - ifFalse: [self numLiterals - 1]) "exclude selector/properties and methodClass" - do: [:i| | lit | - lit := self objectAt: i. - (literal == lit or: [literal literalEqual: lit]) ifTrue: [^true]. "== for Float bindingOf: #NaN since NaN ~= NaN" - lit isCompiledCode - ifTrue: - [(lit refersTo: literal bytecodeScanner: scanBlockOrNil thorough: thorough) ifTrue: - [^true]] - ifFalse: - [thorough ifTrue: - [lit isVariableBinding - ifTrue: - [literal == lit key ifTrue: [^true]] - ifFalse: - [(lit isArray - and: [(lit hasLiteral: literal) - or: [literal isVariableBinding - and: [literal key isSymbol - and: [lit hasLiteral: literal key]]]]) ifTrue: - [^true]]]]]. - scanBlockOrNil ifNotNil: - [(self scanFor: scanBlockOrNil) ifTrue: - [^true]]. - ^false!
Item was removed: - ----- Method: CompiledCode>>refersTo:primaryBytecodeScanner:secondaryBytecodeScanner:thorough: (in category 'literals') ----- - refersTo: literal primaryBytecodeScanner: primaryScanBlockOrNil secondaryBytecodeScanner: secondaryScanBlockOrNil thorough: thorough - "Answer if the receiver refers to the literal. If the scan blocks are non-nil, then - use them to find the literal in bytecode. If thorough is true, dive down into - literal arrays and method properties to locate references to the literal there-in." - ^self - refersTo: literal - bytecodeScanner: (self signFlag - ifTrue: [secondaryScanBlockOrNil] - ifFalse: [primaryScanBlockOrNil]) - thorough: thorough!
Item was changed: ----- Method: CompiledCode>>scanFor: (in category 'scanning') ----- scanFor: byteOrClosure "Answer whether the receiver contains the argument as a bytecode, if it is a number, or evaluates to true if a block. If a block it can take from one to four bytes." | s end | ^(s := InstructionStream on: self) scanFor: (byteOrClosure isBlock ifTrue: [byteOrClosure numArgs caseOf: { [1] -> [byteOrClosure]. [2] -> [[:byte| byteOrClosure value: byte value: s secondByte]]. [3] -> [end := self endPC - 2. [:byte| s pc <= end and: [byteOrClosure value: byte value: s secondByte value: s thirdByte]]]. [4] -> [end := self endPC - 3. [:byte| s pc <= end and: [byteOrClosure value: byte value: s secondByte value: s thirdByte value: s fourthByte]]] }] ifFalse: [[:instr | instr = byteOrClosure]]) " + SystemNavigation default browseAllSelect: [:m | m scanFor: 134] - Smalltalk browseAllSelect: [:m | m scanFor: 134] "!
Item was added: + ----- Method: CompiledCode>>sendsMessage: (in category 'testing') ----- + sendsMessage: aSelector + + self messagesDo: [:selector | + selector = aSelector ifTrue: [^ true]]. + ^ false!
Item was added: + ----- Method: CompiledCode>>sendsSelector: (in category 'testing') ----- + sendsSelector: aSelector + + self flag: #todo. "mt: Deprecate? AST/Refactoring project needs it..." + ^ self sendsMessage: aSelector!
Item was added: + ----- Method: CompiledCode>>sendsToSuper (in category 'testing') ----- + sendsToSuper + "Answer whether the receiver sends any message to super." + + | scanner | + self codeLiteralsDo: [:compiledCode | + scanner := InstructionStream on: compiledCode. + (scanner scanFor: (self encoderClass superSendScanBlockUsing: scanner)) + ifTrue: [^ true]]. + ^ false!
Item was removed: - ----- Method: CompiledMethod>>allLiterals (in category 'literals') ----- - allLiterals - | literals unfoldedSubLiterals | - literals := self literals. - unfoldedSubLiterals := literals - select: [:lit| lit isCompiledCode] - thenCollect: [:blockMethod| blockMethod allSubLiterals]. - unfoldedSubLiterals ifEmpty: - [^literals]. - ^literals, (unfoldedSubLiterals fold: [:a :b| a, b])!
Item was added: + ----- Method: CompiledMethod>>allLiteralsDo: (in category 'literals') ----- + allLiteralsDo: aBlock + "Overwritten to skip certain (raw) literals." + + " Exclude method selector (or properties) and the method's class." + 1 to: self numLiterals - 2 do: [:index | + (self literalAt: index) allLiteralsDo: aBlock]. + + "Enumerate method selector only through additional method state." + self penultimateLiteral isMethodProperties + ifTrue: [self penultimateLiteral allLiteralsDo: aBlock]. + + "Enumerate special selectors." + self flag: #todo. + + "Enumerate special literals such as true and false." + self flag: #todo.!
Item was removed: - ----- Method: CompiledMethod>>hasLiteral: (in category 'literals') ----- - hasLiteral: literal - "Answer whether the receiver references the argument, literal." - 2 to: self numLiterals - 1 do: "exclude selector/properties & methodClass" - [:index | | lit | - lit := self objectAt: index. - (lit literalEqual: literal) ifTrue: - [^true]. - (lit isCompiledCode and: [lit hasLiteral: literal]) ifTrue: - [^true]]. - ^false!
Item was removed: - ----- Method: CompiledMethod>>hasLiteralSuchThat: (in category 'literals') ----- - hasLiteralSuchThat: litBlock - "Answer true if litBlock returns true for any literal in this method, even if embedded in array structure." - (self penultimateLiteral isMethodProperties - and: [self penultimateLiteral hasLiteralSuchThat: litBlock]) ifTrue: - [^true]. - 2 to: self numLiterals + 1 do: - [:index | | lit | - lit := self objectAt: index. - ((litBlock value: lit) - or: [(lit isArray or: [lit isCompiledCode]) and: [lit hasLiteralSuchThat: litBlock]]) ifTrue: - [^true]]. - ^false!
Item was removed: - ----- Method: CompiledMethod>>hasLiteralThorough: (in category 'literals') ----- - hasLiteralThorough: literal - "Answer true if any literal in this method is literal, - even if embedded in array structure." - - (self penultimateLiteral isMethodProperties - and: [self penultimateLiteral hasLiteralThorough: literal]) ifTrue:[^true]. - 2 to: self numLiterals - 1 "exclude superclass + selector/properties" - do:[:index | | lit | - (((lit := self objectAt: index) literalEqual: literal) - or: [(lit isVariableBinding and: [lit key == literal]) - or: [lit isArray and: [lit hasLiteral: literal]]]) ifTrue: - [^ true]]. - ^ false !
Item was removed: - ----- Method: CompiledMethod>>literalsDo: (in category 'literals') ----- - literalsDo: aBlock - "Evaluate aBlock for each of the literals referenced by the receiver." - 1 to: self numLiterals do: - [:index | - aBlock value: (self objectAt: index + 1)]!
Item was removed: - ----- Method: CompiledMethod>>messages (in category 'scanning') ----- - messages - "Answer a Set of all the message selectors sent by this method." - - | scanner aSet | - aSet := Set new. - scanner := InstructionStream on: self. - scanner scanFor: [ :x | - | selector | - (selector := scanner selectorToSendOrSelf) == scanner ifFalse: [ - aSet add: selector ]. - false "keep scanning" ]. - ^aSet!
Item was removed: - ----- Method: CompiledMethod>>messagesDo: (in category 'scanning') ----- - messagesDo: aBlock - "Evaluate aBlock exactly once with all the message selectors sent by me." - - self isQuick ifFalse: - [self messagesDo: aBlock - encoderClass: self encoderClass - visitedSet: IdentitySet new]!
Item was changed: ----- Method: CompiledMethod>>messagesSequence (in category 'scanning') ----- messagesSequence - "Answer a Set of all the message selectors sent by this method."
+ self flag: #todo. "mt: Better change #messages to return an array instead of a set?" + ^ self messages asArray! - ^Array streamContents: - [:str| | scanner | - scanner := InstructionStream on: self. - scanner scanFor: - [:x | | selectorOrSelf | - (selectorOrSelf := scanner selectorToSendOrSelf) == scanner ifFalse: - [str nextPut: selectorOrSelf]. - false "keep scanning"]]!
Item was changed: ----- Method: CompiledMethod>>objectForDataStream: (in category 'file in/out') ----- objectForDataStream: refStrm + "Reconfigure pragma. Example: #(#FFTPlugin #primitiveFFTTransformData 0 0). See FFT >> #pluginTransformData:." + + self primitive = 117 ifTrue: [(self literalAt: 1) at: 4 put: 0].! - - self primitive = 117 ifTrue: [self literals first at: 4 put: 0]. - !
Item was changed: ----- Method: CompiledMethod>>readsField: (in category 'scanning') ----- readsField: varIndex + "Answer whether the receiver loads the instance variable indexed by the argument." + - "Answer whether the receiver loads the instance variable indexed by the argument." | varIndexCode scanner | varIndexCode := varIndex - 1. + self isQuick ifTrue: [^ self isReturnField and: [self returnField = varIndexCode]]. + + self codeLiteralsDo: [:compiledCode | + scanner := InstructionStream on: compiledCode. + (scanner scanFor: (self encoderClass instVarReadScanBlockFor: varIndexCode using: scanner)) + ifTrue: [^ true]]. + + ^ false! - self isQuick ifTrue: - [^self isReturnField and: [self returnField = varIndexCode]]. - scanner := InstructionStream on: self. - ^scanner scanFor:(self encoderClass instVarReadScanBlockFor: varIndexCode using: scanner)!
Item was changed: ----- Method: CompiledMethod>>readsRef: (in category 'scanning') ----- readsRef: variableBinding "Answer whether the receiver reads the value of the argument." "eem 5/24/2008 Rewritten to no longer assume the compler uses the most compact encoding available (for EncoderForLongFormV3 support)." + | litIndex scanner | + (litIndex := self indexOfLiteral: variableBinding) = 0 + ifTrue: [^false]. + + self codeLiteralsDo: [:compiledCode | + scanner := InstructionStream on: compiledCode. + (scanner scanFor: (self encoderClass bindingReadScanBlockFor: litIndex - 1 using: scanner)) + ifTrue: [^ true]]. + + ^ false! - (litIndex := self indexOfLiteral: variableBinding) = 0 ifTrue: - [^false]. - scanner := InstructionStream on: self. - ^scanner scanFor: (self encoderClass bindingReadScanBlockFor: litIndex - 1 using: scanner)!
Item was removed: - ----- Method: CompiledMethod>>refersToLiteral: (in category 'literals') ----- - refersToLiteral:aLiteral - - ^self hasLiteral: aLiteral.!
Item was removed: - ----- Method: CompiledMethod>>sendsSelector: (in category 'literals') ----- - sendsSelector: aSelector - | scanner | - scanner := InstructionStream on: self. - scanner scanFor: - [:x | - scanner selectorToSendOrSelf == aSelector ifTrue: - [^true]. - false "keep scanning"]. - ^false!
Item was removed: - ----- Method: CompiledMethod>>sendsToSuper (in category 'scanning') ----- - sendsToSuper - "Answer whether the receiver sends any message to super." - | scanner | - scanner := InstructionStream on: self. - ^scanner scanFor: (self encoderClass superSendScanBlockUsing: scanner)!
Item was changed: ----- Method: CompiledMethod>>writesField: (in category 'scanning') ----- writesField: varIndex + "Answer whether the receiver stores into the instance variable indexed by the argument." - "Answer whether the receiver stores into the instance variable indexed - by the argument."
+ | varIndexCode scanner | + self isQuick ifTrue: [^ false]. + varIndexCode := varIndex - 1. + + self codeLiteralsDo: [:compiledCode | + scanner := InstructionStream on: compiledCode. + (scanner scanFor: (self encoderClass instVarWriteScanBlockFor: varIndex - 1 using: scanner)) + ifTrue: [^ true]]. + + ^ false! - | scanner | - self isQuick ifTrue: [^false]. - scanner := InstructionStream on: self. - ^scanner scanFor: (self encoderClass instVarWriteScanBlockFor: varIndex - 1 using: scanner)!
Item was changed: ----- Method: CompiledMethod>>writesRef: (in category 'scanning') ----- writesRef: variableBinding "Answer whether the receiver writes the value of the argument." "eem 5/24/2008 Rewritten to no longer assume the compler uses the most compact encoding available (for EncoderForLongFormV3 support)." + | litIndex scanner | + (litIndex := self indexOfLiteral: variableBinding) = 0 + ifTrue: [^ false]. + + self codeLiteralsDo: [:compiledCode | + scanner := InstructionStream on: compiledCode. + (scanner scanFor: (self encoderClass bindingWriteScanBlockFor: litIndex - 1 using: scanner)) + ifTrue: [^ true]]. + + ^ false! - (litIndex := self indexOfLiteral: variableBinding) = 0 ifTrue: - [^false]. - scanner := InstructionStream on: self. - ^scanner scanFor: (self encoderClass bindingWriteScanBlockFor: litIndex - 1 using: scanner)!
Item was removed: - ----- Method: Pragma>>hasLiteralSuchThat: (in category 'testing') ----- - hasLiteralSuchThat: aBlock - "Answer true if litBlock returns true for any literal in the receiver, even if embedded in further array structure. - This method is only intended for private use by CompiledMethod hasLiteralSuchThat:" - ^(aBlock value: keyword) - or: [arguments hasLiteralSuchThat: aBlock]!
Hi Marcel, Hi All,
please review Kernel-eem.1411 and Compiler-eem.460 in inbox as proposed solutions for the self flag: #todo issue in CompiledCode>>#allLiteralsDo: et al.
On Fri, Jul 12, 2019 at 12:59 AM commits@source.squeak.org wrote:
Marcel Taeumel uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-mt.1244.mcz
==================== Summary ====================
Name: Kernel-mt.1244 Author: mt Time: 12 July 2019, 9:59:41.866568 am UUID: d585f898-09cc-094b-98ed-a74204c82019 Ancestors: Kernel-mt.1243
Refactoring of #literalsDo: - Step 2 of 3.
For more information, see http://forum.world.st/Please-Review-Refactoring-for-literalsDo-etc-tp5099756... .
=============== Diff against Kernel-mt.1243 ===============
Item was removed:
- ----- Method: AdditionalMethodState>>hasLiteralSuchThat: (in category
'testing') -----
- hasLiteralSuchThat: aBlock
"Answer true if litBlock returns true for any literal in this
array, even if embedded in further array structure.
This method is only intended for private use by CompiledMethod
hasLiteralSuchThat:"
1 to: self basicSize do: [:i |
| propertyOrPragma "<Association|Pragma>" |
propertyOrPragma := self basicAt: i.
(propertyOrPragma isVariableBinding
ifTrue: [(aBlock value: propertyOrPragma key)
or: [(aBlock value:
propertyOrPragma value)
or: [propertyOrPragma value isArray
and: [propertyOrPragma
value hasLiteralSuchThat: aBlock]]]]
ifFalse: [propertyOrPragma hasLiteralSuchThat:
aBlock]) ifTrue:
[^true]].
^false!
Item was removed:
- ----- Method: CompiledBlock>>allLiterals (in category 'literals') -----
- allLiterals
^self homeMethod allLiterals!
Item was removed:
- ----- Method: CompiledBlock>>allSubLiterals (in category 'literals')
- allSubLiterals
| literalsExceptOuter unfoldedSubLiterals |
literalsExceptOuter := self literals allButLast.
unfoldedSubLiterals := literalsExceptOuter
select:
[:lit| lit isCompiledCode]
thenCollect: [:blockMethod| blockMethod allSubLiterals].
unfoldedSubLiterals ifEmpty:
[^literalsExceptOuter].
^literalsExceptOuter, (unfoldedSubLiterals fold: [:a :b| a, b])!
Item was added:
- ----- Method: CompiledBlock>>codeLiteralsDo: (in category 'literals')
- codeLiteralsDo: aBlock
"Overwritten to not cause infinite loop."
aBlock value: self.
self literalsDo: [:literal |
(literal isCompiledCode and: [literal ~~ self outerCode])
ifTrue: [
literal codeLiteralsDo: aBlock]].!
Item was removed:
- ----- Method: CompiledBlock>>hasLiteral: (in category 'literals') -----
- hasLiteral: literal
"Answer whether the receiver references the argument, literal."
2 to: self numLiterals do: "exclude outerCode"
[:index | | lit |
lit := self objectAt: index.
(lit literalEqual: literal) ifTrue:
[^true].
(lit isCompiledCode and: [lit hasLiteral: literal]) ifTrue:
[^true]].
^false!
Item was removed:
- ----- Method: CompiledBlock>>hasLiteralSuchThat: (in category
'literals') -----
- hasLiteralSuchThat: litBlock
"Answer true if litBlock returns true for any literal in this
method, even if embedded in array structure."
2 to: self numLiterals do: "exclude outerCode"
[:index | | lit |
lit := self objectAt: index.
((litBlock value: lit)
or: [(lit isArray or: [lit isCompiledCode]) and: [lit
hasLiteralSuchThat: litBlock]]) ifTrue:
[^true]].
^false!
Item was changed: ----- Method: CompiledCode>>allLiterals (in category 'literals') ----- allLiterals
"Skip compiled-code objects. Keep literal arrays, bindings, etc."
^ Array streamContents: [:result |
self allLiteralsDo: [:literal | result nextPut: literal]]!
self subclassResponsibility!
Item was added:
- ----- Method: CompiledCode>>allLiteralsDo: (in category 'literals') -----
- allLiteralsDo: aBlock
"Enumerate all literals thoroughly. Follow nested instances of
CompiledCode. Do not treat compiled code as literals here."
self codeLiteralsDo: [:compiledCode | compiledCode literalsDo:
[:literal |
literal isCompiledCode ifFalse: [literal allLiteralsDo:
aBlock] ]].
"Enumerate special selectors."
self flag: #todo.
"Enumerate special literals such as true and false."
self flag: #todo.!
Item was added:
- ----- Method: CompiledCode>>codeLiterals (in category 'literals') -----
- codeLiterals
^ Array streamContents: [:stream |
self codeLiteralsDo: [:compiledCode | stream nextPut:
compiledCode]]!
Item was added:
- ----- Method: CompiledCode>>codeLiteralsDo: (in category 'literals')
- codeLiteralsDo: aBlock
"Enumerate all literals that represent instances of CompiledCode.
This is especially required for SistaV1."
aBlock value: self.
self literalsDo: [:literal | literal isCompiledCode ifTrue: [
literal codeLiteralsDo: aBlock]].!
Item was added:
- ----- Method: CompiledCode>>hasLiteral: (in category 'literals') -----
- hasLiteral: aLiteral
"Since we cannot enumerate this code's special literals, we have
to overwrite this method to invoke the encoder scanner explicitely."
| scanBlock |
(super hasLiteral: aLiteral) ifTrue: [^ true].
scanBlock := self class
scanBlocksForLiteral: aLiteral
do: [:primaryScanner :secondaryScanner |
"E.g., scanner for SistaV1 or scanner for
V3PlusClosures"
self signFlag ifTrue: [secondaryScanner] ifFalse:
[primaryScanner]].
self codeLiteralsDo: [:compiledCode |
(compiledCode scanFor: scanBlock) ifTrue: [^ true]].
^ false!
Item was added:
- ----- Method: CompiledCode>>hasMethodReturn (in category 'testing') -----
- hasMethodReturn
"Answer whether the receiver has a method-return ('^') in its
code."
| scanner |
self codeLiteralsDo: [:compiledCode |
scanner := InstructionStream on: compiledCode.
(scanner scanFor: [:x | (scanner willReturn
and: [scanner willBlockReturn not])
"and: [scanner willReturnTopFromMethod
not]" "-> Not supported in EncoderForSistaV1"])
ifTrue: [^ true]].
^ false!
Item was added:
- ----- Method: CompiledCode>>isQuick (in category 'testing') -----
- isQuick
self subclassResponsibility.!
Item was changed: ----- Method: CompiledCode>>literals (in category 'literals') ----- literals
^ Array streamContents: [:result |
self literalsDo: [:lit | result nextPut: lit]]!
"Answer an Array of the literals referenced by the receiver."
| literals numberLiterals |
literals := Array new: (numberLiterals := self numLiterals).
1 to: numberLiterals do:
[:index |
literals at: index put: (self objectAt: index + 1)].
^literals!
Item was added:
- ----- Method: CompiledCode>>literalsDo: (in category 'literals') -----
- literalsDo: aBlock
"Evaluate aBlock for each of the literals referenced by the
receiver. Note that this (raw) enumeration addresses *all* objects stored *after* the method header and *before* the first byte code. If you require a deep and meaningful enumeration of literals use #allLiteralsDo: or #codeLiteralsDo:."
1 to: self numLiterals do: [:index |
aBlock value: (self literalAt: index)].!
Item was changed: ----- Method: CompiledCode>>messages (in category 'scanning') ----- messages "Answer a Set of all the message selectors sent by this method."
| result |
result := Set new.
self messagesDo: [:selector | result add: selector].
^ result!
| encoderClass scanner aSet |
encoderClass := self encoderClass.
aSet := Set new.
scanner := InstructionStream on: self.
scanner scanFor: [ :x |
| selector |
(selector := encoderClass selectorToSendOrItselfFor:
scanner in: self at: scanner pc) == scanner
ifFalse:
[aSet add: selector]
ifTrue:
[(encoderClass blockMethodOrNilFor:
scanner in: self at: scanner pc) ifNotNil:
[:blockMethod| aSet addAll:
blockMethod messages]].
false "keep scanning" ].
^aSet!
Item was added:
- ----- Method: CompiledCode>>messagesDo: (in category 'scanning') -----
- messagesDo: workBlock
"Evaluate aBlock with all the message selectors sent by me.
Duplicate sends possible."
| scanner selector |
self isQuick ifTrue: [^ self].
self codeLiteralsDo: [:compiledCode |
scanner := InstructionStream on: compiledCode.
scanner scanFor: [ :x |
(selector := scanner selectorToSendOrSelf) ==
scanner
ifFalse: [workBlock value: selector].
false "keep scanning" ] ].!
Item was removed:
- ----- Method: CompiledCode>>messagesDo:encoderClass:visitedSet: (in
category 'private') -----
- messagesDo: aBlock encoderClass: encoderClass visitedSet: visitedSet
"The inner engine for messagesDo:"
| scanner |
scanner := InstructionStream on: self.
scanner scanFor: [ :x |
| selector |
(selector := encoderClass selectorToSendOrItselfFor:
scanner in: self at: scanner pc) == scanner
ifFalse:
[(visitedSet ifAbsentAdd: selector) ifTrue:
[aBlock value: selector]]
ifTrue:
[(encoderClass blockMethodOrNilFor:
scanner in: self at: scanner pc) ifNotNil:
[:blockMethod|
blockMethod messagesDo: aBlock
encoderClass: encoderClass visitedSet: visitedSet]].
false "keep scanning" ]!
Item was removed:
- ----- Method: CompiledCode>>refersTo:bytecodeScanner:thorough: (in
category 'literals') -----
- refersTo: literal bytecodeScanner: scanBlockOrNil thorough: thorough
"Answer if the receiver refers to the literal. If the scan block
is non-nil, then
use it to find the literal in bytecode. If thorough is true,
dive down into
literal arrays and method properties to locate references to the
literal there-in."
2 to: (self isCompiledBlock
ifTrue: [self numLiterals] "exclude outerCode or
methodClass"
ifFalse: [self numLiterals - 1]) "exclude
selector/properties and methodClass"
do: [:i| | lit |
lit := self objectAt: i.
(literal == lit or: [literal literalEqual: lit]) ifTrue:
[^true]. "== for Float bindingOf: #NaN since NaN ~= NaN"
lit isCompiledCode
ifTrue:
[(lit refersTo: literal bytecodeScanner:
scanBlockOrNil thorough: thorough) ifTrue:
[^true]]
ifFalse:
[thorough ifTrue:
[lit isVariableBinding
ifTrue:
[literal == lit
key ifTrue: [^true]]
ifFalse:
[(lit isArray
and: [(lit
hasLiteral: literal)
or:
[literal isVariableBinding
and: [literal key isSymbol
and: [lit hasLiteral: literal key]]]]) ifTrue:
[^true]]]]].
scanBlockOrNil ifNotNil:
[(self scanFor: scanBlockOrNil) ifTrue:
[^true]].
^false!
Item was removed:
- ----- Method:
CompiledCode>>refersTo:primaryBytecodeScanner:secondaryBytecodeScanner:thorough: (in category 'literals') -----
- refersTo: literal primaryBytecodeScanner: primaryScanBlockOrNil
secondaryBytecodeScanner: secondaryScanBlockOrNil thorough: thorough
"Answer if the receiver refers to the literal. If the scan blocks
are non-nil, then
use them to find the literal in bytecode. If thorough is true,
dive down into
literal arrays and method properties to locate references to the
literal there-in."
^self
refersTo: literal
bytecodeScanner: (self signFlag
ifTrue:
[secondaryScanBlockOrNil]
ifFalse:
[primaryScanBlockOrNil])
thorough: thorough!
Item was changed: ----- Method: CompiledCode>>scanFor: (in category 'scanning') ----- scanFor: byteOrClosure "Answer whether the receiver contains the argument as a bytecode, if it is a number, or evaluates to true if a block. If a block it can take from one to four bytes." | s end | ^(s := InstructionStream on: self) scanFor: (byteOrClosure isBlock ifTrue: [byteOrClosure numArgs caseOf: { [1] -> [byteOrClosure]. [2] -> [[:byte| byteOrClosure value: byte value: s secondByte]]. [3] -> [end := self endPC - 2.
[:byte| s pc <= end
and: [byteOrClosure
value: byte value: s secondByte value: s thirdByte]]]. [4] -> [end :=
self endPC - 3.
[:byte| s pc <= end
and: [byteOrClosure
value: byte value: s secondByte value: s thirdByte value: s fourthByte]]] }] ifFalse: [[:instr | instr =
byteOrClosure]]) "
- SystemNavigation default browseAllSelect: [:m | m scanFor: 134]
- Smalltalk browseAllSelect: [:m | m scanFor: 134] "!
Item was added:
- ----- Method: CompiledCode>>sendsMessage: (in category 'testing') -----
- sendsMessage: aSelector
self messagesDo: [:selector |
selector = aSelector ifTrue: [^ true]].
^ false!
Item was added:
- ----- Method: CompiledCode>>sendsSelector: (in category 'testing') -----
- sendsSelector: aSelector
self flag: #todo. "mt: Deprecate? AST/Refactoring project needs
it..."
^ self sendsMessage: aSelector!
Item was added:
- ----- Method: CompiledCode>>sendsToSuper (in category 'testing') -----
- sendsToSuper
"Answer whether the receiver sends any message to super."
| scanner |
self codeLiteralsDo: [:compiledCode |
scanner := InstructionStream on: compiledCode.
(scanner scanFor: (self encoderClass
superSendScanBlockUsing: scanner))
ifTrue: [^ true]].
^ false!
Item was removed:
- ----- Method: CompiledMethod>>allLiterals (in category 'literals') -----
- allLiterals
| literals unfoldedSubLiterals |
literals := self literals.
unfoldedSubLiterals := literals
select:
[:lit| lit isCompiledCode]
thenCollect: [:blockMethod| blockMethod allSubLiterals].
unfoldedSubLiterals ifEmpty:
[^literals].
^literals, (unfoldedSubLiterals fold: [:a :b| a, b])!
Item was added:
- ----- Method: CompiledMethod>>allLiteralsDo: (in category 'literals')
- allLiteralsDo: aBlock
"Overwritten to skip certain (raw) literals."
" Exclude method selector (or properties) and the method's class."
1 to: self numLiterals - 2 do: [:index |
(self literalAt: index) allLiteralsDo: aBlock].
"Enumerate method selector only through additional method state."
self penultimateLiteral isMethodProperties
ifTrue: [self penultimateLiteral allLiteralsDo: aBlock].
"Enumerate special selectors."
self flag: #todo.
"Enumerate special literals such as true and false."
self flag: #todo.!
Item was removed:
- ----- Method: CompiledMethod>>hasLiteral: (in category 'literals') -----
- hasLiteral: literal
"Answer whether the receiver references the argument, literal."
2 to: self numLiterals - 1 do: "exclude selector/properties &
methodClass"
[:index | | lit |
lit := self objectAt: index.
(lit literalEqual: literal) ifTrue:
[^true].
(lit isCompiledCode and: [lit hasLiteral: literal]) ifTrue:
[^true]].
^false!
Item was removed:
- ----- Method: CompiledMethod>>hasLiteralSuchThat: (in category
'literals') -----
- hasLiteralSuchThat: litBlock
"Answer true if litBlock returns true for any literal in this
method, even if embedded in array structure."
(self penultimateLiteral isMethodProperties
and: [self penultimateLiteral hasLiteralSuchThat: litBlock])
ifTrue:
[^true].
2 to: self numLiterals + 1 do:
[:index | | lit |
lit := self objectAt: index.
((litBlock value: lit)
or: [(lit isArray or: [lit isCompiledCode]) and: [lit
hasLiteralSuchThat: litBlock]]) ifTrue:
[^true]].
^false!
Item was removed:
- ----- Method: CompiledMethod>>hasLiteralThorough: (in category
'literals') -----
- hasLiteralThorough: literal
"Answer true if any literal in this method is literal,
even if embedded in array structure."
(self penultimateLiteral isMethodProperties
and: [self penultimateLiteral hasLiteralThorough: literal])
ifTrue:[^true].
2 to: self numLiterals - 1 "exclude superclass +
selector/properties"
do:[:index | | lit |
(((lit := self objectAt: index) literalEqual: literal)
or: [(lit isVariableBinding and: [lit key == literal])
or: [lit isArray and: [lit hasLiteral: literal]]]) ifTrue:
[^ true]].
^ false !
Item was removed:
- ----- Method: CompiledMethod>>literalsDo: (in category 'literals') -----
- literalsDo: aBlock
"Evaluate aBlock for each of the literals referenced by the
receiver."
1 to: self numLiterals do:
[:index |
aBlock value: (self objectAt: index + 1)]!
Item was removed:
- ----- Method: CompiledMethod>>messages (in category 'scanning') -----
- messages
"Answer a Set of all the message selectors sent by this method."
| scanner aSet |
aSet := Set new.
scanner := InstructionStream on: self.
scanner scanFor: [ :x |
| selector |
(selector := scanner selectorToSendOrSelf) == scanner
ifFalse: [
aSet add: selector ].
false "keep scanning" ].
^aSet!
Item was removed:
- ----- Method: CompiledMethod>>messagesDo: (in category 'scanning') -----
- messagesDo: aBlock
"Evaluate aBlock exactly once with all the message selectors sent
by me."
self isQuick ifFalse:
[self messagesDo: aBlock
encoderClass: self encoderClass
visitedSet: IdentitySet new]!
Item was changed:
----- Method: CompiledMethod>>messagesSequence (in category 'scanning')
messagesSequence
"Answer a Set of all the message selectors sent by this method."
self flag: #todo. "mt: Better change #messages to return an array
instead of a set?"
^ self messages asArray!
^Array streamContents:
[:str| | scanner |
scanner := InstructionStream on: self.
scanner scanFor:
[:x | | selectorOrSelf |
(selectorOrSelf := scanner selectorToSendOrSelf)
== scanner ifFalse:
[str nextPut: selectorOrSelf].
false "keep scanning"]]!
Item was changed: ----- Method: CompiledMethod>>objectForDataStream: (in category 'file in/out') ----- objectForDataStream: refStrm
"Reconfigure pragma. Example: #(#FFTPlugin
#primitiveFFTTransformData 0 0). See FFT >> #pluginTransformData:."
self primitive = 117 ifTrue: [(self literalAt: 1) at: 4 put: 0].!
self primitive = 117 ifTrue: [self literals first at: 4 put: 0].
- !
Item was changed: ----- Method: CompiledMethod>>readsField: (in category 'scanning') ----- readsField: varIndex
"Answer whether the receiver loads the instance variable indexed
by the argument."
"Answer whether the receiver loads the instance variable indexed
by the argument." | varIndexCode scanner | varIndexCode := varIndex - 1.
self isQuick ifTrue: [^ self isReturnField and: [self returnField
= varIndexCode]].
self codeLiteralsDo: [:compiledCode |
scanner := InstructionStream on: compiledCode.
(scanner scanFor: (self encoderClass
instVarReadScanBlockFor: varIndexCode using: scanner))
ifTrue: [^ true]].
^ false!
self isQuick ifTrue:
[^self isReturnField and: [self returnField =
varIndexCode]].
scanner := InstructionStream on: self.
^scanner scanFor:(self encoderClass instVarReadScanBlockFor:
varIndexCode using: scanner)!
Item was changed: ----- Method: CompiledMethod>>readsRef: (in category 'scanning') ----- readsRef: variableBinding "Answer whether the receiver reads the value of the argument." "eem 5/24/2008 Rewritten to no longer assume the compler uses the most compact encoding available (for EncoderForLongFormV3 support)."
| litIndex scanner |
(litIndex := self indexOfLiteral: variableBinding) = 0
ifTrue: [^false].
self codeLiteralsDo: [:compiledCode |
scanner := InstructionStream on: compiledCode.
(scanner scanFor: (self encoderClass
bindingReadScanBlockFor: litIndex - 1 using: scanner))
ifTrue: [^ true]].
^ false!
(litIndex := self indexOfLiteral: variableBinding) = 0 ifTrue:
[^false].
scanner := InstructionStream on: self.
^scanner scanFor: (self encoderClass bindingReadScanBlockFor:
litIndex - 1 using: scanner)!
Item was removed:
- ----- Method: CompiledMethod>>refersToLiteral: (in category 'literals')
- refersToLiteral:aLiteral
^self hasLiteral: aLiteral.!
Item was removed:
- ----- Method: CompiledMethod>>sendsSelector: (in category 'literals')
- sendsSelector: aSelector
| scanner |
scanner := InstructionStream on: self.
scanner scanFor:
[:x |
scanner selectorToSendOrSelf == aSelector ifTrue:
[^true].
false "keep scanning"].
^false!
Item was removed:
- ----- Method: CompiledMethod>>sendsToSuper (in category 'scanning') -----
- sendsToSuper
"Answer whether the receiver sends any message to super."
| scanner |
scanner := InstructionStream on: self.
^scanner scanFor: (self encoderClass superSendScanBlockUsing:
scanner)!
Item was changed: ----- Method: CompiledMethod>>writesField: (in category 'scanning') ----- writesField: varIndex
"Answer whether the receiver stores into the instance variable
indexed by the argument."
"Answer whether the receiver stores into the instance variable
indexed
by the argument."
| varIndexCode scanner |
self isQuick ifTrue: [^ false].
varIndexCode := varIndex - 1.
self codeLiteralsDo: [:compiledCode |
scanner := InstructionStream on: compiledCode.
(scanner scanFor: (self encoderClass
instVarWriteScanBlockFor: varIndex - 1 using: scanner))
ifTrue: [^ true]].
^ false!
| scanner |
self isQuick ifTrue: [^false].
scanner := InstructionStream on: self.
^scanner scanFor: (self encoderClass instVarWriteScanBlockFor:
varIndex - 1 using: scanner)!
Item was changed: ----- Method: CompiledMethod>>writesRef: (in category 'scanning') ----- writesRef: variableBinding "Answer whether the receiver writes the value of the argument." "eem 5/24/2008 Rewritten to no longer assume the compler uses the most compact encoding available (for EncoderForLongFormV3 support)."
| litIndex scanner |
(litIndex := self indexOfLiteral: variableBinding) = 0
ifTrue: [^ false].
self codeLiteralsDo: [:compiledCode |
scanner := InstructionStream on: compiledCode.
(scanner scanFor: (self encoderClass
bindingWriteScanBlockFor: litIndex - 1 using: scanner))
ifTrue: [^ true]].
^ false!
(litIndex := self indexOfLiteral: variableBinding) = 0 ifTrue:
[^false].
scanner := InstructionStream on: self.
^scanner scanFor: (self encoderClass bindingWriteScanBlockFor:
litIndex - 1 using: scanner)!
Item was removed:
- ----- Method: Pragma>>hasLiteralSuchThat: (in category 'testing') -----
- hasLiteralSuchThat: aBlock
"Answer true if litBlock returns true for any literal in the
receiver, even if embedded in further array structure.
This method is only intended for private use by CompiledMethod
hasLiteralSuchThat:"
^(aBlock value: keyword)
or: [arguments hasLiteralSuchThat: aBlock]!
squeak-dev@lists.squeakfoundation.org