Guys, please integrate this asap. This is a horrible bug that is probably causing all sorts of crashes in large images on linux, and should have been generally causing horrible crashes all over the place. Bugs are good at lurking :-/.
On Wed, Apr 3, 2013 at 3:27 PM, commits@source.squeak.org wrote:
Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.281.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.281 Author: eem Time: 3 April 2013, 3:27:02.058 pm UUID: 64be55df-6421-4087-a712-5c07419806c7 Ancestors: VMMaker.oscog-eem.280
Cogit: Fix *HORRIBLE* yet ancient bug with the CogObjectRep. Both CogObjectRepresentationForSqueakV3>>couldBeObject: & CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: used signed comparisons for oops and so once the heap size pushes oops into the upper half of the address space constant oops in machine code were no longer being updated by the GC.
StackInterpreter: reqrite the login for printing methods so that printing the frame of a bad receiver won't seg fault.
=============== Diff against VMMaker.oscog-eem.280 ===============
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>couldBeObject: (in category 'garbage collection') ----- couldBeObject: oop ^(objectMemory isNonIntegerObject: oop)
and: [self oop: oop isGreaterThanOrEqualTo: objectMemory
nilObject]!
and: [oop asUnsignedInteger >= objectMemory nilObject]!
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: (in category 'garbage collection') ----- shouldAnnotateObjectReference: anOop "self assert: ((objectMemory isIntegerObject: anOop) or: [objectMemory addressCouldBeObj: anOop])." ^(objectMemory isNonIntegerObject: anOop)
and: [self oop: anOop isGreaterThan: objectMemory trueObject]!
and: [anOop > objectMemory trueObject]!
Item was changed: ----- Method: StackInterpreter class>>requiredMethodNames (in category 'translation') ----- requiredMethodNames "return the list of method names that should be retained for export or other support reasons" | requiredList | requiredList := self exportAPISelectors. requiredList addAll: NewObjectMemory requiredMethodNames. "A number of methods required by VM support code, jitter, specific platforms etc" requiredList addAll: #( assertValidExecutionPointe:r:s: characterForAscii: checkedLongAt: delayExpired
findClassOfMethod:forReceiver: findSelectorOfMethod:
findClassOfMethod:forReceiver:
findSelectorOfMethod:forReceiver: forceInterruptCheck forceInterruptCheckFromHeartbeat fullDisplayUpdate getCurrentBytecode getFullScreenFlag getInterruptKeycode getInterruptPending getSavedWindowSize getThisSessionID highBit: interpret loadInitialContext oopFromChunk: primitiveFail primitiveFailFor: primitiveFlushExternalPrimitives printAllStacks printCallStack printContext: printExternalHeadFrame printFramesInPage: printFrame: printHeadFrame printMemory printOop: printStackPages printStackPageList printStackPagesInUse printStackPageListInUse readableFormat: readImageFromFile:HeapSize:StartingAt: setFullScreenFlag: setInterruptKeycode: setInterruptPending: setInterruptCheckChain: setSavedWindowSize: success: validInstructionPointer:inMethod:framePointer:).
"Nice to actually have all the primitives available" requiredList addAll: (self primitiveTable select: [:each| each
isSymbol]).
"InterpreterProxy is the internal analogue of sqVirtualMachine.c,
so make sure to keep all those" InterpreterProxy organization categories do: [:cat | ((cat ~= 'initialize') and: [cat ~= 'private']) ifTrue: [requiredList addAll: (InterpreterProxy organization listAtCategoryNamed: cat)]].
^requiredList!
Item was added:
- ----- Method: StackInterpreter>>addressCouldBeClassObj: (in category
'debug support') -----
- addressCouldBeClassObj: maybeClassObj
"Answer if maybeClassObj looks like a class object"
<inline: false>
^(objectMemory addressCouldBeObj: maybeClassObj)
and: [((objectMemory isPointersNonInt: maybeClassObj) and:
[(objectMemory lengthOf: maybeClassObj) >= 3])
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: SuperclassIndex ofObject: maybeClassObj))
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: MethodDictionaryIndex ofObject: maybeClassObj))
and: [(objectMemory isIntegerObject: (objectMemory fetchPointer:
InstanceSpecificationIndex ofObject: maybeClassObj))]]]]!
Item was added:
- ----- Method: StackInterpreter>>findClassContainingMethod:startingAt:
(in category 'debug support') -----
- findClassContainingMethod: meth startingAt: classObj
| currClass classDict classDictSize methodArray i |
currClass := classObj.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method: StackInterpreter>>findClassOfMethod:forReceiver: (in category 'debug support') ----- findClassOfMethod: meth forReceiver: rcvr
| rclass |
(objectMemory addressCouldBeOop: rcvr) ifTrue:
[rclass := objectMemory fetchClassOf: rcvr.
(self addressCouldBeClassObj: rclass) ifTrue:
[rclass := self findClassContainingMethod: meth
startingAt: rclass.
rclass ~= objectMemory nilObject ifTrue:
[^rclass]]].
| rclass currClass classDict classDictSize methodArray i | (objectMemory addressCouldBeObj: meth) ifFalse: [^objectMemory nilObject].
^self findClassContainingMethod: meth startingAt: (self
methodClassOf: meth)!
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [rclass := objectMemory fetchClassOf: rcvr]
ifFalse: [rclass := self methodClassOf: meth].
currClass := rclass.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^rclass "method not found in superclass chain"!
Item was added:
- ----- Method: StackInterpreter>>findSelectorOfMethod: (in category
'debug support') -----
- findSelectorOfMethod: meth
| classObj classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
classObj := self methodClassOf: meth.
(self addressCouldBeClassObj: classObj) ifTrue:
[classDict := objectMemory fetchPointer:
MethodDictionaryIndex ofObject: classObj.
classDictSize := objectMemory fetchWordLengthOf:
classDict.
methodArray := objectMemory fetchPointer:
MethodArrayIndex ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i +
SelectorStart ofObject: classDict)].
i := i + 1]].
^objectMemory nilObject!
Item was removed:
- ----- Method: StackInterpreter>>findSelectorOfMethod:forReceiver: (in
category 'debug support') -----
- findSelectorOfMethod: meth forReceiver: rcvr
| currClass classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [currClass := objectMemory fetchClassOf: rcvr]
ifFalse: [currClass := self methodClassOf: meth].
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i + SelectorStart
ofObject: classDict)].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method: StackInterpreter>>printActivationNameFor:receiver:isBlock:firstTemporary: (in category 'debug printing') ----- printActivationNameFor: aMethod receiver: anObject isBlock: isBlock firstTemporary: maybeMessage
| methClass methodSel classObj |
| methClass methodSel | <inline: false> isBlock ifTrue: [self print: '[] in ']. methClass := self findClassOfMethod: aMethod forReceiver: anObject.
methodSel := self findSelectorOfMethod: aMethod.
((objectMemory addressCouldBeOop: anObject)
and: [self addressCouldBeClassObj: (classObj := objectMemory
fetchClassOf: anObject)])
methodSel := self findSelectorOfMethod: aMethod forReceiver:
anObject.
(objectMemory addressCouldBeOop: anObject) ifTrue:
[classObj = methClass
[(objectMemory fetchClassOf: anObject) = methClass ifTrue: [self printNameOfClass: methClass
count: 5] ifFalse:
[self printNameOfClass: classObj
count: 5.
[self printNameOfClass:
(objectMemory fetchClassOf: anObject) count: 5. self print: '('. self printNameOfClass: methClass count: 5. self print: ')']] ifFalse: [self print: 'INVALID RECEIVER']. self print: '>'. (objectMemory addressCouldBeOop: methodSel) ifTrue: [methodSel = objectMemory nilObject ifTrue: [self print: '?'] ifFalse: [self printStringOf: methodSel]] ifFalse: [self print: 'INVALID SELECTOR']. (methodSel = (objectMemory splObj: SelectorDoesNotUnderstand) and: [(objectMemory addressCouldBeObj: maybeMessage) and: [(objectMemory fetchClassOf: maybeMessage) = (objectMemory splObj: ClassMessage)]]) ifTrue: ["print arg message selector" methodSel := objectMemory fetchPointer: MessageSelectorIndex ofObject: maybeMessage. self print: ' '. self printStringOf: methodSel]!
Item was changed: ----- Method: StackInterpreter>>selectorOfContext: (in category 'debug printing') ----- selectorOfContext: aContext (objectMemory isContext: aContext) ifFalse: [^nil].
^self findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)!
^self
findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)
forReceiver: (objectMemory fetchPointer: ReceiverIndex
ofObject: aContext)!
On 4 April 2013 00:37, Eliot Miranda eliot.miranda@gmail.com wrote:
Guys, please integrate this asap. This is a horrible bug that is probably causing all sorts of crashes in large images on linux, and should have been generally causing horrible crashes all over the place. Bugs are good at lurking :-/.
Glad we have less and less of them. Thanks for your effort, Eliot!
I am currently at some remote place in Switzerland ;) , and cannot do much right now.. We're also have an interesting bug with pharo VM which (i guess) related to some stack (mis)balancing, we have a reproducible case where running code given you SmallInteger>>DNU... because some SmallInteger pops up on the stack at some point. At least it doesn't causing VM crash. But i had no time to investigate that. Esteban, do you having any new details on that?
On Wed, Apr 3, 2013 at 3:27 PM, commits@source.squeak.org wrote:
Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.281.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.281 Author: eem Time: 3 April 2013, 3:27:02.058 pm UUID: 64be55df-6421-4087-a712-5c07419806c7 Ancestors: VMMaker.oscog-eem.280
Cogit: Fix *HORRIBLE* yet ancient bug with the CogObjectRep. Both CogObjectRepresentationForSqueakV3>>couldBeObject: & CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: used signed comparisons for oops and so once the heap size pushes oops into the upper half of the address space constant oops in machine code were no longer being updated by the GC.
StackInterpreter: reqrite the login for printing methods so that printing the frame of a bad receiver won't seg fault.
=============== Diff against VMMaker.oscog-eem.280 ===============
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>couldBeObject: (in category 'garbage collection') ----- couldBeObject: oop ^(objectMemory isNonIntegerObject: oop)
and: [self oop: oop isGreaterThanOrEqualTo: objectMemory
nilObject]!
and: [oop asUnsignedInteger >= objectMemory nilObject]!
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: (in category 'garbage collection') ----- shouldAnnotateObjectReference: anOop "self assert: ((objectMemory isIntegerObject: anOop) or: [objectMemory addressCouldBeObj: anOop])." ^(objectMemory isNonIntegerObject: anOop)
and: [self oop: anOop isGreaterThan: objectMemory trueObject]!
and: [anOop > objectMemory trueObject]!
Item was changed: ----- Method: StackInterpreter class>>requiredMethodNames (in category 'translation') ----- requiredMethodNames "return the list of method names that should be retained for export or other support reasons" | requiredList | requiredList := self exportAPISelectors. requiredList addAll: NewObjectMemory requiredMethodNames. "A number of methods required by VM support code, jitter, specific platforms etc" requiredList addAll: #( assertValidExecutionPointe:r:s: characterForAscii: checkedLongAt: delayExpired
findClassOfMethod:forReceiver: findSelectorOfMethod:
findClassOfMethod:forReceiver:
findSelectorOfMethod:forReceiver: forceInterruptCheck forceInterruptCheckFromHeartbeat fullDisplayUpdate getCurrentBytecode getFullScreenFlag getInterruptKeycode getInterruptPending getSavedWindowSize getThisSessionID highBit: interpret loadInitialContext oopFromChunk: primitiveFail primitiveFailFor: primitiveFlushExternalPrimitives printAllStacks printCallStack printContext: printExternalHeadFrame printFramesInPage: printFrame: printHeadFrame printMemory printOop: printStackPages printStackPageList printStackPagesInUse printStackPageListInUse readableFormat: readImageFromFile:HeapSize:StartingAt: setFullScreenFlag: setInterruptKeycode: setInterruptPending: setInterruptCheckChain: setSavedWindowSize: success: validInstructionPointer:inMethod:framePointer:).
"Nice to actually have all the primitives available" requiredList addAll: (self primitiveTable select: [:each| each
isSymbol]).
"InterpreterProxy is the internal analogue of sqVirtualMachine.c,
so make sure to keep all those" InterpreterProxy organization categories do: [:cat | ((cat ~= 'initialize') and: [cat ~= 'private']) ifTrue: [requiredList addAll: (InterpreterProxy organization listAtCategoryNamed: cat)]].
^requiredList!
Item was added:
- ----- Method: StackInterpreter>>addressCouldBeClassObj: (in category
'debug support') -----
- addressCouldBeClassObj: maybeClassObj
"Answer if maybeClassObj looks like a class object"
<inline: false>
^(objectMemory addressCouldBeObj: maybeClassObj)
and: [((objectMemory isPointersNonInt: maybeClassObj) and:
[(objectMemory lengthOf: maybeClassObj) >= 3])
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: SuperclassIndex ofObject: maybeClassObj))
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: MethodDictionaryIndex ofObject: maybeClassObj))
and: [(objectMemory isIntegerObject: (objectMemory fetchPointer:
InstanceSpecificationIndex ofObject: maybeClassObj))]]]]!
Item was added:
- ----- Method: StackInterpreter>>findClassContainingMethod:startingAt:
(in category 'debug support') -----
- findClassContainingMethod: meth startingAt: classObj
| currClass classDict classDictSize methodArray i |
currClass := classObj.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method: StackInterpreter>>findClassOfMethod:forReceiver: (in category 'debug support') ----- findClassOfMethod: meth forReceiver: rcvr
| rclass |
(objectMemory addressCouldBeOop: rcvr) ifTrue:
[rclass := objectMemory fetchClassOf: rcvr.
(self addressCouldBeClassObj: rclass) ifTrue:
[rclass := self findClassContainingMethod: meth
startingAt: rclass.
rclass ~= objectMemory nilObject ifTrue:
[^rclass]]].
| rclass currClass classDict classDictSize methodArray i | (objectMemory addressCouldBeObj: meth) ifFalse: [^objectMemory nilObject].
^self findClassContainingMethod: meth startingAt: (self
methodClassOf: meth)!
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [rclass := objectMemory fetchClassOf: rcvr]
ifFalse: [rclass := self methodClassOf: meth].
currClass := rclass.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^rclass "method not found in superclass chain"!
Item was added:
- ----- Method: StackInterpreter>>findSelectorOfMethod: (in category
'debug support') -----
- findSelectorOfMethod: meth
| classObj classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
classObj := self methodClassOf: meth.
(self addressCouldBeClassObj: classObj) ifTrue:
[classDict := objectMemory fetchPointer:
MethodDictionaryIndex ofObject: classObj.
classDictSize := objectMemory fetchWordLengthOf:
classDict.
methodArray := objectMemory fetchPointer:
MethodArrayIndex ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i +
SelectorStart ofObject: classDict)].
i := i + 1]].
^objectMemory nilObject!
Item was removed:
- ----- Method: StackInterpreter>>findSelectorOfMethod:forReceiver: (in
category 'debug support') -----
- findSelectorOfMethod: meth forReceiver: rcvr
| currClass classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [currClass := objectMemory fetchClassOf: rcvr]
ifFalse: [currClass := self methodClassOf: meth].
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i + SelectorStart
ofObject: classDict)].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method: StackInterpreter>>printActivationNameFor:receiver:isBlock:firstTemporary: (in category 'debug printing') ----- printActivationNameFor: aMethod receiver: anObject isBlock: isBlock firstTemporary: maybeMessage
| methClass methodSel classObj |
| methClass methodSel | <inline: false> isBlock ifTrue: [self print: '[] in ']. methClass := self findClassOfMethod: aMethod forReceiver:
anObject.
methodSel := self findSelectorOfMethod: aMethod.
((objectMemory addressCouldBeOop: anObject)
and: [self addressCouldBeClassObj: (classObj := objectMemory
fetchClassOf: anObject)])
methodSel := self findSelectorOfMethod: aMethod forReceiver:
anObject.
(objectMemory addressCouldBeOop: anObject) ifTrue:
[classObj = methClass
[(objectMemory fetchClassOf: anObject) = methClass ifTrue: [self printNameOfClass: methClass
count: 5] ifFalse:
[self printNameOfClass: classObj
count: 5.
[self printNameOfClass:
(objectMemory fetchClassOf: anObject) count: 5. self print: '('. self printNameOfClass: methClass count: 5. self print: ')']] ifFalse: [self print: 'INVALID RECEIVER']. self print: '>'. (objectMemory addressCouldBeOop: methodSel) ifTrue: [methodSel = objectMemory nilObject ifTrue: [self print: '?'] ifFalse: [self printStringOf: methodSel]] ifFalse: [self print: 'INVALID SELECTOR']. (methodSel = (objectMemory splObj: SelectorDoesNotUnderstand) and: [(objectMemory addressCouldBeObj: maybeMessage) and: [(objectMemory fetchClassOf: maybeMessage) = (objectMemory splObj: ClassMessage)]]) ifTrue: ["print arg message selector" methodSel := objectMemory fetchPointer: MessageSelectorIndex ofObject: maybeMessage. self print: ' '. self printStringOf: methodSel]!
Item was changed: ----- Method: StackInterpreter>>selectorOfContext: (in category 'debug printing') ----- selectorOfContext: aContext (objectMemory isContext: aContext) ifFalse: [^nil].
^self findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)!
^self
findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)
forReceiver: (objectMemory fetchPointer: ReceiverIndex
ofObject: aContext)!
-- best, Eliot
oh, well... I think I have a 100% reproducible case, which is already something :)
anyway, I will integrate your changes tomorrow or monday :)
cheers, Esteban
On Apr 4, 2013, at 1:37 AM, Igor Stasenko siguctua@gmail.com wrote:
On 4 April 2013 00:37, Eliot Miranda eliot.miranda@gmail.com wrote:
Guys, please integrate this asap. This is a horrible bug that is probably causing all sorts of crashes in large images on linux, and should have been generally causing horrible crashes all over the place. Bugs are good at lurking :-/.
Glad we have less and less of them. Thanks for your effort, Eliot!
I am currently at some remote place in Switzerland ;) , and cannot do much right now.. We're also have an interesting bug with pharo VM which (i guess) related to some stack (mis)balancing, we have a reproducible case where running code given you SmallInteger>>DNU... because some SmallInteger pops up on the stack at some point. At least it doesn't causing VM crash. But i had no time to investigate that. Esteban, do you having any new details on that?
On Wed, Apr 3, 2013 at 3:27 PM, commits@source.squeak.org wrote:
Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.281.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.281 Author: eem Time: 3 April 2013, 3:27:02.058 pm UUID: 64be55df-6421-4087-a712-5c07419806c7 Ancestors: VMMaker.oscog-eem.280
Cogit: Fix *HORRIBLE* yet ancient bug with the CogObjectRep. Both CogObjectRepresentationForSqueakV3>>couldBeObject: & CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: used signed comparisons for oops and so once the heap size pushes oops into the upper half of the address space constant oops in machine code were no longer being updated by the GC.
StackInterpreter: reqrite the login for printing methods so that printing the frame of a bad receiver won't seg fault.
=============== Diff against VMMaker.oscog-eem.280 ===============
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>couldBeObject: (in category 'garbage collection') ----- couldBeObject: oop ^(objectMemory isNonIntegerObject: oop)
and: [self oop: oop isGreaterThanOrEqualTo: objectMemory
nilObject]!
and: [oop asUnsignedInteger >= objectMemory nilObject]!
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: (in category 'garbage collection') ----- shouldAnnotateObjectReference: anOop "self assert: ((objectMemory isIntegerObject: anOop) or: [objectMemory addressCouldBeObj: anOop])." ^(objectMemory isNonIntegerObject: anOop)
and: [self oop: anOop isGreaterThan: objectMemory trueObject]!
and: [anOop > objectMemory trueObject]!
Item was changed: ----- Method: StackInterpreter class>>requiredMethodNames (in category 'translation') ----- requiredMethodNames "return the list of method names that should be retained for export or other support reasons" | requiredList | requiredList := self exportAPISelectors. requiredList addAll: NewObjectMemory requiredMethodNames. "A number of methods required by VM support code, jitter, specific platforms etc" requiredList addAll: #( assertValidExecutionPointe:r:s: characterForAscii: checkedLongAt: delayExpired
findClassOfMethod:forReceiver: findSelectorOfMethod:
findClassOfMethod:forReceiver:
findSelectorOfMethod:forReceiver: forceInterruptCheck forceInterruptCheckFromHeartbeat fullDisplayUpdate getCurrentBytecode getFullScreenFlag getInterruptKeycode getInterruptPending getSavedWindowSize getThisSessionID highBit: interpret loadInitialContext oopFromChunk: primitiveFail primitiveFailFor: primitiveFlushExternalPrimitives printAllStacks printCallStack printContext: printExternalHeadFrame printFramesInPage: printFrame: printHeadFrame printMemory printOop: printStackPages printStackPageList printStackPagesInUse printStackPageListInUse readableFormat: readImageFromFile:HeapSize:StartingAt: setFullScreenFlag: setInterruptKeycode: setInterruptPending: setInterruptCheckChain: setSavedWindowSize: success: validInstructionPointer:inMethod:framePointer:).
"Nice to actually have all the primitives available" requiredList addAll: (self primitiveTable select: [:each| each
isSymbol]).
"InterpreterProxy is the internal analogue of sqVirtualMachine.c,
so make sure to keep all those" InterpreterProxy organization categories do: [:cat | ((cat ~= 'initialize') and: [cat ~= 'private']) ifTrue: [requiredList addAll: (InterpreterProxy organization listAtCategoryNamed: cat)]].
^requiredList!
Item was added:
- ----- Method: StackInterpreter>>addressCouldBeClassObj: (in category
'debug support') -----
- addressCouldBeClassObj: maybeClassObj
"Answer if maybeClassObj looks like a class object"
<inline: false>
^(objectMemory addressCouldBeObj: maybeClassObj)
and: [((objectMemory isPointersNonInt: maybeClassObj) and:
[(objectMemory lengthOf: maybeClassObj) >= 3])
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: SuperclassIndex ofObject: maybeClassObj))
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: MethodDictionaryIndex ofObject: maybeClassObj))
and: [(objectMemory isIntegerObject: (objectMemory fetchPointer:
InstanceSpecificationIndex ofObject: maybeClassObj))]]]]!
Item was added:
- ----- Method: StackInterpreter>>findClassContainingMethod:startingAt:
(in category 'debug support') -----
- findClassContainingMethod: meth startingAt: classObj
| currClass classDict classDictSize methodArray i |
currClass := classObj.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method: StackInterpreter>>findClassOfMethod:forReceiver: (in category 'debug support') ----- findClassOfMethod: meth forReceiver: rcvr
| rclass |
(objectMemory addressCouldBeOop: rcvr) ifTrue:
[rclass := objectMemory fetchClassOf: rcvr.
(self addressCouldBeClassObj: rclass) ifTrue:
[rclass := self findClassContainingMethod: meth
startingAt: rclass.
rclass ~= objectMemory nilObject ifTrue:
[^rclass]]].
| rclass currClass classDict classDictSize methodArray i | (objectMemory addressCouldBeObj: meth) ifFalse: [^objectMemory nilObject].
^self findClassContainingMethod: meth startingAt: (self
methodClassOf: meth)!
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [rclass := objectMemory fetchClassOf: rcvr]
ifFalse: [rclass := self methodClassOf: meth].
currClass := rclass.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^rclass "method not found in superclass chain"!
Item was added:
- ----- Method: StackInterpreter>>findSelectorOfMethod: (in category
'debug support') -----
- findSelectorOfMethod: meth
| classObj classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
classObj := self methodClassOf: meth.
(self addressCouldBeClassObj: classObj) ifTrue:
[classDict := objectMemory fetchPointer:
MethodDictionaryIndex ofObject: classObj.
classDictSize := objectMemory fetchWordLengthOf:
classDict.
methodArray := objectMemory fetchPointer:
MethodArrayIndex ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i +
SelectorStart ofObject: classDict)].
i := i + 1]].
^objectMemory nilObject!
Item was removed:
- ----- Method: StackInterpreter>>findSelectorOfMethod:forReceiver: (in
category 'debug support') -----
- findSelectorOfMethod: meth forReceiver: rcvr
| currClass classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [currClass := objectMemory fetchClassOf: rcvr]
ifFalse: [currClass := self methodClassOf: meth].
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i + SelectorStart
ofObject: classDict)].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method: StackInterpreter>>printActivationNameFor:receiver:isBlock:firstTemporary: (in category 'debug printing') ----- printActivationNameFor: aMethod receiver: anObject isBlock: isBlock firstTemporary: maybeMessage
| methClass methodSel classObj |
| methClass methodSel | <inline: false> isBlock ifTrue: [self print: '[] in ']. methClass := self findClassOfMethod: aMethod forReceiver:
anObject.
methodSel := self findSelectorOfMethod: aMethod.
((objectMemory addressCouldBeOop: anObject)
and: [self addressCouldBeClassObj: (classObj := objectMemory
fetchClassOf: anObject)])
methodSel := self findSelectorOfMethod: aMethod forReceiver:
anObject.
(objectMemory addressCouldBeOop: anObject) ifTrue:
[classObj = methClass
[(objectMemory fetchClassOf: anObject) = methClass ifTrue: [self printNameOfClass: methClass
count: 5] ifFalse:
[self printNameOfClass: classObj
count: 5.
[self printNameOfClass:
(objectMemory fetchClassOf: anObject) count: 5. self print: '('. self printNameOfClass: methClass count: 5. self print: ')']] ifFalse: [self print: 'INVALID RECEIVER']. self print: '>'. (objectMemory addressCouldBeOop: methodSel) ifTrue: [methodSel = objectMemory nilObject ifTrue: [self print: '?'] ifFalse: [self printStringOf: methodSel]] ifFalse: [self print: 'INVALID SELECTOR']. (methodSel = (objectMemory splObj: SelectorDoesNotUnderstand) and: [(objectMemory addressCouldBeObj: maybeMessage) and: [(objectMemory fetchClassOf: maybeMessage) = (objectMemory splObj: ClassMessage)]]) ifTrue: ["print arg message selector" methodSel := objectMemory fetchPointer: MessageSelectorIndex ofObject: maybeMessage. self print: ' '. self printStringOf: methodSel]!
Item was changed: ----- Method: StackInterpreter>>selectorOfContext: (in category 'debug printing') ----- selectorOfContext: aContext (objectMemory isContext: aContext) ifFalse: [^nil].
^self findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)!
^self
findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)
forReceiver: (objectMemory fetchPointer: ReceiverIndex
ofObject: aContext)!
-- best, Eliot
-- Best regards, Igor Stasenko.
Yes, I always wanted to ask what oops signed-ness was good for? IMO, they could simply be declared usqInt.
Nicolas
2013/4/4 Esteban Lorenzano estebanlm@gmail.com
oh, well... I think I have a 100% reproducible case, which is already something :)
anyway, I will integrate your changes tomorrow or monday :)
cheers, Esteban
On Apr 4, 2013, at 1:37 AM, Igor Stasenko siguctua@gmail.com wrote:
On 4 April 2013 00:37, Eliot Miranda eliot.miranda@gmail.com wrote:
Guys, please integrate this asap. This is a horrible bug that is
probably
causing all sorts of crashes in large images on linux, and should have
been
generally causing horrible crashes all over the place. Bugs are good at lurking :-/.
Glad we have less and less of them. Thanks for your effort, Eliot!
I am currently at some remote place in Switzerland ;) , and cannot do much right now.. We're also have an interesting bug with pharo VM which (i guess) related to some stack (mis)balancing, we have a reproducible case where running code given you
SmallInteger>>DNU...
because some SmallInteger pops up on the stack at some point. At least it doesn't causing VM crash. But i had no time to investigate that. Esteban, do you having any new details on that?
On Wed, Apr 3, 2013 at 3:27 PM, commits@source.squeak.org wrote:
Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.281.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.281 Author: eem Time: 3 April 2013, 3:27:02.058 pm UUID: 64be55df-6421-4087-a712-5c07419806c7 Ancestors: VMMaker.oscog-eem.280
Cogit: Fix *HORRIBLE* yet ancient bug with the CogObjectRep. Both CogObjectRepresentationForSqueakV3>>couldBeObject: & CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: used signed comparisons for oops and so once the heap size pushes oops into the upper half of the address space constant oops in machine code were no longer being updated by the GC.
StackInterpreter: reqrite the login for printing methods so that printing the frame of a bad receiver won't seg fault.
=============== Diff against VMMaker.oscog-eem.280 ===============
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>couldBeObject: (in category 'garbage collection') ----- couldBeObject: oop ^(objectMemory isNonIntegerObject: oop)
and: [self oop: oop isGreaterThanOrEqualTo: objectMemory
nilObject]!
and: [oop asUnsignedInteger >= objectMemory nilObject]!
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: (in category 'garbage collection') ----- shouldAnnotateObjectReference: anOop "self assert: ((objectMemory isIntegerObject: anOop) or: [objectMemory addressCouldBeObj: anOop])." ^(objectMemory isNonIntegerObject: anOop)
and: [self oop: anOop isGreaterThan: objectMemory
trueObject]!
and: [anOop > objectMemory trueObject]!
Item was changed: ----- Method: StackInterpreter class>>requiredMethodNames (in category 'translation') ----- requiredMethodNames "return the list of method names that should be retained for export or other support reasons" | requiredList | requiredList := self exportAPISelectors. requiredList addAll: NewObjectMemory requiredMethodNames. "A number of methods required by VM support code, jitter,
specific
platforms etc" requiredList addAll: #( assertValidExecutionPointe:r:s: characterForAscii: checkedLongAt: delayExpired
findClassOfMethod:forReceiver: findSelectorOfMethod:
findClassOfMethod:forReceiver:
findSelectorOfMethod:forReceiver: forceInterruptCheck forceInterruptCheckFromHeartbeat fullDisplayUpdate getCurrentBytecode getFullScreenFlag getInterruptKeycode getInterruptPending getSavedWindowSize getThisSessionID highBit: interpret loadInitialContext oopFromChunk: primitiveFail primitiveFailFor: primitiveFlushExternalPrimitives printAllStacks printCallStack
printContext:
printExternalHeadFrame printFramesInPage:
printFrame: printHeadFrame printMemory printOop: printStackPages printStackPageList printStackPagesInUse printStackPageListInUse readableFormat: readImageFromFile:HeapSize:StartingAt: setFullScreenFlag: setInterruptKeycode: setInterruptPending: setInterruptCheckChain: setSavedWindowSize: success: validInstructionPointer:inMethod:framePointer:).
"Nice to actually have all the primitives available" requiredList addAll: (self primitiveTable select: [:each| each
isSymbol]).
"InterpreterProxy is the internal analogue of
sqVirtualMachine.c,
so make sure to keep all those" InterpreterProxy organization categories do: [:cat | ((cat ~= 'initialize') and: [cat ~= 'private']) ifTrue: [requiredList addAll: (InterpreterProxy organization listAtCategoryNamed: cat)]].
^requiredList!
Item was added:
- ----- Method: StackInterpreter>>addressCouldBeClassObj: (in category
'debug support') -----
- addressCouldBeClassObj: maybeClassObj
"Answer if maybeClassObj looks like a class object"
<inline: false>
^(objectMemory addressCouldBeObj: maybeClassObj)
and: [((objectMemory isPointersNonInt: maybeClassObj) and:
[(objectMemory lengthOf: maybeClassObj) >= 3])
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: SuperclassIndex ofObject: maybeClassObj))
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: MethodDictionaryIndex ofObject: maybeClassObj))
and: [(objectMemory isIntegerObject: (objectMemory
fetchPointer:
InstanceSpecificationIndex ofObject: maybeClassObj))]]]]!
Item was added:
- ----- Method: StackInterpreter>>findClassContainingMethod:startingAt:
(in category 'debug support') -----
- findClassContainingMethod: meth startingAt: classObj
| currClass classDict classDictSize methodArray i |
currClass := classObj.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method: StackInterpreter>>findClassOfMethod:forReceiver: (in category 'debug support') ----- findClassOfMethod: meth forReceiver: rcvr
| rclass |
(objectMemory addressCouldBeOop: rcvr) ifTrue:
[rclass := objectMemory fetchClassOf: rcvr.
(self addressCouldBeClassObj: rclass) ifTrue:
[rclass := self findClassContainingMethod: meth
startingAt: rclass.
rclass ~= objectMemory nilObject ifTrue:
[^rclass]]].
| rclass currClass classDict classDictSize methodArray i | (objectMemory addressCouldBeObj: meth) ifFalse: [^objectMemory nilObject].
^self findClassContainingMethod: meth startingAt: (self
methodClassOf: meth)!
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [rclass := objectMemory fetchClassOf: rcvr]
ifFalse: [rclass := self methodClassOf: meth].
currClass := rclass.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^rclass "method not found in superclass chain"!
Item was added:
- ----- Method: StackInterpreter>>findSelectorOfMethod: (in category
'debug support') -----
- findSelectorOfMethod: meth
| classObj classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
classObj := self methodClassOf: meth.
(self addressCouldBeClassObj: classObj) ifTrue:
[classDict := objectMemory fetchPointer:
MethodDictionaryIndex ofObject: classObj.
classDictSize := objectMemory fetchWordLengthOf:
classDict.
methodArray := objectMemory fetchPointer:
MethodArrayIndex ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i +
SelectorStart ofObject: classDict)].
i := i + 1]].
^objectMemory nilObject!
Item was removed:
- ----- Method: StackInterpreter>>findSelectorOfMethod:forReceiver: (in
category 'debug support') -----
- findSelectorOfMethod: meth forReceiver: rcvr
| currClass classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [currClass := objectMemory fetchClassOf: rcvr]
ifFalse: [currClass := self methodClassOf: meth].
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i + SelectorStart
ofObject: classDict)].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method:
StackInterpreter>>printActivationNameFor:receiver:isBlock:firstTemporary:
(in category 'debug printing') ----- printActivationNameFor: aMethod receiver: anObject isBlock: isBlock firstTemporary: maybeMessage
| methClass methodSel classObj |
| methClass methodSel | <inline: false> isBlock ifTrue: [self print: '[] in ']. methClass := self findClassOfMethod: aMethod forReceiver:
anObject.
methodSel := self findSelectorOfMethod: aMethod.
((objectMemory addressCouldBeOop: anObject)
and: [self addressCouldBeClassObj: (classObj := objectMemory
fetchClassOf: anObject)])
methodSel := self findSelectorOfMethod: aMethod forReceiver:
anObject.
(objectMemory addressCouldBeOop: anObject) ifTrue:
[classObj = methClass
[(objectMemory fetchClassOf: anObject) =
methClass
ifTrue: [self printNameOfClass:
methClass
count: 5] ifFalse:
[self printNameOfClass:
classObj
count: 5.
[self printNameOfClass:
(objectMemory fetchClassOf: anObject) count: 5. self print: '('. self printNameOfClass:
methClass
count: 5. self print: ')']] ifFalse: [self print: 'INVALID RECEIVER']. self print: '>'. (objectMemory addressCouldBeOop: methodSel) ifTrue: [methodSel = objectMemory nilObject ifTrue: [self print: '?'] ifFalse: [self printStringOf:
methodSel]]
ifFalse: [self print: 'INVALID SELECTOR']. (methodSel = (objectMemory splObj: SelectorDoesNotUnderstand) and: [(objectMemory addressCouldBeObj: maybeMessage) and: [(objectMemory fetchClassOf: maybeMessage) = (objectMemory
splObj: ClassMessage)]]) ifTrue: ["print arg message selector" methodSel := objectMemory fetchPointer: MessageSelectorIndex ofObject: maybeMessage. self print: ' '. self printStringOf: methodSel]!
Item was changed: ----- Method: StackInterpreter>>selectorOfContext: (in category 'debug printing') ----- selectorOfContext: aContext (objectMemory isContext: aContext) ifFalse: [^nil].
^self findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)!
^self
findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)
forReceiver: (objectMemory fetchPointer: ReceiverIndex
ofObject: aContext)!
-- best, Eliot
-- Best regards, Igor Stasenko.
On Thu, Apr 4, 2013 at 3:17 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Yes, I always wanted to ask what oops signed-ness was good for? IMO, they could simply be declared usqInt.
+10 raisedTo: SmallInteger maxVal. But the milk is already spilt :)
I'm glad you said that. I'm reminded of House of Cards. "You might think so but I couldn't possibly comment." ;)
It might be worth-while trying to make this change and fixing the very few places where signedness is important (the SmalInteger arithmetic primitives).
Nicolas
2013/4/4 Esteban Lorenzano estebanlm@gmail.com
oh, well... I think I have a 100% reproducible case, which is already something :)
anyway, I will integrate your changes tomorrow or monday :)
cheers, Esteban
On Apr 4, 2013, at 1:37 AM, Igor Stasenko siguctua@gmail.com wrote:
On 4 April 2013 00:37, Eliot Miranda eliot.miranda@gmail.com wrote:
Guys, please integrate this asap. This is a horrible bug that is
probably
causing all sorts of crashes in large images on linux, and should have
been
generally causing horrible crashes all over the place. Bugs are good
at
lurking :-/.
Glad we have less and less of them. Thanks for your effort, Eliot!
I am currently at some remote place in Switzerland ;) , and cannot do much right now.. We're also have an interesting bug with pharo VM which (i guess) related to some stack (mis)balancing, we have a reproducible case where running code given you
SmallInteger>>DNU...
because some SmallInteger pops up on the stack at some point. At least it doesn't causing VM crash. But i had no time to investigate that. Esteban, do you having any new details on that?
On Wed, Apr 3, 2013 at 3:27 PM, commits@source.squeak.org wrote:
Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.281.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.281 Author: eem Time: 3 April 2013, 3:27:02.058 pm UUID: 64be55df-6421-4087-a712-5c07419806c7 Ancestors: VMMaker.oscog-eem.280
Cogit: Fix *HORRIBLE* yet ancient bug with the CogObjectRep. Both CogObjectRepresentationForSqueakV3>>couldBeObject: & CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: used signed comparisons for oops and so once the heap size pushes oops into the upper half of the address space constant oops in machine code were no longer being updated by the GC.
StackInterpreter: reqrite the login for printing methods so that printing the frame of a bad receiver won't seg fault.
=============== Diff against VMMaker.oscog-eem.280 ===============
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>couldBeObject: (in category 'garbage collection') ----- couldBeObject: oop ^(objectMemory isNonIntegerObject: oop)
and: [self oop: oop isGreaterThanOrEqualTo: objectMemory
nilObject]!
and: [oop asUnsignedInteger >= objectMemory nilObject]!
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: (in category 'garbage collection') ----- shouldAnnotateObjectReference: anOop "self assert: ((objectMemory isIntegerObject: anOop) or: [objectMemory addressCouldBeObj: anOop])." ^(objectMemory isNonIntegerObject: anOop)
and: [self oop: anOop isGreaterThan: objectMemory
trueObject]!
and: [anOop > objectMemory trueObject]!
Item was changed: ----- Method: StackInterpreter class>>requiredMethodNames (in
category
'translation') ----- requiredMethodNames "return the list of method names that should be retained for export or other support reasons" | requiredList | requiredList := self exportAPISelectors. requiredList addAll: NewObjectMemory requiredMethodNames. "A number of methods required by VM support code, jitter,
specific
platforms etc" requiredList addAll: #( assertValidExecutionPointe:r:s: characterForAscii: checkedLongAt: delayExpired
findClassOfMethod:forReceiver: findSelectorOfMethod:
findClassOfMethod:forReceiver:
findSelectorOfMethod:forReceiver: forceInterruptCheck forceInterruptCheckFromHeartbeat fullDisplayUpdate getCurrentBytecode getFullScreenFlag
getInterruptKeycode
getInterruptPending getSavedWindowSize getThisSessionID highBit: interpret loadInitialContext oopFromChunk: primitiveFail primitiveFailFor: primitiveFlushExternalPrimitives printAllStacks printCallStack
printContext:
printExternalHeadFrame printFramesInPage:
printFrame: printHeadFrame printMemory printOop: printStackPages printStackPageList printStackPagesInUse printStackPageListInUse readableFormat: readImageFromFile:HeapSize:StartingAt: setFullScreenFlag: setInterruptKeycode: setInterruptPending: setInterruptCheckChain: setSavedWindowSize: success: validInstructionPointer:inMethod:framePointer:).
"Nice to actually have all the primitives available" requiredList addAll: (self primitiveTable select: [:each| each
isSymbol]).
"InterpreterProxy is the internal analogue of
sqVirtualMachine.c,
so make sure to keep all those" InterpreterProxy organization categories do: [:cat | ((cat ~= 'initialize') and: [cat ~= 'private']) ifTrue: [requiredList addAll: (InterpreterProxy organization listAtCategoryNamed: cat)]].
^requiredList!
Item was added:
- ----- Method: StackInterpreter>>addressCouldBeClassObj: (in category
'debug support') -----
- addressCouldBeClassObj: maybeClassObj
"Answer if maybeClassObj looks like a class object"
<inline: false>
^(objectMemory addressCouldBeObj: maybeClassObj)
and: [((objectMemory isPointersNonInt: maybeClassObj) and:
[(objectMemory lengthOf: maybeClassObj) >= 3])
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: SuperclassIndex ofObject: maybeClassObj))
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: MethodDictionaryIndex ofObject: maybeClassObj))
and: [(objectMemory isIntegerObject: (objectMemory
fetchPointer:
InstanceSpecificationIndex ofObject: maybeClassObj))]]]]!
Item was added:
- ----- Method:
StackInterpreter>>findClassContainingMethod:startingAt:
(in category 'debug support') -----
- findClassContainingMethod: meth startingAt: classObj
| currClass classDict classDictSize methodArray i |
currClass := classObj.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass
chain"!
Item was changed: ----- Method: StackInterpreter>>findClassOfMethod:forReceiver: (in category 'debug support') ----- findClassOfMethod: meth forReceiver: rcvr
| rclass |
(objectMemory addressCouldBeOop: rcvr) ifTrue:
[rclass := objectMemory fetchClassOf: rcvr.
(self addressCouldBeClassObj: rclass) ifTrue:
[rclass := self findClassContainingMethod:
meth
startingAt: rclass.
rclass ~= objectMemory nilObject ifTrue:
[^rclass]]].
| rclass currClass classDict classDictSize methodArray i | (objectMemory addressCouldBeObj: meth) ifFalse: [^objectMemory nilObject].
^self findClassContainingMethod: meth startingAt: (self
methodClassOf: meth)!
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [rclass := objectMemory fetchClassOf: rcvr]
ifFalse: [rclass := self methodClassOf: meth].
currClass := rclass.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^rclass "method not found in superclass chain"!
Item was added:
- ----- Method: StackInterpreter>>findSelectorOfMethod: (in category
'debug support') -----
- findSelectorOfMethod: meth
| classObj classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
classObj := self methodClassOf: meth.
(self addressCouldBeClassObj: classObj) ifTrue:
[classDict := objectMemory fetchPointer:
MethodDictionaryIndex ofObject: classObj.
classDictSize := objectMemory fetchWordLengthOf:
classDict.
methodArray := objectMemory fetchPointer:
MethodArrayIndex ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i
ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i +
SelectorStart ofObject: classDict)].
i := i + 1]].
^objectMemory nilObject!
Item was removed:
- ----- Method: StackInterpreter>>findSelectorOfMethod:forReceiver:
(in
category 'debug support') -----
- findSelectorOfMethod: meth forReceiver: rcvr
| currClass classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [currClass := objectMemory fetchClassOf: rcvr]
ifFalse: [currClass := self methodClassOf: meth].
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i +
SelectorStart
ofObject: classDict)].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method:
StackInterpreter>>printActivationNameFor:receiver:isBlock:firstTemporary:
(in category 'debug printing') ----- printActivationNameFor: aMethod receiver: anObject isBlock: isBlock firstTemporary: maybeMessage
| methClass methodSel classObj |
| methClass methodSel | <inline: false> isBlock ifTrue: [self print: '[] in ']. methClass := self findClassOfMethod: aMethod forReceiver:
anObject.
methodSel := self findSelectorOfMethod: aMethod.
((objectMemory addressCouldBeOop: anObject)
and: [self addressCouldBeClassObj: (classObj := objectMemory
fetchClassOf: anObject)])
methodSel := self findSelectorOfMethod: aMethod forReceiver:
anObject.
(objectMemory addressCouldBeOop: anObject) ifTrue:
[classObj = methClass
[(objectMemory fetchClassOf: anObject) =
methClass
ifTrue: [self printNameOfClass:
methClass
count: 5] ifFalse:
[self printNameOfClass:
classObj
count: 5.
[self printNameOfClass:
(objectMemory fetchClassOf: anObject) count: 5. self print: '('. self printNameOfClass:
methClass
count: 5. self print: ')']] ifFalse: [self print: 'INVALID RECEIVER']. self print: '>'. (objectMemory addressCouldBeOop: methodSel) ifTrue: [methodSel = objectMemory nilObject ifTrue: [self print: '?'] ifFalse: [self printStringOf:
methodSel]]
ifFalse: [self print: 'INVALID SELECTOR']. (methodSel = (objectMemory splObj: SelectorDoesNotUnderstand) and: [(objectMemory addressCouldBeObj: maybeMessage) and: [(objectMemory fetchClassOf: maybeMessage) = (objectMemory
splObj: ClassMessage)]]) ifTrue: ["print arg message selector" methodSel := objectMemory fetchPointer: MessageSelectorIndex ofObject: maybeMessage. self print: ' '. self printStringOf: methodSel]!
Item was changed: ----- Method: StackInterpreter>>selectorOfContext: (in category
'debug
printing') ----- selectorOfContext: aContext (objectMemory isContext: aContext) ifFalse: [^nil].
^self findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)!
^self
findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)
forReceiver: (objectMemory fetchPointer:
ReceiverIndex
ofObject: aContext)!
-- best, Eliot
-- Best regards, Igor Stasenko.
On 04.04.2013, at 13:25, Eliot Miranda eliot.miranda@gmail.com wrote:
On Thu, Apr 4, 2013 at 3:17 AM, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
Yes, I always wanted to ask what oops signed-ness was good for?
An undeclared variable in C has the type "int". So in theory you could leave out pretty much all type declarations in the generated code, making it more readable.
(Not sure if that was actually the reason. Likely the original implementers were not aware of the dangers of signed vs unsigned in C)
- Bert -
IMO, they could simply be declared usqInt.
+10 raisedTo: SmallInteger maxVal. But the milk is already spilt :)
I'm glad you said that. I'm reminded of House of Cards. "You might think so but I couldn't possibly comment." ;)
It might be worth-while trying to make this change and fixing the very few places where signedness is important (the SmalInteger arithmetic primitives).
Nicolas
2013/4/4 Esteban Lorenzano estebanlm@gmail.com
oh, well... I think I have a 100% reproducible case, which is already something :)
anyway, I will integrate your changes tomorrow or monday :)
cheers, Esteban
On Apr 4, 2013, at 1:37 AM, Igor Stasenko siguctua@gmail.com wrote:
On 4 April 2013 00:37, Eliot Miranda eliot.miranda@gmail.com wrote:
Guys, please integrate this asap. This is a horrible bug that is probably causing all sorts of crashes in large images on linux, and should have been generally causing horrible crashes all over the place. Bugs are good at lurking :-/.
Glad we have less and less of them. Thanks for your effort, Eliot!
I am currently at some remote place in Switzerland ;) , and cannot do much right now.. We're also have an interesting bug with pharo VM which (i guess) related to some stack (mis)balancing, we have a reproducible case where running code given you SmallInteger>>DNU... because some SmallInteger pops up on the stack at some point. At least it doesn't causing VM crash. But i had no time to investigate that. Esteban, do you having any new details on that?
On Wed, Apr 3, 2013 at 3:27 PM, commits@source.squeak.org wrote:
Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.281.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.281 Author: eem Time: 3 April 2013, 3:27:02.058 pm UUID: 64be55df-6421-4087-a712-5c07419806c7 Ancestors: VMMaker.oscog-eem.280
Cogit: Fix *HORRIBLE* yet ancient bug with the CogObjectRep. Both CogObjectRepresentationForSqueakV3>>couldBeObject: & CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: used signed comparisons for oops and so once the heap size pushes oops into the upper half of the address space constant oops in machine code were no longer being updated by the GC.
StackInterpreter: reqrite the login for printing methods so that printing the frame of a bad receiver won't seg fault.
=============== Diff against VMMaker.oscog-eem.280 ===============
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>couldBeObject: (in category 'garbage collection') ----- couldBeObject: oop ^(objectMemory isNonIntegerObject: oop)
and: [self oop: oop isGreaterThanOrEqualTo: objectMemory
nilObject]!
and: [oop asUnsignedInteger >= objectMemory nilObject]!
Item was changed: ----- Method: CogObjectRepresentationForSqueakV3>>shouldAnnotateObjectReference: (in category 'garbage collection') ----- shouldAnnotateObjectReference: anOop "self assert: ((objectMemory isIntegerObject: anOop) or: [objectMemory addressCouldBeObj: anOop])." ^(objectMemory isNonIntegerObject: anOop)
and: [self oop: anOop isGreaterThan: objectMemory trueObject]!
and: [anOop > objectMemory trueObject]!
Item was changed: ----- Method: StackInterpreter class>>requiredMethodNames (in category 'translation') ----- requiredMethodNames "return the list of method names that should be retained for export or other support reasons" | requiredList | requiredList := self exportAPISelectors. requiredList addAll: NewObjectMemory requiredMethodNames. "A number of methods required by VM support code, jitter, specific platforms etc" requiredList addAll: #( assertValidExecutionPointe:r:s: characterForAscii: checkedLongAt: delayExpired
findClassOfMethod:forReceiver: findSelectorOfMethod:
findClassOfMethod:forReceiver:
findSelectorOfMethod:forReceiver: forceInterruptCheck forceInterruptCheckFromHeartbeat fullDisplayUpdate getCurrentBytecode getFullScreenFlag getInterruptKeycode getInterruptPending getSavedWindowSize getThisSessionID highBit: interpret loadInitialContext oopFromChunk: primitiveFail primitiveFailFor: primitiveFlushExternalPrimitives printAllStacks printCallStack printContext: printExternalHeadFrame printFramesInPage: printFrame: printHeadFrame printMemory printOop: printStackPages printStackPageList printStackPagesInUse printStackPageListInUse readableFormat: readImageFromFile:HeapSize:StartingAt: setFullScreenFlag: setInterruptKeycode: setInterruptPending: setInterruptCheckChain: setSavedWindowSize: success: validInstructionPointer:inMethod:framePointer:).
"Nice to actually have all the primitives available" requiredList addAll: (self primitiveTable select: [:each| each
isSymbol]).
"InterpreterProxy is the internal analogue of sqVirtualMachine.c,
so make sure to keep all those" InterpreterProxy organization categories do: [:cat | ((cat ~= 'initialize') and: [cat ~= 'private']) ifTrue: [requiredList addAll: (InterpreterProxy organization listAtCategoryNamed: cat)]].
^requiredList!
Item was added:
- ----- Method: StackInterpreter>>addressCouldBeClassObj: (in category
'debug support') -----
- addressCouldBeClassObj: maybeClassObj
"Answer if maybeClassObj looks like a class object"
<inline: false>
^(objectMemory addressCouldBeObj: maybeClassObj)
and: [((objectMemory isPointersNonInt: maybeClassObj) and:
[(objectMemory lengthOf: maybeClassObj) >= 3])
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: SuperclassIndex ofObject: maybeClassObj))
and: [(objectMemory isPointersNonInt: (objectMemory
fetchPointer: MethodDictionaryIndex ofObject: maybeClassObj))
and: [(objectMemory isIntegerObject: (objectMemory fetchPointer:
InstanceSpecificationIndex ofObject: maybeClassObj))]]]]!
Item was added:
- ----- Method: StackInterpreter>>findClassContainingMethod:startingAt:
(in category 'debug support') -----
- findClassContainingMethod: meth startingAt: classObj
| currClass classDict classDictSize methodArray i |
currClass := classObj.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method: StackInterpreter>>findClassOfMethod:forReceiver: (in category 'debug support') ----- findClassOfMethod: meth forReceiver: rcvr
| rclass |
(objectMemory addressCouldBeOop: rcvr) ifTrue:
[rclass := objectMemory fetchClassOf: rcvr.
(self addressCouldBeClassObj: rclass) ifTrue:
[rclass := self findClassContainingMethod: meth
startingAt: rclass.
rclass ~= objectMemory nilObject ifTrue:
[^rclass]]].
| rclass currClass classDict classDictSize methodArray i | (objectMemory addressCouldBeObj: meth) ifFalse: [^objectMemory nilObject].
^self findClassContainingMethod: meth startingAt: (self
methodClassOf: meth)!
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [rclass := objectMemory fetchClassOf: rcvr]
ifFalse: [rclass := self methodClassOf: meth].
currClass := rclass.
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i < (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^currClass].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^rclass "method not found in superclass chain"!
Item was added:
- ----- Method: StackInterpreter>>findSelectorOfMethod: (in category
'debug support') -----
- findSelectorOfMethod: meth
| classObj classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
classObj := self methodClassOf: meth.
(self addressCouldBeClassObj: classObj) ifTrue:
[classDict := objectMemory fetchPointer:
MethodDictionaryIndex ofObject: classObj.
classDictSize := objectMemory fetchWordLengthOf:
classDict.
methodArray := objectMemory fetchPointer:
MethodArrayIndex ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i +
SelectorStart ofObject: classDict)].
i := i + 1]].
^objectMemory nilObject!
Item was removed:
- ----- Method: StackInterpreter>>findSelectorOfMethod:forReceiver: (in
category 'debug support') -----
- findSelectorOfMethod: meth forReceiver: rcvr
| currClass classDict classDictSize methodArray i |
(objectMemory addressCouldBeObj: meth) ifFalse:
[^objectMemory nilObject].
(objectMemory addressCouldBeOop: rcvr)
ifTrue: [currClass := objectMemory fetchClassOf: rcvr]
ifFalse: [currClass := self methodClassOf: meth].
[classDict := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currClass.
classDictSize := objectMemory fetchWordLengthOf: classDict.
methodArray := objectMemory fetchPointer: MethodArrayIndex
ofObject: classDict.
i := 0.
[i <= (classDictSize - SelectorStart)] whileTrue:
[meth = (objectMemory fetchPointer: i ofObject:
methodArray) ifTrue:
[^(objectMemory fetchPointer: i + SelectorStart
ofObject: classDict)].
i := i + 1].
currClass := self superclassOf: currClass.
currClass = objectMemory nilObject] whileFalse.
^currClass "method not found in superclass chain"!
Item was changed: ----- Method: StackInterpreter>>printActivationNameFor:receiver:isBlock:firstTemporary: (in category 'debug printing') ----- printActivationNameFor: aMethod receiver: anObject isBlock: isBlock firstTemporary: maybeMessage
| methClass methodSel classObj |
| methClass methodSel | <inline: false> isBlock ifTrue: [self print: '[] in ']. methClass := self findClassOfMethod: aMethod forReceiver:
anObject.
methodSel := self findSelectorOfMethod: aMethod.
((objectMemory addressCouldBeOop: anObject)
and: [self addressCouldBeClassObj: (classObj := objectMemory
fetchClassOf: anObject)])
methodSel := self findSelectorOfMethod: aMethod forReceiver:
anObject.
(objectMemory addressCouldBeOop: anObject) ifTrue:
[classObj = methClass
[(objectMemory fetchClassOf: anObject) = methClass ifTrue: [self printNameOfClass: methClass
count: 5] ifFalse:
[self printNameOfClass: classObj
count: 5.
[self printNameOfClass:
(objectMemory fetchClassOf: anObject) count: 5. self print: '('. self printNameOfClass: methClass count: 5. self print: ')']] ifFalse: [self print: 'INVALID RECEIVER']. self print: '>'. (objectMemory addressCouldBeOop: methodSel) ifTrue: [methodSel = objectMemory nilObject ifTrue: [self print: '?'] ifFalse: [self printStringOf: methodSel]] ifFalse: [self print: 'INVALID SELECTOR']. (methodSel = (objectMemory splObj: SelectorDoesNotUnderstand) and: [(objectMemory addressCouldBeObj: maybeMessage) and: [(objectMemory fetchClassOf: maybeMessage) = (objectMemory splObj: ClassMessage)]]) ifTrue: ["print arg message selector" methodSel := objectMemory fetchPointer: MessageSelectorIndex ofObject: maybeMessage. self print: ' '. self printStringOf: methodSel]!
Item was changed: ----- Method: StackInterpreter>>selectorOfContext: (in category 'debug printing') ----- selectorOfContext: aContext (objectMemory isContext: aContext) ifFalse: [^nil].
^self findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)!
^self
findSelectorOfMethod: (objectMemory fetchPointer:
MethodIndex ofObject: aContext)
forReceiver: (objectMemory fetchPointer: ReceiverIndex
ofObject: aContext)!
-- best, Eliot
-- Best regards, Igor Stasenko.
-- best, Eliot
On Thu, Apr 04, 2013 at 01:35:55PM -0700, Bert Freudenberg wrote:
On 04.04.2013, at 13:25, Eliot Miranda eliot.miranda@gmail.com wrote:
On Thu, Apr 4, 2013 at 3:17 AM, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
Yes, I always wanted to ask what oops signed-ness was good for?
An undeclared variable in C has the type "int". So in theory you could leave out pretty much all type declarations in the generated code, making it more readable.
(Not sure if that was actually the reason. Likely the original implementers were not aware of the dangers of signed vs unsigned in C)
- Bert -
You are probably right that it was just a default data type.
As far as the dangers of signed vs unsigned, my guess is that the issue was simply of no practical consequence at the time. I was not there to witness it, but I imagine Dan Ingalls developing the Squeak VM in a flash of creative inspiration over a very short period of time. The target machines had 32-bit integers and pointers, and large object memories would not have been an realistic concern. There would have been no reason to put a lot of time and energy into worrying about the issue back then.
Dave
On Thu, Apr 04, 2013 at 01:25:10PM -0700, Eliot Miranda wrote:
On Thu, Apr 4, 2013 at 3:17 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Yes, I always wanted to ask what oops signed-ness was good for? IMO, they could simply be declared usqInt.
+10 raisedTo: SmallInteger maxVal. But the milk is already spilt :)
I'm glad you said that. I'm reminded of House of Cards. "You might think so but I couldn't possibly comment." ;)
It might be worth-while trying to make this change and fixing the very few places where signedness is important (the SmalInteger arithmetic primitives).
IMO an object pointer should be declared sqOop to clearly distinguish it from some something that is intended to be used as an integer. And a (32- or 64-bit) location in the object memory should have its own type declaration that would just coincidentally be the same size as a sqOop in the current implementations. And maybe there should be one more type definition to represent the 32-bit words in an indexable object.
Dave
On Thu, Apr 4, 2013 at 5:19 PM, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Apr 04, 2013 at 01:25:10PM -0700, Eliot Miranda wrote:
On Thu, Apr 4, 2013 at 3:17 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Yes, I always wanted to ask what oops signed-ness was good for? IMO, they could simply be declared usqInt.
+10 raisedTo: SmallInteger maxVal. But the milk is already spilt :)
I'm glad you said that. I'm reminded of House of Cards. "You might
think
so but I couldn't possibly comment." ;)
It might be worth-while trying to make this change and fixing the very
few
places where signedness is important (the SmalInteger arithmetic primitives).
IMO an object pointer should be declared sqOop to clearly distinguish it from some something that is intended to be used as an integer.
OK, but is sqOop a void pointer or what? void pointers are ok except that they have to be cast all the time. char * is poor; too easily confused with other pointers. sqObj * (where sqObj is some opaque struct) is good. Integral types are easy to deal with. But signedness is the major thing to avoid. SO either unsigned or pointer. But which?
And a (32- or 64-bit) location in the object memory should have its own type declaration that would just coincidentally be the same size as a sqOop in the current implementations. And maybe there should be one more type definition to represent the 32-bit words in an indexable object.
Dave
On Sat, Apr 06, 2013 at 05:15:43PM -0700, Eliot Miranda wrote:
On Thu, Apr 4, 2013 at 5:19 PM, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Apr 04, 2013 at 01:25:10PM -0700, Eliot Miranda wrote:
On Thu, Apr 4, 2013 at 3:17 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Yes, I always wanted to ask what oops signed-ness was good for? IMO, they could simply be declared usqInt.
+10 raisedTo: SmallInteger maxVal. But the milk is already spilt :)
I'm glad you said that. I'm reminded of House of Cards. "You might
think
so but I couldn't possibly comment." ;)
It might be worth-while trying to make this change and fixing the very
few
places where signedness is important (the SmalInteger arithmetic primitives).
IMO an object pointer should be declared sqOop to clearly distinguish it from some something that is intended to be used as an integer.
OK, but is sqOop a void pointer or what? void pointers are ok except that they have to be cast all the time. char * is poor; too easily confused with other pointers. sqObj * (where sqObj is some opaque struct) is good. Integral types are easy to deal with. But signedness is the major thing to avoid. SO either unsigned or pointer. But which?
You are missing my point. If someone is going to go to the trouble of properly declaring object pointers, then they may as well use an intention revealing type declaration.
In principle there is no reason that an object pointer should not refer to the primary key in a relational database table (to pick an intentionally rediculous example). But an object pointer is an object pointer, it is not an integer and it is not a C pointer.
In practice, the current use of sqInt to represent object pointers is confusing, but is not a big problem. After all, object memories of over 7 GB work fine with the 64-bit object format (limited by physical memory on my PC as far as I can tell). Although I note with dismay that there seems to be yet another regression here, so I'll need to hunt that down once more :-/
Dave
And a (32- or 64-bit) location in the object memory should have its own type declaration that would just coincidentally be the same size as a sqOop in the current implementations. And maybe there should be one more type definition to represent the 32-bit words in an indexable object.
Dave
-- best, Eliot
On Sat, Apr 06, 2013 at 09:30:11PM -0400, David T. Lewis wrote:
On Sat, Apr 06, 2013 at 05:15:43PM -0700, Eliot Miranda wrote:
On Thu, Apr 4, 2013 at 5:19 PM, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Apr 04, 2013 at 01:25:10PM -0700, Eliot Miranda wrote:
On Thu, Apr 4, 2013 at 3:17 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Yes, I always wanted to ask what oops signed-ness was good for? IMO, they could simply be declared usqInt.
+10 raisedTo: SmallInteger maxVal. But the milk is already spilt :)
I'm glad you said that. I'm reminded of House of Cards. "You might
think
so but I couldn't possibly comment." ;)
It might be worth-while trying to make this change and fixing the very
few
places where signedness is important (the SmalInteger arithmetic primitives).
IMO an object pointer should be declared sqOop to clearly distinguish it from some something that is intended to be used as an integer.
OK, but is sqOop a void pointer or what? void pointers are ok except that they have to be cast all the time. char * is poor; too easily confused with other pointers. sqObj * (where sqObj is some opaque struct) is good. Integral types are easy to deal with. But signedness is the major thing to avoid. SO either unsigned or pointer. But which?
You are missing my point. If someone is going to go to the trouble of properly declaring object pointers, then they may as well use an intention revealing type declaration.
In principle there is no reason that an object pointer should not refer to the primary key in a relational database table (to pick an intentionally rediculous example). But an object pointer is an object pointer, it is not an integer and it is not a C pointer.
In practice, the current use of sqInt to represent object pointers is confusing, but is not a big problem. After all, object memories of over 7 GB work fine with the 64-bit object format (limited by physical memory on my PC as far as I can tell). Although I note with dismay that there seems to be yet another regression here, so I'll need to hunt that down once more :-/
OK, no regression after all, just a few type definitions required in the unix platforms sources (attached, along with SystemReporter stats that show the memory usage).
With an up-to-date Squeak trunk image traced to 64-bit object format (from http://build.squeak.org/job/Squeak%2064-bit%20image/), and running on a Linux PC with 8GB memory, I can allocate large strings until the system bogs down with swapping at an image size of about 7GB. I can also successfully allocate e.g. a 6GB String or ByteArray, although indexing into the array fails due to issues unrelated to object pointer addressing.
Dave
nice! :)
On 15 April 2013 01:15, David T. Lewis lewis@mail.msen.com wrote:
On Sat, Apr 06, 2013 at 09:30:11PM -0400, David T. Lewis wrote:
On Sat, Apr 06, 2013 at 05:15:43PM -0700, Eliot Miranda wrote:
On Thu, Apr 4, 2013 at 5:19 PM, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Apr 04, 2013 at 01:25:10PM -0700, Eliot Miranda wrote:
On Thu, Apr 4, 2013 at 3:17 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Yes, I always wanted to ask what oops signed-ness was good for? IMO, they could simply be declared usqInt.
+10 raisedTo: SmallInteger maxVal. But the milk is already spilt :)
I'm glad you said that. I'm reminded of House of Cards. "You might
think
so but I couldn't possibly comment." ;)
It might be worth-while trying to make this change and fixing the very
few
places where signedness is important (the SmalInteger arithmetic primitives).
IMO an object pointer should be declared sqOop to clearly distinguish it from some something that is intended to be used as an integer.
OK, but is sqOop a void pointer or what? void pointers are ok except that they have to be cast all the time. char * is poor; too easily confused with other pointers. sqObj * (where sqObj is some opaque struct) is good. Integral types are easy to deal with. But signedness is the major thing to avoid. SO either unsigned or pointer. But which?
You are missing my point. If someone is going to go to the trouble of properly declaring object pointers, then they may as well use an intention revealing type declaration.
In principle there is no reason that an object pointer should not refer to the primary key in a relational database table (to pick an intentionally rediculous example). But an object pointer is an object pointer, it is not an integer and it is not a C pointer.
In practice, the current use of sqInt to represent object pointers is confusing, but is not a big problem. After all, object memories of over 7 GB work fine with the 64-bit object format (limited by physical memory on my PC as far as I can tell). Although I note with dismay that there seems to be yet another regression here, so I'll need to hunt that down once more :-/
OK, no regression after all, just a few type definitions required in the unix platforms sources (attached, along with SystemReporter stats that show the memory usage).
With an up-to-date Squeak trunk image traced to 64-bit object format (from http://build.squeak.org/job/Squeak%2064-bit%20image/), and running on a Linux PC with 8GB memory, I can allocate large strings until the system bogs down with swapping at an image size of about 7GB. I can also successfully allocate e.g. a 6GB String or ByteArray, although indexing into the array fails due to issues unrelated to object pointer addressing.
Dave
Pointer to struct seems like the most obvious choice.
- Bert -
On 06.04.2013, at 17:15, Eliot Miranda eliot.miranda@gmail.com wrote:
On Thu, Apr 4, 2013 at 5:19 PM, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Apr 04, 2013 at 01:25:10PM -0700, Eliot Miranda wrote:
On Thu, Apr 4, 2013 at 3:17 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Yes, I always wanted to ask what oops signed-ness was good for? IMO, they could simply be declared usqInt.
+10 raisedTo: SmallInteger maxVal. But the milk is already spilt :)
I'm glad you said that. I'm reminded of House of Cards. "You might think so but I couldn't possibly comment." ;)
It might be worth-while trying to make this change and fixing the very few places where signedness is important (the SmalInteger arithmetic primitives).
IMO an object pointer should be declared sqOop to clearly distinguish it from some something that is intended to be used as an integer.
OK, but is sqOop a void pointer or what? void pointers are ok except that they have to be cast all the time. char * is poor; too easily confused with other pointers. sqObj * (where sqObj is some opaque struct) is good. Integral types are easy to deal with. But signedness is the major thing to avoid. SO either unsigned or pointer. But which?
And a (32- or 64-bit) location in the object memory should have its own type declaration that would just coincidentally be the same size as a sqOop in the current implementations. And maybe there should be one more type definition to represent the 32-bit words in an indexable object.
Dave
-- best, Eliot
vm-dev@lists.squeakfoundation.org