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

commits at source.squeak.org commits at source.squeak.org
Thu Aug 21 07:19:17 UTC 2014


Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.862.mcz

==================== Summary ====================

Name: VMMaker.oscog-eem.862
Author: eem
Time: 21 August 2014, 8:14:01.395 am
UUID: 34b8f089-7da3-4c40-9996-2d2611fe5111
Ancestors: VMMaker.oscog-eem.861

Make nameOfClass: more robust, in both the real and
simulated VMs.

Add a documentation method for the structure of a
CogMethod.

=============== Diff against VMMaker.oscog-eem.861 ===============

Item was changed:
  VMStructType subclass: #CogBlockMethod
  	instanceVariableNames: 'objectHeader homeOffset startpc padToWord cmNumArgs cmType cmRefersToYoung cpicHasMNUCase cmUsageCount cmUsesPenultimateLit cmUnusedFlags stackCheckOffset'
  	classVariableNames: ''
  	poolDictionaries: 'CogMethodConstants VMBasicConstants'
  	category: 'VMMaker-JIT'!
  
+ !CogBlockMethod commentStamp: 'eem 8/19/2014 17:07' prior: 0!
+ I am the rump method header for a block method embedded in a full CogMethod.  I am the superclass of CogMethod, which is a Cog method header proper.  Instances of both classes have the same second word.  The homeOffset and startpc fields are overlaid on the objectHeader in a CogMethod.  See Cogit class>>structureOfACogMethod for more information.  In C I look like
- !CogBlockMethod commentStamp: 'eem 1/9/2011 08:41' prior: 0!
- I am the rump method header for a block method embedded in a full CogMethod.  I am the superclass of CogMethod, which is a Cog method header proper.  Instances of both classes have the same second word.  The homeOffset abd startpc fields are overlaid on the objectHeader in a CogMethod.  In C I look like
  
  	typedef struct {
  		unsigned short	homeOffset;
  		unsigned short	startpc;
  
  		unsigned		cmNumArgs : 8;
  		unsigned		cmType : 3;
  		unsigned		cmRefersToYoung : 1;
  		unsigned		cmIsUnlinked : 1;
  		unsigned		cmUsageCount : 3;
  		unsigned		stackCheckOffset : 16;
  	} CogBlockMethod;
  
  My instances are not actually used.  The methods exist only as input to Slang.  The simulator uses my surrogates (CogBlockMethodSurrogate32 and CogBlockMethodSurrogate64.!

Item was changed:
  CogBlockMethod subclass: #CogMethod
  	instanceVariableNames: 'blockSize blockEntryOffset methodObject methodHeader selector'
  	classVariableNames: ''
  	poolDictionaries: ''
  	category: 'VMMaker-JIT'!
  
+ !CogMethod commentStamp: 'eem 8/19/2014 17:07' prior: 0!
+ I am a native Cog method or polymorphic inline cache.  If the former I have been produced by compiling a bytecoded CompiledMethod into machine code by the JIT, and I have a circular reference to that CompiledMethod.  The CompiledMethod's header field is a pointer to me, the CogMethod, and my methodHeader field holds the compiled method's actual header.  My objectHeader field looks like a single word object with a compact header with the mark bit set so as to placate the GC, i.e. make a CogMethod look like an object so that the reference to a CogMethod from a compiled method doesn't break the GC.  The cmType, stackCheckOffset, cmNumArgs & cmNumTemps fields are early in the structure because we place dummy two-word CogMethod headers within a method for each block within it to record this information for each block method (see my superclass CogBlockMethod).  In this case the objectHeader field is overlaid by the homeOffset and startpc fields.  The objectHeader field is also used to hold the relocation distance when compacting methods since when functioning as an obhject header it is a constant value and so can easily be reinitialized.  See Cogit class>>structureOfACogMethod for more information.
- !CogMethod commentStamp: 'eem 1/9/2011 08:49' prior: 0!
- I am a native Cog method or polymorphic inline cache.  If the former I have been produced by compiling a bytecoded CompiledMethod into machine code by the JIT, and I have a circular reference to that CompiledMethod.  The CompiledMethod's header field is a pointer to me, the CogMethod, and my methodHeader field holds the compiled method's actual header.  My objectHeader field looks like a single word object with a compact header with the mark bit set so as to placate the GC, i.e. make a CogMethod look like an object so that the reference to a CogMethod from a compiled method doesn't break the GC.  The cmType, stackCheckOffset, cmNumArgs & cmNumTemps fields are early in the structure because we place dummy two-word CogMethod headers within a method for each block within it to record this information for each block method (see my superclass CogBlockMethod).  In this case the objectHeader field is overlaid by the homeOffset and startpc fields.  The objectHeader field is also used to hold the relocation distance when compacting methods since when functioning as an obhject header it is a constant value and so can easily be reinitialized.
  
  In C I look like
  
  	typedef struct {
  	    sqInt   objectHeader;
  	
  	    unsigned        cmNumArgs : 8;
  	    unsigned        cmType : 3;
  	    unsigned        cmRefersToYoung : 1;
  	    unsigned        cmIsUnlinked : 1;
  	    unsigned        cmUsageCount : 3;
  	    unsigned        stackCheckOffset : 16;
  	
  	    unsigned short blockSize;
  	    unsigned short blockEntryOffset;
  	
  	    sqInt   methodObject;
  	    sqInt   methodHeader;
  	    sqInt   selector;
  	 } CogMethod;
  
  Note that in a 64-bit system all fields from cmNumArgs through blockEntry fit in a single 64-bit word.
  
  My instances are not actually used.  The methods exist only as input to Slang.  The simulator uses my surrogates (CogMethodSurrogate32 and CogMethodSurrogate64.!

Item was changed:
  ----- Method: CogVMSimulator>>nameOfClass: (in category 'debug support') -----
  nameOfClass: classOop
+ 	| numSlots maybeThisClassOop maybeNameOop name |
- 	| numSlots |
  	classNameIndex ifNil: [^'??nil cnidx??'].
  	numSlots := objectMemory numSlotsOf: classOop.
  	numSlots = metaclassNumSlots ifTrue:
+ 		[maybeThisClassOop := objectMemory fetchPointer: thisClassIndex ofObject: classOop.
+ 		(self addressCouldBeClassObj: maybeThisClassOop) ifTrue:
+ 			[name := self nameOfClass: maybeThisClassOop.
+ 			 (name beginsWith: 'bad ') ifFalse:
+ 				[^name, ' class']].
+ 		 ^'bad class'].
+ 	(numSlots > classNameIndex
+ 	 and: [maybeNameOop := objectMemory fetchPointer: classNameIndex ofObject: classOop.
+ 		objectMemory isBytes: maybeNameOop]) ifFalse:
- 		[^(self nameOfClass:
- 				(objectMemory fetchPointer: thisClassIndex ofObject: classOop)) , ' class'].
- 	numSlots <= classNameIndex ifTrue:
  		[^'bad class'].
+ 	^self stringOf: maybeNameOop!
- 	^self stringOf: (objectMemory fetchPointer: classNameIndex ofObject: classOop)!

Item was added:
+ ----- Method: Cogit class>>structureOfACogMethod (in category 'tests') -----
+ structureOfACogMethod
+ 	"A CogMethod is the machine code for executable code in the Cog VM, and in the simulator these are
+ 	 instances of CogMethod.  In actuality they are structures in memory in the CogMethodZone..  There
+ 	 are four real kinds, defined by the cmType field, free space: CMFree, methods: CMMethod, closed
+ 	 PICs: CMClosedPIC (finite polymorphic inline caches with up to 6 entries), and open PICs: CMOpenPIC
+ 	 (infinite megamorphicinline caches that probe the first-level method lookup cache).  There is a sixth
+ 	 kind of method, which is merely a header, for blocks: CMBlock, one which exists only within CMMethods,
+ 	 and exist only to allow block activations to refer to something that looks like a CogMethod.
+ 
+ 	 The blockSize field in a CogMethod is the size in bytes of the entire method, including the header.
+ 	 Methods are aligned to an 8 byte boundary in the CogMethodZone.  The size is used to iterate over
+ 	 the methods in the zone.
+ 
+ 	 Follwing the header is the abort and entry code.  Starting immediately after the header is the call to
+ 	 the abort routine called when either a send fails or a stack limit check fails.  Following that is the
+ 	 checked entry point that checks the receiver is of the right class, and this code ends in the unchecked
+ 	 entry point.  Following this is either primitive code, followed by frame building code, or frame-building
+ 	 code, or, for frameless methods, the code for the frameless method.  Following that is the code for the
+ 	 method.  If the mehtrod contains blocks  then followng the method code will be a CMBlock header,
+ 	 followed by code for the block, for each block, and following this will be the block dispatch code,
+ 	 which is pointed to by the blockEntryOffset field in the CogMethod.
+ 
+ 	 Following either the return in the method, or the block dispatch, is the meta data which identifies
+ 	 intersting points in the machine code.  This meta data starts at the end of teh structure and is read
+ 	 backwards towards the start of the method, and is terminated by a null byte.  So the blockSize is
+ 	 used to find the start of the metadata.  The metadata reveals where object references, sends and
+ 	 pc-mapping points exist in the machine code.  Hence the metadata is parsed when garbage collect-
+ 	 ing to find and update object references."
+ 	 !

Item was changed:
  ----- Method: StackInterpreter>>nameOfClass: (in category 'debug printing') -----
  nameOfClass: classOop
  	"Brain-damaged nameOfClass: for C VM.  Does *not* answer Foo class for metaclasses.
  	 Use e.g. classIsMeta: to avoid being fooled."
  	<inline: false>
+ 	<returnTypeC: #'char *'>
+ 	| numSlots maybeNameOop maybeThisClassOop |
- 	<returnTypeC: 'char *'>
- 	| numSlots |
  	numSlots := objectMemory numSlotsOf: classOop.
  	numSlots = metaclassNumSlots ifTrue:
+ 		[maybeThisClassOop := objectMemory fetchPointer: thisClassIndex ofObject: classOop.
+ 		(self addressCouldBeClassObj: maybeThisClassOop) ifTrue:
+ 			[^self nameOfClass: (objectMemory fetchPointer: thisClassIndex ofObject: classOop)].
+ 		 ^'bad class'].
+ 	(numSlots > classNameIndex
+ 	 and: [maybeNameOop := objectMemory fetchPointer: classNameIndex ofObject: classOop.
+ 		objectMemory isBytes: maybeNameOop]) ifFalse:
- 		[^self nameOfClass: (objectMemory fetchPointer: thisClassIndex ofObject: classOop)].
- 	numSlots <= classNameIndex ifTrue:
  		[^'bad class'].
+ 	^objectMemory firstIndexableField: maybeNameOop!
- 	^objectMemory firstIndexableField: (objectMemory fetchPointer: classNameIndex ofObject: classOop)!

Item was changed:
  ----- Method: StackInterpreterSimulator>>nameOfClass: (in category 'debug support') -----
  nameOfClass: classOop
+ 	| numSlots maybeThisClassOop maybeNameOop name |
- 	| numSlots |
  	classNameIndex ifNil: [^'??nil cnidx??'].
  	numSlots := objectMemory numSlotsOf: classOop.
  	numSlots = metaclassNumSlots ifTrue:
+ 		[maybeThisClassOop := objectMemory fetchPointer: thisClassIndex ofObject: classOop.
+ 		(self addressCouldBeClassObj: maybeThisClassOop) ifTrue:
+ 			[name := self nameOfClass: maybeThisClassOop.
+ 			 (name beginsWith: 'bad ') ifFalse:
+ 				[^name, ' class']].
+ 		 ^'bad class'].
+ 	(numSlots > classNameIndex
+ 	 and: [maybeNameOop := objectMemory fetchPointer: classNameIndex ofObject: classOop.
+ 		objectMemory isBytes: maybeNameOop]) ifFalse:
- 		[^(self nameOfClass:
- 				(objectMemory fetchPointer: thisClassIndex ofObject: classOop)) , ' class'].
- 	numSlots <= classNameIndex ifTrue:
  		[^'bad class'].
+ 	^self stringOf: maybeNameOop!
- 	^self stringOf: (objectMemory fetchPointer: classNameIndex ofObject: classOop)!



More information about the Vm-dev mailing list