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

commits at source.squeak.org commits at source.squeak.org
Tue Dec 11 23:18:25 UTC 2012


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

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

Name: VMMaker.oscog-eem.230
Author: eem
Time: 11 December 2012, 3:16:18.03 pm
UUID: 735cb4f0-6d2a-4916-bbd0-cd517917da4e
Ancestors: VMMaker.oscog-eem.229

Fix stackPage headroom calculation in CoInterpreter.  Was getting
things backward.  This increases the stack page headroom by 62%
from 1564 bytes to 2532 bytes.  Shootout benchmarks unchanged,
so reduction in frames per page is not an issue for typical code.

This should result in fewer crashes on linux where the dynamic
linker, if it kicked in during a signal handler, could cause a deep
call chain at interrupt time and trample the start of the adjoining
stack page.

Use self alloca: nbytes over cCode: 'alloca(nbytes)'

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

Item was changed:
  ----- Method: CoInterpreter>>initStackPagesAndInterpret (in category 'initialization') -----
  initStackPagesAndInterpret
  	"Initialize the stack pages and enter interpret. Use alloca'ed memory so that when
  	 we have a JIT its stack pointer will be on the native stack since alloca allocates
  	 memory on the stack. Certain thread systems use the native stack pointer as the
  	 frame ID so putting the stack anywhere else can confuse the thread system."
  
  	"Override to establish the setjmp/longjmp handler for reentering the interpreter
  	 from machine code, and disable executablity on the heap and stack pages."
  
  	"This should be in its own initStackPages method but Slang can't inline
  	 C code strings."
  	| stackPageBytes stackPagesBytes theStackMemory |
  	<var: #theStackMemory type: #'char *'>
  	stackPageBytes := self stackPageByteSize.
  	stackPagesBytes := self computeStackZoneSize.
  	theStackMemory := self
+ 						cCode: [self alloca: stackPagesBytes]
- 						cCode: 'alloca(stackPagesBytes)'
  						inSmalltalk:
  							[stackPages := self stackPagesClass new.
  							 stackPages initializeWithByteSize: stackPagesBytes for: self].
  	self sqMakeMemoryNotExecutableFrom: objectMemory startOfMemory asUnsignedInteger
  		To: objectMemory memoryLimit asUnsignedInteger.
  	self sqMakeMemoryNotExecutableFrom: theStackMemory asUnsignedInteger
  		To: theStackMemory asUnsignedInteger + stackPagesBytes.
  	stackPages
  		initializeStack: theStackMemory
  		numSlots: stackPagesBytes / BytesPerWord
  		pageSize: stackPageBytes / BytesPerWord
  		stackLimitOffset: self stackLimitOffset
  		stackPageHeadroom: self stackPageHeadroom.
  
  	"Once the stack pages are initialized we can continue to bootstrap the system."
  	self loadInitialContext.
  	"We're ready for the heartbeat (poll interrupt)"
  	self ioInitHeartbeat.
  	self initialEnterSmalltalkExecutive.
  	^nil!

Item was changed:
  ----- Method: CoInterpreterStackPages>>initializeStack:numSlots:pageSize:stackLimitOffset:stackPageHeadroom: (in category 'initialization') -----
  initializeStack: theStackPages numSlots: stackSlots pageSize: slotsPerPage stackLimitOffset: stackLimitOffsetBytes stackPageHeadroom: stackPageHeadroomBytes
  	"Initialize the stack pages.  In the C VM theStackPages will be alloca'ed memory to hold the
  	 stack pages on the C stack.  In the simulator they are housed in the memory between the
  	 cogMethodZone and the heap."
  
  	<var: #theStackPages type: #'char *'>
  	<returnTypeC: #void>
  	| numPages page structStackPageSize pageStructBase count |
  	<var: #page type: #'StackPage *'>
  	<var: #pageStructBase type: #'char *'>
