Hi: From the current implementation, which I find in the interpreter, and from testing on Cog I assume that primitive 83, that is 'perform:', does easily handle an arbitrary number of parameters. Is that correct, or does for instance Cog do something else? (it does not seem so) I am just asking, because the number of parameters of the Object>>#perform:with: variants goes only up to three. And, the comment does not mention it. (at least in a recent Pharo image) Furthermore, I guess, there is an upper limit on the number of arguments with regard to frame size? Thanks Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 |
Hi Stefan, On Wed, Dec 7, 2011 at 4:09 PM, Stefan Marr <[hidden email]> wrote:
That's correct. The primitive (InterpreterPrimitives>>primitivePerform) is written in terms of argumentCount and so should cope with any number of arguments up to the maximum (15 is the limit in CompiledMethod, 31 in the bytecode set I believe).
I am just asking, because the number of parameters of the Object>>#perform:with: variants goes only up to three. And, the comment does not mention it. (at least in a recent Pharo image) Not in the StackVM or the Cog VM since these are running on a stack, not in a context, and so there's always plenty of headroom to push args on the stack during a perform. At least the method/bytecode set's limit on argumentCount is going to bite before the stack size. Similarly with perform:withArguments:, as long as the number of arguments is <= LargeFrameSize (56 slots?) the primitive will push arguments. Of course, the number of arguments must match the method that is found, and so the real limits are CompiledMethod's and the bytecode set's.
cheers,
best, Eliot |
Hi Eliot: Are there any known issues with primitivePerformInSuperclass? And, ehm, what is the functionality that is supposed to be supported? I try with a doit, and everything works fine. But when it is used in a TestCase, it crashes :-/ """ Exception Type: EXC_BAD_ACCESS (SIGBUS) Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000000 Crashed Thread: 0 Dispatch queue: com.apple.main-thread Thread 0 Crashed: Dispatch queue: com.apple.main-thread 0 org.squeakfoundation.Squeak 0x0004ef5a primitivePerformInSuperclass + 42 Thread 1: Dispatch queue: com.apple.libdispatch-manager [...] """ With regard to the supported functionality, I would expect it to mirror perform more or less exactly, but the image I use, only knows 'perform: selector withArguments: argArray inSuperclass: lookupClass' which uses an explict array for the arguments. However, from the doIt, the code below seems to work. And, well, when I use the debugger, it works of course too... performSuper: aSymbol <primitive: 100> ^ self perform: aSymbol withArguments: (Array new: 0) inSuperclass: self class superclass performSuper: aSymbol with: anObject <primitive: 100> ^ self perform: aSymbol withArguments: (Array with: anObject) inSuperclass: self class superclass I also tried to put the code from the doit into a class, and see whether that indirection makes a difference, since I remember that you have some special treatment for doits in Cog, right? Thanks Stefan On 08 Dec 2011, at 03:01, Eliot Miranda wrote: > Hi Stefan, > > On Wed, Dec 7, 2011 at 4:09 PM, Stefan Marr <[hidden email]> wrote: > > Hi: > > >From the current implementation, which I find in the interpreter, and from testing on Cog I assume that primitive 83, that is 'perform:', does easily handle an arbitrary number of parameters. > > Is that correct, or does for instance Cog do something else? (it does not seem so) > > That's correct. The primitive (InterpreterPrimitives>>primitivePerform) is written in terms of argumentCount and so should cope with any number of arguments up to the maximum (15 is the limit in CompiledMethod, 31 in the bytecode set I believe). > > I am just asking, because the number of parameters of the Object>>#perform:with: variants goes only up to three. And, the comment does not mention it. (at least in a recent Pharo image) > > Furthermore, I guess, there is an upper limit on the number of arguments with regard to frame size? > > Not in the StackVM or the Cog VM since these are running on a stack, not in a context, and so there's always plenty of headroom to push args on the stack during a perform. At least the method/bytecode set's limit on argumentCount is going to bite before the stack size. Similarly with perform:withArguments:, as long as the number of arguments is <= LargeFrameSize (56 slots?) the primitive will push arguments. Of course, the number of arguments must match the method that is found, and so the real limits are CompiledMethod's and the bytecode set's. > > cheers, > > > Thanks > Stefan > > -- > Stefan Marr > Software Languages Lab > Vrije Universiteit Brussel > Pleinlaan 2 / B-1050 Brussels / Belgium > http://soft.vub.ac.be/~smarr > Phone: +32 2 629 2974 > Fax: +32 2 629 3525 > > > > > -- > best, > Eliot > -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 |
On Mon, Dec 12, 2011 at 01:59:11AM +0100, Stefan Marr wrote: > > Hi Eliot: > > Are there any known issues with primitivePerformInSuperclass? > > And, ehm, what is the functionality that is supposed to be supported? > I think you are missing some arguments for the primitive in your #performSuper methods. See the method comment in Object>>perform:withArguments:inSuperclass: for a description of the functionality. primitivePerformInSuperclass has been around for a long time, as the last real update in the interpreter VM (aside from a recent minor update for return code handing) is stamped 'di 4/12/1999'. As a side note, #primitivePerformInSuperclass is exercised by MirrorPrimiveTests>>testMirrorPerform which AFIK has no known problems on Cog. That test fails on an interpreter VM because mirror primitive support is not yet complete (http://bugs.squeak.org/view.php?id=7429) but hopefully this will be resolved soon. Dave > I try with a doit, and everything works fine. > But when it is used in a TestCase, it crashes :-/ > > """ > Exception Type: EXC_BAD_ACCESS (SIGBUS) > Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000000 > Crashed Thread: 0 Dispatch queue: com.apple.main-thread > > Thread 0 Crashed: Dispatch queue: com.apple.main-thread > 0 org.squeakfoundation.Squeak 0x0004ef5a primitivePerformInSuperclass + 42 > > Thread 1: Dispatch queue: com.apple.libdispatch-manager > [...] > """ > > > With regard to the supported functionality, I would expect it to mirror perform more or less exactly, but the image I use, only knows 'perform: selector withArguments: argArray inSuperclass: lookupClass' which uses an explict array for the arguments. > However, from the doIt, the code below seems to work. > And, well, when I use the debugger, it works of course too... > > performSuper: aSymbol > <primitive: 100> > ^ self perform: aSymbol withArguments: (Array new: 0) inSuperclass: self class superclass > > performSuper: aSymbol with: anObject > <primitive: 100> > ^ self perform: aSymbol withArguments: (Array with: anObject) inSuperclass: self class superclass > > > I also tried to put the code from the doit into a class, and see whether that indirection makes a difference, since I remember that you have some special treatment for doits in Cog, right? > > Thanks > Stefan > > > On 08 Dec 2011, at 03:01, Eliot Miranda wrote: > > > Hi Stefan, > > > > On Wed, Dec 7, 2011 at 4:09 PM, Stefan Marr <[hidden email]> wrote: > > > > Hi: > > > > >From the current implementation, which I find in the interpreter, and from testing on Cog I assume that primitive 83, that is 'perform:', does easily handle an arbitrary number of parameters. > > > > Is that correct, or does for instance Cog do something else? (it does not seem so) > > > > That's correct. The primitive (InterpreterPrimitives>>primitivePerform) is written in terms of argumentCount and so should cope with any number of arguments up to the maximum (15 is the limit in CompiledMethod, 31 in the bytecode set I believe). > > > > I am just asking, because the number of parameters of the Object>>#perform:with: variants goes only up to three. And, the comment does not mention it. (at least in a recent Pharo image) > > > > Furthermore, I guess, there is an upper limit on the number of arguments with regard to frame size? > > > > Not in the StackVM or the Cog VM since these are running on a stack, not in a context, and so there's always plenty of headroom to push args on the stack during a perform. At least the method/bytecode set's limit on argumentCount is going to bite before the stack size. Similarly with perform:withArguments:, as long as the number of arguments is <= LargeFrameSize (56 slots?) the primitive will push arguments. Of course, the number of arguments must match the method that is found, and so the real limits are CompiledMethod's and the bytecode set's. > > > > cheers, > > > > > > Thanks > > Stefan > > > > -- > > Stefan Marr > > Software Languages Lab > > Vrije Universiteit Brussel > > Pleinlaan 2 / B-1050 Brussels / Belgium > > http://soft.vub.ac.be/~smarr > > Phone: +32 2 629 2974 > > Fax: +32 2 629 3525 > > > > > > > > > > -- > > best, > > Eliot > > > > -- > Stefan Marr > Software Languages Lab > Vrije Universiteit Brussel > Pleinlaan 2 / B-1050 Brussels / Belgium > http://soft.vub.ac.be/~smarr > Phone: +32 2 629 2974 > Fax: +32 2 629 3525 |
In reply to this post by Stefan Marr
Hi Stefan, can you mail me your tests?
On Sun, Dec 11, 2011 at 4:59 PM, Stefan Marr <[hidden email]> wrote:
best, Eliot |
In reply to this post by David T. Lewis
Hi Dave, Hi Eliot: On 12 Dec 2011, at 02:42, David T. Lewis wrote: > I think you are missing some arguments for the primitive in your > #performSuper methods. Thanks Dave, indeed. Was certainly to late for me yesterday. I forget the class, in which the lookup is supposed to be started. Eliot, well, there was another argument, which was probably interpreted as the lookup class but was just a SmallInteger instead. Guess that was causing the crash. From the RoarVM interpreter I understand that the lookup class is not crosschecked for being a class. I think it did work on the interpreter for me, because my patched DNU handler is 'a bit to robust', and does not exactly what it is supposed to do. Thanks Stefan -- Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525 |
On Mon, Dec 12, 2011 at 12:53 AM, Stefan Marr <[hidden email]> wrote: --
If so, that's a bug. The prim should check. I'll fix this. So to reproduce I supply a SmallInteger as the lookup class? But the folloiwng doesn't crash my VM:
nil perform: #yourself withArguments: #() inSuperclass: 0 So I still need to know how to reproduce this on Cog.
best, Eliot |
In reply to this post by Stefan Marr
Hi Stefan, On Mon, Dec 12, 2011 at 12:53 AM, Stefan Marr <[hidden email]> wrote:
The problem was that you declared a primitive with too few arguments and this interacted badly with the VMs interpreted frame format. You have a method
Object>performSuper: aSymbol with: anObject "Send the selector, aSymbol, to the receiver with anObject as its argument. Fail if the number of arguments expected by the selector is not one.
Primitive. Optional. See Object documentation whatIsAPrimitive." <primitive: 100>
^ self perform: aSymbol withArguments: (Array with: anObject) inSuperclass: self class superclass which only declares two arguments even though primitive 100, perform:withArguments:inSuperclass: requires three. So when the primitive attempted to access the receiver it actually fetched the field below, which happens to be the interpreted frames' saved ip which is null in this case. So the VM dies trying to follow a null pointer when it tries to fetch the receiver's class (since 0 is not a SmallInteger).
0xbff5d7a4 I OstCompilerTestDomain(OstDomain)>requestSuperExecutionOf:on: 367331552: a(n) OstCompilerTestDomain 0xbff5d7b4: rcvr/clsr: 0x15e508e0 =a(n) OstCompilerTestDomain
0xbff5d7b0: arg0: 0x14d482ec =#xx_omni_x_b 0xbff5d7ac: arg1: 0x15e508c8 =a(n) OstCompilerTestSubjectSub 0xbff5d7a8: caller ip: 0x1380fc8e=327220366 0xbff5d7a4: saved fp: 0xbff5d7c4=-1074407484
0xbff5d7a0: method: 0x1531683c 0x1531683c 355559484: a(n) CompiledMethod 0xbff5d798:intfrm flags: 0x201=513 numArgs: 2 hasContext: 0 isBlock: 0 0xbff5d79c: context: 0x1383c004 =nil
0xbff5d794: saved ip: 0x0 0 0xbff5d790: receiver: 0x15e508e0 =a(n) OstCompilerTestDomain 0xbff5d78c: stck: 0x15e508c8 =a(n) OstCompilerTestSubjectSub 0xbff5d788: stck: 0x14d482ec =#xx_omni_x_b
It dies at this line in primitivePerformInSuperclass trying to access the receiver's header: 32747 if (((ccIndex = (((usqInt) (longAt(rcvr))) >> 12) & 31)) == 0) {
32748 currentClass = (longAt(rcvr - BaseHeaderSize)) & AllButTypeMask; 32749 goto l1; Now the VM has support for checking primitive argument counts, and it will fail a primitive if the number of arguments dropped from the stack is incorrect. But it can only check the number of arguments after the primitive has run. So alas since the crash happens before the prtimitive has finished you are, in the classic phrase, SOL. Sorry :)
BTW, the saved ip is the bytecode address at which to resume execution in the interpreter. The return address of the next frame will be e.g. ceReturnToInterpreter so that when a machine code frame returns to an interpreted frame it returns to a trampoline which then reenters the interpreter and resumes execution at the bytecode pointed to by saved ip.
>From the RoarVM interpreter I understand that the lookup class is not crosschecked for being a class. I think it did work on the interpreter for me, because my patched DNU handler is 'a bit to robust', and does not exactly what it is supposed to do. best, Eliot |
Free forum by Nabble | Edit this page |