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

commits at source.squeak.org commits at source.squeak.org
Fri Jan 18 17:42:08 UTC 2013


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

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

Name: VMMaker.oscog-eem.257
Author: eem
Time: 16 January 2013, 10:38:33.013 am
UUID: cc766916-2d42-4637-b147-e37206b7c669
Ancestors: VMMaker.oscog-eem.256

Fix snafu in last stack page  hanges (last two parameters to stack
page init funcs are unused) and simplify.

Integrate the named serial primitives plus Luc Fabresse's latest fix.

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

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]
  						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.
- 		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 added:
+ ----- Method: CoInterpreterStackPages>>initializeStack:numSlots:pageSize: (in category 'initialization') -----
+ initializeStack: theStackPages numSlots: stackSlots pageSize: slotsPerPage
+ 	"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: []
+ 		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].
+ 	"make sure there's enough headroom"
+ 	self assert: coInterpreter stackPageByteSize - coInterpreter stackLimitBytes - coInterpreter stackLimitOffset
+ 				>= coInterpreter stackPageHeadroom.
+ 	0 to: numPages - 1 do:
+ 		[:index|
+ 		 page := self stackPageAt: index.
+ 		 page
+ 			lastAddress: theStackPages + (index * bytesPerPage);
+ 			baseAddress: page lastAddress + bytesPerPage;
+ 			stackLimit: page baseAddress - coInterpreter stackLimitBytes;
+ 			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: []
+ 		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: []
+ 			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 removed:
- ----- 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: []
- 		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].
- 	"make sure there's enough headroom"
- 	self assert: coInterpreter stackPageByteSize - coInterpreter stackLimitBytes - coInterpreter stackLimitOffset
- 				>= coInterpreter stackPageHeadroom.
- 	0 to: numPages - 1 do:
- 		[:index|
- 		 page := self stackPageAt: index.
- 		 page
- 			lastAddress: theStackPages + (index * bytesPerPage);
- 			baseAddress: page lastAddress + bytesPerPage;
- 			stackLimit: page baseAddress - coInterpreter stackLimitBytes;
- 			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: []
- 		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: []
- 			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 added:
+ ----- Method: InterpreterStackPages>>initializeStack:numSlots:pageSize: (in category 'initialization') -----
+ initializeStack: theStackPages numSlots: stackSlots pageSize: slotsPerPage
+ 	"Initialize the stack pages.  For testing I want stack addresses to be disjoint from
+ 	 normal memory addresses so stack addresses are negative.  The first address is
+ 	 -pageSize bytes.  So for example if there are 1024 bytes per page and 3 pages
+ 	 then the pages are organized as
+ 
+ 		byte address: -1024 <-> -2047 | -2048 <-> -3071 | -3072 <-> -4096 |
+ 							page 3			page 2			page 1
+ 		mem index:        769 <-> 513  |     512 <->  257  |   256 <->        1 |
+ 
+ 	 The byte address is the external address corresponding to a real address in the VM.
+ 	 mem index is the index in the memory Array holding the stack, an index internal to
+ 	 the stack pages.  The first stack page allocated will be the last page in the array of pages
+ 	 at the highest effective address.  Its base address be -1024  and grow down towards -2047."
+ 
+ 	"The lFoo's are to get around the foo->variable scheme in the C call to allocStackPages below."
+ 	<var: #theStackPages type: #'char *'>
+ 	| page structStackPageSize pageStructBase count |
+ 	<var: #page type: #'StackPage *'>
+ 	<var: #pageStructBase type: #'char *'>
+ 	self cCode: ''
+ 		inSmalltalk:
+ 			[self assert: stackMemory size = stackSlots.
+ 			 self assert: stackMemory size - self extraStackBytes \\ slotsPerPage = 0.
+ 			 self assert: stackMemory == theStackPages].
+ 	stackMemory := theStackPages. "For initialization in the C code."
+ 	self cCode: '' inSmalltalk: [pageSizeInSlots := slotsPerPage].
+ 	structStackPageSize := interpreter sizeof: InterpreterStackPage.
+ 	bytesPerPage := slotsPerPage * BytesPerWord.
+ 	numPages := stackSlots // (slotsPerPage + (structStackPageSize / BytesPerWord)).
+ 
+ 	"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: '(StackPage *)pageStructBase'
+ 				  inSmalltalk:
+ 						[pageStructBase class.
+ 						 (1 to: numPages) collect: [:i| InterpreterStackPage new]].
+ 
+ 	"Simulation only.  Since addresses are negative the offset is positive.  To make all
+ 	 stack addresses negative we make the offset a page more than it needs to be so the
+ 	 address of the last slot in memory (the highest address in the stack, or its start) is
+ 		- pageByteSize
+ 	 and the address of the first slot (the lowest address, or its end) is
+ 		- pageByteSize * (numPages + 1)"
+ 	self cCode: '' inSmalltalk: [indexOffset := (numPages + 1) * slotsPerPage].
+ 	"make sure there's enough headroom"
+ 	self assert: interpreter stackPageByteSize - interpreter stackLimitBytes - interpreter stackLimitOffset
+ 				>= interpreter stackPageHeadroom.
+ 	0 to: numPages - 1 do:
+ 		[:index|
+ 		 page := self stackPageAt: index.
+ 		 page
+ 			lastAddress: (self cCode: '(char *)theStackPages + (index * GIV(bytesPerPage))'
+ 							inSmalltalk: [(index * slotsPerPage - indexOffset) * BytesPerWord]);
+ 			baseAddress: (page lastAddress + bytesPerPage);
+ 			stackLimit: page baseAddress - interpreter stackLimitBytes;
+ 			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]))].
+ 	self cCode: ''
+ 		inSmalltalk:
+ 			[| lowestAddress highestAddress |
+ 			lowestAddress := (pages at: 1) lastAddress + BytesPerWord.
+ 			highestAddress := (pages at: numPages) baseAddress.
+ 			"see InterpreterStackPages>>longAt:"
+ 			self assert: lowestAddress // BytesPerWord + indexOffset = 1.
+ 			self assert: highestAddress // BytesPerWord + indexOffset = (numPages * slotsPerPage)].
+ 
+ 	"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: ''
+ 			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 + BytesPerWord) == theIndex.
+ 	 (page := page nextPage) ~= mostRecentlyUsedPage] whileTrue.
+ 	self assert: count == numPages.
+ 	self assert: self pageListIsWellFormed!

