Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.863.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.863 Author: eem Time: 23 August 2014, 5:10:37.802 pm UUID: 379b797e-e115-4d63-b667-6d17ce3230d9 Ancestors: VMMaker.oscog-eem.862
Add an assert to check for a valid mehtodClassAssociation in methods (arguably dubious) to help catch malformed methods in multiple bytecode shenannigans.
Reduce the possibility for heisenbugs by providing noFixupFollowField:ofObject: and using it in debugging code.
=============== Diff against VMMaker.oscog-eem.862 ===============
Item was changed: ----- Method: CoInterpreter>>updateStateOfSpouseContextForFrame:WithSP: (in category 'frame access') ----- updateStateOfSpouseContextForFrame: theFP WithSP: theSP "Update the frame's spouse context with the frame's current state except for the sender and instruction pointer, which are used to mark the context as married." | theContext tempIndex pointer argsPointer | <inline: false> <var: #theFP type: #'char *'> <var: #theSP type: #'char *'> <var: #pointer type: #'char *'> <var: #argsPointer type: #'char *'> self assert: (self frameHasContext: theFP). theContext := self frameContext: theFP. self assert: (objectMemory isContext: theContext). + self assert: (self frameReceiver: theFP) + = (objectMemory noFixupFollowField: ReceiverIndex ofObject: theContext). - objectMemory hasSpurMemoryManagerAPI - ifTrue: - ["We do not need to follow forwarding pointer to the receiver; makeBaseFrameFor: does that. - In any case the assignments below updating the non-argument stack contents will do so." - self assert: ((self frameReceiver: theFP) - = (objectMemory fetchPointer: ReceiverIndex ofObject: theContext) - or: [(objectMemory isOopForwarded: (objectMemory fetchPointer: ReceiverIndex ofObject: theContext)) - and: [(objectMemory followForwarded: (objectMemory fetchPointer: ReceiverIndex ofObject: theContext)) - = (self frameReceiver: theFP)]])] - ifFalse: - [self assert: (self frameReceiver: theFP) - = (objectMemory fetchPointer: ReceiverIndex ofObject: theContext)]. (self isMachineCodeFrame: theFP) ifTrue: [tempIndex := self mframeNumArgs: theFP. pointer := theFP + FoxMFReceiver - BytesPerWord] ifFalse: [tempIndex := self iframeNumArgs: theFP. pointer := theFP + FoxIFReceiver - BytesPerWord]. "update the arguments. this would appear not to be strictly necessary, but is for two reasons. First, the fact that arguments are read-only is only as convention in the Smalltalk compiler; other languages may choose to modify arguments. Second, the Squeak runUntilErrorOrReturnFrom: nightmare pops the stack top, which may, in certain circumstances, be the last argument, and hence the last argument may not have been stored into the context." argsPointer := theFP + (self frameStackedReceiverOffsetNumArgs: tempIndex). 1 to: tempIndex do: [:i| argsPointer := argsPointer - BytesPerWord. self assert: (objectMemory addressCouldBeOop: (stackPages longAt: argsPointer)). objectMemory storePointer: ReceiverIndex + i ofObject: theContext withValue: (stackPages longAt: argsPointer)]. "now update the non-argument stack contents." [pointer >= theSP] whileTrue: [self assert: (objectMemory addressCouldBeOop: (stackPages longAt: pointer)). tempIndex := tempIndex + 1. objectMemory storePointer: ReceiverIndex + tempIndex ofObject: theContext withValue: (stackPages longAt: pointer). pointer := pointer - BytesPerWord]. self assert: ReceiverIndex + tempIndex < (objectMemory lengthOf: theContext). objectMemory storePointerUnchecked: StackPointerIndex ofObject: theContext withValue: (objectMemory integerObjectOf: tempIndex)!
Item was added: + ----- Method: ObjectMemory>>noFixupFollowField:ofObject: (in category 'forward compatibility') ----- + noFixupFollowField: fieldIndex ofObject: anObject + "Spur compatibility; in V3 this is a synonym for fetchPointer:ofObject:" + <inline: true> + ^self fetchPointer: fieldIndex ofObject: anObject!
Item was added: + ----- Method: SpurMemoryManager>>noFixupFollowField:ofObject: (in category 'forwarding') ----- + noFixupFollowField: fieldIndex ofObject: anObject + "Make sure the oop at fieldIndex in anObject is not forwarded (follow the + forwarder there-in if so). Answer the (possibly followed) oop at fieldIndex." + | objOop | + objOop := self fetchPointer: fieldIndex ofObject: anObject. + (self isOopForwarded: objOop) ifTrue: + [objOop := self followForwarded: objOop]. + ^objOop!
Item was changed: ----- Method: StackInterpreter>>findClassContainingMethod:startingAt: (in category 'debug support') ----- findClassContainingMethod: meth startingAt: classObj | currClass classDict classDictSize methodArray i | + (objectMemory isOopForwarded: classObj) + ifTrue: [currClass := objectMemory followForwarded: classObj] + ifFalse: [currClass := classObj]. - currClass := classObj. [self assert: (objectMemory isForwarded: currClass) not. + classDict := objectMemory noFixupFollowField: MethodDictionaryIndex ofObject: currClass. - classDict := objectMemory fetchPointer: MethodDictionaryIndex ofObject: currClass. self assert: (objectMemory isForwarded: classDict) not. classDictSize := objectMemory numSlotsOf: classDict. + methodArray := objectMemory noFixupFollowField: MethodArrayIndex ofObject: classDict. - methodArray := objectMemory fetchPointer: MethodArrayIndex ofObject: classDict. self assert: (objectMemory isForwarded: methodArray) not. i := 0. [i < (classDictSize - SelectorStart)] whileTrue: + [meth = (objectMemory noFixupFollowField: i ofObject: methodArray) ifTrue: - [meth = (objectMemory fetchPointer: i ofObject: methodArray) ifTrue: [^currClass]. i := i + 1]. + currClass := self noFixupSuperclassOf: currClass. - 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 mclass | - | rclass | ((objectMemory addressCouldBeOop: rcvr) and: [(objectMemory isOopForwarded: rcvr) not]) ifTrue: [rclass := objectMemory fetchClassOf: rcvr. (self addressCouldBeClassObj: rclass) ifTrue: [rclass := self findClassContainingMethod: meth startingAt: rclass. rclass ~= objectMemory nilObject ifTrue: [^rclass]]]. ((objectMemory addressCouldBeObj: meth) and: [objectMemory isCompiledMethod: meth]) ifFalse: [^objectMemory nilObject]. + mclass := self safeMethodClassOf: meth. + (self addressCouldBeClassObj: mclass) ifTrue: + [^objectMemory nilObject]. + ^self findClassContainingMethod: meth startingAt: (self safeMethodClassOf: meth)! - ^self findClassContainingMethod: meth startingAt: (self methodClassOf: meth)!
Item was changed: ----- Method: StackInterpreter>>findSelectorOfMethod: (in category 'debug support') ----- findSelectorOfMethod: methArg | meth classObj classDict classDictSize methodArray i | (objectMemory addressCouldBeObj: methArg) ifFalse: [^objectMemory nilObject]. (objectMemory isForwarded: methArg) ifTrue: [meth := objectMemory followForwarded: methArg] ifFalse: [meth := methArg]. (objectMemory isOopCompiledMethod: meth) ifFalse: [^objectMemory nilObject]. + classObj := self safeMethodClassOf: meth. - classObj := self methodClassOf: meth. (self addressCouldBeClassObj: classObj) ifTrue: [classDict := objectMemory fetchPointer: MethodDictionaryIndex ofObject: classObj. classDictSize := objectMemory numSlotsOf: 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 changed: ----- Method: StackInterpreter>>initialPCForHeader:method: (in category 'compiled methods') ----- initialPCForHeader: methodHeader method: theMethod + "Answer the initial PC for a method; used only in methods that build a frame. + Hence add an assert to check that there's a sane methodClassAssociation." + <inline: true> + self assert: (self saneMethodClassAssociationIn: theMethod + numLiterals: (objectMemory literalCountOfMethodHeader: methodHeader)). - <api> ^theMethod + ((LiteralStart + (objectMemory literalCountOfMethodHeader: methodHeader)) * BytesPerOop) + objectMemory baseHeaderSize!
Item was changed: ----- Method: StackInterpreter>>methodClassOf: (in category 'compiled methods') ----- methodClassOf: methodPointer <api> "Using a read barrier here simplifies the become implementation and costs very little because the class index and ValueIndex of the association almost certainly share a cache line." ^self cppIf: NewspeakVM ifTrue: [| literal | literal := self followLiteral: (objectMemory literalCountOf: methodPointer) - 1 ofMethod: methodPointer. literal = objectMemory nilObject ifTrue: [literal] ifFalse: [objectMemory followField: ValueIndex ofObject: literal]] ifFalse: [| literal | literal := self followLiteral: (objectMemory literalCountOf: methodPointer) - 1 ofMethod: methodPointer. + self assert: ((objectMemory isPointers: literal) and: [(objectMemory numSlotsOf: literal) > ValueIndex]). objectMemory followField: ValueIndex ofObject: literal]!
Item was added: + ----- Method: StackInterpreter>>noFixupSuperclassOf: (in category 'message sending') ----- + noFixupSuperclassOf: classPointer + "No fixup version of superclassOf: that should not create heisenbugs" + <inline: true> + ^objectMemory noFixupFollowField: SuperclassIndex ofObject: classPointer!
Item was added: + ----- Method: StackInterpreter>>safeMethodClassOf: (in category 'compiled methods') ----- + safeMethodClassOf: methodPointer + "Safe version of methodClassOf: that deals with malformed compiled methods, + etc, and does not fixup forwarding pointers.." + | literal maybeClass | + literal := self literal: (objectMemory literalCountOf: methodPointer) - 1 ofMethod: methodPointer. + (objectMemory isOopForwarded: literal) ifTrue: + [literal := objectMemory followForwarded: literal]. + ((objectMemory isPointers: literal) and: [(objectMemory numSlotsOf: literal) > ValueIndex]) ifFalse: + [^objectMemory nilObject]. + maybeClass := objectMemory fetchPointer: ValueIndex ofObject: literal. + (objectMemory isOopForwarded: maybeClass) ifTrue: + [maybeClass := objectMemory followForwarded: maybeClass]. + ^maybeClass!
Item was added: + ----- Method: StackInterpreter>>saneMethodClassAssociationIn:numLiterals: (in category 'compiled methods') ----- + saneMethodClassAssociationIn: methodObj numLiterals: numLiterals + | shouldBeAssoc | + shouldBeAssoc := self literal: numLiterals - 1 ofMethod: methodObj. + (objectMemory isForwarded: shouldBeAssoc) ifTrue: + [shouldBeAssoc := objectMemory followForwarded: shouldBeAssoc]. + ^(objectMemory isPointers: shouldBeAssoc) + and: [(objectMemory numSlotsOf: shouldBeAssoc) > ValueIndex + and: [self addressCouldBeClassObj: (objectMemory noFixupFollowField: ValueIndex ofObject: shouldBeAssoc)]]!
vm-dev@lists.squeakfoundation.org