[Vm-dev] Objects may move while reading a file
eliot.miranda at gmail.com
Tue May 14 17:09:39 UTC 2013
On Tue, May 14, 2013 at 5:30 AM, Guillermo Polito <guillermopolito at gmail.com
> On Mon, May 13, 2013 at 11:09 PM, Eliot Miranda <eliot.miranda at gmail.com>wrote:
>> Hi Guillermo,
>> On Mon, May 13, 2013 at 3:04 AM, Guillermo Polito <
>> guillermopolito at gmail.com> wrote:
>>> I was looking at the following primitiveFileRead because I wanted to
>>> extract some code. I do not see why objects should move during the
>>> primitive execution... And I do not see why is this check only made in this
>>> primitive (and the threadedFFI ones...).
>>> Does someone have a clue?
>> This is for the threaded VM with the current GC. Imagine
>> sqFileReadIntoAt blocks and the VM does a thread switch to some other
>> thread. At that point the other thread could cause the VM to perform a GC.
>> Andreas came up with the idea of handling this situation by allowing a
>> blocking thread to prevent full GCs that move objects in old space, but not
>> prevent "incremental" GCs which only move objects in young space. So if
>> the thread executing sqFileReadIntoAt is given only old objects it can
>> safely block if it sets a flag preventing full GCs.
>> In a GC supporting pinning and/or lazy become the blocking thread would
>> instead either pin its buffer or become its buffer into a pinned space, in
>> which case the error below could never occur. But the check is harmless.
>> does this help?
> Yes, so it is only used in case of a threaded VM, what makes more sense :).
> Now I wonder, shouldn't then this check be done in (almost) every
I don't think so. Only in primitives that could block while the VM could do
other things. So for example, DNS lookup. In fact, the current DNS lookup
primitive has its own custom threading scheme sop it can run un the
background (not functional on unix). A threaded VM should eliminate the
need for such special-case code.
>>> <export: true>
>>> | retryCount count startIndex array file elementSize bytesRead |
>>> <var: 'file' type: #'SQFile *'>
>>> <var: 'count' type: #'size_t'>
>>> <var: 'startIndex' type: #'size_t'>
>>> <var: 'elementSize' type: #'size_t'>
>>> retryCount := 0.
>>> count := interpreterProxy positive32BitValueOf: (interpreterProxy
>>> stackValue: 0).
>>> startIndex := interpreterProxy positive32BitValueOf: (interpreterProxy
>>> stackValue: 1).
>>> [array := interpreterProxy stackValue: 2.
>>> file := self fileValueOf: (interpreterProxy stackValue: 3).
>>> (interpreterProxy failed
>>> "buffer can be any indexable words or bytes object except
>>> or: [(interpreterProxy isWordsOrBytes: array) not]) ifTrue:
>>> [^interpreterProxy primitiveFailFor: PrimErrBadArgument].
>>> elementSize := (interpreterProxy isWords: array) ifTrue:  ifFalse:
>>> (startIndex >= 1
>>> and: [(startIndex + count - 1) <= (interpreterProxy slotSizeOf:
>>> array)]) ifFalse:
>>> [^interpreterProxy primitiveFailFor: PrimErrBadIndex].
>>> "Note: adjust startIndex for zero-origin indexing"
>>> bytesRead := self
>>> sqFile: file
>>> Read: count * elementSize
>>> Into: (self cCoerce: (interpreterProxy firstIndexableField: array) to:
>>> #'char *')
>>> At: (startIndex - 1) * elementSize.
>>> *interpreterProxy primitiveFailureCode = PrimErrObjectMayMove*
>>> * and: [(retryCount := retryCount + 1) <= 2] "Two objects, the file and
>>> the array can move"*] whileTrue:
>>> primitiveFailFor: PrimNoErr].
>>> interpreterProxy failed ifFalse:
>>> pop: 5 "pop rcvr, file, array, startIndex, count"
>>> thenPush:(interpreterProxy integerObjectOf: bytesRead // elementSize)
>>> "push # of elements read"]
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Vm-dev