Re: Status of Strongtalk C++ code: VM stability and progress on a graphical debugger
talksmall <[email protected]> Tue, 20 May 2008 03:51:04 -0700 (PDT)
| Newsgroups | gmane.comp.lang.smalltalk.strongtalk |
|---|---|
| Message-ID | <3abf7b84-6e62-48b3-8d6f-cf736046abee@y38g2000hsy.googlegroups.com> |
Hi Shaping, On May 20, 4:47 am, Shaping <[email protected]> wrote: > On May 18, 10:18 pm, talksmall <[email protected]> wrote: > I'm not sure > > > what you mean when you refer to interpreted methods being "fully > > reified". > > Both are modeled as first-class objects in Smalltalk? Seems that way. No. Only the interpreted version is visible to Smalltalk. The compiled version appears as an nmethod in the VM, but I don't believe there is a Smalltalk level equivalent. When Activation objects are created for the StackTraceInspector the stack has already been deoptimised to leave on interpreted frames (and therefore interpreted methods). > > Do you mean the methods, or context objects for the stack > > > frames? > > Both. I'm asking how we model compiled and interpreted forms of a > method, specifically, so that I can determine how to track-down all > references that may need to participate in a #become: In the VM a (re)compiled method is represented as an nmethod. An interpreted method is represented as a methodOopDesc usually referred to be a methodOop pointer. The core of the code necessary for a become: is in phase 1 of the mark and sweep garbage collection in markSweep.cpp. This illustrates iteration over all places where the VM may store references to Smalltalk objects. At the moment this code uses a function pointer passed to a series of iterator functions (such as Universe::oops_do()). Continuing with this means that we would need to put the state in global variables, an idea I'm really not keen on, but may be better than the alternatives. > So the CompiledMethod instance that models a compiled method is still > retained for use in debugging, even if the compiled method's machine > code has been inlined in another method being called from an actual > frame on the stack. Well the inlined method may not have been inlined at all call sites, and the inlining may need to be updated if the site is a polymorphic send that subsequently needs updating. Also, whenever the stack gets deoptimised, such as for Smalltalk level debugging, the interpreted methods (they are actually just referred to as Method(s) in Strongtalk Smalltalk code) are still required. Also, any reflective performs may need interpreted or at least non-inlined versions of the method code. > > > If you are swapping pointers during a #become:, you have to be able to > > > find all references. Is doing this reliably the problem? > > > Finding all of the references for become: is not really a problem. > > After all, this is exactly what the garbage collector has to do when > > moving objects around. The code is specific to the garbage collector > > though, so it will need to be extracted to allow its reuse for > > become:. As Gilad mentioned, it's not that it's hard, it's just work > > that has to be done, and no-one's done it yet. > > That is what I supposed and was wondering why the traversal from the > roots of the world hadn't been factored-out for use in #become: > I suspect this is solely because no-one got around to implementing become: yet. > > The generated bytecode primitives and the recompiled native methods. > > "Recompiling" is the iterative compiling of bottlenecked regions of > code? It's not iterative exactly, but it may happen repeatedly if a method is heavily used. Note that tight loops inside a single method activation that never ends (the typical case being event loops) are not optimized by the recompiler. Recompilation is typically triggered on send sites, but the new version of the method is only used for a new activation of the method, not for existing activations. > > > The way that the interpreted code works at the moment is to identify > > that the IC is stale (ie. the receiver class doesn't match) and fall > > through to the lookup code which is supposed to patch the method and > > class in the IC. The code then jumps back to the start IC test again > > and falls through again. Actually why this causes the stack overflow I > > saw when I tried earlier, I'm not sure. I was actually expecting it to > > go into a spin loop around the send. > > Seems that that once the patch in the IC is done correctly, the test > for stale will not longer fall through to the lookup code. Perhaps > the patch itself is the problem. > No. You can only patch the IC with a method that matches the signature of the message send. doesNotUnderstand: doesn't meet this criteria. In particular, it expects an instance of Message as an argument, rather than a list of arguments for the original message send. To work in the way you suggest the lookup routine would need to pop the arguments off the stack, construct a Message with those arguments and push it back in their place, then patch the IC, keeping in mind that this is all occurring in a different frame of the stack - that of the method containing the IC, rather than that of the lookup function. In addition, and somewhat more problematically, the next time you hit that IC it will contain a reference to doesNotUnderstand:. That's not so bad if the receiver class has changed, because the lookup gets called to updated the IC, but if it is the same class, you have a problem, because there is now no hook to pop the arguments from the stack and create a Message with them. All round, I think it is easier to change the send code to invoke doesNotUnderstand: rather than trying to do it in the lookup function. > > > > To fix this, message sends in compiled and interpreted methods need to > > > > allow for a failed lookup followed by an invocation of > > > > doesNotUnderstand: that pops the arguments from the stack and pushes > > > > the result returned by the method. > > > > Are you saying that you want the exception handling following the > > > raising of the MNU expection to work correctly? Apparently the > > > exception itself is not being raised at all. Is this the problem? > > > Actually the current doesNotUnderstand: doesn't signal a MNU. > > Strongtalk doesn't have ANSI standard exceptions. Instead it calls > > > Processor stopWithError: (ProcessDoesNotUnderstandError new message: > > m) > > > which is a bit like an exception, without quite being one. > > Specifically, there is no mechanism to catch this error other than the > > ProcessorScheduler's stopHandler. > > So what magic do we do inside this special handler? > Typically the stopHandler starts a StackTraceInspector on the stopped process. Take a look at Launcher. This is the main Transcript window. When the programming environment starts it sets the stopHandler on the Processor (a ProcessorScheduler instance). The code is in Launcher>>startProgEnv. Of course, the stop handler could be set to something else using stopHandler: on the Processor, but there's effectively only one chance to catch the error, not a nested set of exception handlers. This is what my exception handling implementation provides using the ANSI Smalltalk description. > I could use Eclipse for editing code, and then jump out to a command > prompt to run a nmake, but I don't relish the idea. Well Eclipse lets you launch external commands automatically, so you don't need to jump out to a command prompt (or at least not manually). Regards, Steve --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Strongtalk-general" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/strongtalk-general?hl=en -~----------~----~----~----~------~----~------~--~---