Eliot Miranda uploaded a new version of MethodMassage to project VM Maker: http://source.squeak.org/VMMaker/MethodMassage-eem.54.mcz
==================== Summary ====================
Name: MethodMassage-eem.54 Author: eem Time: 21 July 2021, 9:21:51.551737 am UUID: d57514ae-00cd-46a3-a83a-8d690b0e262c Ancestors: MethodMassage-eem.53
Extend the AssemblerAbsentClassImport scheme to support disassembler annotations in current in-image compilation. Allow an AssemblerMethod to specify its source and the class's inst var names (AssemblerMethod>>assemblerStringForAbsentImport).
=============== Diff against MethodMassage-eem.53 ===============
Item was changed: Object subclass: #AssemblerAbsentClassImport + instanceVariableNames: 'className instVars' - instanceVariableNames: 'className' classVariableNames: '' poolDictionaries: '' category: 'MethodMassage-Kernel'!
Item was added: + ----- Method: AssemblerAbsentClassImport>>allInstVarNames (in category 'accessing') ----- + allInstVarNames + ^instVars!
Item was added: + ----- Method: AssemblerAbsentClassImport>>bindingOf:environment: (in category 'compiling') ----- + bindingOf: aSymbol environment: anEnvironment + ^anEnvironment bindingOf: aSymbol!
Item was added: + ----- Method: AssemblerAbsentClassImport>>compilerClass (in category 'compiling') ----- + compilerClass + "Answer a compiler class appropriate for source methods of this class." + + ^Compiler!
Item was added: + ----- Method: AssemblerAbsentClassImport>>instSize (in category 'accessing') ----- + instSize + ^instVars basicSize "answers 0 for nil"!
Item was added: + ----- Method: AssemblerAbsentClassImport>>instVarNames (in category 'accessing') ----- + instVarNames + + ^instVars!
Item was changed: ----- Method: AssemblerAbsentClassImport>>instVarNamesAndOffsetsDo: (in category 'compiling') ----- instVarNamesAndOffsetsDo: aBinaryBlock "This is part of the interface between the compiler and a class's instance or field names. The class should enumerate aBinaryBlock with the instance variable name strings and their integer offsets. The order is important. Names evaluated later will override the same names occurring earlier."
+ instVars ifNotNil: + [instVars withIndexDo: aBinaryBlock]! - "Nothing to do here; We assume Context et al are present." - ^self!
Item was added: + ----- Method: AssemblerAbsentClassImport>>instVars (in category 'accessing') ----- + instVars + + ^instVars!
Item was added: + ----- Method: AssemblerAbsentClassImport>>instVars: (in category 'accessing') ----- + instVars: anArray + + instVars := anArray!
Item was added: + ----- Method: AssemblerAbsentClassImport>>isAbsentClass (in category 'testing') ----- + isAbsentClass + ^true!
Item was added: + ----- Method: AssemblerAbsentClassImport>>newParser (in category 'compiling') ----- + newParser + "Answer a Parser suitable for parsing source code in this Behavior" + ^self parserClass new!
Item was added: + ----- Method: AssemblerAbsentClassImport>>parserClass (in category 'compiling') ----- + parserClass + "Answer a parser class to use for parsing method headers." + + ^self compilerClass parserClass!
Item was added: + ----- Method: AssemblerAbsentClassImport>>variablesAndOffsetsDo: (in category 'compiling') ----- + variablesAndOffsetsDo: aBinaryBlock + "This is the interface between the compiler and a class's instance or field names. The + class should enumerate aBinaryBlock with the field definitions (with nil offsets) followed + by the instance variable name strings and their integer offsets (1-relative). The order is + important; names evaluated later will override the same names occurring earlier." + + instVars ifNotNil: + [instVars withIndexDo: aBinaryBlock]!
Item was changed: Object subclass: #AssemblerMethod + instanceVariableNames: 'literals instructions numArgs numTemps frameSize primitive flag signFlag noCountersFlag accessModifier trailer methodClass selector compiledMethodClass fixLabels encoder header initialPC endPC source allInstVars instVars' - instanceVariableNames: 'literals instructions numArgs numTemps frameSize primitive flag signFlag noCountersFlag accessModifier trailer methodClass selector compiledMethodClass fixLabels encoder header initialPC endPC' classVariableNames: 'AccessorGetters AccessorSetters VerifierGetters VerifierSetters' poolDictionaries: '' category: 'MethodMassage-Kernel'!
!AssemblerMethod commentStamp: 'eem 3/24/2017 08:26' prior: 0! An AssemblerMethod is a holder for a sequence of literals and a sequence of instructions which can represent a disassembled method, or a method being assembled. AssemblerMethod supports three modes of operation.
The first mode is transcription, CompiledMethod -> AssemblerMethod -> CompiledMethod. e.g. | original "CompiledMethod" assembler "AssemblerMethod" replica "CompiledMethod" | original := Object >> #printOn:. assembler := original disassemble. replica := assembler assemble. self assert: original = replica
The second mode is to construct an AssemblerMethod and assemble it. e.g. EncoderForSistaV1 assembler pushReceiver; trapIfNotInstanceOf: {SmallInteger. Character. LargePositiveInteger. LargeNegativeInteger. Integer. Fraction. Magnitude}; pushReceiver; methodReturnTop; assemble
AssemblerMethod new methodClass: Object; selector: #printOn:; numArgs: 1; numTemps: 2; pushReceiver; send: #class; send: #name; popIntoTemporaryVariable: 1; pushTemporaryVariable: 0; doDup; pushTemporaryVariable: 1; send: #first; send: #isVowel; jump: 'L1' if: false; pushConstant: 'an '; jump: 'L2'; label: 'L1'; pushConstant: 'a '; label: 'L2'; send: #nextPutAll:; doPop; pushTemporaryVariable: 1; send: #nextPutAll:; doPop; methodReturnReceiver; assemble
A third mode, useful for storage, inter-image transporation ,etc, is AssemblerMethod -> executable string -> AssemblerMethod. e.g. | original "CompiledMethod" assembler "AssemblerMethod" assemblerText "String" replica "CompiledMethod" | original := Object >> #printOn:. assembler := original disassemble. assemblerText := assembler assemblerString. replica := (Compiler evaluate: assemblerText) assemble. self assert: original = replica
Instance Variables accessModifier: <nil|0,1,2,3> compiledMethodClass: <nil|CompiledCode> encoder: <BytecodeEncoder> endPC: <nil|Integer> fixLabels: <UndefinedObject|Boolean> flag: <Boolean> frameSize: <Integer> header: <nil|Integer> initialPC: <nil|Integer> instructions: <SequenceableCollection> literals: <SequenceableCollection> methodClass: <Behavior> noCountersFlag: <nil|Boolean> numArgs: <Integer> numTemps: <Integer> primitive: <Integer> signFlag: <Boolean> trailer: <CompiledMethodTrailer>
accessModifier - if not nil this is the values of the two bits of flags that specify Newspeak access control in the method header
compiledMethodClass - if not nil this is the class to use to create a method from this assembly
encoder - the encoder to use to encode literals during assembly
endPC - this is the expected endPC of the resulting method. If not nil it will be checked against the actual endPC
fixLabels - if nil, the AssemblerMethod is being used in transcription mode and branch offsets should be integers. if a boolean then it indicates whether instructions contains one or more instructions that need their branches fixing up.
flag - the value of the method's header flag (see CompiledMethod>>flag)
frameSize - the size of the method's frame (see CompiledMethod>>frameSize)
header - this is the expected header of the resulting method. If not nil it will be checked against the actual header
initialPC - this is the expected initialPC of the resulting method. If not nil it will be checked against the actual initialPC
instructions - the sequence of Message and LookupKey objects making up the method's instructions
literals - the sequence of objects making up the method's literals
methodClass - the target class for the method (see CompiledMethod>>methodClass)
noCountersFlag - if not nil this is the value of the Sista JIT-without-performance-counters flag
numArgs - the method's argument count (see CompiledMethod>>numArgs)
numTemps - the method's temporary count (see CompiledMethod>>numTemps)
primitive - the method's primitive (see CompiledMethod>>primitive)
signFlag - the value of the method's signFlag (see CompiledMethod>>signFlag)
trailer - the method's trailer (see CompiledMethod>>trailer)
!
Item was changed: ----- Method: AssemblerMethod>>assemble (in category 'assembling') ----- assemble + | assembler method | - | assembler | assembler := BytecodeAssembler new. encoder ifNotNil: [assembler encoder: encoder]. + method := assembler assemble: self. + (instVars notNil and: [methodClass isAbsentClass]) ifTrue: [methodClass instVars: instVars]. + source ifNotNil: [method properties at: #source put: source]. + ^method! - ^assembler assemble: self!
Item was added: + ----- Method: AssemblerMethod>>assemblerStringForAbsentImport (in category 'printing') ----- + assemblerStringForAbsentImport + "Include all inst var names and source code, in case the class is not present." + ^String streamContents: + [:s| + self printAsAssemblerOn: s + appending: + [:stream| + stream crtab; nextPutAll: 'instVars: '; store: allInstVars; nextPut: $;. + source ifNotNil: + [:theSource| + stream crtab; nextPutAll: 'source: '; store: theSource; nextPut: $;]]]!
Item was added: + ----- Method: AssemblerMethod>>instVars (in category 'accessing') ----- + instVars + ^instVars!
Item was added: + ----- Method: AssemblerMethod>>instVars: (in category 'accessing') ----- + instVars: anArray + instVars := anArray!
Item was changed: ----- Method: AssemblerMethod>>printAsAssemblerOn: (in category 'printing') ----- printAsAssemblerOn: aStream + self printAsAssemblerOn: aStream appending: nil! - aStream nextPut: $(; print: self class; nextPutAll: ' new'. - - self printAccessorsForAssemblyOn: aStream. - self printVerifiersForAssemblyOn: aStream. - self printLiteralsForAssemblyOn: aStream. - self printInstructionsForAssemblyOn: aStream. - - aStream crtab; nextPutAll: #yourself; nextPut: $)!
Item was added: + ----- Method: AssemblerMethod>>printAsAssemblerOn:appending: (in category 'private') ----- + printAsAssemblerOn: aStream appending: aBlockOrNil + aStream nextPut: $(; print: self class; nextPutAll: ' new'. + + self printAccessorsForAssemblyOn: aStream. + self printVerifiersForAssemblyOn: aStream. + self printLiteralsForAssemblyOn: aStream. + self printInstructionsForAssemblyOn: aStream. + + aBlockOrNil ifNotNil: [:aBlock| aBlock value: aStream]. + + aStream crtab; nextPutAll: #yourself; nextPut: $)!
Item was changed: ----- Method: AssemblerMethod>>recordVerificationInfoFrom: (in category 'initialize-release') ----- recordVerificationInfoFrom: aMethod "Record header, initialPC and endPC from aMethod for checking." header := aMethod header. endPC := aMethod endPC. + initialPC := aMethod initialPC. + source := aMethod sourcePointer ~= 0 + ifTrue: [aMethod getSourceFromFile asString] + ifFalse: [aMethod properties at: #source ifAbsent: nil]. + allInstVars := aMethod methodClass allInstVarNames! - initialPC := aMethod initialPC!
Item was added: + ----- Method: AssemblerMethod>>source (in category 'accessing') ----- + source + ^source!
Item was added: + ----- Method: AssemblerMethod>>source: (in category 'accessing') ----- + source: aString + source := aString!
Item was added: + ----- Method: Behavior>>isAbsentClass (in category '*MethodMassage-testing') ----- + isAbsentClass + ^false!
vm-dev@lists.squeakfoundation.org