[Vm-dev] VM Maker: VMMaker.oscog-eem.863.mcz

commits at source.squeak.org commits at source.squeak.org
Sat Aug 23 16:13:14 UTC 2014

Eliot Miranda uploaded a new version of VMMaker to project VM Maker:

==================== 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)
  			[tempIndex := self mframeNumArgs: theFP.
  			 pointer := theFP + FoxMFReceiver - BytesPerWord]
  			[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:
  		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:
  		 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:
  	((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>
  	+ ((LiteralStart + (objectMemory literalCountOfMethodHeader: methodHeader)) * BytesPerOop)
  	+ objectMemory baseHeaderSize!

Item was changed:
  ----- Method: StackInterpreter>>methodClassOf: (in category 'compiled methods') -----
  methodClassOf: methodPointer
  	"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
  			[| literal |
  			 literal := self followLiteral: (objectMemory literalCountOf: methodPointer) - 1 ofMethod: methodPointer.
  			 literal = objectMemory nilObject
  				ifTrue: [literal]
  				ifFalse: [objectMemory followField: ValueIndex ofObject: literal]]
  			[| 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)]]!

More information about the Vm-dev mailing list