Just curious about the difference in instructionPointer between these two... StackInterpreter>>transferTo: self assertValidExecutionPointe: instructionPointer + 1 r: framePointer s: stackPointer. CoIntepreter>>transferTo:from: self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer. cheers -ben |
Hi Ben, > On Jun 9, 2016, at 6:46 PM, Ben Coman <[hidden email]> wrote: > > > Just curious about the difference in instructionPointer between these two... > > StackInterpreter>>transferTo: > self assertValidExecutionPointe: instructionPointer + 1 r: > framePointer s: stackPointer. > > > CoIntepreter>>transferTo:from: > self assertValidExecutionPointe: instructionPointer r: > framePointer s: stackPointer. The difference is to support richer logging of process switch events in the Cog VM. In the StackInterpreter context switches only occur in two contexts, within a primitive or checkForEventsMayContextSwitch:. One might think that the Cog VM is similar but it's much more complicated because a primitive can be invoked in different ways. One way is from the interpreter via slowPrimitiveResponse, just like the StackInterpreter. Another way is from a jitted method containing a primitive. Yet another way is in the attempt to lookup and link a send from machine code that binds to a method with a primitive. Yet another way is in invoking a primitive in a method that should be interpreted (because it has more literals than the limit for jitting) from machine code. The VM optimises this transition by using a PIC which can have entries that speed up invoking interpreted methods or MNUs, not just polymorphic sends. To debug context switch in these contexts (and one more historical context that I think no longer occurs) I needed the richer logging that the from: argument gave me to discover the actual path taken to a process switch. HTH > > cheers -ben |
On Fri, Jun 10, 2016 at 11:30 AM, Eliot Miranda <[hidden email]> wrote: > > Hi Ben, > >> On Jun 9, 2016, at 6:46 PM, Ben Coman <[hidden email]> wrote: >> >> >> Just curious about the difference in instructionPointer between these two... >> >> StackInterpreter>>transferTo: >> self assertValidExecutionPointe: instructionPointer + 1 r: >> framePointer s: stackPointer. >> >> >> CoIntepreter>>transferTo:from: >> self assertValidExecutionPointe: instructionPointer r: >> framePointer s: stackPointer. > > The difference is to support richer logging of process switch events in the Cog VM. > > In the StackInterpreter context switches only occur in two contexts, within a primitive or checkForEventsMayContextSwitch:. > > One might think that the Cog VM is similar but it's much more complicated because a primitive can be invoked in different ways. One way is from the interpreter via slowPrimitiveResponse, just like the StackInterpreter. Another way is from a jitted method containing a primitive. Yet another way is in the attempt to lookup and link a send from machine code that binds to a method with a primitive. Yet another way is in invoking a primitive in a method that should be interpreted (because it has more literals than the limit for jitting) from machine code. The VM optimises this transition by using a PIC which can have entries that speed up invoking interpreted methods or MNUs, not just polymorphic sends. > > To debug context switch in these contexts (and one more historical context that I think no longer occurs) I needed the richer logging that the from: argument gave me to discover the actual path taken to a process switch. Thanks Eliot. Great info that I'll file for reference, but this seems only to describe the addition to Cog of the #from: argument, and I'm not sure how that relates to my query on why the assert for StackInterpreter increments the instructionPointer by one, and the assert for the CoInterpreter does not. Sorry if my question was too brief an unclear? cheers -ben |
Great info indeed! :) Eliot, is that in a class comment or a paper somewhere? I'd like to read the rest of it if so. thanks again, -C -- Craig Latta Black Page Digital Amsterdam [hidden email] +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS) |
In reply to this post by Ben Coman
Hi Ben, this time I'll try and answer your question rather than my brain fart... > On Jun 9, 2016, at 6:46 PM, Ben Coman <[hidden email]> wrote: > > > Just curious about the difference in instructionPointer between these two... > > StackInterpreter>>transferTo: > self assertValidExecutionPointe: instructionPointer + 1 r: > framePointer s: stackPointer. > > > CoIntepreter>>transferTo:from: > self assertValidExecutionPointe: instructionPointer r: > framePointer s: stackPointer. In the StackInterpreter, as in the context Interpreter the next bytecode is fetched by pre-incrementing the instructionPointer and then fetching the byte it points to. Hence it may point to before the first bytecode and hence the + 1 above. 1 is subtracted from a context's pc (2 actually cuz pc is 1-relative and instructionPointer is 0-relative) to derive instructionPointer. In the Cog VM instructionPointer may also be a machine code pc. So rather than add one, which only makes sense for interpreted methods, the CoInterpreter's assertValidExecutionPointer:s: allows for the - 1 if a frame us interpreted. The StackInterpreter's method predates the CoInterpreter. > > > cheers -ben _,,,^..^,,,_ (phone) |
In reply to this post by Craig Latta
Hi Craig, > On Jun 10, 2016, at 12:46 AM, Craig Latta <[hidden email]> wrote: > > > > Great info indeed! :) Eliot, is that in a class comment or a paper > somewhere? I'd like to read the rest of it if so. I had planned to write at least a blog post on this and related topics, essentially in how Cog coordinates an interpreter and a JIT, but I've not found time in 5 years :-/. I think it's important to write up. I remember reading something about the Erlang VM wanting to do the same and they ended up having two separate stacks for interpreted and machine code frames, bad for a number of reasons. The stars may yet align and I'll write it up... > thanks again, > > -C _,,,^..^,,,_ (phone) |
In reply to this post by Eliot Miranda-2
On 10 June 2016 at 20:17, Eliot Miranda <[hidden email]> wrote:
I was just wandering in the vicinity of this again, and had a new query... What is the semantic difference in the naming of the arguments (i.e. lsp<=> lisp and lfp<=>lifp) between.... ? StackInterpreter >> assertValidExecutionPointe: lip r: lfp s: lsp imbar: inInterpreter line: ln CoInterpreter >> assertValidExecutionPointe: lip r: lifp s: lisp imbar: inInterpreter line: ln because search/replacing makes it easier to diff the two methods... This shows the StackInterpreter method refactored slightly to extract "methodField" variable similar to the CoInterpreter making it easier to compare the two, i.e. red-line-16 and green-line-18 are identical, but red-line-13 and green-line-14 set "methodField" using different messages, which however have identical definitions. StackInterpreter >> frameMethod: theFP <inline: true> <var: #theFP type: #'char *'> ^stackPages longAt: theFP + FoxMethod CoInterpreter >> frameMethodField: theFP <inline: true> <var: #theFP type: #'char *'> ^stackPages longAt: theFP + FoxMethod Would it be reasonable to change red-line-13 to send #frameMethodField: instead? Hopefully my slight rearrangement of the asserts in red okay. cheers -ben |
On 6 May 2018 at 16:56, Ben Coman <[hidden email]> wrote:
======================== I found it a bit convoluted following where CoInterpreter overrides StackInterpreter >> frameIsBlockActivation: StackInterpreter >> frameIsBlockActivation: theFP "<Integer>" <inline: true> <var: #theFP type: #'char *'> ^(stackPages byteAt: theFP + FoxFrameFlags + 3) ~= 0 CoInterpreter >> frameIsBlockActivation: theFP "<Integer>" <inline: true> <var: #theFP type: #'char *'> ^(self isMachineCodeFrame: theFP) ifTrue: [self mframeIsBlockActivation: theFP] ifFalse: [self iframeIsBlockActivation: theFP] But I notice StackInterpreter >> frameIsBlockActivation: is identical to... CoInterpreter >> iframeIsBlockActivation: theFP "<Integer>" <inline: true> <var: #theFP type: #'char *'> ^(stackPages byteAt: theFP + FoxIFrameFlags + 3) ~= 0 while... StackInterpreter >> iframeIsBlockActivation: theFP "<Integer>" ^self frameIsBlockActivation: theFP So reversing StackInterpreter's definitions of these two methods thus... StackInterpreter >> iframeIsBlockActivation: theFP "<Integer>" <inline: true> <var: #theFP type: #'char *'> ^(stackPages byteAt: theFP + FoxFrameFlags + 3) ~= 0 StackInterpreter >> frameIsBlockActivation: theFP "<Integer>" ^self iframeIsBlockActivation: theFP makes the existing CoInterpreter override clearer... CoInterpreter >> frameIsBlockActivation: theFP "<Integer>" <inline: true> <var: #theFP type: #'char *'> ^(self isMachineCodeFrame: theFP) ifTrue: [self mframeIsBlockActivation: theFP] ifFalse: [self iframeIsBlockActivation: theFP] and also CoInterpreter >> iframeIsBlockActivation becomes redundant. Can I submit a changeset for these? cheers -ben |
Hi Ben,
|
Free forum by Nabble | Edit this page |