Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1070.mcz
==================== Summary ====================
Name: Kernel-eem.1070
Author: eem
Time: 23 March 2017, 11:32:43.949379 am
UUID: 1b8bfbce-9034-46cb-9ac9-631f9d57ae80
Ancestors: Kernel-eem.1069
Move some source and decompilation related methods up from CompiledMethod to CompiledCode. provide method on CompiledCode to allow simple forwarding to the CompiledMehtod from CompiledBlock via outerCode.
Correct a comment.
=============== Diff against Kernel-eem.1069 ===============
Item was added:
+ ----- Method: CompiledCode>>decompile (in category 'decompiling') -----
+ decompile
+ "Return the decompiled parse tree that represents self"
+
+ | class selector |
+ class := self methodClass ifNil: [Object].
+ selector := self selector ifNil: [self defaultSelector].
+ ^class decompilerClass new decompile: selector in: class method: self methodForDecompile!
Item was added:
+ ----- Method: CompiledCode>>decompileWithTemps (in category 'decompiling') -----
+ decompileWithTemps
+ "Answer the decompiled parse tree that represents self, but with the temp names obtained
+ either by compiling the source code, or directly if the method has temps in its trailer."
+
+ ^self method decompileWithTemps!
Item was added:
+ ----- Method: CompiledCode>>getSource (in category 'source code management') -----
+ getSource
+ ^ self getSourceFor: self selector in:self methodClass.!
Item was added:
+ ----- Method: CompiledCode>>getSourceFor:in: (in category 'source code management') -----
+ getSourceFor: selector in: class
+ "Retrieve or reconstruct the source code for this method."
+
+ ^self method getSourceFor: selector in: class!
Item was added:
+ ----- Method: CompiledCode>>method (in category 'accessing') -----
+ method
+ "Answer the home method associated with the receiver."
+
+ ^self subclassResponsibility!
Item was added:
+ ----- Method: CompiledCode>>printReferenceOn: (in category 'printing') -----
+ printReferenceOn: aStream
+ "Print a string that can be used to access the currently installed method."
+ aStream print: self methodClass;
+ nextPutAll: '>>';
+ nextPutAll: self selector storeString!
Item was added:
+ ----- Method: CompiledCode>>printSignatureOn: (in category 'printing') -----
+ printSignatureOn: aStream
+ "Print a string that can be used to access the currently installed method."
+ aStream print: self methodClass;
+ nextPutAll: '>>';
+ nextPutAll: self selector storeString!
Item was added:
+ ----- Method: CompiledCode>>selector (in category 'accessing') -----
+ selector
+ ^self subclassResponsibility!
Item was removed:
- ----- Method: CompiledMethod>>decompile (in category 'decompiling') -----
- decompile
- "Return the decompiled parse tree that represents self"
-
- | class selector |
- class := self methodClass ifNil: [Object].
- selector := self selector ifNil: [self defaultSelector].
- ^class decompilerClass new decompile: selector in: class method: self methodForDecompile!
Item was removed:
- ----- Method: CompiledMethod>>getSource (in category 'source code management') -----
- getSource
- ^ self getSourceFor: self selector in:self methodClass.!
Item was added:
+ ----- Method: CompiledMethod>>method (in category 'accessing') -----
+ method
+ "Answer the home method associated with the receiver.
+ This is polymorphic with closure, CompiledBlock, Context etc"
+
+ ^self!
Item was removed:
- ----- Method: CompiledMethod>>printReferenceOn: (in category 'printing') -----
- printReferenceOn: aStream
- "Print a string that can be used to access the currently installed method."
- aStream print: self methodClass;
- nextPutAll: '>>';
- nextPutAll: self selector storeString!
Item was removed:
- ----- Method: CompiledMethod>>printSignatureOn: (in category 'printing') -----
- printSignatureOn: aStream
- "Print a string that can be used to access the currently installed method."
- aStream print: self methodClass;
- nextPutAll: '>>';
- nextPutAll: self selector storeString!
Item was changed:
----- Method: CompiledMethod>>selector (in category 'accessing') -----
selector
"Answer a method's selector. This is either the penultimate literal,
or, if the method has any properties or pragmas, the selector of
+ the AdditionalMethodState stored in the penultimate literal."
- the MethodProperties stored in the penultimate literal."
| penultimateLiteral |
^(penultimateLiteral := self penultimateLiteral) isMethodProperties
ifTrue: [penultimateLiteral selector]
ifFalse: [penultimateLiteral]!
Eliot Miranda uploaded a new version of SUnit to project The Trunk:
http://source.squeak.org/trunk/SUnit-eem.109.mcz
==================== Summary ====================
Name: SUnit-eem.109
Author: eem
Time: 23 March 2017, 11:29:55.78263 am
UUID: f193663e-b6f8-403f-b8e9-06dad33aa71a
Ancestors: SUnit-eem.108
And delete the method in CompiledMethod
=============== Diff against SUnit-eem.108 ===============
Item was removed:
- ----- Method: CompiledMethod>>isTestMethod (in category '*SUnit-testing') -----
- isTestMethod
-
- ^ self methodClass isTestClass and: [self selector isTestSelector]!
Eliot Miranda uploaded a new version of SUnit to project The Trunk:
http://source.squeak.org/trunk/SUnit-eem.108.mcz
==================== Summary ====================
Name: SUnit-eem.108
Author: eem
Time: 23 March 2017, 11:22:48.940876 am
UUID: 41df1dc8-2451-49f8-a56b-8beac05db850
Ancestors: SUnit-ul.107
Make isTestMethod self-supported in MethodReference instead of replying on CompiledMethod.
=============== Diff against SUnit-ul.107 ===============
Item was changed:
----- Method: MethodReference>>isTestMethod (in category '*SUnit-testing') -----
isTestMethod
+ ^self actualClass isTestClass and: [self methodSymbol isTestSelector]!
- ^ self compiledMethod isTestMethod!
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1069.mcz
==================== Summary ====================
Name: Kernel-eem.1069
Author: eem
Time: 23 March 2017, 11:10:58.741571 am
UUID: f327f174-6584-4322-9adf-aabbb7b95f89
Ancestors: Kernel-eem.1068
Move most relevant accessing mehtods up from Compiledmethod to CompiledCode. Still remaining is a comprehensive localLiterals/literals split.
Add the outerCode accessors to CompiledBlock and its (non-Opal-specific) senders.
Nuke hasNewPropertyFormat; this has been obsolete for ages.
=============== Diff against Kernel-eem.1068 ===============
Item was added:
+ ----- Method: CompiledBlock>>method (in category 'accessing') -----
+ method
+ "answer the compiled method that I am installed in, or nil if none."
+ ^self outerCode method!
Item was added:
+ ----- Method: CompiledBlock>>methodClass (in category 'accessing') -----
+ methodClass
+ "answer the compiled method that I am installed in, or nil if none."
+ ^self outerCode methodClass!
Item was added:
+ ----- Method: CompiledBlock>>methodNode (in category 'accessing') -----
+ methodNode
+ ^ self outerCode methodNode!
Item was added:
+ ----- Method: CompiledBlock>>outerCode (in category 'accessing') -----
+ outerCode
+ "answer the compiled code that I am installed in, or nil if none."
+ ^self literalAt: self numLiterals!
Item was added:
+ ----- Method: CompiledBlock>>outerCode: (in category 'accessing') -----
+ outerCode: aCompiledCode
+ ^self literalAt: self numLiterals put: aCompiledCode!
Item was added:
+ ----- Method: CompiledBlock>>selector (in category 'accessing') -----
+ selector
+ ^ self outerCode selector!
Item was added:
+ ----- Method: CompiledCode>>= (in category 'comparing') -----
+ = method
+ "Answer whether the receiver implements the same code as the argument, method.
+ Here ``same code'' means that if the receiver's source is compiled with the same
+ compiler it should produce the same sequence of bytecodes and literals, same
+ trailer and same properties. Hence this definition of #= (only one of many plausible
+ definitions) can be used to quickly identify changes in the compiler's output."
+ | numLits |
+ method isCompiledMethod ifFalse: [^false].
+ self size = method size ifFalse: [^false].
+ self header = method header ifFalse: [^false]. "N.B. includes numLiterals comparison."
+ self initialPC to: self endPC do:
+ [:i | (self at: i) = (method at: i) ifFalse: [^false]].
+ numLits := self numLiterals.
+ 1 to: numLits do:
+ [:i| | lit1 lit2 |
+ lit1 := self literalAt: i.
+ lit2 := method literalAt: i.
+ (lit1 == lit2 or: [lit1 literalEqual: lit2]) ifFalse:
+ [(i = 1 and: [#(117 120) includes: self primitive])
+ ifTrue:
+ [lit1 isArray
+ ifTrue:
+ [(lit2 isArray and: [(lit1 first: 2) = (lit2 first: 2)]) ifFalse:
+ [^false]]
+ ifFalse: "ExternalLibraryFunction"
+ [(lit1 analogousCodeTo: lit2) ifFalse:
+ [^false]]]
+ ifFalse:
+ [i = (numLits - 1)
+ ifTrue: "properties"
+ [(self properties analogousCodeTo: method properties)
+ ifFalse: [^false]]
+ ifFalse: "last literal (methodClassAssociation) of class-side methods is not unique"
+ [(i = numLits
+ and: [lit1 isVariableBinding
+ and: [lit2 isVariableBinding
+ and: [lit1 key == lit2 key
+ and: [lit1 value == lit2 value]]]]) ifFalse:
+ [^false]]]]].
+ ^true!
Item was added:
+ ----- Method: CompiledCode>>asString (in category 'converting') -----
+ asString
+
+ ^self printString!
Item was added:
+ ----- Method: CompiledCode>>at:ifAbsent: (in category 'accessing') -----
+ at: index ifAbsent: exceptionBlock
+ "Answer the element at my position index. If I do not contain an element
+ at index, answer the result of evaluating the argument, exceptionBlock."
+
+ (index <= self size and: [self initialPC <= index]) ifTrue: [^self at: index].
+ ^exceptionBlock value!
Item was added:
+ ----- Method: CompiledCode>>bytecodeSetName (in category 'accessing') -----
+ bytecodeSetName
+ ^self encoderClass name copyReplaceAll: 'EncoderFor' with: ''!
Item was added:
+ ----- Method: CompiledCode>>clearFlag (in category 'accessing') -----
+ clearFlag
+ "Clear the user-level flag bit"
+
+ self objectAt: 1 put: (self header bitAnd: (1 << 29) bitInvert)!
Item was added:
+ ----- Method: CompiledCode>>clearSignFlag (in category 'accessing') -----
+ clearSignFlag
+ "Clear the sign flag bit. The sign flag bit may be
+ used by the VM to select an alternate bytecode set."
+
+ self signFlag ifTrue:
+ [self objectAt: 1 put: self header - SmallInteger minVal]!
Item was added:
+ ----- Method: CompiledCode>>copyFrom: (in category 'copying') -----
+ copyFrom: anotherObject
+ "Copy to myself all instance variables I have in common with anotherObject.
+ This is dangerous because it ignores an object's control over its own inst vars."
+
+ <primitive: 168>
+ anotherObject isCompiledCode
+ ifTrue:
+ [1 to: self numLiterals do:
+ [:i| self literalAt: i put: (anotherObject literalAt: i)]]
+ ifFalse:
+ [1 to: self numLiterals do:
+ [:i| self literalAt: i put: (anotherObject at: i)]].
+ self initialPC to: (self basicSize min: anotherObject basicSize) do:
+ [:i|
+ self basicAt: i put: (anotherObject basicAt: i)]!
Item was added:
+ ----- Method: CompiledCode>>copyWithTrailerBytes: (in category 'copying') -----
+ copyWithTrailerBytes: trailer
+ "Testing:
+ (CompiledMethod compiledMethodAt: #copyWithTrailerBytes:)
+ tempNamesPut: 'copy end '
+ "
+ | copy end start |
+ start := self initialPC.
+ end := self endPC.
+ copy := trailer createMethod: end - start + 1 class: self class header: self header.
+ 1 to: self numLiterals do: [:i | copy literalAt: i put: (self literalAt: i)].
+ start to: end do: [:i | copy at: i put: (self at: i)].
+ copy postCopy.
+ ^copy!
Item was added:
+ ----- Method: CompiledCode>>encoderClass (in category 'accessing') -----
+ encoderClass
+ "Answer the encoder class that encoded the bytecodes in this method.
+ The sign flag bit is used by the VM to select a bytecode set. This formulation
+ may seem odd but this has to be fast, so no property probe unless needed."
+
+ ^self header >= 0
+ ifTrue:
+ [PrimaryBytecodeSetEncoderClass]
+ ifFalse:
+ [PrimaryBytecodeSetEncoderClass == SecondaryBytecodeSetEncoderClass
+ ifTrue: "Support for testing prior to installing another set"
+ [(self propertyValueAt: #encoderClass) ifNil: [SecondaryBytecodeSetEncoderClass]]
+ ifFalse:
+ [SecondaryBytecodeSetEncoderClass]]!
Item was added:
+ ----- Method: CompiledCode>>endPC (in category 'accessing') -----
+ endPC
+ "Answer the index of the last bytecode."
+ ^ self trailer endPC
+ !
Item was added:
+ ----- Method: CompiledCode>>flag (in category 'accessing') -----
+ flag
+ "Answer the user-level flag bit"
+
+ ^((self header bitShift: -29) bitAnd: 1) = 1!
Item was added:
+ ----- Method: CompiledCode>>flushCache (in category 'cleaning') -----
+ flushCache
+ "Tell the virtual machine to remove all references to this method from its method
+ lookup cache(s), if it has them. This is provided for backwards compatibility.
+ When a method is redefined (added to, removed from, or replaced in, a method
+ dictionary) then Symbol flushCache should be used. This is because adding or
+ removing a method may alter the method that a given selector should invoke
+ for methods other than the receiver. For example, if a subclass inherits a
+ method and this is overridden, flushing the new method will not flush the existing
+ method.
+
+ If a method is modified in-place (for example, some bytecode is replaced by
+ bytecode that effects a breakpoint) then voidCogVMState should be used."
+
+ <primitive: 116>!
Item was added:
+ ----- Method: CompiledCode>>frameSize (in category 'accessing') -----
+ frameSize
+ "Answer the size of temporary frame needed to run the receiver."
+ "NOTE: Versions 2.7 and later use two sizes of contexts."
+
+ (self header noMask: 16r20000)
+ ifTrue: [^ SmallFrame]
+ ifFalse: [^ LargeFrame]
+ !
Item was added:
+ ----- Method: CompiledCode>>hash (in category 'comparing') -----
+ hash
+ "CompiledMethod>>#= compares code, i.e. same literals and same bytecode.
+ So we look at the header, methodClass and some bytes between initialPC and endPC,
+ but /not/ the selector because the equal method does not compare selectors.
+ Note that we must override ByteArray>hash which looks at all bytes of the receiver.
+ Using bytes from the pointer part of a COmpiledmethod can lead to a variable hash
+ if and when when the GC moves literals in the receiver."
+ | initialPC endPC hash |
+ initialPC := self initialPC.
+ endPC := self endPC.
+ hash := self species hash + self header + initialPC + endPC + self methodClass hash bitAnd: 16rFFFFFFF.
+ "sample approximately 20 bytes"
+ initialPC to: endPC by: (endPC - initialPC // 20 max: 1) do:
+ [:i| hash := hash + (self at: i)].
+ ^hash
+
+ "(CompiledMethod>>#hash) hash"!
Item was added:
+ ----- Method: CompiledCode>>header (in category 'literals') -----
+ header
+ "Answer the word containing the information about the form of the
+ receiver and the form of the context needed to run the receiver.
+
+ sign:1 29-28:accessModifier 27-24:numArgs 23-18:numTemps 17:largeFrameFlag 16:hasPrimitive 15:isOptimized 14-0:numLits"
+
+ ^self objectAt: 1!
Item was added:
+ ----- Method: CompiledCode>>initialPC (in category 'accessing') -----
+ initialPC
+ "Answer the program counter for the receiver's first bytecode."
+
+ ^ (self numLiterals + 1) * Smalltalk wordSize + 1
+ !
Item was added:
+ ----- Method: CompiledCode>>literalAt: (in category 'literals') -----
+ literalAt: index
+ "Answer the literal indexed by the argument."
+
+ ^self objectAt: index + 1!
Item was added:
+ ----- Method: CompiledCode>>literalAt:put: (in category 'literals') -----
+ literalAt: index put: value
+ "Replace the literal indexed by the first argument with the second
+ argument. Answer the second argument."
+
+ ^self objectAt: index + 1 put: value!
Item was added:
+ ----- Method: CompiledCode>>methodClass (in category 'accessing') -----
+ methodClass
+ ^self subclassResponsibility!
Item was added:
+ ----- Method: CompiledCode>>needsFrameSize: (in category 'initialize-release') -----
+ needsFrameSize: newFrameSize
+ "Set the largeFrameBit to accomodate the newFrameSize"
+ | largeFrameBit header |
+ largeFrameBit := 16r20000.
+ (self numTemps + newFrameSize) > LargeFrame ifTrue:
+ [^ self error: 'Cannot compile -- stack including temps is too deep'].
+ header := self objectAt: 1.
+ (header bitAnd: largeFrameBit) ~= 0
+ ifTrue: [header := header - largeFrameBit].
+ self objectAt: 1 put: header
+ + ( ((self numTemps + newFrameSize) > SmallFrame or: [ self primitive = 84 "perform:withArguments:"])
+ ifTrue: [largeFrameBit]
+ ifFalse: [0])!
Item was added:
+ ----- Method: CompiledCode>>numArgs (in category 'accessing') -----
+ numArgs
+ "Answer the number of arguments the receiver takes."
+
+ ^ (self header bitShift: -24) bitAnd: 16r0F!
Item was added:
+ ----- Method: CompiledCode>>numLiterals (in category 'accessing') -----
+ numLiterals
+ "Answer the number of literals used by the receiver."
+ ^self header bitAnd: 16r7FFF!
Item was added:
+ ----- Method: CompiledCode>>numTemps (in category 'accessing') -----
+ numTemps
+ "Answer the number of temporary variables used by the receiver."
+
+ ^ (self header bitShift: -18) bitAnd: 16r3F!
Item was added:
+ ----- Method: CompiledCode>>objectAt: (in category 'literals') -----
+ objectAt: index
+ "Primitive. Answer the method header (if index=1) or a literal (if index
+ >1) from the receiver. Essential. See Object documentation
+ whatIsAPrimitive."
+
+ <primitive: 68>
+ self primitiveFailed!
Item was added:
+ ----- Method: CompiledCode>>objectAt:put: (in category 'literals') -----
+ objectAt: index put: value
+ "Primitive. Store the value argument into a literal in the receiver. An
+ index of 2 corresponds to the first literal. Fails if the index is less than 2
+ or greater than the number of literals. Answer the value as the result.
+ Normally only the compiler sends this message, because only the
+ compiler stores values in CompiledMethods. Essential. See Object
+ documentation whatIsAPrimitive."
+
+ <primitive: 69>
+ self primitiveFailed!
Item was added:
+ ----- Method: CompiledCode>>outboundPointersDo: (in category 'tracing') -----
+ outboundPointersDo: aBlock
+
+ | numLiterals |
+ aBlock value: self class.
+ numLiterals := self numLiterals.
+ 1 to: numLiterals do: [:i | aBlock value: (self literalAt: i)]!
Item was added:
+ ----- Method: CompiledCode>>printOn: (in category 'printing') -----
+ printOn: aStream
+ "Overrides method inherited from the byte arrayed collection."
+ aStream nextPut: $(.
+ self printReferenceOn: aStream.
+ aStream space; nextPut: $".
+ self printNameOn: aStream.
+ aStream nextPut: $(;
+ print: self identityHash;
+ nextPut: $);
+ nextPut: $";
+ nextPut: $)!
Item was added:
+ ----- Method: CompiledCode>>protocol (in category 'accessing') -----
+ protocol
+ ^self methodClass ifNotNil:
+ [:class|
+ self selector ifNotNil:
+ [:selector|
+ class whichCategoryIncludesSelector: selector]]!
Item was added:
+ ----- Method: CompiledCode>>readDataFrom:size: (in category 'file in/out') -----
+ readDataFrom: aDataStream size: varsOnDisk
+ "Fill in my fields. My header and number of literals are already installed. Must read both objects for the literals and bytes for the bytecodes."
+
+ self error: 'Must use readMethod'.!
Item was added:
+ ----- Method: CompiledCode>>reference (in category 'printing') -----
+ reference
+ ^ String streamContents: [ : stream | self printReferenceOn: stream ]!
Item was added:
+ ----- Method: CompiledCode>>referredInstVars (in category 'accessing') -----
+ referredInstVars
+ "Answer a Set of the inst var names the receiver accesses."
+ | allInstVarNames instVarNames |
+ allInstVarNames := self methodClass allInstVarNames.
+ self isReturnField ifTrue:
+ [^Set with: (allInstVarNames at: self returnField + 1)].
+ instVarNames := Set new.
+ self abstractBytecodeMessagesDo:
+ [:msg|
+ (#(#popIntoReceiverVariable:
+ #pushReceiverVariable:
+ #storeIntoReceiverVariable:) includes: msg selector) ifTrue:
+ [instVarNames add: (allInstVarNames at: msg argument + 1)]].
+ ^instVarNames
+
+ "Dictionary newFromPairs: (Point selectors collect: [:s| { s. (Point >> s) referredInstVars}])"!
Item was added:
+ ----- Method: CompiledCode>>scanner (in category 'accessing') -----
+ scanner
+
+ ^ InstructionStream on: self!
Item was added:
+ ----- Method: CompiledCode>>setSignFlag (in category 'accessing') -----
+ setSignFlag
+ "Set the sign flag bit. The sign flag bit may be
+ used by the VM to select an alternate bytecode set."
+
+ self signFlag ifFalse:
+ [self objectAt: 1 put: self header + SmallInteger minVal]!
Item was added:
+ ----- Method: CompiledCode>>signFlag (in category 'accessing') -----
+ signFlag
+ "Answer the sign flag bit. The sign flag bit may be
+ used by the VM to select an alternate bytecode set."
+
+ ^self header < 0!
Item was added:
+ ----- Method: CompiledCode>>storeDataOn: (in category 'file in/out') -----
+ storeDataOn: aDataStream
+ "Store myself on a DataStream. I am a mixture of objects and raw data bytes. Only use this for blocks. Normal methodDictionaries should not be put out using ReferenceStreams. Their fileOut should be attached to the beginning of the file."
+
+ | byteLength lits |
+ "No inst vars of the normal type"
+ byteLength := self basicSize.
+ aDataStream
+ beginInstance: self class
+ size: byteLength.
+ lits := self numLiterals + 1. "counting header"
+ 1 to: lits do:
+ [:ii | aDataStream nextPut: (self objectAt: ii)].
+ lits*4+1 to: byteLength do:
+ [:ii | aDataStream byteStream nextPut: (self basicAt: ii)].
+ "write bytes straight through to the file"!
Item was added:
+ ----- Method: CompiledCode>>storeOn: (in category 'printing') -----
+ storeOn: aStream
+ | noneYet |
+ aStream nextPutAll: '(('.
+ aStream nextPutAll: self class name.
+ aStream nextPutAll: ' newMethod: '.
+ aStream store: self size - self initialPC + 1.
+ aStream nextPutAll: ' header: '.
+ aStream store: self header.
+ aStream nextPut: $).
+ noneYet := self storeElementsFrom: self initialPC to: self endPC on: aStream.
+ 1 to: self numLiterals do:
+ [:index |
+ noneYet
+ ifTrue: [noneYet := false]
+ ifFalse: [aStream nextPut: $;].
+ aStream nextPutAll: ' literalAt: '.
+ aStream store: index.
+ aStream nextPutAll: ' put: '.
+ aStream store: (self literalAt: index)].
+ noneYet ifFalse: [aStream nextPutAll: '; yourself'].
+ aStream nextPut: $)!
Item was added:
+ ----- Method: CompiledCode>>trailer (in category 'accessing') -----
+ trailer
+ "Answer the receiver's trailer"
+ ^ CompiledMethodTrailer new method: self
+ !
Item was added:
+ ----- Method: CompiledCode>>veryDeepCopyWith: (in category 'file in/out') -----
+ veryDeepCopyWith: deepCopier
+ "Return self. I am always shared. Do not record me. Only use this for blocks. Normally methodDictionaries should not be copied this way."!
Item was added:
+ ----- Method: CompiledCode>>voidCogVMState (in category 'cleaning') -----
+ voidCogVMState
+ "Tell the VM to remove all references to any machine code form of the method.
+ This primitive must be called whenever a method is in use and modified. This is
+ more aggressive (and *much* more costly) than flushCache since it must search
+ through all context objects, making sure that none have a (hidden) machine code pc
+ in the receiver. Since modifying a method will likely change the generated machine code,
+ modifying a method (rather than redefining it) requires this more aggressive flush."
+
+ <primitive: 215>
+ ^self flushCache!
Item was removed:
- ----- Method: CompiledMethod>>= (in category 'comparing') -----
- = method
- "Answer whether the receiver implements the same code as the argument, method.
- Here ``same code'' means that if the receiver's source is compiled with the same
- compiler it should produce the same sequence of bytecodes and literals, same
- trailer and same properties. Hence this definition of #= (only one of many plausible
- definitions) can be used to quickly identify changes in the compiler's output."
- | numLits |
- method isCompiledMethod ifFalse: [^false].
- self size = method size ifFalse: [^false].
- self header = method header ifFalse: [^false]. "N.B. includes numLiterals comparison."
- self initialPC to: self endPC do:
- [:i | (self at: i) = (method at: i) ifFalse: [^false]].
- numLits := self numLiterals.
- 1 to: numLits do:
- [:i| | lit1 lit2 |
- lit1 := self literalAt: i.
- lit2 := method literalAt: i.
- (lit1 == lit2 or: [lit1 literalEqual: lit2]) ifFalse:
- [(i = 1 and: [#(117 120) includes: self primitive])
- ifTrue:
- [lit1 isArray
- ifTrue:
- [(lit2 isArray and: [(lit1 first: 2) = (lit2 first: 2)]) ifFalse:
- [^false]]
- ifFalse: "ExternalLibraryFunction"
- [(lit1 analogousCodeTo: lit2) ifFalse:
- [^false]]]
- ifFalse:
- [i = (numLits - 1)
- ifTrue: "properties"
- [(self properties analogousCodeTo: method properties)
- ifFalse: [^false]]
- ifFalse: "last literal (methodClassAssociation) of class-side methods is not unique"
- [(i = numLits
- and: [lit1 isVariableBinding
- and: [lit2 isVariableBinding
- and: [lit1 key == lit2 key
- and: [lit1 value == lit2 value]]]]) ifFalse:
- [^false]]]]].
- ^true!
Item was removed:
- ----- Method: CompiledMethod>>asString (in category 'converting') -----
- asString
-
- ^self printString!
Item was removed:
- ----- Method: CompiledMethod>>at:ifAbsent: (in category 'accessing') -----
- at: index ifAbsent: exceptionBlock
- "Answer the element at my position index. If I do not contain an element
- at index, answer the result of evaluating the argument, exceptionBlock."
-
- (index <= self size and: [self initialPC <= index]) ifTrue: [^self at: index].
- ^exceptionBlock value!
Item was removed:
- ----- Method: CompiledMethod>>bytecodeSetName (in category 'accessing') -----
- bytecodeSetName
- ^self encoderClass name copyReplaceAll: 'EncoderFor' with: ''!
Item was removed:
- ----- Method: CompiledMethod>>clearFlag (in category 'accessing') -----
- clearFlag
- "Clear the user-level flag bit"
-
- self objectAt: 1 put: (self header bitAnd: (1 << 29) bitInvert)!
Item was removed:
- ----- Method: CompiledMethod>>clearSignFlag (in category 'accessing') -----
- clearSignFlag
- "Clear the sign flag bit. The sign flag bit may be
- used by the VM to select an alternate bytecode set."
-
- self signFlag ifTrue:
- [self objectAt: 1 put: self header - SmallInteger minVal]!
Item was removed:
- ----- Method: CompiledMethod>>copyFrom: (in category 'copying') -----
- copyFrom: anotherObject
- "Copy to myself all instance variables I have in common with anotherObject.
- This is dangerous because it ignores an object's control over its own inst vars."
-
- <primitive: 168>
- anotherObject isCompiledMethod
- ifTrue:
- [1 to: self numLiterals do:
- [:i| self literalAt: i put: (anotherObject literalAt: i)]]
- ifFalse:
- [1 to: self numLiterals do:
- [:i| self literalAt: i put: (anotherObject at: i)]].
- self initialPC to: (self basicSize min: anotherObject basicSize) do:
- [:i|
- self basicAt: i put: (anotherObject basicAt: i)]!
Item was removed:
- ----- Method: CompiledMethod>>copyWithTrailerBytes: (in category 'copying') -----
- copyWithTrailerBytes: trailer
- "Testing:
- (CompiledMethod compiledMethodAt: #copyWithTrailerBytes:)
- tempNamesPut: 'copy end '
- "
- | copy end start |
- start := self initialPC.
- end := self endPC.
- copy := trailer createMethod: end - start + 1 class: self class header: self header.
- 1 to: self numLiterals do: [:i | copy literalAt: i put: (self literalAt: i)].
- start to: end do: [:i | copy at: i put: (self at: i)].
- copy postCopy.
- ^copy!
Item was removed:
- ----- Method: CompiledMethod>>encoderClass (in category 'accessing') -----
- encoderClass
- "Answer the encoder class that encoded the bytecodes in this method.
- The sign flag bit is used by the VM to select a bytecode set. This formulation
- may seem odd but this has to be fast, so no property probe unless needed."
-
- ^self header >= 0
- ifTrue:
- [PrimaryBytecodeSetEncoderClass]
- ifFalse:
- [PrimaryBytecodeSetEncoderClass == SecondaryBytecodeSetEncoderClass
- ifTrue: "Support for testing prior to installing another set"
- [(self propertyValueAt: #encoderClass) ifNil: [SecondaryBytecodeSetEncoderClass]]
- ifFalse:
- [SecondaryBytecodeSetEncoderClass]]!
Item was removed:
- ----- Method: CompiledMethod>>endPC (in category 'accessing') -----
- endPC
- "Answer the index of the last bytecode."
- ^ self trailer endPC
- !
Item was removed:
- ----- Method: CompiledMethod>>flag (in category 'accessing') -----
- flag
- "Answer the user-level flag bit"
-
- ^((self header bitShift: -29) bitAnd: 1) = 1!
Item was removed:
- ----- Method: CompiledMethod>>flushCache (in category 'accessing') -----
- flushCache
- "Tell the interpreter to remove all references to this method from its method lookup cache, if it has one. This primitive must be called whenever a method is defined or removed.
- NOTE: Only one of two selective flush methods needs to be used.
- Squeak 2.2 and earlier uses 119 (See Symbol flushCache).
- Squeak 2.3 and later uses 116 (See CompiledMethod flushCache)."
-
- <primitive: 116>
- !
Item was removed:
- ----- Method: CompiledMethod>>frameSize (in category 'accessing') -----
- frameSize
- "Answer the size of temporary frame needed to run the receiver."
- "NOTE: Versions 2.7 and later use two sizes of contexts."
-
- (self header noMask: 16r20000)
- ifTrue: [^ SmallFrame]
- ifFalse: [^ LargeFrame]
- !
Item was removed:
- ----- Method: CompiledMethod>>hasNewPropertyFormat (in category 'testing') -----
- hasNewPropertyFormat
- "As of the closure compiler all methods have (or better have) the new
- format where the penultimate literal is either the method's selector
- or its properties and the ultimate literal is the class association."
- ^true!
Item was removed:
- ----- Method: CompiledMethod>>hash (in category 'comparing') -----
- hash
- "CompiledMethod>>#= compares code, i.e. same literals and same bytecode.
- So we look at the header, methodClass and some bytes between initialPC and endPC,
- but /not/ the selector because the equal method does not compare selectors.
- Note that we must override ByteArray>hash which looks at all bytes of the receiver.
- Using bytes from the pointer part of a COmpiledmethod can lead to a variable hash
- if and when when the GC moves literals in the receiver."
- | initialPC endPC hash |
- initialPC := self initialPC.
- endPC := self endPC.
- hash := self species hash + self header + initialPC + endPC + self methodClass hash bitAnd: 16rFFFFFFF.
- "sample approximately 20 bytes"
- initialPC to: endPC by: (endPC - initialPC // 20 max: 1) do:
- [:i| hash := hash + (self at: i)].
- ^hash
-
- "(CompiledMethod>>#hash) hash"!
Item was removed:
- ----- Method: CompiledMethod>>header (in category 'literals') -----
- header
- "Answer the word containing the information about the form of the
- receiver and the form of the context needed to run the receiver.
- There are two different formats, selected by the sign bit. These are
-
- Original Squeak V3:
- 30:sign:0 29:flag 28:prim (high bit) 27-24:numArgs 23-18:numTemps 17:largeFrameFlag 16-9:numLits 8-0:prim (low 9 bits)
-
- Alternate Bytecode Set
- 30:sign:1 29-28:accessModifier 27-24:numArgs 23-18:numTemps 17:largeFrameFlag 16:hasPrimitive 15-0:numLits
-
- i.e. the Alternate Bytecode Set expands the number of literals to 65535 by assuming a CallPrimitive bytecode."
-
- ^self objectAt: 1!
Item was removed:
- ----- Method: CompiledMethod>>initialPC (in category 'accessing') -----
- initialPC
- "Answer the program counter for the receiver's first bytecode."
-
- ^ (self numLiterals + 1) * Smalltalk wordSize + 1
- !
Item was removed:
- ----- Method: CompiledMethod>>literalAt: (in category 'literals') -----
- literalAt: index
- "Answer the literal indexed by the argument."
-
- ^self objectAt: index + 1!
Item was removed:
- ----- Method: CompiledMethod>>literalAt:put: (in category 'literals') -----
- literalAt: index put: value
- "Replace the literal indexed by the first argument with the second
- argument. Answer the second argument."
-
- ^self objectAt: index + 1 put: value!
Item was removed:
- ----- Method: CompiledMethod>>needsFrameSize: (in category 'initialize-release') -----
- needsFrameSize: newFrameSize
- "Set the largeFrameBit to accomodate the newFrameSize"
- | largeFrameBit header |
- largeFrameBit := 16r20000.
- (self numTemps + newFrameSize) > LargeFrame ifTrue:
- [^ self error: 'Cannot compile -- stack including temps is too deep'].
- header := self objectAt: 1.
- (header bitAnd: largeFrameBit) ~= 0
- ifTrue: [header := header - largeFrameBit].
- self objectAt: 1 put: header
- + ( ((self numTemps + newFrameSize) > SmallFrame or: [ self primitive = 84 "perform:withArguments:"])
- ifTrue: [largeFrameBit]
- ifFalse: [0])!
Item was removed:
- ----- Method: CompiledMethod>>numArgs (in category 'accessing') -----
- numArgs
- "Answer the number of arguments the receiver takes."
-
- ^ (self header bitShift: -24) bitAnd: 16r0F!
Item was removed:
- ----- Method: CompiledMethod>>numLiterals (in category 'accessing') -----
- numLiterals
- "Answer the number of literals used by the receiver."
- ^self header bitAnd: 16r7FFF!
Item was removed:
- ----- Method: CompiledMethod>>numTemps (in category 'accessing') -----
- numTemps
- "Answer the number of temporary variables used by the receiver."
-
- ^ (self header bitShift: -18) bitAnd: 16r3F!
Item was removed:
- ----- Method: CompiledMethod>>objectAt: (in category 'literals') -----
- objectAt: index
- "Primitive. Answer the method header (if index=1) or a literal (if index
- >1) from the receiver. Essential. See Object documentation
- whatIsAPrimitive."
-
- <primitive: 68>
- self primitiveFailed!
Item was removed:
- ----- Method: CompiledMethod>>objectAt:put: (in category 'literals') -----
- objectAt: index put: value
- "Primitive. Store the value argument into a literal in the receiver. An
- index of 2 corresponds to the first literal. Fails if the index is less than 2
- or greater than the number of literals. Answer the value as the result.
- Normally only the compiler sends this message, because only the
- compiler stores values in CompiledMethods. Essential. See Object
- documentation whatIsAPrimitive."
-
- <primitive: 69>
- self primitiveFailed!
Item was removed:
- ----- Method: CompiledMethod>>outboundPointersDo: (in category 'tracing') -----
- outboundPointersDo: aBlock
-
- | numLiterals |
- aBlock value: self class.
- numLiterals := self numLiterals.
- 1 to: numLiterals do: [:i | aBlock value: (self literalAt: i)]!
Item was removed:
- ----- Method: CompiledMethod>>printOn: (in category 'printing') -----
- printOn: aStream
- "Overrides method inherited from the byte arrayed collection."
- aStream nextPut: $(.
- self printReferenceOn: aStream.
- aStream space; nextPut: $".
- self printNameOn: aStream.
- aStream nextPut: $(;
- print: self identityHash;
- nextPut: $);
- nextPut: $";
- nextPut: $)!
Item was removed:
- ----- Method: CompiledMethod>>protocol (in category 'accessing') -----
- protocol
- ^self methodClass ifNotNil:
- [:class|
- self selector ifNotNil:
- [:selector|
- class whichCategoryIncludesSelector: selector]]!
Item was removed:
- ----- Method: CompiledMethod>>readDataFrom:size: (in category 'file in/out') -----
- readDataFrom: aDataStream size: varsOnDisk
- "Fill in my fields. My header and number of literals are already installed. Must read both objects for the literals and bytes for the bytecodes."
-
- self error: 'Must use readMethod'.!
Item was removed:
- ----- Method: CompiledMethod>>reference (in category 'printing') -----
- reference
- ^ String streamContents: [ : stream | self printReferenceOn: stream ]!
Item was removed:
- ----- Method: CompiledMethod>>referredInstVars (in category 'accessing') -----
- referredInstVars
- "Answer a Set of the inst var names the receiver accesses."
- | allInstVarNames instVarNames |
- allInstVarNames := self methodClass allInstVarNames.
- self isReturnField ifTrue:
- [^Set with: (allInstVarNames at: self returnField + 1)].
- instVarNames := Set new.
- self abstractBytecodeMessagesDo:
- [:msg|
- (#(#popIntoReceiverVariable:
- #pushReceiverVariable:
- #storeIntoReceiverVariable:) includes: msg selector) ifTrue:
- [instVarNames add: (allInstVarNames at: msg argument + 1)]].
- ^instVarNames
-
- "Dictionary newFromPairs: (Point selectors collect: [:s| { s. (Point >> s) referredInstVars}])"!
Item was removed:
- ----- Method: CompiledMethod>>scanner (in category 'accessing') -----
- scanner
-
- ^ InstructionStream on: self!
Item was removed:
- ----- Method: CompiledMethod>>setSignFlag (in category 'accessing') -----
- setSignFlag
- "Set the sign flag bit. The sign flag bit may be
- used by the VM to select an alternate bytecode set."
-
- self signFlag ifFalse:
- [self objectAt: 1 put: self header + SmallInteger minVal]!
Item was removed:
- ----- Method: CompiledMethod>>signFlag (in category 'accessing') -----
- signFlag
- "Answer the sign flag bit. The sign flag bit may be
- used by the VM to select an alternate bytecode set."
-
- ^self header < 0!
Item was removed:
- ----- Method: CompiledMethod>>storeDataOn: (in category 'file in/out') -----
- storeDataOn: aDataStream
- "Store myself on a DataStream. I am a mixture of objects and raw data bytes. Only use this for blocks. Normal methodDictionaries should not be put out using ReferenceStreams. Their fileOut should be attached to the beginning of the file."
-
- | byteLength lits |
- "No inst vars of the normal type"
- byteLength := self basicSize.
- aDataStream
- beginInstance: self class
- size: byteLength.
- lits := self numLiterals + 1. "counting header"
- 1 to: lits do:
- [:ii | aDataStream nextPut: (self objectAt: ii)].
- lits*4+1 to: byteLength do:
- [:ii | aDataStream byteStream nextPut: (self basicAt: ii)].
- "write bytes straight through to the file"!
Item was removed:
- ----- Method: CompiledMethod>>storeOn: (in category 'printing') -----
- storeOn: aStream
- | noneYet |
- aStream nextPutAll: '(('.
- aStream nextPutAll: self class name.
- aStream nextPutAll: ' newMethod: '.
- aStream store: self size - self initialPC + 1.
- aStream nextPutAll: ' header: '.
- aStream store: self header.
- aStream nextPut: $).
- noneYet := self storeElementsFrom: self initialPC to: self endPC on: aStream.
- 1 to: self numLiterals do:
- [:index |
- noneYet
- ifTrue: [noneYet := false]
- ifFalse: [aStream nextPut: $;].
- aStream nextPutAll: ' literalAt: '.
- aStream store: index.
- aStream nextPutAll: ' put: '.
- aStream store: (self literalAt: index)].
- noneYet ifFalse: [aStream nextPutAll: '; yourself'].
- aStream nextPut: $)!
Item was removed:
- ----- Method: CompiledMethod>>trailer (in category 'accessing') -----
- trailer
- "Answer the receiver's trailer"
- ^ CompiledMethodTrailer new method: self
- !
Item was removed:
- ----- Method: CompiledMethod>>veryDeepCopyWith: (in category 'file in/out') -----
- veryDeepCopyWith: deepCopier
- "Return self. I am always shared. Do not record me. Only use this for blocks. Normally methodDictionaries should not be copied this way."!
Item was removed:
- ----- Method: CompiledMethod>>voidCogVMState (in category 'cleaning') -----
- voidCogVMState
- "Tell the VM to remove all references to any machine code form of the method.
- This primitive must be called whenever a method is in use and modified. This is
- more aggressive (and *much* more costly) than flushCache since it must search
- through all context objects, making sure that none have a (hidden) machine code pc
- in the receiver. Since modifying a method will likely change the generated machine code,
- modifying a method (rather than redefining it) requires this more aggressive flush."
-
- <primitive: 215>
- ^self flushCache!
Eliot Miranda uploaded a new version of KernelTests to project The Trunk:
http://source.squeak.org/trunk/KernelTests-eem.322.mcz
==================== Summary ====================
Name: KernelTests-eem.322
Author: eem
Time: 23 March 2017, 10:58:30.6781 am
UUID: b6798800-d9b8-4301-a3cd-396963409a59
Ancestors: KernelTests-eem.321
Eliominate tests for methods having the new property format. They have for several years now.
=============== Diff against KernelTests-eem.321 ===============
Item was removed:
- ----- Method: CompiledMethodTest>>testHasNewPropertyFormat (in category 'tests - testing') -----
- testHasNewPropertyFormat
- | method |
- method := (self class)>>#returnTrue.
- self assert: method hasNewPropertyFormat.
- !
Item was removed:
- ----- Method: MethodPropertiesTest>>testAllMethodsHaveNewPropertyFormat (in category 'testing') -----
- testAllMethodsHaveNewPropertyFormat
- Smalltalk garbageCollect.
- self assert: (CompiledMethod allInstances
- reject: [:cm | cm hasNewPropertyFormat]) isEmpty
- description: 'CompiledMethods must have new property format'!
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1068.mcz
==================== Summary ====================
Name: Kernel-eem.1068
Author: eem
Time: 23 March 2017, 10:12:09.692043 am
UUID: ee70e995-61c9-468a-8ff5-3238631c3710
Ancestors: Kernel-eem.1067
Add isCompiledCode to Object. Later we can eliminate isCompiledMethod from Object if desired and implement isCompiledBlock and isCompiledMethod only on CompiledCode and subclasses. In any case we need isCompiledCode in Object now more than we need isCompiledMethod. Apologies to all offended by is methods (but get over it ;-) ).
Implement isCompiledBlock in CompiledCode (for subclasses of CompiledCode, foo isCompiledMethod = foo isCompiledBlock not).
Move the relevant class methods up from CompiledMethod to CompiledCode. Redo the error messages in basicNew, new et al.
=============== Diff against Kernel-eem.1067 ===============
Item was added:
+ ----- Method: CompiledBlock>>isCompiledBlock (in category 'testing') -----
+ isCompiledBlock
+ ^true!
Item was added:
+ ----- Method: CompiledCode class>>basicNew (in category 'instance creation') -----
+ basicNew
+ ^self newMethodViaNewError!
Item was added:
+ ----- Method: CompiledCode class>>basicNew: (in category 'instance creation') -----
+ basicNew: size
+ ^self newMethodViaNewError!
Item was added:
+ ----- Method: CompiledCode class>>fullFrameSize (in category 'constants') -----
+ fullFrameSize "CompiledMethod fullFrameSize"
+ ^ LargeFrame!
Item was added:
+ ----- Method: CompiledCode class>>handleFailingFailingNewMethod:header: (in category 'private') -----
+ handleFailingFailingNewMethod: numberOfBytes header: headerWord
+ "This newMethod:header: gets sent after handleFailingBasicNew: has done a full
+ garbage collection and possibly grown memory. If this basicNew: fails then the
+ system really is low on space, so raise the OutOfMemory signal.
+
+ Primitive. Answer an instance of this class with the number of indexable variables
+ specified by the argument, headerWord, and the number of bytecodes specified
+ by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes
+ is negative, or if the receiver is not a CompiledMethod class, or if there is not enough
+ memory available. Essential. See Object documentation whatIsAPrimitive."
+
+ <primitive: 79>
+ "space must be low."
+ OutOfMemory signal.
+ "retry if user proceeds"
+ ^self newMethod: numberOfBytes header: headerWord!
Item was added:
+ ----- Method: CompiledCode class>>handleFailingNewMethod:header: (in category 'private') -----
+ handleFailingNewMethod: numberOfBytes header: headerWord
+ "This newMethod:header: gets sent after newMethod:header: has failed
+ and allowed a scavenging garbage collection to occur. The scavenging
+ collection will have happened as the VM is activating the (failing) basicNew:.
+ If handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient
+ space and a global garbage collection is required. Retry after garbage
+ collecting and growing memory if necessary.
+
+ Primitive. Answer an instance of this class with the number of indexable variables
+ specified by the argument, headerWord, and the number of bytecodes specified
+ by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes
+ is negative, or if the receiver is not a CompiledMethod class, or if there is not enough
+ memory available. Essential. See Object documentation whatIsAPrimitive."
+
+ <primitive: 79>
+ | bytesRequested |
+ bytesRequested := (headerWord bitAnd: 16rFFFF) + 1 * Smalltalk wordSize + numberOfBytes + 16.
+ Smalltalk garbageCollect < bytesRequested ifTrue:
+ [Smalltalk growMemoryByAtLeast: bytesRequested].
+ "retry after global garbage collect and possible grow"
+ ^self handleFailingFailingNewMethod: numberOfBytes header: headerWord!
Item was added:
+ ----- Method: CompiledCode class>>headerFlagForEncoder: (in category 'method encoding') -----
+ headerFlagForEncoder: anEncoder
+ anEncoder class == PrimaryBytecodeSetEncoderClass ifTrue:
+ [^0].
+ anEncoder class == SecondaryBytecodeSetEncoderClass ifTrue:
+ [^SmallInteger minVal].
+ self error: 'The encoder is not one of the two installed bytecode sets'!
Item was added:
+ ----- Method: CompiledCode class>>initialize (in category 'class initialization') -----
+ initialize "CompiledMethod initialize"
+ "Initialize class variables specifying the size of the temporary frame
+ needed to run instances of me."
+
+ SmallFrame := 16. "Context range for temps+stack"
+ LargeFrame := 56.
+ PrimaryBytecodeSetEncoderClass ifNil:
+ [PrimaryBytecodeSetEncoderClass := EncoderForV3PlusClosures].
+ SecondaryBytecodeSetEncoderClass ifNil:
+ [SecondaryBytecodeSetEncoderClass := EncoderForV3PlusClosures]!
Item was added:
+ ----- Method: CompiledCode class>>installPrimaryBytecodeSet: (in category 'class initialization') -----
+ installPrimaryBytecodeSet: aBytecodeEncoderSubclass
+ PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue:
+ [^self].
+ (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse:
+ [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder'].
+ (self allSubInstances
+ detect: [:m| m header >= 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]]
+ ifNone: []) ifNotNil:
+ [Warning signal: 'There are existing CompiledMethods with a different encoderClass.'].
+ PrimaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass!
Item was added:
+ ----- Method: CompiledCode class>>installSecondaryBytecodeSet: (in category 'class initialization') -----
+ installSecondaryBytecodeSet: aBytecodeEncoderSubclass
+ PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue:
+ [^self].
+ (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse:
+ [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder'].
+ (self allSubInstances
+ detect: [:m| m header < 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]]
+ ifNone: []) ifNotNil:
+ [Warning signal: 'There are existing CompiledMethods with a different encoderClass.'].
+ SecondaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass!
Item was added:
+ ----- Method: CompiledCode class>>maxNumLiterals (in category 'constants') -----
+ maxNumLiterals
+ "The current header format and the VM's interpretation of it allows for a maximum of 32767 literals."
+ ^32767!
Item was added:
+ ----- Method: CompiledCode class>>new (in category 'instance creation') -----
+ new
+ ^self newMethodViaNewError!
Item was added:
+ ----- Method: CompiledCode class>>new: (in category 'instance creation') -----
+ new: size
+ ^self newMethodViaNewError!
Item was added:
+ ----- Method: CompiledCode class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive: (in category 'instance creation') -----
+ newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex
+ "Answer an instance of me. The header is specified by the message
+ arguments. The remaining parts are not as yet determined."
+ | method pc |
+ nArgs > 15 ifTrue:
+ [^self error: 'Cannot compile -- too many arguments'].
+ nTemps > 63 ifTrue:
+ [^self error: 'Cannot compile -- too many temporary variables'].
+ nLits > 32767 ifTrue:
+ [^self error: 'Cannot compile -- too many literals'].
+
+ method := trailer
+ createMethod: numberOfBytes
+ class: self
+ header: (nArgs bitShift: 24)
+ + (nTemps bitShift: 18)
+ + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0])
+ + nLits
+ + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]).
+ primitiveIndex > 0 ifTrue:
+ [pc := method initialPC.
+ method
+ at: pc + 0 put: method encoderClass callPrimitiveCode;
+ at: pc + 1 put: (primitiveIndex bitAnd: 16rFF);
+ at: pc + 2 put: (primitiveIndex bitShift: -8)].
+ ^method!
Item was added:
+ ----- Method: CompiledCode class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive:flag: (in category 'instance creation') -----
+ newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex flag: flag
+ "Answer an instance of me. The header is specified by the message
+ arguments. The remaining parts are not as yet determined."
+ | method pc |
+ nArgs > 15 ifTrue:
+ [^self error: 'Cannot compile -- too many arguments'].
+ nTemps > 63 ifTrue:
+ [^self error: 'Cannot compile -- too many temporary variables'].
+ nLits > 32767 ifTrue:
+ [^self error: 'Cannot compile -- too many literals'].
+
+ method := trailer
+ createMethod: numberOfBytes
+ class: self
+ header: (nArgs bitShift: 24)
+ + (nTemps bitShift: 18)
+ + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0])
+ + nLits
+ + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0])
+ + (flag ifTrue: [1 bitShift: 29] ifFalse: [0]).
+ primitiveIndex > 0 ifTrue:
+ [pc := method initialPC.
+ method
+ at: pc + 0 put: method encoderClass callPrimitiveCode;
+ at: pc + 1 put: (primitiveIndex bitAnd: 16rFF);
+ at: pc + 2 put: (primitiveIndex bitShift: -8)].
+ ^method!
Item was added:
+ ----- Method: CompiledCode class>>newFrom: (in category 'instance creation') -----
+ newFrom: aCompiledMethod
+ "Clone the argument, aCompiledMethod"
+ | inst |
+ "CompiledMethod newFrom: CompiledMethod class >> #newFrom:"
+ inst := self newMethod: aCompiledMethod basicSize - aCompiledMethod initialPC + 1
+ header: aCompiledMethod header.
+ 1 to: aCompiledMethod numLiterals do:
+ [:index|
+ inst literalAt: index put: (aCompiledMethod literalAt: index)].
+ aCompiledMethod initialPC to: aCompiledMethod size do:
+ [:index |
+ inst at: index put: (aCompiledMethod at: index)].
+ inst postCopy.
+ ^inst!
Item was added:
+ ----- Method: CompiledCode class>>newInstanceFrom:variable:size:map: (in category 'instance creation') -----
+ newInstanceFrom: oldInstance variable: variable size: instSize map: map
+ "Create a new instance of the receiver based on the given old instance.
+ The supplied map contains a mapping of the old instVar names into
+ the receiver's instVars"
+ | new |
+ new := self newFrom: oldInstance.
+ 1 to: instSize do:
+ [:offset | (map at: offset) > 0 ifTrue:
+ [new instVarAt: offset
+ put: (oldInstance instVarAt: (map at: offset))]].
+ ^new!
Item was added:
+ ----- Method: CompiledCode class>>newMethod:header: (in category 'instance creation') -----
+ newMethod: numberOfBytes header: headerWord
+ "Primitive. Answer an instance of me. The number of literals (and other
+ information) is specified by the headerWord (see my class comment).
+ The first argument specifies the number of fields for bytecodes in the
+ method. Fail if either argument is not a SmallInteger, or if numberOfBytes
+ is negative, or if memory is low. Once the header of a method is set by
+ this primitive, it cannot be changed to change the number of literals.
+ Essential. See Object documentation whatIsAPrimitive."
+
+ <primitive: 79 error: ec>
+ ec == #'insufficient object memory' ifTrue:
+ [^self handleFailingNewMethod: numberOfBytes header: headerWord].
+ ^self primitiveFailed!
Item was added:
+ ----- Method: CompiledCode class>>newMethodViaNewError (in category 'private') -----
+ newMethodViaNewError
+
+ ^self error: self class name, 's may only be created with newMethod:header:'!
Item was added:
+ ----- Method: CompiledCode class>>smallFrameSize (in category 'constants') -----
+ smallFrameSize
+
+ ^ SmallFrame!
Item was added:
+ ----- Method: CompiledCode>>isCompiledBlock (in category 'testing') -----
+ isCompiledBlock
+ ^false!
Item was added:
+ ----- Method: CompiledCode>>isCompiledCode (in category 'testing') -----
+ isCompiledCode
+ ^true!
Item was added:
+ ----- Method: CompiledCode>>isCompiledMethod (in category 'testing') -----
+ isCompiledMethod
+ ^false!
Item was removed:
- ----- Method: CompiledMethod class>>basicNew (in category 'instance creation') -----
- basicNew
-
- self error: 'CompiledMethods may only be created with newMethod:header:' !
Item was removed:
- ----- Method: CompiledMethod class>>basicNew: (in category 'instance creation') -----
- basicNew: size
-
- self error: 'CompiledMethods may only be created with newMethod:header:' !
Item was removed:
- ----- Method: CompiledMethod class>>fullFrameSize (in category 'constants') -----
- fullFrameSize "CompiledMethod fullFrameSize"
- ^ LargeFrame!
Item was removed:
- ----- Method: CompiledMethod class>>handleFailingFailingNewMethod:header: (in category 'private') -----
- handleFailingFailingNewMethod: numberOfBytes header: headerWord
- "This newMethod:header: gets sent after handleFailingBasicNew: has done a full
- garbage collection and possibly grown memory. If this basicNew: fails then the
- system really is low on space, so raise the OutOfMemory signal.
-
- Primitive. Answer an instance of this class with the number of indexable variables
- specified by the argument, headerWord, and the number of bytecodes specified
- by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes
- is negative, or if the receiver is not a CompiledMethod class, or if there is not enough
- memory available. Essential. See Object documentation whatIsAPrimitive."
-
- <primitive: 79>
- "space must be low."
- OutOfMemory signal.
- "retry if user proceeds"
- ^self newMethod: numberOfBytes header: headerWord!
Item was removed:
- ----- Method: CompiledMethod class>>handleFailingNewMethod:header: (in category 'private') -----
- handleFailingNewMethod: numberOfBytes header: headerWord
- "This newMethod:header: gets sent after newMethod:header: has failed
- and allowed a scavenging garbage collection to occur. The scavenging
- collection will have happened as the VM is activating the (failing) basicNew:.
- If handleFailingBasicNew: fails then the scavenge failed to reclaim sufficient
- space and a global garbage collection is required. Retry after garbage
- collecting and growing memory if necessary.
-
- Primitive. Answer an instance of this class with the number of indexable variables
- specified by the argument, headerWord, and the number of bytecodes specified
- by numberOfBytes. Fail if this if the arguments are not Integers, or if numberOfBytes
- is negative, or if the receiver is not a CompiledMethod class, or if there is not enough
- memory available. Essential. See Object documentation whatIsAPrimitive."
-
- <primitive: 79>
- | bytesRequested |
- bytesRequested := (headerWord bitAnd: 16rFFFF) + 1 * Smalltalk wordSize + numberOfBytes + 16.
- Smalltalk garbageCollect < bytesRequested ifTrue:
- [Smalltalk growMemoryByAtLeast: bytesRequested].
- "retry after global garbage collect and possible grow"
- ^self handleFailingFailingNewMethod: numberOfBytes header: headerWord!
Item was removed:
- ----- Method: CompiledMethod class>>headerFlagForEncoder: (in category 'method encoding') -----
- headerFlagForEncoder: anEncoder
- anEncoder class == PrimaryBytecodeSetEncoderClass ifTrue:
- [^0].
- anEncoder class == SecondaryBytecodeSetEncoderClass ifTrue:
- [^SmallInteger minVal].
- self error: 'The encoder is not one of the two installed bytecode sets'!
Item was removed:
- ----- Method: CompiledMethod class>>initialize (in category 'class initialization') -----
- initialize "CompiledMethod initialize"
- "Initialize class variables specifying the size of the temporary frame
- needed to run instances of me."
-
- SmallFrame := 16. "Context range for temps+stack"
- LargeFrame := 56.
- PrimaryBytecodeSetEncoderClass ifNil:
- [PrimaryBytecodeSetEncoderClass := EncoderForV3PlusClosures].
- SecondaryBytecodeSetEncoderClass ifNil:
- [SecondaryBytecodeSetEncoderClass := EncoderForV3PlusClosures]!
Item was removed:
- ----- Method: CompiledMethod class>>installPrimaryBytecodeSet: (in category 'class initialization') -----
- installPrimaryBytecodeSet: aBytecodeEncoderSubclass
- PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue:
- [^self].
- (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse:
- [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder'].
- (self allSubInstances
- detect: [:m| m header >= 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]]
- ifNone: []) ifNotNil:
- [Warning signal: 'There are existing CompiledMethods with a different encoderClass.'].
- PrimaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass!
Item was removed:
- ----- Method: CompiledMethod class>>installSecondaryBytecodeSet: (in category 'class initialization') -----
- installSecondaryBytecodeSet: aBytecodeEncoderSubclass
- PrimaryBytecodeSetEncoderClass == aBytecodeEncoderSubclass ifTrue:
- [^self].
- (aBytecodeEncoderSubclass inheritsFrom: BytecodeEncoder) ifFalse:
- [self error: 'A bytecode set encoder is expected to be a subclass of BytecodeEncoder'].
- (self allSubInstances
- detect: [:m| m header < 0 and: [m encoderClass ~~ aBytecodeEncoderSubclass]]
- ifNone: []) ifNotNil:
- [Warning signal: 'There are existing CompiledMethods with a different encoderClass.'].
- SecondaryBytecodeSetEncoderClass := aBytecodeEncoderSubclass!
Item was removed:
- ----- Method: CompiledMethod class>>maxNumLiterals (in category 'constants') -----
- maxNumLiterals
- "The current header format and the VM's interpretation of it allows for a maximum of 32767 literals."
- ^32767!
Item was removed:
- ----- Method: CompiledMethod class>>new (in category 'instance creation') -----
- new
- "This will not make a meaningful method, but it could be used
- to invoke some otherwise useful method in this class."
- ^self newMethod: 2 header: 1024!
Item was removed:
- ----- Method: CompiledMethod class>>new: (in category 'instance creation') -----
- new: size
-
- self error: 'CompiledMethods may only be created with newMethod:header:'!
Item was removed:
- ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive: (in category 'instance creation') -----
- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex
- "Answer an instance of me. The header is specified by the message
- arguments. The remaining parts are not as yet determined."
- | method pc |
- nArgs > 15 ifTrue:
- [^self error: 'Cannot compile -- too many arguments'].
- nTemps > 63 ifTrue:
- [^self error: 'Cannot compile -- too many temporary variables'].
- nLits > 32767 ifTrue:
- [^self error: 'Cannot compile -- too many literals'].
-
- method := trailer
- createMethod: numberOfBytes
- class: self
- header: (nArgs bitShift: 24)
- + (nTemps bitShift: 18)
- + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0])
- + nLits
- + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0]).
- primitiveIndex > 0 ifTrue:
- [pc := method initialPC.
- method
- at: pc + 0 put: method encoderClass callPrimitiveCode;
- at: pc + 1 put: (primitiveIndex bitAnd: 16rFF);
- at: pc + 2 put: (primitiveIndex bitShift: -8)].
- ^method!
Item was removed:
- ----- Method: CompiledMethod class>>newBytes:trailerBytes:nArgs:nTemps:nStack:nLits:primitive:flag: (in category 'instance creation') -----
- newBytes: numberOfBytes trailerBytes: trailer nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex flag: flag
- "Answer an instance of me. The header is specified by the message
- arguments. The remaining parts are not as yet determined."
- | method pc |
- nArgs > 15 ifTrue:
- [^self error: 'Cannot compile -- too many arguments'].
- nTemps > 63 ifTrue:
- [^self error: 'Cannot compile -- too many temporary variables'].
- nLits > 32767 ifTrue:
- [^self error: 'Cannot compile -- too many literals'].
-
- method := trailer
- createMethod: numberOfBytes
- class: self
- header: (nArgs bitShift: 24)
- + (nTemps bitShift: 18)
- + ((nTemps + stackSize) > SmallFrame ifTrue: [1 bitShift: 17] ifFalse: [0])
- + nLits
- + (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0])
- + (flag ifTrue: [1 bitShift: 29] ifFalse: [0]).
- primitiveIndex > 0 ifTrue:
- [pc := method initialPC.
- method
- at: pc + 0 put: method encoderClass callPrimitiveCode;
- at: pc + 1 put: (primitiveIndex bitAnd: 16rFF);
- at: pc + 2 put: (primitiveIndex bitShift: -8)].
- ^method!
Item was removed:
- ----- Method: CompiledMethod class>>newFrom: (in category 'instance creation') -----
- newFrom: aCompiledMethod
- "Clone the argument, aCompiledMethod"
- | inst |
- "CompiledMethod newFrom: CompiledMethod class >> #newFrom:"
- inst := self newMethod: aCompiledMethod basicSize - aCompiledMethod initialPC + 1
- header: aCompiledMethod header.
- 1 to: aCompiledMethod numLiterals do:
- [:index|
- inst literalAt: index put: (aCompiledMethod literalAt: index)].
- aCompiledMethod initialPC to: aCompiledMethod size do:
- [:index |
- inst at: index put: (aCompiledMethod at: index)].
- inst postCopy.
- ^inst!
Item was removed:
- ----- Method: CompiledMethod class>>newInstanceFrom:variable:size:map: (in category 'instance creation') -----
- newInstanceFrom: oldInstance variable: variable size: instSize map: map
- "Create a new instance of the receiver based on the given old instance.
- The supplied map contains a mapping of the old instVar names into
- the receiver's instVars"
- | new |
- new := self newFrom: oldInstance.
- 1 to: instSize do:
- [:offset | (map at: offset) > 0 ifTrue:
- [new instVarAt: offset
- put: (oldInstance instVarAt: (map at: offset))]].
- ^new!
Item was removed:
- ----- Method: CompiledMethod class>>newMethod:header: (in category 'instance creation') -----
- newMethod: numberOfBytes header: headerWord
- "Primitive. Answer an instance of me. The number of literals (and other
- information) is specified by the headerWord (see my class comment).
- The first argument specifies the number of fields for bytecodes in the
- method. Fail if either argument is not a SmallInteger, or if numberOfBytes
- is negative, or if memory is low. Once the header of a method is set by
- this primitive, it cannot be changed to change the number of literals.
- Essential. See Object documentation whatIsAPrimitive."
-
- <primitive: 79 error: ec>
- ec == #'insufficient object memory' ifTrue:
- [^self handleFailingNewMethod: numberOfBytes header: headerWord].
- ^self primitiveFailed!
Item was removed:
- ----- Method: CompiledMethod class>>smallFrameSize (in category 'constants') -----
- smallFrameSize
-
- ^ SmallFrame!
Item was added:
+ ----- Method: Object>>isCompiledCode (in category 'testing') -----
+ isCompiledCode
+ ^false!
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1067.mcz
==================== Summary ====================
Name: Kernel-eem.1067
Author: eem
Time: 22 March 2017, 1:20:50.066536 pm
UUID: 0073e975-c0c9-4923-9702-88e51890ae33
Ancestors: Kernel-eem.1066
Add CompiledCode and CompiledBlock to the package explciitly, now that the script has created them. Provide the class comments.
=============== Diff against Kernel-eem.1066 ===============
Item was added:
+ CompiledCode variableByteSubclass: #CompiledBlock
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Kernel-Methods'!
+
+ !CompiledBlock commentStamp: 'eem 3/22/2017 12:10' prior: 0!
+ CompiledBlock instances are blocks suitable for interpretation by the virtual machine. They are a specialization oif CompiledCode. This requires both bytecode set and compiler support. The V3 bytecode (EncoderForV3PlusClosures) does not provide support for CompiledBlock. The SistaV1 set does (EncoderForSistaV1).
+
+ The last literal in a CompiledBlock is reserved for a reference to its enclosing CompiledBlock or CompiledMethod. Super sends in CompiledBlocks must use the directed super send bytecode.
+
+ By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState may be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledBlock that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledBlock subclass to answer the specialized subclass of AdditionalMethodState. Enterprising programmers are encouraged to try and implement this support automatically through suitable modifications to the compiler and class builder.!
Item was added:
+ ByteArray variableByteSubclass: #CompiledCode
+ instanceVariableNames: ''
+ classVariableNames: 'LargeFrame PrimaryBytecodeSetEncoderClass SecondaryBytecodeSetEncoderClass SmallFrame'
+ poolDictionaries: ''
+ category: 'Kernel-Methods'!
+
+ !CompiledCode commentStamp: 'eem 3/22/2017 12:14' prior: 0!
+ CompiledCode instances are methods suitable for execution by the virtual machine. Instances of CompiledCode and its subclasses are the only objects in the system that have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledCode object is pointers, the second part is bytes. CompiledCode inherits from ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledCode is-a ByteArray.
+
+ Instance variables: *indexed* (no named inst vars)
+
+ Class variables:
+ SmallFrame - the number of stack slots in a small frame Context
+ LargeFrame - the number of stack slots in a large frame Context
+ PrimaryBytecodeSetEncoderClass - the encoder class that defines the primary instruction set
+ SecondaryBytecodeSetEncoderClass - the encoder class that defines the secondary instruction set
+
+ The current format of a CompiledCode object is as follows:
+
+ header (4 or 8 bytes, SmallInteger)
+ literals (4 or 8 bytes each, Object, see "The last literal..." below)
+ bytecodes (variable, bytes)
+ trailer (variable, bytes)
+
+ The header is a SmallInteger (which in the 32-bit system has 31 bits, and in the 64-bit system, 61 bits) in the following format:
+
+ (index 0) 15 bits: number of literals (#numLiterals)
+ (index 15) 1 bit: is optimized - reserved for methods that have been optimized by Sista
+ (index 16) 1 bit: has primitive
+ (index 17) 1 bit: whether a large frame size is needed (#frameSize => either SmallFrame or LargeFrame)
+ (index 18) 6 bits: number of temporary variables (#numTemps)
+ (index 24) 4 bits: number of arguments to the method (#numArgs)
+ (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public), although accessors for bit 29 exist (see #flag).
+ sign bit: 1 bit: selects the instruction set, >= 0 Primary, < 0 Secondary (#signFlag)
+
+ If the method has a primitive then the first bytecode of the method must be a callPrimitive: bytecode that encodes the primitive index. This bytecode can encode a primitive index from 0 to 65535.
+
+ The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer.
+
+ While there are disadvantages to this "flat" representation (it is impossible to add named instance variables to CompiledCode or its subclasses, but it is possible indirectly; see AdditionalMethodState) it is effective for interpreters. It means that both bytecodes and literals can be fetched directly from a single method object, and that only one object, the method, must be saved and restored on activation and return. A more natural representation, in which there are searate instance variables for the bytecode, and (conveniently) the literals, requires either much more work on activation and return setting up references to the literals and bytecodes, or slower access to bytecodes and literals, indirecting on each access.
+
+ The last literal of a CompiledCode object is reserved for special use by the kernel and/or the virtual machine. In CompiledMethod instances it must either be the methodClassAssociation, used to implement super sends, or nil, if the method is anonymous. In CompiledBlock it is to be used for a reference to the enclosing method or block object.
+
+ By convention, the penultimate literal is reserved for special use by the kernel. CompiledMethod instances it must either be the method selector, or an instance of AdditionalMethodState which holds the selector and any pragmas or properties in the method. In CompiledBlock it is reserved for use for an AdditionalMethodState.
+
+ Note that super sends in CompiledBlock instances do not use a methodClass association, but expect a directed supersend bytecode, in which the method class (the subclass of the class in which to start the lookup) is a literal. Logically when we switch to a bytecode set that supports the directed super send bytecode, and discard the old super send bytecodes, we can use the last literal to store the selector or the enclosing method/block or an AdditionalMethodState, and the AdditionalMethodState can hold the selector and/or the enclosing method/block.!
Item was changed:
+ CompiledCode variableByteSubclass: #CompiledMethod
- ByteArray variableByteSubclass: #CompiledMethod
instanceVariableNames: ''
+ classVariableNames: ''
- classVariableNames: 'LargeFrame PrimaryBytecodeSetEncoderClass SecondaryBytecodeSetEncoderClass SmallFrame'
poolDictionaries: ''
category: 'Kernel-Methods'!
+ !CompiledMethod commentStamp: 'eem 3/22/2017 13:17' prior: 0!
+ CompiledMethod instances are methods suitable for interpretation by the virtual machine. They are a specialization of CompiledCode. They represent methods, and may also, depending on the bytecode set, include nested blocks. Bytecode sets that support non-nested blocks with use CompiledBlock instances to implement nested block methods, that are separate from their enclosing method. This requires compiler support.
- !CompiledMethod commentStamp: 'eem 1/22/2015 15:47' prior: 0!
- CompiledMethod instances are methods suitable for interpretation by the virtual machine. Instances of CompiledMethod and its subclasses are the only objects in the system that have both indexable pointer fields and indexable 8-bit integer fields. The first part of a CompiledMethod is pointers, the second part is bytes. CompiledMethod inherits from ByteArray to avoid duplicating some of ByteArray's methods, not because a CompiledMethod is-a ByteArray.
+ The last literal in a CompiledMethod must be its methodClassAssociation, a binding whose value is the class the method is installed in. The methodClassAssociation is used to implement super sends. If a method contains no super send then its methodClassAssociation may be nil (as would be the case for example of methods providing a pool of inst var accessors).
- Class variables:
- SmallFrame - the number of stack slots in a small frame Context
- LargeFrame - the number of stack slots in a large frame Context
- PrimaryBytecodeSetEncoderClass - the encoder class that defines the primary instruction set
- SecondaryBytecodeSetEncoderClass - the encoder class that defines the secondary instruction set
+ By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState holds the method's selector and any pragmas and properties of the method. AdditionalMethodState may also be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledMethod that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledMethod subclass to answer the specialized subclass of AdditionalMethodState. Enterprising programmers are encouraged to try and implement this support automatically through suitable modifications to the compiler and class builder.!
- The current format of a CompiledMethod is as follows:
-
- header (4 or 8 bytes, SmallInteger)
- literals (4 or 8 bytes each, Object, see "The last literal..." below)
- bytecodes (variable, bytes)
- trailer (variable, bytes)
-
- The header is a SmallInteger (which in the 32-bit system has 31 bits, and in the 64-bit system, 61 bits) in the following format:
-
- (index 0) 15 bits: number of literals (#numLiterals)
- (index 15) 1 bit: is optimized - reserved for methods that have been optimized by Sista
- (index 16) 1 bit: has primitive
- (index 17) 1 bit: whether a large frame size is needed (#frameSize => either SmallFrame or LargeFrame)
- (index 18) 6 bits: number of temporary variables (#numTemps)
- (index 24) 4 bits: number of arguments to the method (#numArgs)
- (index 28) 2 bits: reserved for an access modifier (00-unused, 01-private, 10-protected, 11-public), although accessors for bit 29 exist (see #flag).
- sign bit: 1 bit: selects the instruction set, >= 0 Primary, < 0 Secondary (#signFlag)
-
- If the method has a primitive then the first bytecode of the method must be a callPrimitive: bytecode that encodes the primitive index.
-
- The trailer is an encoding of an instance of CompiledMethodTrailer. It is typically used to encode the index into the source files array of the method's source, but may be used to encode other values, e.g. tempNames, source as a string, etc. See the class CompiledMethodTrailer.
-
- The last literal in a CompiledMethod must be its methodClassAssociation, a binding whose value is the class the method is installed in. The methodClassAssociation is used to implement super sends. If a method contains no super send then its methodClassAssociation may be nil (as would be the case for example of methods providing a pool of inst var accessors). By convention the penultimate literal of a method is either its selector or an instance of AdditionalMethodState. AdditionalMethodState holds any pragmas and properties of a method, but may also be used to add instance variables to a method, albeit ones held in the method's AdditionalMethodState. Subclasses of CompiledMethod that want to add state should subclass AdditionalMethodState to add the state they want, and implement methodPropertiesClass on the class side of the CompiledMethod subclass to answer the specialized subclass of AdditionalMethodState.!
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1066.mcz
==================== Summary ====================
Name: Kernel-eem.1066
Author: eem
Time: 22 March 2017, 11:44:28.351522 am
UUID: 90c23fd4-0e78-4f36-87a2-6dd74f6a284f
Ancestors: Kernel-eem.1065
Invoke the script to install CompiledCode and CompiledBlock
=============== Diff against Kernel-eem.1065 ===============
Item was added:
+ (PackageInfo named: 'Kernel') preamble: 'CompiledMethod addCompiledCodeAndCompiledBlock'!