Item was removed:
- ----- Method: InterpreterStackPages>>initializeStack:numSlots:pageSize:stackLimitOffset:stackPageHeadroom: (in category 'initialization') -----
- initializeStack: theStackPages numSlots: stackSlots pageSize: slotsPerPage stackLimitOffset: stackLimitOffsetBytes stackPageHeadroom: stackPageHeadroomBytes
- 	"Initialize the stack pages.  For testing I want stack addresses to be disjoint from
- 	 normal memory addresses so stack addresses are negative.  The first address is
- 	 -pageSize bytes.  So for example if there are 1024 bytes per page and 3 pages
- 	 then the pages are organized as
- 
- 		byte address: -1024 <-> -2047 | -2048 <-> -3071 | -3072 <-> -4096 |
- 							page 3			page 2			page 1
- 		mem index:        769 <-> 513  |     512 <->  257  |   256 <->        1 |
- 
- 	 The byte address is the external address corresponding to a real address in the VM.
- 	 mem index is the index in the memory Array holding the stack, an index internal to
- 	 the stack pages.  The first stack page allocated will be the last page in the array of pages
- 	 at the highest effective address.  Its base address be -1024  and grow down towards -2047."
- 
- 	"The lFoo's are to get around the foo->variable scheme in the C call to allocStackPages below."
- 	<var: #theStackPages type: #'char *'>
- 	| page structStackPageSize pageStructBase count |
- 	<var: #page type: #'StackPage *'>
- 	<var: #pageStructBase type: #'char *'>
- 	self cCode: ''
- 		inSmalltalk:
- 			[self assert: stackMemory size = stackSlots.
- 			 self assert: stackMemory size - self extraStackBytes \\ slotsPerPage = 0.
- 			 self assert: stackMemory == theStackPages].
- 	stackMemory := theStackPages. "For initialization in the C code."
- 	self cCode: '' inSmalltalk: [pageSizeInSlots := slotsPerPage].
- 	structStackPageSize := interpreter sizeof: InterpreterStackPage.
- 	bytesPerPage := slotsPerPage * BytesPerWord.
- 	numPages := stackSlots // (slotsPerPage + (structStackPageSize / BytesPerWord)).
- 
- 	"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: '(StackPage *)pageStructBase'
- 				  inSmalltalk:
- 						[pageStructBase class.
- 						 (1 to: numPages) collect: [:i| InterpreterStackPage new]].
- 
- 	"Simulation only.  Since addresses are negative the offset is positive.  To make all
- 	 stack addresses negative we make the offset a page more than it needs to be so the
- 	 address of the last slot in memory (the highest address in the stack, or its start) is
- 		- pageByteSize
- 	 and the address of the first slot (the lowest address, or its end) is
- 		- pageByteSize * (numPages + 1)"
- 	self cCode: '' inSmalltalk: [indexOffset := (numPages + 1) * slotsPerPage].
- 	"make sure there's enough headroom"
- 	self assert: interpreter stackPageByteSize - interpreter stackLimitBytes - interpreter stackLimitOffset
- 				>= interpreter stackPageHeadroom.
- 	0 to: numPages - 1 do:
- 		[:index|
- 		 page := self stackPageAt: index.
- 		 page
- 			lastAddress: (self cCode: '(char *)theStackPages + (index * GIV(bytesPerPage))'
- 							inSmalltalk: [(index * slotsPerPage - indexOffset) * BytesPerWord]);
- 			baseAddress: (page lastAddress + bytesPerPage);
- 			stackLimit: page baseAddress - interpreter stackLimitBytes;
- 			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]))].
- 	self cCode: ''
- 		inSmalltalk:
- 			[| lowestAddress highestAddress |
- 			lowestAddress := (pages at: 1) lastAddress + BytesPerWord.
- 			highestAddress := (pages at: numPages) baseAddress.
- 			"see InterpreterStackPages>>longAt:"
- 			self assert: lowestAddress // BytesPerWord + indexOffset = 1.
- 			self assert: highestAddress // BytesPerWord + indexOffset = (numPages * slotsPerPage)].
- 
- 	"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: ''
- 			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 + BytesPerWord) == theIndex.
- 	 (page := page nextPage) ~= mostRecentlyUsedPage] whileTrue.
- 	self assert: count == numPages.
- 	self assert: self pageListIsWellFormed!

