[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