+ 	self cCode: []
- 	self cCode: ''
  		inSmalltalk:
  			[self assert: objectMemory startOfMemory - coInterpreter cogCodeSize - coInterpreter methodCacheSize - coInterpreter primTraceLogSize - coInterpreter rumpCStackSize
  					= (stackSlots * BytesPerWord)].
  	structStackPageSize := coInterpreter sizeof: CogStackPage.
  	bytesPerPage := slotsPerPage * BytesPerWord.
  	numPages := coInterpreter numStkPages.
  
  	"Because stack pages grow down baseAddress is at the top of a stack page and so to avoid
  	 subtracting BytesPerWord from baseAddress and lastAddress in the init loop below we simply
  	 push the stackPage array up one word to avoid the overlap.  This word is extraStackBytes."
  	pageStructBase := theStackPages + (numPages * bytesPerPage) + BytesPerWord.
  	pages := self cCode: [self cCoerceSimple: pageStructBase to: #'StackPage *']
  				  inSmalltalk:
  					[pageMap := Dictionary new.
  					 ((0 to: numPages - 1) collect:
  						[:i|
  						 CogStackPage surrogateClass new
  							address: pageStructBase + (i * structStackPageSize)
  							simulator: coInterpreter
  							zoneBase: coInterpreter stackZoneBase
  							zoneLimit: objectMemory startOfMemory])
  						do: [:pageSurrogate|
  							pageMap at: pageSurrogate address put: pageSurrogate];
  						yourself].
  	0 to: numPages - 1 do:
  		[:index|
  		 page := self stackPageAt: index.
  		 page
  			lastAddress: theStackPages + (index * bytesPerPage);
+ 			baseAddress: page lastAddress + bytesPerPage;
+ 			stackLimit: page baseAddress
+ 						- stackLimitOffsetBytes
+ 						- stackPageHeadroomBytes;
- 			baseAddress: (page lastAddress + bytesPerPage);
- 			stackLimit: page lastAddress
-                             + stackLimitOffsetBytes
-                             + stackPageHeadroomBytes;
  			realStackLimit: page stackLimit;
  			baseFP: 0;
  			nextPage: (self stackPageAt: (index = (numPages - 1) ifTrue: [0] ifFalse: [index + 1]));
  			prevPage: (self stackPageAt: (index = 0 ifTrue: [numPages - 1] ifFalse: [index - 1]))].
  
  	"Now compute stackBasePlus1 so that the pageIndexFor: call maps all addresses from
  	 aPage baseAddress to aBase limitAddress + 1 to the same index (stacks grow down)"
  	stackBasePlus1 := (self cCoerceSimple: theStackPages to: #'char *') + 1.
+ 	self cCode: []
- 	self cCode: ''
  		inSmalltalk:
  			[minStackAddress := theStackPages.
  			 maxStackAddress := theStackPages + (numPages * bytesPerPage) + BytesPerWord - 1].
  
  	"The overflow limit is the amount of stack to retain when moving frames from an overflowing
  	 stack to reduce thrashing.  See stackOverflowOrEvent:mayContextSwitch:"
  	page := self stackPageAt: 0.
  	overflowLimit := page baseAddress - page realStackLimit * 3 // 5.
  	0 to: numPages - 1 do:
  		[:index|
  		 page := self stackPageAt: index.
  		 self assert: (self pageIndexFor: page baseAddress) == index.
  		 self assert: (self pageIndexFor: page baseAddress - (slotsPerPage - 1 * BytesPerWord)) == index.
  		 self assert: (self stackPageFor: page baseAddress) == page.
  		 self assert: (self stackPageFor: page stackLimit) == page.
+ 		 self cCode: []
- 		 self cCode: ''
  			inSmalltalk:
  				[| memIndex |
  				 memIndex := index * slotsPerPage + 1. "this is memIndex in the block above"
  				 self assert: (self memIndexFor: (self oopForPointer: page baseAddress))
  							== (memIndex + slotsPerPage - 1).
  				 index < (numPages - 1) ifTrue:
  					[self assert: (self stackPageFor: page baseAddress + BytesPerWord) == (self stackPageAt: index + 1)]].
  		self assert: (page trace: -1) ~= 0 "for assert checking of the page tracing flags. -1 == invalid state"].
  
  	mostRecentlyUsedPage := self stackPageAt: 0.
  	page := mostRecentlyUsedPage.
  	count := 0.
  	[| theIndex |
  	 count := count + 1.
  	 theIndex := self pageIndexFor: page baseAddress.
  	 self assert: (self stackPageAt: theIndex) == page.
  	 self assert: (self pageIndexFor: page baseAddress) == theIndex.
  	 self assert: (self pageIndexFor: page stackLimit) == theIndex.
  	 self assert: (self pageIndexFor: page lastAddress + 1) == theIndex.
  	 (page := page nextPage) ~= mostRecentlyUsedPage] whileTrue.
  	self assert: count == numPages.
  	self assert: self pageListIsWellFormed!

Item was changed:
  ----- Method: StackInterpreter>>initStackPages (in category 'initialization') -----
  initStackPages
  	"Initialize the stackPages.  This version is only for simulation
  	 because Slang refuses to inline it, which makes the alloca invalid."
  	| stackPageBytes stackPagesBytes theStackMemory |
  	stackPageBytes := self stackPageByteSize.
  	stackPagesBytes := self computeStackZoneSize.
  	theStackMemory := self
+ 						cCode: [self alloca: stackPagesBytes]
- 						cCode: 'alloca(stackPagesBytes)'
  						inSmalltalk:
  							[stackPages := self stackPagesClass new.
  							 stackPages initializeWithByteSize: stackPagesBytes for: self].
  	stackPages
  		initializeStack: theStackMemory
  		numSlots: stackPagesBytes / BytesPerWord
  		pageSize: stackPageBytes / BytesPerWord
  		stackLimitOffset: self stackLimitOffset
  		stackPageHeadroom: self stackPageHeadroom!

Item was changed:
  ----- Method: StackInterpreter>>initStackPagesAndInterpret (in category 'initialization') -----
  initStackPagesAndInterpret
  	"Initialize the stack pages and enter interpret. Use alloca'ed memory so that when
  	 we have a JIT its stack pointer will be on the native stack since alloca allocates
  	 memory on the stack. Certain thread systems use the native stack pointer as the
  	 frame ID so putting the stack anywhere else can confuse the thread system."
  
  	"This should be in its own initStackPages method but Slang can't inline
  	 C code strings."
  	| stackPageBytes stackPagesBytes theStackMemory |
  	<var: #theStackMemory type: #'void *'>
  	stackPageBytes := self stackPageByteSize.
  	stackPagesBytes := self computeStackZoneSize.
  	theStackMemory := self
+ 						cCode: [self alloca: stackPagesBytes]
- 						cCode: 'alloca(stackPagesBytes)'
  						inSmalltalk:
  							[stackPages := self stackPagesClass new.
  							 stackPages initializeWithByteSize: stackPagesBytes for: self].
  	stackPages
  		initializeStack: theStackMemory
  		numSlots: stackPagesBytes / BytesPerWord
  		pageSize: stackPageBytes / BytesPerWord
  		stackLimitOffset: self stackLimitOffset
  		stackPageHeadroom: self stackPageHeadroom.
  
  	"Once the stack pages are initialized we can continue to bootstrap the system."
  	self loadInitialContext.
  	"We're ready for the heartbeat (poll interrupt)"
  	self ioInitHeartbeat.
  	self interpret.
  	^nil!

Item was removed:
- ----- Method: ThreadedFFIPlugin>>alloca: (in category 'simulation') -----
- alloca: size
- 	<doNotGenerate>
- 	^ByteArray new: size!

Item was added:
+ ----- Method: VMClass>>alloca: (in category 'C library simulation') -----
+ alloca: size
+ 	"Simulation of alloca(3)"
+ 	<doNotGenerate>
+ 	^ByteArray new: size!



More information about the Vm-dev mailing list