Item was changed:
  SmartSyntaxInterpreterPlugin subclass: #SerialPlugin
  	instanceVariableNames: ''
  	classVariableNames: ''
  	poolDictionaries: ''
  	category: 'VMMaker-Plugins'!
  
+ !SerialPlugin commentStamp: '<historical>' prior: 0!
+ Implement the serial port primitives.  Since it requires platform support it will only be built when supported on your platform.
+ 
+ IMPORTANT: So far, we are converting everytime a string into a char* and then we look for it in the ports array. That can be optimized a lot by just answering the external handler (the position in the array perhaps) after open and using it instead the name.
+ Also, using open by id functions doesn't help because internally they are also converted into a char* (using sprintf).
+ 
+ If needed, that can be optimized then. !
- !SerialPlugin commentStamp: 'tpr 5/2/2003 15:49' prior: 0!
- Implement the serial port primitives.  Since it requires platform support it will only be built when supported on your platform!

Item was added:
+ ----- Method: SerialPlugin>>primitiveSerialPortOpenByName:baudRate:stopBitsType:parityType:dataBits:inFlowControlType:outFlowControlType:xOnByte:xOffByte: (in category 'primitives') -----
+ primitiveSerialPortOpenByName: portName baudRate: baudRate stopBitsType: stopBitsType parityType: parityType dataBits: dataBits inFlowControlType: inFlowControl outFlowControlType: outFlowControl xOnByte: xOnChar xOffByte: xOffChar
+ 	<var: #port type: 'char *'>
+ 
+ 	| port portNameSize |
+ 	
+ 	self primitive: 'primitiveSerialPortOpenByName'
+ 		parameters: #(String SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger SmallInteger ).
+ 
+ 	portNameSize := interpreterProxy slotSizeOf: (portName asOop: String).
+ 	port := self cCode: 'calloc(portNameSize, sizeof(char))'.
+ 	self cCode: 'memcpy(port, portName, portNameSize)'.
+ 	
+ 	self cCode: 'serialPortOpenByName(
+ 			port, baudRate, stopBitsType, parityType, dataBits,
+ 			inFlowControl, outFlowControl, xOnChar, xOffChar)'.
+ 	
+ 	self free: port.!

