Re: runops_args vs NCI
Sam Ruby wrote: However, VTABLE_invoke on NCI methods is where the real work is done (including reading from and writing to registers), and a null dest is returned. One more remark: This is classes/nci.pmc:invoke void* invoke (void * next) { Parrot_csub_t func = (Parrot_csub_t)D2FPTR(PMC_data(SELF)); func(INTERP, SELF); return next; } It's not returning NULL. leo
Re: runops_args vs NCI
Leopold Toetsch wrote: Sam Ruby wrote: However, VTABLE_invoke on NCI methods is where the real work is done (including reading from and writing to registers), and a null dest is returned. One more remark: This is classes/nci.pmc:invoke void* invoke (void * next) { Parrot_csub_t func = (Parrot_csub_t)D2FPTR(PMC_data(SELF)); func(INTERP, SELF); return next; } It's not returning NULL. Fixed. - Sam Ruby
Re: runops_args vs NCI
Sam Ruby wrote: However, VTABLE_invoke on NCI methods is where the real work is done (including reading from and writing to registers), and a null dest is returned. Ouch. Sorry, probably cut'n'paste code, relicts or whatever. runops_* isn't supposed to be called for NCI methods. It's for running PASM opcodes. A NCI methods wraps a C function to be callable by PASM. If we are calling a NCI function from C, we can run the code diretly too. I'll fix that. - Sam Ruby leo
Re: runops_args vs NCI
Leopold Toetsch wrote: Sam Ruby wrote: However, VTABLE_invoke on NCI methods is where the real work is done (including reading from and writing to registers), and a null dest is returned. Ouch. Sorry, probably cut'n'paste code, relicts or whatever. runops_* isn't supposed to be called for NCI methods. It's for running PASM opcodes. A NCI methods wraps a C function to be callable by PASM. If we are calling a NCI function from C, we can run the code diretly too. I'll fix that. I have a number of cases (filter, map, reduce), where I am passed an arbirary sub and need to call it. I should not have to know how the sub is implemented. So, what you are telling me is that I need to clone runops_args and fix it right. I'll do that. - Sam Ruby
Re: runops_args vs NCI
Sam Ruby wrote: Leopold Toetsch wrote: Sam Ruby wrote: However, VTABLE_invoke on NCI methods is where the real work is done (including reading from and writing to registers), and a null dest is returned. Ouch. Sorry, probably cut'n'paste code, relicts or whatever. runops_* isn't supposed to be called for NCI methods. It's for running PASM opcodes. A NCI methods wraps a C function to be callable by PASM. If we are calling a NCI function from C, we can run the code diretly too. I'll fix that. I have a number of cases (filter, map, reduce), where I am passed an arbirary sub and need to call it. I should not have to know how the sub is implemented. Just invoke it. So, what you are telling me is that I need to clone runops_args and fix it right. I'll do that. Argh. I didn't tell you that. The interface to run an arbitrary piece of code is VTABLE_invoke. The runops_fromc* functions run *opcodes* from inside C. - Sam Ruby leo
Re: runops_args vs NCI
Leopold Toetsch wrote: Sam Ruby wrote: Leopold Toetsch wrote: Sam Ruby wrote: However, VTABLE_invoke on NCI methods is where the real work is done (including reading from and writing to registers), and a null dest is returned. Ouch. Sorry, probably cut'n'paste code, relicts or whatever. runops_* isn't supposed to be called for NCI methods. It's for running PASM opcodes. A NCI methods wraps a C function to be callable by PASM. If we are calling a NCI function from C, we can run the code diretly too. I'll fix that. I have a number of cases (filter, map, reduce), where I am passed an arbirary sub and need to call it. I should not have to know how the sub is implemented. Just invoke it. So, what you are telling me is that I need to clone runops_args and fix it right. I'll do that. Argh. I didn't tell you that. The interface to run an arbitrary piece of code is VTABLE_invoke. The runops_fromc* functions run *opcodes* from inside C. Grrr. First you tell me: Crunops is a low-level function that awaits all properly setup. Around that are more function that e.g. create a return continuation and do argument or returnvalue passing. Just use one of these functions as delegate.c does. To which I respond: I *am* using Parrot_run_meth_fromc_args, just like delegate.c does. Now you tell me, Just invoke it. But I need to do more than that. I need to do what Parrot_run_meth_fromc_args is attempting to do (i.e., create a return continuation and do argument or returnvalue passing.), but correctly. - Sam Ruby
Re: runops_args vs NCI
Sam Ruby wrote: But I need to do more than that. I need to do what Parrot_run_meth_fromc_args is attempting to do (i.e., create a return continuation and do argument or returnvalue passing.), but correctly. 1) runops_fromc and friends are running *opcodes*, nothing else 2) the functions are working, nothing needs fixing here. I've already stated several times: let's adjust Parrot's method dispatch and overloaded method signatures, so that it's directly usable for target languages. When that is done, you can get rid of all the additional dispatch functions. - Sam Ruby leo
Re: runops_args vs NCI
Sam Ruby wrote: I have a number of cases (filter, map, reduce), where I am passed an arbirary sub and need to call it. I should not have to know how the sub is implemented. I'd a look at map and friends now. You are running code that has a signature of PP. You'd need additionally: if (func-vtable-base_type == enum_class_NCI) { typedef PMC* (*func_pp)(Interp*, PMC*); func_pp cfunc = (func_pp) D2FPTR(PMC_struct_val(func)); item = (cfunc)(interpreter, item); } else { ... You could of course add a general call_PP wrapper that handles both cases. But as you did already replace the general runops_args with a hand-crafted call setup, adding above lines should do it. leo
Re: runops_args vs NCI
Leopold Toetsch wrote: Sam Ruby wrote: But I need to do more than that. I need to do what Parrot_run_meth_fromc_args is attempting to do (i.e., create a return continuation and do argument or returnvalue passing.), but correctly. 1) runops_fromc and friends are running *opcodes*, nothing else 2) the functions are working, nothing needs fixing here. I've made a clone of these functions, and made the relevant fixes to my copy. Hopefully someday this will get refactored back into Parrot. For the record, in the test case I provided, I was calling Parrot_run_meth_fromc_args twice. The first time with a real Sub. One implemented with opcodes. Or, as you prefer to say it, *opcodes*. It was this call that did not restore the context interpreter-ctx.bp. As near as I can tell, this path is identical to the usage in classes/delegate.c. In other words, it is an accident waiting to happen. Take a look at Parrot_PyClass_runops_fromc. If you do, you will see that I am only restoring the value of interpreter-ctx.bp if dest is non-zero. Think about it. The second time I called Parrot_run_meth_fromc_args, it was with an NCI method. The only problem is that in this call, the parameters were set into registers after the invoke call. I believe it to be customary to set the parameters into registers prior to the invoke call. In fact, I have logic in PyFunc.pmc (again which is used to invoke Python functions which are implemented in opcodes, er, I mean *opcodes*), which depends on things happening in this order in order to handle defaults and varargs. I've already stated several times: let's adjust Parrot's method dispatch and overloaded method signatures, so that it's directly usable for target languages. When that is done, you can get rid of all the additional dispatch functions. I am not interested in discussing this any more. The current Parrot has bugs. I've notified you of a number of them. You are apparently not interested as you would prefer to rewrite Parrot instead. Undoubtably, at that time it will have a different set of bugs. At which point, undoubtably, the process will repeat. Onward. - Sam Ruby
Re: runops_args vs NCI
Sam Ruby wrote: I've made a clone of these functions, and made the relevant fixes to my copy. As you said, that's your time. You can clone half of Parrot core for experiments. Hopefully someday this will get refactored back into Parrot. The code for running PASM/PIR code is fine. The second time I called Parrot_run_meth_fromc_args, it was with an NCI method. The only problem is ... ... that you are calling the wrong function during your handrolled and unneeded redispatch. Why are you are creating a return continuation for calling a C function? Why do you pass registers according to pdd03 to a C function? Why do you execute a C function with a new context structure? *runops_args* is running *opcodes*. A NCI fuction is a thin wrapper around a piece of C code. I am not interested in discussing this any more. Sam, it's a big difficult to tell you that the current approach of implementing Python will not work, because as soon as I say so, you gonna stop discussing necessary issues. The current Parrot has bugs. I've notified you of a number of them. Sure - And, yes, thanks your notice I've fixed one today. ... You are apparently not interested as you would prefer to rewrite Parrot instead. Make it workable. Complete. Which admittedly needs some rewrite, yes. Such is life. Undoubtably, at that time it will have a different set of bugs. At which point, undoubtably, the process will repeat. No, there are of course no bugs in Parrot final, never ;) Onward. - Sam Ruby leo
runops_args vs NCI
pseudo-code for runops_args: runops_args(PMC* sub, char* sig, va_list ap) { dest = VTABLE_invoke(interpreter, sub, NULL); REG_*[*] = ap[*], as appropriate if (dest) runops } However, VTABLE_invoke on NCI methods is where the real work is done (including reading from and writing to registers), and a null dest is returned. The net effect is that if you try to invoke a NCI with a signature of PP, the NCI method will be called with whatever happens to be in PMC_REG(5) at the time, and what it returns will be overwritten with your first argument. Is there a reason why the invoke couldn't be done immediately prior to the call to runops? - Sam Ruby