Re: pdd03 (calling conventions) revised; get_params vs. READONLY
On 11/29/05, Chip Salzenberg [EMAIL PROTECTED] wrote: I've reviewed pdd03 and brought it back from pdds/clip. Thanks for reviving this document Chip. Way back when I implemented some of the original lexical and calling code (like the scratchpad -- may it rest in peace). What is the status of the todo's mentioned in the BUGS section, who is working on these -- I am looking for a place to jump in. Also what is the status of the exception subsystem you mentioned? I guess one more todo I could take on is the add the use of the set_* and get_* ops to examples/subs. A short example in the pdd might be helpful too. Jonathan
pdd20 questions
I have some clarification questions about the new pdd20 on lexical variables -- likely stemming from my having been out of it for so long. Also I am happy to send a patch to pdd20 capturing these clarifications once I am sure I understand things correctly. 1. What is expected to be in P0 in: .lex $a, P0 2. Should we provide a way for a compiler to provide depths to the find_lex and store_lex ops if it chooses to? 3. 'Call frame' is mentioned often--what is a call frame in the context of continuation passing style? 4. In the section Closure creation: Capturing the lexical environment, LexPad is used a couple of times when LexEnv is meant, right? 5. Thinking about closure support vs. outer support - the difference and the need for both mechanisms is not clear to me. 6. The pdd mentions walking the call stack to find frames ... but is there a call stack? And finding lexpads on the call stack makes me think of dynamic variable binding rather than lexical? 7. Finally, what is the status of the implementation? (As an aside is there interest in having the names of the invoke ops more consistent, say: callcc and callcc_method; or invokecc and invokecc_method?) Jonathan
Re: pdd20 questions
On 11/30/05, Chip Salzenberg [EMAIL PROTECTED] wrote: On Wed, Nov 30, 2005 at 12:02:08PM -0800, Jonathan Sillito wrote: I have some clarification questions about the new pdd20 1. What is expected to be in P0 in: .lex $a, P0 The .lex directive is compile-time only, and has no runtime effect on the contents of P0. (Of course, once a register is available with a lexical name, store_lex may modify it.) OK, so this directive makes $a an alias for P0. 2. Should we provide a way for a compiler to provide depths to the find_lex and store_lex ops if it chooses to? Maximum depths, you mean? I know of no use case for it. Not maximum depth but the exact depth for a given lexical variable in the case of closures. The reason would simply be performance, though maybe insignificant in the common case (i.e. shallow nesting). 5. Thinking about closure support vs. outer support - the difference and the need for both mechanisms is not clear to me. Could you unpack this, please? Well, using :outer allows the look up algorithm to walk through enclosing lexical scopes ($sub = $sub.outer). In the case of closures the LexEnv is populated with the enclosing LexPads which I assume come from enclosing lexical scopes, which allows the the look up to do the same thing, no? I must be missing something here. Chip Salzenberg [EMAIL PROTECTED] Thanks, Jonathan
Re: pdd20 questions
On 11/30/05, Chip Salzenberg [EMAIL PROTECTED] wrote: What you're missing is that without the :outer information, Parrot wouldn't be able to decide *which* LexPads *should* be searched, either now (find_lex w/o LexEnv) or later (newclosure - LexEnv). Right and I see that this is consistent with the closure creation section (which is more clear now). Thanks, Jonathan
RE: [perl #22745] [PATCH] Parrot subroutines
The patch looks pretty good to me. Here is a proposal for an alternative inheritance hierarchy. Invocable, the root of the hierarchy, is basically a sub that is not a closure (i.e. *no* context at all, just an address). pmclass Invocable { # I called this sublite before /* SELF-data is always NULL */ /* SELF-cache.int_val holds address */ void set_integer_native(INTVAL value) { SELF-cache.int_val = value; } void* invoke() { return (void*)SELF-cache.int_value; } ... } pmclass Sub extends Invocable { /* SELF-data is a lex_pad (or stack as Leo suggests) */ } pmclass Continuation extends Invocable { /* SELF-data is a pointer to a Parrot_Context struct */ } pmclass Coroutine extends Continuation {...} /* maybe ??? */ In the current implementation there is a difference between the sub pmc and the struct Parrot_Sub. The same goes for continuations and coroutines. The above suggests that we could merge those together and just have the pmc versions. -- Jonathan Sillito
RE: ad #22717: CPS and more
-Original Message- From: Melvin Smith [mailto:[EMAIL PROTECTED] I tried this, and there was a distinct slowdown on accessing the regs through the dereference. Dan and I debated this because I had the same idea, but after profiling I proved Dan right. I think it is best optimized to the common case which is register access, not context switches. However now the registers are no longer in the Parrot_Context struct, so it may be worth revisiting this ... -Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED] [snip] So all these subroutine types should have probably this structure: typedef struct Parrot_Sub { struct Parrot_Context ctx; opcode_t *address; } * parrot_sub_t; Or a PMC with SELF-data pointing to a Parrot_Context struct and SELF-cache.int_val holding the address? On *construction* they would do: all: save_context(); // like in new_continuation sub, coro:push_current_lexpad_on_own_ctx(); // like new_coroutine [snip] Here is what I think. All of these things need an address and some amount of context which is saved on construction and restored on invoke. The different types the context to be saved and restored[1]: sublite[2]: none - just address sub: pointer to a lex pad coroutine: whole Parrot_Context[3] - i.e same as ... continuation for cps approach: whole Parrot_Context[3] Sound correct? -- Jonathan Sillito [1] This is not considering other context information that Dan has been talking about. [2] This does not exist but could if we wanted to support subs that are not closures - many are not. [3] This is in the worst case, and I would like to see variations that are more optimized.
RE: ad #22717: CPS and more
-Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED] The patch is fine with two exceptions: 1) still breaks existing P6C tests WRT exceptions rules 2) performance of CPS sucks ad 1) I'd like to preserve the old style invoke/ret scheme too. incokecc and friends could call a new ContSub[1] class, which is the same as sub.pmc but doesn't put the return address on the control stack during invoke. ad 2) CPS subroutines are 3 times slower for calling the sub. There are 2 problems here: 2a) The main is: the continuation object is generated for each[2] subroutine call. Replacing the invokecc with an explicit sequence of constructing the return Continuation object once outside the loop brings again the same speed as invoke/ret. This is the reason for the new implementation of the invoke op which assumes that the continuation has already been put in place. Also allowing the invokecc to take an argument specifying the type of continuation to save may be helpful: invokecc .AddressOnlyContinuation # or something ... invokecc .EverythingButTheKitchenSinkContinuation 2b) There is still too much context copying going on AFAIK. The register top and base pointers are copied too in {save,restore}context worth of 8 words, while just copying the 3 stacks (pad, control, user) should more then be enough. The coroutine code only swaps these - BTW and doesn't set them COW. I am not sure I follow this. Are you suggesting that the register stacks do not need to be copied? Again different types of continuations would be good. So we have currently: sub.pmc (+ contsub.pmc), continuation.pmc, and coroutine.pmc do very similar things. The only major difference is, where they branch on invoke. The differences are: - sub.pmc doesn't have an own context, it pushes the current lex_pad on the interpreters pad_stack on invoke - continuation.pmc saves/restores the whole context structure and marks the 3 stacks COW - coroutine.pmc swaps the 3 stacks and doesn't mark them COW This leads to some questions: - shouldn't these all preserve the same stack(s)? - which stack(s): pad_stack only or control/user/intstack too? - can we pull out the construction of the return continuation of the loop like done below? - what parts of current context structure should then be preserved (registers are already out, why then deal with register backing store)? Comments welcome As suggested in a previous email coroutine.pmc could just go away. Since returning from an otherwise normal sub using: invokecc P1 will save the appropriate context for a subsequent 'coroutine' call. leo [1] we could AFAIK reuse CSub, which is obsoleted by NCI. (also most routines in method_utils.c seems to be obsolete) [2] new P10, .PerlUndef set P10, 100 new P11, .PerlUndef set P11, 0 new P0, .Sub set_addr I12, func set P0, I12 set I0, 0 # no prototype set I2, 0 # no PMC params set I3, 0 # void context new P1, .Continuation ## set_addr I12, ret ## set P1, I12 ## lp: pushbottomp invoke ## invokecc ret: popbottomp inc P11 lt P11, P10, lp end func: invoke P1
RE: ad #22717: CPS and more
-Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED] Jonathan Sillito wrote: -Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED] The patch is fine with two exceptions: 1) still breaks existing P6C tests WRT exceptions rules You didn't mention this point. It might be only a small change in P6C code, I didn't look at (4 tests are failing now due to invoke changes). Sorry I haven't looked at this yet. 2) performance of CPS sucks This is the reason for the new implementation of the invoke op which assumes that the continuation has already been put in place. Ok then we need a new opcode: newsub Px, .Class, jump_or_ret_addr Sounds fine to me. At one point the following worked: new Px, .Class, address This constructs a sub or continuation type subroutine PMC in Px of class .Class and the referenced label - in one instruction. Also allowing the invokecc to take an argument specifying the type of continuation to save may be helpful: No, don't think so. The type is specified by the PMC class. The invoke of this class takes the appropriate action. I agree that constructing the continuation separately is functionally equivalent: new P1 .SomeContinuationClass, label# or newsub invoke label: # return's to here however I think a common case is made more convenient using: invokecc .SomeContinuationClass # assumes expr NEXT() # return's to here though, either way is fine with me. 2b) There is still too much context copying going on AFAIK. The register top and base pointers are copied too in {save,restore}context worth of 8 words, while just copying the 3 stacks (pad, control, user) should more then be enough. The coroutine code only swaps these - BTW and doesn't set them COW. I am not sure I follow this. Are you suggesting that the register stacks do not need to be copied? Again different types of continuations would be good. I honestly don't know, what has to be copied. I just know that all now do copy different things and if CPS is involved also restore different things. Please look at sub/continuation/coroutine and their context saving: all are different. I guess this needs some reworking see below. [snip] Still a lot (almost all) of my original concerns are not addressed yet. And performance and consistency are the main concerns, correct? Following are some ideas that may address theses. (1) A continuation is an invokable pmc that contains some context and an address to jump to. The context can vary and I suggest that we provide several continuation types to support this. I think the following may make sense (ordered from fastest to slowest). - no context (just an address) - just the pad stack - three stacks (pad, control and user) - three stacks plus register stacks I suppose other variations could be added as well. I am not sure what names to give each of these, but probably the no context pmc could be the base extended by the others. (2) Could the Parrot_Context struct be reworked such that the register stacks are only one pointer each? This would make the save and restore slightly more efficient. (3) One other efficiency thought: I wonder if the interpreter's context could be changed to a pointer to struct Parrot_Context? This would make accessing the stacks slightly slower but would of course make restoring the context very quick. Just a thought ... What do you think? -- Jonathan Sillito
RE: Context, continuations, and call speed
I missed this discussion I see, but for what it's worth, the patch I submitted earlier in the week introduced a continuation pmc that does **not** save or restore the registers. The old continuation pmc that saved (including the registers) everything has been renamed to completecontext.pmc. On the other hand I like the idea several types of continuations including one that saves and restores half of the registers. Finally if the registers are never to be saved as part of the context, we should reorganize the relevant structs so that the registers are not part of the Parrot_Context struct. Jonathan Sillito -Original Message- From: Dan Sugalski [mailto:[EMAIL PROTECTED] Sent: June 12, 2003 4:11 PM To: Luke Palmer Cc: [EMAIL PROTECTED] Subject: Re: Context, continuations, and call speed At 5:01 PM -0600 6/12/03, Luke Palmer wrote: At 4:28 PM -0600 6/12/03, Luke Palmer wrote: Okay, at the moment I'm working on getting an implementation of classes and objects working. I'm also taking a look at calling speed, as I'd really like to not suck with our call times. :) First off, the core stuff looks good. I'd not really looked at it until now, but now that I have, well... good job folks. I put in a minor tweak that may or may not speed things up (basically checking for the COW flag on stack chunks and bailing on the walk up if they're already marked) depending on what's resident in the L1/L2 cache. We'll see. Second, I see that the registers themselves are in the context structure. I think this may be a good part of our speed problem with taking continuations. Now, continuations should *not* restore the registers, so this strikes me as an incorrect thing to do, but before I twiddle the context structure some and remove them, I want to check and make sure that there's not a good reason to have them in. Well, aren't the registers really part of the context? Nope. If they were, there would be no way to return data from a function. The return values go in the registers, remember, and we return to the caller by invoking the continuation it passed into us. But they really are, honest. No. No, they aren't. Registers are really data, so arguably a continuation restore shouldn't restore *any* of the register stacks. That'd make things rather... odd, so we're not doing that. I may regret it in the future, of course. Continuations are supposed to save only control information, not data. Registers are data. (And so far as I know, no system that does continuations saves register contents for restore, since there'd be no way to pass data back and forth) Are the register stacks saved with the continuation? Yes, of course they are. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
RE: Context, continuations, and call speed
-Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED] [snip] The compiler can't decide on not to emit saveall/restoreall - we are talking here about Parrot calling conventions and the caller saves all. The compiler may omit the saveall/restoreall on the last function call, *if* the compiler is really sure, that its calling really a leaf (If that returns with Cinvoke the compiler *doesn't* be sure). The calling convention says that the caller saves everything that the caller cares about, but that may not be everything. If a sub uses only one or two registers it only needs to save those before calling another sub ... right? -- Jonathan Sillito
RE: [perl #22633] [PATCH] convert parrot to continuation passing style
-Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED] Jonathan Sillito [EMAIL PROTECTED] wrote: This patch converts parrot to a continuation passing style. You seem to be changing current tests WRT invoke - does invoke still work as it did? Or more specifically: Do imcc tests and perl6 test still pass? Not quite. In the case of sub.pmc the 'next' argument to the invoke vtable function is ignored, instead the continuation to return to is expected to be in P1. All of what used to be just plain 'invoke' now should be 'invokecc' -- this will do the extra setup. So in the normal cases we should use: invokecc # rather than invoke invoke P1# rather than ret All imcc tests pass if the attached tiny patch is applied. Perl6 on the other hand I have never looked at, but I can do that next I guess ... Oh, one other difference is that 'invoke Px' will now put the sub from Px into P0, since this is where the callee will expect it to be. Or is this form of the op intended for something else? I am not satisfied with the time taken to make a call. I did some rough benchmarking and the parrot implementation makes us slower than python 2.2.1. Optimized parrot build? $ perl assemble.pl test.pasm test.pbc ; time ./parrot test.pbc CGP or jit should be a lot faster. Adding --jit does not seem to make a difference. Am I missing somthing? Some minor remarks: - the changes s/interp/interpreter/ make it harder the read the real changes - and I don't see any benefit to rename variable names. This was for consistency since everywhere else 'interpreter' seems to be used. - you are undoing some PMC_data changes. Doh! -- Jonathan Sillito imcc.patch Description: Binary data
Re: [perl #22633] [PATCH] convert parrot to continuation passing style
On Wed, 11 Jun 2003, Leopold Toetsch wrote: Jonathan Sillito wrote: Why not just leave the old behaviour? IMHO[1]: - Make a new class based on Continuations - invokecc and such are based on it [snip] [1] I don't know too much about all the HL stuff. But anyway, some languages might be quite fine with the current implementation (which seems to be more lightweight, when it just comes to calling a plain subroutine) Have a look at P6Cs usage for exceptions and in regexen code. I know, its not final, but its a working implementation. Some less fancy HL might be just fine with the way how its working currently. Or I'm totally wrong here ;-) Here is another suggestion (I think I mentioned this in another email) we could support a few different types of continuations. The simplest continuation could be just a saved return address (i.e. an opcode_t*). This would be roughly as lightweight as the current implementation, I think. What do you think? I am thinking it would be easier to have one calling convention then callees know what to expect. invokecc .LiteContinuation # or something ... One more thing Leo (excuse my ignorance) why is there a stack calling convention in imcc? How does it relate to calling subs via the calling convention? -- Jonathan Sillito
RE: [perl #22633] [PATCH] convert parrot to continuation passing style
-Original Message- From: Jerome Vouillon [mailto:[EMAIL PROTECTED] The python interpreter seems rather slow. I get these numbers with the Ocaml bytecode interpreter. mistral-jerome:/tmp time python test.py python test.py 2,59s user 0,00s system 100% cpu 2,582 total mistral-jerome:/tmp ocamlc -o tst test.ml; time ./tst ./tst 0,14s user 0,00s system 106% cpu 0,131 total mistral-jerome:/tmp cat test.ml let foo () = () in for i = 1 to 100 do foo () done That is impressive. I don't know Ocaml but do you think there is an optimization being done since foo takes no args, returns not values and has an empty body? Also I should have mentioned that python spends between one third and one half of its time executing the loop instructions (test and increment). Parrot is much faster at this of course. Parrot sub and method calls can be made faster or slower depending on how much of the context needs to be saved. I can imagine several types of continuations that differ on how much context they save and restore: a. only an opcode ptr to jump to b. opcode and the stacks c. opcode, stacks and half of the registers d. opcode, stacks and all of the registers The patch I sent supports two types: type b (in continuation.pmc) and type d (in completecontext.pmc). Also in this patch is the option to not create a new continuation --as in a tail call-- which of course makes it very fast. -- Jonathan Sillito
RE: [perl #22549] [PATCH] rename invoke to call, and more
Hey, thanks for the comments. So you suggest leaving as the op as invoke? I don't mind, I just think we should be consistent in our naming; what about having the following four ops: - invoke - invokecc - invoke_method - invokecc_method You also wondered about the need for the 'cc' variants of these ops. If parrot's calling convention is to be continuation passing style then before each invoke we need to set up a continuation (in P1). In the common case this is just the current continuation. In pasm this could be: new P1, .Continuation set_addr I3, returnhere set P1, I3 invoke # or invoke_method returnhere: # etc ... With a 'cc' variant the common case is simplified to be just: invokecc # or invokecc_method # etc ... What do you think? Is it worth two more ops? BTW does anyone (leo?, dan?) want to comment on my idea for getting rid of the register stacks etc: calling convention and continuation ramblings http://xrl.us/iy8 Jonathan Sillito -Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED] Jonathan Sillito [EMAIL PROTECTED] wrote: 1. some adding and renaming in core.ops, which gives the following ops: - call() - call(in PMC) Suboptimal. We will get a name clash in imcc. (Imcc has call as an alias for bsr) 2. adds pmc access macros to register.h (as suggested by Mitchell). Thats fine. 3. updates tests, examples and documentation to use call instead of invoke. still to do: - update language/imcc to use call instead of invoke?? This - if ever - can only be done in one big change in parrot and imcc. But I don't know, why we actually should s/invoke/call/. bsr/call is similar to a hardware CPU subroutine call, so I think, it should remain call (in imcc). invoke is a higher level construct and therfore deserves its special name. - add callcc and callcc_method - patch coming soon Why do we need another 2 ops? invoke on the appropriate class should be enough. leo
calling convention and continuation ramblings
I have a working implementation that that switches parrot to a continuation passing style. While working on cleaning up a few things up, I got the following idea ... The current parrot context struct has a set of register stacks struct IRegChunk *int_reg_top; struct NRegChunk *num_reg_top; etc ... These are used when saving and restoring the registers. Are they used other than when following the (old) calling convention? I would like to get rid of these register stacks. In their place I would like to introduce a context object (call it a continuation?) that saves and restores the stacks (user_stack, pad_stack, control_stack, and intstack) and the last half of the registers: P16-P31, I16-I31, etc. (These registers are not involved in the calling or returning convention.) This would make it unnecessary to put a saveall and a restoreall around each call/callcc. Of course it would still be possible to save and restore individual registers on the user stack. Calling a subroutine would look like (note: no saveall/restoreall needed) set P0, ... # put Sub PMC in place callcc # creates a context object # invokes the sub in P0 or for tail calls and other fancy stuff set P0, ... # put Sub PMC in place set P1, ... # put some context in P1 (unless it # is already in place as it would # be for most tail calls) call # invokes the sub in P0, the current # context is not saved returning looks like sub: # put return values in registers ... return # invokes context in P1, which # restores context etc or even just sub: # put return values in registers ... call P1 # same as return Just to be clear my current implementation does most of this, except that none of the registers are saved as part of the context, just the stacks (including the register stacks). So my proposal is to get rid of the register stacks and have the context object save (and restore) *half* of the registers in addition to the user, pad, control and int stacks. This seems like a nice approach to me as it simplifies the Parrot_Context struct and the calling and returning from subs and methods. Comments? -- Jonathan Sillito
RE: Method calling
Dan, Why is there a callmeth op? Can't we just use a regular invoke as with other subs? Or does the callmeth op do both a find and invoke as an optimization? Jonathan Sillito -Original Message- From: Dan Sugalski [mailto:[EMAIL PROTECTED] Nope, not objects, but at least it's partway there. This bit is about making method calls. We've two issues on the front end. First, we need to be able to get a method PMC from an object, in those cases where we want to save that for later, and second we need to call methods. So, here's how we're going to do it. We add three ops, findmeth, callmeth and callmethcc. (The latter just automatically takes a continuation for the following op and stashes it in P2, while the former assumes one has been put in P2 already) They all find a method PMC based on the object and method name already loaded. The call ops then call that PMC's invoke vtable entry, which acts as normal. So the sequence is: P0 = P2-find_method(interpreter, P2); and for the call ops, then: dest = P0-invoke(interpreter, P0, expr NEXT()); goto ADDRESS(dest); The returned method PMC handles anything fancy--multimethod dispatch and whatnot. We need base engine support for MMD and method caching, amongst other things, but we can get to that later. The method PMC returned by findmeth can be invoked as a regular subroutine, so we're fine there. I'm not, at the moment, leaning towards a separate invoke this pre-fetched PMC sub as a method op, since we're not passing on any information as to how a PMC is invoked outside of there being an object in P2, but I can be convinced otherwise if we can make a good case for languages actually using that information. I'm thinking at this point, since we need to add the call and callcc ops as it is, that we should probably have tail versions of all these ops, which just puts the various bits from the continuation in P1 back before making the call, but we can talk about that later if we want. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
RE: Method calling
Thanks Dan. One little picky thing what is the naming convention for ops? find_method (currently in core.ops), call_method, and call_method_cc (or callcc_method?) or findmeth, callmeth, and callmethcc (or callccmeth?) or findmethod, callmethod, and callmethodcc (or callccmethod?) Also, should the current 'invoke' op be changed to 'call'? I don't care exactly what the names are, but consistency is nice. Jonathan -Original Message- From: Dan Sugalski [mailto:[EMAIL PROTECTED] At 9:20 AM -0700 5/30/03, Jonathan Sillito wrote: Dan, Why is there a callmeth op? Can't we just use a regular invoke as with other subs? Or does the callmeth op do both a find and invoke as an optimization? It does a find and invoke, and the callmethcc does a find, cc-capture, and invoke. I'm not sure if there'll be much win, but it is more information available to analyzers, so they *know* that this is a method call rather than a random sub call. I figure the vast majority of the method calls most languages make will be either callmeth or callmethcc calls, so it makes sense to wad up the functionality in a single op. -Original Message- From: Dan Sugalski [mailto:[EMAIL PROTECTED] Nope, not objects, but at least it's partway there. This bit is about making method calls. We've two issues on the front end. First, we need to be able to get a method PMC from an object, in those cases where we want to save that for later, and second we need to call methods. So, here's how we're going to do it. We add three ops, findmeth, callmeth and callmethcc. (The latter just automatically takes a continuation for the following op and stashes it in P2, while the former assumes one has been put in P2 already) They all find a method PMC based on the object and method name already loaded. The call ops then call that PMC's invoke vtable entry, which acts as normal. So the sequence is: P0 = P2-find_method(interpreter, P2); and for the call ops, then: dest = P0-invoke(interpreter, P0, expr NEXT()); goto ADDRESS(dest); The returned method PMC handles anything fancy--multimethod dispatch and whatnot. We need base engine support for MMD and method caching, amongst other things, but we can get to that later. The method PMC returned by findmeth can be invoked as a regular subroutine, so we're fine there. I'm not, at the moment, leaning towards a separate invoke this pre-fetched PMC sub as a method op, since we're not passing on any information as to how a PMC is invoked outside of there being an object in P2, but I can be convinced otherwise if we can make a good case for languages actually using that information. I'm thinking at this point, since we need to add the call and callcc ops as it is, that we should probably have tail versions of all these ops, which just puts the various bits from the continuation in P1 back before making the call, but we can talk about that later if we want. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
RE: Method calling
Calling convention says that before a sub/method is invoked: - P0 Holds the object representing the subroutine. - P1 Holds the continuation for the caller, assuming this sub was called with callcc. Otherwise NULL. - P2 Holds the object the sub was called on. (For method calls) Or put another way P2 is the receiver object. So I guess this was a typo; the continuation should be stashed in P1. While I am at it, here is an **untested** implementation of the call_method op. I don't want to send a patch since I am not sure how to test this yet (since no PMCs respond to find_method). op call_method(in STR) { opcode_t *dest; /* assumes receiver object is in P2 */ PMC* receiver = interpreter-ctx.pmc_reg.registers[2]; PMC* method = receiver-vtable-find_method(interpreter, receiver, $1); /* calling convention says that method should be in P0 and name in S0 */ interpreter-ctx.pmc_reg.registers[0] = method; interpreted-ctx.string_reg.registers[0] = $1; dest = (opcode_t *)method-vtable-invoke(interpreter, method, expr NEXT()); goto ADDRESS(dest); } op call_method(in PMC, in STR) { opcode_t *dest; PMC* method = $1-vtable-find_method(interpreter, $1, $2); /* calling convention says that receiver should be in P2 and method in P0 */ interpreter-ctx.pmc_reg.registers[0] = method; interpreter-ctx.pmc_reg.registers[2] = $1; interpreted-ctx.string_reg.registers[0] = $2; dest = (opcode_t *)method-vtable-invoke(interpreter, method, expr NEXT()); goto ADDRESS(dest); } -- Jonathan Sillito -Original Message- From: Nicholas Clark [mailto:[EMAIL PROTECTED] Behalf Of Nicholas Clark I'm not sure if I'm asking a stupid question here, but: On Fri, May 30, 2003 at 08:12:34AM -0400, Dan Sugalski wrote: We add three ops, findmeth, callmeth and callmethcc. (The latter just automatically takes a continuation for the following op and stashes it in P2, while the former assumes one has been put in P2 already) You say P2 is a continuation They all find a method PMC based on the object and method name already loaded. The call ops then call that PMC's invoke vtable entry, which acts as normal. So the sequence is: P0 = P2-find_method(interpreter, P2); But you seem to be using P2 like it's the object I'm confused. Surely there are 3 things to play with - object, method name and continuation to return to? If so, are they P0, P1 and P2 before these ops? Nicholas Clark
RE: coroutines end and DFG
-Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED] Does a couroutine end? And how? The current implementation jumps forth and back by the Binvoke opcode, one is a call coroutine the other is a yield. There seems to be no possibility, that the coroutine states, I'm finished now - with possibly meaning don't call me again. That's correct. And from imcc's register allocations POV the whole coroutine stuff is a PITA, no registers are preserved, AFAIK, so a coroutines and the caller + all edges out from both do share the same registers, don't they? They do, except that each coroutine has its own user stack so saveall and restoreall can work properly. -- jonathan sillito
RE: Three questions
-Original Message- From: Kevin Reid [mailto:[EMAIL PROTECTED]] 0. PDD 3 says: P1 Holds the continuation for the caller, assuming this sub was called with callcc. Otherwise NULL. and implies a similar possible absence for P2. How does one ensure that a PMC register is 'NULL'? One other example language compiler implies that there is no(t yet) an op for this. 1. Is there a complete example (e.g. multiple lexically nested subroutines using the full PDD3 calling conventions) of how the pad operations are intended to be used? Some examples are in: examples/assembly/lexical.pasm examples/assembly/lexical2.pasm t/op/lexicals.t t/pmc/scratchpad.t t/pmc/sub.t These are probably not sufficient, I still intended (this week I hope) to post a how to document for the lexical stuff. I've implemented what appears to be appropriate usage based on examination of t/pmc/sub.t and core_ops.pod, but it is not exhibiting proper closure behavior - all subs share the same state. Would you like to post your code? Then we can figure out if you have found a bug or if we just need to clarify how to use the lexical ops etc. -- jonathan
RE: Objects, methods, attributes, properties, and other related frobnitzes
-Original Message- From: Andy Wardley [mailto:[EMAIL PROTECTED]]On Behalf Of Andy Wardley Dan Sugalski wrote much sense, including these gems: *) Method: Some sort of action that an object can do. Methods are global and public--only one foo method for an object. Methods may be inherited from parent classes, or redefined in a particular class. Redefined methods hide parent class methods of the same name What about redefining methods for a particular object instance? It's something that Ruby does and can be extremely useful. Behind the scenes ruby creates a new (anonymous) subclass, which contains the new method. -- jonathan
RE: Objects, finally (try 1)
I realize this will vary from language to language, but generally we will need a PMC that encapsulates a method (and responds to the invoke vtable method like Sub, or maybe the Sub PMC could do?). This python code is interesting: class A: def f (self): print A.f() def g (self): print g() a = A() a.f()# output: A.f() x = a.f # get the method, a limited form of currying # since the first arg (a==self) is stored x() # output: A.f() setattr(A, f, g) # replace A's f with g a.f()# output: g() x() # output (still): A.f() !!! Which shows that the dispatch (i.e. selecting which method to call) can happen before the invocation. -- Jonathan Sillito -Original Message- From: Dan Sugalski [mailto:[EMAIL PROTECTED]] At 8:53 PM -0800 1/14/03, Adriano wrote: On Tue, 14 Jan 2003 17:18:22 -0500, Dan Sugalski [EMAIL PROTECTED] wrote: Dan: You're off. It'll be something like: callmethod Px, method_name or jmpmethod Px, method_name Jonathan: Is there going to be any way to (in PASM) find a method with out invoking it? I am not sure, but it may be useful for currying and some efficiency stuff (like moving dispatch outside of a loop that repeatedly invokes a method). Dan: Yep. There should be a can operator, though I'm not sure how often one wants to check for the existence of a method in an object without calling it. But no reason not to. More for rev 2. I think what Jonathan asked for was an operator for returning a method (as an object) which can be invoked later with some arguments (or even applied with a partial list of arguments for currying). This would be a lot more useful than a yes-or-no answer about the existence of a method. I thought about this--it's what the find_method vtable method was for in the first place. Unfortunately, as was pointed out to me, there's no good way to cache the result, since it could potentially be wrong by the time the method is actually called. We could potentially get around this if we put in place a notification framework to invalidate these method handles, but that means we have to have a fair amount of infrastructure in place to do that. (Though, honestly, I do really like the idea, as it means we can be faster by default and just pay the price when things change, but there's that pesky code that needs writing and systems that need designing to support it...) -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
RE: Objects, finally (try 1)
Sounds like we want objects *and* classes to support: static_attribs - which are defined at compile time and accessed by offset probably stored in an array. dynamic_attribs - which come and go at run time and are generally accessed by name and likely stored in a hash. -- Jonathan Sillito -Original Message- From: Nicholas Clark [mailto:[EMAIL PROTECTED]] Sent: January 15, 2003 12:41 PM To: Dan Sugalski Cc: Gopal V; [EMAIL PROTECTED] Subject: Re: Objects, finally (try 1) On Wed, Jan 15, 2003 at 11:17:17AM -0500, Dan Sugalski wrote: In that case they'd correspond to our properties, and I can already feel a massive terminology disconnect looming. Maybe we should rename properties and attributes to frobs and thingies, just so there's no overlap. :( We could call them houses and hotels - you'd only be allowed attributes after you had 4 properties, and if you want to mortgage, er serialise the object you'd have to hand them all back to the bank, er GC system. Mmm. Maybe that's taking the analogy well beyond breaking point. I've had a look in a thesaurus for words similar to property and attribute, and I can't see much that's good. idiosyncrasy is a nice word, but it's 6 syllables, and hard to spell. satellite seems quite good for objects and stuff that are hangers-on, as does chattels. I quite liked the idea of virtue for a quality, although I'm not sure if Larry would sanction PMCs having vices as well :-) The downside of finding completely new names for these two concepts is that everyone would have to learn what they meant. The upside is that there would be no confusion with every other language's contradictory definitions. Nicholas Clark
RE: Objects, finally (try 1)
Dan, Below are some questions about this ... -Original Message- From: Dan Sugalski [mailto:[EMAIL PROTECTED]] [snip] Objects, as far as I see it, have the following properties: 1) They have runtime-assignable properties Terminology question: what is the difference between a property and an attribute? Perhaps the answer could go in the glossary. [snip] #3 Since each class has a PMC type, we just need to associate the PMC type with the data a class needs. Also pretty much no big deal, and something we already have facilities for. So, while there may be exceptions, generally all classes will be instances of the Class PMC, true? [snip] The call/jmpmeth opcodes either make a returnable or non-returnable method call. They fetch the function pointer from the object PMC and either dispatch to it or save the current state and jsr to it. Note that you can't jmpmeth into a C-implemented method, so no tail calling into those without some wrapper opcodes. The registers still need to be set up appropriately, just like with a regular sub call. So the call opcode takes a method name or offset and calls a vtable method to find the method and then invokes it? The find_method vtable entry should die, and be replaced with a plain method entry. This should return either the address of the start of the method's bytecode, or NULL. The NULL return is for those cases where the method actually executed via native code, and thus doesn't have to go anywhere. If an address is returned it's expected that the engine will immediately dispatch to that spot, obeying parrot's calling conventions. Not sure what this means, does it mean that there is a method named find_method accessed something like call Px, Py, find_method which I can then call to find the method or am I off? [snip] The structures: *) Attr PMCs have an array off their data pointer. *) Classes are variants of Attr PMCs. They have the following guaranteed attributes in slots: 0) Hash with class name to attribute offset I am not sure what this means, Don't we already have the class and it's attributes if we are accessing these slots? 1) Hash with attribute name to attribute offset (relative to the offset found from the hash in slot 0, generally known at compile time, but introspection is nice) 2) Integer number of attributes this class has 3) Notification array Do we store ptrs to parent classes in one of these slots? Also Can I access slots like: set Px, Py[1]# store the name to offset hash in Px [snip] So to sum up we need the following pmc's: pmclass Ref { data is a pointer to an object } pmclass Attr { data is an array of attributes } pmclass Class extends Attr { } pmclass Object { this was not explained, but I guess it at least has a reference to a Class and field data ??? } Does that cover it? -- Jonathan Sillito
RE: Objects, finally (try 1)
-Original Message- From: Dan Sugalski [mailto:[EMAIL PROTECTED]] A property is a runtime assignable name/value pair that you stick on a variable or value. An attribute is a named variable that all objects of a particular class have. Properties can come and go at runtime, but attributes are fixed. (I think you could also consider attributes instance variables, but I'm a bit OO fuzzy so I'm not sure that's entirely right) Ok, in the case of python or ruby, instance variables are not fixed and they are not declared as part of the class. I suppose this can be handled by giving such classes one hash attribute for storing these instance variables. You're off. It'll be something like: callmethod Px, method_name or jmpmethod Px, method_name Is there going to be any way to (in PASM) find a method with out invoking it? I am not sure, but it may be useful for currying and some efficiency stuff (like moving dispatch outside of a loop that repeatedly invokes a method). Do we store ptrs to parent classes in one of these slots? Also Can I access slots like: set Px, Py[1]# store the name to offset hash in Px No the parent's gotten to via the vtable, and yes you can. Sorry if this is obvious, but which vtable method is used to get the parents? Thanks! -- Jonathan Sillito
RE: [CVS ci] clone, dod stack reporting
-Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED]] Further remark: the scratchpad clone code looks dubious, the 2 lists in the data (lex) entry should probably cloned too - and at least the lex ptrs themselves. The destroy method leaks, because we can't cleanup duplicated lex ptrs. Can somone better knowing scratchpads comment on this please. I guess there is a related problem with the way the function scratchpad new works, since it needs to copy lex ptrs from enclosing scopes? I will look into it more in a bit ... -- Jonathan Sillito
RE: [PATCH] [CVS ci] clone, dod stack reporting
The attached patch fixes the problem. It changes Scratchpad's data pointer to be a pointer to an array of Parrot_Lexicals (rather than an array of pointers to Parrot_Lexicals). The (name and value) lists are shared but never the actual Parrot_Lexical ptr. So no more leak. Patch touches: -- classes/scratchpad.pmc -- sub.c -- t/pmc/scratchpad.t (adds a test) -- Jonathan Sillito -Original Message- From: Jonathan Sillito [mailto:[EMAIL PROTECTED]] -Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED]] Further remark: the scratchpad clone code looks dubious, the 2 lists in the data (lex) entry should probably cloned too - and at least the lex ptrs themselves. The destroy method leaks, because we can't cleanup duplicated lex ptrs. Can somone better knowing scratchpads comment on this please. I guess there is a related problem with the way the function scratchpad new works, since it needs to copy lex ptrs from enclosing scopes? I will look into it more in a bit ... scratchpad_leak.patch Description: Binary data
RE: [perl #18170] [PATCH] very complete lexical scope implementation
-Original Message- From: kj [mailto:[EMAIL PROTECTED]] I'm getting mixed results building from this morning's CVS -- on Linux/x86 I only get the t/op.lexicals.t failures, but on Darwin/PPC I'm also getting failures in t/pmc/scratchpad.t. Would your patch have anything to do with the latter? I'm still learning the internals, and haven't quite figured that out yet. With a fresh checkout I am getting no errors in Linux/x86, however I don't have access to a Darwin/PPC box. Would you mind getting the latest from CVS and try again on Darwin/PPC? As much detail as you can send me about any failures would be appreciated. Thanks. -- Jonathan Sillito
RE: [perl #18170] [PATCH] very complete lexical scope implementation
Steve, Thanks! Was there a problem applying the patch? I just checked out a new cvs images and the file t/op/lexicals.t has not been updated. As a result, a few tests are failing. Should I resubmit the part of the patch that updates t/op/lexicals.t? -- Jonathan Sillito -Original Message- From: Steve Fink [mailto:steve;fink.com] Sent: November 14, 2002 9:51 PM To: [EMAIL PROTECTED] Subject: Re: [perl #18170] [PATCH] very complete lexical scope implementation Applied, finally. Thanks.
RE: [purl #18379] [PATCH] Lexical scope and functions in languages/scheme
-Original Message- From: Dan Sugalski [mailto:dan;sidhe.org] At 2:07 PM + 11/14/02, Jürgen Bömmels (via RT) wrote: This patch obsoletes #17109 (which isn't applied yet). Does it obsolete 18170? No, it seems to depend on it. -Original Message- From: Jürgen Bömmels (via RT) DEPENDS ON #18170 [... reordered ...] One thing I'm not very happy about that I need 2 pop_pads at function return, one cleaning up the newly generated pad from new_pad, and one for cleaning up the stored scope of function definition. I have no idea how to solve this. Well currently the way to return from a sub is using the ret op. It may be useful to add a 'return' op that does one pop of the lexical stack (in addition to doing what ret does). This would mean that a sub would only need an explicit pop_pad for each local scope created. However, subs that are not closures could continue using the ret op. (So Dan, should I submit a patch adding a 'return' op?). -- Jonathan Sillito
Re: [perl #18170] [PATCH] very complete lexical scope implementation
On 2 Nov 2002, Juergen Boemmels wrote: Ok, I tested the patch (I tried to use this scratchpads for the scheme compiler) One thing I missed (or at least didn't find): How can I generate a new scope? new_pad generates a new one one the pad stack with a size which is actually smaller than the current one. I may be misunderstanding the question, but I'll try and answer anyway. There are two ways to create a new scratchpad. The first looks like: op new_pad(in INT) which creates a new scratchpad and grabs to depth int of the current scope (i.e. the scratchpad at the top of the stack). This I think will be the usual way to create a new scope. The alternative looks like this: op new_pad(out PMC, in INT) which does the same as the previous form, but does not push the new pad on the stack, rather it is stored in the given PMC register. Does that answer your question? Apart from that: Nice patch. -- Jonathan Sillito
RE: [perl #18170] [PATCH] very complete lexical scope implementation
-Original Message- From: Leopold Toetsch [mailto:lt;toetsch.at] WRT your comment: should we use a List * here, I slightly vote for yes. In the long run we could use List as the basic store for registers and stacks as well. List would only need a small extension to manage arbitrary sized data. Ok, if the code goes in I can easily change this ... WRT names: wouldn't be a hash faster then the linear search? My thinking is that compilers will most often generate code that accesses lexicals using position and the current structure provides constant time by position access to the lexicals. While by name access is linear time. As you say, this could be improved using a hash, but at some cost in space (maybe?). In any case, the implementation details of the struct Parrot_Lexicals are (currently) only touched in sub.c, so it should be easy to change the approach. Thanks for the comments, anything else? -- Jonathan Sillito
RE: Scratchpad confusion
I think, I can answer a few of these questions. -Original Message- From: Allen Short [mailto:washort;twistedmatrix.com] The ops described in PDD 6 and docs/parrot_assembly.pod for scratchpads appear to be subtly different from the ones actually in core.ops. In particular, i was led astray by the docs referring to the newpad op and core.ops implementing new_pad. which is it supposed to be? =) Neither, Dan Sugalski owes us an update, which should be coming soon ... I started investigating scratchpads because I'm interested in improving the scheme compiler. I'd agree with Sean O'Rourke's comments (http://archive.develooper.com/perl6-internals;perl.org/msg12722.html) -- the current ops seem too limited; in particular, I dont see how one would save a scratchpad with a function definition, or modify the toplevel scratchpad. Looking beyond Scheme, it appears to me that other languages would need more flexible handling of scoping as well; Common Lisp, for example, keeps functions in a separate namespace from other variables. Being new to Parrot hacking, could someone point me at the rationale for making scratchpads a special case, rather than a PMC? I am sure they will be a PMC. In fact two different patches have been submitted to make them PMCs, one by me and a better one by Sean O'Rourke. Sean's has not been committed yet, probably because he is waiting for a decision on the more flexible ops by Dan. -- Jonathan Sillito
RE: [PATCH] PMC initializer stuff
-Original Message- From: Dan Sugalski [mailto:dan;sidhe.org] Okay, it's been a while, I've been out of it, it's time to start getting going. Welcome back! Today's first topic: PMCs with real initializers. Here's a snip from the updated PDD2: -- =item void init_pmc(INTERP, PMC* self, PMC* initializer) This form of the init method takes a single initializer parameter. The initializer is an array that contains keys and values. The meaning of the keys and their corresponding values is left up to the PMC. Then I assume that the op new_pmc should be added which calls the init_pmc vtable function? If so the patch in [perl #17811] should do the trick. [snip] Dimension, 3, Color, Green]. Note that, in all cases, the array is an array of PMCs. (So you get either an int PMC or a string PMC in the list of keys) Do you mean PerlInt and PerlString? Or do we want Int and String PMCs? In the case of Sub PMCs an initializer could provide an address for the sub to jump to which could look like this: # # build initializer # new P10, .Array set P10, 2 new P11, .PerlString set P11, address new P12, .PerlInt set_addr I0, subroutine set P12, I0 set P10[0], P11 set P10[1], P12 # # construct Sub using initializer # new P0, .Sub, P10 invoke end subroutine: print in sub routine\n ret This seems tedious, but maybe I am missing the point? Anyway if this is what we want the attached patch modifies sub.pmc to support this, and adds a test to t/pmc/sub.t. This patch depends on [perl #17811]. -- Jonathan Sillito sub_init.patch Description: Binary data
RE: [perl #17739] [PATCH] Tests for assign ops
-Original Message- From: Peter Gibbs [mailto:[EMAIL PROTECTED]] [snip] An interesting question, not discussed when the change was initiated, relates to property assignments eg new P0, .PerlArray set P0, 6 This most certainly does not set register P0 to six, so the 'set' opcode should not apply, but it is also not really an assignment either. Any thoughts? there is a similar problem with subs new P0, .Sub set P0, some label I guess the problem is that set is being used for too much? This is the way I thought things were headed: set_x_x just moves a pointer or a value, possibly needing a cast, copy or conversion $1 = $2; $1 = string_from_num($2); etc While assign_p_x calls the appropriate vtable method $1-vtable-set_pmc(interpreter, $1, $2); $1-vtable-set_integer_native(interpreter, $1, $2); etc The above .Sub and .PerlArray examples could be handled with op new(out PMC, in INT, in PMC) op new(out PMC, in INT, in INT) etc instead of the set op. I think this separation could be more clear, but I suppose this leaves some cases out. So maybe a set_property op? Though some things could be left to _methods_ instead of ops. -- Jonathan Sillito The primary goal of the exercise was to be able to distinguish between 'set P0, P1' which simply sets the P0 register equal to the P1 register, and 'assign P0, P1' which would, somehow, cause the existing PMC referenced by P0 to acquire the value of the PMC referenced by P1 (via the vtable method set_pmc). How to achieve this has never been resolved. The changes of the other 'set P0, xxx' opcodes to 'assign' are basically for consistency. -- Peter Gibbs EmKel Systems
RE: pre-PATCH: functions in languages/scheme
-Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] The current pad_stack handling is very much tied to Sub.pmc. The only way of getting the current scope is creation of a new sub; the only way setting the current pad is invoking this sub. But I didn't used Sub.pmc, partly because the lexical scope is not working in CVS subs and i don't want to add yet another set of prepatches, partly because I added the formal parameters to the procedure object. So I think there are two possible ways out: adding operations to core.ops (get_current_pad_p and new_pad_p) or rolling the lexical pad on my own. It would be nice if parrot provided the lexical scope semantics scheme (and other languages) needs rather than have each language implement their own. I guess this would be Dan's call, but just as another suggestion, could the lexical ops be limited to something like the following, plus keyed access to the pad? new Px, .ScratchPad push_pad Px peek_pad Px pop_pad Px (The find_lex and store_lex ops would be unnecessary, but could be kept of course) And there is a diffrence between define and set!, define creates a new binding in the top lexical scope, ignoring every previous definition, but set! changes the binding of a formerly defined variable. This 2 diffrent operations don't map very well on the store_lex_s_p operation. I used the diffrent keyed access methods of Seans Scratchpad.pmc for differentating this use cases: define : P31[-1;S0] set! : P31[S0] Assuming Sean's patch (not my above suggestioned ops), would this implement the correct semantics for scheme's (define a ...): new_pad 1 new P0, .SchemeUndef store_lex 1, a, P0 # ... pop_pad and could (set! a 12) inside of the above define be: new P0, .SchemeInteger store_lex a, P0 # looks back through nested pads -- Jonathan Sillito
RE: pre-PATCH: lexicals
-Original Message- From: Piers Cawley [mailto:[EMAIL PROTECTED]] Jonathan Sillito [EMAIL PROTECTED] writes: get_counter: new_pad 1 Doesn't this violate the 'caller saves' principle, making it hard to do tail call optimization? Would it make sense to move the creation of a new pad into the Sub's invoke method? I am not sure how this violates the 'caller saves' principle, unless you mean that the caller should be saving its own scratch pad if necessary? I did notice that this is in pdd03: The caller is responsible for preserving any environment it is interested in keeping. This includes any and all registers, lexical scoping and scratchpads, opcode libraries, and so forth. I suppose scratchpads could be an exception, to this? I have to think more about the tail call optimization. I am not sure how putting the creation of the new pad into the sub's invoke method would help, it still seems like it would be created each time the method was invoked (which seems equivalent to putting a new_pad instruction at the top ... On the other hand, if the instruction is left to the PASM for some subs it could easily be optomized away by the compiler. Or maybe it could be conditional? get_counter: new_pad 1 get_counter_no_new_pad: # etc Would this address the problem? Or am I missing somthing? -- Jonathan Sillito
Re: [perl #17030] [PATCH] Implementation of Lists for languages/scheme
Sorry if this comment is out of context, I am behind but catching up. The patch in [perl #16797] adds a scratchpad pmc (among other things). Hopefully it is not too far out of date to apply. I believe Melvin is looking into it ... -- Jonathan Sillito On Tue, 10 Sep 2002, Piers Cawley wrote: Juergen Boemmels [EMAIL PROTECTED] writes: Piers Cawley [EMAIL PROTECTED] writes: { type = '*environment*' value = {scratchpad = aScratchPadPMC} There is already a ScratchPadPMC. Where is it? It's not in classes/, is it. As a first implementation a PerlHash is sufficent, (I actually have a patch doing exactly this, it just needs a little polish. Maybe I will submit it tomorrow). But most of the lexical scope can resolved at compile time. parrot_assembly.pod describes an op fetch_lex_p_i_i but this seems not implemented yet.
Re: Lexicals
I am not the best one to answer these questions, but I will make some comments anyway, though Dan is/was planning to give us an authoritative position doc on some of these issues. I have done some work on some of this, but my latest code submission has not been accepted yet. On 9 Sep 2002, Juergen Boemmels wrote: I have several questions regarding lexicals. There is a discrepancy between parrot_assembly.pod and core.ops parrot_assembly.pod says that find_lex will return a pointer, where as core.ops uses find_lex to retrive a value and store_lex to set this value. Which of this is correct? I would think it will become pointers. parrot_assembly mentions a fetch_lex_p_i_i but there is no implementation yet. This functions would be very handy when you know at compile time whats in the lexical scope. Is this left-out intentional or just because nobody has yet implemented it. In the later case, is somebody already working on this? This is still the plan and I believe that by index is going to be the fastest way to access lexicals. I have been thinking about implementing something for this but I am waiting to see if my previous patch gets committed so I can be sure I am heading in a reasonable direction. On the other hand maybe I should just press forward? How are the integers of the lexicals in the pad assigned? I assume they get increasing numbers for each store_lex, starting at 0 for a new pad. Correct? How do I store to a lexical by number? Shouldn't be there also a store_lex_i_i_p (or set_lex to indicate that it is a change of an already existing binding). Dan has hinted that there will be some way, in parrot assembly, to provide a static pad descriptor that could be used to put all lexicals in place when the pad is first created. Is there a possibility to get a pointer to the current pad, to store it in the closure? (Im not sure, maybe only the top-pad is needed). There need also be a way to reinstate the saved lexical. I have submitted code that does this sort of thing for subroutines. -- Jonathan Sillito
Re: A show of hands of the non-perl people?
On Wed, 2002-09-04 at 04:31, Dan Sugalski wrote: Can I get a quick show of hands for the folks working on Parrot, even peripherally, who *aren't* perl folks? I am not a perl person. I haven't done much work on parrot, and it seems that most of what I have done is on hold or up in the air still (my patch in [perl #16797] for example). But I am hoping to somehow get more involved. Also, for what it is worth, I personally don't much care what the email list is called. -- Jonathan Sillito
Re: [COMMIT] GC_DEBUG, Some GC Fixes, and Remaining GC Bugs
Mike, I tried to have a look at the lexicals and subs issues but I am finding that with the GC_DEBUG flag set to 1, I *always* get a segmentation fault, even for simple pasm files like : set I0, 12 end or just: end Is there something I am doing wrong? I did a fresh checkout about an hour ago. ??? --- Jonathan Sillito On Mon, 2002-08-12 at 01:56, Mike Lambert wrote: Hey, I re-added the GC_DEBUG define today, and weeded out a bunch of issues. For those who don't remember, GC_DEBUG (currently in parrot.h) causes various limits and settings and logic to be setup such that GC bugs occur relatively soon after the offending code. It allocates one header at a time, and performs DOD and collection runs extremely frequently (effectively, anywhere they could possibly occur if GC_DEBUG weren't defined.) It's goal is to make GC bugs which appear only in complex programs...appear in simpler ones as well. Check the cvs-commit traffic if you're interested in what issues I've fixed already. From what I can tell, two things remain: - regexes (these are known to be broken. angel's latest patch should fix these in theory. Probably not worth spending time on fixing these.) - hashes (these were recently rewritten to use indices, a step forward, but they aren't 100% clean yet) - lexicals (there's one remaining issue on the last test I didn't look into) - subs (likely includes all variety of them. Basically, I got the wrong result on one test, instead of GPF failures like I received on the above bugs.) - possibly other that got lost in the noise of the above issues Anyone more well-versed in these departments than I care to take a look at the potential problems? Just change GC_DEBUG in parrot.h, and you can be on your way. :) Thanks, Mike Lambert
Re: [perl #16087] [PATCH] Scratchpad pmc
Dan, some time ago you mentioned that you were preparing a position doc on issues raised in the 'maybe-PATCH: sub/continuation/dlsym/coroutine clean-up' thread. Are you nearly ready with that doc? Does this patch (i.e. a scratchpad pmc) fit into what you have in mind? Sorry to be harassing you about this, but I am anxious to do more coding and I just want to be sure that I am moving in roughly the right direction ... ... well, while I am already harassing you two, I'll try a few questions. 1) The Parrot_Sub struct in sub.h has its own user_stack and control_stack. Why is this necessary? 2) If they are necessary, then does that mean the caller needs to save and restore their user_stack and control_stack? 3) Some of the caller save burden (and overhead?) could be minimized if there was 'ret' vtable method that was called to do some clean up ... ok so that is not a question just some random thought. 4) Parrot_Coroutine's 'init' is not longer used and can go away, I guess I could remove it in a future patch ... ok so that's not a question either. Anyway, thanks for any info! -- Jonathan Sillito On Thu, 2002-08-08 at 14:29, Jonathan Sillito wrote: # New Ticket Created by Jonathan Sillito # Please include the string: [perl #16087] # in the subject line of all future correspondence about this issue. # URL: http://rt.perl.org/rt2/Ticket/Display.html?id=16087 The main purpose of this patch is to give scratchpads a pointer to their parent pad. In the process I added a Scratchpad pmc that uses its data pointer to point to a PerlHash (temporarily) and uses its cache pointer to point to its parent. I am not sure about this use of the cache pointer, but it is only used internally so it should be easy to change. The scratchpad.pmc file is attached, the important bits (so far) are the init(), mark(), set_pmc_keyed() and get_pmc_keyed() vtable methods. The attached patch has the following effects: - changes lexical ops in core.ops to use Scratchpad pmc. - adds Scratchpad to enum in include/parrot/pmc.h - adds Parrot_Scratchpad_class_init(enum_class_Scratchpad); to global_setup.c - adds additional test to t/op/lexicals.t - fixes examples/assembly/lexicals.pasm (reverses PMC and string arguments to store_lex op). MISSING --- Access by integer index, I am waiting for a way to pass a pad descriptor (or at least the number of lexicals to go in the pad) to the init vtable method. There is no integration with subs/coroutines/continuations. I will add this if people think this approach is reasonable. Comments? -- Jonathan Sillito -- attachment 1 -- url: http://rt.perl.org/rt2/attach/33293/27417/874baa/lexicals.patch -- attachment 2 -- url: http://rt.perl.org/rt2/attach/33293/27418/a51da2/scratchpad.pmc Index: core.ops === RCS file: /cvs/public/parrot/core.ops,v retrieving revision 1.195 diff -u -r1.195 core.ops --- core.ops 7 Aug 2002 04:01:24 - 1.195 +++ core.ops 8 Aug 2002 20:19:54 - -3662,8 +3662,8 =cut op new_pad() { -PMC* hash = pmc_new(interpreter, enum_class_PerlHash); -stack_push(interpreter, interpreter-ctx.pad_stack, hash, STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL); +PMC * pad = pmc_new(interpreter, enum_class_Scratchpad); +stack_push(interpreter, interpreter-ctx.pad_stack, pad, STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL); goto NEXT(); } -3674,24 +3674,22 } op store_lex(in STR, in PMC) { -PMC * hash = NULL; +PMC * pad; KEY key; Stack_entry_type type = 0; MAKE_KEY(key, $1, enum_key_string, struct_val); -hash = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type); -hash-vtable-set_pmc_keyed(interpreter, hash, NULL, $2, key); +pad = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type); +pad-vtable-set_pmc_keyed(interpreter, pad, NULL, $2, key); goto NEXT(); } op find_lex(out PMC, in STR) { -PMC * hash = NULL; +PMC * pad; KEY key; Stack_entry_type type = 0; MAKE_KEY(key, $2, enum_key_string, struct_val); -hash = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type); -$1 = hash-vtable-get_pmc_keyed(interpreter, hash, key); - -/* FIXME: should the not found case be an internal_exception ? */ +pad = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type); +$1 = pad-vtable-get_pmc_keyed(interpreter, pad, key); goto NEXT(); } Index: global_setup.c === RCS file: /cvs/public/parrot/global_setup.c,v retrieving revision 1.31 diff -u -r1.31 global_setup.c --- global_setup.c4 Aug 2002 22:54:31 - 1.31 +++ global_setup.c8 Aug 2002 20:19:54 - -34,6
Re: questions about pdd03_calling_conventions.pod
On Tue, 2002-08-06 at 20:11, Sean O'Rourke wrote: On Tue, 6 Aug 2002, Dan Sugalski wrote: At 12:57 PM -0600 8/6/02, Jonathan Sillito wrote: Can a prototyped sub take a variable number of parameters (ie can it have 'rest' params?). If so, should there be some way for the caller to specify how many params are being passed in pmc registers? A prototyped sub can take a variable number of params, and there should be a counter somewhere. I thought that was specified, but apparently not. I'll fix that. I'm guessing this would be: I1 The number of items pushed onto the stack. Though I think what is missing is the number of PMC's passed in registers. The pdd mentions callcc, but the callcc op seems to be going away (replaced with invoke on a continuation pmc) ... is that the plan? Callcc needs to stay--its removal is an oversight. Does it? We can do the same thing (and other, more devious ones) with existing ops. From my understanding of pdd03, the exact implementation would be this: # P0 contains a function object new P1, .Continuation set_addr I4, L1 set P1, I4 # Setup rest of args invoke L1: I like it. What do you think Dan? -- Jonathan Sillito
Re: Lexical variables, scratchpads, closures, ...
On Fri, 2002-08-02 at 10:43, Jerome Vouillon wrote: Sure, you need a hash. But this can be a statically allocated hash, mapping variable names to indices. Could two parallel arrays work? One stores the lexicals (accessed by index) and the other stores the names of the lexicals. Then to access a lexical by name involves a sequential search through the (probably not large) array of names, to get the index, then the index is used to get the lexical from the other array. Or would that make access by name too slow? -- Jonathan Sillito
Re: maybe-PATCH: sub/continuation/dlsym/coroutine clean-up
Looks good to me. Couple of quick things, when I applied the patch locally, it indented the end bracket of the invoke op in core.ops which breaks ops2c.pl. Also the patch removed the yield op from core.ops, was this intentional? More comments below. On Tue, 2002-07-30 at 22:07, Sean O'Rourke wrote: This patch implements native extensions and continuations as pmcs. It also cleans up the existing Sub and Coroutine types, and removes the following now-obsolete ops: callco callcc capturecc call callnative These are all handled through various uses of invoke (see t/pmc/sub.t for simple examples). I like this, then the code generator does not need to know what type of sub it is dealing with. While I am thinking about it, would it make sense to distinguish between a sub and a closure? A sub would be a little more efficient in cases where a closure is not needed. [skipping] - not integrated with lexicals. Parrot is a fast-moving target nowadays! Current discussion on the list makes me wonder if this is still up in the air a bit. However I would be happy work on this, once I feel like I understand what the consensus is for lexicals ... -- Jonathan Sillito
Re: Lexical variables, scratchpads, closures, ...
On Wed, 2002-07-31 at 10:25, Jerome Vouillon wrote: Let us think a bit about the implementation of lexical variables. Thanks for spelling this out in such detail. Here is a variation based on the lexical ops (new_pad, pop_pad, store_lex, find_lex) committed yesterday. Note that lexical pads are stored in the Parrot_Context struct's pad_stack field (see include/parrot/interpreter.h). In what follows I assume that all lexicals are stored as pointers (instance of classes/pointer.pmc?) in the pad and that each scope will have a reference to all of the pointers it needs to know about. In other words a each pad has a pointer to all lexical variables declared or referenced in the scope associated with the pad. A given pointer object may live in multiple pads. So: - store_lex does not change the object that is in the hash, it just changes what the object points to, - and find_lex does not return the (pointer) object in the hash, it returns the object pointed to by the object in the hash. So here is my take on a slightly simpler example: sub foo { my $x = 13; return sub { print $x\n; }; } $foo() main: new_pad # push this on the lexical stack # some constant descriptor should also be passed # to the new_pad op which would then know about # the lexical variable 'x', and would create an # associated pointer object new P0, .Sub # gets current lexicals from interp's context set_addr I0, foo set P0, I0 # current hack to get the correct address in sub pop_pad invoke# assumes sub is in P0 # on invoke the sub pmc fixes the current # context to have the correct lexicals end foo: # We assume the closure is in P0 new P1, .Int store_lex P1, x # probably by number not by name but ... # the store would then store the new int in a # the pointer object already allocated set P1, 13 new_pad # again a constant descriptor should be passed # to the new_pad op which would then know about # the lexical variable 'x', and would get a pointer # object from the parent scope (ie would not # allocated a new pointer) new P0, .Sub # this would then get the correct lexical # info from interp's context so no need for a # set_pad op set_addr I0, sub set P0, I0 # current hack to get the correct address in sub pop_pad ret # return the sub object sub: # on invoke the correct lexicals are in the current scope find_lex P1, x # again probably by index not name # after this P1 holds the int pmc # print ret Does that make sense? -- Jonathan Sillito
Re: Lexical variables, scratchpads, closures, ...
On Wed, 2002-07-31 at 13:49, Jerome Vouillon wrote: On Wed, Jul 31, 2002 at 11:40:39AM -0600, Jonathan Sillito wrote: new_pad # push this on the lexical stack # some constant descriptor should also be passed # to the new_pad op which would then know about # the lexical variable 'x', and would create an # associated pointer object Do you really need a stack? A stack is how it is currently implemented. As Melvin suggested, this makes it easy to push an pop scopes as each block is entered and exited. There is an example of this in examples/assembly/lexicals.pasm Of course other approaches's are possible. When is the pointer object created? This part is not implemented currently. Once there is a pad descriptor that the assembler understands, the pointer object could be created immediately (maybe pointing to an instance of the PerlUndef pmc?). BTW: is anyone working on or thinking about pad descriptors right now? invoke# assumes sub is in P0 # on invoke the sub pmc fixes the current # context to have the correct lexicals Can you elaborate on this? What is done precisely to fix the current context? This also is not implemented (unless Sean O'Rourke's recent patch does this?) However the Sub (or Coroutine, or Continuation, or ...) PMC could have the responsibility of putting the correct context in place before actually jumping to the body of the sub. Melvin's code in sub.c has a start on this, I think ... I am kind of just thinking out loud here, but does that clear up anything? -- Jonathan Sillito
Re: [perl #15800] [PATCH] lexical scope ops, test and example
On Mon, 2002-07-29 at 17:12, Simon Glover wrote: I think you forgot to attach the patch... oops, now the files are attached ... - patch: lex.patch - test file: lexicals.t - example file: lexicals.pasm On Tue, 2002-07-30 at 02:14, Stephen Rawls wrote: --- Jonathan Sillito close_lex # end of nested lexical scope find_lex P3, a print P3 # prints 12 print \n end That's a typo, right? It should print the first value of a (10). Just making sure I'm not crazy ... Hey, thanks for reading this over. It is not a typo, but it may be incorrect. My code does overwrite previous lexicals in enclosing scopes (i.e. lexicals in pads lower on the stack), but maybe I have the semantics of the store_lex op wrong? The following example shows what I had in mind: my $x = 13; sub foo { $x = 12; } foo(); print $x; # prints 12 The alternative (what you have in mind I guess) is: my $x = 13; sub foo { my $x = 12; # notice the my } foo(); print $x; # prints 13 So I guess I see your point. Let me know if I should change the implementation (it would be a quick change). Also note that there is currently no support for accessing lexicals by index or for creating pads from descriptors. Thanks for any comments. -- Jonathan Sillito Index: core.ops === RCS file: /cvs/public/parrot/core.ops,v retrieving revision 1.187 diff -u -r1.187 core.ops --- core.ops 26 Jul 2002 19:15:56 - 1.187 +++ core.ops 29 Jul 2002 23:03:24 - -3604,6 +3604,24 +=item Bopen_lex() + +Start a new lexical scope + +=item Bclose_lex() + +Close most recently opened lexical scope + +=item Bstore_lex(in PMC, in STR) + +Store object $1 as lexical symbol $2. This currently involves +looking back through the stack of pads to see if there is an +entry (corresponding to $2) that should be overwritten. + +=item Bfind_lex(in PMC, in STR) + +Find the lexical variable named $2 and store it in $1 + =item Bstore_global(in PMC, in STR) Store global $1 as global symbol $2 -3613,6 +3631,80 Find the global named $2 and store it in $1 =cut + +op open_lex() { +PMC* hash = pmc_new(interpreter, enum_class_PerlHash); +stack_push(interpreter, interpreter-ctx.pad_stack, hash, STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL); + +goto NEXT(); +} + +op close_lex() { +stack_pop(interpreter, interpreter-ctx.pad_stack, NULL, STACK_ENTRY_DESTINATION); +goto NEXT(); +} + +op store_lex(in PMC, in STR) { +Stack_Chunk_t *cur_stack; +Stack_Entry_t *entry = NULL; +PMC * cur_hash = NULL; +PMC * found = NULL; +unsigned int i; +KEY key; +Stack_entry_type type = 0; + +MAKE_KEY(key, $2, enum_key_string, struct_val); + +/* walk back through stack of pads for the key */ +cur_stack = interpreter-ctx.pad_stack; +while (cur_stack) { +if (cur_stack-buffer) { +entry = (Stack_Entry_t *)(cur_stack-buffer-bufstart); +for (i = 0; i cur_stack-used; i++) { + cur_hash = (PMC *)entry[i].entry.pmc_val; + found = cur_hash-vtable-get_pmc_keyed(interpreter, cur_hash, key); + if (found) break; +} +} +cur_stack = cur_stack-prev; +} + +if (!found) { /* set the top pad to be cur_hash */ + cur_hash = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type); +} +cur_hash-vtable-set_pmc_keyed(interpreter, cur_hash, NULL, $1, key); + +goto NEXT(); +} + +op find_lex(out PMC, in STR) { +Stack_Chunk_t *cur_stack; +Stack_Entry_t *entry = NULL; +PMC * cur_hash = NULL; +PMC * found = NULL; +unsigned int i; +KEY key; + +MAKE_KEY(key, $2, enum_key_string, struct_val); + +cur_stack = interpreter-ctx.pad_stack; +while (cur_stack) { +if (cur_stack-buffer) { +entry = (Stack_Entry_t *)(cur_stack-buffer-bufstart); +for (i = 0; i cur_stack-used; i++) { + cur_hash = (PMC *)entry[i].entry.pmc_val; + found = cur_hash-vtable-get_pmc_keyed(interpreter, cur_hash, key); + if (found) break; +} +} +cur_stack = cur_stack-prev; +} + +/* found will still be NULL if key was not found + * FIXME: should the not found case be an internal_exception ? */ +$1 = found; +goto NEXT(); +} op store_global(in PMC, in STR) { KEY key; Index: dod.c === RCS file: /cvs/public/parrot/dod.c,v retrieving revision 1.8 diff -u -r1.8 dod.c --- dod.c 23 Jul 2002 07:25:02 - 1.8 +++ dod.c 29 Jul 2002 23:03:24 - -92,6 +92,23 } } +/* Walk lexical pad stack */ +cur_stack = interpreter-ctx.pad_stack; +while (cur_stack) { +if (cur_stack-buffer) { + buffer_lives(cur_stack-buffer); + entry = (Stack_Entry_t
Re: [perl #15800] [PATCH] lexical scope ops, test and example
Thanks for the correction. May I ask about the find_lex op? In my implementation it looks back through the stack of pads for the given lexical: new P0, .PerlInt new P1, .PerlInt set P0, 10 open_lex store_lex P0, a # nested lexical scope open_lex find_lex P1, a print P1 # prints 10 # etc Also, should open_lex/close_lex be named new_pad/close_pad instead? If you want to hold off on applying the patch, I will submit one with the correct semantics in the next couple of hours. Or if you have already submitted it I will send a patch to fix it. Thanks again. -- Jonathan Sillito On Tue, 2002-07-30 at 10:47, Melvin Smith wrote: See my 2 comments: new P0, .PerlInt new P1, .PerlInt new P2, .PerlInt new P3, .PerlInt set P0, 10 set P1, 11 set P2, 12 # outer most lexical scope open_lex New pad store_lex P0, a find_lex P3, a print P3 # prints 10 print \n # nested lexical scope open_lex store_lex P1, b find_lex P3, b print P3 # prints 11 print \n store_lex P2, a # overwrites previous a ^ Should not overwrite, should shadow since it is stored in the current pad find_lex P3, a print P3 # prints 12 print \n close_lex # end of nested lexical scope ^ Pad goes away, with b and a, so the outer values should be back in effect. find_lex P3, a print P3 # prints 12 print \n end I'll apply this, since it is clean, but the semantics need adjustment. Thanks, -Melvin Smith IBM :: Atlanta Innovation Center [EMAIL PROTECTED] :: 770-835-6984
Re: lexical scopes and scratchpads
Thanks for the response. On Tue, 2002-07-23 at 13:23, Melvin Smith wrote: [reordered] If you want to take a whack at it before I get to it, take a look at the global variable ops, although they aren't perfect. I just stacked them on top of the Hash PMC that we already had. If you think you won't get to it for a while then I would be happy to give it a stab. I started on a simple implementation. I decided to just use the PerlHash that we already have. I planned to add a new stack for lexical scopes, making it COW, and the newpad op would simply create a new Hash PMC and push it onto that stack, and vice-versa. [...] The fun part after you get the skeleton working is copying the pads on write for closures, etc. Do you think a linked list approach (like 'struct Stash' for globals) where each scope has a link to it's parent scope would be both simpler and sufficient? We could give the Parrot_Context struct a pointer to the current scope, and inside of the invoke method of the Closure (Sub?) PMC I think we would just need to set the interpreter's pointer to the correct scope, something like: interpreter-ctx.current_scope = SELF-scope; What do you think? Is there something I am misunderstanding about how closures work? On this line, we need to discuss the symbol table format for the bytecode. I played around a bit but nothing I wish to commit. I haven't given this any thought yet ... -- Jonathan Sillito
lexical scopes and scratchpads
Is now a good time to start a discussion on lexical scopes? Is anyone currently working on an implementation of scratchpads? I have sketched out a simple implementation, based on the struct at the end of this email, but there are somethings that I do not understand, so I am hoping someone can set me straight. Here are my two main questions: 1) How should a scratchpad be created. The only documentation I found was in docs/parrot_assembly.pod: Pad descriptors are templates for a particular pad. They are specified in the constant area of a bytecode file, and contain the names, types, and attributes for the variables referenced in the scope the pad is for. [...] newpad pad_descriptor Create a new scratchpad using pad_descriptor as a template. Has anyone worked out how pad descriptors will look and be handled by the assembler, passed to constructor, etc? 2) How are values stored in scratchpads? Will scratchpads only contain pointers? /* Scratchpad, for implementing lexically scoped variables. */ typedef struct Scratchpad { /* sub class of buffer (?) */ Buffer buffer; /* pad for enclosing lexical scope */ struct Scratchpad *parent; /* for (slow) by name access, this could be a string to int hash instead */ struct parrot_string_t * names; /* for (faster) by index access */ PMC * data; /* subtracted from indexes before accessing data, calculated from the parent's offset and size (an index less than this offset, should refer to a variable in an enclosing scope) */ INTVAL offset; /* number of pointers in data */ INTVAL size; } * scratchpad_t; Thanks, for any help/feedback! -- Jonathan Sillito
[PATCH] add invoke vtable method
On Fri, 2002-07-19 at 16:36, Melvin Smith wrote: Send me a complete patch and I'll put it in. I might rename the op to 'call'. The attached patch makes the following changes: - adds invoke op to core.ops (patch does not remove call and callco) - adds vtable method 'invoke' to vtable.tbl - adds simple description (stolen from Dan's email) of the method to docs/pdd/pdd02_vtables.pod - adds default invoke to classes/default.pmc - adds an invoke method to classes/sub.pmc - adds an invoke method to classes/coroutine.pmc If either the op or the vtable method (or both) should be be named 'call' instead of 'invoke' then let me know and I will rework my stuff and resubmit the patch. I had a small patch ready for docs/core_ops.pod, but I see that the file has been removed, so now I am not sure where to put the description of the invoke op. Next on my list is (next 24 hours or so): 1) remove old call and callco ops (invoke takes care of both) from core.ops 2) change examples/assembly/sub.pasm and coroutine.pasm to use invoke instead of call and callco 3) add some tests After that I will look into adding a Continuation PMC. -- Jonathan Sillito Index: core.ops === RCS file: /cvs/public/parrot/core.ops,v retrieving revision 1.185 diff -u -r1.185 core.ops --- core.ops 18 Jul 2002 04:29:39 - 1.185 +++ core.ops 22 Jul 2002 16:52:05 - -4179,6 +4179,34 goto NEXT(); } +inline op invoke() { + opcode_t *dest; + PMC * p = interpreter-ctx.pmc_reg.registers[0]; + + /* + * FIXME: the stack manipulation code (this push and the pop below) should + * be moved to the vtable method. (I think ?) + */ + stack_push(interpreter, interpreter-ctx.control_stack, expr NEXT(), STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL); + + dest = (opcode_t *)p-vtable-invoke(interpreter, p); + if(dest == 0) { +/* + * invoke returned 0 (means nothing more needs to be done), so just + * move on to the next instruction + */ +stack_pop(interpreter, interpreter-ctx.control_stack, NULL, STACK_ENTRY_DESTINATION); +goto NEXT(); + } + else { +/* + * invoke returned non 0, so it should have returned a and address + * so that's our next + */ +goto ADDRESS(dest); + } +} + inline op call() { /* This op will be a vtable entry */ struct Parrot_Sub * sub = (struct Parrot_Sub*)interpreter-ctx.pmc_reg..registers[0]-data; Index: vtable.tbl === RCS file: /cvs/public/parrot/vtable.tbl,v retrieving revision 1.25 diff -u -r1.25 vtable.tbl --- vtable.tbl 21 Jun 2002 17:22:01 - 1.25 +++ vtable.tbl 22 Jul 2002 16:52:05 - -325,3 +325,5 STRING* substr_str(INTVAL offset, INTVAL length) STRING* substr_str_keyed(KEY* key, INTVAL offset, INTVAL length) STRING* substr_str_keyed_int(INTVAL* key, INTVAL offset, INTVAL length) + +INTVAL invoke() Index: docs/pdds/pdd02_vtables.pod === RCS file: /cvs/public/parrot/docs/pdds/pdd02_vtables.pod,v retrieving revision 1.19 diff -u -r1.19 pdd02_vtables.pod --- docs/pdds/pdd02_vtables.pod 21 Jun 2002 17:23:37 - 1.19 +++ docs/pdds/pdd02_vtables.pod 22 Jul 2002 16:52:05 - -1194,6 +1194,18 The key is guaranteed to be not NULL. +=item INTVAL invoke(INTERP, PMC* self) + +For invoking Invoke the given PMC. + +It should set up the environment for the sub and return the absolute +address that the interpreter should jump to. If it returns 0, then +the interpreter should just take up with the next instruction. (If the +sub just goes and does its thing and returns, which most C subs will +do at the moment) + +See pdd03_calling_conventions.pod for more details. + =back =cut Index: classes/default.pmc === RCS file: /cvs/public/parrot/classes/default.pmc,v retrieving revision 1.24 diff -u -r1.24 default.pmc --- classes/default.pmc 18 Jul 2002 02:19:16 - 1.24 +++ classes/default.pmc 22 Jul 2002 16:52:06 - -2478,4 +2478,15 INT_TO_KEY(r_key, *key); return SELF-vtable-substr_str_keyed(INTERP, SELF, r_key, offset, length); } + +INTVAL invoke() { + /* + * FIXME: should be an exception instead: + * Invoking something that can not be invoked ?? + */ + +/* returning 0 should mean the interpretor will move on to the next op */ +return 0; + +} } Index: classes/sub.pmc === RCS file: /cvs/public/parrot/classes/sub.pmc,v retrieving revision 1.2 diff -u -r1.2 sub.pmc --- classes/sub.pmc 18 Jul 2002 03:48:33 - 1.2 +++ classes/sub.pmc 22 Jul 2002 16:52:06 - -325,4 +325,9 void repeat_same (PMC * value, PMC* dest) { } */ + + INTVAL invoke () { + /* return address that the interpreter should jump to */ + return ((struct
Re: Subs?
On Wed, 2002-07-17 at 22:01, Melvin Smith wrote: Subs, co-routines and continuations are at a very limited, but functional state. Basically you can create a PMC with a bytecode address or label and use the call/callco/callcc ops on it. Subs seem to be broken right now. Here is a pasm file set_addr I0, MYSUB new P0, .Sub, I0 call end MYSUB: print this is the sub\n ret and the output from running the associated pbc file ./parrot rough.pbc Segmentation fault ./parrot -t rough.pbc PC=0; OP=65 (set_addr_i_ic); ARGS=(I0=0, 9) PC=3; OP=727 (new_p_ic_i); ARGS=(P0=0x81403c0, 9, I0=135578484) PC=7; OP=757 (call) If I understand things correctly, the problem is that the address argument (i.e. the last argument) to the new op is being ignored, and sub-init is always set to 0. So the call op is returning 0 as the next op for the interpreter (in core.ops): goto ADDRESS(sub-init); /* always 0 */ Is there a different pasm syntax I should be using for creating and calling subs? I seem to remember some discussion about changing how things are passed to constructors but I am not sure what the conclusion was. -- Jonathan Sillito
Re: [PATCH] Subs?
On Thu, 2002-07-18 at 14:27, Melvin Smith wrote: The temporary fix is to do: new P0, .Sub set_addr I0, MYSUB set P0, I0 call Attached are three small patches, two of them change example files (examples/assembly/coroutine.pasm and examples/assembly/sub.pasm) to use this fix that Melvin mentioned. The third is a fix for a simple bug in coroutine.pmc: Parrot_Coroutine was being cast to a Parrot_Sub which caused a seg fault when callco was called. (This is my first attempt at sending patches to the list, so any comments about how this should really be done would be appreciated.) -- Jonathan Sillito Index: examples/assembly/sub.pasm === RCS file: /cvs/public/parrot/examples/assembly/sub.pasm,v retrieving revision 1.2 diff -u -r1.2 sub.pasm --- examples/assembly/sub.pasm 7 Jun 2002 23:41:21 - 1.2 +++ examples/assembly/sub.pasm 18 Jul 2002 22:51:09 - -1,13 +1,20 +# sub.pasm +# # Sample sub-routines in Parrot # -# Create 2 subroutines +# $Id: $ # -set_addr I0, SUB -new P0, .ParrotSub, I0 + +# Create 2 subroutines +set_addr I0, SUB +new P0, .Sub +set P0, I0 save P0 -new P0, .ParrotSub, I0 +new P0, .Sub +set P0, I0 # Calling convention says P0 will contain the sub call + restore P0 # Call second one call Index: classes/coroutine.pmc === RCS file: /cvs/public/parrot/classes/coroutine.pmc,v retrieving revision 1.2 diff -u -r1.2 coroutine.pmc --- classes/coroutine.pmc 18 Jul 2002 03:48:33 - 1.2 +++ classes/coroutine.pmc 18 Jul 2002 22:53:12 - -77,11 +77,11 } */ void set_integer (PMC * value) { - ((struct Parrot_Sub*)SELF-data)-init = (opcode_t*)value-vtable-get_integer(INTERP, value); + ((struct Parrot_Coroutine*)SELF-data)-init = (opcode_t*)value-vtable-get_integer(INTERP, value); } void set_integer_native (INTVAL value) { - ((struct Parrot_Sub*)SELF-data)-init = (opcode_t*)value; + ((struct Parrot_Coroutine*)SELF-data)-init = (opcode_t*)value; } /* void set_integer_bigint (BIGINT value) { Index: examples/assembly/coroutine.pasm === RCS file: /cvs/public/parrot/examples/assembly/coroutine.pasm,v retrieving revision 1.1 diff -u -r1.1 coroutine.pasm --- examples/assembly/coroutine.pasm 7 Jun 2002 23:36:03 - 1.1 +++ examples/assembly/coroutine.pasm 18 Jul 2002 22:50:56 - -1,11 +1,17 +# coroutine.pasm +# # Sample co-routines in Parrot # -# Create 2 coroutines +# $Id: $ # + set_addr I0, MYCOROUTINE -new P0, .ParrotCoroutine, I0 +new P0, .Coroutine +set P0, I0 save P0 -new P0, .ParrotCoroutine, I0 +new P0, .Coroutine +set P0, I0 + # Calling convention says P0 will contain the sub so.. print Calling 1st co-routine\n callco