Item was added:
+ ----- Method: SerialPlugin>>primitiveSerialPortReadByName:into:startingAt:count: (in category 'primitives') -----
+ primitiveSerialPortReadByName: portName into: array startingAt: startIndex count: count 
+ 	<var: #port type: 'char *'>
+ 
+ 	| port portNameSize bytesRead arrayPtr |
+ 
+ 	self primitive: 'primitiveSerialPortReadByName'
+ 		parameters: #(String ByteArray SmallInteger SmallInteger ).
+ 
+ 	interpreterProxy success: (startIndex >= 1 and: [startIndex + count - 1 <= (interpreterProxy byteSizeOf: array cPtrAsOop)]).
+ 	"adjust for zero-origin indexing"
+ 
+ 	portNameSize := interpreterProxy slotSizeOf: (portName asOop: String).
+ 	port := self cCode: 'calloc(portNameSize, sizeof(char))'.
+ 	self cCode: 'memcpy(port, portName, portNameSize)'.
+ 
+ 	arrayPtr := array asInteger + startIndex - 1.
+ 	bytesRead := self cCode: 'serialPortReadIntoByName( port, count, arrayPtr)'.
+ 	
+ 	self free: port.
+ 	
+ 	^ bytesRead asSmallIntegerObj!

Item was added:
+ ----- Method: SerialPlugin>>primitiveSerialPortWriteByName:from:startingAt:count: (in category 'primitives') -----
+ primitiveSerialPortWriteByName: portName from: array startingAt: startIndex count: count 
+ 	<var: #port type: 'char *'>
+ 
+ 	| bytesWritten arrayPtr portNameSize port |
+ 	
+ 	self primitive: 'primitiveSerialPortWriteByName'
+ 		parameters: #(String ByteArray SmallInteger SmallInteger ).
+ 
+ 	portNameSize := interpreterProxy slotSizeOf: (portName asOop: String).
+ 	port := self cCode: 'calloc(portNameSize, sizeof(char))'.
+ 	self cCode: 'memcpy(port, portName, portNameSize)'.
+ 
+ 	interpreterProxy success: (startIndex >= 1 and: [startIndex + count - 1 <= (interpreterProxy byteSizeOf: array cPtrAsOop)]).
+ 	interpreterProxy failed
+ 		ifFalse: [arrayPtr := array asInteger + startIndex - 1.
+ 			bytesWritten := self cCode: 'serialPortWriteFromByName(port, count, arrayPtr)' ].
+ 	
+ 	self free: port.
+ 
+ 	^ bytesWritten asSmallIntegerObj!

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]
  						inSmalltalk:
  							[stackPages := self stackPagesClass new.
  							 stackPages initializeWithByteSize: stackPagesBytes for: self].
  	stackPages
  		initializeStack: theStackMemory
  		numSlots: stackPagesBytes / BytesPerWord
+ 		pageSize: stackPageBytes / 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]
  						inSmalltalk:
  							[stackPages := self stackPagesClass new.
  							 stackPages initializeWithByteSize: stackPagesBytes for: self].
  	stackPages
  		initializeStack: theStackMemory
  		numSlots: stackPagesBytes / BytesPerWord
+ 		pageSize: stackPageBytes / 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!



More information about the Vm-dev mailing list