Eliot Miranda uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-eem.286.mcz
==================== Summary ====================
Name: Compiler-eem.286
Author: eem
Time: 5 August 2014, 9:44:57.105 pm
UUID: 34f9ea24-6e5a-4bb3-9e9f-0f59fb8c93cf
Ancestors: Compiler-eem.285
Provide the selector scanning support InstructionStream
needs to make selectorToSendOrSelf multiple bytecode set
capable.
Provide the method generators so that methods can be
generated with the two different header formats.
Provide a class comment for SpecialSelectorNode.
=============== Diff against Compiler-eem.285 ===============
Item was added:
+ ----- Method: BytecodeEncoder class>>selectorToSendOrItselfFor:in:at: (in category 'instruction stream support') -----
+ selectorToSendOrItselfFor: anInstructionStream in: method at: pc
+ "If anInstructionStream is at a send bytecode then answer the send's selector,
+ otherwise answer anInstructionStream itself. The rationale for answering
+ anInstructionStream instead of, say, nil, is that potentially any existing object
+ can be used as a selector, but since anInstructionStream postdates the method,
+ it can't be one of them."
+
+ self subclassResponsibility!
Item was added:
+ ----- Method: BytecodeEncoder>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') -----
+ computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex
+ "Compute the compiled method header that encodes the arguments
+ in the receiver's header format (see CompiledMehtod's class comment)."
+ self subclassResponsibility!
Item was added:
+ ----- Method: BytecodeEncoder>>generateMethodOfClass:trailer:from: (in category 'method generation') -----
+ generateMethodOfClass: aCompiledMethodClass trailer: trailer from: methodNode
+ "methodNode is the root of a parse tree. Answer an instance of aCompiledMethodClass
+ in the receiver's bytecode set and using the receiver's method header format.
+ The argument, trailer, is arbitrary but is typically either the reference to the source code
+ that is stored with every CompiledMethod, or an encoding of the method's temporary names."
+
+ self subclassResponsibility!
Item was added:
+ ----- Method: EncoderForV3 class>>selectorToSendOrItselfFor:in:at: (in category 'instruction stream support') -----
+ selectorToSendOrItselfFor: anInstructionStream in: method at: pc
+ "If anInstructionStream is at a send bytecode then answer the send's selector,
+ otherwise answer anInstructionStream itself. The rationale for answering
+ anInstructionStream instead of, say, nil, is that potentially any existing object
+ can be used as a selector, but since anInstructionStream postdates the method,
+ it can't be one of them."
+
+ | byte byte2 |
+ byte := method at: pc.
+ byte < 131 ifTrue: [^anInstructionStream].
+ byte >= 176
+ ifTrue:
+ ["special byte or short send"
+ byte >= 208
+ ifTrue: [^method literalAt: (byte bitAnd: 15) + 1]
+ ifFalse: [^Smalltalk specialSelectorAt: byte - 176 + 1]]
+ ifFalse:
+ [byte <= 134 ifTrue:
+ [byte2 := method at: pc + 1.
+ byte = 131 ifTrue: [^method literalAt: byte2 \\ 32 + 1].
+ byte = 132 ifTrue: [byte2 < 64 ifTrue: [^method literalAt: (method at: pc + 2) + 1]].
+ byte = 133 ifTrue: [^method literalAt: byte2 \\ 32 + 1].
+ byte = 134 ifTrue: [^method literalAt: byte2 \\ 64 + 1]]].
+ ^anInstructionStream!
Item was added:
+ ----- Method: EncoderForV3>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') -----
+ computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex
+ | primBits |
+ numTemps > 63 ifTrue:
+ [^self error: 'Cannot compile -- too many temporary variables'].
+ numLits > 255 ifTrue:
+ [^self error: 'Cannot compile -- too many literals'].
+ primBits := primitiveIndex <= 16r1FF
+ ifTrue: [primitiveIndex]
+ ifFalse: "For now the high bit of primitive no. is in the 29th bit of header"
+ [primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large'].
+ (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)].
+ ^(numArgs bitShift: 24)
+ + (numTemps bitShift: 18)
+ "+ (largeBit bitShift: 17)" "largeBit gets filled in later"
+ + (numLits bitShift: 9)
+ + primBits!
Item was added:
+ ----- Method: EncoderForV3>>generateMethodOfClass:trailer:from: (in category 'method generation') -----
+ generateMethodOfClass: aCompiledMethodClass trailer: trailer from: methodNode
+ "The receiver is the root of a parse tree. Answer an instance of aCompiledMethodClass.
+ The argument, trailer, is arbitrary but is typically either the reference to the source code
+ that is stored with every CompiledMethod, or an encoding of the method's temporary names."
+
+ | primErrNode blkSize nLits literals header method stack |
+ primErrNode := methodNode primitiveErrorVariableName ifNotNil:
+ [self fixTemp: methodNode primitiveErrorVariableName].
+ blkSize := (methodNode block sizeCodeForEvaluatedValue: self)
+ + (primErrNode
+ ifNil: [0]
+ ifNotNil: [primErrNode sizeCodeForStore: self "The VM relies on storeIntoTemp: (129)"]).
+ header := self computeMethodHeaderForNumArgs: methodNode arguments size
+ numTemps: self maxTemp
+ numLits: (nLits := (literals := self allLiterals) size)
+ primitive: methodNode primitive.
+ method := trailer
+ createMethod: blkSize
+ class: aCompiledMethodClass
+ header: header.
+ 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
+ self streamToMethod: method.
+ stack := ParseStack new init.
+ primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: self].
+ stack position: method numTemps.
+ [methodNode block emitCodeForEvaluatedValue: stack encoder: self]
+ on: Error "If an attempt is made to write too much code the method will be asked"
+ do: [:ex| "to grow, and the grow attempt will fail in CompiledMethod class>>#new:"
+ ex signalerContext sender method = (CompiledMethod class>>#new:)
+ ifTrue: [^self error: 'Compiler code size discrepancy']
+ ifFalse: [ex pass]].
+ stack position ~= (method numTemps + 1) ifTrue:
+ [^self error: 'Compiler stack discrepancy'].
+ self methodStreamPosition ~= (method size - trailer size) ifTrue:
+ [^self error: 'Compiler code size discrepancy'].
+ method needsFrameSize: stack size - method numTemps.
+ ^method!
Item was added:
+ ----- Method: EncoderForV3PlusClosures>>generateMethodOfClass:trailer:from: (in category 'method generation') -----
+ generateMethodOfClass: aCompiledMethodClass trailer: trailer from: methodNode
+ "The receiver is the root of a parse tree. Answer an instance of aCompiledMethodClass.
+ The argument, trailer, is arbitrary but is typically either the reference to the source code
+ that is stored with every CompiledMethod, or an encoding of the method's temporary names."
+
+ | primErrNode blkSize nLits locals literals header method stack |
+ primErrNode := methodNode primitiveErrorVariableName ifNotNil:
+ [self fixTemp: methodNode primitiveErrorVariableName].
+ methodNode ensureClosureAnalysisDone.
+ self rootNode: methodNode. "this is for BlockNode>>sizeCodeForClosureValue:"
+ blkSize := (methodNode block sizeCodeForEvaluatedValue: self)
+ + (primErrNode
+ ifNil: [0]
+ ifNotNil:
+ [primErrNode
+ index: methodNode arguments size + methodNode temporaries size;
+ sizeCodeForStore: self "The VM relies on storeIntoTemp: (129)"]).
+ locals := methodNode arguments, methodNode temporaries, (primErrNode ifNil: [#()] ifNotNil: [{primErrNode}]).
+ self noteBlockExtent: methodNode block blockExtent hasLocals: locals.
+ header := self computeMethodHeaderForNumArgs: methodNode arguments size
+ numTemps: locals size
+ numLits: (nLits := (literals := self allLiterals) size)
+ primitive: methodNode primitive.
+ method := trailer
+ createMethod: blkSize
+ class: aCompiledMethodClass
+ header: header.
+ 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
+ self streamToMethod: method.
+ stack := ParseStack new init.
+ primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: self].
+ stack position: method numTemps.
+ [methodNode block emitCodeForEvaluatedValue: stack encoder: self]
+ on: Error "If an attempt is made to write too much code the method will be asked"
+ do: [:ex| "to grow, and the grow attempt will fail in CompiledMethod class>>#new:"
+ ex signalerContext sender method = (CompiledMethod class>>#new:)
+ ifTrue: [^self error: 'Compiler code size discrepancy']
+ ifFalse: [ex pass]].
+ stack position ~= (method numTemps + 1) ifTrue:
+ [^self error: 'Compiler stack discrepancy'].
+ self methodStreamPosition ~= (method size - trailer size) ifTrue:
+ [^self error: 'Compiler code size discrepancy'].
+ method needsFrameSize: stack size - method numTemps.
+ ^method!
Item was changed:
SelectorNode subclass: #SpecialSelectorNode
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Compiler-ParseNodes'!
+
+ !SpecialSelectorNode commentStamp: 'eem 8/5/2014 20:18' prior: 0!
+ A SpecialSelectorNode is a subclass of SelectorNode that handles the special selectors, a high static and/or dynamic frequency set of selectors that are assigned their own bytecodes. Special selectors both save space in the literal frame and allow an interpreter to implement these sends directly for certain classes of receiver and argument, for example the SmallIntegers, a technique known as static receiver prediction.!
Eliot Miranda uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-eem.286.mcz
==================== Summary ====================
Name: Compiler-eem.286
Author: eem
Time: 5 August 2014, 9:44:57.105 pm
UUID: 34f9ea24-6e5a-4bb3-9e9f-0f59fb8c93cf
Ancestors: Compiler-eem.285
Provide the selector scanning support InstructionStream
needs to make selectorToSendOrSelf multiple bytecode set
capable.
Provide the method generators so that methods can be
generated with the two different header formats.
Provide a class comment for SpecialSelectorNode.
=============== Diff against Compiler-eem.285 ===============
Item was added:
+ ----- Method: BytecodeEncoder class>>selectorToSendOrItselfFor:in:at: (in category 'instruction stream support') -----
+ selectorToSendOrItselfFor: anInstructionStream in: method at: pc
+ "If anInstructionStream is at a send bytecode then answer the send's selector,
+ otherwise answer anInstructionStream itself. The rationale for answering
+ anInstructionStream instead of, say, nil, is that potentially any existing object
+ can be used as a selector, but since anInstructionStream postdates the method,
+ it can't be one of them."
+
+ self subclassResponsibility!
Item was added:
+ ----- Method: BytecodeEncoder>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') -----
+ computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex
+ "Compute the compiled method header that encodes the arguments
+ in the receiver's header format (see CompiledMehtod's class comment)."
+ self subclassResponsibility!
Item was added:
+ ----- Method: BytecodeEncoder>>generateMethodOfClass:trailer:from: (in category 'method generation') -----
+ generateMethodOfClass: aCompiledMethodClass trailer: trailer from: methodNode
+ "methodNode is the root of a parse tree. Answer an instance of aCompiledMethodClass
+ in the receiver's bytecode set and using the receiver's method header format.
+ The argument, trailer, is arbitrary but is typically either the reference to the source code
+ that is stored with every CompiledMethod, or an encoding of the method's temporary names."
+
+ self subclassResponsibility!
Item was added:
+ ----- Method: EncoderForV3 class>>selectorToSendOrItselfFor:in:at: (in category 'instruction stream support') -----
+ selectorToSendOrItselfFor: anInstructionStream in: method at: pc
+ "If anInstructionStream is at a send bytecode then answer the send's selector,
+ otherwise answer anInstructionStream itself. The rationale for answering
+ anInstructionStream instead of, say, nil, is that potentially any existing object
+ can be used as a selector, but since anInstructionStream postdates the method,
+ it can't be one of them."
+
+ | byte byte2 |
+ byte := method at: pc.
+ byte < 131 ifTrue: [^anInstructionStream].
+ byte >= 176
+ ifTrue:
+ ["special byte or short send"
+ byte >= 208
+ ifTrue: [^method literalAt: (byte bitAnd: 15) + 1]
+ ifFalse: [^Smalltalk specialSelectorAt: byte - 176 + 1]]
+ ifFalse:
+ [byte <= 134 ifTrue:
+ [byte2 := method at: pc + 1.
+ byte = 131 ifTrue: [^method literalAt: byte2 \\ 32 + 1].
+ byte = 132 ifTrue: [byte2 < 64 ifTrue: [^method literalAt: (method at: pc + 2) + 1]].
+ byte = 133 ifTrue: [^method literalAt: byte2 \\ 32 + 1].
+ byte = 134 ifTrue: [^method literalAt: byte2 \\ 64 + 1]]].
+ ^anInstructionStream!
Item was added:
+ ----- Method: EncoderForV3>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') -----
+ computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex
+ | primBits |
+ numTemps > 63 ifTrue:
+ [^self error: 'Cannot compile -- too many temporary variables'].
+ numLits > 255 ifTrue:
+ [^self error: 'Cannot compile -- too many literals'].
+ primBits := primitiveIndex <= 16r1FF
+ ifTrue: [primitiveIndex]
+ ifFalse: "For now the high bit of primitive no. is in the 29th bit of header"
+ [primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large'].
+ (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)].
+ ^(numArgs bitShift: 24)
+ + (numTemps bitShift: 18)
+ "+ (largeBit bitShift: 17)" "largeBit gets filled in later"
+ + (numLits bitShift: 9)
+ + primBits!
Item was added:
+ ----- Method: EncoderForV3>>generateMethodOfClass:trailer:from: (in category 'method generation') -----
+ generateMethodOfClass: aCompiledMethodClass trailer: trailer from: methodNode
+ "The receiver is the root of a parse tree. Answer an instance of aCompiledMethodClass.
+ The argument, trailer, is arbitrary but is typically either the reference to the source code
+ that is stored with every CompiledMethod, or an encoding of the method's temporary names."
+
+ | primErrNode blkSize nLits literals header method stack |
+ primErrNode := methodNode primitiveErrorVariableName ifNotNil:
+ [self fixTemp: methodNode primitiveErrorVariableName].
+ blkSize := (methodNode block sizeCodeForEvaluatedValue: self)
+ + (primErrNode
+ ifNil: [0]
+ ifNotNil: [primErrNode sizeCodeForStore: self "The VM relies on storeIntoTemp: (129)"]).
+ header := self computeMethodHeaderForNumArgs: methodNode arguments size
+ numTemps: self maxTemp
+ numLits: (nLits := (literals := self allLiterals) size)
+ primitive: methodNode primitive.
+ method := trailer
+ createMethod: blkSize
+ class: aCompiledMethodClass
+ header: header.
+ 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
+ self streamToMethod: method.
+ stack := ParseStack new init.
+ primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: self].
+ stack position: method numTemps.
+ [methodNode block emitCodeForEvaluatedValue: stack encoder: self]
+ on: Error "If an attempt is made to write too much code the method will be asked"
+ do: [:ex| "to grow, and the grow attempt will fail in CompiledMethod class>>#new:"
+ ex signalerContext sender method = (CompiledMethod class>>#new:)
+ ifTrue: [^self error: 'Compiler code size discrepancy']
+ ifFalse: [ex pass]].
+ stack position ~= (method numTemps + 1) ifTrue:
+ [^self error: 'Compiler stack discrepancy'].
+ self methodStreamPosition ~= (method size - trailer size) ifTrue:
+ [^self error: 'Compiler code size discrepancy'].
+ method needsFrameSize: stack size - method numTemps.
+ ^method!
Item was added:
+ ----- Method: EncoderForV3PlusClosures>>generateMethodOfClass:trailer:from: (in category 'method generation') -----
+ generateMethodOfClass: aCompiledMethodClass trailer: trailer from: methodNode
+ "The receiver is the root of a parse tree. Answer an instance of aCompiledMethodClass.
+ The argument, trailer, is arbitrary but is typically either the reference to the source code
+ that is stored with every CompiledMethod, or an encoding of the method's temporary names."
+
+ | primErrNode blkSize nLits locals literals header method stack |
+ primErrNode := methodNode primitiveErrorVariableName ifNotNil:
+ [self fixTemp: methodNode primitiveErrorVariableName].
+ methodNode ensureClosureAnalysisDone.
+ self rootNode: methodNode. "this is for BlockNode>>sizeCodeForClosureValue:"
+ blkSize := (methodNode block sizeCodeForEvaluatedValue: self)
+ + (primErrNode
+ ifNil: [0]
+ ifNotNil:
+ [primErrNode
+ index: methodNode arguments size + methodNode temporaries size;
+ sizeCodeForStore: self "The VM relies on storeIntoTemp: (129)"]).
+ locals := methodNode arguments, methodNode temporaries, (primErrNode ifNil: [#()] ifNotNil: [{primErrNode}]).
+ self noteBlockExtent: methodNode block blockExtent hasLocals: locals.
+ header := self computeMethodHeaderForNumArgs: methodNode arguments size
+ numTemps: locals size
+ numLits: (nLits := (literals := self allLiterals) size)
+ primitive: methodNode primitive.
+ method := trailer
+ createMethod: blkSize
+ class: aCompiledMethodClass
+ header: header.
+ 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
+ self streamToMethod: method.
+ stack := ParseStack new init.
+ primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: self].
+ stack position: method numTemps.
+ [methodNode block emitCodeForEvaluatedValue: stack encoder: self]
+ on: Error "If an attempt is made to write too much code the method will be asked"
+ do: [:ex| "to grow, and the grow attempt will fail in CompiledMethod class>>#new:"
+ ex signalerContext sender method = (CompiledMethod class>>#new:)
+ ifTrue: [^self error: 'Compiler code size discrepancy']
+ ifFalse: [ex pass]].
+ stack position ~= (method numTemps + 1) ifTrue:
+ [^self error: 'Compiler stack discrepancy'].
+ self methodStreamPosition ~= (method size - trailer size) ifTrue:
+ [^self error: 'Compiler code size discrepancy'].
+ method needsFrameSize: stack size - method numTemps.
+ ^method!
Item was changed:
SelectorNode subclass: #SpecialSelectorNode
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Compiler-ParseNodes'!
+
+ !SpecialSelectorNode commentStamp: 'eem 8/5/2014 20:18' prior: 0!
+ A SpecialSelectorNode is a subclass of SelectorNode that handles the special selectors, a high static and/or dynamic frequency set of selectors that are assigned their own bytecodes. Special selectors both save space in the literal frame and allow an interpreter to implement these sends directly for certain classes of receiver and argument, for example the SmallIntegers, a technique known as static receiver prediction.!
Eliot Miranda uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-eem.286.mcz
==================== Summary ====================
Name: Compiler-eem.286
Author: eem
Time: 5 August 2014, 9:44:57.105 pm
UUID: 34f9ea24-6e5a-4bb3-9e9f-0f59fb8c93cf
Ancestors: Compiler-eem.285
Provide the selector scanning support InstructionStream
needs to make selectorToSendOrSelf multiple bytecode set
capable.
Provide the method generators so that methods can be
generated with the two different header formats.
Provide a class comment for SpecialSelectorNode.
=============== Diff against Compiler-eem.285 ===============
Item was added:
+ ----- Method: BytecodeEncoder class>>selectorToSendOrItselfFor:in:at: (in category 'instruction stream support') -----
+ selectorToSendOrItselfFor: anInstructionStream in: method at: pc
+ "If anInstructionStream is at a send bytecode then answer the send's selector,
+ otherwise answer anInstructionStream itself. The rationale for answering
+ anInstructionStream instead of, say, nil, is that potentially any existing object
+ can be used as a selector, but since anInstructionStream postdates the method,
+ it can't be one of them."
+
+ self subclassResponsibility!
Item was added:
+ ----- Method: BytecodeEncoder>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') -----
+ computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex
+ "Compute the compiled method header that encodes the arguments
+ in the receiver's header format (see CompiledMehtod's class comment)."
+ self subclassResponsibility!
Item was added:
+ ----- Method: BytecodeEncoder>>generateMethodOfClass:trailer:from: (in category 'method generation') -----
+ generateMethodOfClass: aCompiledMethodClass trailer: trailer from: methodNode
+ "methodNode is the root of a parse tree. Answer an instance of aCompiledMethodClass
+ in the receiver's bytecode set and using the receiver's method header format.
+ The argument, trailer, is arbitrary but is typically either the reference to the source code
+ that is stored with every CompiledMethod, or an encoding of the method's temporary names."
+
+ self subclassResponsibility!
Item was added:
+ ----- Method: EncoderForV3 class>>selectorToSendOrItselfFor:in:at: (in category 'instruction stream support') -----
+ selectorToSendOrItselfFor: anInstructionStream in: method at: pc
+ "If anInstructionStream is at a send bytecode then answer the send's selector,
+ otherwise answer anInstructionStream itself. The rationale for answering
+ anInstructionStream instead of, say, nil, is that potentially any existing object
+ can be used as a selector, but since anInstructionStream postdates the method,
+ it can't be one of them."
+
+ | byte byte2 |
+ byte := method at: pc.
+ byte < 131 ifTrue: [^anInstructionStream].
+ byte >= 176
+ ifTrue:
+ ["special byte or short send"
+ byte >= 208
+ ifTrue: [^method literalAt: (byte bitAnd: 15) + 1]
+ ifFalse: [^Smalltalk specialSelectorAt: byte - 176 + 1]]
+ ifFalse:
+ [byte <= 134 ifTrue:
+ [byte2 := method at: pc + 1.
+ byte = 131 ifTrue: [^method literalAt: byte2 \\ 32 + 1].
+ byte = 132 ifTrue: [byte2 < 64 ifTrue: [^method literalAt: (method at: pc + 2) + 1]].
+ byte = 133 ifTrue: [^method literalAt: byte2 \\ 32 + 1].
+ byte = 134 ifTrue: [^method literalAt: byte2 \\ 64 + 1]]].
+ ^anInstructionStream!
Item was added:
+ ----- Method: EncoderForV3>>computeMethodHeaderForNumArgs:numTemps:numLits:primitive: (in category 'method generation') -----
+ computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex
+ | primBits |
+ numTemps > 63 ifTrue:
+ [^self error: 'Cannot compile -- too many temporary variables'].
+ numLits > 255 ifTrue:
+ [^self error: 'Cannot compile -- too many literals'].
+ primBits := primitiveIndex <= 16r1FF
+ ifTrue: [primitiveIndex]
+ ifFalse: "For now the high bit of primitive no. is in the 29th bit of header"
+ [primitiveIndex > 16r3FF ifTrue: [self error: 'prim num too large'].
+ (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r200) bitShift: 19)].
+ ^(numArgs bitShift: 24)
+ + (numTemps bitShift: 18)
+ "+ (largeBit bitShift: 17)" "largeBit gets filled in later"
+ + (numLits bitShift: 9)
+ + primBits!
Item was added:
+ ----- Method: EncoderForV3>>generateMethodOfClass:trailer:from: (in category 'method generation') -----
+ generateMethodOfClass: aCompiledMethodClass trailer: trailer from: methodNode
+ "The receiver is the root of a parse tree. Answer an instance of aCompiledMethodClass.
+ The argument, trailer, is arbitrary but is typically either the reference to the source code
+ that is stored with every CompiledMethod, or an encoding of the method's temporary names."
+
+ | primErrNode blkSize nLits literals header method stack |
+ primErrNode := methodNode primitiveErrorVariableName ifNotNil:
+ [self fixTemp: methodNode primitiveErrorVariableName].
+ blkSize := (methodNode block sizeCodeForEvaluatedValue: self)
+ + (primErrNode
+ ifNil: [0]
+ ifNotNil: [primErrNode sizeCodeForStore: self "The VM relies on storeIntoTemp: (129)"]).
+ header := self computeMethodHeaderForNumArgs: methodNode arguments size
+ numTemps: self maxTemp
+ numLits: (nLits := (literals := self allLiterals) size)
+ primitive: methodNode primitive.
+ method := trailer
+ createMethod: blkSize
+ class: aCompiledMethodClass
+ header: header.
+ 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
+ self streamToMethod: method.
+ stack := ParseStack new init.
+ primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: self].
+ stack position: method numTemps.
+ [methodNode block emitCodeForEvaluatedValue: stack encoder: self]
+ on: Error "If an attempt is made to write too much code the method will be asked"
+ do: [:ex| "to grow, and the grow attempt will fail in CompiledMethod class>>#new:"
+ ex signalerContext sender method = (CompiledMethod class>>#new:)
+ ifTrue: [^self error: 'Compiler code size discrepancy']
+ ifFalse: [ex pass]].
+ stack position ~= (method numTemps + 1) ifTrue:
+ [^self error: 'Compiler stack discrepancy'].
+ self methodStreamPosition ~= (method size - trailer size) ifTrue:
+ [^self error: 'Compiler code size discrepancy'].
+ method needsFrameSize: stack size - method numTemps.
+ ^method!
Item was added:
+ ----- Method: EncoderForV3PlusClosures>>generateMethodOfClass:trailer:from: (in category 'method generation') -----
+ generateMethodOfClass: aCompiledMethodClass trailer: trailer from: methodNode
+ "The receiver is the root of a parse tree. Answer an instance of aCompiledMethodClass.
+ The argument, trailer, is arbitrary but is typically either the reference to the source code
+ that is stored with every CompiledMethod, or an encoding of the method's temporary names."
+
+ | primErrNode blkSize nLits locals literals header method stack |
+ primErrNode := methodNode primitiveErrorVariableName ifNotNil:
+ [self fixTemp: methodNode primitiveErrorVariableName].
+ methodNode ensureClosureAnalysisDone.
+ self rootNode: methodNode. "this is for BlockNode>>sizeCodeForClosureValue:"
+ blkSize := (methodNode block sizeCodeForEvaluatedValue: self)
+ + (primErrNode
+ ifNil: [0]
+ ifNotNil:
+ [primErrNode
+ index: methodNode arguments size + methodNode temporaries size;
+ sizeCodeForStore: self "The VM relies on storeIntoTemp: (129)"]).
+ locals := methodNode arguments, methodNode temporaries, (primErrNode ifNil: [#()] ifNotNil: [{primErrNode}]).
+ self noteBlockExtent: methodNode block blockExtent hasLocals: locals.
+ header := self computeMethodHeaderForNumArgs: methodNode arguments size
+ numTemps: locals size
+ numLits: (nLits := (literals := self allLiterals) size)
+ primitive: methodNode primitive.
+ method := trailer
+ createMethod: blkSize
+ class: aCompiledMethodClass
+ header: header.
+ 1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
+ self streamToMethod: method.
+ stack := ParseStack new init.
+ primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: self].
+ stack position: method numTemps.
+ [methodNode block emitCodeForEvaluatedValue: stack encoder: self]
+ on: Error "If an attempt is made to write too much code the method will be asked"
+ do: [:ex| "to grow, and the grow attempt will fail in CompiledMethod class>>#new:"
+ ex signalerContext sender method = (CompiledMethod class>>#new:)
+ ifTrue: [^self error: 'Compiler code size discrepancy']
+ ifFalse: [ex pass]].
+ stack position ~= (method numTemps + 1) ifTrue:
+ [^self error: 'Compiler stack discrepancy'].
+ self methodStreamPosition ~= (method size - trailer size) ifTrue:
+ [^self error: 'Compiler code size discrepancy'].
+ method needsFrameSize: stack size - method numTemps.
+ ^method!
Item was changed:
SelectorNode subclass: #SpecialSelectorNode
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Compiler-ParseNodes'!
+
+ !SpecialSelectorNode commentStamp: 'eem 8/5/2014 20:18' prior: 0!
+ A SpecialSelectorNode is a subclass of SelectorNode that handles the special selectors, a high static and/or dynamic frequency set of selectors that are assigned their own bytecodes. Special selectors both save space in the literal frame and allow an interpreter to implement these sends directly for certain classes of receiver and argument, for example the SmallIntegers, a technique known as static receiver prediction.!
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.864.mcz
==================== Summary ====================
Name: Kernel-eem.864
Author: eem
Time: 5 August 2014, 9:27:06.696 pm
UUID: 3fa01ebb-bef4-4b68-aac7-3cf0a41e3df1
Ancestors: Kernel-eem.863
Allow encoderClass to be stored in a property to allow
tsting of methods in different bytecode sets before those
sets have been installed.
Don't create blocks in the property accessors unless
absolutely necessary.
=============== Diff against Kernel-eem.863 ===============
Item was changed:
----- 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."
- The sign flag bit is used by the VM to select a bytecode set."
^self header >= 0
+ ifTrue:
+ [PrimaryBytecodeSetEncoderClass]
+ ifFalse:
+ [PrimaryBytecodeSetEncoderClass == SecondaryBytecodeSetEncoderClass
+ ifTrue: "Support for testing prior to installing another set"
+ [(self propertyValueAt: #encoderClass) ifNil: [SecondaryBytecodeSetEncoderClass]]
+ ifFalse:
+ [SecondaryBytecodeSetEncoderClass]]!
- ifTrue: [PrimaryBytecodeSetEncoderClass]
- ifFalse: [SecondaryBytecodeSetEncoderClass]!
Item was changed:
----- Method: CompiledMethod>>pragmaAt: (in category 'accessing-pragmas & properties') -----
pragmaAt: aKey
"Answer the pragma with selector aKey, or nil if none."
| propertiesOrSelector |
^(propertiesOrSelector := self penultimateLiteral) isMethodProperties
+ ifTrue: [propertiesOrSelector at: aKey ifAbsent: nil]
- ifTrue: [propertiesOrSelector at: aKey ifAbsent: [nil]]
ifFalse: [nil]!
Item was changed:
----- Method: CompiledMethod>>propertyValueAt: (in category 'accessing-pragmas & properties') -----
propertyValueAt: propName
| propertiesOrSelector |
^(propertiesOrSelector := self penultimateLiteral) isMethodProperties
+ ifTrue: [propertiesOrSelector propertyValueAt: propName ifAbsent: nil]
- ifTrue: [propertiesOrSelector propertyValueAt: propName ifAbsent: [nil]]
ifFalse: [nil]!
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.864.mcz
==================== Summary ====================
Name: Kernel-eem.864
Author: eem
Time: 5 August 2014, 9:27:06.696 pm
UUID: 3fa01ebb-bef4-4b68-aac7-3cf0a41e3df1
Ancestors: Kernel-eem.863
Allow encoderClass to be stored in a property to allow
tsting of methods in different bytecode sets before those
sets have been installed.
Don't create blocks in the property accessors unless
absolutely necessary.
=============== Diff against Kernel-eem.863 ===============
Item was changed:
----- 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."
- The sign flag bit is used by the VM to select a bytecode set."
^self header >= 0
+ ifTrue:
+ [PrimaryBytecodeSetEncoderClass]
+ ifFalse:
+ [PrimaryBytecodeSetEncoderClass == SecondaryBytecodeSetEncoderClass
+ ifTrue: "Support for testing prior to installing another set"
+ [(self propertyValueAt: #encoderClass) ifNil: [SecondaryBytecodeSetEncoderClass]]
+ ifFalse:
+ [SecondaryBytecodeSetEncoderClass]]!
- ifTrue: [PrimaryBytecodeSetEncoderClass]
- ifFalse: [SecondaryBytecodeSetEncoderClass]!
Item was changed:
----- Method: CompiledMethod>>pragmaAt: (in category 'accessing-pragmas & properties') -----
pragmaAt: aKey
"Answer the pragma with selector aKey, or nil if none."
| propertiesOrSelector |
^(propertiesOrSelector := self penultimateLiteral) isMethodProperties
+ ifTrue: [propertiesOrSelector at: aKey ifAbsent: nil]
- ifTrue: [propertiesOrSelector at: aKey ifAbsent: [nil]]
ifFalse: [nil]!
Item was changed:
----- Method: CompiledMethod>>propertyValueAt: (in category 'accessing-pragmas & properties') -----
propertyValueAt: propName
| propertiesOrSelector |
^(propertiesOrSelector := self penultimateLiteral) isMethodProperties
+ ifTrue: [propertiesOrSelector propertyValueAt: propName ifAbsent: nil]
- ifTrue: [propertiesOrSelector propertyValueAt: propName ifAbsent: [nil]]
ifFalse: [nil]!
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.864.mcz
==================== Summary ====================
Name: Kernel-eem.864
Author: eem
Time: 5 August 2014, 9:27:06.696 pm
UUID: 3fa01ebb-bef4-4b68-aac7-3cf0a41e3df1
Ancestors: Kernel-eem.863
Allow encoderClass to be stored in a property to allow
tsting of methods in different bytecode sets before those
sets have been installed.
Don't create blocks in the property accessors unless
absolutely necessary.
=============== Diff against Kernel-eem.863 ===============
Item was changed:
----- 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."
- The sign flag bit is used by the VM to select a bytecode set."
^self header >= 0
+ ifTrue:
+ [PrimaryBytecodeSetEncoderClass]
+ ifFalse:
+ [PrimaryBytecodeSetEncoderClass == SecondaryBytecodeSetEncoderClass
+ ifTrue: "Support for testing prior to installing another set"
+ [(self propertyValueAt: #encoderClass) ifNil: [SecondaryBytecodeSetEncoderClass]]
+ ifFalse:
+ [SecondaryBytecodeSetEncoderClass]]!
- ifTrue: [PrimaryBytecodeSetEncoderClass]
- ifFalse: [SecondaryBytecodeSetEncoderClass]!
Item was changed:
----- Method: CompiledMethod>>pragmaAt: (in category 'accessing-pragmas & properties') -----
pragmaAt: aKey
"Answer the pragma with selector aKey, or nil if none."
| propertiesOrSelector |
^(propertiesOrSelector := self penultimateLiteral) isMethodProperties
+ ifTrue: [propertiesOrSelector at: aKey ifAbsent: nil]
- ifTrue: [propertiesOrSelector at: aKey ifAbsent: [nil]]
ifFalse: [nil]!
Item was changed:
----- Method: CompiledMethod>>propertyValueAt: (in category 'accessing-pragmas & properties') -----
propertyValueAt: propName
| propertiesOrSelector |
^(propertiesOrSelector := self penultimateLiteral) isMethodProperties
+ ifTrue: [propertiesOrSelector propertyValueAt: propName ifAbsent: nil]
- ifTrue: [propertiesOrSelector propertyValueAt: propName ifAbsent: [nil]]
ifFalse: [nil]!
Eliot Miranda uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System.spur-eem.684.mcz
==================== Summary ====================
Name: System.spur-eem.684
Author: eem
Time: 5 August 2014, 8:07:21.622 pm
UUID: 8eda4cf2-26ab-4f5c-b55b-ce56de81314a
Ancestors: System-eem.684
System-eem.684 patched for Spur by SpurBootstrapMonticelloPackagePatcher Cog-eem.179
Fix mis-categorization
=============== Diff against System-eem.684 ===============
Item was changed:
----- Method: SmalltalkImage>>compactClassesArray (in category 'special objects') -----
compactClassesArray
"Smalltalk compactClassesArray"
+ "Backward-compatibility support. Spur does not have compact classes."
+ ^{}!
- "Return the array of 31 classes whose instances may be
- represented compactly"
- ^ self specialObjectsArray at: 29!
Item was added:
+ ----- Method: SmalltalkImage>>growMemoryByAtLeast: (in category 'memory space') -----
+ growMemoryByAtLeast: numBytes
+ "Grow memory by at least the requested number of bytes.
+ Primitive. Essential. Fail if no memory is available."
+ <primitive: 180>
+ (numBytes isInteger and: [numBytes > 0]) ifTrue:
+ [OutOfMemory signal].
+ ^self primitiveFailed!
Item was added:
+ ----- Method: SmalltalkImage>>maxIdentityHash (in category 'system attributes') -----
+ maxIdentityHash
+ "Answer the maximum identityHash value supported by the VM."
+ <primitive: 176>
+ ^self primitiveFailed!
Item was changed:
----- Method: SmalltalkImage>>recreateSpecialObjectsArray (in category 'special objects') -----
recreateSpecialObjectsArray
"Smalltalk recreateSpecialObjectsArray"
"To external package developers:
**** DO NOT OVERRIDE THIS METHOD. *****
If you are writing a plugin and need additional special object(s) for your own use,
use addGCRoot() function and use own, separate special objects registry "
"The Special Objects Array is an array of objects used by the Squeak virtual machine.
Its contents are critical and accesses to it by the VM are unchecked, so don't even
think of playing here unless you know what you are doing."
| newArray |
+ newArray := Array new: 60.
- newArray := Array new: 58.
"Nil false and true get used throughout the interpreter"
newArray at: 1 put: nil.
newArray at: 2 put: false.
newArray at: 3 put: true.
"This association holds the active process (a ProcessScheduler)"
newArray at: 4 put: (self specialObjectsArray at: 4) "(self bindingOf: #Processor) but it answers an Alias".
"Numerous classes below used for type checking and instantiation"
newArray at: 5 put: Bitmap.
newArray at: 6 put: SmallInteger.
newArray at: 7 put: ByteString.
newArray at: 8 put: Array.
newArray at: 9 put: Smalltalk.
newArray at: 10 put: Float.
+ newArray at: 11 put: (self globals at: #MethodContext ifAbsent: [self globals at: #Context]).
+ newArray at: 12 put: nil. "was BlockContext."
- newArray at: 11 put: MethodContext.
- newArray at: 12 put: BlockContext.
newArray at: 13 put: Point.
newArray at: 14 put: LargePositiveInteger.
newArray at: 15 put: Display.
newArray at: 16 put: Message.
newArray at: 17 put: CompiledMethod.
+ newArray at: 18 put: ((self specialObjectsArray at: 18) ifNil: [Semaphore new]). "low space Semaphore"
- newArray at: 18 put: (self specialObjectsArray at: 18).
- "(low space Semaphore)"
newArray at: 19 put: Semaphore.
newArray at: 20 put: Character.
newArray at: 21 put: #doesNotUnderstand:.
newArray at: 22 put: #cannotReturn:.
newArray at: 23 put: nil. "This is the process signalling low space."
"An array of the 32 selectors that are compiled as special bytecodes,
paired alternately with the number of arguments each takes."
newArray at: 24 put: #( #+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1
#* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1
#at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 #class 0
#blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0 ).
"An array of the 255 Characters in ascii order.
+ Cog inlines table into machine code at: prim so do not regenerate it.
+ This is nil in Spur, which has immediate Characters."
- Cog inlines table into machine code at: prim so do not regenerate it."
newArray at: 25 put: (self specialObjectsArray at: 25).
newArray at: 26 put: #mustBeBoolean.
newArray at: 27 put: ByteArray.
newArray at: 28 put: Process.
+ "An array of up to 31 classes whose instances will have compact headers; an empty array in Spur"
- "An array of up to 31 classes whose instances will have compact headers"
newArray at: 29 put: self compactClassesArray.
+ newArray at: 30 put: ((self specialObjectsArray at: 30) ifNil: [Semaphore new]). "delay Semaphore"
+ newArray at: 31 put: ((self specialObjectsArray at: 31) ifNil: [Semaphore new]). "user interrupt Semaphore"
- newArray at: 30 put: (self specialObjectsArray at: 30). "(delay Semaphore)"
- newArray at: 31 put: (self specialObjectsArray at: 31). "(user interrupt Semaphore)"
"Entries 32 - 34 unreferenced. Previously these contained prototype instances to be copied for fast initialization"
+ newArray at: 32 put: nil. "was the prototype Float"
+ newArray at: 33 put: nil. "was the prototype 4-byte LargePositiveInteger"
+ newArray at: 34 put: nil. "was the prototype Point"
- newArray at: 32 put: nil. "was (Float new: 2)"
- newArray at: 33 put: nil. "was (LargePositiveInteger new: 4)"
- newArray at: 34 put: nil. "was Point new"
newArray at: 35 put: #cannotInterpret:.
+ newArray at: 36 put: nil. "was the prototype MethodContext"
- "Note: This must be fixed once we start using context prototypes (yeah, right)"
- "(MethodContext new: CompiledMethod fullFrameSize)."
- newArray at: 36 put: (self specialObjectsArray at: 36). "Is the prototype MethodContext (unused by the VM)"
newArray at: 37 put: BlockClosure.
+ newArray at: 38 put: nil. "was the prototype BlockContext"
- "(BlockContext new: CompiledMethod fullFrameSize)."
- newArray at: 38 put: (self specialObjectsArray at: 38). "Is the prototype BlockContext (unused by the VM)"
"array of objects referred to by external code"
+ newArray at: 39 put: (self specialObjectsArray at: 39). "external semaphores"
- newArray at: 39 put: (self specialObjectsArray at: 39). "preserve external semaphores"
newArray at: 40 put: nil. "Reserved for Mutex in Cog VMs"
+ newArray at: 41 put: ((self specialObjectsArray at: 41) ifNil: [LinkedList new]). "Reserved for a LinkedList instance for overlapped calls in CogMT"
+ newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]). "finalization Semaphore"
- newArray at: 41 put: nil. "Reserved for a LinkedList instance for overlapped calls in CogMT"
- "finalization Semaphore"
- newArray at: 42 put: ((self specialObjectsArray at: 42) ifNil: [Semaphore new]).
newArray at: 43 put: LargeNegativeInteger.
"External objects for callout.
Note: Written so that one can actually completely remove the FFI."
newArray at: 44 put: (self at: #ExternalAddress ifAbsent: []).
newArray at: 45 put: (self at: #ExternalStructure ifAbsent: []).
newArray at: 46 put: (self at: #ExternalData ifAbsent: []).
newArray at: 47 put: (self at: #ExternalFunction ifAbsent: []).
newArray at: 48 put: (self at: #ExternalLibrary ifAbsent: []).
newArray at: 49 put: #aboutToReturn:through:.
newArray at: 50 put: #run:with:in:.
"51 reserved for immutability message"
+ newArray at: 51 put: #attemptToAssign:withIndex:.
- "newArray at: 51 put: #attemptToAssign:withIndex:."
- newArray at: 51 put: (self specialObjectsArray at: 51 ifAbsent: []).
newArray at: 52 put: #(nil "nil => generic error" #'bad receiver'
#'bad argument' #'bad index'
#'bad number of arguments'
#'inappropriate operation' #'unsupported operation'
#'no modification' #'insufficient object memory'
#'insufficient C memory' #'not found' #'bad method'
#'internal error in named primitive machinery'
#'object may move' #'resource limit exceeded'
+ #'object is pinned' #'primitive write beyond end of object').
- #'object is pinned').
"53 to 55 are for Alien"
newArray at: 53 put: (self at: #Alien ifAbsent: []).
newArray at: 54 put: #invokeCallbackContext::. "use invokeCallback:stack:registers:jmpbuf: for old Alien callbacks."
newArray at: 55 put: (self at: #UnsafeAlien ifAbsent: []).
+ "Used to be WeakFinalizationList for WeakFinalizationList hasNewFinalization, obsoleted by ephemeron support."
+ newArray at: 56 put: nil.
- "Weak reference finalization"
- newArray at: 56 put: (self at: #WeakFinalizationList ifAbsent: []).
"reserved for foreign callback process"
newArray at: 57 put: (self specialObjectsArray at: 57 ifAbsent: []).
newArray at: 58 put: #unusedBytecode.
+ "59 reserved for Sista counter tripped message"
+ newArray at: 59 put: #conditionalBranchCounterTrippedOn:.
+ "60 reserved for Sista class trap message"
+ newArray at: 60 put: #classTrapFor:.
"Now replace the interpreter's reference in one atomic operation"
+ self specialObjectsArray becomeForward: newArray!
- self specialObjectsArray becomeForward: newArray
- !
Item was changed:
----- Method: SmalltalkImage>>setGCParameters (in category 'snapshot and quit') -----
setGCParameters
+ "Adjust the VM's default GC parameters to avoid too much tenuring.
+ Maybe this should be left to the VM?"
- "Adjust the VM's default GC parameters to avoid premature tenuring."
+ | proportion edenSize survivorSize averageObjectSize numObjects |
+ proportion := 0.9. "tenure when 90% of pastSpace is full"
+ edenSize := SmalltalkImage current vmParameterAt: 44.
+ survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)"
+ averageObjectSize := 8 * self wordSize. "a good approximation"
+ numObjects := (proportion * survivorSize / averageObjectSize) rounded.
+ SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"!
- self vmParameterAt: 5 put: 4000. "do an incremental GC after this many allocations"
- self vmParameterAt: 6 put: 2000. "tenure when more than this many objects survive the GC"
- !
Item was changed:
----- Method: SpaceTally>>spaceForInstancesOf: (in category 'instance size') -----
spaceForInstancesOf: aClass
+ "Answer a pair of the number of bytes consumed by all instances of the
+ given class, including their object headers, and the number of instances."
- "Answer the number of bytes consumed by all instances of the given class, including their object headers and the number of instances."
+ | instances total |
+ instances := aClass allInstances.
+ instances isEmpty ifTrue: [^#(0 0)].
- | smallHeaderSize instVarBytes isVariable bytesPerElement total lastInstance instance instanceCount |
- instance := aClass someInstance ifNil: [ ^#(0 0) ].
- smallHeaderSize := aClass isCompact ifTrue: [ 4 ] ifFalse: [ 8 ].
- instVarBytes := aClass instSize * 4.
- isVariable := aClass isVariable.
- bytesPerElement := isVariable
- ifFalse: [ 0 ]
- ifTrue: [ aClass isBytes ifTrue: [ 1 ] ifFalse: [ 4 ] ].
total := 0.
+ aClass isVariable
+ ifTrue:
+ [instances do:
+ [:i| total := total + (aClass byteSizeOfInstanceOfSize: i basicSize)]]
+ ifFalse:
+ [total := instances size * aClass byteSizeOfInstance].
+ ^{ total. instances size }!
- instanceCount := 0.
- "A modified version of #allInstancesDo: is inlined here. It avoids an infinite loop when another process is creating new instances of aClass."
- self flag: #allInstancesDo:.
- lastInstance :=
- aClass == CompiledMethod "CompiledMethod has special format, see its class comment"
- ifTrue: [aClass new]
- ifFalse: [aClass basicNew].
- [ instance == lastInstance ] whileFalse: [
- | contentBytes headerBytes |
- contentBytes := instVarBytes + (isVariable
- ifFalse: [ 0 ]
- ifTrue: [ instance basicSize * bytesPerElement ]).
- headerBytes := contentBytes > 255
- ifTrue: [ 12 ]
- ifFalse: [ smallHeaderSize ].
- total := total + headerBytes + (contentBytes roundUpTo: 4).
- instanceCount := instanceCount + 1.
- instance := instance nextInstance ].
- ^{ total. instanceCount }!
Item was added:
+ ----- Method: SystemDictionary>>growMemoryByAtLeast: (in category 'memory space') -----
+ growMemoryByAtLeast: numBytes
+ "Grow memory by at least the requested number of bytes.
+ Primitive. Fail if no memory is available. Essential."
+ <primitive: 180>
+ ^(numBytes isInteger and: [numBytes > 0])
+ ifTrue: [OutOfMemory signal]
+ ifFalse: [self primitiveFailed]!
Item was added:
+ ----- Method: SystemDictionary>>maxIdentityHash (in category 'system attributes') -----
+ maxIdentityHash
+ "Answer the maximum identityHash value supported by the VM."
+ <primitive: 176>
+ ^self primitiveFailed!
Item was added:
+ ----- Method: SystemDictionary>>setGCParameters (in category 'snapshot and quit') -----
+ setGCParameters
+ "Adjust the VM's default GC parameters to avoid too much tenuring.
+ Maybe this should be left to the VM?"
+
+ | proportion edenSize survivorSize averageObjectSize numObjects |
+ proportion := 0.9. "tenure when 90% of pastSpace is full"
+ edenSize := SmalltalkImage current vmParameterAt: 44.
+ survivorSize := edenSize / 5.0. "David's paper uses 140Kb eden + 2 x 28kb survivor spaces; Spur uses the same ratios :-)"
+ averageObjectSize := 8 * self wordSize. "a good approximation"
+ numObjects := (proportion * survivorSize / averageObjectSize) rounded.
+ SmalltalkImage current vmParameterAt: 6 put: numObjects "tenure when more than this many objects survive the GC"!
Item was added:
+ ----- Method: SystemNavigation>>allObjects (in category 'as yet unclassified') -----
+ allObjects
+ "Answer an Array of all objects in the system. Fail if
+ there isn't enough memory to instantiate the result."
+ <primitive: 178>
+ ^self primitiveFailed!
Item was changed:
----- Method: SystemNavigation>>allObjectsDo: (in category 'query') -----
allObjectsDo: aBlock
+ "Evaluate the argument, aBlock, for each object in the system, excluding immediates
+ such as SmallInteger and Character."
+ self allObjectsOrNil
+ ifNotNil: [:allObjects| allObjects do: aBlock]
+ ifNil:
+ ["Fall back on the old single object primitive code. With closures, this needs
+ to use an end marker (lastObject) since activation of the block will create
+ new contexts and cause an infinite loop. The lastObject must be created
+ before calling someObject, so that the VM can settle the enumeration (e.g.
+ by flushing new space) as a side effect of someObject"
+ | object lastObject |
+ lastObject := Object new.
+ object := self someObject.
+ [lastObject == object or: [0 == object]] whileFalse:
+ [aBlock value: object.
+ object := object nextObject]]!
- "Evaluate the argument, aBlock, for each object in the system
- excluding SmallIntegers. With closures, this needs to use an end
- marker (lastObject) since activation of the block will create new
- contexts and cause an infinite loop."
- | object lastObject |
- object := self someObject.
- lastObject := Object new.
- [lastObject == object or: [0 == object]]
- whileFalse: [aBlock value: object.
- object := object nextObject]!
Item was added:
+ ----- Method: SystemNavigation>>allObjectsOrNil (in category 'as yet unclassified') -----
+ allObjectsOrNil
+ "Answer an Array of all objects in the system. Fail if there isn't
+ enough memory to instantiate the result and answer nil."
+ <primitive: 178>
+ ^nil!