I was chasing a problem with Sophie where the VM would suddenly grow
by 800MB. In looking I discovered a problem with how Slang interprets the following code. Background: When an incremental garbage collection is done and the free space is less than the grow head room and the bias to grow is turned on, then we call biasToGrow. I'll note normally the gcBiasToGrow would be false unless you turn it on so few users have seen this problem. The problem is that Slang converts the "growSize := growHeadroom*3/2 - (self sizeOfFree: freeBlock)" to nothing. In the past I know this worked because I had worked on choosing the magic 3/2 number. ObjectMemory>>incrementalGC ... (((self sizeOfFree: freeBlock) < growHeadroom) and: [gcBiasToGrow > 0]) ifTrue: [self biasToGrow. weDidGrow := true]. youngStart := freeBlock]. ... ObjectMemory>>biasToGrow | growSize | growSize := growHeadroom*3/2 - (self sizeOfFree: freeBlock) self growObjectMemory: growSize ObjectMemory>>growObjectMemory: delta "Attempt to grow the object memory by the given delta amount " | limit | statGrowMemory := statGrowMemory + 1. limit := self sqGrowMemory: memoryLimit By: delta. limit = memoryLimit ifFalse: [memoryLimit := limit - 24. "remove a tad for safety" self initializeMemoryFirstFree: freeBlock] --------------------------------------------------- But the C code that Slang generates looks like so: if ((((longAt(foo->freeBlock)) & AllButTypeMask) < foo- >growHeadroom) && (foo->gcBiasToGrow > 0)) { /* begin biasToGrow */ /* begin growObjectMemory: */ foo->statGrowMemory += 1; limit = sqGrowMemoryBy(foo->memoryLimit, growSize); if (!(limit == foo->memoryLimit)) { foo->memoryLimit = limit - 24; initializeMemoryFirstFree(foo->freeBlock); } weDidGrow = 1; } The C compiler is happy (mostly) and depending on what it sticks in the growSize memory location, perhaps it's perhaps zero, perhaps not, we might as I did some odd behaviour. How clever, and if you've come this far, you've like seen the missing period. at the end of "growSize := growHeadroom*3/2 - (self sizeOfFree: freeBlock)" Helpfully Slang doesn't complaint about the missing period and forges onward creating in-valid C code, without the proper meaning. Hopefully people writing Slang code are muttering, gee I wonder if I have some code that isn't quite what I think it is? With the period of course the code becomes if ((((longAt(foo->freeBlock)) & AllButTypeMask) < foo- >growHeadroom) && (foo->gcBiasToGrow > 0)) { /* begin biasToGrow */ growSize = (((sqInt) (foo->growHeadroom * 3) >> 1)) - ((longAt(foo- >freeBlock)) & AllButTypeMask); /* begin growObjectMemory: */ foo->statGrowMemory += 1; limit = sqGrowMemoryBy(foo->memoryLimit, growSize); if (!(limit == foo->memoryLimit)) { foo->memoryLimit = limit - 24; initializeMemoryFirstFree(foo->freeBlock); } weDidGrow = 1; } Mostly likely in working with Tim I managed to copy/paste some code and missed the '.' Lastly I'll note the biasToGrow logic is there because there is a problem when Squeak reaches the boundary point where it must decide to grow, before doing that it does an incremental GC, the issue is that if the incremental GC can recover just enough few bytes the grow will not happen, but we will do another GC really really soon, thus you see Squeak at 100% CPU in the GC logic, yet not quite growing, at some point you will go over the boundary and grow, solving the problem. The bias to grow logic then ensures the VM will grow in increments up to a certain threshold before forcing a full GC, thus avoids the particular problem. -- ======================================================================== === John M. McIntosh <[hidden email]> Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== === |
Am Jan 23, 2007 um 6:15 schrieb John M McIntosh:
> ObjectMemory>>biasToGrow > | growSize | > growSize := growHeadroom*3/2 - (self sizeOfFree: freeBlock) > self growObjectMemory: growSize > > How clever, and if you've come this far, you've like seen the > missing period. at the end of > "growSize := growHeadroom*3/2 - (self sizeOfFree: freeBlock)" > > Helpfully Slang doesn't complaint about the missing period and > forges onward creating in-valid C code, without the proper meaning. Ugh. Evil slang. So the fix would be that the receiver of a keyword message must be a variable in Slang, and if it is not, we should complain? Or, make it translate to the actual equivalent C code, calling growObjectMemory with two arguments, the first of which would be self(growHeadroom*3/2-sizeOfFree(freeBlock)) so this becomes growSize = growObjectMemory(self(growHeadroom*3/2-sizeOfFree (freeBlock)), growSize) Hrmm. For C code that looks even sensible. I guess comnplaining is way safer. > Hopefully people writing Slang code are muttering, gee I wonder if > I have some code that isn't quite what I think it is? Nah, couldn't ever happen to me. Ever. Err. (... goes looking ...) - Bert - |
On Tue, Jan 23, 2007 at 11:36:16AM +0100, Bert Freudenberg wrote:
> Am Jan 23, 2007 um 6:15 schrieb John M McIntosh: > > >ObjectMemory>>biasToGrow > > | growSize | > > growSize := growHeadroom*3/2 - (self sizeOfFree: freeBlock) > > self growObjectMemory: growSize > > > >How clever, and if you've come this far, you've like seen the > >missing period. at the end of > > "growSize := growHeadroom*3/2 - (self sizeOfFree: freeBlock)" > > > >Helpfully Slang doesn't complaint about the missing period and > >forges onward creating in-valid C code, without the proper meaning. > > Ugh. Evil slang. Um, wait a minute. The Smalltalk compiler does not complain about it, so why would we expect the Slang translator to complain about it? It's perfectly valid Smalltalk, and it does not blow up until you run it in Squeak. Wasn't being able to write and test the code in Squeak sort of the whole point of Slang in the first place? > So the fix would be that the receiver of a keyword message must be a > variable in Slang, and if it is not, we should complain? Or, make it > translate to the actual equivalent C code, calling growObjectMemory > with two arguments, the first of which would be > > self(growHeadroom*3/2-sizeOfFree(freeBlock)) > > so this becomes > > growSize = growObjectMemory(self(growHeadroom*3/2-sizeOfFree > (freeBlock)), growSize) > > Hrmm. For C code that looks even sensible. I guess comnplaining is > way safer. Another thing that might help is to have some simple way to show generated C code for a method, perhaps right in a browser. Dave |
Free forum by Nabble | Edit this page |